Istruzioni specifiche del sistema operativo in CMAKE: come?


108

Sono un principiante di CMAKE. Di seguito è riportato un semplice file cmake che funziona bene nelle finestre dell'ambiente mingw. Il problema è chiaramente con la target_link_libraries()funzione di CMAKE in cui sto collegando libwsock32.a. In Windows funziona e ottengo i risultati.

Tuttavia, come previsto, in Linux, la /usr/bin/ldricerca -lwsock32NON è presente sul sistema operativo Linux.

Il mio problema è: come posso istruire CMAKE per evitare di collegare la libreria wsock32 nel sistema operativo Linux ???

Qualsiasi aiuto sarà molto apprezzato.

Il mio file CMake semplice:

 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 )

Risposte:


144

Uso

if (WIN32)
    #do something
endif (WIN32)

o

if (UNIX)
    #do something
endif (UNIX)

o

if (MSVC)
    #do something
endif (MSVC)

o simili

vedere Variabili utili di CMake e Piattaforma di controllo CMake


Cosa si usa per Solaris?
jww

Hmm, la pagina collegata è utile ma non menziona né WIN32 né UNIX. Eventuali altre risorse simili che potrebbero?
rchilton1980

1
Ah, ho trovato questo. Menziona UNIX, WIN32 e presumibilmente tutti i loro "pari": cmake.org/Wiki/CMake_Checking_Platform
rchilton1980

2
@ rchilton1980: Pagina spostata, nuovo collegamento: gitlab.kitware.com/cmake/community/wikis/doc/cmake/…
schnaader

Per chiunque altro si chieda : 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.Fonte: cmake.org/cmake/help/latest/command/if.html
Zyl

73

Dato che questo è un problema così comune, 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

Nomi delle piattaforme CMake, ecc.


9
Grazie per averlo menzionato APPLE.
Victor Sergienko

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

3
non dare per scontato che unix sia linux. collegamento al sito Web di variabili utili cmake per cmake_system_name. usa il rilevatore di sistemi operativi con case miste Linux
don brillante

La risposta di tibur è migliore
don bright

1
Sì, anche FreeBSD passerà (UNIX AND NOT APPLE)... e il collegamento di @mlvljr è cambiato in: gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/… ora.
SlySven

45

In generale

Puoi rilevare e specificare variabili per diversi sistemi operativi come questo:

Rileva Microsoft Windows

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

O:

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

Rileva Apple MacOS

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

Rileva Unix e Linux

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

Il tuo problema con il linker specifico

Per risolvere il tuo problema con la wsock32libreria specifica di Windows , rimuovila da altri sistemi, in questo modo:

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

2
Cosa si usa per Solaris?
jww

1
Errore di battitura: MSVS dovrebbe essere MSVC. Ho provato a modificarlo per te ma stackoverflow non consente modifiche inferiori a 6 caratteri per qualche motivo ...
mchiasson

1
Secondo la documentazione, "APPLE" implica solo che stiamo costruendo per un target Apple; cioè OSX, ma anche iOS, watchOS ecc. Esistono modi per rilevare OS X in modo affidabile?

@Julien se stai creando per iOS, tvOS o watchOS, molto probabilmente utilizzerai un file toolchain cmake, che dovrebbe contenere una sorta di variabile impostata che potrebbe essere utilizzata per ottenere ciò che stai cercando.
mchiasson

@Julien FWIW: la documentazione di cmake conferma solo che include anche iOS, watchOS, tvOS dalla 3.10.3
itMaxence

19

Hai alcune parole speciali da CMAKE, dai un'occhiata:

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

3
Il modo CMake standard: internamente incoerente :) [questa è una risposta giusta /
precisa

Per coloro che cercano, ecco la lista dei nomi github.com/Kitware/CMake/blob/master/Modules/...
AT

STREQUALaccetta variabili (oltre alla stringa) come primo operando, quindi potrebbe essere il più concisoif(CMAKE_SYSTEM_NAME STREQUAL "Linux")...
Annuncio N

11

Sono possibili anche espressioni del generatore:

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

Questo collegherà libA, wsock32 e libC su Windows e collegherà libA, libB e libC su Linux

CMake Generator Expressions


Grazie per questo basta aggiungere ">" extra. che è "$ <$ <PLATFORM_ID: Windows>: wsock32>"
wow2006

6

Prova questo:

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

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

Puoi trovare altre variabili utili qui .


Ha funzionato e personalmente mi piace perché è molto intuitivo. Grazie mille.
Prasad

2

Voglio lasciarlo qui perché ho lottato con questo durante la compilazione per Android in Windows con Android SDK.

CMake distingue tra TARGET e piattaforma HOST.

Il mio TARGET era Android quindi le variabili come CMAKE_SYSTEM_NAME avevano il valore "Android" e la variabile WIN32 dall'altra risposta qui non era definita. Ma volevo sapere se il mio sistema HOST era Windows perché avevo bisogno di fare alcune cose in modo diverso durante la compilazione su Windows, Linux o IO. Per farlo ho usato CMAKE_HOST_SYSTEM_NAME che ho trovato a malapena conosciuto o menzionato da nessuna parte perché per la maggior parte delle persone TARGEt e HOST sono uguali o non si preoccupano.

Spero che questo aiuti qualcuno da qualche parte ...


-5

Usa qualche macro del preprocessore per verificare se è in Windows o Linux. Per esempio

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

include -l $ (LIB) nel comando di compilazione.

È inoltre possibile specificare alcuni argomenti della riga di comando per differenziarli entrambi.


6
L'utente sta chiedendo makefile CMake.
tibur
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.