CMake: упорядочение каталогов включения (Как смешать системные и пользовательские пути включения?) - PullRequest
8 голосов
/ 13 октября 2011

У меня есть проект CMake, который включает в себя ссылки на две библиотеки, скажем, A и B (на самом деле их больше двух, и одна из них является улучшением, но здесь это не имеет значения).Оба находятся с помощью FindSomething.cmake сценариев, которые (правильно) заполняют стандартные переменные CMake, такие как включающие каталоги, добавляются через

INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${B_INCLUDE_DIRS})

, а связывание позже выполняется через

TARGET_LINK_LIBRARIES(mytarget ${A_LIBRARIES} ${B_LIBRARIES})

Теперьпроблема в том, что обе библиотеки могут находиться либо в пользовательском расположении, либо в системных каталогах (я, кстати, на linux, CMake 2.8.2) - или в обеих.Допустим, A только в $HOME/usr/include и $HOME/usr/lib, в то время как B (в моем случае повышение) находится как в системных путях (/usr/include и /usr/lib), так и в пользовательских путях - в разных версиях,Сценарии поиска могут быть созданы для поиска либо системы, либо пользовательской библиотеки B, это работает.

Проблема начинается, когда я хочу установить связь с B из системных путей. ${B_INCLUDE_DIRS}и ${B_LIBRARIES} правильно указывают на общесистемные расположения заголовков и библиотек.Но все еще есть ${A_INCLUDE_DIRS}, который указывает на несистемный каталог включения, и, в конечном счете, также заголовки для библиотеки B берутся из этого местоположения, в то время как для связывания B используется версия из системных путей (через * 1025).*) что приводит к конфликтам, т. е. связывает ошибки.

Изменение порядка операторов INCLUDE_DIRECTORIES, похоже, ничего не меняет.Я проверил происхождение символов, которые вызывают ошибки связывания через nm --line-numbers в объектных файлах.

Что я могу сделать?Есть ли хитрость, чтобы

  • принудительно упорядочивал каталоги включения (даже если это означало бы отдавать приоритет системному пути, хотя там также указывается местоположение на основе пользователя)?
  • указывает CMake использовать ${A_INCLUDE_DIRS} для всех заголовков от A и ${B_INCLUDE_DIRS} для всех заголовков от B?

Ответы [ 3 ]

3 голосов
/ 14 октября 2011

При использовании сторонних библиотек, я всегда делал бы это

Заголовочные файлы библиотеки A + B:

third_party / include / libA_name / <- помещать туда заголовочные файлы </p>

third_party / include / libB_name / <- поместить туда файлы заголовков </p>

В исходных файлах вы всегда будете использовать его следующим образом

#include "libA_name/file.h" <-- no ambiguity possible

#include "libB_name/file.h" <-- no ambiguity possible

Тогда вы все равно можете использовать -I "third_party / include "как папка включения, и в исходных файлах не будет никакой двусмысленности при упорядочении.

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

3 голосов
/ 14 декабря 2015

Вот что CMake говорит о include_directories():

include_directories ([ПОСЛЕ | ДО] [СИСТЕМА] dir1 [dir2 ...])

Вы можете указать, что вы хотите, чтобы каталоги поиска выполнялись до или после того, как система включает каталоги в тот момент, когда вы говорите об этих каталогах.

Вы также можете указывать конкретную цель:

target_include_directories (target [SYSTEM] [BEFORE] [items1 ...] [[items2 ...] ...])

2 голосов
/ 14 октября 2011

Если A и B - это разные библиотеки, содержащие разные заголовочные файлы и пути, не должно возникнуть никаких проблем с тем, что вы делаете сейчас.

С другой стороны, если A и B являются похожими библиотеками, содержащими заголовочные файлы с одинаковыми именами в одном месте, это проблематично. В этом случае важен порядок вызова include_directory(). Я провел небольшой тест, где у меня было три копии файла заголовка. Первая копия находится в моем системном пути (скажем, /usr/include). Другие копии находятся в двух определенных пользователем местах (скажем, /tmp/include1 и /tmp/include2). Файл в /tmp/include1 будет найден и использован первым, если я поставлю вызов include_directory() в следующем порядке:

include_directory("/tmp/include1")
include_directory("/tmp/include2")

Файл в /tmp/include2 будет найден и использован первым, если я поставлю вызов include_directory() в следующем порядке:

include_directory("/tmp/include2")
include_directory("/tmp/include1")

Если я не ставлю оператор include_directory(), тогда заголовок в системном пути будет найден и использован.

Возможно, вы захотите еще раз проверить, как написаны ваши FindSomething.cmake. Порядок поиска команд find_*() CMake можно найти в документации CMake ,

Насколько я помню, теперь есть способ указать CMake использовать ${A_INCLUDE_DIRS} для всех заголовков из A и ${B_INCLUDE_DIRS} для всех заголовков из B, если файл заголовка находится в обоих местах. , Все зависит от того, в каком порядке будет сделан звонок include_directory(). Если FindSomething.cmake написаны правильно, если CMAKE_MODULE_PATH (это место, где CMake будет искать файлы Find*.cmake), установлено правильно и все пути хороши, тогда вам следует идти. Если нет, мне потребуется дополнительная информация о вашей текущей настройке CMake / библиотеки.

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