【问题标题】:how propagate compilation options from a target to all others on Cmake如何将编译选项从目标传播到 Cmake 上的所有其他人
【发布时间】:2019-05-10 08:01:55
【问题描述】:

我正在一个 ARM 项目上实现现代 Cmake。我有 3 个不同的 CMakeLists:

  • top CMakeLists:包含要编译的应用程序文件 (main.c) + 2 目标依赖项(算法和硬件)
target_link_libraries(app_target PUBLIC algo_target hardware_target)
  • algo CMakeLists 只有 C 文件 只计算 (algo.c)
  • 编译的硬件 CMakeLists 所有关于硬件依赖关系的文件(hardware.c)和编译选项,具体取决于硬件 -mcpu -mthumb -mfloat-abi -mfpu
target_compile_options(hardware_target -mcpu=${CPU} -mthumb -mfloat-abi=hard -mfpu=${FPU})

问题是,编译选项会传播到顶部,但不会传播到 algo_target。我有以下错误:

app 使用 VFP 寄存器参数,algo.a(algo.cpp.obj) 不使用

如何在所有目标上传播编译选项? 我不想在编译选项变量中设置编译选项,将来应用程序将在 2 个不同的硬件目标上运行

【问题讨论】:

    标签: c gcc cmake cross-platform target


    【解决方案1】:

    由于您没有提供最小的工作示例,我可能无法完全回答您的问题。但是,由于 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_* 朋友还需要填充目标的INTERFACE_* 属性,即target_* 命令需要将属性定义为PUBLIC(同时出现在头文件和实现文件中)或INTERFACE(仅出现在头文件中),而不是PRIVATE(仅出现在实现文件中)。

    【讨论】:

    • 你完全理解我的问题。我很奇怪算法目标取决于硬件目标,我不想在构建 algo.cpp 时构建 hardware.cpp。这是否意味着,我需要第 4 个 CMakeLists.txt 仅用于编译选项?
    • 也许不是。 CMake 必须了解目标的消费者,以及目标的属性/配置如何(如果有的话)传播到目标的消费者。根据the documentation,如果只在目标名称后的target_compile_options 后面加上PUBLIC 关键字,应该没问题。但真正的问题是,所有这些目标都是相互解耦的,除非你定义一些依赖或使用toolchain 文件来定义全局选项
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 2015-08-07
    • 2017-11-01
    相关资源
    最近更新 更多