Как вы экспортируете системную библиотеку, используя cmake? - PullRequest
7 голосов
/ 13 августа 2011

Как я могу экспортировать библиотеки, от которых зависит библиотека cmake, чтобы исполняемый файл, зависящий от этой библиотеки, не должен вручную зависеть от зависимостей этой библиотеки?

Немного, так вот пример:

пустышка (приложение) ----> зависит от либы

liba ----> зависит от libpng

Компиляция пустышки выдает ошибки:

-- Found LIBPNG
-- Found LIBA
-- Configuring done
-- Generating done
-- Build files have been written to: /home/doug/projects/dummy/build
Linking C executable dummy
../deps/liba/build/liba.a(a.c.o): In function `a_dummy':
/home/doug/projects/dummy/deps/liba/src/a.c:6: undefined reference to `png_sig_cmp'
collect2: ld returned 1 exit status
make[2]: *** [dummy] Error 1
make[1]: *** [CMakeFiles/dummy.dir/all] Error 2
make: *** [all] Error 2

Я могу исправить это, добавив это в CMakeLists.txt для пустышки:

TARGET_LINK_LIBRARIES (pummy png)

Однако, dummy не знает, как liba реализует свои API. В какой-то момент это может измениться на libjpg или что-то еще, что сломает пустое приложение.

После получения справки из списка рассылки cmake меня направили на этот пример для экспорта: http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file

Однако, следуя этому подходу, я застреваю в этой строке:

export (TARGETS $ {LIBPNG_LIBRARY} FILE "$ {PROJECT_BINARY_DIR} /ALibraryDepends.cmake")

Очевидно, я что-то здесь упускаю; эта команда экспорта выглядит так, как будто она предназначена для экспорта подпроектов на высокий уровень; то есть. вложенные проекты внутри liba.

Однако здесь проблема не в этом.

При настройке liba (или любой библиотеки cmake) я всегда буду генерировать список зависимостей, которые не являются частью этого проекта.

Как я могу экспортировать их, чтобы они отображались как часть LIBA_LIBRARY, когда я использую find_package () для разрешения liba?

Использование статических библиотек не является опцией (статическая библиотека для чего-то, что ссылается на opengl? No.)

Ответы [ 3 ]

7 голосов
/ 13 августа 2011

Учитывая, что ваш комментарий к ответу arrowdodger о страхе установки чего-либо может испортить вашу систему, я решил дать концептуальный комментарий в форме ответа из-за его длины.

Цепной проект cmake работает через find_package,который ищет файлы * Config.cmake и * -config.cmake.

CMakeLists.txt проекта A:

#CMakeLists.txt
project(A)
install(FILES 
  ${CMAKE_CURRENT_SOURCE_DIR}/AConfig.cmake share/A/cmake
)

#AConfig.cmake
message("Yepp, you've found me.")

$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/test-install ..
$ make install

CMakeLists.txt проекта B:

project(B)
find_package(A)

Тогда

$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/test-install ..
$ make install

приводит к

...
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
Yepp, you've found me.

B найденному A, потому что он установил AConfig.cmake в место, где cmake найдет его 'share / A / cmake' И получилто же значение для CMAKE_INSTALL_PREFIX.

Теперь это так.Давайте подумаем о том, что вы можете сделать в AConfig.cmake: AFAIK все, что вы хотите.Но наиболее распространенная задача - получить информацию о целях A с помощью include (), выполнить некоторые дополнительные вызовы find_package для сторонних пакетов (HINT HINT) и создать переменные

A_LIBRARIES
A_INCLUDE_DIRS

Что вы хотите включитьэто файл, который был создан

install(EXPORT A-targets
   DESTINATION share/A/cmake
)

в CMakeLists.txt A, где A-target относится к глобальной переменной cmake, которая накапливала всю информацию о цели при использовании в

install(TARGETS ...
  EXPORT A-targets
  ...
)

statments,При make install создается файл

/tmp/test-install/share/A/cmake/A-targets.cmake

, который затем располагается вместе с AConfig.cmake в том же каталоге.Пожалуйста, еще раз посмотрите на вики-страницу о том, как использовать этот файл в AConfig.cmake.

Относительно команды export (): Это удобно, если ваши проекты получили ОГРОМНОЕ, и это занимает значительное времяустановить их.Чтобы ускорить процесс, вы хотите напрямую использовать то, что находится в директории build /.Это оптимизация и также объяснено в вики.Это все еще работает через find_package (), см.

Но я настоятельно рекомендую вам сейчас пойти по обычному маршруту make install.

2 голосов
/ 15 августа 2011

Я нашел свое решение этой проблемы, используя принятое выше решение, которое оставляю здесь для других:

В liba / CMakeLists.txt:

# Self
set(A_INCLUDE_DIRS ${A_INCLUDE_DIRS} "${PROJECT_SOURCE_DIR}/include")
set(A_LIBRARIES ${A_LIBRARIES} "${PROJECT_BINARY_DIR}/liba.a")

# Libpng
FIND_PACKAGE(libpng REQUIRED)
set(A_INCLUDE_DIRS ${A_INCLUDE_DIRS} ${LIBPNG_INCLUDE_DIRS})
set(A_LIBRARIES ${A_LIBRARIES} ${LIBPNG_LIBRARIES})

ADD_LIBRARY(a ${SOURCES})

# Includes
INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})

# Allow other projects to use this
configure_file(AConfig.cmake.in "${PROJECT_BINARY_DIR}/AConfig.cmake")

В liba / AConfig.cmake:

set(A_LIBRARIES @A_LIBRARIES@)
set(A_INCLUDE_DIRS @A_INCLUDE_DIRS@)

In dummy / CMakeLists.txt:

FIND_PACKAGE(A REQUIRED)
INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(dummy ${A_LIBRARIES})

Это приводит к AConfig.cmake, который читает:

set(A_LIBRARIES /home/doug/projects/dummy/deps/liba/build/liba.a;/usr/lib/libpng.so)
set(A_INCLUDE_DIRS /home/doug/projects/dummy/deps/liba/include;/usr/include)

И многословная компиляция, которая гласит:

/usr/bin/gcc  -std=c99 -g   CMakeFiles/dummy.dir/src/main.c.o  -o dummy -rdynamic ../deps/liba/build/liba.a -lpng 

Именно это я и искал.

1 голос
/ 13 августа 2011

Если liba не предоставляет никаких средств для определения своих зависимостей, вы ничего не можете сделать.Если liba - это библиотека, разработанная вами, и вы используете CMake для ее сборки, то вам следует установить файл libaConfig.cmake с самой liba, которая будет содержать необходимые определения.Затем вы включаете libaConfig в dummy CMakeLists.txt для получения информации о том, как была построена liba.

Вы можете посмотреть, как это делается в проекте LLVM, соответствующие файлы имеют расширение cmake.in http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/

* 1005.* В конце концов, в фиктивном проекте вы должны использовать

target_link_libraries( ${LIBA_LIBRARIES} )

include_directories( ${LIBA_INCLUDE_DIR} )

link_directories( ${LIBA_LIBRARY_DIR} )

Если используется только эта библиотекапо пустякам, вы можете собрать его из одного проекта CMake.Это более удобно, так как вам не нужно устанавливать liba каждый раз, когда вы перекомпилируете ее, и она будет автоматически перестраиваться и снова связываться с пустышкой при каждом запуске make.Если вам понравился этот подход, единственное, что вам следует сделать - определить в liba переменные CMakeLists.txt, которые вам нужны, с параметром PARENT_SCOPE (см. Руководство к команде set ()).

Наконец, вы можете использовать разделяемые библиотеки,.так что нет такой проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...