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

Mat*_*mes 0 cmake toolchain sdcc

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

如此链接所述,如果toolchain.cmake文件定义了 a ,CMake 将在目录下CMAKE_SYSTEM_NAME查找具有 的文件。这个文件应该定义特定于平台的选项。就我而言,我用它来查找${CMAKE_SYSTEM_NAME}.cmakeModule/Platformsdcc编译器并设置一些编译器标志。

这对我来说效果很好。使用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")
Run Code Online (Sandbox Code Playgroud)

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.")
Run Code Online (Sandbox Code Playgroud)

我的CMakeLists.txt如下:

cmake_minimum_required(VERSION 3.10)
project(PicExample)

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

add_executable(pic_example main.c)
Run Code Online (Sandbox Code Playgroud)

我从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".
Run Code Online (Sandbox Code Playgroud)

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

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

小智 5

Tsyvarev 回答了为什么工具链在 CMake 中多次使用。太长了;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})
Run Code Online (Sandbox Code Playgroud)

如果您想查看工具链脚本执行了多少次,请尝试在其中添加 message() 调用以获取乐趣。

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

如果您想知道我如何知道这些信息,那是因为我阅读了 Craig Scott 的 CMake 书籍“专业 CMake:实用指南”中的工具链部分

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