외부 라이브러리에 대한 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.html 및 https://cmake.org/cmake/help/latest/command/target_include_directories.html

외부 소프트웨어에 사용할 수있는 경우 find_library및 find_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=14185 및 http://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.