CMAKE中的操作系统特定说明:如何操作?

Pra*_*sad 74 c++ linux portability mingw cmake

我是CMAKE的初学者.下面是一个简单的cmake文件,适用于mingw环境窗口.问题显然target_link_libraries()是CMAKE的功能,我链接libwsock32.a.在Windows中这是有效的,我得到了结果.

但是,正如预期的那样,在Linux中,/usr/bin/ld将寻找-lwsock32Linux操作系统中不存在的内容.

我的问题是:我如何指示CMAKE避免在Linux OS中链接wsock32库?

任何帮助将不胜感激.

我的简单CMake文件:

 PROJECT(biourl)
 set (${PROJECT_NAME}_headers ./BioSocketAddress.h  ./BioSocketBase.h ./BioSocketBuffer.h ./BioSocketCommon.h  ./BioSocketListener.h  ./BioSocketPrivate.h  ./BioSocketStream.h ./BioUrl.h BioDatabase.h )

set (${PROJECT_NAME}_sources BioSocketAddress.C  BioSocketBase.C  BioSocketCommon.C BioSocketStream.C  BioUrl.C BioDatabase.C )

add_library(${PROJECT_NAME} STATIC ${${PROJECT_NAME}_headers} ${${PROJECT_NAME}_sources} )

# linkers
#find_library(ws NAMES wsock32 PATHS ${PROJECT_SOURCE_DIR} NO_SYSTEM_ENVIRONMENT_PATH NO_DEFAULT_PATH)

target_link_libraries(${PROJECT_NAME} bioutils wsock32)

install (TARGETS ${PROJECT_NAME}
       RUNTIME DESTINATION bin
       LIBRARY DESTINATION lib
       ARCHIVE DESTINATION lib/archive )
Run Code Online (Sandbox Code Playgroud)

rel*_*xxx 109

使用

if (WIN32)
    #do something
endif (WIN32)
Run Code Online (Sandbox Code Playgroud)

要么

if (UNIX)
    #do something
endif (UNIX)
Run Code Online (Sandbox Code Playgroud)

要么

if (MSVC)
    #do something
endif (MSVC)
Run Code Online (Sandbox Code Playgroud)

或类似的

请参阅CMake有用变量CMake检查平台

  • 等等,这是检查主机平台还是构建目标平台?似乎是后者(我需要前者)。 (4认同)
  • 对于其他想知道的人:`根据传统, else() 和 endif() 命令允许可选的 <condition> 参数。如果使用,它必须是开头 if 命令的参数的逐字重复。来源:https://cmake.org/cmake/help/latest/command/if.html (3认同)
  • 啊,发现了这个。它提到了 UNIX、WIN32,大概还提到了它们的所有“同行”:https://cmake.org/Wiki/CMake_Checking_Platform (2认同)
  • @ rchilton1980:页面移动,新链接:https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/Checking-Platform (2认同)

mlv*_*ljr 57

鉴于这是一个常见的问题,geronto发布:

    if(UNIX AND NOT APPLE)
        set(LINUX TRUE)
    endif()

    # if(NOT LINUX) should work, too, if you need that
    if(LINUX) 
        message(STATUS ">>> Linux")
        # linux stuff here
    else()
        message(STATUS ">>> Not Linux")
        # stuff that should happen not on Linux 
    endif()
Run Code Online (Sandbox Code Playgroud)

CMake布尔逻辑文档

  • 谢谢你提到`APPLE`. (5认同)
  • 不要以为unix是linux.链接到cmake_system_name的cmake有用变量网站.使用Linux混合案例OS检测器 (3认同)
  • 是的,FreeBSD 也会通过 `(UNIX AND NOT APPLE)` ...并且 @mlvljr 的链接已更改为:https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/How -立即进行写入平台检查。 (2认同)

Afr*_*Afr 40

一般来说

您可以检测并指定多个操作系统的变量,如下所示:

检测Microsoft Windows

if(WIN32)
    # for Windows operating system in general
endif()
Run Code Online (Sandbox Code Playgroud)

要么:

if(MSVC OR MSYS OR MINGW)
    # for detecting Windows compilers
endif()
Run Code Online (Sandbox Code Playgroud)

检测Apple MacOS

if(APPLE)
    # for MacOS X or iOS, watchOS, tvOS (since 3.10.3)
endif()
Run Code Online (Sandbox Code Playgroud)

检测Unix和Linux

if(UNIX AND NOT APPLE)
    # for Linux, BSD, Solaris, Minix
endif()
Run Code Online (Sandbox Code Playgroud)

您的特定链接器问题

要解决Windows特定wsock32库的问题,只需将其从其他系统中删除,如下所示:

if(WIN32)
    target_link_libraries(${PROJECT_NAME} bioutils wsock32)
else
    target_link_libraries(${PROJECT_NAME} bioutils)
endif()
Run Code Online (Sandbox Code Playgroud)

  • Solaris的一个用途是什么? (2认同)
  • 根据文档,“APPLE”仅意味着我们正在为 Apple 目标构建;即 OSX,还有 iOS、watchOS 等。有没有办法以可靠的方式检测 os X? (2认同)

leg*_*s2k 31

现代 CMake 方式

\n

避免使用WIN32、等。摘自官方论坛APPLE版主的回复:

\n
\n

WIN32、等变量是 \xe2\x80\x9csoft\xe2\x80\x9d 已弃用 [...]是我\xe2\x80\x99d 在 CMake 代码中使用的,APPLE在生成器表达式中需要。UNIXCMAKE_SYSTEM_NAMEPLATFORM_ID

\n
\n

CMAKE_SYSTEM_NAME可以或取什么可能的值PLAFORM_ID参考来源

\n

如何检测平台

\n

使用STREQUAL

\n
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")\n  # Linux-specific stuff\nendif ()\n
Run Code Online (Sandbox Code Playgroud)\n

如何检测多个平台

\n

创建一个列表变量并使用IN_LIST

\n
set(OPENGL_PLATFORMS Linux Windows)\nif (CMAKE_SYSTEM_NAME IN_LIST OPENGL_PLATFORMS)\n  # platform-specific stuff e.g.\n  find_package(OpenGL REQUIRED)\nendif ()\n
Run Code Online (Sandbox Code Playgroud)\n

生成器表达式

\n

使用PLATFORM_ID

\n
target_link_libraries(TARGET_NAME PRIVATE\n  $<$<PLATFORM_ID:Linux,Windows>:OpenGL::GL>)\n
Run Code Online (Sandbox Code Playgroud)\n

旁白:生成器表达式只有在手册指出的情况下才能使用。例如,target_link_libraries文档中提到了这一点,而set_target_properties没有。我想阅读CMake: set_target_properties 失败,目标由生成器表达式定义,以了解原因。

\n

  • 我对投反对票没有任何问题。默默的否决有助于发泄情绪,更有用的是说出原因。它会帮助其他人(和我自己)从这篇文章的错误中吸取教训。谢谢! (3认同)

小智 17

你有CMAKE的一些特别的话,看看:

if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
    // do something for Linux
else
    // do something for other OS
Run Code Online (Sandbox Code Playgroud)

  • 对于那些搜索者,这里是名称列表 https://github.com/Kitware/CMake/blob/master/Modules/CMakeDetermineSystem.cmake (4认同)
  • 标准的CMake方式:*内部不一致*:) [这是一个正确的/对点的答案,但是] (3认同)
  • `STREQUAL` 接受变量(除了字符串之外)作为第一个操作数,因此它可能是更简洁的 `if(CMAKE_SYSTEM_NAME STREQUAL "Linux")...` (2认同)

Nic*_*tke 9

我想把这个留在这里,因为我在使用 Android SDK 在 Windows 中编译 Android 时遇到了这个问题。

CMake 区分 TARGET 和 HOST 平台。

我的目标是 Android,因此像 CMAKE_SYSTEM_NAME 这样的变量的值为“Android”,并且此处其他答案中的变量 WIN32 未定义。但我想知道我的主机系统是否是 Windows,因为在 Windows、Linux 或 IO 上进行编译时,我需要做一些不同的事情。为此,我使用了 CMAKE_HOST_SYSTEM_NAME ,我发现它在任何地方都几乎不为人知或提及,因为对于大多数人来说,TARGEt 和 HOST 是相同的,或者他们不关心。

希望这对某个地方的人有帮助......


Cas*_*des 6

生成器表达式也是可能的:

target_link_libraries(
    target_name
    PUBLIC
        libA
        $<$<PLATFORM_ID:Windows>:wsock32>
    PRIVATE
        $<$<PLATFORM_ID:Linux>:libB>
        libC
)
Run Code Online (Sandbox Code Playgroud)

这将在Windows上链接libA,wsock32和libC,在Linux上链接libA,libB和libC

CMake Generator表达式


tib*_*bur 5

试试看:

if(WIN32)
    set(ADDITIONAL_LIBRARIES wsock32)
else()
    set(ADDITIONAL_LIBRARIES "")
endif()

target_link_libraries(${PROJECT_NAME} bioutils ${ADDITIONAL_LIBRARIES})
Run Code Online (Sandbox Code Playgroud)

您可以在此处找到其他有用的变量.