Инструкции для ОС в CMAKE: Как это сделать?

110

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

Однако, как и ожидалось, в 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 )
Прасад
источник

Ответы:

148

Использовать

if (WIN32)
    #do something
endif (WIN32)

или

if (UNIX)
    #do something
endif (UNIX)

или

if (MSVC)
    #do something
endif (MSVC)

или похожие

см. Полезные переменные CMake и Платформа проверки CMake

Relaxxx
источник
Что используется для 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
Зил
75

Учитывая, что это такая распространенная проблема, 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

Названия платформ CMake и т. Д.

оборота mlvljr
источник
9
Спасибо за упоминание APPLE.
Виктор Сергиенко
@VictorSergienko Всегда рад помочь :)
mlvljr
3
не думайте, что unix - это linux. ссылка на сайт полезных переменных cmake для cmake_system_name. использовать Linux смешанный детектор ОС
Дон
ответ tibur лучше
don bright
1
Да, FreeBSD также пройдет (UNIX AND NOT APPLE)... и ссылка @mlvljr изменилась на: gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/ ... сейчас.
SlySven,
47

В основном

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

Обнаружить 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()
Afr
источник
2
Что используется для Solaris?
jww
1
Опечатка: MSVS должен быть MSVC. Я пытался отредактировать его для вас, но stackoverflow по какой-то причине не позволяет редактировать,
длина которого
1
Согласно документации, «ЯБЛОКО» подразумевает только то, что мы строим цель для яблока; т.е. OSX, но также iOS, watchOS и т. д. Существуют ли какие-либо способы надежного обнаружения OS X?
@Julien, если вы создаете для iOS, tvOS или watchOS, вы, скорее всего, будете использовать файл цепочки инструментов cmake, в котором должна быть какая-то переменная, которая может быть использована для достижения того, что вы ищете.
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.

Моим TARGET был 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 06