Поскольку вы не предоставили минимальный рабочий пример, я не смог бы ответить на ваш вопрос полностью. Тем не менее, поскольку CMake занимается исключительно целями и управлением зависимостями между этими целями, я полагаю, что любая цель, которой требуются некоторые настройки / зависимости от другой, должна зависеть от этой цели.
Предположим, что у нас есть следующая структура каталогов:
.
├── algo
│ ├── CMakeLists.txt
│ ├── include
│ │ └── algo.hpp
│ └── src
│ └── algo.cpp
├── CMakeLists.txt
├── hardware
│ ├── CMakeLists.txt
│ ├── include
│ │ └── hardware.hpp
│ └── src
│ └── hardware.cpp
└── main.cpp
6 directories, 8 files
со следующим содержимым файла для algo
# algo/CMakeLists.txt
add_library(algo
include/algo.hpp
src/algo.cpp
)
target_include_directories(algo
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
# if (TARGET hardware)
# target_link_libraries(algo PRIVATE hardware)
# endif()
/* algo/include/algo.hpp */
#pragma once
double func1(const double);
/* algo/src/algo.cpp */
#include "algo.hpp"
double func1(const double x) {
#ifdef IMPORTANT_DEF
return 2 * x;
#else
return x;
#endif
}
для hardware
# hardware/CMakeLists.txt
add_library(hardware
include/hardware.hpp
src/hardware.cpp
)
target_include_directories(hardware
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_compile_definitions(hardware
PUBLIC
IMPORTANT_DEF
)
/* hardware/include/hardware.hpp */
#pragma once
#ifdef IMPORTANT_DEF
double func2(const double, const double);
#else
int func2(int, const int);
#endif
/* hardware/src/hardware.cpp */
#include "hardware.hpp"
#ifdef IMPORTANT_DEF
double func2(const double x, const double y) { return x + y; }
#else
int func2(int x, const int y) { return x - y; }
#endif
и, наконец, для app
# CMakeLists.txt
cmake_minimum_required(VERSION 3.9)
project(propagate LANGUAGES C CXX)
add_subdirectory(hardware)
add_subdirectory(algo)
add_executable(app main.cpp)
target_link_libraries(app
PRIVATE
hardware
algo
)
/* main.cpp */
#include <iostream>
using namespace std;
#include "hardware.hpp"
#include "algo.hpp"
int main(int argc, char* argv[]) {
cout << func1(5) << '\n';
cout << func2(5, 3) << '\n';
return 0;
}
Когда мы создаем вышеуказанный проект и запускаем его, мы получаем
./app
5
8
Это потому, что мы не сказали CMake, что algo
зависит от hardware
. Когда мы раскомментируем часть
# if (TARGET hardware)
# target_link_libraries(algo PRIVATE hardware)
# endif()
в algo/CMakeLists.txt
и пересоберите проект, на этот раз мы получим
./app
10
8
В основном, команды target_*
используются для определения зависимостей, которые должны или не должны распространяться на потребителей целей. Следовательно, мы должны сделать цель algo
потребителем цели hardware
.
Обратите также внимание, что для распространения target_*
friends aldo необходимо заполнить свойства INTERFACE_*
цели, т. Е. Команды target_*
должны определить свойства либо как PUBLIC
(отображая оба в заголовочных файлах и файлах реализации) или INTERFACE
(отображаются только в заголовочных файлах), но не PRIVATE
(отображаются только в файлах реализации).