Trong CMake, làm cách nào để kiểm tra xem trình biên dịch có phải là Clang không?


151

Chúng tôi có một bộ các kịch bản xây dựng CMake đa nền tảng và chúng tôi hỗ trợ xây dựng với Visual C ++GCC .

Chúng tôi đang thử Clang , nhưng tôi không thể tìm ra cách kiểm tra xem trình biên dịch có phải là Clang với tập lệnh CMake của chúng tôi hay không.

Tôi nên kiểm tra xem trình biên dịch có phải là Clang hay không? Chúng tôi hiện đang sử dụng MSVCCMAKE_COMPILER_IS_GNU<LANG>để kiểm tra Visual C ++ và GCC, tương ứng.


Bạn có thể thiết lập trình biên dịch bằng cách đặt CMAKE_C_COMPILER và CMAKE_CXX_COMPILER thành đường dẫn đến clang hoặc clang ++. +1 cho tiếng kêu.
Zaffy

Tại sao bạn cần quan tâm? Clang rất giống GCC, về các tùy chọn trình biên dịch được chấp nhận ...
Basile Starynkevitch

2
@BasileStarynkevitch Vì chúng tôi đã hỗ trợ MSVC, chúng tôi cần phát hiện Clang để chúng tôi biết nên bật tùy chọn giống GCC hay tùy chọn giống MSVC. Nó đã quá dài để tôi nhớ, nhưng chắc chắn cũng có thể chúng tôi đang sử dụng các tùy chọn không được Clang hỗ trợ.
leedm777

1
@BasileStarynkevitch - Clang giả vờ là cả hai __GNUC___MSC_VER, nhưng nó không thể tiêu thụ các chương trình tương tự như một trong hai trình biên dịch. Phát hiện LLVM Clang và Apple Clang là rất quan trọng để đảm bảo mã biên dịch và thực thi như mong đợi. Tôi rất mệt mỏi khi phải làm việc với BS của Clang, chúng tôi chỉ phá vỡ phần biên dịch trên Windows . Chúng tôi đã áp dụng chính sách cho phép người dùng khiếu nại với LLVM để các nhà phát triển Clang thay đổi hành vi của họ. Xem thêm Làm thế nào để nói với Clang ngừng giả vờ là trình biên dịch khác?
jww

Câu trả lời:


242

Một kiểm tra đáng tin cậy là sử dụng các CMAKE_<LANG>_COMPILER_IDbiến. Ví dụ, để kiểm tra trình biên dịch C ++:

if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  # using Clang
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  # using GCC
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
  # using Intel C++
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
  # using Visual Studio C++
endif()

Chúng cũng hoạt động chính xác nếu một trình bao bọc trình biên dịch như ccache được sử dụng.

Kể từ CMake 3.0.0, CMAKE_<LANG>_COMPILER_IDgiá trị cho Clang do Apple cung cấp hiện đã có AppleClang. Để kiểm tra cả Clang do Apple cung cấp và Clang thông thường, hãy sử dụng các điều sau nếu có điều kiện:

if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  # using regular Clang or AppleClang
endif()

Cũng xem mô tả chính sách của AppleClang .

CMake 3.15 đã bổ sung hỗ trợ cho cả clang-cl và mặt trước clang thông thường. Bạn có thể xác định biến thể giao diện người dùng bằng cách kiểm tra biến CMAKE_CXX_COMPILER_FRONTEND_VARIANT:

if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
    # using clang with clang-cl front end
  elseif (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
    # using clang with regular front end
  endif()
endif()

Các tài liệu cmake khẳng định "này được sử dụng trong việc xác định trình biên dịch và có thể thay đổi". Nếu không, nó sẽ hoàn hảo :-(
leedm777

17
Kể từ CMake 2.8.10, biến này là (cuối cùng!) Được ghi lại. Xem: cmake.org/cmake/help/v2.8.10/ Quảng cáo
Nick Hutchinson

9
Lưu ý rằng CMAKE_CXX_COMPILER_IDbiến chỉ có sẵn sau lệnh project(Foo CXX).
waldyrious

5
Và đối với các cờ mà cả gcc và clang đều chấp nhận, tôi sử dụngif (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") ... endif()
Fred Schoen

4
Nếu bạn bối rối tại sao bạn không thể phát hiện AppleClangcụ thể, @sakra chỉ ra rằng đã cmake 3.0.0phát hànhAppleClang . Tuy nhiên, chỉ vì cmake --versioncác báo cáo bằng hoặc cao hơn là không đủ - bạn phải sử dụng cmake_minimum_required(VERSION 3.0.0)các 3.0.0tiêu chuẩn!
svenevs

2

Mã nguồn của công cụ OGRE 3D sử dụng như sau kiểm tra :

if (CMAKE_CXX_COMPILER MATCHES ".*clang")
    set(CMAKE_COMPILER_IS_CLANGXX 1)
endif ()

3
Điều đó gần, nhưng không hoạt động khi bạn sử dụng ccache (tức là export CXX="ccache clang++")
leedm777

4
Đủ gần, tôi sẽ đưa nó cho bạn. Tôi đã sử dụng if ("${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" MATCHES ".*clang")để xử lý các trường hợp ccache.
leedm777

1
Điều này không làm việc cho tôi như ${CMAKE_CXX_COMPILER} == /Library/Developer/CommandLineTools/usr/bin/c++. Câu trả lời được chấp nhận hoạt động.
Fred Schoen

1

Để tránh mọi vấn đề sai chính tả, tôi đang sử dụng phép so sánh không phân biệt chữ hoa chữ thường, như:

string( TOLOWER "${CMAKE_CXX_COMPILER_ID}" COMPILER_ID )
if (COMPILER_ID STREQUAL "clang")
    set(IS_CLANG_BUILD true)
else ()
    set(IS_CLANG_BUILD false)
endif ()

Để tạo ra biểu thức MATCHESkhông phân biệt chữ hoa chữ thường, tôi đã thử mọi thứ ở đây mà không thành công (dường như không được hỗ trợ trong CMake).


thực sự, như ngày nay, trường hợp không phù hợp với trường hợp không thể cmake.org/pipermail/cmake/2017-May/065432.html
fferri

-2

Đây là một câu trả lời chi tiết hơn một chút cho những người mới chơi cmake, được sửa đổi từ câu trả lời của sakra, chỉ cần nối các dòng sau vào CMakeLists.txt:

if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
  MESSAGE("Clang")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
  MESSAGE("GNU")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
  MESSAGE("Intel")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
  MESSAGE("MSVC")
endif()

Sau đó chạy cmake .trong thư mục chứa CMakeLists.txt. Sau đó, bạn sẽ thấy một loạt các kết quả đầu ra cùng với câu trả lời của bạn.

...
-- Detecting CXX compile features
-- Detecting CXX compile features - done
GNU
-- Configuring done
-- Generating done
...
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.