CMakeLists.txtで任意のファイルを任意のディレクトリにコピーする(タイトル長い)
気に入らないので一部修正しました
テスト用の実行ファイル、例えば a.out なんかは buildディレクトリに作成させることが多い
例えば 何かのファイルを読み込むコードを考えるとテストとしては'何かのファイル'もbuildディレクトリにコピーしてくれると楽になる
これは地味に面倒くさい
$ ./a.out ../testfile/test01.json
これを
$ ./a.out test01.json
にしたい。
そのためには、上記の例では ../testfileにある *.jsonをbuildにコピーさせたい
そういう話なので、CMakeLists.txt用の関数を作った
function(copy_files PJ_NAME S_DIR FILE_EXT TAG_DIR)
file(GLOB TARGET_FILES "${S_DIR}/*.${FILE_EXT}")
if(NOT TARGET_FILES)
return()
endif()
# Generate a unique target name using UUID
string(RANDOM LENGTH 8 ALPHABET "0123456789ABCDEF" RANDOM_SUFFIX)
string(REPLACE "/" "_" CLEAN_S_DIR "${S_DIR}")
string(REPLACE "@" "_" CLEAN_S_DIR "${CLEAN_S_DIR}")
string(REPLACE "/" "_" CLEAN_PJ_NAME "${PJ_NAME}")
string(REPLACE "@" "_" CLEAN_PJ_NAME "${CLEAN_PJ_NAME}")
set(UNIQUE_TARGET_NAME "${CLEAN_PJ_NAME}_${CLEAN_S_DIR}_${FILE_EXT}_${RANDOM_SUFFIX}_copy")
string(REGEX REPLACE "[^a-zA-Z0-9_]" "_" UNIQUE_TARGET_NAME "${UNIQUE_TARGET_NAME}")
# Ensure target length remains manageable
string(SUBSTRING "${UNIQUE_TARGET_NAME}" 0 50 UNIQUE_TARGET_NAME)
set(COPIED_TARGET_FILES "")
foreach(TARGET_FILE ${TARGET_FILES})
get_filename_component(TARGET_FILENAME ${TARGET_FILE} NAME)
set(OUTPUT_FILE "${TAG_DIR}/${TARGET_FILENAME}")
# Add a custom command to copy each file
add_custom_command(
OUTPUT ${OUTPUT_FILE}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${TARGET_FILE} ${OUTPUT_FILE}
DEPENDS ${TARGET_FILE}
COMMENT "Copying updated ${TARGET_FILENAME} to ${TAG_DIR}"
)
list(APPEND COPIED_TARGET_FILES ${OUTPUT_FILE})
endforeach()
if(COPIED_TARGET_FILES)
# Check if the target already exists
if(NOT TARGET ${UNIQUE_TARGET_NAME})
add_custom_target(${UNIQUE_TARGET_NAME} ALL
DEPENDS ${COPIED_TARGET_FILES}
COMMENT "Ensuring all .${FILE_EXT} files are copied to ${TAG_DIR}"
)
# Make the main project depend on this custom target to ensure it runs
add_dependencies(${PJ_NAME} ${UNIQUE_TARGET_NAME})
endif()
else()
message(WARNING "No target files found to copy in ${S_DIR}")
endif()
endfunction()
使い方は簡単で上記のコードをCMakeLists.txtの一番後ろにでも貼り付けて、その後に下のように呼び出すだけ
呼び出しは複数行記述しても問題ない
# Usage example
copy_files(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/json" "json" "${CMAKE_BINARY_DIR}")
テスト用の拡張子を持つファイルを編集した場合には、makeを実行するとちゃんと更新される(一応簡単に試した)
ので、安心
念のために、OpenAIのChatGPT-4oに添削をお願いしたところ
コードは修正がなかったけど英文のコメントのスペルミスを指摘された
ちぇっ