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 )
Prasad
la source

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

relaxxx
la source
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.

mlvljr
la source
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()
Afr
la source
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
Bruno Soares
la source
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

Cascades
la source
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 .

tibur
la source
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 ...

Nico Heidtke
la source
-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.

Barun Parichha
la source
6
L'utilisateur demande des makefiles CMake.
tibur