我們經常會遇到將第三方庫文件復制到項目運行時文件夾,或者將子項目生成的庫文件復制到項目運行時文件夾的情況,本文介紹FILE-COPY、add_custom_command、ADD_CUSTOM_TARGET三種方法及CMake COMMAND提供的命令說明。
一、 FILE-COPY
file(<COPY|INSTALL> <files>... DESTINATION <dir> [FILE_PERMISSIONS <permissions>...] [DIRECTORY_PERMISSIONS <permissions>...] [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS] [FOLLOW_SYMLINK_CHAIN] [FILES_MATCHING] [[PATTERN <pattern> | REGEX <regex>] [EXCLUDE] [PERMISSIONS <permissions>...]] [...])
COPY將文件,目錄和符號鏈接復制到目標文件夾。相對於當前源目錄評估相對輸入路徑,相對於當前構建目錄評估相對目的地。復制會保留輸入文件的時間戳,並優化文件(如果該文件存在於具有相同時間戳的目標文件中)。復制將保留輸入權限,除非給出明確的權限或NO_SOURCE_PERMISSIONS(默認為USE_SOURCE_PERMISSIONS)。
如果指定了FOLLOW_SYMLINK_CHAIN,則COPY將在給定的路徑上遞歸解析符號鏈接,直到找到真實文件為止,然后在目標位置為遇到的每個符號鏈接安裝相應的符號鏈接。對於已安裝的每個符號鏈接,解析都會從目錄中剝離,僅保留文件名,這意味着新符號鏈接指向與符號鏈接相同目錄中的文件。此功能在某些Unix系統上很有用,在這些系統中,庫是作為帶有符號鏈接的版本號安裝的,而較少特定的版本指向的是特定版本。FOLLOW_SYMLINK_CHAIN會將所有這些符號鏈接和庫本身安裝到目標目錄中。例如,如果您具有以下目錄結構:
- /opt/foo/lib/libfoo.so.1.2.3
- /opt/foo/lib/libfoo.so.1.2 -> libfoo.so.1.2.3
- /opt/foo/lib/libfoo.so.1 -> libfoo.so.1.2
- /opt/foo/lib/libfoo.so -> libfoo.so.1
你可以:
file(COPY /opt/foo/lib/libfoo.so DESTINATION lib FOLLOW_SYMLINK_CHAIN)
這會將所有符號鏈接和libfoo.so.1.2.3本身安裝到lib中。
請參閱install(DIRECTORY)命令以獲取權限,FILES_MATCHING,PATTERN,REGEX和EXCLUDE選項的文檔。即使使用選項來選擇文件的子集,復制目錄也會保留其內容的結構。
INSTALL與COPY略有不同:它打印狀態消息(取決於CMAKE_INSTALL_MESSAGE變量),並且默認為NO_SOURCE_PERMISSIONS。 install()命令生成的安裝腳本使用此簽名(以及一些未記錄的內部使用選項)。
二、 ADD_CUSTOM_COMMAND
add_custom_command:
該命令可以為生成的構建系統添加一條自定義的構建規則。這里又包含兩種使用方式,一種是通過自定義命令在構建中生成輸出文件,另外一種是向構建目標添加自定義命令。命令格式分別為:
(1)生成文件
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:
指定命令預期產生的輸出文件。如果輸出文件的名稱是相對路徑,即相對於當前的構建的源目錄路徑。輸出文件可以指定多個output1,output2(可選)等。
COMMAND:
指定要在構建時執行的命令行。如果指定多個COMMAND,它們講按順心執行。ARGS參數是為了向后兼容,為可選參數。args1和args2為參數,多個參數用空格隔開。
MAIN_DEPENDENCY:
可選命令,指定命令的主要輸入源文件。
DEPENDS:
指定命令所依賴的文件。
BYPRODUCTS:
可選命令,指定命令預期產生的文件,但其修改時間可能會比依賴性更新,也可能不會更新。
IMPLICIT_DEPENDS:
可選命令,請求掃描輸入文件的隱式依賴關系。給定的語言指定應使用相應的依賴性掃描器的編程語言。目前只支持C和CXX語言掃描器。必須為IMPLICIT_DEPENDS列表中的每個文件指定語言。從掃描中發現的依賴關系在構建時添加到自定義命令的依賴關系。請注意,IMPLICIT_DEPENDS選項目前僅支持Makefile生成器,並且將被其他生成器忽略。
WORKING_DIRECTORY:
可選命令,使用給定的當前工作目錄執行命令。如果它是相對路徑,它將相對於對應於當前源目錄的構建樹目錄。
COMMENT:
可選命令,在構建時執行命令之前顯示給定消息。
DEPFILE:
可選命令,為Ninja生成器指定一個.d depfile。 .d文件保存通常由自定義命令本身發出的依賴關系。對其他生成器使用DEPFILE是一個錯誤。
COMMAND_EXPAND_LISTS:
將擴展COMMAND參數中的列表,包括使用生成器表達式創建的列表,從而允許COMMAND參數,例如${CC} "-I$<JOIN:$<TARGET_PROPERTY:foo,INCLUDE_DIRECTORIES>,;-I>" foo.cc為適當擴展。
VERBATIM:
對於構建工具,將正確轉義命令的所有自變量,以便調用的命令不變地接收每個自變量。 請注意,在add_custom_command甚至沒有看到參數之前,CMake語言處理器仍使用一種轉義。 建議使用VERBATIM,因為它可以使行為正確。 如果未提供VERBATIM,則該行為是特定於平台的,因為沒有針對工具的特殊字符的保護。
使用實例:
add_executable(MakeTable MakeTable.cxx) add_custom_command ( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h DEPENDS MakeTable COMMENT "This is a test" )
(2)自定義構建事件
add_custom_command(TARGET <target> PRE_BUILD | PRE_LINK | POST_BUILD COMMAND command1 [ARGS] [args1...] [COMMAND command2 [ARGS] [args2...] ...] [BYPRODUCTS [files...]] [WORKING_DIRECTORY dir] [COMMENT comment] [VERBATIM] [USES_TERMINAL])
參數介紹:
TARGET:
定義了與構建指定相關聯的新命令。當已經存在是,相應的command將不再執行。
PRE_BUILD:
在目標中執行任何其他規則之前運行。這僅在Visual Studio 7或更高版本上受支持。對於所有其他生成器PRE_BUILD將被視為PRE_LINK。
PRE_LINK:
在編譯源之后運行,但在鏈接二進制文件或運行靜態庫的庫管理器或存檔器工具之前運行。
POST_BUILD:
在目標中的所有其他規則都已執行后運行。
示例:將子項目生成的庫文件復制到項目運行時文件夾。
#=============Copy Plugins Runtime FILES to Main Project============ #一般將此內容放在lib子項目的CMakelists.txt的最后,該方法采用POST_BUILD,所以需注意要復制的源應該是一個固定字符串,而不能用FILE GLOB的方法,因為在編譯前該源為空,在VS中會出現MSB3073錯誤,提示copy from 為空值。 SET(Plugins_TEST_Debug_DLL_FILE ${CMAKE_CURRENT_BINARY_DIR}/Debug/lib${PROJECT_NAME}.dll ) SET(Plugins_TEST_Release_DLL_FILE ${CMAKE_CURRENT_BINARY_DIR}/Release/lib${PROJECT_NAME}.dll ) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<$<CONFIG:Release>:${Plugins_TEST_Release_DLL_FILE}>" "$<$<CONFIG:Debug>:${Plugins_TEST_Debug_DLL_FILE}>" "${CMAKE_BINARY_DIR}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/Plugins/org_test_plugins/" )
三、 ADD_CUSTOM_TARGET
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...]])
參數介紹:
Name:
指定目標的名稱,單獨成為一個子項目。
ALL:
表明此目標應添加到默認構建目標,以便每次都將運行(該命令名稱不能為ALL)
SOURCES:
指定要包括在自定義目標中的其他源文件。指定的源文件將被添加到IDE項目文件中,以方便編輯,即使它們沒有構建規則。
示例:將第三方庫文件復制到項目運行時文件夾
#=============Copy Source files to Build Runtime Dir=============== #該內容一般放在項目頂層CMakelists.txt的最后, #目的是將項目生成后的執行文件所需的第三方庫復制到執行程序目錄, #並區分Debug和Release版本。 #該方法中的COMMAND_EXPAND_LISTS參數值得關注,可以復制列表內所有文件。 FILE(GLOB Plugin_Runtime_Debug_DLL_FILES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Plugin_Runtime_Dir/Debug/*.* ) FILE(GLOB Plugin_Runtime_Release_DLL_FILES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Plugin_Runtime_Dir/Release/*.* ) FILE(GLOB Plugin_Runtime_Debug_Resources_FILES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Plugin_Runtime_Dir/Debug/Resources/icos/*.* ) FILE(GLOB Plugin_Runtime_Release_Resources_FILES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Plugin_Runtime_Dir/Release/Resources/icos/*.* ) add_custom_target(CopyRuntimeFiles ALL VERBATIM COMMAND_EXPAND_LISTS COMMAND ${CMAKE_COMMAND} -E make_directory "${PROJECT_BINARY_DIR}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<$<CONFIG:Release>:${Plugin_Runtime_Release_DLL_FILES}>" "$<$<CONFIG:Debug>:${Plugin_Runtime_Debug_DLL_FILES}>" "${PROJECT_BINARY_DIR}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/" COMMAND ${CMAKE_COMMAND} -E make_directory "${PROJECT_BINARY_DIR}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/Resources/icos/" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<$<CONFIG:Release>:${Plugin_Runtime_Release_Resources_FILES}>" "$<$<CONFIG:Debug>:${Plugin_Runtime_Debug_Resources_FILES}>" "${PROJECT_BINARY_DIR}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/Resources/icos/" COMMAND ${CMAKE_COMMAND} -E make_directory "${PROJECT_BINARY_DIR}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/Plugins/org_test_plugins/" )
四、 COMMAND
cmake version 3.15.2 Usage: <command> [arguments...] Available commands: capabilities - Report capabilities built into cmake in JSON format chdir dir cmd [args...] - run command in a given directory compare_files [--ignore-eol] file1 file2 - check if file1 is same as file2 copy <file>... destination - copy files to destination (either file or directory) copy_directory <dir>... destination - copy content of <dir>... directories to 'destination' directory copy_if_different <file>... destination - copy files if it has changed echo [<string>...] - displays arguments as text echo_append [<string>...] - displays arguments as text but no new line env [--unset=NAME]... [NAME=VALUE]... COMMAND [ARG]... - run command in a modified environment environment - display the current environment make_directory <dir>... - create parent and <dir> directories md5sum <file>... - create MD5 checksum of files sha1sum <file>... - create SHA1 checksum of files sha224sum <file>... - create SHA224 checksum of files sha256sum <file>... - create SHA256 checksum of files sha384sum <file>... - create SHA384 checksum of files sha512sum <file>... - create SHA512 checksum of files remove [-f] <file>... - remove the file(s), use -f to force it remove_directory <dir>... - remove directories and their contents rename oldname newname - rename a file or directory (on one volume) server - start cmake in server mode sleep <number>... - sleep for given number of seconds tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...] - create or extract a tar or zip archive time command [args...] - run command and display elapsed time touch <file>... - touch a <file>. touch_nocreate <file>... - touch a <file> but do not create it. create_symlink old new - create a symbolic link new -> old Available on Windows only: delete_regv key - delete registry value env_vs8_wince sdkname - displays a batch file which sets the environment for the provided Windows CE SDK installed in VS2005 env_vs9_wince sdkname - displays a batch file which sets the environment for the provided Windows CE SDK installed in VS2008 write_regv key value - write registry value
++++++++++++++++++++++++
參考:
https://cmake.org/cmake/help/latest/genindex.html
https://yemi.me/2017/10/04/cmake-notes/
https://www.cnblogs.com/alphagl/p/6280061.html
https://stackoverflow.com/questions/14368919/cmake-custom-command-copy-multiple-files/54446162#54446162