摘自:https://www.jianshu.com/p/e4bd3ab9e5d6php
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, 如Object
, SharedLibrary
,StaticLibrary
,LoadableModule
,StaticObject
,CFile
ide
編譯多個文件很是簡單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分爲三種
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],不少東西都沒寫,在平常工做中能夠一點一點去體會。