Instrucciones específicas del sistema operativo en CMAKE: ¿Cómo?

108

Soy un principiante en CMAKE. A continuación se muestra un archivo cmake simple que funciona bien en las ventanas del entorno mingw. El problema es claramente con la target_link_libraries()función de CMAKE donde estoy vinculando libwsock32.a. En Windows esto funciona y obtengo los resultados.

Sin embargo, como se esperaba, en Linux, /usr/bin/ldbuscará -lwsock32cuál NO está en el sistema operativo Linux.

Mi problema es: ¿Cómo le indico a CMAKE que evite vincular la biblioteca wsock32 en el sistema operativo Linux?

Cualquier ayuda será apreciada.

Mi archivo CMake simple:

 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 )
Prasad
fuente

Respuestas:

144

Utilizar

if (WIN32)
    #do something
endif (WIN32)

o

if (UNIX)
    #do something
endif (UNIX)

o

if (MSVC)
    #do something
endif (MSVC)

o similar

consulte Variables útiles de CMake y Plataforma de comprobación de CMake

relaxxx
fuente
¿Qué se usa para Solaris?
jww
Mmm, la página vinculada es útil pero no menciona ni WIN32 ni UNIX. ¿Algún otro recurso similar que pueda?
rchilton1980
1
Ah, encontré esto. Menciona UNIX, WIN32 y presumiblemente todos sus "pares": cmake.org/Wiki/CMake_Checking_Platform
rchilton1980
2
@ rchilton1980: Página movida, nuevo enlace: gitlab.kitware.com/cmake/community/wikis/doc/cmake/…
schnaader
Para cualquiera que se pregunte: 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.Fuente: cmake.org/cmake/help/latest/command/if.html
Zyl
73

Dado que este es un problema tan común, geronto-post:

    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 documentos de lógica booleana

Nombres de plataformas de CMake, etc.

mlvljr
fuente
9
Gracias por mencionar APPLE.
Victor Sergienko
@VictorSergienko Всегда рад помочь :)
mlvljr
3
no asuma que Unix es Linux. enlace al sitio web de variables útiles cmake para cmake_system_name. el uso de Linux detector de mayúsculas y minúsculas OS
don brillante
la respuesta de tibur es mejor
don bright
1
Sí, FreeBSD también pasará (UNIX AND NOT APPLE)... y el enlace de @mlvljr ha cambiado a: gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/… ahora.
SlySven
45

En general

Puede detectar y especificar variables para varios sistemas operativos como ese:

Detectar Microsoft Windows

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

O:

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

Detectar Apple MacOS

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

Detecta Unix y Linux

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

Su problema específico del vinculador

Para resolver su problema con la wsock32biblioteca específica de Windows , simplemente elimínela de otros sistemas, así:

if(WIN32)
    target_link_libraries(${PROJECT_NAME} bioutils wsock32)
else
    target_link_libraries(${PROJECT_NAME} bioutils)
endif()
Afr
fuente
2
¿Qué se usa para Solaris?
jww
1
Error tipográfico: MSVS debería ser MSVC. Traté de editarlo por usted, pero stackoverflow no permite ediciones de menos de 6 caracteres por alguna razón ...
mchiasson
1
Según la documentación, "APPLE" solo implica que estamos construyendo para un objetivo de Apple; es decir, OSX, pero también iOS, watchOS, etc. ¿Hay alguna forma de detectar OS X de forma fiable?
@Julien, si está compilando para iOS, tvOS o watchOS, lo más probable es que use un archivo de cadena de herramientas de cmake, que debería tener algún tipo de variable establecida allí que podría usarse para lograr lo que está buscando.
mchiasson
@Julien FWIW: la documentación de cmake solo confirma que también incluye iOS, watchOS, tvOS desde 3.10.3
itMaxence
19

Tienes algunas palabras especiales de CMAKE, échale un vistazo:

if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
    // do something for Linux
else
    // do something for other OS
Bruno Soares
fuente
3
La forma estándar de CMake: internamente inconsistente :) [aunque esta es una respuesta correcta / al grano]
mlvljr
Para aquellos que buscan, aquí está la lista de nombres github.com/Kitware/CMake/blob/master/Modules/…
AT
STREQUALacepta variables (además de la cadena) como primer operando, por lo que podría ser más concisoif(CMAKE_SYSTEM_NAME STREQUAL "Linux")...
Anuncio N
11

Las expresiones generadoras también son posibles:

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

Esto vinculará libA, wsock32 y libC en Windows y vinculará libA, libB y libC en Linux

Expresiones del generador de CMake

Cascadas
fuente
Gracias por esto, solo agrega ">" extra. que es "$ <$ <PLATFORM_ID: Windows>: wsock32>"
wow2006
6

Trata eso:

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

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

Puede encontrar otras variables útiles aquí .

tibur
fuente
Esto funcionó y personalmente me gusta esto ya que es muy intuitivo. Muchas gracias.
Prasad
2

Quiero dejar esto aquí porque tuve problemas con esto al compilar para Android en Windows con el SDK de Android.

CMake distingue entre plataforma TARGET y HOST.

Mi OBJETIVO era Android, por lo que las variables como CMAKE_SYSTEM_NAME tenían el valor "Android" y la variable WIN32 de la otra respuesta aquí no estaba definida. Pero quería saber si mi sistema HOST era Windows porque necesitaba hacer algunas cosas de manera diferente al compilar en Windows, Linux o IO. Para hacer eso, utilicé CMAKE_HOST_SYSTEM_NAME que encontré que apenas se conoce o se menciona en ninguna parte porque para la mayoría de las personas TARGEt y HOST son lo mismo o no les importa.

Espero que esto ayude a alguien en algún lugar ...

Nico Heidtke
fuente
-5

Use alguna macro de preprocesador para verificar si está en Windows o Linux. Por ejemplo

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

incluya -l $ (LIB) en su comando de compilación.

También puede especificar algún argumento de línea de comando para diferenciar ambos.

Barun Parichha
fuente
6
El usuario solicita archivos MAKE de CMake.
tibur