scons使用


1.概述

    scons是一個Python寫的自動化構建工具,和GNU make相比優點明顯:
    A.移植性:python能運行的地方,就能運行scons
    B. 擴展性:理論上scons只是提供了python的類,scons使用者可以在這個類的基礎上做所有python能做的事情。比如想把一個已經使用了Makefile大型工程切換到scons,就可以保留原來的Makefile,並用python解析Makefile中的編譯選項、源/目標文件等,作為參數傳遞給scons,完成編譯。
    C. 智能:Scons繼承了autoconf/automake的功能,自動解析系統的include路徑、typedef等;“以全局的觀點來看所有的依賴關系”

2.scons文件

    scons中可能出現的文件:
        SConstruct,Sconstruct,sconstruct,SConscript

    scons將在當前目錄以下次序 SConstruct,Sconstruct,sconstruct 來搜索配置文件,從讀取的第一個文件中讀取相關配置。
    在配置文件SConstruct中可以使用函數SConscript()函數來定附屬的配置文件。按慣例,這些附屬配置文件被命名為”SConscript”,當然也可以使用任意其它名字。

3.scons的命令行參數

1     scons: 執行SConstruct中腳本
2     scons -c   clean
3     scons -Q  只顯示編譯信息,去除多余的打印信息
4     scons -Q   --implicit-cache hello 保存依賴關系
5                    --implicit-deps-changed   強制更新依賴關系
6                    --implicit-deps-unchanged  強制使用原先的依賴關系,即使已經改變

4.SConstruct提供的方法

4.1 Program:生成可執行文件

1     Program('hello.c')                         //編譯hello.c可執行文件,根據系統自動生成(hello.exe on Windows; hello on POSIX)
2     Program('hello','hello.c')                    //指定Output文件名(hello.exe on Windows; hello on POSIX)
3     Program(['hello.c', 'file1.c', 'file2.c'])            //編譯多個文件,Output文件名以第一個文件命名
4     Program(source = "hello.c",target = "hello")
5     Program(target = "hello" , source = "hello.c")
6     Program('hello', Split('hello.c file1.c file2.c'))       //編譯多個文件
7 
8     Program(Glob("*.c"))
9     src = ["hello.c","foo.c"];Program(src)

4.2 Object:生成目標文件

1     Object('hello.c')                         //編譯hello.c目標文件,根據系統自動生成(hello.obj on Windows; hello.o on POSIX)

4.3 Library:生成靜態/動態庫文件

1 Library('foo', ['f1.c', 'f2.c', 'f3.c'])               //編譯library
2 SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])            //編譯 shared library
3 StaticLibrary('bar', ['f4.c', 'f5.c', 'f6.c'])            //編譯 static library

 庫的使用:

1  Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.')        //連接庫,不需加后綴或是前綴

4.4 SourceSignatures:判斷源文件是否修改

1     SourceSignatures('MD5')                       //根據內容是否改變,默認方式
2     SourceSignatures('timestamp')                  //根據修改時間

4.5 TargetSignatures:判斷目標文件是否改變

1     TargetSignatures('build')                     //根據編譯結果
2     TargetSignatures('content')                    //根據文件內容,如果只是加了句注釋,將不會被重新編譯

4.6 Ignore:忽略依賴關系

1     Ignore(hello, 'hello.h')                     //忽略某個依賴關系

4.7 Depends:明確依賴關系

1 Depends(hello, 'other_file')                     //明確依賴關系 

4.8 SConscript:scons的配置文件

    源文件的目錄結構如下:
    src:
    |    SConstruct
    |    test.cpp
    |    mA(目錄):
         |     SConscript
         |     func.cpp
    其中test.cpp為主文件,中調用func.cpp中定義的函數
  
    SConstruct內容如下:

1 env = Environment()
2 flags = env.ParseFlags(['-pthread -I/usr/include/stlport ',' -L .'])
3 env.MergeFlags(class_flags)
4 subobj = SConscript(['mA/SConscript'])
5 obj = subobj + env.Object(Glob("*.cpp"))
6 env.Program("test",list(obj),LIBS = ['libstlport.a'])

mA/SConscrip如下:

1 obj = Object(Glob("*.cpp"))
2 Return("obj")

不出意外的話上邊的工程編譯可以通過,但是運行的時候會Aborted。因為test.cpp,mA/func.cpp都使用了包含string類型的那個類,但是由於編譯環境的不同,test.cpp認為string變量的大小是24字節, mA/func.cpp認為string變量的大小是4個字節(libstlport.a搗的鬼)。

     解決問題的辦法就是環境變量輸出,修改SConstruct和mA/SConscript如下:
    SConstruct:

1 env = Environment()
2 flags = env.ParseFlags(['-pthread -I/usr/include/stlport ',' -L .'])
3 env.MergeFlags(class_flags)
4 Export('env')
5 subobj = SConscript(['mA/SConscript'],exports = 'env')
6 obj = subobj + env.Object(Glob("*.cpp"))
7 env.Program("test",list(obj),LIBS = ['libstlport.a'])

mA/SConscript:

1 Import('env')
2 obj = env.Object(Glob("*.cpp"))
3 Return("obj")

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM