CMake: как связать библиотеку БЕЗ функции автоматического поиска FIND_PACKAGE? - PullRequest
15 голосов
/ 08 августа 2011

Интересно, как найти / связать библиотеку без FIND_PACKAGE.

Предположим, что у нас есть "личная" библиотека с именем testlib:

/perso/testlib/include/testlib1.h
/perso/testlib/include/testlib2.h
/perso/testlib/lib/testlib1.a
/perso/testlib/lib/testlib2.a

Как связать ее с CMake?

1) Какие функции связывают его непосредственно в коде CMakeLists.txt?

2) Как разрешить пользователю выбирать, где находятся файлы?

3) Мне сложно понять, что интерпретируется, а что нет CMake.Например, если вы определяете переменную $ {MYVARIABLE_INCLUDE_DIR} или $ {MYVARIABLE_LIBRARIES}, это «INCLUDE_DIR» или «LIBRARIES» расширение, интерпретируемое CMake, или нет никакой разницы, если я называю эту переменную $ {MYVARIABLE_INCDIR}? *

1013? * *1012* 10134) Как выполнить те же процедуры (включая «личную» библиотеку), если у вас есть библиотека, содержащая десять или более библиотечных файлов в каталоге lib?

5) И наконец, когда вы набираете TARGET_LINK_LIBRARIES(myexecutable gmp)откуда вы знаете, что имя библиотеки "gmp".Почему не "Gmp" или "GMP"?Имя библиотеки для этой функции просто равно .a файлу минус "lib" и ".a"?Например, libgmp.a -> gmp?Если я хочу связать библиотеку с именем libtestlolexample.a, нужно ли вводить TARGET_LINK_LIBRARIES(myexecutable testlolexample)?

Большое спасибо.

Ответы [ 3 ]

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

Вы можете использовать target_link_libraries(myexecutable mylib) для ссылки на библиотеку "mylib".Компилятор будет использовать путь по умолчанию для поиска указанной библиотеки (например, он будет искать libmylib.a в Linux).Компилятор будет смотреть только в link_directories(directory1 directory2 ...), поэтому вы можете попробовать эту команду, чтобы добавить необходимые каталоги в путь поиска.

Когда «mylib» также скомпилирован с CMake, это будет распознано, и все должно работатьавтоматически.

Если вы хотите, чтобы пользователь указал каталог, вы можете использовать кэшированную переменную CMake.set(MYPATH "NOT-DEFINED" CACHE PATH "docstring").

Для более сложных вещей очень желательно написать модуль поиска CMake, который можно использовать с find_package.Я предлагаю вам взглянуть на FindALSA.cmake, который можно использовать в качестве хорошей отправной точки.

Интересная часть в конце:

if(ALSA_FOUND)
  set( ALSA_LIBRARIES ${ALSA_LIBRARY} )
  set( ALSA_INCLUDE_DIRS ${ALSA_INCLUDE_DIR} )
endif()

mark_as_advanced(ALSA_INCLUDE_DIR ALSA_LIBRARY)

ALSA_LIBRARY и ALSA_INCLUDE_DIR переменные настраиваются пользователем и хранятся в кеше, тогда как ALSA_LIBRARIES и ALSA_INCLUDE_DIRS, а также ALSA_FOUND вычисляются и являются теми, которые пользователь модуля поиска должен использовать.

Обычно можно использовать модуль поиска следующим образом:

find_package(ALSA REQUIRED)
include_directories(${ALSA_INCLUDE_DIRS})
target_link_libraries(myexe ${ALSA_LIBRARIES})

Я уверен, что вы можете адаптировать его для своей личной библиотеки.

4 голосов
/ 08 августа 2011

Обычно, когда вы хотите создать ссылку на библиотеку, в которой нет модуля find_package (например, это необычная библиотека или ваша собственная библиотека), вы можете использовать основные команды (команды find_X) для установки переменных с помощью пути, которые вам нужны. Затем вы используете эти переменные как с find_package (include_directories, target_link_libraries).

Если вы собираетесь использовать эту библиотеку из нескольких пакетов, вы можете создать модуль find_package; в основном он использует те же команды с определенными соглашениями.

Любой из них позволяет вам указать пути (в модуле CMake) для поиска, и они позволяют пользователю переопределять пути (переменные отображаются как опции в ccmake / cmake-gui).

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

Если вам просто нужно быстрое и грязное решение, вы можете сделать это, но я бы не советовал:

include_directories(/perso/testlib/include)
add_executable(myexecutable myexecutable.cpp)
target_link_libraries(myexecutable
    /perso/testlib/lib/testlib1.a
    /perso/testlib/lib/testlib2.a)

Что касается вашего вопроса о target_link_libraries (# 5), вы можете сделать это несколькими способами. Если вы хотите, вы можете указать полное имя (например, target_link_libraries(myexe libfoo.a)), но я думаю, что лучше (я полагаю, более переносимым) использовать короткое имя (например, target_link_libraries(myexe foo). Вы также можете включить флаги компоновщика; Я не уверен, где я это прочитал, но я думаю, что он может перевести флаги -L и -l для разных компоновщиков.

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

# First, find and set TESTLIB_LIBRARY_DIR, e.g. with find_path
# ...

# This assumes the libraries are e.g. 'libtestlib1.a' and 'libtestlib2.a'
set(TESTLIB_LIBRARIES
    -L${TESTLIB_LIBRARY_DIR)
    -l testlib1
    -l testlib2)

add_executable(myexecutable myexecutable.cpp)
target_link_libraries(myexecutable ${TESTLIB_LIBRARIES})

Если вы хотите создать свой собственный модуль find_package (как упомянуто trenki, FindALSA.cmake кажется хорошей отправной точкой), вы можете использовать его, добавив каталог в CMAKE_MODULE_PATH; например, если вы поместили свои модули в подкаталог cmake/modules/:

# Look for extra CMake modules in a subdirectory of this project
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/" ${CMAKE_MODULE_PATH})

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

# Change this line
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)

# To this (with no path/extension it will search the CMake modules path):
include(FindPackageHandleStandardArgs)

И чтобы получить использование FIND_PACKAGE_HANDLE_STANDARD_ARGS, посмотрите FindPackageHandleStandardArgs.cmake в каталоге CMake Modules.

0 голосов
/ 08 августа 2011

CMake имеет хорошую документацию .

  1. Статическая связь (если я правильно вас понимаю) архивируется путем передачи ключевого слова STATIC в add_library
  2. Я бы посоветовал не делать этого (я не эксперт по CMake), но похоже, что расходы будут слишком большими.
  3. Разницы нет, ${MYVARIABLE_INCLUDE_DIR} - это просто имя переменнойэто все, что вы хотите.Но я бы посоветовал вам следовать соглашению об именах.
  4. Один библиотека всегда является одним файлом .lib / .a, поэтому проблем быть не должно, просто используйте add_library & target_link_libraries & add_dependencies функция.
  5. Имя библиотеки - это всегда имя, которое вы передаете add_library .Однако Gmp или gMP будут такими же, как у CMake с учетом регистра
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...