CMAKE 中的操作系统特定说明:操作方法

OS specific instructions in CMAKE: How to?

本文关键字:说明 操作方法 操作系统 CMAKE      更新时间:2023-10-16

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

但是,正如预期的那样,在Linux中,/usr/bin/ld将查找Linux操作系统上不存在的-lwsock32

我的问题是:如何指示 CMAKE 避免在 Linux 操作系统中链接 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 )

使用

if (WIN32)
    # do something
endif (WIN32)

if (UNIX)
    # do something
endif (UNIX)

if (MSVC)
    # do something
endif (MSVC)

或类似

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

鉴于这是一个如此普遍的问题,geronto-posting:

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()

CMake 布尔逻辑文档

CMake 平台名称等

一般

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

检测Microsoft窗口

if(WIN32)
    # for Windows operating system in general
endif()

或:

if(MSVC OR MSYS OR MINGW)
    # for detecting Windows compilers
endif()

检测苹果 MacOS

if(APPLE)
    # for MacOS X or iOS, watchOS, tvOS (since 3.10.3)
endif()

检测 Unix 和 Linux

if(UNIX AND NOT APPLE)
    # for Linux, BSD, Solaris, Minix
endif()

您的特定链接器问题

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

if(WIN32)
    target_link_libraries(${PROJECT_NAME} bioutils wsock32)
else
    target_link_libraries(${PROJECT_NAME} bioutils)
endif()

您有一些来自CMAKE的特殊词,请看:

if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
    // do something for Linux
else
    // do something for other OS

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

target_link_libraries(
    target_name
    PUBLIC
        libA
        $<$<PLATFORM_ID:Windows>:wsock32>
    PRIVATE
        $<$<PLATFORM_ID:Linux>:libB>
        libC
)

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

CMake 生成器表达式

Modern CMake Way

避免使用WIN32APPLE等。 版主在官方论坛上的回复摘录:

WIN32APPLEUNIX等变量被"软"弃用 [...] CMAKE_SYSTEM_NAME 是我在 CMake 代码中使用的,PLATFORM_ID在生成器表达式中是必需的。

CMAKE_SYSTEM_NAMEPLAFORM_ID可以采用哪些可能的值? 参考来源。

如何检测平台

使用STREQUAL

if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
  # Linux-specific stuff
endif ()

如何检测多个平台

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

set(OPENGL_PLATFORMS Linux Windows)
if (CMAKE_SYSTEM_NAME IN_LIST OPENGL_PLATFORMS)
  # platform-specific stuff e.g.
  find_package(OpenGL REQUIRED)
endif ()

生成器表达式

使用PLATFORM_ID

target_link_libraries(TARGET_NAME PRIVATE
  $<$<PLATFORM_ID:Linux,Windows>:OpenGL::GL>)

旁白:生成器表达式只能在手册调用时使用。 例如target_link_libraries的文档调用了它,而set_target_properties没有。 我会阅读 CMake:set_target_properties 在生成器表达式定义的目标下失败以了解原因。

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

CMake 区分了 TARGET 和 HOST 平台。

我的目标是Android,所以像CMAKE_SYSTEM_NAME这样的变量的值为"Android",而这里另一个答案中的变量WIN32没有定义。但我想知道我的主机系统是否是Windows,因为我在Windows,Linux或IO上编译时需要做一些不同的事情。为此,我使用了CMAKE_HOST_SYSTEM_NAME我发现在任何地方都鲜为人知或提及,因为对于大多数人来说,TARGEt 和 HOST 是相同的,或者他们不在乎。

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

试试:

if(WIN32)
    set(ADDITIONAL_LIBRARIES wsock32)
else()
    set(ADDITIONAL_LIBRARIES "")
endif()
target_link_libraries(${PROJECT_NAME} bioutils ${ADDITIONAL_LIBRARIES})

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

简单

target_link_libraries(${PROJECT_NAME}
  aaa
  bbb
  ccc
  $<$<BOOL:$<PLATFORM_ID:Linux>>:rt>
  $<$<BOOL:$<PLATFORM_ID:Linux>>:dl>
  )

使用一些预处理器宏来检查它是在Windows还是Linux中。例如

#ifdef WIN32
LIB= 
#elif __GNUC__
LIB=wsock32
#endif

在构建命令中包含 -l$(LIB(。

您还可以指定一些命令行参数来区分两者。