2019年1月13日 星期日

Note for SCons 3.0.3 User Guide, CH5 Node Objects


所有的檔案與目錄在SCons中都被視為"Nodes",善用"Node"可以使您的SConscript文件可移植且易於閱讀。

5.1. Builder Methods Return Lists of Target Nodes

所有builder methods都回傳一個Node list,用於辨識要構建的目標文件。這Node list可作為參數傳遞給其他builder methods。
brook@vista:~/scons/04.7$ cat SConstruct
a_list = Object('a.c', CCFLAGS='-DHELLO')
b_list = Object('b.c', CCFLAGS='-DWORLD')
Program(a_list + b_list)
 
brook@vista:~/scons/04.7$ scons -Q
gcc -o a.o -c -DHELLO a.c
gcc -o b.o -c -DWORLD b.c
gcc -o a a.o b.o


5.2. Explicitly Creating File and Directory Nodes

SCons的File()與Dir()可回傳file或directory Node,而Entry()可回傳file或directory Node。
hello_c = File('hello.c')
Program(hello_c)
 
classes = Dir('classes')
Java(classes, 'src')
 
xyzzy = Entry('xyzzy')


5.3. Printing Node File Names

您可以對Node執行print,打Node所代表的檔名。
brook@vista:~/scons/05.3$ cat SConstruct
object_list = Object(['a.c', 'b.c'])
program_list = Program(object_list)
print("The object file is: %s"%object_list)
print("The program file is: %s"%program_list[0])

brook@vista:~/scons/05.3$ scons -Q
The object file is: ['a.o', 'b.o']
The program file is: a
scons: `.' is up to date.


5.4. Using a Node's File Name as a String

您可以使用Python的str函數將Node轉成字串加以處理。
brook@vista:~/scons/05.5$ cat SConstruct
import os
object_list = Object(['a.c', 'b.c'])
obj_str = str(object_list[0])
print("The object file is: %s"% obj_str)
if not os.path.exists(obj_str):
    print("%s does not exist!"% obj_str)
else:
    print("%s exist!"% obj_str)
brook@vista:~/scons/05.5$ scons -Q
The object file is: a.o
a.o exist!
scons: `.' is up to date.


5.5. GetBuildPath: Getting the Path From a Node or String

env.GetBuildPath(file_or_list)可以用來取得file/Node的路徑。
brook@vista:~/scons/05.6$ cat SConstruct
object_list = Object(['a.c', 'b.c'])
env=Environment(VAR="value")
n=File("foo.c")
print(env.GetBuildPath([n, "sub/dir/$VAR", '/tmp'] + object_list))
brook@vista:~/scons/05.6$ scons -Q
['foo.c', 'sub/dir/value', '/tmp', 'a.o', 'b.o']
scons: `.' is up to date.





Note for SCons 3.0.3 User Guide, CH4 Building and Linking with Libraries


4.1. Building Libraries

在軟體開發過程中,將軟體切成數個library是很常見的,build成library在SCons中也是很容易完成的。
如果是要build成library,只需將builder method從Program換成Library即可。
Library('foo', ['f1.c', 'f2.c', 'f3.c'])

SCons會根據當前的系統,build出該Library,如Linux
% scons -Q
cc -o f1.o -c f1.c
cc -o f2.o -c f2.c
cc -o f3.o -c f3.c
ar rc libfoo.a f1.o f2.o f3.o
ranlib libfoo.a

Windows
C:\>scons -Q
cl /Fof1.obj /c f1.c /nologo
cl /Fof2.obj /c f2.c /nologo
cl /Fof3.obj /c f3.c /nologo
lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj

Library會build成static library,你也可以使用StaticLibrary來build static library
brook@vista:~/scons/04.2$ cat SConstruct
StaticLibrary('foo',['a.c', 'b.c'])

brook@vista:~/scons/04.2$ scons -Q
gcc -o a.o -c a.c
gcc -o b.o -c b.c
ar rc libfoo.a a.o b.o
ranlib libfoo.a

你也可以使用SharedLibrary 來build shared library
brook@vista:~/scons/04.3$ cat SConstruct
SharedLibrary('foo',['a.c', 'b.c'])

brook@vista:~/scons/04.3$ scons -Q
gcc -o a.os -c -fPIC a.c
gcc -o b.os -c -fPIC b.c
gcc -o libfoo.so -shared a.os b.os


4.2. Linking with Libraries

如果你的Program需要link某個Library,你只需在Program中指定$LIBS與$LIBPATH
brook@vista:~/scons/04.5$ cat SConstruct
SharedLibrary('foo',['a.c'])
StaticLibrary('bar',['b.c'])
Program('prog', 'prog.c', LIBS=['foo', 'bar'], LIBPATH='.')

brook@vista:~/scons/04.5$ scons -Q
gcc -o a.os -c -fPIC a.c
gcc -o b.o -c b.c
ar rc libbar.a b.o
ranlib libbar.a
gcc -o libfoo.so -shared a.os
gcc -o prog.o -c prog.c
gcc -o prog prog.o -L. -lfoo -lbar


4.3. Finding Libraries: the $LIBPATH Construction Variable

如果你要SCons尋找系統以外的library目錄,你指定$LIBPATH
brook@vista:~/scons/04.5$ cat SConstruct
SharedLibrary('foo',['a.c'])
StaticLibrary('bar',['b.c'])
Program('prog', 'prog.c', LIBS=['foo', 'bar'], LIBPATH=['/brook/lib', '.'])

brook@vista:~/scons/04.5$ scons -Q
gcc -o a.os -c -fPIC a.c
gcc -o b.o -c b.c
ar rc libbar.a b.o
ranlib libbar.a
gcc -o libfoo.so -shared a.os
gcc -o prog.o -c prog.c
gcc -o prog prog.o -L/brook/lib -L. -lfoo -lbar





2019年1月5日 星期六

Note for SCons 3.0.1 User Guide, CH3 Less Simple Things to Do With Builds


3.1. Specifying the Name of the Target (Output) File

當你呼叫Program()時,Scons會build出跟source file一樣檔名的程式,如果要build不同檔名的程式,可以Program()左邊參數放檔名,右邊放source file
brook@vista:~/scons/03.1$ cat SConstruct
Program('new_hello', 'hello.c')

brook@vista:~/scons/03.1$ scons -Q
gcc -o hello.o -c hello.c
gcc -o new_hello hello.o
brook@vista:~/scons/03.1$ scons -c -Q
Removed hello.o
Removed new_hello


3.2. Compiling Multiple Source Files

如果要從多個source file建立程式,只需在Program()放置python list,則會建立以第一個source file為檔名的程式檔
brook@vista:~/scons/03.1$ cat SConstruct
Program(['hello.c', 'a.c'])

brook@vista:~/scons/03.1$ scons -Q
gcc -o a.o -c a.c
gcc -o hello.o -c hello.c
gcc -o hello hello.o a.o


如果要建立不同程式名稱,只需在Program()左邊參數放檔名,右邊放source file list即可
brook@vista:~/scons/03.1$ cat SConstruct
Program('new_hello', ['hello.c', 'a.c'])

brook@vista:~/scons/03.1$ scons -Q
gcc -o a.o -c a.c
gcc -o hello.o -c hello.c
gcc -o new_hello hello.o a.o


3.3. Making a list of files with Glob

你可以適用Glob()來找尋matching的檔案,其語法可以使用*, ? and [abc]等shell的regular expression
brook@vista:~/scons/03.02$ cat SConstruct
Program('new_hello', Glob("*.c"))

brook@vista:~/scons/03.02$ scons -Q
gcc -o a.o -c a.c
gcc -o hello.o -c hello.c
gcc -o new_hello a.o hello.o


3.4. Specifying Single Files Vs. Lists of Files

SCons將所有source file視為list,只要符合list即可
# The following two calls both work correctly: 
Program('program1', 'program1.c') 
Program('program2', ['program2.c'])


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'])


3.5. Making Lists of Files Easier to Read

SCons中的Split()可以將字串內的檔案換成list,讓developer寫一個容易閱讀的list
brook@vista:~/scons/03.4$ cat SConstruct
print('a.c b.c c.c')
print(Split('a.c b.c c.c'))
src_files = Split('a.c b.c c.c')
print(src_files)

brook@vista:~/scons/03.4$ scons -Q
a.c b.c c.c
['a.c', 'b.c', 'c.c']
['a.c', 'b.c', 'c.c']
scons: `.' is up to date.


3.6. Keyword Arguments

Python預設是positional argument(位置參數),是按順序傳入function。關鍵字參數(keyword argument),顧名思義是以關鍵字方式傳入,使用keyword argument時,對順序沒有要求。Program(target, source)
src_files = Split('main.c file1.c file2.c') 
Program(target = 'program', source = src_files)

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


3.7. Compiling Multiple Programs

如果要編譯多個程式,只需多描述幾行Program()即可
brook@vista:~/scons/03.7$ cat SConstruct
Program('a.c')
Program('b.c')

brook@vista:~/scons/03.7$ scons -Q
gcc -o a.o -c a.c
gcc -o a a.o
gcc -o b.o -c b.c
gcc -o b b.o


3.8. Sharing Source Files Between Multiple Programs

SCons會自行判斷build的dependence,所以你只需照實描述各個program所需的source file即可
brook@vista:~/scons/03.7$ cat SConstruct
Program('a', ['a.c', 'comm.c'])
Program('b', ['b.c', 'comm.c'])

brook@vista:~/scons/03.7$ scons -Q
gcc -o a.o -c a.c
gcc -o comm.o -c comm.c
gcc -o a a.o comm.o
gcc -o b.o -c b.c
gcc -o b b.o comm.o


3.9. Overriding construction variables when calling a Builder

當你在呼叫這些builder時,Scons允許你帶入一些參數或覆蓋原本的參數,如 adds 'include' to $CPPPATH, 'EBUG' to $CPPDEFINES, and 'm' to $LIBS.
Program('hello', 'hello.c', parse_flags = '-Iinclude -DEBUG -lm')





2019年1月1日 星期二

Note for SCons 3.0.1 User Guide, CH2 Simple Builds


SCons是一個用Python的新一代軟體建構工具(SCons is a next-generation software construction tool),就像Make一樣可以建構軟體的工具。

CH 2.1. Build Simple C/C++ Programs

主要依具名為SConstruct的檔案進行建構,最小的SConstruct內容如下
Program('hello.c') 
這裡面包含兩個資訊,你要建構的程式名稱(hello),以及從哪個檔案建構(hello.c),"Program"在文中被稱為builder_method,主要用於告訴SCons要建構執行檔。
% scons scons: Reading SConscript files ... 
scons: done reading SConscript files. 
scons: Building targets ... 
cc -o hello.o -c hello.c 
cc -o hello hello.o 
scons: done building targets.


CH 2.2. Building Object Files

Object('hello.c') 
Objcet這個builder method用於告訴SCons如何從指定的source files中建立一個Object file
% scons scons: Reading SConscript files ... 
scons: done reading SConscript files. 
scons: Building targets ... 
cc -o hello.o -c hello.c 
scons: done building targets.


2.4. Cleaning Up After a Build

在SCons清除(Cleaning Up)一個build只需要在scons後面新增"-c"/"--clean"即可

2.5. The SConstruct File

SConstruct之於SCons就等同於Makefile之於Make,而SConstruct是個Python Script,注意,SConstruct的順序並非SCons實際執行的順序 比如該SConstruct的內容與其執行結果分別為
print("Calling Program('hello.c')") 
Program('hello.c') 
print("Calling Program('goodbye.c')") 
Program('goodbye.c') 
print("Finished calling Program()") 
hello.c先被呼叫,而後才是goodbye.c

% scons 
scons: Reading SConscript files ... 
Calling Program('hello.c') 
Calling Program('goodbye.c') 
Finished calling Program() 
scons: done reading SConscript files. 
scons: Building targets ... 
cc -o goodbye.o -c goodbye.c 
cc -o goodbye goodbye.o 
cc -o hello.o -c hello.c 
cc -o hello hello.o 
scons: done building targets. 
goodbye先被建置,而後才是hello

2.6. Making the SCons Output Less Verbose

參數"-Q"可以讓SCons輸出較少的建置訊息
brook@vista:~$ scons -Q
gcc -o hello.o -c hello.c

brook@vista:~$ scons -c
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed hello.o
scons: done cleaning targets.

brook@vista:~$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o hello.o -c hello.c
scons: done building targets.



熱門文章