Hướng dẫn cụ thể về hệ điều hành trong CMAKE: Làm thế nào để?


108

Tôi là người mới bắt đầu CMAKE. Dưới đây là một tệp cmake đơn giản hoạt động tốt trong các cửa sổ môi trường mingw. Vấn đề rõ ràng là với target_link_libraries()chức năng của CMAKE nơi tôi đang liên kết libwsock32.a. Trong cửa sổ điều này hoạt động và tôi nhận được kết quả.

Tuy nhiên, như mong đợi, trong Linux, /usr/bin/ldý muốn tìm kiếm -lwsock32KHÔNG có trên Hệ điều hành Linux.

Vấn đề của tôi là: Làm cách nào để hướng dẫn CMAKE tránh liên kết thư viện wsock32 trong Hệ điều hành Linux ???

Chúng tôi rất trân trọng bất kỳ sự giúp đỡ nào.

Tệp CMake đơn giản của tôi:

 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 )

Câu trả lời:


144

Sử dụng

if (WIN32)
    #do something
endif (WIN32)

hoặc là

if (UNIX)
    #do something
endif (UNIX)

hoặc là

if (MSVC)
    #do something
endif (MSVC)

hoặc tương tự

xem Các biến hữu ích của CMakeNền tảng kiểm tra CMake


Người ta sử dụng gì cho Solaris?
jww

Rất tiếc, trang được liên kết đến rất hữu ích nhưng không đề cập đến WIN32 hoặc UNIX. Bất kỳ tài nguyên nào khác / tương tự có thể?
rchilton1980

1
Ah, tìm thấy cái này. Nó đề cập đến UNIX, Win32, và có lẽ tất cả các "đồng nghiệp" của họ: cmake.org/Wiki/CMake_Checking_Platform
rchilton1980

2
@ rchilton1980: Đã chuyển trang, liên kết mới: gitlab.kitware.com/cmake/community/wikis/doc/cmake/…
schnaader

Đối với bất kỳ ai khác thắc mắc: 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.Nguồn: cmake.org/cmake/help/latest/command/if.html
Zyl

73

Cho rằng đây là một vấn đề phổ biến như vậy, ge Toronto-đăng:

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

Tài liệu logic boolean CMake

Tên nền tảng CMake, v.v.


9
Cảm ơn vì đã đề cập APPLE.
Victor Sergienko

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

3
không giả sử unix là linux. liên kết đến trang web biến hữu ích cmake cho cmake_system_name. sử dụng trình phát hiện hệ điều hành trường hợp hỗn hợp Linux
don sáng

câu trả lời của tibur là tốt hơn
don sáng

1
Vâng, FreeBSD cũng sẽ vượt qua (UNIX AND NOT APPLE)... và liên kết của @mlvljr đã thay đổi thành: gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/… ngay bây giờ.
SlySven

45

Nói chung

Bạn có thể phát hiện và chỉ định các biến cho một số hệ điều hành như vậy:

Phát hiện Microsoft Windows

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

Hoặc là:

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

Phát hiện Apple MacOS

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

Phát hiện Unix và Linux

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

Sự cố trình liên kết cụ thể của bạn

Để giải quyết vấn đề của bạn với wsock32thư viện dành riêng cho Windows , chỉ cần xóa nó khỏi các hệ thống khác, như sau:

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

2
Người ta sử dụng gì cho Solaris?
jww

1
Đánh máy: MSVS phải là MSVC. Tôi cố gắng để chỉnh sửa nó cho bạn, nhưng stackoverflow không cho phép chỉnh sửa mà ít hơn 6 ký tự đối với một số lý do ...
mchiasson

1
Theo tài liệu, "APPLE" chỉ ngụ ý rằng chúng tôi đang xây dựng cho một mục tiêu quả táo; tức là OSX, nhưng cả iOS, watchOS, v.v. Có cách nào để phát hiện os X một cách đáng tin cậy không?

@Julien nếu bạn đang xây dựng cho iOS, tvOS hoặc watchOS, rất có thể bạn sẽ sử dụng tệp chuỗi công cụ cmake, tệp này sẽ có một số loại biến được đặt trong đó có thể được sử dụng để đạt được những gì bạn đang tìm kiếm.
mchiasson

@Julien FWIW: các tài liệu cmake chỉ xác nhận rằng nó cũng bao gồm iOS, watchos, tvOS từ 3.10.3
itMaxence

19

Bạn có một số từ đặc biệt từ CMAKE, hãy xem:

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

3
Các CMake cách tiêu chuẩn: nội bộ mâu thuẫn :) [đây là một trong những quyền to-the-điểm / câu trả lời, mặc dù]
mlvljr

Đối với những người tìm kiếm, đây là danh sách các tên github.com/Kitware/CMake/blob/master/Modules/...
AT

STREQUALchấp nhận các biến (ngoài chuỗi) làm toán hạng đầu tiên, vì vậy nó có thể ngắn gọn hơnif(CMAKE_SYSTEM_NAME STREQUAL "Linux")...
Ad N

10

Biểu thức trình tạo cũng có thể:

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

Thao tác này sẽ liên kết libA, wsock32 & libC trên Windows và liên kết libA, libB & libC trên Linux

Biểu thức CMake Generator


Cảm ơn vì điều này chỉ bạn thêm ">". là "$ <$ <PLATFORM_ID: Windows>: wsock32>"
wow2006

6

Hãy thử điều đó:

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

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

Bạn có thể tìm thấy các biến hữu ích khác tại đây .


Điều này đã hoạt động và cá nhân tôi thích điều này vì nó rất trực quan. Cảm ơn rât nhiều.
Prasad

2

Tôi muốn để điều này ở đây vì tôi đã vật lộn với điều này khi biên dịch cho Android trong Windows với Android SDK.

CMake phân biệt giữa nền tảng TARGET và HOST.

TARGET của tôi là Android nên các biến như CMAKE_SYSTEM_NAME có giá trị "Android" và biến WIN32 từ câu trả lời khác ở đây không được xác định. Nhưng tôi muốn biết liệu hệ thống HOST của mình có phải là Windows hay không vì tôi cần thực hiện một số việc khác khi biên dịch trên Windows hoặc Linux hoặc IO. Để làm điều đó, tôi đã sử dụng CMAKE_HOST_SYSTEM_NAME mà tôi thấy hầu như không được biết đến hoặc được đề cập ở bất cứ đâu vì đối với hầu hết mọi người, TARGEt và HOST đều giống nhau hoặc họ không quan tâm.

Hy vọng điều này sẽ giúp ai đó ở đâu đó ...


-5

Sử dụng một số macro tiền xử lý để kiểm tra xem nó có trong windows hay linux không. Ví dụ

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

bao gồm -l $ (LIB) trong lệnh xây dựng của bạn.

Bạn cũng có thể chỉ định một số đối số dòng lệnh để phân biệt cả hai.


6
Người dùng đang yêu cầu trang điểm CMake.
tibur
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.