CMake有指令file(COPY …)可以用來copy檔案,可是如果將此指令寫在CMakeLists.txt中,該指令只會在configuration階段複製檔案。
有時我們會希望每次建置、make時都copy一次檔案。
自己遇到的使用案例 : 更新shader source file
OpenGL的shader是在Runtime用OpenGL的API將source code交給drive編譯的,因此在runtime需要有檔案提供shader的source。
這類檔案就像DLL一樣當程式啟動時需要能找到並載入,將檔案跟執行檔放在同一個目錄之下是最簡單的做法。
因此我的需求是要cmake每次都將source tree(原始碼目錄)中的shader file複製到build tree(建置目錄)中執行檔的目錄。
對於純粹想建置專案的人來說,把file(COPY …)寫在CMakeLists.txt中是OK的,因為檔案有copy到build tree就好。
但是對於專案開發者來說,需要能在每次建置時都從source tree複製shader到build tree中,以確保使用最新版本的shader file執行Debug。當然也可以手動,比較麻煩就是了。
如前所述,只將複製指令寫在CMakeLists.txt是不夠的。
利用add_custom_target或add_custom_command安插建置步驟,使任務在建置時執行
上StackOverflow找到的相關解答:
大致上,這方法額外寫個CMake檔案並利用add_custom_target安插執行此cmake檔案的步驟,該cmake腳本內的指令就是file(COPY …)
若想讓特定事件在每次建置時發生可利用這類方法
更好的方法
S.O.上找到的方法需要額外的cmake file,並使用script processing mode執行。我發現cmake除了processing mode也有command mode。該模式透過加入flag “-E” 切換:
cmake已經為我們準備了需多常用的指令,接下來只要如法炮製讓cmake在建置時觸發cmake的copy command就行了:
|
|
建立自訂目標後cmake會在指定的建置系統中建置對應的目標,如果建置系統為Unix make可以用以下指令執行copy指令:
問題: Xcode或Visual Studio的build type目錄
若你是使用Unix make或許到目前已經功德圓滿了,建置系統會在每次建置執行檔時幫我們複製shader。可是我遇到問題了。
Xcode或Visual Studio這類IDE內建build type而不同build type的執行檔通常會放在不同目錄裡:
Oh no..輸出的執行檔main在Debug下,而我們的shaders卻在Debug之外。可見CMAKE_SOURCE_DIR變數指向的位置跟實際執行檔輸出的位置是可能有出入的。
執行檔會輸出到哪是IDE決定的,而IDE的專案是CMake的Generator產生的,因此除非將路徑寫死在CMakeLists.txt,否則輸出路徑是generator決定的。
shader被複製到哪裡並不重要,只要他跟輸出的執行擋在同一個目錄即可。
對於Generating階段才做的決定cmake有一類像placeholder的特殊變數(`$’開頭,很像變數)代表generator給出的值。
使用 $
我的執行檔建置目標稱為main,因此 $
可是,單純的修改先前的code會得到cyclic depedencies錯誤。
建置目標的depdencies為我們的copy_shader_files目標,而要決定檔案目的地的卻又是建置目標,造成循環相依性。
add_custom_command
別灰心,除了add_custom_target,我們還可以透過add_custom_command叫cmake幫我們做事。只是add_custom_command不會在建置系統中建立任務或目標,沒辦法手動啟動,對於建置系統來說就是建置執行檔的一個環節。
|
|
add_custom_command的語法稍微不同,不過指令依然是cmake的command mode。
目前這段code可以滿足我的需求: 在每次建置時把檔案複製到執行檔的目錄中。