日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CMake笔记:add_custom_command不执行

發(fā)布時(shí)間:2023/12/8 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CMake笔记:add_custom_command不执行 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

0x00. 前言

在網(wǎng)上看別人做一些手工教程視頻,經(jīng)常能看到這樣的評論:

腦子:我感覺我會(huì)了。
手:你行你來。

之前一直通過編譯腳本去尋找代碼入口,感覺我已經(jīng)懂得CMake的語法了,直到今天寄己要寫一個(gè)腳本去編譯一個(gè)工程才發(fā)現(xiàn),事情并不簡單:腳本并沒有按照我期望的去執(zhí)行。

此工程需要用到Protocol Buffer,因此當(dāng)代碼構(gòu)建的時(shí)候需要使用使用Protocol Buffer編譯器去編譯.proto文件獲得對應(yīng)的生成文件。理論上,想要達(dá)到這個(gè)目的,我們只需要在CMakeLists.txt中使用add_custom_command命令就可以可以生成對應(yīng)的構(gòu)建規(guī)則。但出人意料的是,這條命令并沒有被執(zhí)行,也就是說,并沒有編譯.proto文件的規(guī)則生成,因此當(dāng)最終使用Make去構(gòu)建工程的時(shí)候,沒能通過.proto文件得到對應(yīng)的源代碼。

0x01. 踩雷

整個(gè)命令的使用如下面的代碼所示,作用就是將位${REPO_ROOT}/protobuf/onnx-operators-ml.proto以及${REPO_ROOT}/protobuf/onnx-ml.proto這兩個(gè)文件編譯成C++頭文件以及源文件,并存放到{REPO_ROOT}/src目錄下,其中${REPO_ROOT}是項(xiàng)目的根目錄,例如在我的例子中為/home/sunny/workspace/model-tool/:

set(PROTOBUF_PROTOC_EXECUTABLE ${REPO_ROOT}/build/third_party/protobuf/cmake/protoc)list(APPEND PROTO_FILES "${REPO_ROOT}/protobuf/onnx-operators-ml.proto""${REPO_ROOT}/protobuf/onnx-ml.proto")set(output_dir ${REPO_ROOT}/include) set(protoc_include ${REPO_ROOT}/protobuf)foreach(fil ${PROTO_FILES})get_filename_component(abs_fil ${fil} ABSOLUTE)get_filename_component(fil_we ${fil} NAME_WE)list(APPEND ${srcs_var} "${output_dir}/${fil_we}.pb.cc")list(APPEND ${hdrs_var} "${output_dir}/${fil_we}.pb.h")add_custom_command(OUTPUT "${output_dir}/${fil_we}.pb.cc""${output_dir}/${fil_we}.pb.h"COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --cpp_out ${output_dir} -I${protoc_include} ${abs_fil}DEPENDS ${abs_file}COMMENT "Running C++ protocol buffer compiler on ${fil}" VERBATIM ) endforeach()

官方文檔中該命令的簽名有兩個(gè)形式,在開源的項(xiàng)目中經(jīng)常看到的是下面這個(gè)形式:

add_custom_command(OUTPUT output1 [output2 ...]COMMAND command1 [ARGS] [args1...][COMMAND command2 [ARGS] [args2...] ...][MAIN_DEPENDENCY depend][DEPENDS [depends...]][BYPRODUCTS [files...]][IMPLICIT_DEPENDS <lang1> depend1[<lang2> depend2] ...][WORKING_DIRECTORY dir][COMMENT comment][DEPFILE depfile][JOB_POOL job_pool][VERBATIM] [APPEND] [USES_TERMINAL][COMMAND_EXPAND_LISTS])

從中可以看到,只有OUTPUT以及COMMAND這兩個(gè)參數(shù)是必須的,也就是說,正常情況下只要正確提供了這兩個(gè)參數(shù)的值,在構(gòu)建的時(shí)候肯定會(huì)執(zhí)行這條命令生成的規(guī)則去編譯.proto。但是在我確認(rèn)提供的參數(shù)都沒問題的情況下,這條命令依舊沒有按照預(yù)期工作。

這就非常奇怪了,坦白的講,我的例子中的命令就是從ONNX Runtime中拷貝過來,只不過將一些變量的值修改成了指向我本地機(jī)器中的文件而已,它在別人的工程中能執(zhí)行,為什么到了我這就不好使了呢?把可選的參數(shù)嘗試了一遍,仍然木有結(jié)果。

我終于意識(shí)到,這樣蠻干是不行的,即便瞎貓碰上死耗子偶然嘗試對了一種組合,我依舊不知道它為什么又行了,回頭再需要編寫其他命令的時(shí)候一樣抓瞎。還是需要去文檔中尋找答案。

好在,最終我還是從文檔中悟出了答案。

0x02. 解惑

其實(shí)在官方的文檔中一開始就說的很明白了,只不過當(dāng)時(shí)著急,并沒有認(rèn)真看對整個(gè)命令的綜述,而是著急忙慌地去看應(yīng)該怎么去構(gòu)造每個(gè)參數(shù)的值。官方文檔中是這么說的:

This defines a command to generate specified OUTPUT file(s). A target created in the same directory (CMakeLists.txt file) that specifies any output of the custom command as a source file is given a rule to generate the file using the command at build time.……In makefile terms this creates a new target in the following form:

OUTPUT: MAIN_DEPENDENCY DEPENDSCOMMAND

看到這一段話,我已經(jīng)知道在我的項(xiàng)目中為什么這個(gè)命令不好使了:只有當(dāng)構(gòu)建的目標(biāo)以add_custome_command生成的OUTPUT文件為源代碼的情況下,add_custome_command中指定的命令才會(huì)才會(huì)執(zhí)行。到目前為止,我并沒有在CMakeLists.txt中生成目標(biāo)文件的時(shí)候使用到諸如model-ml.pb.h, model-ml.pb.cc這些文件,也就是說當(dāng)構(gòu)建我的代碼的時(shí)候,根本就用不到model-ml.pb.h, model-ml.pb.cc,既然用不到,那生成它們干啥呢?因此“聰明”的構(gòu)建系統(tǒng)就不去執(zhí)行編譯.proto的命令了。

我們知道,Makefile文件由一系列規(guī)則(rules)構(gòu)成,規(guī)則的形式如下所示:

<target> : <prerequisites> [tab] <commands>

根據(jù)我的項(xiàng)目里CMakeLists.txt中的內(nèi)容,會(huì)生成一個(gè)Makefile文件(Ubuntu中默認(rèn)情況下),其形式大概如下:

model_tool: main.cpp onnx-ml.pb.ccC++ -o model_tool main.cpp onnx-ml.pb.cconnx-ml.pb.cc: onnx-ml.protoprotoc --cpp_out ./include -I./protobuf/ ./protobuf/onnx-ml.proto

為了生成model_tool,需要先生成onnx-ml.pb.cc,因此需要先執(zhí)行protoc命令。而如果我再CMakeLists.txt中并沒有將onnx-ml.pb.cc指定為生成model_tool的源文件之一,所生成的Makefile便會(huì)如下面所示 ,此時(shí)規(guī)則1對規(guī)則2就不存在依賴關(guān)系,因此protoc就不會(huì)執(zhí)行了。

model_tool: main.cppC++ -o model_tool main.cpponnx-ml.pb.cc: onnx-ml.protoprotoc --cpp_out ./include -I./protobuf/ ./protobuf/onnx-ml.proto

想讓model_tool對onnx-ml.pb.cc形成依賴也很簡單,只要在將onnx-ml.pb.cc作為值傳個(gè)最終生成model_tool的命令add_executable就行,如下所示:

list(APPEND CXX_SRCS ${REPO_ROOT}/src/main.cpp${REPO_ROOT}/include/onnx-ml.pb.cc) add_executable(model_tool ${CXX_SRCS}

我一開始就是因?yàn)闆]將onnx-ml.pb.cc也列為生成model_tool的源文件,才導(dǎo)致add_custom_command沒有效果。至于main.cpp中是不是真的引用了onnx-ml.pb.cc的內(nèi)容,Who care?

0x03 總結(jié)

作為總結(jié),這里展示一個(gè)小Demo,文件結(jié)構(gòu)如下:

demo/CMakeLists.txtmain.cppsource.txtutils.h

其中每個(gè)文件中的內(nèi)容如下:

// main.cpp #include "utils.h"int main(int argc, char **argv) {greeting("Sunny");return 0; }// utils.h #ifndef MY_OWN_DEADER__ #define MY_OWN_HEADER__#include <iostream> #include <string> void greeting(std::string who);#endif // #define MY_OWN_HEADER__// source.txt #include <iostream> #include <string>#include "utils.h"void greeting(std::string who) {std::cout<< "Hello " << who << std::endl; }

此時(shí),如果CMakeLists.txt的內(nèi)容如下所示,則會(huì)執(zhí)行cat source.txt > test_file.cpp這條命令生成test_file.cpp,編譯得以通過:

# CMakeLists.txt cmake_minimum_required(VERSION 3.5)project(demo VERSION 0.1 LANGUAGES C CXX)add_custom_command(OUTPUT test_file.cppCOMMAND cat source.txt > test_file.cppDEPENDS source.txt COMMENT "Just copy file contents")add_executable(demo main.cpp test_file.cpp)

而如果CMakeLists.txt的內(nèi)容如下所示,則cat source.txt > test_file.cpp便不會(huì)執(zhí)行,在鏈接階段就會(huì)因?yàn)槿鄙賢est_file.cpp中的函數(shù)實(shí)現(xiàn)而失敗:

# CMakeLists.txt cmake_minimum_required(VERSION 3.5)project(demo VERSION 0.1 LANGUAGES C CXX)add_custom_command(OUTPUT test_file.cppCOMMAND cat source.txt > test_file.cppDEPENDS source.txt COMMENT "Just copy file contents")add_executable(demo main.cpp)

唯一的區(qū)別就是有沒有在add_executable命令中指明demo對test_file.cpp的依賴。


首發(fā)于個(gè)人微信公眾號【愛碼士1024】。微信掃描上方二維碼或者微信搜索【愛碼士1024】并關(guān)注,及時(shí)獲取更多最新文章!
C++ | Python | 推理引擎 | AI框架源碼,有一起玩耍的么?

0x03. References

[1] https://cmake.org/cmake/help/latest/command/add_custom_command.html

總結(jié)

以上是生活随笔為你收集整理的CMake笔记:add_custom_command不执行的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。