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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CMake中执行shell命令之execute_process、add_custom_target和add_custom_command

發布時間:2023/12/8 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CMake中执行shell命令之execute_process、add_custom_target和add_custom_command 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景


以下情況可能需要在CMake中執行shell腳本:

  • cmake未提供的功能而實際構建中又需要時,如獲取Linux發行版本
  • 項目構建時需要執行腳本才能完成,如boost構建過程

有的需要shell腳本的返回值,而有的不需要,這個關系不大。本文主要關注的是在cmake中執行shell腳本的方法。

主要涉及三個命令:execute_process、add_custom_target和add_custom_command。

execute_process


通過execute_process方法可以執行多個子進程。

原型如下:

execute_process(COMMAND <cmd1> [<arguments>][COMMAND <cmd2> [<arguments>]]...[WORKING_DIRECTORY <directory>][TIMEOUT <seconds>][RESULT_VARIABLE <variable>][RESULTS_VARIABLE <variable>][OUTPUT_VARIABLE <variable>][ERROR_VARIABLE <variable>][INPUT_FILE <file>][OUTPUT_FILE <file>][ERROR_FILE <file>][OUTPUT_QUIET][ERROR_QUIET][COMMAND_ECHO <where>][OUTPUT_STRIP_TRAILING_WHITESPACE][ERROR_STRIP_TRAILING_WHITESPACE][ENCODING <name>][ECHO_OUTPUT_VARIABLE][ECHO_ERROR_VARIABLE][COMMAND_ERROR_IS_FATAL <ANY|LAST>])

命令COMMAND會并行執行,每個子進程的標準輸出映射到下一個進程的標準輸入上,所有進程共用standard error管道。

各選項說明如下:

  • COMMAND: 子進程的命令行,直接使用操作系統api執行。可以提供多個command,它們會并行執行。如果需要多個命令順序執行,可以調用execute_process多次
  • WORKING_DIRECTORY:在該目錄下執行COMMAND命令
  • TIMEOUT:超時時間,過了這個時間,所有子進程會被終止,RESULT_VARIABLE會被設置為“timeout”
  • RESULT_VARIABLE:最后一個子進程的返回值(正常是0,異常是其他整數),或者描述發生錯誤的字符串
  • RESULTS_VARIABLE:對應于每個子進程的返回值,使用分號分割的列表
  • OUTPUT_VARIABLE:對應于standard output的內容
  • ERROR_VARIABLE:對應于standard error的內容
  • INPUT_FILE:第一個子進程的standard input
  • OUTPUT_FILE:最后一個子進程的standard output
  • ERROR_FILE:所有子進程的standard error
  • OUTPUT_QUIET/ERROR_QUIET:忽略standard output 和 standard error
  • COMMAND_ECHO:重顯命令到指定的標準設備,如STDERR、STDOUT、NONE。使用CMAKE_EXECUTE_PROCESS_COMMAND_ECHO變量來修改它的行為
  • OUTPUT_STRIP_TRAILING_WHITESPACE/ERROR_STRIP_TRAILING_WHITESPACE:刪除空白字符
  • ENCODING:在windows系統上指定進程輸出時的解碼方式,默認是utf-8,其他平臺會忽略該參數
  • ECHO_OUTPUT_VARIABLE/ECHO_ERROR_VARIABLE:輸出將被復制,它將被發送到配置的變量中,也會在標準輸出或標準錯誤中,3.18版本支持
  • COMMAND_ERROR_IS_FATAL:觸發致命錯誤并終止進程執行,方式取決于參數。ANY表示任意命令執行失敗都觸發,LAST表示最后一個進程執行失敗才觸發,3.19版本支持

示例如下:

cmake_minimum_required(VERSION 3.2)project(cmake_test)execute_process(COMMAND echo "hello world"WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}TIMEOUT 3RESULT_VARIABLE result_varOUTPUT_VARIABLE output_varERROR_VARIABLE error_varOUTPUT_STRIP_TRAILING_WHITESPACEERROR_STRIP_TRAILING_WHITESPACE)message(STATUS "result: ${result_var}") message(STATUS "output: ${output_var}") message(STATUS "error: ${error_var}")

輸出如下:

-- result: 0 -- output: hello world -- error:

如果要執行一個shell腳本,只需要把echo命令替換為如:bash a.sh 即可。

add_custom_target


添加自定義的沒有輸出的目標,它總會被構建。

原型如下:

add_custom_target(Name [ALL] [command1 [args1...]][COMMAND command2 [args2...] ...][DEPENDS depend depend depend ... ][BYPRODUCTS [files...]][WORKING_DIRECTORY dir][COMMENT comment][JOB_POOL job_pool][VERBATIM] [USES_TERMINAL][COMMAND_EXPAND_LISTS][SOURCES src1 [src2...]])

目標沒有輸出文件,總是被認為是過時的,可以使用 add_custom_command() 命令生成依賴的文件供 DEPENDS 參數使用。

常用參數說明如下:

  • Name:目標名稱
  • ALL:說明該目標需要添加到默認目標的構建中,所以命令每次都會被執行。注意Name不能是ALL
  • COMMAND:構建時執行的命令,如果指定了多個COMMAND,它們將按順序執行,但不一定組成有狀態shell或批處理腳本。(要運行完整的腳本,可以使用configure_file命令或GENERATE命令來創建它,然后指定一個command來啟動它。)
  • COMMENT:注釋信息,會在命令執行前打印出來
  • DEPENDS:通常以同一CMakeLists.txt文件中的add_custom_command()命令生成的文件作為依賴,目標構建后依賴會被更為最新
  • SOURCES:生成目標所需要的額外的源文件,它們會被添加到IDE項目文件中
  • WORKING_DIRECTORY:執行命令的目標,如果是相對目錄,則以當前源文件目錄為基準

從以上說明可以看出,可以直接使用add_custom_target執行shell命令,并且使用DEPENDS可以讓各個目標之間產生關聯。

通常和add_custom_command命令配合使用來產生DEPENDS。

比如我們在編譯boost庫時,需要執行shell命令,示例如下:

add_custom_target(build_boost_libsCOMMAND ./bootstrap.sh --prefix=/usr/local/boostCOMMAND ./b2 link=static runtime-link=static threading=multi --with-system --with-thread --with-filesystemWORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/boost/" COMMENT "begin build boost libs...")

這樣,我們自定義了目標build_boost_libs,它是通過兩行命令來構建完成的。

關于add_custom_command,下面介紹。

add_custom_command


為構建系統添加自定義的構建規則。

它有兩種形式的原型,下面分別介紹。

生成文件

簽名如下:

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])

使用命令生成指定的輸出文件。具體參數不再說明,詳情可參考后文資料。

使用示例:

add_custom_command(OUTPUT out.cCOMMAND someTool -i ${CMAKE_CURRENT_SOURCE_DIR}/in.txt-o out.cDEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/in.txtVERBATIM)add_library(myLib out.c)

這樣,在生成myLib庫時依賴out.c,而out.c由add_custom_command生成,每次in.txt的變動都會導致add_custom_command中命令的執行。

add_custom_command指定的DEPENDS可以是某個target(通過add_library/add_executable/add_custom_target創建),或者直接是某個文件。

如果add_custom_command命令不指定DEPENDS的話,那么只要沒有這個OUTPUT的文件,都會生成自己并執行command。

構建事件

為庫、可執行文件等目標添加自定義命令,可以在構建目標前或者構建目標后執行一些命令。

要執行的命令會成為目標的一部分,并且只在目標構建時執行,如果目標已經構建完成,這些命令也不會執行。

原型:

add_custom_command(TARGET <target>PRE_BUILD | PRE_LINK | POST_BUILDCOMMAND command1 [ARGS] [args1...][COMMAND command2 [ARGS] [args2...] ...][BYPRODUCTS [files...]][WORKING_DIRECTORY dir][COMMENT comment][VERBATIM] [USES_TERMINAL][COMMAND_EXPAND_LISTS])

這樣就為指定的target關聯了要執行的命令,target必須在當前目錄里定義。

命令執行的時機:

  • PRE_BUILD:在所有規則執行前執行
  • PRE_LINK:在源文件編譯后且鏈接前執行
  • POST_BUILD:在所有規則執行后執行命令

其他參數不再說明。

示例:

# 在目標構建完成后執行一些操作 add_executable(myExe myExe.c) add_custom_command(TARGET myExe POST_BUILDCOMMAND someHasher -i "$<TARGET_FILE:myExe>"-o "$<TARGET_FILE:myExe>.hash"VERBATIM)

add_custom_target vs add_custom_command


add_custom_target有依賴文件時,經常和add_custom_command的生成文件模式搭配使用。

它們之間的關系比較曖昧,這里說明一下。

當add_custom_target所要生成的target依賴add_custom_command所生成的文件時,這個文件就是一個紐帶。

add_custom_command命令輸出的OUTPUT文件和命令里的command之間的關系是:每當這個文件需要被重新生成時,都會執行這段command。

這個文件會不會被生成,取決于構建的target是否depends這個output文件。

這個文件會不會被重新生成,取決于這個output文件depends的東西變了沒。

上面也有點繞,舉例說明一下:

add_custom_command(OUTPUT config_bootstrapCOMMAND ./bootstrap.sh --prefix=/usr/localWORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/boost/" COMMENT "begin config_bootstrap")add_custom_target(build_boost_libsCOMMAND ./b2 link=static runtime-link=static threading=multi --with-system --with-thread --with-filesystemWORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/boost/" DEPENDS config_bootstrapCOMMENT "begin build_boost_libs")

執行流程為:

  • 開始構建目標build_boost_libs,發現它依賴config_bootstrap,cmake會根據該依賴和緩存決定是否重新構建該目標
  • config_bootstrap是由add_custom_command生成的,它是否需要重新生成,取決于它自己的depends,該例中它沒有depends,則只要沒有config_bootstrap,就重新生成
  • 只要config_bootstrap需要構建,add_custom_command中的命令就會被執行
  • 這個流程與MakeFile決定是否重新編譯目標是一個道理,它會自動識別模塊間的依賴關系,并自己構建需要構建的模塊。

    寫cmake的過程,也是告訴cmake模塊間依賴關系的過程。

    小結


    cmake提供了對執行自定義命令的支持,可以很方便地使用它們執行shell命令。

    但它們使用上有一些區別,比如有的會無條件每次執行,有的則依賴于依賴文件是否被更新。

    具體使用哪種模式,就看需求了。

    參考資料

    execute_process
    add_custom_target
    add_custom_command

    總結

    以上是生活随笔為你收集整理的CMake中执行shell命令之execute_process、add_custom_target和add_custom_command的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。