Instrukcje dotyczące systemu operacyjnego w CMAKE: jak to zrobić?

109

Jestem początkującym w CMAKE. Poniżej znajduje się prosty plik cmake, który dobrze działa w oknach środowiska mingw. Problem jest wyraźnie ztarget_link_libraries() funkcji CMAKE, w której łączę libwsock32.a. W oknach to działa i otrzymuję wyniki.

Jednak, zgodnie z oczekiwaniami, w Linuksie /usr/bin/ldbędzie szukać tego, -lwsock32czego NIE ma w systemie operacyjnym Linux.

Mój problem to: Jak poinstruować CMAKE, aby unikał łączenia biblioteki wsock32 w systemie Linux?

Każda pomoc będzie bardzo mile widziana.

Mój prosty plik 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 )
Prasad
źródło

Odpowiedzi:

147

Posługiwać się

if (WIN32)
    #do something
endif (WIN32)

lub

if (UNIX)
    #do something
endif (UNIX)

lub

if (MSVC)
    #do something
endif (MSVC)

lub podobne

zobacz CMake Useful Variables and CMake Checking Platform

relaxxx
źródło
Czego używa się w Solarisie?
jww
Hmm, strona, do której prowadzi link, jest pomocna, ale nie wspomina o WIN32 ani UNIX. Jakieś inne / podobne zasoby, które mogą?
rchilton1980
1
Ach, znalazłem to. Wspomina o UNIX
ie
2
@ rchilton1980: Strona przeniesiona, nowy link: gitlab.kitware.com/cmake/community/wikis/doc/cmake/ ...
schnaader
Dla każdego, kto się zastanawia: 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.Źródło: cmake.org/cmake/help/latest/command/if.html
Zyl
75

Biorąc pod uwagę, że jest to tak powszechny problem, wysyłanie geronto:

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

Dokumentacja logiki boolowskiej CMake

Nazwy platform CMake itp.

mlvljr
źródło
9
Dzięki za wzmiankę APPLE.
Victor Sergienko
@VictorSergienko Всегда рад помочь :)
mlvljr
3
nie zakładaj, że unix to Linux. link do strony z użytecznymi zmiennymi cmake dla cmake_system_name. użyj wykrywacza systemu operacyjnego dla mieszanych przypadków w systemie Linux
don jasne
odpowiedź Tibura jest lepsza
don jasne
1
Tak, FreeBSD również przejdzie (UNIX AND NOT APPLE)... a link @mlvljr zmienił się na: gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/ ... teraz.
SlySven
47

Ogólnie

Możesz wykryć i określić zmienne dla kilku systemów operacyjnych, takich jak ten:

Wykryj Microsoft Windows

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

Lub:

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

Wykryj Apple MacOS

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

Wykryj Unix i Linux

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

Twój konkretny problem z łącznikiem

Aby rozwiązać problem z wsock32biblioteką specyficzną dla systemu Windows , po prostu usuń ją z innych systemów, na przykład:

if(WIN32)
    target_link_libraries(${PROJECT_NAME} bioutils wsock32)
else
    target_link_libraries(${PROJECT_NAME} bioutils)
endif()
Afr
źródło
2
Czego używa się w Solarisie?
jww
1
Literówka: MSVS powinno być MSVC. Próbowałem to dla ciebie edytować, ale stackoverflow z jakiegoś powodu nie pozwala na edycję mniejszą niż 6 znaków ...
mchiasson
1
Zgodnie z dokumentacją „APPLE” oznacza tylko, że budujemy dla celu jabłkowego; tj. OSX, ale także iOS, watchOS itp. Czy są jakieś sposoby na niezawodne wykrycie OS X?
@Julien, jeśli tworzysz na iOS, tvOS lub watchOS, najprawdopodobniej będziesz używać pliku narzędzi cmake, który powinien mieć ustawioną jakąś zmienną, której można użyć do osiągnięcia tego, czego szukasz.
mchiasson
@Julien FWIW: dokumentacja cmake tylko potwierdza, że ​​od 3.10.3
itMaxence
19

Masz kilka specjalnych słów od CMAKE, spójrz:

if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
    // do something for Linux
else
    // do something for other OS
Bruno Soares
źródło
3
Standardowy sposób CMake: wewnętrznie niespójny :) [jest to jednak jedna właściwa /
konkretna
Dla szukających, oto lista nazwisk github.com/Kitware/CMake/blob/master/Modules/ ...
AT
STREQUALakceptuje zmienne (oprócz ciągu znaków) jako pierwszy operand, więc może być bardziej zwięzłyif(CMAKE_SYSTEM_NAME STREQUAL "Linux")...
Ad N,
11

Możliwe są również wyrażenia generatora:

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

Spowoduje to połączenie libA, wsock32 i libC w systemie Windows oraz połączenie libA, libB i libC w systemie Linux

Wyrażenia generatora CMake

Kaskady
źródło
Dzięki za to, po prostu dodasz ">". czyli „$ <$ <PLATFORM_ID: Windows>: wsock32>”
wow2006,
6

Spróbuj tego:

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

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

Możesz znaleźć inne przydatne zmienne tutaj .

Tibur
źródło
To zadziałało i osobiście podoba mi się to, ponieważ jest bardzo intuicyjne. Dziękuję Ci bardzo.
Prasad,
2

Chcę to tutaj zostawić, ponieważ zmagałem się z tym podczas kompilacji dla Androida w systemie Windows z Android SDK.

CMake rozróżnia platformy TARGET i HOST.

Moim celem był Android, więc zmienne takie jak CMAKE_SYSTEM_NAME miały wartość „Android”, a zmienna WIN32 z drugiej odpowiedzi nie została zdefiniowana. Ale chciałem wiedzieć, czy moim systemem HOST jest Windows, ponieważ musiałem zrobić kilka rzeczy inaczej podczas kompilacji w systemie Windows, Linux lub IO. Aby to zrobić, użyłem CMAKE_HOST_SYSTEM_NAME, który, jak znalazłem, jest ledwo znany lub nigdzie wspomniany, ponieważ dla większości ludzi TARGEt i HOST są takie same lub ich to nie obchodzi.

Mam nadzieję, że to pomoże komuś gdzieś ...

Nico Heidtke
źródło
-5

Użyj makra preprocesora, aby sprawdzić, czy jest w systemie Windows lub Linux. Na przykład

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

włącz -l $ (LIB) do polecenia budowania.

Możesz także określić argument wiersza poleceń, aby rozróżnić oba.

Barun Parichha
źródło
6
Użytkownik prosi o pliki makefile CMake.
Tibur