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


167

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상대적으로 설정해야 합니까?


그 패턴은 나에게 매우 이상해 보인다. CMake를 사용하는 라이브러리는 이러한 방법으로 '찾기'모듈을 노출하지 않아야합니다. "SomeLib"을 찾는 방법을 어떻게 생각 해냈습니까? 그리고 어떤 라이브러리입니까?
SirDarius

2
비슷한 것이 cmake.org/Wiki/… 에서 이루어집니다 . 그리고 그것은 OGRE입니다.
MarcDefiant

2
"현재 CMake가 배송하지 않기 때문에 프로젝트 내에서 배송해야합니다." 이것이 내가 flvmeta에서 LibYAML을 찾기 위해 한 일입니다 ( github.com/noirotm/flvmeta/tree/master/cmake/modules 참조 ). 모듈 경로는 프로젝트 내에서이 디렉토리를 가리 킵니다.
SirDarius

3
나는 보통 FindXXX 모듈을 내 프로젝트에 복사하고 CMAKE_MODULE_PATH (그 모듈이 CMake에없는 경우)를 설정하면 다른 프로젝트
에서도이

답변:


213

명령 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

구성 모드 (사용)

가져온 대상 find_package(... CONFIG)에 포함 FooConfig.cmake하는 데 사용 합니다 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

가져온 대상은 고도로 구성 가능합니다. 내 답변을 참조하십시오 .

최신 정보


1
당신의 대답은 훌륭합니다. 그러나 github의 예제는 IMO 일 수있는 것보다 더 복잡합니다. 서브 디렉토리 (모듈)가 단일 아티팩트를 내보내는 일반적인 경우, 헤더와 함께 lib를 지정하면 사용자 정의 * Config.cmake를 생성 할 필요가 없습니다. 결과적으로 구성을 크게 줄일 수 있습니다. 나는 비슷한 예를 직접 만들 것이라고 생각합니다.
Dimitris 2018 년

2
@Dimitris 예, 조금 단순화 할 수 있습니다. github 예제를 업데이트 했으므로 이제는 사용하지 않습니다 configure_package_config_file. 그건 그렇고 다른 제안이 있으면 나에게 풀 요청을 보낼 수 있습니다.

1
@rusio 여기 내 예제가있다 . 단일 빌드 (루트 폴더의 모든 모듈) 또는 자율 빌드 (각 모듈을 개별적으로 설치해야 함)를 지원합니다.
Dimitris

1
@Dimitris 좋아, 이제 알겠다. 일반적으로 "최적화"한 파일은 find_dependency 와 같은 추가 항목을로드하는 데 사용 됩니다. 시작하기에 좋은 템플릿이라고 생각하므로 실제로 사용하지 않아도 유지할 것입니다. 버전, dll로 내보내기, 레이아웃 bin/lib(실행 파일을 설치하고 Windows에서 실행)과 같은 일부 기능이 누락되어 나머지 코드가 더 단순 해 보입니다 . 그리고 네임 스페이스는 매우 예쁘게 보이기 때문에 계속 유지할 것입니다 :) 또한 monolithic빌드를 추가 했습니다.

1
귀하의 각 예는 저에게 매우 도움이되었습니다. 둘 다 감사합니다!
zmb

2

수퍼 빌드의 일부로 자신 cmake을 생성하기 위해 실행중인 경우 사용자 패키지 레지스트리SomeLib 사용을 고려하십시오 . 여기에는 하드 코딩 된 경로가 필요하지 않으며 크로스 플랫폼입니다. Windows (mingw64 포함)에서는 레지스트리를 통해 작동합니다. find_packages () 명령 모드 로 설치 접두사 목록을 구성하는 방법을 살펴보면 사용자 패키지 레지스트리가 요소 중 하나라는 것을 알 수 있습니다.CONFIG

간단한 사용법

생성 된 파일 SomeLib의 내보내기 세트에 추가하여 외부 프로젝트 외부에 필요한 대상을 연관 시키십시오 CMakeLists.txt.

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

크리에이트 XXXConfig.cmake에 대한 파일을 SomeLib자신의 ${CMAKE_CURRENT_BUILD_DIR}과를 두 번 호출 추가하여 사용자 패키지 레지스트리에서이 위치를 저장 수출 () 받는 사람 CMakeLists.txt과 관련된를 SomeLib:

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

문제 find_package(SomeLib REQUIRED)의 Section 명령 CMakeLists.txt에 따라 프로젝트의 파일 SomeLib땜질은 "하드 코딩 경로가 아닌 크로스 플랫폼"하지 않고를 CMAKE_MODULE_PATH.

올바른 접근 방식 일 때

이 방법은 빌드 디렉토리의 다운 스트림에서 소프트웨어를 절대 사용하지 않는 상황 (예 : 크로스 컴파일을하거나 컴퓨터에 아무것도 설치하지 않거나 테스트를 실행하기 위해 소프트웨어를 빌드하는 경우)에 가장 적합합니다. "빌드"출력에 .cmake 파일에 대한 링크를 작성하므로 임시 디렉토리 일 수 있습니다.

그러나 실제로 SomeLib워크 플로에 설치하지 않은 경우 전화를 EXPORT(PACKAGE <name>)사용하면 하드 코딩 된 경로를 피할 수 있습니다. 그리고 물론 설치하는 경우 SomeLib플랫폼 CMAKE_MODULE_PATH등을 알고있을 것이므로 @ user2288008의 훌륭한 답변을 통해 설명합니다.


1

모듈 경로 자체를 지정할 필요 는 없습니다 . CMake는 자체 내장 find_package 스크립트 세트와 함께 제공되며 해당 위치는 기본 CMAKE_MODULE_PATH에 있습니다.

CMakeified 된 종속 프로젝트의 일반적인 사용 사례는 CMake의 external_project 명령을 사용한 다음 하위 프로젝트의 Use [Project] .cmake 파일을 포함하는 것입니다. Find [Project] .cmake 스크립트 만 있으면 하위 프로젝트에서 자신의 프로젝트 소스 코드로 복사 한 다음 시스템 수준에서 하위 프로젝트를 찾기 위해 CMAKE_MODULE_PATH를 보강 할 필요가 없습니다.


12
their location is in the default CMAKE_MODULE_PATH기본적으로 CMAKE_MODULE_PATH비어

2018 년에 @ user2288008 님의 댓글을 확인할 수 CMAKE_MODULE_PATH있습니다. Windows에서 비어 있습니다.
Jeroen

프로젝트와 함께 제공되는 모듈에 대한 프로젝트 특정 변수입니다. "기본적으로 비어 있으므로 프로젝트에서 설정합니다." cmake.org/cmake/help/latest/variable/CMAKE_MODULE_PATH.html
Farway

1

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

해당 모듈을 가지고 CMake를 신뢰하지 않는 경우, - 예, 그렇게 - 종류의 : 복사 find_SomeLib.cmake및 종속성 당신에 cmake/디렉토리. 이것이 내가 폴백으로하는 일입니다. 그러나 추악한 솔루션입니다.

FindFoo.cmake모듈은 각각 플랫폼 의존성과 플랫폼 독립성을 잇는 일종의 브리지입니다. 다양한 플랫폼 별 위치에서 플랫폼 독립적 인 이름의 변수 경로를 찾습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.