У меня есть статическая библиотека, зависящая от gtkmm. Я успешно создаю файл liblibrary.a
, однако когда я пытаюсь связать клиентское приложение с этой библиотекой, я получаю неопределенную ссылку на функции gtkmm. Как я могу связать статическую библиотеку, которая зависит от других библиотек?
Файл cmake библиотеки:
cmake_minimum_required(VERSION 3.28)
project(library)
set(CMAKE_CXX_STANDARD 23)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTKMM REQUIRED gtkmm-3.0)
include_directories(${GTKMM_INCLUDE_DIRS})
link_directories(${GTKMM_LIBRARY_DIRS})
add_library(library STATIC library.cpp library.h)
target_link_libraries(library ${GTKMM_LIBRARIES})
Файл cmake клиентского приложения:
cmake_minimum_required(VERSION 3.28)
project(cairomotion)
set(CMAKE_CXX_STANDARD 23)
include_directories(/home/user/Projects/library)
add_executable(client main.cpp)
target_link_libraries(client /home/user/Projects/library/cmake-build-debug/liblibrary.a)
спасибо за помощь
@Jarod42, я поменял на target_link_libraries(library PUBLIC ${GTKMM_LIBRARIES})
, к сожалению, безрезультатно. Что касается target_link_libraries(client library)
, статическая библиотека не установлена в масштабе всей системы, поэтому мне приходится использовать абсолютный путь.
Извините, я обнаружил, что статическое связывание gtkmm не рекомендуется... поэтому вопрос не стоит ответа. stackoverflow.com/questions/8229094/…
«статическая библиотека не установлена во всей системе». Обычно она есть в вашем CMakelist как include(library)
, и поэтому использование target будет выполнять работу (использование материала INTERFACE CMake, например, использование PUBLIC
для «наследования» некоторой «автоматической» ссылки/ включает/определяет).
Извините, я обнаружил, что статическое связывание gtkmm не рекомендуется... Статическая компоновка – работа с приложением GTKmm? - переработано
Этот CMakeLists.txt работает:
cmake_minimum_required(VERSION 3.28)
project(cairomotion)
set(CMAKE_CXX_STANDARD 23)
include_directories(/home/user/Projects/library)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTKMM REQUIRED gtkmm-3.0)
include_directories(${GTKMM_INCLUDE_DIRS})
link_directories(${GTKMM_LIBRARY_DIRS})
add_executable(client main.cpp)
target_link_libraries(client /home/user/Projects/library/cmake-build-debug/liblibrary.a ${GTKMM_LIBRARIES})
Указывать абсолютный путь к библиотеке в target_link_libraries
неправильно в 100% случаев. Не делай это.
Если вы собираетесь разделить свою библиотеку и клиент на два проекта, вам необходимо экспортировать библиотеку из ее сборки. Вот широко комментируемый пример:
cmake_minimum_required(VERSION 3.28)
## Declare the project and its version.
# A version number is essential for find_package to work
# correctly. Set the major version to zero until you have
# defined a stable API/ABI.
project(library VERSION 0.1.0)
## Find our dependencies.
# We ask PkgConfig to create an imported target because
# one should ALWAYS link to a target rather than to a
# raw library by path. Linking to a target also sets up
# include directories
find_package(PkgConfig REQUIRED)
pkg_check_modules(gtkmm-3.0 REQUIRED IMPORTED_TARGET gtkmm-3.0)
## Create our main library target.
# We also create an alias that will match its exported
# name in case we want to support add_subdirectory or
# FetchContent down the line. The installation rules
# below would need to be guarded by an off-by-default
# option() and components would need to be added.
add_library(library STATIC library.cpp)
add_library(library::library ALIAS library)
## Declare the public headers.
# These headers will be installed along with the binaries.
# Additionally, targets linking to this library will have
# their include paths set appropriately.
target_sources(library PUBLIC FILE_SET HEADERS FILES library.h)
## Set the language level.
# Declaring this as a public build requirement of the
# library will ensure that other targets that link to
# it will also require C++23.
target_compile_features(library PUBLIC cxx_std_23)
## Link our dependencies.
# This is the way to link libraries. With this, we have
# completed the process of defining our library and its
# usage requirements.
target_link_libraries(library PRIVATE PkgConfig::gtkmm-3.0)
## Import the build-in helpers for defining install rules
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
## Create a custom path variable for the location of the
# CMake package files.
set(library_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/library"
CACHE STRING "Path to CMake config files")
## Create the package config file.
configure_package_config_file(
"library-config.cmake.in" "${library_INSTALL_CMAKEDIR}/library-config.cmake"
INSTALL_DESTINATION "${library_INSTALL_CMAKEDIR}")
## Create the package version file.
write_basic_package_version_file(
"${library_INSTALL_CMAKEDIR}/library-config-version.cmake"
COMPATIBILITY SameMajorVersion
)
## Install the package config/version files.
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/${library_INSTALL_CMAKEDIR}/library-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${library_INSTALL_CMAKEDIR}/library-config-version.cmake"
DESTINATION "${library_INSTALL_CMAKEDIR}")
## Install the library
install(TARGETS library
EXPORT library-targets
FILE_SET HEADERS)
## Generate a file that contains the target definition
# for the library.
install(EXPORT library-targets
DESTINATION "${library_INSTALL_CMAKEDIR}"
NAMESPACE library::)
@PACKAGE_INIT@
## We use find_dependency rather than find_package
# inside a package config file.
include(CMakeFindDependencyMacro)
## Look for gtkmm-3.0 in the downstream build
find_dependency(PkgConfig)
pkg_check_modules(gtkmm-3.0 IMPORTED_TARGET gtkmm-3.0)
## Provide a helpful error message if we cannot find it
# It is not appropriate to FATAL_ERROR for this since the
# downstream user should decide what to do if your package
# cannot be found.
if (NOT gtkmm-3.0_FOUND)
set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE
"dependency gtkmm-3.0 could not be found")
set(${CMAKE_FIND_PACKAGE_NAME}_FOUND 0)
return()
endif ()
## Add the generated targets
include("${CMAKE_CURRENT_LIST_DIR}/library-targets.cmake")
## Ensure that no invalid components were requested
check_required_components(${CMAKE_FIND_PACKAGE_NAME})
cmake_minimum_required(VERSION 3.28)
project(cairomotion)
## Find the library
find_package(library REQUIRED)
## Create the client executable
add_executable(client main.cpp)
target_compile_features(client PRIVATE cxx_std_23)
## Link to the library
target_link_libraries(client PRIVATE library::library)
Предполагая, что у вас есть оба каталога проекта в ~/workspace
:
~/workspace$ ls
client library
~/workspace$ export CMAKE_BUILD_TYPE=RelWithDebInfo
~/workspace$ export CMAKE_GENERATOR=Ninja
~/workspace$ export CMAKE_PREFIX_PATH = "$PWD/.local"
~/workspace$ cmake -S library -B library/build
~/workspace$ cmake --build library/build
~/workspace$ cmake --install library/build --prefix "$CMAKE_PREFIX_PATH"
~/workspace$ cmake -S client -B client/build
~/workspace$ cmake --build client/build
Установка CMAKE_PREFIX_PATH
здесь обеспечивает связь между двумя проектами.
Большое спасибо!
target_link_libraries(library PUBLIC ${GTKMM_LIBRARIES})
/target_link_libraries(client library)
?