scons使用


轉載請注明來源:https://www.cnblogs.com/hookjc/

一、SConstruct File {{{1
    1. Sconstruct 文件 是scons用來控制編譯的文件
    2. Sconstruct 文件 是一個python腳本
    3. SConstruct 文件 是一個類似於makefile一樣的東西, 告訴 scons做什么,而不是嚴格的規定soncs做這件事的步驟

二、scons選項 {{{1
    -c      Cleaning up After a Build
    -Q      Making the scons output less verbose

三、SConstruct 腳本的編寫基礎 {{{1
    
1. builder method {{{2
    Program      : generate executable file
    Object       : generate Object file
    Java         : 編譯java程序, User Guide 2.3, Chapter 25
    Library      : 靜態庫,   也可以使用 StaticLibrary替代
    SharedLibrary: 動態庫

2. 指定目標名 {{{2
    Program('hello.c')                # 生成 hello.exe
    Program('new_hello', 'hello.c')   # 生成 new_hello.exe

3. 編譯多個文件 {{{2
    Program(['prog.c', 'file1.c', 'file2.c'])             # 生成 prog.exe
    Program('program', ['prog.c', 'file1.c', 'file2.c'])  # 生成program.exe
    Program('program', ['prog.c', 'file1.obj', 'file2.obj'])  # 可以在文件列表中指定.obj文件

    3.1 使用Glob 編譯所有匹配的文件
        Program('program', Glob('*.c') )

        Glob原型為:Glob(self, pattern, ondisk=True, source=False, strings=False)
            其中pattern 支持unix系統下的文件名匹配: *(任意多個字符), ?(單個字符) 和 [](括號中的任一字符)
    3.2 使用Split
        Program('program', Split('main.c file1.c file2.c'))

        Split以空白字符為分隔符,將字符串分割,因此,你也可以這樣寫:
        Program('program', Split("""
                                    main.c
                                    file1.c
                                    file2.c
                                 """) )
    3.3 使用關鍵字參數
        Program(target = 'program', source = 'hello.c')
        

4. 指定編譯選項 {{{2
    $CPPFLAGS  指定編譯選項
    $LINKFLAGS 指定鏈接選項, 如 /DEBUG
    $CPPDEFINES指定預編譯器

    $LIBS      指定所需要鏈接的庫文件
    $LIBPATH   指定庫文件(.lib)的搜索目錄
    $CPPPATH   指定[.h, .c, .cpp]等文件搜索路徑

    例如:
        Library('foo', Split('f1.c f2.c f3.c') )
        Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.')

        注:LIBS和LIBPATH若為一個可以使用字符串,若為多個則使用列表

四、使用Environments {{{1
    一個environment是一個影響程序執行的值得集合。
    (1) 外部環境 External Environment
        外部環境是運行Scons時 用戶的環境變量。它們可以通過os.environ獲取

    (2) 構建環境 Construction Environment
        它包含一些變量,這些變量會影響Scons構建目標的行為
    (3) 執行環境 Execution Environment
        執行環境用於Scons執行外部命令(external command), 以構建一個或多個目標。
        注意:它與外部環境不相同

1. Construction Environment {{{2
    > 創建 construction Environment
        env = Environment()
        一個Environment是一個 (name,value)的集合,可以這樣查看它的內容:
            for item in env.Dictionary():
                print '(%s:%s)' % (item, env[item])

    > 查看變量
        env['CC'] #查看 CC ,即C語言編譯器
        env.subst('$CC') # 功能同上
            它的優勢在於,它會將出現在結果中的環境變量轉換成最終的值
            使用AllowSubstException()函數,使得當subst中的變量不存在時報告錯誤,
                AllowSubstException()
                env.subst('$missing') # 出現異常,NameError
    > 修改環境變量
        拷貝一個環境變量
            使用env.Clone #詳見user guide 7.2.7
        替換一個已經存在的環境變量
            env.Replace
        為一個沒有被定義的變量設置默認值
            env.SetDefault
        為一個已存在的環境變量增加一個值
            env.Append, 例如:
            env.Append(CCFLAGS = '-option -O3 -O1')
            env.Append(CCFLAGS = ['-option', 'O3'])
        為一個環境變量增加一個唯一的值
            env.AppendUnique
        在最前邊添加一個值
            env.Prepend
        在最前邊添加一個唯一的值
            env.PrependUnique
        合並環境變量
            env.MergeFlags, 例如:
            flags = {'CCFLAGS':'-option -O3 -O1'}
            env.MergeFlags(flags)
            flags = {'CPPPATH' : ['/user/opt/include', 'user/local/include']}
            env.MergeFlags(flags)

            #若參數不是Dictionary, 內部調用ParseFlags將其轉化為Dictionary
            env.MergeFlags('-whatever -I/usr/opt/include -O3 -I/usr/local/include')

    > 一些實用的變量
        判斷是否是windows: 
            env['PLATFORM'] == 'win32'

2. Execution Environment {{{2
    當scons構建一個目標文件時,它所使用的外部環境和執行scons時的環境變量是不同的。
    scons使用$ENV 構建變量 中 存儲的目錄 作為它執行命令的外部環境變量

    > PATH 
        POSIX 系統中默認的PATH是 /user/local/bin:/user/bin
        Window系統中默認的PATH是 command interpreter在注冊表中的值

        1. 在構建環境中顯示初始化PATH
            path = ['/user/local/bin', '/bin', '/user/bin']
            env = Environment(ENV = {'PATH':path})
        上面這種方式,只設置了ENV,如果你想保留其他的變量,可以這么做:
            env['ENV']['PATH'] = ['/user/local/bin', '/bin', '/user/bin']
        2. 從 外部環境 初始化 PATH
            import os
            env = Environment(ENV = {'path' : os.environ['PATH']})

            你也可以將完整的外部變量傳遞給執行環境變量:
            import os
            env = Environment(ENV = os.environ)
            這樣做的缺點是:如果環境變量目錄中,有多個目錄包含編譯器如gcc,那么,
                            scons將執行第一個被找到的gcc

        3. 使用env.PrependENVPath 和 env.AppendENVPath
            例如:將'/user/local/bin' 插入 $PATH中第一個位置
                env.PrependENVPath('PATH', '/user/local/bin')
            例如:將'/user/local/bin' 插入 $LIB中最后一個位置
                env.AppendENVPath('lib', '/user/local/lib')

五、Controlling Build Output {{{1
1. 使用Help 函數 來說明SConstruct腳本
    例如:
    Help('this is a debug version')

    在控制台上使用 scons -h 命令查看此幫助信息

    你可以在腳本中多次使用Help,幫助信息會被連接到一起

六、scons 命令行參數 {{{1
    用戶可以為scons指定三種類型的參數:
    > Options    : 以 一個或兩個(-) 開頭 , 詳細參考 User Guide 10.1
    > Variables  : 形式為:variable=value, 詳細參考            10.2
    > Target     : 如果不是一個 Option 或 Variable ,那么就是一個Target , 詳細參考 User Guide 10.3

1. 讀取命令行的Variable參數
    命令行:scons debug=1
    SConstruct腳本如下:
    debug = ARGUMENTS.get('debug', 0)
    if int(debug) :
        pass # do something

2. Command-Line Targets
    scons提供 COMMAND_LINE_TARGETS 供用戶訪問命令行參數中的 Targets列表,例如:
    if 'bar' in COMMAND_LINE_TARGETS:
        print "Don't forget to copy 'bar' to the archivel"
    Default(Program('foo.c'))
    Program('bar.c')

    > 使用 Default函數 定義 默認目標
        當你沒有在命令行參數中指定目標時,scons會編譯每一個目標
        例子:
        env = Environment()
        hello = env.Program('hello.c')
        env.Program('goodbye.c')
        Default(hello)      #如果沒有在命令行指定Target,則會編譯hello

        使用DEFAULT_TARGETS獲取 默認目標, 例如:
            prog1 = Program('prog1.c')
            Default(prog1)
            print "DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS)

        使用 BUILD_TARGETS 獲取要編譯的目標

七、控制目標文件的路徑 {{{1
1. BINDIR {{{2
  >使用Install:如,
      test = env.Program('test.cpp')
      env.Install('bin', 'test.exe') #表示要將test.exe 放到bin目錄下
      或
      env.Install('bin', test)

  >在指定目標名的時候指定其目錄,如:
      env.Program('bin/test', 'test.cpp')

  >將目標放到其他目錄下,並修改名字
      test = env.Program('test.cpp')
      env.InstallAs('bin/testapp.exe', 'test.exe') #表示將test.exe 拷貝到 bin/testapp.exe
      或 這樣寫
      env.InstallAs('bin/testapp', test)
      
      當 需要對多個目標做此操作時,可以這樣做:
           env = Environment()
           hello = env.Program('hello.c')
           goodbye = env.Program('goodbye.c')
           env.InstallAs(['/usr/bin/hello-new', '/usr/bin/goodbye-new'], [hello, goodbye]) #多個目標
           env.Alias('install', '/usr/bin')
      

2. obj文件路徑 {{{2
    使用VariantDir函數指定
3. 一份代碼構建多個版本的Target {{{2
    通常會有這樣的需求,一份源碼,既要構建它的debug版本,又要構建它的release版本,這種情況下,

    >我們需要為不同版本指定不能的obj名字,否則就會產生沖突,導致scons不能工作。簡單的示例如下:
        opt = Environment(CCFLAGS = '-O2')
         dbg = Environment(CCFLAGS = '-g')

         o = opt.Object('foo-opt', 'foo.c')  // 生成 foo-opt.o
         opt.Program(o)

         d = dbg.Object('foo-dbg', 'foo.c')  // 生成 foo-dbg.o
         dbg.Program(d)

     >或者將不同版本的obj放到不同的路徑下:
         o = opt.Object('opt/foo', 'foo.c')  // 生成 foo-opt.o
         opt.Program(o)

         d = dbg.Object('dbg/foo', 'foo.c')  // 生成 foo-dbg.o
         dbg.Program(d)

來源:python腳本自動遷移


免責聲明!

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



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