Cmake C在windows上交叉编译时生成find_package()搜索路径

Cmake C在windows上交叉编译时生成find_package()搜索路径,cmake,Cmake,我正在尝试使用cmake在windows上使用arm none eabi gcc进行交叉编译,出于某种原因,find_package()正在搜索$PATH中所有目录的版本,而不是工具链文件中提供的cmake_find_ROOT_路径。具体而言,在工具链文件中,我有以下几行: SET(CMAKE_INSTALL_PREFIX "C:/toolchains/cm0p_root" CACHE PATH "Cmake install prefix") set(CMAKE_FIND_ROOT_PATH $

我正在尝试使用cmake在windows上使用arm none eabi gcc进行交叉编译,出于某种原因,find_package()正在搜索$PATH中所有目录的版本,而不是工具链文件中提供的cmake_find_ROOT_路径。具体而言,在工具链文件中,我有以下几行:

SET(CMAKE_INSTALL_PREFIX "C:/toolchains/cm0p_root" CACHE PATH "Cmake install prefix")
set(CMAKE_FIND_ROOT_PATH ${CMAKE_INSTALL_PREFIX})
...
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)
我使用相同的工具链编译并安装了我的库,所有内容都正确地安装到了cmp0_根目录中

My projects CMakeLists.txt文件中包含以下内容:

find_package(myLIB REQUIRED)
target_link_libraries(testProject PUBLIC myLIB::myLIB)
而find_package()找不到库。如果我将这两个版本中的任何一个添加了提示或路径,它就会成功

find_package(myLIB REQUIRED HINTS /)
find_package(myLIB REQUIRED PATHS "C:/toolchains/cm0p_root")
使用命令行选项
-D CMAKE\u FIND\u DEBUG\u MODE=ON
我可以看到它正在搜索以下路径:

Checking prefix [C:/toolchains/cm0p_root/git-sdk-64/mingw64/]
Checking prefix [C:/toolchains/cm0p_root/Users/myname/]
Checking prefix [C:/toolchains/cm0p_root/Program Files/ConEmu/]
Checking prefix [C:/toolchains/cm0p_root/Python/Python36-32/]
Checking prefix [C:/toolchains/cm0p_root/Python/Python36-32/Scripts/]
Checking prefix [C:/toolchains/cm0p_root/Windows/]
Checking prefix [C:/toolchains/cm0p_root/LLVM/]
Checking prefix [C:/toolchains/cm0p_root/Program Files (x86)/IAR Systems/Embedded Workbench 8.0/common/]
Checking prefix [C:/toolchains/cm0p_root/Program Files (x86)/IAR Systems/Embedded Workbench 8.0/avr/]
Checking prefix [C:/toolchains/cm0p_root/Program Files (x86)/IAR Systems/Embedded Workbench 8.2/arm/]
Checking prefix [C:/toolchains/cm0p_root/Program Files (x86)/MSBuild/12.0/Bin/]
还有更多,但很明显,CMake将FIND_ROOT_路径作为前缀添加到所有windows$PATH变量的开头!列表要长得多,但它从不搜索
C:/toolschains/cm0p\u root/
,这正是我所需要的(我猜为什么这个提示有效)

如何让CMake不搜索所有这些目录?我正在交叉编译,据我所知,它应该只搜索我的“假”根目录,因为
CMAKE\u FIND\u root\u PATH\u MODE\u PACKAGE
设置为
only

根据Tsyvarev的评论创建答案

变量
CMAKE\u FIND\u ROOT\u PATH
表示要搜索的根目录,但实际前缀是通过将目录附加到根目录来计算的。这方面的具体实现可在中找到

相关步骤为前两步(来自CMake文档):

  • 搜索
    \u ROOT
    CMake变量和
    \u ROOT
    环境变量中指定的路径,其中
    是要查找的包。包根变量作为堆栈进行维护,因此如果从find模块中调用,父级find模块的根路径也将在当前包的路径后进行搜索。如果
    没有传递包根路径,或者通过设置
  • 在cmake特定缓存变量中指定的搜索路径。这些命令用于命令行中的
    -DVAR=value
    。这些值被解释为分号分隔的列表。如果传递了
    NO\u CMAKE\u PATH
    ,或者通过将
    CMAKE\u FIND\u USE\u CMAKE\u PATH
    设置为
    FALSE
    ,则可以跳过此操作:
    • MAKE_PREFIX_PATH
    • CMAKE\u框架\u路径
    • CMAKE\u APPBUNDLE\u路径
  • 我们关心的变量是用以下值初始化的:

    以分号分隔的目录列表,指定要由find_package()、find_program()、find_library()、find_file()和find_path()命令搜索的安装前缀。每个命令都将按照自己的文档中的指定添加相应的子目录(如bin、lib或include)

    因此,更好的工具链可以清除
    CMAKE\u SYSTEM\u PREFIX\u PATH
    中的值,例如:

    SET(CMAKE_INSTALL_PREFIX "C:/toolchains/cm0p_root" CACHE PATH "Cmake install prefix")
    set(CMAKE_FIND_ROOT_PATH ${CMAKE_INSTALL_PREFIX})
    set(CMAKE_SYSTEM_PREFIX_PATH /)
    ...
    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)
    
    关于是否应执行此操作的注释:

    这项技术并没有真正奏效。这很难维护,因为对于每个不兼容的编译选项组合,都需要单独的“sysroot”。相反,至少现在,我使用缓存和使用预编译的依赖项。对于较小的东西,我只使用它作为本机CMake模块的良好包装

    变量
    CMake_FIND_ROOT_PATH
    表示要搜索的根目录,但实际前缀是通过在根目录中附加一些子目录来计算的。您可以在中找到计算前缀的算法。默认情况下,CMake不会在
    /
    子目录下搜索,因此CMake不会将根目录解释为搜索前缀。您将
    /
    添加到变量
    CMAKE\u PREFIX\u PATH
    ,因此您的根路径也将被视为前缀。我混淆了
    CMAKE\u FIND\u root\u PATH
    ,认为根路径在文档中的搜索路径中用作前缀。在你的评论之后重新阅读它,它会更有意义。因此,一个更好的工具链片段会添加一行:
    set(CMAKE\u SYSTEM\u PREFIX\u PATH/)
    ?我使用了
    CMAKE\u-SYSTEM\u-PREFIX\u-PATH
    ,因为它似乎更适合于工具链文件,文档说
    CMAKE\u-PREFIX\u-PATH
    应该在项目中设置。嗯,我不确定变量
    CMAKE\u-SYSTEM\u-PREFIX\u-PATH
    的预期用途是什么,但根据其文档,它看起来就像是一个工具链。顺便问一下,为什么你要把你的程序安装到根目录中?这就像你在
    C://
    中安装了一样。通常,在Windows上,
    C:/Program Files/
    用作安装前缀。您交叉编译的操作系统是什么?我不是直接安装到根目录中,而是使用GNUInstallDirs模块。因此,头被放入
    C:/toolschains/cm0p\u root/include
    ,库被放入
    C:/toolschains/cm0p\u root/lib
    ,cmake配置文件被放入
    C:/toolschains/cm0p\u root/share/*/
    等等。我正在交叉编译裸臂皮质和AVR。我希望使用一个“sysroot”,在那里我可以安装软件包,这样我就不需要巨大的单片源代码树。例如,我使用的一个简单的实时调度器需要在每个源代码树中复制,但最好在每个体系结构中编译并“安装”它一次。
    set(CMAKE\u SYSTEM\u NAME Generic)
    set(CMAKE\u SYSTEM\u PROCESSOR cortex-m0plus)
    应该将
    CMAKE\u交叉编译
    设置为true。但同样,不是为linux编译,只是一个裸机设备。除非显式地将is设置为linux,否则可能在内部以windows方式构造前缀。这似乎是个坏主意,因为据我所知,大多数裸机工具链都使用gnu文件夹结构(甚至在windows上)。