scons 簡單入門

scons 簡單入門

摘自:https://www.jianshu.com/p/e4bd3ab9e5d6php

0.2042019.01.20 12:58:44字數 1201閱讀 3021

簡單入門

hello world

scons由Sconstruct 做爲入口,控制如何進行編譯操做。Sconstruct 自己是一個python文件,故須要遵循python的語法,以及能使用一些python的方法。(如咱們能夠用print 來debug)css

這有一段很簡單的hello.cpppython

#include <iostream> int main() { std::cout << "hello world" << std::endl; } 

以及一個很簡單的Sconstructios

Program("hello.cpp") 

Program是Scons中的一個編譯方法(builder_method), 告訴Scons 咱們想要把hello.cpp 編譯成一個可執行文件。c++

保證Sconstruct 和hello.cpp 在同一個文件夾下,執行scons,就能夠完成編譯,生成可執行文件hello。shell

scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... g++ -o hello.o -c hello.cpp g++ -o hello hello.o scons: done building targets. 

能夠看到,咱們只指定了一個cpp文件,scons會默認給可執行文件一個名字,以及完成.o文件的生成,很是智能。固然,咱們也能指定輸出文件的名字,Program("target_name", hello.cpp")bash

另外,除了Program ,還有其餘不少builder_method, 如ObjectSharedLibraryStaticLibraryLoadableModuleStaticObjectCFileide

編譯多個文件

編譯多個文件很是簡單ui

  • 直接使用list Program(["a.cpp", "b.cpp", "c.cpp"])便可。spa

  • 也可使用Glob方法

    source = Glob("src/*.cpp")
    print source # python語法,能夠打印出來debug
    Program(["hello.cpp"] + source)

    用這種方式把src下的文件都加進來

  • Program(Split("a.cpp, b.cpp c.cpp") Split 也是SCons提供的一個方法,顧名思義了。

編譯一個庫

把Program改成 Library (或者StaticLibrary,這二者是同樣的)便可。

Library("t", Glob("src/*.cpp"))

這樣就能獲得一個靜態庫了。 若是如要一個動態庫,則可使用SharedLibrary。

連接一個庫

上邊咱們學會如何編譯一個庫了,那麼如何連接呢?也很簡單,加個參數便可

source = Glob("src/*.cpp")
SharedLibrary("t", source)
Program(["hello.cpp"], LIBS=["t"], LIBPATH=".")

Program 能夠理解爲python 的一個方法,不少參數都有默認值,咱們要作的只用覆蓋其默認值便可。如上,咱們指定引入LIBS。一樣的,LIBS參數也能夠是個str,LIBPATH也能夠是個list,放上全部要查找的路徑,如['/usr/lib', '/usr/local/lib'],這裏就不贅述了。

略微高級一點的功能

判斷是否須要從新編譯

SCons很智能,只會編譯須要編譯的內容。好比我剛執行完scons,再次執行,則會提示scons: . is up to date.。 那麼他是如何作到的呢?也不復雜,依賴一個Decider的方法,以及一個.sconsign.dblite文件。

默認狀況下,若是文件的md5值改變了,纔會從新編譯。每次編譯,SCons都會把md5存起來,再次執行時,若是md5沒變,則不須要rebuild。

若是咱們不但願使用md5,而是使用文件修改時間呢?很簡單,增長Decider('timestamp-newer')(默認狀況下爲md5)。也可使用'MD5-timestamp,則他們一塊兒變了纔會rebuild。

咱們前面也說到,Decider是一個方法,那很顯然,咱們也能夠本身寫個decider方法,詳細的能夠看scons-user.pdf 6.1.5,這裏不細寫了。。

env

env分爲三種

  • external enviroment 保存在os.environ 中,和scons其實沒太大關係,保存着一些系統定義的環境變量,如PATH之類

  • construction environment

    這個比較重要,咱們可能但願不一樣的源文件使用不一樣的編譯參數,這時候咱們就能設置不一樣的編譯環境,指定哪一個文件用哪一種編譯。construction environment 中保存了構建相關的一些參數。

    使用方式以下

    env1 = Environment(CXX = 'gcc') # 建立一個env print env1["CXX"] # 獲取參數 env2 = env1.Clone(CXX = 'g++') # 複製一個env env1.Replace(CXX = 'g++') # 修改參數 env1["CXX"] = "clang++" #再修改參數 env1.MergeFlags("-g") #增長一個flag 

    就能夠構建出一個env,除了CXX 被修改之外,其餘參數均不變。另外,咱們也能夠像一個dict同樣,去獲取env中的內容。

  • execution enviroment

    這其實就是construction environment 中的一個變量ENV

    env = Environment()
    print env["ENV"]
    
    env2 = Environment(ENV=os.environ)
    env3 = Environment(ENV = {"PATH" : os.environ["PATH"]})

    幾個簡單的例子,一看就明白了

命令行輸入的參數

好比咱們想經過一個debug字段來控制是否開啓debug模式,怎麼作呢?能夠經過ARGUMENTS

env = Environment() debug = ARGUMENTS.get("debug", 0) if int(debug): print "in debug mode" 

scons debug=1就能夠了。

小結

上面只是我在看的時候作的一個小結,詳細的能夠看(文檔)[https://scons.org/doc/production/PDF/scons-user.pdf],不少東西都沒寫,在平常工做中能夠一點一點去體會。

相關文章
相關標籤/搜索