คำแนะนำเฉพาะระบบปฏิบัติการใน CMAKE: ทำอย่างไร?


116

ฉันเป็นมือใหม่กับ CMAKE ด้านล่างนี้เป็นไฟล์ cmake แบบธรรมดาซึ่งทำงานได้ดีในหน้าต่างสภาพแวดล้อม mingw ปัญหาชัดเจนกับtarget_link_libraries()ฟังก์ชันของ CMAKE ที่ฉันเชื่อมโยง libwsock32.a ใน windows สิ่งนี้ใช้งานได้และฉันได้รับผลลัพธ์

อย่างไรก็ตามตามที่คาดไว้ใน Linux /usr/bin/ldจะมองหา-lwsock32สิ่งที่ไม่มีใน Linux OS

ปัญหาของฉันคือ: ฉันจะสั่งให้ CMAKE หลีกเลี่ยงการเชื่อมโยงไลบรารี wsock32 ใน Linux OS ได้อย่างไร ???

ความช่วยเหลือใด ๆ จะได้รับการชื่นชมอย่างมาก

ไฟล์ Simple 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 )

คำตอบ:


156

ใช้

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

77

เนื่องจากนี่เป็นปัญหาทั่วไปการโพสต์บนเว็บไซต์:

    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ขอขอบคุณสำหรับการกล่าวขวัญ
Victor Sergienko

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

3
อย่าถือว่า unix เป็น linux ลิงก์ไปยังเว็บไซต์ตัวแปรที่มีประโยชน์ของ cmake สำหรับ cmake_system_name ใช้เครื่องตรวจจับระบบปฏิบัติการกรณีผสม Linux
อย่าสว่าง

คำตอบของ tibur ดีกว่า
อย่าสดใส

1
ใช่ FreeBSD ก็จะผ่านไป(UNIX AND NOT APPLE)... และลิงก์ของ @mlvljr ได้เปลี่ยนเป็น: gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/…ในขณะนี้
SlySven

49

โดยทั่วไป

คุณสามารถตรวจจับและระบุตัวแปรสำหรับระบบปฏิบัติการต่างๆเช่น:

ตรวจหา 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 ไม่อนุญาตให้แก้ไขที่มีอักขระน้อยกว่า 6 ตัวด้วยเหตุผลบางประการ ...
mchiasson

1
ตามเอกสาร "APPLE" บอกเป็นนัย ๆ เท่านั้นว่าเรากำลังสร้างเป้าหมายแอปเปิ้ล เช่น OSX แต่ยังรวมถึง iOS, watchOS เป็นต้นมีวิธีใดบ้างในการตรวจจับ os X ด้วยวิธีที่เชื่อถือได้?

@ Julien หากคุณกำลังสร้างสำหรับ iOS, tvOS หรือ watchOS คุณมักจะใช้ไฟล์ cmake toolchain ซึ่งควรมีตัวแปรบางอย่างที่สามารถใช้เพื่อให้บรรลุสิ่งที่คุณกำลังมองหา
mchiasson

@Julien FWIW: เอกสาร cmakeยืนยันเพียงว่ารวม iOS, watchOS, tvOS ตั้งแต่3.10.3
itMaxence

20

คุณมีคำพิเศษจาก CMAKE โปรดดู:

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

3
วิธีมาตรฐาน CMake: ไม่สอดคล้องกันภายใน :) [นี่เป็นคำตอบที่ถูกต้อง / ตรงประเด็นเท่านั้น]
mlvljr

เพื่อการค้นหาเหล่านั้นนี่คือรายการของชื่อgithub.com/Kitware/CMake/blob/master/Modules/...
AT

STREQUALยอมรับตัวแปร (นอกเหนือจากสตริง) เป็นตัวถูกดำเนินการตัวแรกดังนั้นจึงมีความกระชับมากขึ้นif(CMAKE_SYSTEM_NAME STREQUAL "Linux")...
โฆษณา N

13

นอกจากนี้ยังมีนิพจน์เครื่องกำเนิดไฟฟ้า:

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 Generator


ขอบคุณสำหรับสิ่งนี้ที่คุณเพิ่มพิเศษ ">" ซึ่งก็คือ "$ <$ <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})

คุณสามารถค้นหาตัวแปรที่มีประโยชน์อื่น ๆที่นี่


สิ่งนี้ได้ผลและฉันชอบสิ่งนี้เป็นการส่วนตัวเนื่องจากใช้งานง่ายมาก ขอบคุณมาก.
ประสาท

3

ฉันต้องการออกจากที่นี่เพราะฉันประสบปัญหานี้เมื่อรวบรวมสำหรับ 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) ในคำสั่ง build ของคุณ

คุณยังสามารถระบุอาร์กิวเมนต์บรรทัดคำสั่งเพื่อแยกความแตกต่างทั้งสองได้


6
ผู้ใช้กำลังขอ CMake makefiles
tibur
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.