scons:

Scons框架

SCons采用分层架构设计,分为编译引擎、API接口和脚本接口,如下图所示

 

StaticLibrary和Library一样都是用来构建静态库,而SharedLibrary用来构建动态共享库。

如何编译静态库

env.StaticLibrary(target = lib_name, source = lib_source)

如何编译动态库

env.SharedLibrary(target = lib_name, source = lib_source)

构建变量

LIBS:使用Python列表指定一个或多个链接所需要的函数库。
LIBPATH:使用Python列表指定函数库所在的一个或多个目录。

CPPPATH:使用Python列表指定一个或多个编译所需要的头文件所在的目录。
CPPDEFINES:A platform independent specification of C preprocessor definitions.
CC:指明所需使用的编译器。

CFLAGS:编译参数。
LDFLAG:链接参数。

env = Environment(LIBS = 'log4cxx')
bin_name = 'hello_world'
env.Program(target = bin_name, source = ['hello_world.cpp'])

Exclude deprecated files from build using SCons

If you check the existing documentation, the MAN page as well as the UserGuide, you'll find that the Glob() command supports the exclude parameter. You can use it to specify a list of patterns that should get excluded from the returned list.

Another option is to simply filter the list of found entries yourself, remember that you have the full power of Python at your fingertips:

excluded_files = ['src/a.cpp', 'src/b.cpp']
sources = [x for x in Glob('src/*.cpp') if str(x) not in excluded_files]
env.Program('project', sources)

 Glob(pattern, [ondisk, source, strings, exclude]) , 

env.Glob(pattern, [ondisk, source, strings, exclude])

 

The specified pattern uses Unix shell style metacharacters for matching:

  *       matches everything
  ?       matches any single character
  [seq]   matches any character in seq
  [!seq]  matches any char not in seq

[Character matches do not span directory separators是不跨越目录分隔符的,和正常的正则表达式是有区别的

If the first character of a filename is a dot, it must be matched explicitly. Character matches do not span directory separators.

Program('foo', Glob('*.c'))
Zip('/tmp/everything', Glob('.??*') + Glob('*'))
sources = Glob('*.cpp', exclude=['os_*_specific_*.cpp']) + Glob('os_%s_specific_*.cpp'%currentOS)

Trying to do "Python things" that mix strings and lists will cause errors or lead to incorrect results:

common_sources = ['file1.c', 'file2.c']

# THE FOLLOWING IS INCORRECT AND GENERATES A PYTHON ERROR
# BECAUSE IT TRIES TO ADD A STRING TO A LIST:
Program('program1', common_sources + 'program1.c')

# The following works correctly, because it's adding two
# lists together to make another list.
Program('program2', common_sources + ['program2.c'])
    

Making Lists of Files Easier to Read 

One drawback to the use of a Python list for source files is that each file name must be enclosed in quotes (either single quotes or double quotes). This can get cumbersome and difficult to read when the list of file names is long. Fortunately, SCons and Python provide a number of ways to make sure that the SConstruct file stays easy to read.

To make long lists of file names easier to deal with, SCons provides a Split function that takes a quoted list of file names, with the names separated by spaces or other white-space characters, and turns it into a list of separate file names. Using the Split function turns the previous example into:

Program('program', Split('main.c file1.c file2.c'))

 Keyword Arguments

src_files = Split('main.c file1.c file2.c')
Program(target = 'program', source = src_files)

Building and Linking with Libraries

Library('foo', ['f1.c', 'f2.c', 'f3.c'])
Library('foo', ['f1.c', 'f2.o', 'f3.c', 'f4.o']) 
StaticLibrary('foo', ['f1.c', 'f2.c', 'f3.c']) 
SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])

Finding Libraries: the $LIBPATH Construction Variable

Program('prog.c', LIBS = 'm', LIBPATH = ['/usr/lib', '/usr/local/lib']) 
cc -o prog prog.o -L/usr/lib -L/usr/local/lib -lm

Node Objects

Internally, SCons represents all of the files and directories it knows about as Nodes. These internal objects (not object files) can be used in a variety of ways to make your SConscript files portable and easy to read.

One way to combine these object files into the resulting program would be to call the Program builder with the names of the object files listed as sources:

Object('hello.c', CCFLAGS='-DHELLO')
Object('goodbye.c', CCFLAGS='-DGOODBYE')
Program(['hello.o', 'goodbye.o'])
    

The problem with specifying the names as strings is that our SConstruct file is no longer portable across operating systems. It won't, for example, work on Windows because the object files there would be named hello.obj and goodbye.obj, not hello.o and goodbye.o.

A better solution is to assign the lists of targets returned by the calls to the Object builder to variables, which we can then concatenate in our call to the Program builder:

hello_list = Object('hello.c', CCFLAGS='-DHELLO')
goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE')
Program(hello_list + goodbye_list)

Dependencies(是否重新编译)

So far we've seen how SCons handles one-time builds. But one of the main functions of a build tool like SCons is to rebuild only what is necessary when source files change--or, put another way, SCons should not waste time rebuilding things that don't need to be rebuilt. You can see this at work simply by re-invoking SCons after building our simple hello example:

Using MD5 Signatures to Decide if a File Has Changed

Using Time Stamps to Decide If a File Has Changed

Deciding If a File Has Changed Using Both MD Signatures and Time Stamps

 Writing Your Own Custom Decider Function

Implicit Dependencies(隐示依赖): The $CPPPATH Construction Variable

Now suppose that our "Hello, World!" program actually has an #include line to include the hello.h file in the compilation:

#include <hello.h>
int
main()
{
    printf("Hello, %s!\n", string);
}

And, for completeness, the hello.h file looks like this:
#define string    "world"
      
In this case, we want SCons to recognize that, if the contents of the hello.h file change, the hello program must be recompiled. To do this, we need to modify theSConstruct file like so:
Program('hello.c', CPPPATH = '.')

The $CPPPATH value tells SCons to look in the current directory ('.') for any files included by C source files (.c or .h files). With this assignment in the SConstruct file:

% scons -Q hello
cc -o hello.o -c -I. hello.c
cc -o hello hello.o
% scons -Q hello
scons: `hello' is up to date.
%     [CHANGE THE CONTENTS OF hello.h]

Caching Implicit Dependencies

每次都检查依赖文件是否更新,太费时,所以出现了--implicit-deps-changed等选项

Explicit Dependencies: the Depends Function

Sometimes a file depends on another file that is not detected by an SCons scanner. For this situation, SCons allows you to specific explicitly that one file depends on another file, and must be rebuilt whenever that file changes. This is specified using the Depends method:

hello = Program('hello.c')
Depends(hello, 'other_file')

Environments

External Environment

The external environment is the set of variables in the user's environment at the time the user runs SCons. These variables are available within the SConscript files through the Python os.environ dictionary. See Section 7.1, “Using Values From the External Environment”, below.

Construction Environment

construction environment is a distinct object created within a SConscript file and which contains values that affect how SCons decides what action to use to build a target, and even to define which targets should be built from which sources. One of the most powerful features of SCons is the ability to create multiple construction environments, including the ability to clone a new, customized construction environment from an existing construction environment. See Section 7.2, “Construction Environments”, below.

Creating a Construction Environment: the Environment Function

construction environment is created by the Environment method:

env = Environment()

By default, SCons initializes every new construction environment with a set of construction variables based on the tools that it finds on your system, plus the default set of builder methods necessary for using those tools. The construction variables are initialized with values describing the C compiler, the Fortran compiler, the linker, etc., as well as the command lines to invoke them.

When you initialize a construction environment you can set the values of the environment's construction variables to control how a program is built. For example:

 env = Environment(CC = 'gcc', CCFLAGS = '-O2')

 env.Program('foo.c')

Execution Environment

An execution environment is the values that SCons sets when executing an external command (such as a compiler or linker) to build one or more targets. Note that this is not the same as the external environment (see above). See Section 7.3, “Controlling the Execution Environment for Issued Commands”, below.

The default value of the PATH environment variable on a POSIX system is /usr/local/bin:/bin:/usr/bin. The default value of the PATH environment variable on a Windows system comes from the Windows registry value for the command interpreter. If you want to execute any commands--compilers, linkers, etc.--that are not in these default locations, you need to set the PATH value in the $ENV dictionary in your construction environment.(指定执行时使用的具体命令程序在哪里)

Hierarchical Builds

The source code for large software projects rarely stays in a single directory, but is nearly always divided into a hierarchy of directories. Organizing a large software build using SCons involves creating a hierarchy of build scripts using the SConscript function.

SConscript(['drivers/SConscript',
            'parser/SConscript',
            'utilities/SConscript'])

Path Names Are Relative to the SConscript Directory

Subsidiary SConscript files make it easy to create a build hierarchy because all of the file and directory names in a subsidiary SConscript files are interpreted relative to the directory in which the SConscript file lives. Typically, this allows the SConscript file containing the instructions to build a target file to live in the same directory as the source files from which the target will be built, making it easy to update how the software is built whenever files are added or deleted (or other changes are made).

For example, suppose we want to build two programs prog1 and prog2 in two separate directories with the same names as the programs. One typical way to do this would be with a top-level SConstruct file like this:

SConscript(['prog1/SConscript',
            'prog2/SConscript'])

And subsidiary SConscript files that look like this:

env = Environment()
env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c'])

env = Environment() env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c'])

Absolute Path Names

Of course, you can always specify an absolute path name for a file--for example:

env = Environment() env.Program('prog', ['main.c', '/usr/joe/lib/foo1.c', 'foo2.c'])

Then, when we run SCons in the top-level directory, our build looks like:

% scons -Q

cc -o prog1/foo1.o -c prog1/foo1.c
cc -o prog1/foo2.o -c prog1/foo2.c
cc -o prog1/main.o -c prog1/main.c
cc -o prog1/prog1 prog1/main.o prog1/foo1.o prog1/foo2.o
cc -o prog2/bar1.o -c prog2/bar1.c
cc -o prog2/bar2.o -c prog2/bar2.c
cc -o prog2/main.o -c prog2/main.c
cc -o prog2/prog2 prog2/main.o prog2/bar1.o prog2/bar2.o

Exporting Variables

SCons supports the ability to export variables from a parent SConscript file to its subsidiary SConscript files, which allows you to share common initialized values throughout your build hierarchy.

you can specify a list of variables to export as a second argument to the SConscript function call: SConscript('src/SConscript', 'env')

These calls export the specified variables to only the listed SConscript files. You may, however, specify more than one SConscript file in a list: //环境变量导出到。。。

SConscript(['src1/SConscript', 'src2/SConscript'], exports='env')

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值