Инструкции для ОС в 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


Что используется для 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 и т. Д.


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

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.