当前位置: 首页 > 工具软件 > SCons > 使用案例 >

SCons教程(6) 环境

长孙硕
2023-12-01

环境

外部环境

用户在执行 SCons 的外部环境变量设置是,可以使用 pythonos.ennviron 模块,可以将 import os 放在任意 SConstruct 中,并在该文件中使用用户外部环境变量。

import os

env = os.environ
print("current OS is", env["OS"])

执行 socns 结果就是 ‘Windows_NT’,对此,认为可以使用用户环境变量或者是系统环境变量。

admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons -Q
('current OS is', 'Windows_NT')
scons: `.' is up to date.

特此说明,SCons 可以使用大部分 python 中的语法、环境、库等信息,模块调用也可以共享。

本地环境

在一个构建环境中,可以对环境内容进行设置,例如设置不同编译器,优化等级,库文件,头文件搜索路径或者其他参数,此时需要使用 Environment 相关函数。

创建一个环境

env = Environment(CC='gcc', CCFLAGS='-O2')
env.Program('hello.c')

执行 scons 之后的结果就是下面结果,可以看出和之前不同的是,编译语句增加了 -O2 的优化等级,和设置的一致。

admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons -Q
gcc -o hello.o -c -O2 hello.c
gcc -o hello.exe hello.o

除了可以设置环境变量之外,也可以通过 get 函数获取变量的值,并打印输出。

env = Environment()
print("CC is: %s" % env['CC'])
print("LATEX is: %s" % env.get('LATEX', None))

执行 scons 之后的结果就是下面结果,默认编译器就是 gccLATEX 变量没有值,使用了设置的默认值 None

admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons -Q
CC is: gcc
LATEX is: None
scons: `.' is up to date.

查看默认 SCons 的默认变量,可以使用下面语句:

env = Environment()
for item in sorted(env.Dictionary().items()):
    print("construction variable = '%s', value = '%s'" % item)

# 或者
env = Environment()
print(env.Dump())

命令行参数

增加 help 语句

在一个命令不知道怎么使用时,使用 --help 来获取当前命令的选项帮助是最好的方法。SCons 也是提供了 help 选项的编写,可以帮助用户简单的创建 --help 的语句。

Help("""
Type: 'scons program' to build the production program,
'scons debug' to build the debug version.
""")
admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons -h
scons: Reading SConscript files ...
scons: done reading SConscript files.

Type: 'scons program' to build the production program,
'scons debug' to build the debug version.

Use scons -H for help about command-line options.


使用 -H 可以看有关 SCons 的帮助文档。


admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ 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.
  -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.

获取命令行输入参数

可以使用 ARGUMENTS.get 来获取命令行参数,在一些情况下,可以增加选项以增加多个项目的构建。

env = Environment()
if ARGUMENTS.get('VERBOSE') != '1':
    print("VERBOSE")
admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons -Q
VERBOSE
scons: '.' is up to date.

admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons -Q VERBOSE=1
scons: '.' is up to date.

或者使用 set PARAM=VALUE 方式显式设置参数的值。

admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ set SCONSFLAGS=-Q

admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons
VERBOSE
scons: `.' is up to date.

获取参数

  • GetOption
    修改 SCsonstruct 内容如下,在命令行使用 -h, --help 时,可以使用 GetOption 来获取 help 参数,如果有 help 选项,则输出 help text 文本,没有 help 选项时,输出 not help
if not GetOption('help'):
    SConscript('SConscript', export='env')
    print("not hellp")
else :
    Help("help text")
    print("hellp")

可以看出预期结果进行输出。

admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons -h
hellp
help text
Use scons -H for help about command-line options.

admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons
not hellp
scons: `.' is up to date.

设置选项

  • SetOption

使用 SetOption 可以设置命令行选项,例如设置 GetOption('help') 就可以看作是执行了 scons -h

import os

SetOption('help', "1")
print("help :  %s" % GetOption('help'))
Program('hello.c')

下面可以看到 SCson 的可选项有 -h, -d, -e, -m, -S, -t, -w 等,可以使用 SetOption 进行配置。

admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons
scons: Reading SConscript files ...
help :  1
scons: done reading SConscript files.
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

可以使用 GetOption 或者 SetOption 的选项如下:

String for GetOption and SetOptionCommand-Line Option(s)
cache_debug–cache-debug
cache_disable–cache-disable
cache_force–cache-force
cache_show–cache-show
clean-c, --clean, --remove
config–config
directory-C, --directory
diskcheck–diskcheck
duplicate–duplicate
file-f, --file, --makefile , --sconstruct
help-h, --help
ignore_errors–ignore-errors
implicit_cache–implicit-cache
implicit_deps_changed–implicit-deps-changed
implicit_deps_unchanged–implicit-deps-unchanged
interactive–interact, --interactive
keep_going-k, --keep-going
max_drift–max-drift
no_exec-n, --no-exec, --just-print, --dry-run, --recon
no_site_dir–no-site-dir
num_jobs-j, --jobs
profile_file–profile
question-q, --question
random–random
repository-Y, --repository, --srcdir
silent-s, --silent, --quiet
site_dir–site-dir
stack_size–stack-size
taskmastertrace_file–taskmastertrace
warn–warn --warning

增加选项

暂时不做解释

变量

随时可以在构建命令中,使用 ARGUMENTS 或者 增加选项来通过 GetOption 来获取命令行中的选项变量,但是每次执行,都需要开发者对执行命令特别熟悉,以防止漏掉选项造成编译失败或者编译与实际情况不符等现象。为了解决上述问题,可以使用 python 读取一个文件,文件内存储使用的选项变量。SCons 提供了 Variables 类来处理构建变量,来影响整个构建过程。

  • Add
    增加一个变量,使用 key-value 结构。
vars = Variables(None, ARGUMENTS)
vars.Add('HELLO_BUILD', default=0)
env = Environment(variables=vars, CPPDEFINES={'HELLO': '${HELLO_BUILD}'})
env.Program(['hello.c'])

执行 scons -Q -HELLO_BUILD=1 可以得到以下输出。

admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons -Q HELLO_BUILD=1
gcc -o hello.o -c -DHELLO=1 hello.c
gcc -o hello.exe hello.o
  • 读取外部文件

创建外部文件,作为选项的存放文件,所有的选项都放在这个文件内,使用时通过 python 来读取每个选项,并增加到当前环境中。

vars = Variables('var.py', ARGUMENTS)
vars.Add('HELLO_BUILD')
env = Environment(variables=vars, CPPDEFINES={'HELLO': '${HELLO_BUILD}'})
env.Program(['hello.c'])
admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons -Q
gcc -o hello.o -c -DHELLO=2 hello.c
gcc -o hello.exe hello.o

同时可以使用 BoolVariable 类来创建一个变量,使用 Add 来添加到当前环境中。三个参数依次是: 参数名称, 帮助信息, 默认值。bool变量可以是 True 和 False 两个值。 yes,y,t,True 都认为是 True, no,n,f,False 都认为是 False。

vars = Variables('var1.py', ARGUMENTS)
vars.Add(BoolVariable('HELLO_BUILD', help='Set to build for release', default=0))
env = Environment(variables=vars, CPPDEFINES={'HELLO': '${HELLO_BUILD}'})
env.Program(['hello.c'])
admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons -Q HELLO_BUILD=t
gcc -o hello.o -c -DHELLO=True hello.c

admin@DESKTOP-NQU1HUV C:\Users\admin\Desktop\scons\day6
$ scons -Q HELLO_BUILD=yes
gcc -o hello.o -c -DHELLO=True hello.c
gcc -o hello.exe hello.o

初此之外,还有其他类来实现变量的创建,下面简单介绍:

  • EnumVariable
# enmu
vars.Add(
    EnumVariable(
        'COLOR',
        help='Set background color',
        default='red',
        allowed_values=('red', 'green', 'blue'),
        map={'navy': 'blue'},
    )
)

# 增加一个 map 参数,是一个设置别名的方法,例如 `navy` 可以当作是 `blue` 的别名,是同样的意思。
# 枚举变量的值默认是严格大小写区分的,需要注意。如果要忽略大小写,可以增加 `ignorecase=1,` 的参数
# 
# 可以使用 --help  来查看当前 enum 的取值范围

scons -Q -h
COLOR: Set background color (red|green|blue)
default: red
actual: red

ignorecase 的使用方法:

当值为1的时候,忽略命令行参数值的大小写,且将命令行参数直接添加到构建环境内。
ignorecase = 1 ==> scons -Q COLOR=Red foo.o cc -o foo.o -c -DCOLOR="Red" foo.c

当值为2的时候,忽略命令行参数值的大小写,且将命令行参数转为全小写添加到构建环境内。
ignorecase = 2 ==> scons -Q COLOR=Red foo.o cc -o foo.o -c -DCOLOR="red" foo.c

  • ListVariable

可以使用 ListVariable 一次增加多个选项。具体应用如下:

vars = Variables('custom.py')
vars.Add(
    ListVariable(
        'COLORS', help='List of colors', default=0, names=['red', 'green', 'blue']
    )
)
env = Environment(variables=vars, CPPDEFINES={'COLORS': '"${COLORS}"'})
env.Program('foo.c')

执行结果:

% scons -Q COLORS=red,blue foo.o
cc -o foo.o -c -DCOLORS="red -Dblue" foo.c
% scons -Q COLORS=blue,green,red foo.o
cc -o foo.o -c -DCOLORS="blue -Dgreen -Dred" foo.c
  • PathVariable
    可以使用 PathVariable 来方便的创建构建变量的文件。例如如果选哟创建一个配置文件,来包含需要的选项,则按照一下操作:

创建 config.cfg 文件,内容为选项值:

COLOR=red
vars = Variables('custom.py')
vars.Add(
    PathVariable(
        'CONFIG',
        help='Path to configuration file',
        default='config.cfg',
        validator=PathVariable.PathIsFile,
    )
)
env = Environment(variables=vars, CPPDEFINES={'CONFIG_FILE': '"$CONFIG"'})
env.Program('foo.c')

执行过程:

% scons -Q foo.o
cc -o foo.o -c -DCONFIG_FILE="config.cfg" foo.c
% scons -Q CONFIG=./config.cfg foo.o
scons: 'foo.o' is up to date.

其中 validator 可以设置验证函数,验证功能函数有以下几个:
如果想确保任何指定路径实际上都需要是文件而不是目录,请使用 PathVariable.PathIsFile 作为验证函数。
如果是目录,则需要使用 PathVariable.PathIsDir ,并修改下面传入参数 env = Environment(variables=vars, CPPDEFINES={'DBDIR': '"$DBDIR"'})
如果目录不存在,且需要创建,则需要使用 PathVariable.PathIsDirCreate ,并修改下面传入函数 env = Environment(variables=vars, CPPDEFINES={'DBDIR': '"$DBDIR"'})
如果不关心输入的是文件还是目录是否存在,则需要使用 PathVariable.PathAccept

  • PackageVariable
    后面详细介绍

  • UnknownVariables

命令行目标

SCons 提供了一个 COMMAND_LINE_TARGETS 变量来保存命令行中的目标参数,如果需要的话,可以对目标进行检查,做出对应的处理。
下面举例说明: 对 hello 目标的显示构建,在构建过程中显示,提示开发者。

if 'hello' in COMMAND_LINE_TARGETS:
    print("hello  is being built!!! ")
Default(Program('hello.c'))
Program('hello.c')

但是实际执行,一直在出错,暂时不做测试,后期进行补充。

Default 默认构建目标

SCons 在默认状态下,会对构建脚本中所有目标进行构建,如果需要默认构建一个目标,则需要使用 Default 来指定构建目标。
没有测试出来,后面进行补充

 类似资料: