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


109

我是CMAKE的初学者。下面是一个简单的cmake文件,在mingw环境窗口中效果很好。问题显然与target_link_libraries()我链接libwsock32.a的CMAKE函数有关。在Windows中,这行得通,我得到结果。

但是,正如预期的那样,在Linux中,/usr/bin/ld将查找-lwsock32Linux OS上没有的遗嘱。

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

Answers:


147

if (WIN32)
    #do something
endif (WIN32)

要么

if (UNIX)
    #do something
endif (UNIX)

要么

if (MSVC)
    #do something
endif (MSVC)

或类似

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


Solaris的一个用途是什么?
jww

嗯,链接到页面很有帮助,但没有提到WIN32或UNIX。还有其他/类似资源吗?
rchilton1980 '17

1
啊,找到了。它提到了UNIX,WIN32以及大概所有的“同级”:cmake.org/Wiki/CMake_Checking_Platform
rchilton1980 '17

2
@ rchilton1980:页面已移动,新链接:gitlab.kitware.com/cmake/community/wikis/doc/cmake/…–
schnaader

对于任何其他想知道的人:Per legacy, the else() and endif() commands admit an optional <condition> argument. If used, it must be a verbatim repeat of the argument of the opening if command.来源:cmake.org/cmake/help/latest/command/if.html
Zyl

75

鉴于这是一个普遍的问题,所以在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()

CMake布尔逻辑文档

CMake平台名称等


9
感谢您的提及APPLE
Victor Sergienko

@VictorSergienkoВсегдарадпомочь:)
mlvljr

3
不要假设Unix是Linux。链接到cmake有用变量网站,获取cmake_system_name。使用Linux混合机箱OS检测器
唐明亮

Tibur酒店的答案是更好
唐亮

1
是的,FreeBSD也将通过(UNIX AND NOT APPLE)...,并且@mlvljr的链接已更改为:gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/…
SlySven

47

一般来说

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

检测Microsoft Windows

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

2
Solaris的一个用途是什么?
jww

1
错别字:MSVS应该是MSVC。我尝试为您进行编辑,但是由于某些原因stackoverflow不允许少于6个字符的编辑…
mchiasson

1
根据文档,“ APPLE”仅表示我们正在为苹果目标构建;例如OSX,还有iOS,watchOS等。有没有什么方法可以可靠地检测os X?

@Julien如果您要为iOS,tvOS或watchOS进行构建,则很可能会使用cmake工具链文件,该文件中应设置有某种变量,可用于实现所需的内容。
mchiasson

@Julien FWIW:cmake文档仅确认其自3.10.3
itMaxence

19

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

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

3
标准CMake方式:内部不一致 :) [尽管这是一个正确的/关键点的答案]
mlvljr

对于那些搜索,这里是名称的列表github.com/Kitware/CMake/blob/master/Modules/...
AT

STREQUAL接受变量(除字符串外)作为第一个操作数,因此可能更简洁if(CMAKE_SYSTEM_NAME STREQUAL "Linux")...
广告N

11

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

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 Generator表达式


感谢您为此添加额外的“>”。这是“ $ <$ <PLATFORM_ID:Windows>:wsock32>”
wow2006

6

试试看:

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

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

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


这很有效,因为它非常直观,所以我个人喜欢它。非常感谢你。
普拉萨德'02

2

我想将其保留在此处,因为在使用Android SDK在Windows中为Android进行编译时,我为此感到困扰。

CMake区分TARGET和HOST平台。

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

希望这可以帮助某人...


-5

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

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

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

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


6
用户要求CMake makefile。
tibur
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.