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

  • top CMakeLists: 包含要编译的应用程序文件 (main.c) + 2
    目标依赖项(算法和硬件)
  • target_link_libraries(app_target PUBLIC algo_target hardware_target)
    
  • 算法 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。我有以下错误:



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

    最佳答案

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

    关于c - 如何将编译选项从目标传播到 Cmake 上的所有其他人,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56073201/

    10-15 16:45