2013-03-02 10 views
67

Mam projektu A, który wywozi statyczną bibliotekę jako cel:CUpewnij: Jak zbudować projektów zewnętrznych i obejmują swoje cele

install(TARGETS alib DESTINATION lib EXPORT project_a-targets) 
install(EXPORT project_a-targets DESTINATION lib/alib) 

Teraz chcę użyć rzutować jako projekt zewnętrznego z Projektu B uwzględnij swoje wbudowane obiekty docelowe:

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) 

Problem polega na tym, że plik ten nie istnieje jeszcze po uruchomieniu CMakeLists of Project B.

Czy istnieje sposób uzależnienia tej opcji od tworzonego projektu zewnętrznego?

Odpowiedz

45

Myślę, że mieszacie tu dwa różne paradygmaty.

Jak zauważyłeś, bardzo elastyczny moduł ExternalProject uruchamia swoje polecenia w czasie kompilacji, więc nie możesz bezpośrednio użyć pliku importu projektu A, ponieważ jest on tworzony dopiero po zainstalowaniu projektu A.

Jeśli chcesz include rzutować w pliku importu, będziesz mieć zainstalować projekt jest ręcznie przed wywołaniem Projekt B za CMakeLists.txt - podobnie jak wszystkie inne uzależnienia trzecich dodało ten sposób, albo poprzez find_file/find_library/find_package.

Jeśli chcesz skorzystać z ExternalProject_Add, trzeba dodać coś takiego do swojej 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)
+1

Dzięki za odpowiedź. To, co sugerujesz, jest podobne do tego, co miałem wcześniej. Mam nadzieję znaleźć sposób na wykorzystanie wyeksportowanych celów, ponieważ wydawał się lepszym interfejsem niż ręczne określanie ścieżek do biblioteki ... – mirkokiefer

+0

@mirkok W pewnym sensie zgadzam się, że jest to przyjemniejszy interfejs. Nie * są * kilka innych opcji. Możesz na przykład po prostu dołączyć źródło projektu A do podkatalogu projektu B i przeciągnąć go przez 'add_subdirectory'. Lub możesz użyć 'ExternalProject_Add' i zrobić sztuczkę, która powoduje dwukrotne uruchomienie CMake; po raz pierwszy budując projekt zewnętrzny, po raz drugi z powodzeniem zbiera plik importu "project_a-targets.cmake". – Fraser

+2

Chciałem uniknąć konieczności uwzględniania źródła zewnętrznych projektów w moim drzewie źródłowym. Byłoby świetnie, gdyby 'ExternalProject_Add' zachował się po prostu jak' add_subdirectory' i odsłonił wszystkie cele. Rozwiązanie, które opisałeś powyżej, prawdopodobnie nadal jest najczystsze. – mirkokiefer

4

Można także wymusić kompilację zależnej w celu wtórnego marki proces

Zobacz my answer na temat pokrewny.

8

This post ma wystarczającą odpowiedź:

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 

Jednak wydaje się, całkiem hacky. Chciałbym zaproponować alternatywne rozwiązanie - użyj podmodułów 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" 

Następnie w MyProject/dependencies/gtest/CMakeList.txt można zrobić coś takiego:

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") 

nie próbowałem tego jeszcze obszernie, ale wydaje się czystsze.

Edycja: W tym podejściu występuje jedna z wad: podkatalog może uruchamiać polecenia install(), których nie chcesz. This post has an approach to disable them, ale był błędny i nie działał dla mnie.

Edycja 2: Jeśli używasz add_subdirectory("googletest" EXCLUDE_FROM_ALL), wydaje się, że polecenia install() w podkatalogu nie są używane domyślnie.