在 Linux 环境下开发 C 代码,感觉写 Makefile 比较麻烦,尤其是源文件比较多的情况下,经常找不到文件或者库,编译出错;发现一个比较好的工具,SCons ,可以自动的分析依赖关系,使用简单方便。
SCons 是一个开源软件构建工具。SCons 被视为是经典 Make 程序的改进的跨平台替代者,具有类似于 autoconf/automake 和编译器缓存(如 ccache)的集成功能。简而言之,SCons 是一种更简单、更可靠、更快速的软件构建方式。
现在安装很方便,可以直接在Linux 的终端窗口敲入命令:
apt install scons
root@maixsense:~# scons -h
usage: scons [OPTION] [TARGET] ...
SCons Options:
-b, -d, -e, -m, -S, -t, -w, --environment-overrides, --no-keep-going,
--no-print-directory, --print-directory, --stop, --touch
Ignored for compatibility.
-c, --clean, --remove Remove specified targets and dependencies.
-C DIR, --directory=DIR Change to DIR before doing anything.
--cache-debug=FILE Print CacheDir debug info to FILE.
--cache-disable, --no-cache
Do not retrieve built targets from CacheDir.
--cache-force, --cache-populate
Copy already-built targets into the CacheDir.
--cache-readonly Do not update CacheDir with built targets.
--cache-show Print build actions for files from CacheDir.
--config=MODE Controls Configure subsystem: auto, force,
cache.
-D Search up directory tree for SConstruct,
build all Default() targets.
--debug=TYPE Print various types of debugging information:
count, duplicate, explain, findlibs, includes,
memoizer, memory, objects, pdb, prepare,
presub, stacktrace, time, action-timestamps.
--diskcheck=TYPE Enable specific on-disk checks.
--duplicate=DUPLICATE Set the preferred duplication methods. Must be
one of hard-soft-copy, soft-hard-copy,
hard-copy, soft-copy, copy
--enable-virtualenv Import certain virtualenv variables to SCons
-f FILE, --file=FILE, --makefile=FILE, --sconstruct=FILE
Read FILE as the top-level SConstruct file.
-h, --help Print defined help message, or this one.
-H, --help-options Print this message and exit.
-i, --ignore-errors Ignore errors from build actions.
-I DIR, --include-dir=DIR Search DIR for imported Python modules.
--ignore-virtualenv Do not import virtualenv variables to SCons
--implicit-cache Cache implicit dependencies
--implicit-deps-changed Ignore cached implicit dependencies.
--implicit-deps-unchanged Ignore changes in implicit dependencies.
--interact, --interactive Run in interactive mode.
-j N, --jobs=N Allow N jobs at once.
-k, --keep-going Keep going when a target can't be made.
--max-drift=N Set maximum system clock drift to N seconds.
--md5-chunksize=N Set chunk-size for MD5 signature computation to
N kilobytes.
-n, --no-exec, --just-print, --dry-run, --recon
Don't build; just print commands.
--no-site-dir Don't search or use the usual site_scons dir.
--profile=FILE Profile SCons and put results in FILE.
-q, --question Don't build; exit status says if up to date.
-Q Suppress "Reading/Building" progress messages.
--random Build dependencies in random order.
-s, --silent, --quiet Don't print commands.
--site-dir=DIR Use DIR instead of the usual site_scons dir.
--stack-size=N Set the stack size of the threads used to run
jobs to N kilobytes.
--taskmastertrace=FILE Trace Node evaluation to FILE.
--tree=OPTIONS Print a dependency tree in various formats: all,
derived, prune, status, linedraw.
-u, --up, --search-up Search up directory tree for SConstruct,
build targets at or below current directory.
-U Search up directory tree for SConstruct,
build Default() targets from local SConscript.
-v, --version Print the SCons version number and exit.
--warn=WARNING-SPEC, --warning=WARNING-SPEC
Enable or disable warnings.
-Y REPOSITORY, --repository=REPOSITORY, --srcdir=REPOSITORY
Search REPOSITORY for source and target files.
这是一个在 R329 的 Armbian 21.08.0-trunk Bullseye with bleeding edge Linux 5.14.0-rc4-sun50iw11 环境下开发音频程序的代码,以此为例,硬件信息可参考:
MaixSense R329板开箱 - 音频视频测试_小手智联老徐的博客-CSDN博客
root@maixsense:~/audio_loop# ls
audio_loop.c main.c R329_Pys_control.h
audio_loop_data.c linuxinit.c R329_init.c
audio_loop.h linuxinit.h R329_init.h
audio_loop_private.h R329_alsa_audio.c rtmodel.h
audio_loop_types.h R329_alsa_audio.h R329_Pys_control.c
R329_RTOS_header.h
root@maixsense:~/audio_loop# nano SConstruct
GNU nano 5.4 SConstruct
Program('audio_loop',Glob('*.c'),
LIBS=['m','asound','pthread','rt','dl'],
CCFLAGS='-DSTACK_SIZE=64')
有多个 C 文件的时候,可以用 Glob('*.c') 来代替,LIBS 里添加需要链接的库的名称。
其中 LIBS 和 CCFLAGS 是 SCons 内置的关键字,它们的作用如下:
LIBS: 显示的指明要在链接过程中使用的库,如果有多个库,应该把它们放在一个列表里面。
CCFLAGS: 编译选项,可以指定需要的任意编译选项,如果有多个选项,应该放在一个列表中。
也可以指定文件路径:
CPPPATH:指定文件的路径,
LIBPATH: 链接库的搜索路径,多个搜索路径放在一个列表中。
如:库的搜索路径是 /usr/lib 和 /usr/local/lib,LIBPATH = ['/usr/lib', '/usr/local/lib']。
SCons 支持多种编译类型:
Program: 编译成可执行程序,这是最常用的一种编译类型。
Object: 只编译成目标文件。使用这种类型,编译结束后,只会产生目标文件。在 POSIX 系统中,目标文件以 .o 结尾,在 Windows 平台上以 .OBJ 结尾。
Library: 编译成库文件。SCons 默认编译的库是指静态链接库。
StaticLibrary: 显示的编译成静态链接库,与上面的 Library 效果一样。
SharedLibrary: 在 POSIX 系统上编译动态链接库,在 Windows 平台上编译 DLL。
root@maixsense:~/audio_loop# scons -Q
gcc -o R329_Pys_control.o -c -DSTACK_SIZE=64 R329_Pys_control.c
gcc -o R329_alsa_audio.o -c -DSTACK_SIZE=64 R329_alsa_audio.c
gcc -o R329_init.o -c -DSTACK_SIZE=64 R329_init.c
gcc -o audio_loop.o -c -DSTACK_SIZE=64 audio_loop.c
gcc -o audio_loop_data.o -c -DSTACK_SIZE=64 audio_loop_data.c
gcc -o main.o -c -DSTACK_SIZE=64 main.c
gcc -o linuxinit.o -c -DSTACK_SIZE=64 linuxinit.c
gcc -o audio_loop R329_Pys_control.o R329_alsa_audio.o R329_init.o audio_loop.o audio_loop_data.o main.o linuxinit.o -lm -lasound -lpthread -lrt -ldl
其中,-Q 参数是减少编译时的由 scons 产生的冗余信息。
root@maixsense:~/audio_loop# ls
audio_loop main.c R329_Pys_control.h
audio_loop.c main.o R329_Pys_control.o
audio_loop_data.c linuxinit.c R329_init.c
audio_loop_data.o linuxinit.h R329_init.h
audio_loop.h linuxinit.o R329_init.o
audio_loop.o R329_alsa_audio.c rtmodel.h
audio_loop_private.h R329_alsa_audio.h
audio_loop_types.h R329_alsa_audio.o SConstruct
R329_RTOS_header.h R329_Pys_control.c
audio_loop 是产生的可执行文件。
root@maixsense:~/audio_loop# file audio_loop
audio_loop: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=***********, for GNU/Linux 3.7.0, not stripped
root@maixsense:~/audio_loop# ./audio_loop
**** Starting audio loop ****
root@maixsense:~/audio_loop# scons -c
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed R329_Pys_control.o
Removed R329_alsa_audio.o
Removed R329_init.o
Removed audio_loop.o
Removed audio_loop_data.o
Removed main.o
Removed linuxinit.o
Removed audio_loop
scons: done cleaning targets.
sudo apt-get install git
git clone https://github.com/Arm-software/ComputeLibrary.git
cd ComputeLibrary
如果需要特定的非最新版本,如:v18.05,执行下面的命令,
git tag -l
git checkout v18.05
sudo apt-get install scons
cd ComputeLibrary
scons Werror=0 -j2 debug=0 neon=1 opencl=0 os=linux arch=armv7a openmp=1 examples=0 asserts=0 build=native
scons Werror=0 -j2 debug=0 neon=0 opencl=1 os=linux arch=arm64-v8a openmp=1 examples=0 asserts=0 build=native
armv7 target:
sudo apt-get install g++-arm-linux-gnueabihf
setenv('LINARO_TOOLCHAIN_AARCH32', '/usr/bin')
armv8 target:
sudo apt-get install g++-aarch64-linux-gnu
setenv('LINARO_TOOLCHAIN_AARCH64', '/usr/bin')
scons Werror=0 -j8 debug=0 neon=1 opencl=0 os=linux arch=arm64-v8a openmp=1 cppthreads=1 examples=0 asserts=0 build=cross_compile
SCons 有更加复杂和灵活的应用,有待慢慢研究。
老徐 ,2022 / 5 / 25