waf python build 工具使用流程


waf python build 工具使用流程

waf 的 build 理念

  build 了之后,可以跟蹤到 ${SRC} 和 ${TGT} 有關聯的文件,只有 ${SRC} 被修改過,在下次build的時候才會重新 build 這個文件,想想如果一個 project 非常大,在測試過程中或者發布都要 build 一次,每次都要全部 build 一遍,盡管你只修改了一個文件,當然如果你知道你改了哪個文件,可以單獨 build 那個文件,但是誰能記得清自己修改了哪些文件,waf 可以解決這個問題,不過 waf 雖然可以用相對路徑,但是最終還是絕對路徑,如果移動了 project 文件夾,那么 SRC 和 TGT 的關系就丟失了,如果 build 關系也能用相對路徑,那就更完美了。

設置運行 waf 的 alias

注意,以下使用的是 Git bash 控制台

waf是python寫的,所以用python來運行

alias waf='[python-path]/python.exe [waf-path]/waf'

基本的 wscript

 1 #!//usr/bin/python
 2 # -*- coding: utf-8 -*-
 3 
 4 top = '.'
 5 out = 'build' #這個是默認的out文件夾,可以設其它名
 6 
 7 def configure(cfg):
 8     for f in cfg.path.ant_glob('folder/**/*.py'):  #通過ant.glob來獲取某個文件夾下面的所有py文件,f 是 waf 的某個類對象,所以有以下的方法
 9         print(f.abspath())  #絕對路徑
10         print(f.srcpath())  #相對路徑,f 是 waf 中的類對象,所以絕對路徑是 wscript 所在的路徑
11 
12 def build(bld):
13     bld(rule='"python.exe -OO -c "import py_compile;py_compile.compile(\'${SRC}\', cfile=\'${TGT}\', doraise=True)"',
14         source='test/foo.py',   #注意:source的路徑是相對路徑(wscript所在的路徑),不然build的過程會說source找不到
15         target='D:/foo.pyc',    #注意:target可以是絕對路徑,也可以是相對路徑,如果是相對路徑,build后會在wscript所在文件夾下的 build(out文件夾) 文件夾中找到
16         )

代碼解析:

top:一般默認是'.',代表源代碼所在的工程目錄

out:是執行 waf build 后在 wscript 所在路徑自動生成的 build 文件夾,target 中如果使用相對路徑,都會存放在 out 中,這也是默認的 waf build command 運行的路徑,build 的時候可以看到 entering directory 'xxx',如果結合其它非 waf 命令,就要注意這點。

cfg.path:代表 wscript 的所在路徑

cfg.path.ant_glob():正則匹配cfg.path下的文件

configure(cfg) 和 build(bld) 函數:waf 內置的函數,我們通過重寫它們來實現我們的功能,它們的第一個參數也是內置的 waf 類,有定義好的各種功能

bld()中的 rule 參數,${SRC} 和 ${TGT} 是內置的變量,分別代表 source 和 target 參數,注意:source 和 target 最后傳遞到 rule 里是一個waf node list [],source 的路徑是以 wscript 所在路徑為前綴的,而且在win系統中 f 中的路徑使用的是'\',既然 rule 是 str,使用 f 就要注意轉義。另外可以這樣:

"${SRC[0].abspath().replace(\'\\\\\', \'/\')}"

如果是win系統,直接加r:

'r\'%s\''%"${SRC[0].abspath()}"

bld() rule 中執行多行命令

bld(rule = 'set PYTHONPATH=%%%%PYTHONPATH%%%%;D:/myPath && python.exe myPython.py')

代碼解釋:

用 && 來區別多行執行,這應該是 bat 的多行命令符號

注意%的格式化,'%%'才是代表一個'%',而在str中當命令,如果前面不帶r,就要四個%%%%

build bld() task 任務強制執行

waf 會對 source 跟蹤,如果編譯過的文件沒有被修改,那么再次編譯的時候就不會去處理那個文件,但是有這樣一種情況,我們只是在 bld 中去運行其他的編譯工具,那么 source 是不會經常被改變的,而且跟蹤的事是其他的編譯工具的事情,waf 要強制這個bld運行,只要加 always 參數即可,具體如下:

def build(bld):
    bld(
        rule = '',
        always = True
    )        

 

wscript 使用基本流程

waf configure  在build之前必須 configure 過

waf build    build

waf distclean  清理所有 waf 的動作所生成的中間文件,執行后,如果想 build,需要重新 configure

waf install

waf 提供了非常方便的安裝方式。

假如在 wscript 中的 build 方法內

def build(bld):
    start_dir = bld.path.find_dir('src/bar')
    bld.install_files('D:/installPath', start_dir.ant_glob('**/*.py[cod]'),
                          cwd = start_dir, relative_trick = True)

注意:waf build 並不會執行 bld.install_files() 方法,正確執行的方法是:

waf install

waf uninstall   #這是卸載

代碼解釋:

install_files()

參數1:安裝路徑

參數2:安裝的文件

cwd 和 relative_trick:兩者結合,安裝到 'D:/installPath' 后,就會保留 cwd 后面的目錄結構(就是把cwd的部分去掉),例如 [cwd]/myFolder/* -> [參數1 路徑]/myFolder/*

start_dir.ant_glob('**/*.py[cod]'):在 start_dir 下找到所有的 pyc,pyo,pyd,注意:**/* 是waf的正則表達式,表示所有子目錄下的文件

更多waf install 函數,請參考:waf 文檔 5.2.2. Installing files

cmd 判斷

如 waf install,它其實執行的是 build(bld),尤其是一些 bld(always = True) 的情況,我們需要根據不同的 cmd 來判斷是否需要執行一些函數

bld.cmd == 'build'

bld.cmd == 'install'

等等

waf node

The Waf nodes inherit the class waflib.Node.Node and provide a tree structure to represent the file system

waf node 繼承於 waflib.Node.Node,和提供了一個代表文件系統的樹結構

一些路徑處理方式:

ctx.root:系統的根目錄,linux為/,win系統為包含了所有磁盤的文件夾,這個 node 可以用來獲得與 wscript 無關的一些路徑的node,例如 ctx.root.find_dir("D:/"),在處理一些其它路徑的時候非常有用

ctx.srcnode:top 路徑,ctx是 wscript 方法的第一個參數

ctx.bldnode:out 路徑,ctx是 wscript 方法的第一個參數

node.abspath():返回 node 的絕對路徑,類型是str,注意這里的絕對路徑是是以top路徑為前綴的

node.srcpath():返回 node 的相對路徑,類型是str,注意這里是top的相對路徑

node.from_path(node):去掉 node 的部分

node.find_dir(''):在 node 的路徑下找相應路徑,返回一個 node

node.search_node(""):找一個node(文件或者文件夾),如果找不到,返回 None

ctx.path:wscript所在路徑

node.parent:父路徑

node.child:子目錄

node.ant_glob():正則匹配 node 下的文件,默認返回的都是文件,ant_glob() 參數說明:

參數1:str 或者 str list,如果是 list,表示匹配里面多個可能

excl = []:不包含[]中匹配到的內容

dir = False:如果是 True,則返回的是匹配到的文件夾

scr = False:暫時不知道有何作用,可以忽略,不過按照字面的意思,可能是返回的是相對了的路徑

常用的正則表達式:

node.ant_glob('*'):node 下的所有文件,不包括子文件夾里面的文件

node.ant_glob('**'):node 下的所有文件,包括子文件夾里面的文件

node.ant_glob('**/folder/'):node folder文件夾(包括子文件夾)下的所有文件

node.ant_glob('**/file'):node folder文件夾(包括子文件夾)下的所有的 file

node.ant_glob('**/*.py[cod]'):node 文件夾(包括子文件夾)下的所有 pyc pyo pyd 文件

提醒:當out 和 top 與 wscript 不在同一個目錄,就要注意路徑處理

env 環境設置

 1 #!//usr/bin/python
 2 # -*- coding: utf-8 -*-
 3 
 4 top = '.'
 5 out = 'build'
 6 
 7 def configure(cfg):
 8     cfg.env.TESTENV = 0
 9     #or
10     #cfg.env[TESTENV] = 0
11 
12 def build(bld):
13     print(bld.env.TESTENV)

 

waf 還有很多其它功能

官方文檔:https://waf.io/book/#_projects_and_commands


免責聲明!

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



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