Instruksi khusus OS di CMAKE: Bagaimana caranya?

109

Saya seorang pemula CMAKE. Di bawah ini adalah file cmake sederhana yang berfungsi dengan baik di jendela lingkungan mingw. Masalahnya jelas dengan target_link_libraries()fungsi CMAKE di mana saya menghubungkan libwsock32.a. Di jendela ini berfungsi dan saya mendapatkan hasilnya.

Namun, seperti yang diharapkan, di Linux, /usr/bin/ldpencarian -lwsock32yang TIDAK ada di OS Linux.

Masalah saya adalah: Bagaimana cara menginstruksikan CMAKE untuk menghindari menautkan pustaka wsock32 di OS Linux ???

Bantuan apa pun akan sangat dihargai.

File CMake Sederhana saya:

 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
sumber

Jawaban:

147

Menggunakan

if (WIN32)
    #do something
endif (WIN32)

atau

if (UNIX)
    #do something
endif (UNIX)

atau

if (MSVC)
    #do something
endif (MSVC)

atau serupa

lihat Variabel Berguna CMake dan Platform Pemeriksaan CMake

relaxxx
sumber
Apa yang digunakan untuk Solaris?
jww
Hmm, halaman tertaut bermanfaat tetapi tidak menyebutkan WIN32 atau UNIX. Sumber daya lain / serupa yang mungkin?
rchilton1980
1
Ah, ketemu ini. Ini menyebutkan UNIX, WIN32, dan mungkin semua "rekan" mereka: cmake.org/Wiki/CMake_Checking_Platform
rchilton1980
2
@ rchilton1980: Halaman dipindahkan, tautan baru: gitlab.kitware.com/cmake/community/wikis/doc/cmake/…
schnaader
Bagi orang lain yang bertanya-tanya: 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.Sumber: cmake.org/cmake/help/latest/command/if.html
Zyl
75

Mengingat ini adalah masalah yang umum, 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()

Dokumentasi logika boolean CMake

Nama platform CMake, dll.

mlvljr
sumber
9
Terima kasih telah menyebutkan APPLE.
Victor Sergienko
@VictorSergienko Всегда рад помочь :)
mlvljr
3
jangan berasumsi unix adalah linux. tautan ke situs web variabel yang berguna cmake untuk cmake_system_name. menggunakan detektor Linux kasus campuran OS
jangan terang
Jawaban tibur lebih baik
jangan terang
1
Ya, FreeBSD juga akan lewat (UNIX AND NOT APPLE)... dan tautan @mlvljr telah berubah menjadi: gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/… sekarang.
SlySven
47

Secara umum

Anda dapat mendeteksi dan menentukan variabel untuk beberapa sistem operasi seperti itu:

Deteksi Microsoft Windows

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

Atau:

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

Deteksi Apple MacOS

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

Deteksi Unix dan Linux

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

Masalah linker spesifik Anda

Untuk mengatasi masalah Anda dengan wsock32pustaka khusus Windows , hapus saja dari sistem lain, seperti itu:

if(WIN32)
    target_link_libraries(${PROJECT_NAME} bioutils wsock32)
else
    target_link_libraries(${PROJECT_NAME} bioutils)
endif()
Afr
sumber
2
Apa yang digunakan untuk Solaris?
jww
1
Salah ketik: MSVS harus MSVC. Saya mencoba mengeditnya untuk Anda tetapi stackoverflow tidak mengizinkan pengeditan yang kurang dari 6 karakter karena alasan tertentu ...
mchiasson
1
Menurut dokumentasi, "APPLE" hanya menyiratkan, bahwa kita sedang membangun untuk target apel; yaitu OSX, tetapi juga iOS, watchOS, dll. Apakah ada cara untuk mendeteksi os X dengan cara yang andal?
@Julien jika Anda membuat untuk iOS, tvOS atau watchOS, kemungkinan besar Anda akan menggunakan file toolchain cmake, yang seharusnya memiliki beberapa jenis variabel yang disetel di sana yang dapat digunakan untuk mencapai apa yang Anda cari.
mchiasson
@Julien FWIW: dokumentasi cmake hanya mengonfirmasi bahwa itu juga mencakup iOS, watchOS, tvOS sejak 3.10.3
itMaxence
19

Anda memiliki beberapa kata khusus dari CMAKE, lihat:

if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
    // do something for Linux
else
    // do something for other OS
Bruno Soares
sumber
3
Cara CMake standar: secara internal-tidak konsisten :) [ini adalah satu jawaban yang benar / langsung, meskipun]
mlvljr
Bagi yang mencari, berikut adalah daftar nama github.com/Kitware/CMake/blob/master/Modules/…
AT
STREQUALmenerima variabel (selain string) sebagai operan pertama, jadi bisa lebih ringkasif(CMAKE_SYSTEM_NAME STREQUAL "Linux")...
Ad N
11

Ekspresi generator juga dimungkinkan:

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

Ini akan menautkan libA, wsock32 & libC di Windows dan menautkan libA, libB & libC di Linux

Ekspresi Generator CMake

Cascades
sumber
Terima kasih untuk ini, tambahkan saja ">" ekstra. yaitu "$ <$ <PLATFORM_ID: Windows>: wsock32>"
wow2006
6

Coba itu:

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

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

Anda dapat menemukan variabel berguna lainnya di sini .

tibur
sumber
Ini berhasil dan saya pribadi suka ini karena sangat intuitif. Terima kasih banyak.
Prasad
2

Saya ingin meninggalkan ini di sini karena saya kesulitan dengan ini ketika menyusun untuk Android di Windows dengan Android SDK.

CMake membedakan antara platform TARGET dan HOST.

TARGET saya adalah Android jadi variabel seperti CMAKE_SYSTEM_NAME memiliki nilai "Android" dan variabel WIN32 dari jawaban lain di sini tidak ditentukan. Tetapi saya ingin tahu apakah sistem HOST saya adalah Windows karena saya perlu melakukan beberapa hal secara berbeda saat mengompilasi pada Windows atau Linux atau IOs. Untuk melakukan itu saya menggunakan CMAKE_HOST_SYSTEM_NAME yang saya temukan hampir tidak dikenal atau disebutkan di mana saja karena bagi kebanyakan orang TARGEt dan HOST sama atau mereka tidak peduli.

Semoga ini bisa membantu seseorang di suatu tempat ...

Nico Heidtke
sumber
-5

Gunakan beberapa makro preprocessor untuk memeriksa apakah itu ada di windows atau linux. Sebagai contoh

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

sertakan -l $ (LIB) di perintah build Anda.

Anda juga dapat menentukan beberapa argumen baris perintah untuk membedakan keduanya.

Barun Parichha
sumber
6
Pengguna meminta file makefile CMake.
tibur