PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Tuesday, September 13, 2022

[FIXED] how propagate compilation options from a target to all others on Cmake

 September 13, 2022     c, cmake, cross-platform, gcc, target     No comments   

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 aldo 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 - Senaida (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing