在CMake中检测底层平台/版本

28

有没有人知道任何可以提供正在执行的底层平台名称/版本名称的cmake变量或钩子或其他内容? 例如:Linux-CentOs Linux-Ubuntu Linux-SLES

我知道cmake有"CMAKE_SYSTEM"变量,但这不能帮助区分不同的Linux版本。任何帮助都将不胜感激。

编辑: 我刚刚读到可以使用lsb_release命令来完成?

7个回答

27
下面的代码片段将使用关于底层Linux系统的信息填充LSB_RELEASE_ID_SHORT cmake变量:
find_program(LSB_RELEASE_EXEC lsb_release)
execute_process(COMMAND ${LSB_RELEASE_EXEC} -is
    OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT
    OUTPUT_STRIP_TRAILING_WHITESPACE
)

例如,在Ubuntu上,它会产生Ubuntu


不同的发行版将相同的内容放置在不同的位置。这是使用那些特定于发行版的位置来包含库的完美方式。 - moodboom
可能希望以简洁的方式检查一下是否为linux系统。我自己也在学习cmake。 - fuzzyTew
在ARM64 Ubuntu上测试,它显示“没有可用的LSB模块”。 - tresf
1
你的系统中是否安装了 lsb_release 二进制文件?例如,在 Arch 上,它的软件包名为 lsb-release - thiagowfx

11

相对于检查文件系统上的文件而言,从可用的CMAKE_SYSTEM变量中尽可能推导出最佳方案会稍微简单一些。例如,一个包含如下内容的 CMakeLists.txt 文件:

message("-- CMAKE_SYSTEM_INFO_FILE: ${CMAKE_SYSTEM_INFO_FILE}")
message("-- CMAKE_SYSTEM_NAME:      ${CMAKE_SYSTEM_NAME}")
message("-- CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
message("-- CMAKE_SYSTEM:           ${CMAKE_SYSTEM}")

string (REGEX MATCH "\\.el[1-9]" os_version_suffix ${CMAKE_SYSTEM})
message("-- os_version_suffix:      ${os_version_suffix}")

我在运行 cmake . 时输出了这个:

-- CMAKE_SYSTEM_INFO_FILE: Platform/Linux
-- CMAKE_SYSTEM_NAME:      Linux
-- CMAKE_SYSTEM_PROCESSOR: x86_64
-- CMAKE_SYSTEM:           Linux-2.6.32-573.7.1.el6.x86_64
-- os_version_suffix:      .el6

对于我的情况来说,.el6 已经足够区分了。


1
你只捕获一个数字,我认为使用"\.el[1-9]+"会是个更好的主意;-) - Doncho Gunchev

7
很可能你需要自行编写此类测试。以下是一个可能的示例,只需使用 Google 搜索即可:https://htcondor-wiki.cs.wisc.edu/index.cgi/fileview?f=build/cmake/FindLinuxPlatform.cmake&v=4592599fecc08e5588c4244e2b0ceb7d32363a56 但是,根据您的实际需求,测试可能会非常复杂。例如,作为基于 Debian 的操作系统,Ubuntu 总是具有 /etc/debian_version,而许多基于 RPM 的操作系统传统上具有 /etc/redhat-release。Linux 标准库规范(LSB)中有一个文件 /etc/os-release,但例如在本地主机上,由于未知原因,此文件为空。

是的,问题相当复杂,我正在考虑手动设置变量,但只是想看看是否有其他解决方案。 - voidMainReturn
好的,我已经给出了上面的一种可能的实现。对于基于SuSE的系统,您还可以查看/etc/SuSE-release。另一个可能的解决方案是检测“主要版本”(例如,它是基于RPMDEB还是<YOU-NAME-THE-PACKAGE-MANAGER>,然后调用检测到的软件包管理器并查找特定的软件包,如此处所述。 - user3159253
1
请注意,/etc/os-release 至少可以在所有基于systemd的发行版上使用。 - mattdm

6

我知道这是一个老问题,但截至目前,仍然没有一个内置的cmake函数能够详细地找到这些信息。我实现了一个小实用程序函数,使用Linux上的lsb_release来查找许多相关的系统细节:

function(get_linux_lsb_release_information)
    find_program(LSB_RELEASE_EXEC lsb_release)
    if(NOT LSB_RELEASE_EXEC)
        message(FATAL_ERROR "Could not detect lsb_release executable, can not gather required information")
    endif()

    execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --id OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE)
    execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --release OUTPUT_VARIABLE LSB_RELEASE_VERSION_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE)
    execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --codename OUTPUT_VARIABLE LSB_RELEASE_CODENAME_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE)

    set(LSB_RELEASE_ID_SHORT "${LSB_RELEASE_ID_SHORT}" PARENT_SCOPE)
    set(LSB_RELEASE_VERSION_SHORT "${LSB_RELEASE_VERSION_SHORT}" PARENT_SCOPE)
    set(LSB_RELEASE_CODENAME_SHORT "${LSB_RELEASE_CODENAME_SHORT}" PARENT_SCOPE)
endfunction()

将它添加到您的 CMakeLists.txt 中,然后像这样使用:

if(CMAKE_SYSTEM_NAME MATCHES "Linux")
    get_linux_lsb_release_information()
    message(STATUS "Linux ${LSB_RELEASE_ID_SHORT} ${LSB_RELEASE_VERSION_SHORT} ${LSB_RELEASE_CODENAME_SHORT}")
endif()

如果您需要更多细节,请使用“lsb_release -a”查看lsb_release提供的其他内容。
请注意,并非每个Linux都安装了lsb_release。大多数系统提供它,但不是强制性的。例如,在较新的Ubuntu上,它是桌面安装的默认选项,并且是ubuntu-minimal所需的。如果您的计算机上缺少它,则可以使用sudo apt install lsb-release进行安装。

1
在我的电脑上。
CMAKE_SYSTEM_INFO_FILE == "Platform/Linux"
CMAKE_SYSTEM_NAME == "Linux"
CMAKE_SYSTEM == "Linux-<kernel version>"

通过使用cmake --system-information命令,我知道有人在他们自己的CMakeLists.txt文件中使用所述的宏,以便按预期工作,可能CMAKE_SYSTEM_NAME是你真正想要的,但在这里你可以获得这个3以及检查您的机器属性的cmake命令。

1
不幸的是,Linux内核版本通常是给定Linux安装的最不重要的特征。从技术上讲,我可以在我的工作站上设置一个非常古老的内核。好吧,那么我可能还需要降级或专门编译LIBC...好吧,再加上一些“核心软件”。 - user3159253
@user3159253 这就是为什么我添加了这个命令,该命令会提供您编译软件所需的所有信息。 - user2485710
不,我使用基于Ubuntu的发行版,它没有提供任何关于这方面的信息,甚至没有告诉我我的实际发行版(KDE Neon)。必须使用 uname 命令。 - xeruf

1
基于 thiagowfx的回答,如果您想获取发行版的代号(如果可用):
execute_process(COMMAND lsb_release -cs
    OUTPUT_VARIABLE RELEASE_CODENAME
    OUTPUT_STRIP_TRAILING_WHITESPACE
)

例如,在Ubuntu 14.04中,变量RELEASE_CODENAME将保存trusty

1
### find our os (wins, centos, ubuntu, etc)
set(VAR_OS "")
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
        MESSAGE(DEBUG "Linux")
        execute_process (
                COMMAND bash -c "awk -F= '/^ID=/{print $2}' /etc/os-release |tr -d '\n' | tr -d '\"'"
                OUTPUT_VARIABLE outOS
        )
        MESSAGE(DEBUG "Linux os: ${outOS}")
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Windows")
        MESSAGE(DEBUG "Windows")
        set(VAR_OS "wins")
ELSE()
        MESSAGE(FATAL "No OS detected!")
ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接