SCons的使用


一、概述

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

 

二、scons文件

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

  

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

 

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

 

四、SConstruct提供的方法

1、Program:生成可執行文件

    Program('hello.c')  編譯hello.c可執行文件,根據系統自動生成(hello.exe on Windows; hello on POSIX)
    Program('hello','hello.c') 指定Output文件名(hello.exe on Windows; hello on POSIX)
    Program(['hello.c', 'file1.c', 'file2.c']) 編譯多個文件,Output文件名以第一個文件命名
    Program(source = "hello.c",target = "hello")
    Program(target = "hello" , source = "hello.c")
    Program('hello', Split('hello.c file1.c file2.c')) 編譯多個文件

    Program(Glob("*.c"))
    src = ["hello.c","foo.c"];Program(src)
 
2、Object:生成目標文件

    Object('hello.c') 編譯hello.c目標文件,根據系統自動生成(hello.obj on Windows; hello.o on POSIX)
 
3、Library:生成靜態/動態庫文件

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

    庫的使用:

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

 

4、SourceSignatures:判斷源文件是否修改
    SourceSignatures('MD5')     根據內容是否改變,默認方式
    SourceSignatures('timestamp') 根據修改時間

 

5、TargetSignatures:判斷目標文件是否改變
    TargetSignatures('build')   根據編譯結果
    TargetSignatures('content')  根據文件內容,如果只是加了句注釋,將不會被重新編譯
 
6、Ignore:忽略依賴關系

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

 

7、Depends:明確依賴關系

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

 

8、SConscript:scons的配置文件。

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

        <textarea cols="57" rows="1" name="code" class="cpp"> subobj = SConscript(['mA/SConscript']) obj = subobj + Object(Glob("*.cpp")) Program("test",list(obj)) </textarea>  
    SConscript內容 :
        <textarea cols="57" rows="1" name="code" class="cpp"> obj = Object(Glob("*.cpp")) Return("obj") </textarea>    
    上例中,在主目錄中執行 scons就可以編譯整個"工程"。SConstruct編譯主目錄中的test.cpp,並通過SConscript編譯mA目錄下的源文件,並最終生 成可執行文件;SConscript用於編譯mA中的func.cpp並把生成的func.o傳遞給主目錄的SConstruct。

 
10.env:環境變量
     環境變量用於設置在編譯過程中的各種參數,可以用下面的SConstruct打印環境變量的所有信息(實際上env就是一個python字典)
     可以使用如下的SConstruct查看環境變量的內容:
       <textarea cols="73" rows="6" name="code" class="cpp">env = Environment() dict = env.Dictionary() keys = dict.keys() keys.sort() for key in keys: print "construction variable = '%s', value = '%s'" % (key, dict[key]) </textarea>      
     環境變量的使用:
         env = Environment()   #創建默認的環境變量,默認scons會按編譯器的默認選項來進行編譯
         import os
         env = Environment(CC = 'gcc',CCFLAGS = '-O2') #創建並設置環境 變量
         env.Program('foo.c')

     環境變量的復制:
         env = Environment(CC = 'gcc')
         opt = env.Clone(CCFLAGS = '-O2')
         dbg = env.Clone(CCFLAGS = '-g')

     環境變量的替換:
         env = Environment(CCFLAGS = '-DDEFINE1')
         env.Replace(CCFLAGS = '-DDEFINE2')
         env.Program('foo.c') 
     環境變量的輸入輸出:用於統一多目錄源文件的編譯選項,如:
     src:
     |    SConstruct
     |    libstlport.a
     |    test.cpp
     |     include(目錄):
          |    foo.h
     |    mA(目錄):
          |    SConscript
          |    func.cpp
   

     test.cpp和mA/func.cpp都引用了include/foo.h,test.cpp調用了mA/func.cpp的功能函數,其中include/foo.h中定義了一個包含string類型的類。

     SConstruct如下:
       <textarea cols="72" rows="4" name="code" class="cpp">env = Environment() flags = env.ParseFlags(['-pthread -I/usr/include/stlport ',' -L .']) env.MergeFlags(class_flags) subobj = SConscript(['mA/SConscript']) obj = subobj + env.Object(Glob("*.cpp")) env.Program("test",list(obj),LIBS = ['libstlport.a']) </textarea>

    mA/SConscrip如下:
       <textarea cols="73" rows="1" name="code" class="cpp">obj = Object(Glob("*.cpp")) Return("obj") </textarea>  


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

     解決問題的辦法就是環境變量輸出,修改SConstruct和mA/SConscript如下:
    SConstruct:
       <textarea cols="72" rows="5" name="code" class="cpp">env = Environment() flags = env.ParseFlags(['-pthread -I/usr/include/stlport ',' -L .']) env.MergeFlags(class_flags) Export('env') subobj = SConscript(['mA/SConscript'],exports = 'env') obj = subobj + env.Object(Glob("*.cpp")) env.Program("test",list(obj),LIBS = ['libstlport.a']) </textarea> 
    mA/SConscript:
       <textarea cols="73" rows="2" name="code" class="cpp">Import('env') obj = env.Object(Glob("*.cpp")) Return("obj")</textarea>

 

from:http://blog.csdn.net/sealyao/article/details/6402257


免責聲明!

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



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