Issue
I'm implementing modern Cmake on a ARM project. I have 3 different CMakeLists:
- top CMakeLists: contains application files to compile (main.c) + 2 target dependencies (algo and hardware)
target_link_libraries(app_target PUBLIC algo_target hardware_target)
- algo CMakeLists has only C files which do only computes (algo.c)
- hardware CMakeLists which compiles all files about hardware dependencies (hardware.c) and compile options depending of the hardware specially -mcpu -mthumb -mfloat-abi -mfpu
target_compile_options(hardware_target -mcpu=${CPU} -mthumb -mfloat-abi=hard -mfpu=${FPU})
The problem is, the compile options are propagate to the top, but not on algo_target. I have the following error:
app uses VFP register arguments, algo.a(algo.cpp.obj) does not
How propagate compilation options on all targets ? I don't want to set compile options in compile option variable, in the future, the application will run on 2 different hardware targets
Solution
Because you do not provide a minimal working example, I might not be able to answer your question fully. However, since CMake is all about targets and dependency management among those targets, I guess that any target that needs some settings/dependencies from another one should depend on that target.
Assume that we have the following directory structure:
.
├── 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
with the following file contents for 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
}
for 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
and, finally, for 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;
}
When we build the above project and run it, we get
./app
5
8
This is because we have not told CMake that algo
depends on hardware
. When we uncomment the part
# if (TARGET hardware)
# target_link_libraries(algo PRIVATE hardware)
# endif()
in algo/CMakeLists.txt
and rebuild the project, this time we get
./app
10
8
Basically, target_*
commands are used to define dependencies that should or should not propagate to the consumers of the targets. Hence, we should make the algo
target a consumer of the hardware
target.
Please note also that, for the propagation to happen, target_*
friends also need to populate the INTERFACE_*
properties of the target, i.e., target_*
commands need to define the properties as either PUBLIC
(appearing both in header and implementation files) or INTERFACE
(appearing only in header files), but not PRIVATE
(appearing only in the implementation files).
Answered By - Arda Aytekin Answer Checked By - Katrina (WPSolving Volunteer)