CMAKE 中的 OS 特定指令:如何操作?

2024-10-18 09:00:00
admin
原创
189
摘要:问题描述:我是 CMAKE 的新手。下面是一个简单的 cmake 文件,它在 mingw 环境 windows 中运行良好。问题显然出在target_link_libraries()CMAKE 函数上,我正在链接 libwsock32.a。在 windows 中,这有效,我得到了结果。然而,正如预期的那样,在...

问题描述:

我是 CMAKE 的新手。下面是一个简单的 cmake 文件,它在 mingw 环境 windows 中运行良好。问题显然出在target_link_libraries()CMAKE 函数上,我正在链接 libwsock32.a。在 windows 中,这有效,我得到了结果。

然而,正如预期的那样,在 Linux 中,/usr/bin/ld将会寻找-lwsock32Linux 操作系统上不存在的内容。

我的问题是:如何指示 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 )

解决方案 1:

使用

if (WIN32)
    # do something
endif (WIN32)

或者

if (UNIX)
    # do something
endif (UNIX)

或者

if (MSVC)
    # do something
endif (MSVC)

或类似

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

解决方案 2:

鉴于这是一个常见的问题,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 平台名称等

解决方案 3:

一般来说

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

检测 Microsoft Windows

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

或者:

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

检测 Apple 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()

解决方案 4:

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

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

解决方案 5:

现代 CMake 方式

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

WIN32、、、APPLE等变量UNIX是“软”弃用的[...]CMAKE_SYSTEM_NAME是我在 CMake 代码中使用的,PLATFORM_ID在生成器表达式中是需要的。

CMAKE_SYSTEM_NAME可以或PLAFORM_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 因生成器表达式定义的目标而失败,才能明白原因。

解决方案 6:

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

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 生成器表达式

解决方案 7:

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

CMake 区分 TARGET 和 HOST 平台。

我的 TARGET 是 Android,因此 CMAKE_SYSTEM_NAME 等变量的值为“Android”,而此处其他答案中的变量 WIN32 未定义。但我想知道我的 HOST 系统是否是 Windows,因为在 Windows、Linux 或 IO 上编译时我需要做一些不同的事情。为此,我使用了 CMAKE_HOST_SYSTEM_NAME,我发现它几乎不为人所知或从未被提及,因为对于大多数人来说,TARGEt 和 HOST 是相同的,或者他们不关心。

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

解决方案 8:

尝试一下:

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

target_link_libraries(${PROJECT_NAME} bioutils ${ADDITIONAL_LIBRARIES})

您可以在这里找到其他有用的变量。

解决方案 9:

简单喜欢

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

解决方案 10:

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

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

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

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

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1120  
  IPD(Integrated Product Development,集成产品开发)流程是一种广泛应用于高科技和制造业的产品开发方法论。它通过跨职能团队的紧密协作,将产品开发周期缩短,同时提高产品质量和市场成功率。在IPD流程中,CDCP(Concept Decision Checkpoint,概念决策检查点)是一个关...
IPD培训课程   75  
  研发IPD(集成产品开发)流程作为一种系统化的产品开发方法,已经在许多行业中得到广泛应用。它不仅能够提升产品开发的效率和质量,还能够通过优化流程和资源分配,显著提高客户满意度。客户满意度是企业长期成功的关键因素之一,而IPD流程通过其独特的结构和机制,能够确保产品从概念到市场交付的每个环节都围绕客户需求展开。本文将深入...
IPD流程   66  
  IPD(Integrated Product Development,集成产品开发)流程是一种以跨职能团队协作为核心的产品开发方法,旨在通过优化资源分配、提高沟通效率以及减少返工,从而缩短项目周期并提升产品质量。随着企业对产品上市速度的要求越来越高,IPD流程的应用价值愈发凸显。通过整合产品开发过程中的各个环节,IPD...
IPD项目管理咨询   76  
  跨部门沟通是企业运营中不可或缺的一环,尤其在复杂的产品开发过程中,不同部门之间的协作效率直接影响项目的成败。集成产品开发(IPD)作为一种系统化的项目管理方法,旨在通过优化流程和增强团队协作来提升产品开发的效率和质量。然而,跨部门沟通的复杂性往往成为IPD实施中的一大挑战。部门之间的目标差异、信息不对称以及沟通渠道不畅...
IPD是什么意思   70  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用