Інструкції для ОС в CMAKE: Як?


108

Я новачок у CMAKE. Нижче наведено простий файл cmake, який добре працює у вікнах середовища mingw. Проблема явно полягає у target_link_libraries()роботі CMAKE, де я посилаюся на libwsock32.a. У вікнах це працює, і я отримую результати.

Однак, як і очікувалося, в Linux, /usr/bin/ldпошук, -lwsock32якого НЕ існує в ОС Linux.

Моя проблема полягає в тому, як я вказую CMAKE уникати зв’язування бібліотеки wsock32 в ОС Linux ???

Будь-яка допомога буде вдячна.

Мій простий файл 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 )

Відповіді:


144

Використовуйте

if (WIN32)
    #do something
endif (WIN32)

або

if (UNIX)
    #do something
endif (UNIX)

або

if (MSVC)
    #do something
endif (MSVC)

або подібне

див. корисні змінні CMake та платформу перевірки CMake


Що використовується для Solaris?
jww

Хм, посилання на сторінку корисно, але не згадує ні WIN32, ні UNIX. Будь-які інші / подібні ресурси, які можуть?
rchilton1980

1
Ах, знайшов це. У ньому згадуються UNIX, WIN32 та, мабуть, усі їх "однолітки": cmake.org/Wiki/CMake_Checking_Platform
rchilton1980

2
@ rchilton1980: Сторінку переміщено, нове посилання: gitlab.kitware.com/cmake/community/wikis/doc/cmake/…
schnaader

Для тих, хто цікавиться: 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.Джерело: cmake.org/cmake/help/latest/command/if.html
Zyl

73

З огляду на це таке поширене питання, геронто-розміщення:

    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

Назви платформ CMake тощо.


9
Дякую за згадку APPLE.
Віктор Сергієнко

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

3
не припускайте, що unix є Linux. посилання на веб-сайт корисних змінних cmake для cmake_system_name. використовуйте детектор ОС для змішаного корпусу Linux
дон яскравий

Відповідь тибура краща
дон яскравий

1
Так, FreeBSD також пройде (UNIX AND NOT APPLE)... і посилання @mlvljr змінилося на: gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/… зараз.
SlySven

45

В загальному

Ви можете виявити та вказати змінні для декількох операційних систем, наприклад:

Виявлення Microsoft Windows

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

Або:

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

Виявити Apple MacOS

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

Виявити Unix та Linux

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

Ваша конкретна проблема з компонуванням

Щоб вирішити проблему з wsock32бібліотекою Windows , просто видаліть її з інших систем, наприклад:

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

2
Що використовується для Solaris?
jww

1
Помилка: MSVS має бути MSVC. Я намагався відредагувати його для вас, але
stackoverflow

1
Згідно з документацією, "APPLE" лише означає, що ми будуємо для яблучної мішені; тобто OSX, а також iOS, watchOS тощо. Чи існують способи надійного виявлення OS X?

@Julien, якщо ви будуєте для iOS, tvOS або watchOS, ви, швидше за все, будете використовувати файл cmake toolchain, який повинен мати там якусь змінну, яка може бути використана для досягнення того, що ви шукаєте.
mchiasson

@Julien FWIW: документація cmake лише підтверджує, що вона також включає iOS, watchOS, tvOS з 3.10.3
itMaxence

19

У вас є кілька спеціальних слів від CMAKE, погляньте:

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

3
Стандартний спосіб CMake: внутрішньо-суперечливий :) [правда, це одна відповідь прямо /
точно

Для тих , хто шукає, ось список імен github.com/Kitware/CMake/blob/master/Modules / ...
AT

STREQUALприймає змінні (на додаток до рядка) як перший операнд, тому він може бути більш стислимif(CMAKE_SYSTEM_NAME STREQUAL "Linux")...
Ad N

11

Також можливі вирази генератора:

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

Це зв’яже libA, wsock32 & libC у Windows та libA, libB & libC у Linux

Вирази генератора CMake


Дякуємо за це, просто додайте додаткове ">". що "$ <$ <PLATFORM_ID: Windows>: wsock32>"
wow2006,

6

Спробуйте:

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

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

Інші корисні змінні ви можете знайти тут .


Це спрацювало, і мені особисто це подобається, оскільки це дуже інтуїтивно. Велике спасибі.
Прасад

2

Я хочу залишити це тут, оскільки я боровся з цим, компілюючи для Android у Windows за допомогою Android SDK.

CMake розрізняє платформу TARGET та HOST.

Мій ЦІЛЬ був Android, тому змінні, такі як CMAKE_SYSTEM_NAME, мали значення "Android", а змінна WIN32 з іншої відповіді тут не була визначена. Але я хотів дізнатись, чи моєю системою HOST є Windows, тому що мені потрібно було зробити кілька речей по-іншому під час компіляції в Windows, Linux або IO. Для цього я використав CMAKE_HOST_SYSTEM_NAME, який, як я виявив, ледь відомий або де-небудь згадується, оскільки для більшості людей TARGEt і HOST однакові, або їм це байдуже.

Сподіваюся, це комусь десь допомагає ...


-5

Використовуйте якийсь макрос препроцесора, щоб перевірити, чи є він у Windows або Linux. Наприклад

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

включіть -l $ (LIB) в команду побудови.

Ви також можете вказати якийсь аргумент командного рядка, щоб розрізнити обидва.


6
Користувач запитує файли make-файлів CMake.
tibur
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.