![](/img/trans.png)
[英]Copying executable using CMake add_custom_command in visual studio
[英]cmake: add_custom_command only invoked first time
對於自定義目標(使用 add_custom_target 創建),我遇到了 add_custom_command 問題。
我的總體想法是將靜態代碼分析工具合並到 cmake 工具鏈中。 我的解決方案基於此處描述的解決方案: https : //github.com/rpavlik/cmake-modules/blob/master/CppcheckTargets.cmake
簡而言之,我要運行靜態代碼分析的每個項目都有以下兩行代碼:
include(cppcheck)
add_cppcheck(${le_project} STYLE POSSIBLE_ERROR FAIL_ON_WARNINGS)
該模塊在文件的頂部有這個:
if (NOT TARGET ANALYZE_CODE)
add_custom_target(ANALYZE_CODE WORKING_DIRECTORY ${LE_LITEN_ROOT})
set_target_properties(ANALYZE_CODE PROPERTIES EXCLUDE_FROM_ALL TRUE)
endif ()
稍后在函數中添加自定義命令:
add_custom_command(TARGET
ANALYZE_CODE
PRE_BUILD
COMMAND
${CPPCHECK_EXECUTABLE}
${CPPCHECK_QUIET_ARG}
${CPPCHECK_TEMPLATE_ARG}
${_cppcheck_args}
${_files}
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT
"${_name}_cppcheck: Running cppcheck on target ${_name}..."
VERBATIM)
我看到的問題是該命令只為首先包含該文件的項目添加。 我不確定為什么以及發生了什么。 我使用 message() 命令驗證了以下內容:
但是當我在visual studio中實際查看目標時,只添加了第一個包含/函數調用命令。
如果只包含文件而不調用函數,則根本不會添加自定義命令。
期望的行為:
我希望一個名為“ANALYZE_CODE”的目標運行通過調用該函數添加的所有命令。
即,如果 3 個項目包括上面的兩行,則目標 ANALYZE_CODE 被創建一次,但 3 個自定義命令被添加到其中,每個項目一個。
事實證明,您在這里有點卡在岩石和堅硬的地方之間。 我認為這個問題歸結為幾個因素。
首先,雖然文檔沒有明確說明,但add_custom_command(TARGET ...)
僅適用於在同一目錄中創建的目標。 所以第一個調用include(cppcheck)
子項目是唯一可以有效地將自定義命令添加到目標ANALYZE_CODE
。
對此的解決方法似乎是將所有對add_cppcheck
調用從其各自的子目錄移動到頂級 CMakeLists 文件。
include(cppcheck)
add_cppcheck(${le_first_project} STYLE POSSIBLE_ERROR FAIL_ON_WARNINGS)
add_cppcheck(${le_second_project} STYLE POSSIBLE_ERROR FAIL_ON_WARNINGS)
...
這不是一個很好的解決方案,因為它們確實屬於它們自己的子目錄。 但更大的問題是源文件的屬性僅在添加它們的 CMakeLists.txt 范圍內持續存在。 這一點都不明顯,但來自set_source_files_properties
的文檔:
源文件屬性僅對添加到同一目錄 (CMakeLists.txt) 中的目標可見。
add_cppcheck
的內部有以下代碼塊:
foreach(_source ${_cppcheck_sources})
get_source_file_property(_cppcheck_lang "${_source}" LANGUAGE)
get_source_file_property(_cppcheck_loc "${_source}" LOCATION)
if("${_cppcheck_lang}" MATCHES "CXX")
list(APPEND _files "${_cppcheck_loc}")
endif()
endforeach()
因此,這是檢查給定目標的每個源文件是否被指定為 C++ 文件,然后再將其添加到要提供給 cppcheck 的文件列表中。 如果從定義目標(即子目錄)的 CMakeLists.txt 中調用此函數,則所有文件都具有適當的屬性並被正確添加。
但是,如果從父 CMakeLists.txt 調用該函數,則文件將丟失其屬性,因此不會添加任何內容,並且 cppcheck 會傳遞一個空列表!
現在進行可能的修復。 擺脫這個坑的方法可能很少——我可以指出幾個。
您可以繼續選擇始終從頂級 CMake 文件調用add_cppcheck
並避免使用源文件的屬性。 所以上面的問題代碼塊可以改為更像:
set(CxxExtensions .cpp .CPP .cc .CC .cxx .CXX)
foreach(_source ${_cppcheck_sources})
get_filename_component(Extension "${_source}" EXT)
list(FIND CxxExtensions "${Extension}" IsCxxFile)
if(IsCxxFile GREATER -1)
list(APPEND _files "${_source}")
endif()
endforeach()
您甚至可以通過在函數的開頭添加如下內容來強制僅從頂級 CMakeLists.txt 調用該函數:
if(NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
message(FATAL_ERROR "This can only be called from the top-level CMakeLists.txt")
endif()
第二個修復(我個人更喜歡)是將add_cppcheck
調用留在子目錄中,並讓函數添加自定義目標而不是命令。 這些目標可以成功地作為頂級目標ANALYZE_CODE
依賴項應用。 例如,將add_custom_command
更改為:
add_custom_target(ANALYZE_${_name}
${CPPCHECK_EXECUTABLE}
${CPPCHECK_QUIET_ARG}
${CPPCHECK_TEMPLATE_ARG}
${_cppcheck_args}
${_files}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "ANALYZE_${_name}: Running cppcheck on target ${_name}..."
VERBATIM)
add_dependencies(ANALYZE_CODE ANALYZE_${_name})
set_target_properties(ANALYZE_${_name} PROPERTIES FOLDER "Code Analysis")
這應該會導致構建ANALYZE_CODE
以觸發構建每個從屬ANALYZE_...
目標。
它的缺點是使用大量額外目標“污染”解決方案,但好處是您可以在add_test
調用中使用這些目標(盡管這可能是一步過頭):
# CMake 2.8.0 and newer
add_test(NAME ${_name}_cppcheck_test
COMMAND ${CMAKE_COMMAND}
--build ${CMAKE_BINARY_DIR}
--target ANALYZE_${_name})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.