摘要:以上便是所有的內容,可以看到涉及到的文件不算多。用也一樣,一般是再等機器的轟鳴停止后繼續工作流。這個抽象幾乎相互獨立,個人認為是很好的一個抽象。從聲明式表達到生成的這項任務,由完成。
前言
看懂這篇文章需要一點使用waf的經驗,不過也不費事,看看例子也夠了。
構建系統簡談軟件構建系統不像是個很多人在研究的東西,所以在網絡上很少能找到剖析某個構建系統原理、或者闡述構建系統principle的文章??磏s3的過程中接觸到了waf,發現其文檔waf book[https://waf.io/book/]很好的闡述了構建系統的一些基礎知識,個人認為比cmake的文檔好一些。因為其核心只有十幾個文件,這個構建系統只需要一個10k+的waf文件,所以可以放到版本庫里(像對python的評價一樣,batteries included),唯一要求就是環境中有python,而這對一個開發人員來說顯然不是一件困難的事情。
|-- Build.py |-- ConfigSet.py |-- Configure.py |-- Context.py |-- Errors.py |-- Logs.py |-- Node.py |-- Options.py |-- Runner.py |-- Scripting.py |-- Task.py |-- TaskGen.py |-- Tools [directory] |-- Utils.py |-- ansiterm.py |-- extras |-- fixpy2.py `-- processor.py
以上便是所有waf的內容,可以看到涉及到的文件不算多。Tools下包含了很多語言的構建工具,比如c/c++/java/qt/ruby/tex等等,如果自己有能力定制,可以只保留自己項目里需要的tool,可以做到更小。(雖然個人認為沒有必要)
核心抽象如果是寫編譯語言的(c/c++/rust/go/fc/d),那么構建系統是每天都在用的。在敲擊make
像make clean dist類似,可以在構建命令后面自行添加指令,這種capibility由Context提供
構建系統最重要的功能就是按需構建,要判斷出哪些文件要編譯而哪些是不用的,這用到了TaskGen與Task的抽象
并行構建提升速度,由Runner來提供。
這3個抽象幾乎相互獨立,個人認為是很好的一個抽象。
Context每一個跟在./waf后面的指令,都對應一個Context。如果是build/configure/list/step/install/uninstall,waf自行提供了對應的Context的子類用于執行這些命令,如果是其他的自定義函數,那么就會依托于Context本身,可以在自定義函數里用Context自定義的函數,比如recurse來遍歷子目錄執行子目錄里的同名自定義函數。
如果項目根目錄下的wscript有do_sth,就可以./waf do_sth
def do_sth(ctx): ctx.load("compiler_cxx") # 加載工具 ctx.recurse(["src","dep"]) # 遍歷子目錄,執行子目錄下wscript里的do_sth ctx.exec_command("touch foo.txt") ctx.msg("hello")
這里函數參數ctx就是指向了Context的一個實例,而do_sth是作為Context上的一個方法而存在的,可以直觀的理解為,我們為Context增加了一個自定義的do_sth方法,所以可以自由調用Context里本來提供的方法。
./waf build執行時綁定的Context是BuildConetxt,在Build.py里被定義,在waf build的時候,執行的是wscript里def build(bld)這個方法。舉一個例子
def configure(conf): conf.load("compiler_cxx") def build(bld): bld.shlib(source="a.cpp", target="mylib3") bld.program(source="main.cpp", target="app", use="mylib") bld.stlib(target="foo", source="b.cpp") # 直接調用bld bld(features = "c cprogram glib2", use = "GLIB GIO GOBJECT", source = "main.c org.glib2.test.gresource.xml", target = "gsettings-test")
這里bld指向了BuildContext的一個實例,這意味著BuildContext里所有的方法都在這個函數里都是可用的,可以通過bld.xxx來調用。
值得注意的是,在Build.py中,可是找不到shlib/probram/stlib這3個方法的,但是在這里卻調用成功沒有報錯,這全部依賴于conf.load("compiler_cxx")這一句。執行這句話后,就給bld指向的BuildContext實例綁定了shlib/program/stlib這3個方法。
那直接調用bld()呢?這個就要看Build.py里的BuildContex():__call__方法了。從這里開始,就涉及到TaskGen這個抽象了。
最終需要執行的編譯指令、中間代碼生成等,每一條都對應一個task,我們不可能去一個一個的寫task,而是希望以一種聲明式的方法表達想要做的事情,這就是task_gen所完成的任務。從聲明式表達到生成task的這項任務,由waf build完成。在執行的過程中,會對搜集到的每個task_gen執行一下post(),然后這個task_gen就生成了自己所有的task。作為一個靈活的構建系統,waf提供了很多方法來讓我們hook到post()的過程中。對于每個task,到底該不該執行需不需要執行,它自己會追蹤自己的依賴,職責分離,我很喜歡這個設計思路。
以前一小節為例,共在build(bld)里一共進行了4次調用,這意味著生成了4個task_gen的實例,在真正執行構建過程之前,會有一個地方對這4個實例各自調用一下post(),把所有的task_gen都消滅掉,變成task。至于怎么hook,這是個比較關鍵的點,如果理解了,就能很好的自定義waf了。
首先看看寫好的wscript,它的聲明式體現在什么地方呢?體現在函數參數里。得益于python的語言特點,可以隨便加參數,然后在函數實現里用**kw來取這些值。這意味著可以隨便加自己想要的key=value進去,這些加進去的參數是可以在自定義的hook過程中取到的,這算是可自定義的一個基礎。(ruby自定義的能力更強,畢竟dsl是其強項,但可能限于ruby的流行程度以及發行版是否默認安裝,讓作者最后選擇了python,不過也已經夠用了)
在post()的過程中,會從task_gen.meths[]里依次取出方法來執行,hook的方式就是把自定義的方法塞到這個task_gen.meths[]之中。這只要在自定義的方法上加一個@TaskGen.taskgen_method的注解就能實現,還是挺簡潔的吧?聲明式中寫的key=val,都能通過taskgen.key取到,這樣一來,幾乎就獲得了無限的能力來自定義構建過程了。
在taskgen.meths[]里有幾項預定義的方法,waf也提供了指令來讓我們定制自己方法執行的位置??偠灾?,想要什么內容,直接在wscript里以key=val的方式指定,然后在自己的方法里用getattr來取就行了。
這也只是個支持性框架,具體到某個語言(c/c++)是怎么做的,到后面再看。
waf自己會默認起和cpu core相同數量的進程來執行構建認任務,而且構建過程的輸出也很清晰漂亮。waf也提供了lazy的模式,不是一下子把所有的task_gen都轉化,所以也是用了一些技巧來達成這個目的。在看waf代碼的過程中,能看到很多pythonic和近乎炫技的技法,可見作者真是把python語言玩弄于股掌之中。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/45266.html
摘要:在上安裝標簽空格分隔監控首先說一句,在上安裝真的很坑爹。。?;蛉绻厦孢@個方法無法安裝那就用源碼安裝的方法。安裝開始好幾次就死在安裝這個上面,版本的通過命令安裝的不行,對應版本的包的名字叫做。 在 CentOS 5.8 上安裝 Graphite 標簽(空格分隔): 監控 monitor CentOS 5.8 Graphite 首先說一句,在 CentOS 5.8 上安裝真的很坑爹...
摘要:漢字拼音 Awesome Python A curated list of awesome Python frameworks, libraries and software. Inspired by awesome-php. Awesome Python Environment Management Package Management Package Repositorie...
摘要:如今,多樣化的攻擊手段層出不窮,傳統安全解決方案越來越難以應對網絡安全攻擊。自適應安全平臺集成了預測預防檢測和響應的能力,為您提供精準持續可視化的安全防護。 近一年來,Docker 已經逐漸成為 container 界的事實標準,成為技術人員不可或缺的技能之一,就像 Docker 宣稱的那樣,「Build,Ship,and Run Any App,Anywhere」,容器極大簡化了環境...
摘要: Caching Libraries for caching data. Beaker - A library for caching and sessions for use with web applications and stand-alone Python scripts and applications. dogpile.cache - dogpile.cache...
閱讀 3490·2019-08-30 15:53
閱讀 3406·2019-08-29 16:54
閱讀 2190·2019-08-29 16:41
閱讀 2397·2019-08-23 16:10
閱讀 3377·2019-08-23 15:04
閱讀 1342·2019-08-23 13:58
閱讀 347·2019-08-23 11:40
閱讀 2452·2019-08-23 10:26