LINUX.ORG.RU

Как заставить CMake добавлять каталоги инклудов в проект статической библиотеки от другой ст. библиотеки

 


0

1

У меня две статические библиотеки. Первая:

project(library1)

add_library(library1 STATIC)

Вторая:

project(library2)

add_library(library2 STATIC)
target_link_library(library2 PUBLIC library1)

Если я линкую (target_link_library) первую библиотеку к исполняемому файлу, то к нему автоматически добавляется путь к файлу проекта библиотеки в качестве каталога с инклуд директори. Однако, если я линкую первую библиотеку ко второй библиотеке, то путь к первой не входит в состав инклуд директори второй библиотеки. Для меня впринципе не понятно почему. Подскажите, как второй библиотеке получить каталог первой в качестве инклуд директори, и почему в вышеописанных примерах симэйк листов это не происходит, как в случае линковки к исполняемому файлу?

★★★

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

Какая версия CMake? Как добавляешь инклюды к library1?

Скорее всего, нужно делать

target_include_directories(library1 PRIVATE ...)

обрати внимание на PRIVATE.

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

target_include_directories(library1 PRIVATE ...)
обрати внимание на PRIVATE.

Точно PRIVATE? Может INTERFACE?

CMake 3.21.1. Те инклюды в library1 (если речь идёт о каталогах), которые добавляю при помощи target_include_directories(), наследуются в целевой таргет нормально, но я не делаю target_include_directories() для каталога с library1, так как он, как мне кажется, должен подключаться автоматически, что и происходит в случае если линкующим таргетом является исполняемый модуль, но не в случае, если это статическая либа.

normann ★★★
() автор топика

Всё работает как ты предполагаешь, у тебя ошибка где-то в том месте что ты не показал. Например, target_include_directories у library1 PRIVATE вместо PUBLIC или INTERFACE.

/tmp% cat CMakeLists.txt  
cmake_minimum_required(VERSION 3.23)
project(foo)

add_library(library1 STATIC lib1/empty.c)
target_include_directories(library1 PUBLIC lib1)

add_library(library2 STATIC lib2/empty.c)
target_link_libraries(library2 PUBLIC library1)
target_include_directories(library2 PUBLIC lib2)

add_executable(foo empty.c)
target_link_libraries(foo PRIVATE library2)
/tmp% mkdir lib{1,2} && touch {lib1/,lib2/,}empty.c && cmake -DCMAKE_VERBOSE_MAKEFILE=ON . >/dev/null 2>&1 && make 2>&1 | grep -- -I
/usr/bin/cc  -I/tmp/lib1  -MD -MT CMakeFiles/library1.dir/lib1/empty.c.o -MF CMakeFiles/library1.dir/lib1/empty.c.o.d -o CMakeFiles/library1.dir/lib1/empty.c.o -c /tmp/lib1/empty.c
/usr/bin/cc  -I/tmp/lib2 -I/tmp/lib1  -MD -MT CMakeFiles/library2.dir/lib2/empty.c.o -MF CMakeFiles/library2.dir/lib2/empty.c.o.d -o CMakeFiles/library2.dir/lib2/empty.c.o -c /tmp/lib2/empty.c
/usr/bin/cc  -I/tmp/lib2 -I/tmp/lib1  -MD -MT CMakeFiles/foo.dir/empty.c.o -MF CMakeFiles/foo.dir/empty.c.o.d -o CMakeFiles/foo.dir/empty.c.o -c /tmp/empty.c
slovazap ★★★★★
()
Ответ на: комментарий от iliyap

target_include_directories(library1 PUBLIC path)

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

normann ★★★
() автор топика
Ответ на: комментарий от slovazap

Похоже я что-то напутал, а разве должен вообще путь к dir1 (lib1) попадать в пути поиска заголовков в зависимом таргете (exe или другой либе), куда куда library1, без вызова target_include_directories() в файле проекта library1? В документации об этом ничего не сказано, а я почему-то думал что должен попадать. Я перепроверил ещё раз, создав тестовый проект, без target_include_directories, и ни какому проекту в пути поиска ничего не передаётся.

У меня в library1 нет никаких target_include_directories.

normann ★★★
() автор топика
Ответ на: комментарий от normann

Похоже я что-то напутал, а разве должен вообще путь к dir1 (lib1) попадать в пути поиска заголовков в зависимом таргете (exe или другой либе), куда куда library1, без вызова target_include_directories() в файле проекта library1?

Тут сразу несколько вопросов намешано.

Если мы говорим об этом конкретном примере, где цепочка зависимостей такая: app→lib2→lib1, то в lib2 путь к инклудам lib1 попадать безусловно должен, иначе как lib2, используя lib1, найдёт её инклуды? Должен ли он попадать в app зависит от того как устроена lib2 - она может прокидывать через себя интерфейсы lib1 (как например, glib торчит через gtk), то должны, если же она только использует lib1 и никуда им не светит, то не должны. Поведение CMake в этом аспекте контролируется через PUBLIC/PRIVATE/INTERFACE в target_link_libraries и target_include_directories. То есть для случая когда lib2 потребляет lib1 и никак им не светит, нужно было бы делать target_link_libraries(library2 PRIVATE library1), тогда получим:

/usr/bin/cc  -I/tmp/lib1  -MD -MT CMakeFiles/library1.dir/lib1/empty.c.o -MF CMakeFiles/library1.dir/lib1/empty.c.o.d -o CMakeFiles/library1.dir/lib1/empty.c.o -c /tmp/lib1/empty.c
/usr/bin/cc  -I/tmp/lib2 -I/tmp/lib1  -MD -MT CMakeFiles/library2.dir/lib2/empty.c.o -MF CMakeFiles/library2.dir/lib2/empty.c.o.d -o CMakeFiles/library2.dir/lib2/empty.c.o -c /tmp/lib2/empty.c
/usr/bin/cc  -I/tmp/lib2  -MD -MT CMakeFiles/foo.dir/empty.c.o -MF CMakeFiles/foo.dir/empty.c.o.d -o CMakeFiles/foo.dir/empty.c.o -c /tmp/empty.c

Ну и надо ещё раз сделать акцент на том что в современном CMake инклуды распространяются только через цели. То есть когда ты используешь библиотеку, нужно сделать только target_link_libraries, это подтянет как саму библиотеку, так и её заголовки, правильным образом. target_include_directories на заголовочные файлы зависимости делать никогда не надо.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 2)
Ответ на: комментарий от slovazap

Мне вопрос остался не ясным, без вызова target_include_directories(library1 ${CMAKE_CURRENT_SOURCE_DIR}) в самом CMakeLists.txt проекта library1, будет ли (должен ли) ${CMAKE_CURRENT_SOURCE_DIR} передаваться в импортирующие таргеты?

normann ★★★
() автор топика