Programming

어쨌든 CMAKE_MODULE_PATH를 지정 해야하는 경우 find_package ()는 어떻게 사용됩니까?

procodes 2020. 6. 22. 21:28
반응형

어쨌든 CMAKE_MODULE_PATH를 지정 해야하는 경우 find_package ()는 어떻게 사용됩니까?


CMake를 사용하여 크로스 플랫폼 빌드 시스템을 사용하려고합니다. 이제 소프트웨어에는 몇 가지 종속성이 있습니다. 직접 컴파일하여 시스템에 설치했습니다.

설치된 예제 파일들 :

-- Installing: /usr/local/share/SomeLib/SomeDir/somefile
-- Installing: /usr/local/share/SomeLib/SomeDir/someotherfile
-- Installing: /usr/local/lib/SomeLib/somesharedlibrary
-- Installing: /usr/local/lib/SomeLib/cmake/FindSomeLib.cmake
-- Installing: /usr/local/lib/SomeLib/cmake/HelperFile.cmake

이제 CMake는 파일 find_package()을 열고 Find*.cmake시스템의 라이브러리를 검색하고 SomeLib_FOUND등의 변수를 정의합니다 .

내 CMakeLists.txt에는 다음과 같은 내용이 포함되어 있습니다.

set(CMAKE_MODULE_PATH "/usr/local/lib/SomeLib/cmake/;${CMAKE_MODULE_PATH}")
find_package(SomeLib REQUIRED)

애프터 CMake 검색 첫 번째 명령을 정의 Find*.cmake하고 내가의 디렉토리에 추가 SomeLib어디에 FindSomeLib.cmake찾을 수 있습니다, 그래서 find_package()예상대로 작동합니다.

그러나 이것이 find_package()존재 하는 이유 중 하나는 비 플랫폼 플랫폼 하드 코딩 된 경로에서 벗어나기 때문에 이상합니다.

이것은 보통 어떻게 이루어 집니까? cmake/디렉토리를 SomeLib프로젝트에 복사 하고 CMAKE_MODULE_PATH상대적으로 설정해야 합니까?


명령 find_package에는 Module모드와 Config모드의 두 가지 모드가 있습니다. Module실제로 Config모드 가 필요할 때 모드 를 사용하려고 합니다.

모듈 모드

Find<package>.cmake프로젝트 내에있는 파일 . 이 같은:

CMakeLists.txt
cmake/FindFoo.cmake
cmake/FindBoo.cmake

CMakeLists.txt 함유량:

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
find_package(Foo REQUIRED) # FOO_INCLUDE_DIR, FOO_LIBRARIES
find_package(Boo REQUIRED) # BOO_INCLUDE_DIR, BOO_LIBRARIES

include_directories("${FOO_INCLUDE_DIR}")
include_directories("${BOO_INCLUDE_DIR}")
add_executable(Bar Bar.hpp Bar.cpp)
target_link_libraries(Bar ${FOO_LIBRARIES} ${BOO_LIBRARIES})

참고 CMAKE_MODULE_PATH높은 우선 순위가 있고 표준 다시 작성해야 할 때 유용 할 수있다 Find<package>.cmake파일.

구성 모드 (설치)

<package>Config.cmake파일은 외부에 있으며 install다른 프로젝트의 명령에 의해 생성됩니다 ( Foo예 :).

foo 도서관:

> cat CMakeLists.txt 
cmake_minimum_required(VERSION 2.8)
project(Foo)

add_library(foo Foo.hpp Foo.cpp)
install(FILES Foo.hpp DESTINATION include)
install(TARGETS foo DESTINATION lib)
install(FILES FooConfig.cmake DESTINATION lib/cmake/Foo)

구성 파일의 단순화 된 버전 :

> cat FooConfig.cmake 
add_library(foo STATIC IMPORTED)
find_library(FOO_LIBRARY_PATH foo HINTS "${CMAKE_CURRENT_LIST_DIR}/../../")
set_target_properties(foo PROPERTIES IMPORTED_LOCATION "${FOO_LIBRARY_PATH}")

기본적으로 프로젝트는 CMAKE_INSTALL_PREFIX디렉토리에 설치됩니다 .

> cmake -H. -B_builds
> cmake --build _builds --target install
-- Install configuration: ""
-- Installing: /usr/local/include/Foo.hpp
-- Installing: /usr/local/lib/libfoo.a
-- Installing: /usr/local/lib/cmake/Foo/FooConfig.cmake

구성 모드 (사용)

Use find_package(... CONFIG) to include FooConfig.cmake with imported target foo:

> cat CMakeLists.txt 
cmake_minimum_required(VERSION 2.8)
project(Boo)

# import library target `foo`
find_package(Foo CONFIG REQUIRED)

add_executable(boo Boo.cpp Boo.hpp)
target_link_libraries(boo foo)
> cmake -H. -B_builds -DCMAKE_VERBOSE_MAKEFILE=ON
> cmake --build _builds
Linking CXX executable Boo
/usr/bin/c++ ... -o Boo /usr/local/lib/libfoo.a

Note that imported target is highly configurable. See my answer.

Update


If you are running cmake to generate SomeLib yourself (say as part of a superbuild), consider using the User Package Registry. This requires no hard-coded paths and is cross-platform. On Windows (including mingw64) it works via the registry. If you examine how the list of installation prefixes is constructed by the CONFIG mode of the find_packages() command, you'll see that the User Package Registry is one of elements.

Brief how-to

Associate the targets of SomeLib that you need outside of that external project by adding them to an export set in the CMakeLists.txt files where they are created:

add_library(thingInSomeLib ...)
install(TARGETS thingInSomeLib Export SomeLib-export DESTINATION lib)

Create a XXXConfig.cmake file for SomeLib in its ${CMAKE_CURRENT_BUILD_DIR} and store this location in the User Package Registry by adding two calls to export() to the CMakeLists.txt associated with SomeLib:

export(EXPORT SomeLib-export NAMESPACE SomeLib:: FILE SomeLibConfig.cmake) # Create SomeLibConfig.cmake
export(PACKAGE SomeLib)                                                    # Store location of SomeLibConfig.cmake

Issue your find_package(SomeLib REQUIRED) commmand in the CMakeLists.txt file of the project that depends on SomeLib without the "non-cross-platform hard coded paths" tinkering with the CMAKE_MODULE_PATH.

When it might be the right approach

This approach is probably best suited for situations where you'll never use your software downstream of the build directory (e.g., you're cross-compiling and never install anything on your machine, or you're building the software just to run tests in the build directory), since it creates a link to a .cmake file in your "build" output, which may be temporary.

But if you're never actually installing SomeLib in your workflow, calling EXPORT(PACKAGE <name>) allows you to avoid the hard-coded path. And, of course, if you are installing SomeLib, you probably know your platform, CMAKE_MODULE_PATH, etc, so @user2288008's excellent answer will have you covered.


You don't need to specify the module path per se. CMake ships with its own set of built-in find_package scripts, and their location is in the default CMAKE_MODULE_PATH.

The more normal use case for dependent projects that have been CMakeified would be to use CMake's external_project command and then include the Use[Project].cmake file from the subproject. If you just need the Find[Project].cmake script, copy it out of the subproject and into your own project's source code, and then you won't need to augment the CMAKE_MODULE_PATH in order to find the subproject at the system level.


How is this usually done? Should I copy the cmake/ directory of SomeLib into my project and set the CMAKE_MODULE_PATH relatively?

If you don't trust CMake to have that module, then - yes, do that - sort of: Copy the find_SomeLib.cmake and its dependencies into your cmake/ directory. That's what I do as a fallback. It's an ugly solution though.

Note that the FindFoo.cmake modules are each a sort of a bridge between platform-dependence and platform-independence - they look in various platform-specific places to obtain paths in variables whose names is platform-independent.

참고URL : https://stackoverflow.com/questions/20746936/what-use-is-find-package-if-you-need-to-specify-cmake-module-path-anyway

반응형