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

时间:2012-02-06 12:47:21

标签: c++ linux cmake mingw portability

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

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

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

8 个答案:

答案 0 :(得分:86)

使用

if (WIN32)
    #do something
endif (WIN32)

if (UNIX)
    #do something
endif (UNIX)

if (MSVC)
    #do something
endif (MSVC)

或类似的

CMake Useful VariablesCMake Checking Platform

答案 1 :(得分:51)

鉴于这是一个常见问题,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 boolean logic docs

CMake platform names, etc.

答案 2 :(得分:36)

一般

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

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

您的特定链接器问题<​​/ h1>

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

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

答案 3 :(得分:10)

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

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

答案 4 :(得分:5)

试试:

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

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

您可以找到其他有用的变量here

答案 5 :(得分:2)

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

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 Expressions

答案 6 :(得分:0)

我想把它留在这里,因为在使用Android SDK在Windows中为Android编译时,我为此感到困扰。

CMake区分了TARGET和HOST平台。

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

希望这对某人有帮助...

答案 7 :(得分:-4)

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

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

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

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