CMake의 FetchContent는 빌드 과정까지 처리해 주기에 git-submodule 보다 편리한 방식인 것 같다. 다만, version 3.22.1 기준으로 여러 프로젝트 들이 동일한 target이름을 중복해서 선언하는 경우에는 이를 잘 처리 하지 못하고 위와 같은 에러를 뱉고 종료되는 문제가 있다.
-- Found systemd via pkg-config. CMake Error at build/_deps/grpc-src/CMakeLists.txt:667 (add_custom_target): add_custom_target cannot create target "tools" because another target with the same name already exists. The existing target is a custom target created in source directory "<absolute_path_to_the_build_dir>/_deps/vsomeip-src". See documentation for policy CMP0002 for more details.
위의 오류는 COVESA의 vsomeip project와 gRPC를 FetchContent로 구성하는 중에 발생한 것인데, 두 프로젝트 모두 “tools”라는 custom target을 선언하기 때문에 중복으로 오류가 발생한 것이다.
아쉽게도 현재로써는 깔끔하게 해결하는 방법은 없는 것 같고, 두 프로젝트 중 하나의 custom target 이름을 변경해서 중복되지 않도록 해 주는 패치를 작성해서 FetchContent의 PATCH_COMMAND에 인자로 넣어주는 방법으로 회피가 가능하다.
먼저 vsomeip project의 custom target인 tools를 vsomeip_tools로 변경하는 패치를 다음과 같이 작성하고 fix_custom_target.patch로 저장한다.
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3501e02..0467426 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -654,7 +654,7 @@ add_subdirectory( examples/routingmanagerd ) endif() # build tools -add_custom_target( tools ) +add_custom_target( vsomeip_tools ) add_subdirectory( tools ) # build examples -- 2.34.1
다음으로 FetchConetnet에 PATCH_COMMAND argument를 명시한다.
# VSOME/IP set( fix_custom_target git apply ${CMAKE_CURRENT_SOURCE_DIR}/fix_custom_target.patch ) FetchContent_Declare( vsomeip GIT_REPOSITORY https://github.com/COVESA/vsomeip.git GIT_TAG <GIT_TAG> PATCH_COMMAND ${fix_custom_target} ) FetchContent_MakeAvailable(vsomeip gRPC)
이제 cmake를 실행하면 patch가 적용되어 중복되는 target 이름 문제를 해결할 수 있다.
하지만 이 해결책은 아직 깔끔하진 않은데 그 이유는 처음 cmake를 실행하면 patch가 적용되면서 잘 되지만 두번째로 cmake를 실행 할 때는 이미 적용된 patch 때문에 git apply 명령어가 실패 하기 때문에 매번 patch가 적용된 directory(_deps/vsomeip-src)로 이동해서 git checkout -f를 실행해 주어야 하기 때문이다.
최종버전
git apply의 –reverse –check 옵션을 사용하면 패치가 적용되어 있는지 여부를 검사할 수 있으니 이 것을 이용해서 다음과 같은 간단한 shell script를 만들고 apply_patch_if_not.sh로 저장한다.
#!/usr/bin/env sh # apply_patch_if_not.sh # Apply given patch if not already applied. # # - Sep 2024, litcoder if [ -z $1 ]; then echo "Usage: $0 <patch file path>" exit 1 fi # Check if the patch was already applied. git apply --reverse --check $1 if [ $? -eq 0 ]; then echo "The patch already applied, skip." exit 0 else # Apply the patch git apply $1 fi
이제 앞에서 작성한 FetchContent_Declare가 이 script를 부르도록 변경한다.
# VSOME/IP set( fix_custom_target apply_patch_if_not.sh ${CMAKE_CURRENT_SOURCE_DIR}/fix_custom_target.patch ) FetchContent_Declare( vsomeip GIT_REPOSITORY https://github.com/COVESA/vsomeip.git GIT_TAG <GIT_TAG> PATCH_COMMAND ${fix_custom_target} ) FetchContent_MakeAvailable(vsomeip gRPC)