Instructions spécifiques au système d'exploitation dans CMAKE: Comment faire?


108

Je suis un débutant à CMAKE. Vous trouverez ci-dessous un simple fichier cmake qui fonctionne bien dans les fenêtres d'environnement mingw. Le problème est clairement avectarget_link_libraries() fonction de CMAKE où je lie libwsock32.a. Dans Windows, cela fonctionne et j'obtiens les résultats.

Cependant, comme prévu, sous Linux, le /usr/bin/ldcherchera -lwsock32ce qui n'est PAS là sur le système d'exploitation Linux.

Mon problème est le suivant: comment demander à CMAKE d'éviter de lier la bibliothèque wsock32 sous Linux OS ???

Toute aide sera fortement appréciée.

Mon fichier 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 )

Réponses:


144

Utilisation

if (WIN32)
    #do something
endif (WIN32)

ou

if (UNIX)
    #do something
endif (UNIX)

ou

if (MSVC)
    #do something
endif (MSVC)

ou similaire

voir Variables utiles CMake et plateforme de vérification CMake


Qu'utilise-t-on pour Solaris?
jww

Hmm, la page liée est utile mais ne mentionne ni WIN32 ni UNIX. Des ressources autres / similaires qui pourraient?
rchilton1980

1
Ah, j'ai trouvé ça. Il mentionne UNIX, WIN32 et vraisemblablement tous leurs «pairs»: cmake.org/Wiki/CMake_Checking_Platform
rchilton1980

2
@ rchilton1980: Page déplacée, nouveau lien: gitlab.kitware.com/cmake/community/wikis/doc/cmake/…
schnaader

Pour quiconque se demande: 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.Source: cmake.org/cmake/help/latest/command/if.html
Zyl

73

Étant donné qu'il s'agit d'un problème si courant, 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()

Documentation sur la logique booléenne CMake

Noms des plateformes CMake, etc.


9
Merci d'avoir mentionné APPLE.
Victor Sergienko

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

3
ne supposez pas qu'unix est Linux. lien vers le site Web des variables utiles cmake pour cmake_system_name. utiliser le détecteur de système d'exploitation à cas mixte Linux
don lumineux

La réponse de tibur est meilleure
don

1
Ouais, FreeBSD passera également (UNIX AND NOT APPLE)... et le lien de @mlvljr a changé en: gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/… maintenant.
SlySven

45

En général

Vous pouvez détecter et spécifier des variables pour plusieurs systèmes d'exploitation comme celui-ci:

Détecter Microsoft Windows

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

Ou:

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

Détecter Apple MacOS

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

Détecter Unix et Linux

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

Votre problème d'éditeur de liens spécifique

Pour résoudre votre problème avec la wsock32bibliothèque spécifique à Windows , supprimez-la simplement des autres systèmes, comme ça:

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

2
Qu'utilise-t-on pour Solaris?
jww

1
Typo: MSVS doit être MSVC. J'ai essayé de le modifier pour vous mais stackoverflow n'autorise pas les modifications de moins de 6 caractères pour une raison quelconque ...
mchiasson

1
D'après la documentation, "APPLE" implique seulement que nous construisons pour une cible Apple; ie OSX, mais aussi iOS, watchOS etc. Existe-t-il des moyens de détecter os X de manière fiable?

@Julien si vous construisez pour iOS, tvOS ou watchOS, vous allez probablement utiliser un fichier de chaîne d'outils cmake, qui devrait contenir une sorte de variable qui pourrait être utilisée pour atteindre ce que vous recherchez.
mchiasson

@Julien FWIW: la documentation cmake confirme seulement qu'elle inclut également iOS, watchOS, tvOS depuis la 3.10.3
itMaxence

19

Vous avez quelques mots spéciaux de CMAKE, jetez un œil:

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

3
La méthode CMake standard: incohérente en interne :) [c'est une réponse juste /
directe

Pour ceux qui recherchent, voici la liste des noms github.com/Kitware/CMake/blob/master/Modules/…
AU

STREQUALaccepte les variables (en plus de la chaîne) comme premier opérande, donc cela pourrait être le plus concisif(CMAKE_SYSTEM_NAME STREQUAL "Linux")...
Annonce N

11

Les expressions génératrices sont également possibles:

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

Cela liera libA, wsock32 et libC sous Windows et reliera libA, libB et libC sous Linux

Expressions du générateur CMake


Merci pour cela, ajoutez simplement ">". qui est "$ <$ <PLATFORM_ID: Windows>: wsock32>"
wow2006

6

Essayez ça:

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

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

Vous pouvez trouver d'autres variables utiles ici .


Cela a fonctionné et j'aime personnellement cela car c'est très intuitif. Merci beaucoup.
Prasad

2

Je veux laisser cela ici car j'ai eu du mal avec cela lors de la compilation pour Android sous Windows avec le SDK Android.

CMake fait la distinction entre la plate-forme TARGET et HOST.

Mon TARGET était Android, donc les variables comme CMAKE_SYSTEM_NAME avaient la valeur "Android" et la variable WIN32 de l'autre réponse ici n'était pas définie. Mais je voulais savoir si mon système HOST était Windows parce que je devais faire certaines choses différemment lors de la compilation sous Windows, Linux ou IO. Pour ce faire, j'ai utilisé CMAKE_HOST_SYSTEM_NAME qui, selon moi, est à peine connu ou mentionné, car pour la plupart des gens, TARGEt et HOST sont identiques ou s'en moquent.

J'espère que cela aide quelqu'un quelque part ...


-5

Utilisez une macro de préprocesseur pour vérifier si elle est sous Windows ou Linux. Par exemple

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

incluez -l $ (LIB) dans votre commande de construction.

Vous pouvez également spécifier un argument de ligne de commande pour différencier les deux.


6
L'utilisateur demande des makefiles CMake.
tibur
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.