정적 라이브러리를 대상으로 내보내는 프로젝트 A가 있습니다.
install(TARGETS alib DESTINATION lib EXPORT project_a-targets)
install(EXPORT project_a-targets DESTINATION lib/alib)
이제 프로젝트 A를 프로젝트 B의 외부 프로젝트로 사용하고 빌드 된 대상을 포함하려고합니다.
ExternalProject_Add(project_a
URL ...project_a.tar.gz
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/project_a
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
)
include(${CMAKE_CURRENT_BINARY_DIR}/lib/project_a/project_a-targets.cmake)
문제는 프로젝트 B의 CMakeLists가 실행될 때 포함 파일이 아직 존재하지 않는다는 것입니다.
빌드중인 외부 프로젝트에 따라 include를 만드는 방법이 있습니까?
업데이트 : 나는이것과 내가 만난 다른 일반적인 문제를 기반으로 예제 자습서 의 짧은 CMake를 작성했습니다.
답변
여기서 두 가지 다른 패러다임을 혼합하고 있다고 생각합니다.
앞서 언급했듯이 매우 유연한 ExternalProject
모듈은 빌드시 명령을 실행하므로 프로젝트 A가 설치된 후에 만 생성되므로 프로젝트 A의 가져 오기 파일을 직접 사용할 수 없습니다.
당신이 원하는 경우 include
프로젝트 A의 가져 오기 파일, 당신은 것 이 다른 타사의 의존성이 방법을 추가하거나 통해처럼 – 수동으로 프로젝트 B의 CMakeLists.txt를 호출하기 전에 프로젝트를 설치 find_file
/ find_library
/ find_package
.
을 사용하려면 ExternalProject_Add
CMakeLists.txt에 다음과 같은 내용을 추가해야합니다.
ExternalProject_Add(project_a
URL ...project_a.tar.gz
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/project_a
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
)
include(${CMAKE_CURRENT_BINARY_DIR}/lib/project_a/project_a-targets.cmake)
ExternalProject_Get_Property(project_a install_dir)
include_directories(${install_dir}/include)
add_dependencies(project_b_exe project_a)
target_link_libraries(project_b_exe ${install_dir}/lib/alib.lib)
답변
이 게시물 에는 합리적인 답변이 있습니다.
CMakeLists.txt.in
:
cmake_minimum_required(VERSION 2.8.2)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master
SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
CMakeLists.txt
:
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in
googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
execute_process(COMMAND ${CMAKE_COMMAND} --build .
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
# Prevent GoogleTest from overriding our compiler/linker options
# when building with Visual Studio
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This adds
# the following targets: gtest, gtest_main, gmock
# and gmock_main
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
${CMAKE_BINARY_DIR}/googletest-build)
# The gtest/gmock targets carry header search path
# dependencies automatically when using CMake 2.8.11 or
# later. Otherwise we have to add them here ourselves.
if (CMAKE_VERSION VERSION_LESS 2.8.11)
include_directories("${gtest_SOURCE_DIR}/include"
"${gmock_SOURCE_DIR}/include")
endif()
# Now simply link your own targets against gtest, gmock,
# etc. as appropriate
그러나 그것은 꽤 엉망인 것 같습니다. 대체 솔루션을 제안하고 싶습니다-Git 하위 모듈을 사용하십시오.
cd MyProject/dependencies/gtest
git submodule add https://github.com/google/googletest.git
cd googletest
git checkout release-1.8.0
cd ../../..
git add *
git commit -m "Add googletest"
그런 다음 다음 MyProject/dependencies/gtest/CMakeList.txt
과 같이 할 수 있습니다.
cmake_minimum_required(VERSION 3.3)
if(TARGET gtest) # To avoid diamond dependencies; may not be necessary depending on you project.
return()
endif()
add_subdirectory("googletest")
나는 이것을 광범위하게 시도하지 않았지만 더 깨끗해 보인다.
편집 :이 방법에는 단점이 있습니다. 하위 디렉터리에서 install()
원하지 않는 명령을 실행할 수 있습니다 . 이 게시물에는 비활성화하는 방법이 있지만 버그가 많고 저에게 효과적이지 않았습니다.
편집 2 : 사용 add_subdirectory("googletest" EXCLUDE_FROM_ALL)
하는 경우 install()
하위 디렉토리 의 명령이 기본적으로 사용되지 않는 것 같습니다 .
답변
편집 : CMake는 이제이를 지원합니다. 새로운 답변을 참조하십시오 .
보조 make 프로세스에서 종속 대상을 강제로 빌드 할 수도 있습니다.
관련 주제에 대한 내 대답 을 참조하십시오 .
답변
cmake는 ExternalProject_Add
실제로 사용할 수 있지만 내가 좋아하지 않은 점은 빌드, 연속 폴링 등에서 무언가를 수행한다는 것입니다. 빌드 단계에서 프로젝트를 빌드하는 것을 선호합니다. ExternalProject_Add
불행히도 성공하지 못한 채 여러 번의 시도로 재정의 를 시도했습니다.
그런 다음 git 하위 모듈도 추가하려고 시도했지만 전체 git 저장소를 드래그하지만 특정 경우에는 전체 git 저장소의 하위 집합 만 필요합니다. 내가 확인한 것-실제로 희소 git 체크 아웃을 수행하는 것이 가능하지만 아래에 작성한 별도의 기능이 필요합니다.
#-----------------------------------------------------------------------------
#
# Performs sparse (partial) git checkout
#
# into ${checkoutDir} from ${url} of ${branch}
#
# List of folders and files to pull can be specified after that.
#-----------------------------------------------------------------------------
function (SparseGitCheckout checkoutDir url branch)
if(EXISTS ${checkoutDir})
return()
endif()
message("-------------------------------------------------------------------")
message("sparse git checkout to ${checkoutDir}...")
message("-------------------------------------------------------------------")
file(MAKE_DIRECTORY ${checkoutDir})
set(cmds "git init")
set(cmds ${cmds} "git remote add -f origin --no-tags -t master ${url}")
set(cmds ${cmds} "git config core.sparseCheckout true")
# This command is executed via file WRITE
# echo <file or folder> >> .git/info/sparse-checkout")
set(cmds ${cmds} "git pull --depth=1 origin ${branch}")
# message("In directory: ${checkoutDir}")
foreach( cmd ${cmds})
message("- ${cmd}")
string(REPLACE " " ";" cmdList ${cmd})
#message("Outfile: ${outFile}")
#message("Final command: ${cmdList}")
if(pull IN_LIST cmdList)
string (REPLACE ";" "\n" FILES "${ARGN}")
file(WRITE ${checkoutDir}/.git/info/sparse-checkout ${FILES} )
endif()
execute_process(
COMMAND ${cmdList}
WORKING_DIRECTORY ${checkoutDir}
RESULT_VARIABLE ret
)
if(NOT ret EQUAL "0")
message("error: previous command failed, see explanation above")
file(REMOVE_RECURSE ${checkoutDir})
break()
endif()
endforeach()
endfunction()
SparseGitCheckout(${CMAKE_BINARY_DIR}/catch_197 https://github.com/catchorg/Catch2.git v1.9.7 single_include)
SparseGitCheckout(${CMAKE_BINARY_DIR}/catch_master https://github.com/catchorg/Catch2.git master single_include)
함수 사용 방법을 설명하기 위해 아래에 두 개의 함수 호출을 추가했습니다.
누군가는 마스터 / 트렁크가 손상되었을 수 있으므로 체크 아웃하는 것을 좋아하지 않을 수 있습니다. 그러면 특정 태그를 항상 지정할 수 있습니다.
체크 아웃은 캐시 폴더를 지울 때까지 한 번만 수행됩니다.
답변
비슷한 솔루션을 찾고있었습니다. 여기에 대한 답변과 상단의 튜토리얼은 유익합니다. 여기에 언급 된 게시물 / 블로그를 연구하여 성공적으로 구축했습니다. 나는 완전한 CMakeLists.txt를 게시하고 있습니다. 초보자를위한 기본 템플릿으로 도움이 될 것 같습니다.
"CMakeLists.txt"
cmake_minimum_required(VERSION 3.10.2)
# Target Project
project (ClientProgram)
# Begin: Including Sources and Headers
include_directories(include)
file (GLOB SOURCES "src/*.c")
# End: Including Sources and Headers
# Begin: Generate executables
add_executable (ClientProgram ${SOURCES})
# End: Generate executables
# This Project Depends on External Project(s)
include (ExternalProject)
# Begin: External Third Party Library
set (libTLS ThirdPartyTlsLibrary)
ExternalProject_Add (${libTLS}
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/${libTLS}
# Begin: Download Archive from Web Server
URL http://myproject.com/MyLibrary.tgz
URL_HASH SHA1=<expected_sha1sum_of_above_tgz_file>
DOWNLOAD_NO_PROGRESS ON
# End: Download Archive from Web Server
# Begin: Download Source from GIT Repository
# GIT_REPOSITORY https://github.com/<project>.git
# GIT_TAG <Refer github.com releases -> Tags>
# GIT_SHALLOW ON
# End: Download Source from GIT Repository
# Begin: CMAKE Comamnd Argiments
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/${libTLS}
CMAKE_ARGS -DUSE_SHARED_LIBRARY:BOOL=ON
# End: CMAKE Comamnd Argiments
)
# The above ExternalProject_Add(...) construct wil take care of \
# 1. Downloading sources
# 2. Building Object files
# 3. Install under DCMAKE_INSTALL_PREFIX Directory
# Acquire Installation Directory of
ExternalProject_Get_Property (${libTLS} install_dir)
# Begin: Importing Headers & Library of Third Party built using ExternalProject_Add(...)
# Include PATH that has headers required by Target Project
include_directories (${install_dir}/include)
# Import librarues from External Project required by Target Project
add_library (lmytls SHARED IMPORTED)
set_target_properties (lmytls PROPERTIES IMPORTED_LOCATION ${install_dir}/lib/libmytls.so)
add_library (lmyxdot509 SHARED IMPORTED)
set_target_properties(lmyxdot509 PROPERTIES IMPORTED_LOCATION ${install_dir}/lib/libmyxdot509.so)
# End: Importing Headers & Library of Third Party built using ExternalProject_Add(...)
# End: External Third Party Library
# Begin: Target Project depends on Third Party Component
add_dependencies(ClientProgram ${libTLS})
# End: Target Project depends on Third Party Component
# Refer libraries added above used by Target Project
target_link_libraries (ClientProgram lmytls lmyxdot509)