微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么工具链文件在 CMake 中执行了几次?

如何解决为什么工具链文件在 CMake 中执行了几次?

在尝试使用 SDCC 编译器创建交叉编译 CMake 工具链模板时,我遇到了一个非常奇怪的问题。

this link中所述,如果toolchain.cmake文件定义了CMAKE_SYstem_NAME,CMake将在${CMAKE_SYstem_NAME}.cmake目录下寻找带有Module/Platform文件。此文件应定义特定于平台的选项。就我而言,我使用它来查找 sdcc 编译器并设置一些编译器标志。

这对我来说很好用。使用 cmake -DCMAKE_MODULE_PATH="${PATH_TO_MY_MODULES}" -DCMAKE_TOOLCHAIN_FILE="${PATH_TO_MY_TOOLCHAIN}" -DSDCC_SYSROOT="SOME_VALUE",CMake 找到所有正确的工具链和平台文件

似乎工具链和平台文件在配置过程中被执行几次(不确定这是否正确)。在最初的几次中,我在 CMake 命令中传递的变量 SDCC_SYSROOT 具有预期的值 SOME_VALUE。但是,在上次执行这些工具链/平台文件时,相同的变量 SDCC_SYSROOT 似乎丢失了值。所以它们是空的。这会导致我的脚本生成致命错误

toolchain.cmake 有以下内容

set(CMAKE_SYstem_NAME SDCC_PIC_16F877A)

# Finding resource settings
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# Set default MCU family and model
if (NOT microcHIP_FAMILY)
  set(microcHIP_FAMILY "pic16")
endif()

if (microcHIP_MODEL STREQUAL "pic16")
  set(microcHIP_MODEL "16f877a")
endif()


# Need a better way to detect the supported models here
if (NOT microcHIP_FAMILY STREQUAL "pic16" AND NOT microcHIP_MODEL STREQUAL "16f877a")
  message(FATAL_ERROR "Settings not supported. Please drop a request.")
endif()

if (NOT SDCC_ROOT)
  message(FATA_ERROR "Need to provide the root (from toolchain.)")
endif()

# Cache those variables
set(SDCC_ROOT "${SDCC_ROOT}"
  CACHE INTERNAL "Root directory of SDCC installation")

set(microcHIP_FAMILY "${microcHIP_FAMILY}"
  CACHE INTERNAL "Family of the chip to compile for")

set(microcHIP_MODEL "${microcHIP_MODEL}"
  CACHE INTERNAL "Model of the chip to compile for")

Module/Platform/SDCC_PIC_16F877A.cmake 文件包含以下内容

# Check if the shit exists
message("!!! The value of root is ${SDCC_ROOT}")
if (NOT SDCC_ROOT)
  message(FATAL_ERROR
    "SDCC_ROOT is not defined. Please set this variable e.g.\n"
    "cmake -DSDCC_ROOT=\"C:/Program Files/sdcc\"")
endif()

# Finding the compilers
find_program(CMAKE_C_COMPILER
  sdcc
  PATHS ${SDCC_ROOT}
  PATH_SUFFIXES "bin"
  DOC "path to the SDCC C compiler.")

我的 CMakeLists.txt 如下:

cmake_minimum_required(VERSION 3.10)
project(PicExample)

message("THE COMPILER IS ${CMAKE_C_COMPILER}")

add_executable(pic_example main.c)

我从 project/build 目录调用内容以及我得到的错误

 cmake -DCMAKE_MODULE_PATH:FILEPATH="/mnt/c/Users/mathe/Desktop/coding/sdcc-pic-template/Modules" -DCMAKE_TOOLCHAIN_FILE:FILEPATH="/mnt/c/Users/mathe/Desktop/coding/sdcc-pic-template/Modules/toolchain.cmake" -DSDCC_ROOT="testing/" ..
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
!!! The value of root is testing/
!!! The value of root is testing/
-- Check for working C compiler: /usr/bin/cc
FATA_ERRORNeed to provide the root (from toolchain.)
!!! The value of root is
CMake Error at /mnt/c/Users/mathe/Desktop/coding/sdcc-pic-template/Modules/Platform/SDCC_PIC_16F877A.cmake:4 (message):
  SDCC_ROOT is not defined.  Please set this variable e.g.

  cmake -DSDCC_ROOT="C:/Program Files/sdcc"
Call Stack (most recent call first):
  /usr/share/cmake-3.16/Modules/CMakeSystemSpecificinformation.cmake:26 (include)
  /mnt/c/Users/mathe/Desktop/coding/sdcc-pic-template/build/CMakeFiles/CMakeTmp/CMakeLists.txt:3 (project)


CMake Error at /usr/share/cmake-3.16/Modules/CMakeTestCCompiler.cmake:44 (try_compile):
  Failed to configure test project build system.
Call Stack (most recent call first):
  CMakeLists.txt:2 (project)


-- Configuring incomplete,errors occurred!
See also "/mnt/c/Users/mathe/Desktop/coding/sdcc-pic-template/build/CMakeFiles/CMakeOutput.log".

为什么工具链文件被 CMake 多次“执行”并且在最近的运行中无法访问缓存?我发现交叉编译的 CMake 文档非常困难,尤其是当您使用非标准编译器时。

我知道其他人以前也遇到过同样的问题,但我并不是简单地要求一个简单的解决方案(设置环境变量)。我实际上想知道为什么会发生这种情况(之前的答案没有解决)。

解决方法

为了确定编译器或库是否支持某些功能,CMake 使用 try_compile 方法:在配置阶段,它创建单独的 CMake 项目并立即配置和构建它。因为它是一个单独的项目,它的配置步骤与主项目相同,并且加载工具链文件

try_compile 可以由(用户)项目用于检查库或编译器的功能。有许多 CMake 模块在其实现中使用 try_compile。例如。 CheckSymbolExists

try_compile 也由 CMake 本身在平台文件中用于对编译器执行基本检查。在您的日志中,您可以找到以下行:

CMake 错误在 /usr/share/cmake-3.16/Modules/CMakeTestCCompiler.cmake:44 (try_compile)

除了 try_compile,新的 CMake 项目是在 ExternalProject_Add 命令中创建的。该创建还伴随着工具链文件的读取。 (更准确地说,不是在处理 ExternalProject_Add 调用时而是在配置相应项目时创建新项目。此配置在主项目的构建阶段执行。)

,

Tsyvarev 回答了为什么在 CMake 中多次使用工具链。 TLDR; CMake 需要它进行多次 try_compile() 调用,它在内部用于错误检查和其他事情。

这对我来说很好用。 -DCMAKE_MODULE_PATH="${PATH_TO_MY_MODULES}" -DCMAKE_TOOLCHAIN_FILE="${PATH_TO_MY_TOOLCHAIN}" -DSDCC_SYSROOT="SOME_VALUE",

要在此处解决您的问题,这是您需要做的。

本质上,您将参数传递给您的工具链文件。而这个论点 SDCC_SYSROOT 基本上超出了范围。

要解决此问题,您需要执行此操作。

# Use list(APPEND) rather than set() so that any variables added by CMake aren't lost!
#
# Here is the docs for this variable: 
# https://cmake.org/cmake/help/latest/variable/CMAKE_TRY_COMPILE_PLATFORM_VARIABLES.html
list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES ${SDCC_SYSROOT})

如果您想查看您的工具链脚本执行了多少次,请尝试在其中放入一个 message() 调用以获得乐趣。

如果你真的有兴趣查看你的构建文件夹,看看 CMake 正在做什么。

如果您想知道我是如何知道这些信息的,那是因为我阅读了 Craig Scott 的 CMake 书籍“Professional CMake: 实用指南"

这是一个链接:https://crascit.com/professional-cmake/

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。