외부 라이브러리에 대한 CMake 링크


126

동일한 CMake 프로젝트 내에서 빌드되지 않은 외부 공유 라이브러리에 실행 파일을 연결하도록 CMake를 얻는 방법은 무엇입니까?

그냥 target_link_libraries(GLBall ${CMAKE_BINARY_DIR}/res/mylib.so)하면 오류가 발생합니다.

make[2]: *** No rule to make target `res/mylib.so', needed by `GLBall'.  Stop.
make[1]: *** [CMakeFiles/GLBall.dir/all] Error 2
make: *** [all] Error 2
(GLBall is the executable)

라이브러리를 바이너리 dir에 복사 한 후 bin/res.

나는 사용해 보았다 find_library(RESULT mylib.so PATHS ${CMAKE_BINARY_DIR}/res)

어느와 함께 실패합니다 RESULT-NOTFOUND.

답변:


101

먼저 라이브러리 검색 경로를 설정하십시오.

LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/res)

그리고 그냥

TARGET_LINK_LIBRARIES(GLBall mylib)

44
link_directories자체 문서에서도를 사용 하지 않는 것이 좋습니다. find_library원래 질문에서 실패한 전화 를 해결 하거나 @Andre의 솔루션을 사용하는 것이 더 나을 것이라고 생각합니다 .
Fraser

4
"가져온"라이브러리 대상은 단순히 전역 검색 경로를 제공하는 대신 특정 라이브러리의 위치를 ​​대상으로하기 때문에 더 강력하다는 것을 알았습니다. Andre의 대답을 참조하십시오.
Mark Lakata

1
find_library하드 코딩하는 대신 항상 이 경로를 사용 하고 사용해야합니다. 내 대답 .
usr1234567

121

arrowdodger의 대답은 정확하고 많은 경우 선호됩니다. 나는 그의 대답에 대안을 추가하고 싶습니다.

링크 디렉토리 대신 "가져온"라이브러리 대상을 추가 할 수 있습니다. 다음과 같은 것 :

# Your-external "mylib", add GLOBAL if the imported library is located in directories above the current.
add_library( mylib SHARED IMPORTED )
# You can define two import-locations: one for debug and one for release.
set_target_properties( mylib PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/res/mylib.so )

그런 다음이 라이브러리가 프로젝트에서 빌드 된 것처럼 연결합니다.

TARGET_LINK_LIBRARIES(GLBall mylib)

이러한 접근 방식은 약간의 유연성을 제공합니다. add_library () 명령 및 가져온 라이브러리와 관련된 많은 대상 속성을 살펴보십시오 .

이것이 "업데이트 된 libs 버전"으로 문제를 해결할 수 있을지 모르겠습니다.


2
그건 아마 것 add_library( mylib SHARED IMPORTED )또는 당신은 얻을 add_library called with IMPORTED argument but no library type오류
마빈

4
@Andre : 난 후 생각 IMPORTED_LOCATION오프닝 브래킷은 잘못
Ela782

5
현재 위의 디렉토리에서 가져온 라이브러리에 액세스하려면 GLOBAL다음 에 추가해야합니다 IMPORTED.add_library(breakpad STATIC IMPORTED GLOBAL)
Roman Kruglov

@Andre IMPORTED_LOCATION은 파일을 포함하는 디렉토리 대신 파일 경로를 요구하는 것 같습니다
SOUser

1
@SOUser : 예, IMPORTED_LOCATION은 디렉터리가 아닌 파일을 가리켜 야합니다. 저자가 불평하지 않을 것이라고 생각합니다.
Tsyvarev

64

나는 당신이 foo 라는 라이브러리에 연결하고 싶다고 가정합니다. 파일 이름은 일반적으로 link foo.dll또는 libfoo.so.

1. 도서관 찾기 도서관
을 찾아야합니다. 라이브러리의 경로를 알고 있더라도 이것은 좋은 생각입니다. 라이브러리가 사라지거나 새 이름이 있으면 CMake에서 오류가 발생합니다. 이를 통해 오류를 조기에 발견하고 문제의 원인을 사용자 (자신이 직접)에게 분명히 알릴 수 있습니다.
라이브러리 foo 를 찾고 FOO_LIB사용중인 경로를 저장 하려면

    find_library(FOO_LIB foo)

CMake는 실제 파일 이름이 어떻게되는지 스스로 알아낼 것입니다. 이 같은 일반적인 장소 확인 /usr/lib, /usr/lib64및의 경로를 PATH.

도서관의 위치를 ​​이미 알고 있습니다. CMAKE_PREFIX_PATHCMake를 호출 할 때에 추가하면 CMake도 전달 된 경로에서 라이브러리를 찾습니다.

힌트 나 경로 접미사를 추가해야하는 경우가 있습니다. 자세한 내용은 설명서를 참조하십시오. https://cmake.org/cmake/help/latest/command/find_library.html

2. 라이브러리 연결 1.에서 전체 라이브러리 이름이 FOO_LIB. 이것을 사용하여 라이브러리를 대상에 연결합니다 GLBall.

  target_link_libraries(GLBall PRIVATE "${FOO_LIB}")

당신은 추가해야 PRIVATE , PUBLIC또는 INTERFACE대상, 참조 후 문서 : https://cmake.org/cmake/help/latest/command/target_link_libraries.html

이러한 가시성 지정자 중 하나를 추가하지 않으면 CMake 버전 및 정책 세트에 따라 PRIVATE또는 처럼 작동합니다 PUBLIC.

3. 포함 추가 (이 단계는 필수가 아닐 수 있음)
헤더 파일도 포함하려면 find_path유사 항목을 사용 find_library하고 헤더 파일을 검색합니다. 그런 다음이와 디렉토리를 포함 추가 target_include_directories비슷합니다 target_link_libraries.

선적 서류 비치: https://cmake.org/cmake/help/latest/command/find_path.htmlhttps://cmake.org/cmake/help/latest/command/target_include_directories.html

외부 소프트웨어에 사용할 수있는 경우 find_libraryfind_path으로 대체 할 수 있습니다 find_package.


4
IMHO 이것이 최고의 답변입니다. 그러나 "project"뒤에 "find_library"를, "add_executable"뒤에 "target_link_libraries"를 호출하지 않았기 때문에 문제가 발생했습니다.
smoothware

1
find_package이 단계를 따르는 것보다 훨씬 간단합니다
activedecay

2
2 단계를 이해하지 못하는 것 같습니다. 공유 라이브러리의 경우 $ {FOO_LIB}는 /full/path/to/libfoo.dylib와 같습니다. 그게 어떻게 유용할까요? target_link_libraries는 "-L / full / path / to -lfoo"를 생성하지 않으므로 find_library는 라이브러리가 이미 알고있는 위치에 있는지 확인하는 것 외에는 유용한 정보를 반환하지 않습니다. 내가 무엇을 놓치고 있습니까?
guymac dec. 06 '182018-12-06

target_link_libraries(mylib "${FOO_LIB}")? 목표는 mylib그의 실제 목표 대신에 GLBall? 별로 말이 안
돼요

5

또 다른 대안은 Appstore로 작업하는 경우 "Entitlements"가 필요하므로 Apple-Framework와 연결해야합니다.

작업에 인 타이틀먼트의 경우 (예 : 게임 센터) 당신은 필요 에 "바이너리를 라이브러리와 연결"-buildstep을 가지고 다음 "GameKit.framework"로 연결합니다. CMake는 "낮은 수준"의 라이브러리를 명령 줄에 "주입"하므로 Xcode는 실제로 그것에 대해 알지 못하므로 Capabilities 화면에서 GameKit을 활성화 하지 않습니다 .

CMake를 사용하고 "Link with Binaries"빌드 단계를 갖는 한 가지 방법은 CMake로 xcodeproj를 생성 한 다음 'sed'를 사용하여 '검색 및 교체'하고 XCode가 좋아하는 방식으로 GameKit을 추가하는 것입니다.

스크립트는 다음과 같습니다 (Xcode 6.3.1의 경우).

s#\/\* Begin PBXBuildFile section \*\/#\/\* Begin PBXBuildFile section \*\/\
    26B12AA11C10544700A9A2BA \/\* GameKit.framework in Frameworks \*\/ = {isa = PBXBuildFile; fileRef = 26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/; };#g

s#\/\* Begin PBXFileReference section \*\/#\/\* Begin PBXFileReference section \*\/\
    26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System\/Library\/Frameworks\/GameKit.framework; sourceTree = SDKROOT; };#g

s#\/\* End PBXFileReference section \*\/#\/\* End PBXFileReference section \*\/\
\
\/\* Begin PBXFrameworksBuildPhase section \*\/\
    26B12A9F1C10543B00A9A2BA \/\* Frameworks \*\/ = {\
        isa = PBXFrameworksBuildPhase;\
        buildActionMask = 2147483647;\
        files = (\
            26B12AA11C10544700A9A2BA \/\* GameKit.framework in Frameworks xxx\*\/,\
        );\
        runOnlyForDeploymentPostprocessing = 0;\
    };\
\/\* End PBXFrameworksBuildPhase section \*\/\
#g

s#\/\* CMake PostBuild Rules \*\/,#\/\* CMake PostBuild Rules \*\/,\
            26B12A9F1C10543B00A9A2BA \/\* Frameworks xxx\*\/,#g
s#\/\* Products \*\/,#\/\* Products \*\/,\
            26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/,#g

이것을 "gamecenter.sed"에 저장하고 다음과 같이 "적용"합니다 (xcodeproj를 변경합니다!).

sed -i.pbxprojbak -f gamecenter.sed myproject.xcodeproj/project.pbxproj

필요에 맞게 스크립트 명령을 변경해야 할 수도 있습니다.

경고 : 프로젝트 형식이 변경 될 수 있으므로 다른 Xcode 버전으로 중단 될 수 있습니다. (하드 코딩 된) 고유 번호는 실제로 고유하지 않을 수 있으며 일반적으로 다른 사람들의 솔루션이 더 좋습니다. 따라서 Appstore +를 지원할 필요가없는 경우 권한 (및 자동화 된 빌드),이 작업을 수행하지 마십시오.

이것은 CMake 버그입니다. http://cmake.org/Bug/view.php?id=14185http://gitlab.kitware.com/cmake/cmake/issues/14185 참조


특히-cmake를 외부 라이브러리와 연결하는 것은 문제가 아닙니다 (위에 몇 가지 해결책이 있습니다). 이를 자동화 된 방식으로 작동시켜 Apple Appstore 권한 함께 작동하도록하는 것은 어려운 일입니다. 이 특정 경우에는 XCode가 그런 방식으로 링크 된 라이브러리를 '보지'않고 권한 만 작동하지 않기 때문에 위의 솔루션이 작동하지 않습니다. Afaik cmake는 xcode가 '앱 스토어와 호환되는 방식'으로 필요로하는 방식으로 라이브러리를 추가 할 수 없습니다.
kalmiya

1
아, 슬프 네요. 완전성을 위해 현재 commnet을 포함하지 않는 새로운 이슈 트래커에 대한 링크 : gitlab.kitware.com/cmake/cmake/issues/14185
usr1234567

문제는 5 개월 전에 해결되었으므로 최신 버전의 CMake에서는 더 이상 존재하지 않습니다. 참조 gitlab.kitware.com/cmake/cmake/issues/14185
usr1234567
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.