Làm cách nào để thêm một trình liên kết hoặc cờ biên dịch trong tệp CMake?


220

Tôi đang sử dụng arm-linux-androideabi-g++trình biên dịch. Khi tôi cố gắng biên dịch một "Xin chào, thế giới!" Đơn giản chương trình nó biên dịch tốt. Khi tôi kiểm tra nó bằng cách thêm một xử lý ngoại lệ đơn giản trong mã đó, nó cũng hoạt động (sau khi thêm -fexceptions.. tôi đoán nó bị tắt theo mặc định).

Cái này dành cho thiết bị Android và tôi chỉ muốn sử dụng CMake chứ không muốn ndk-build.

Ví dụ - first.cpp

#include <iostream>

using namespace std;

int main()
{
   try
   {
   }
   catch (...)
   {
   }
   return 0;
}

./arm-linux-androideadi-g++ -o first-test first.cpp -fexceptions

Nó hoạt động không có vấn đề ...

Vấn đề ... Tôi đang cố gắng biên dịch tệp bằng tệp CMake.

Tôi muốn thêm -fexceptionsnhư một lá cờ. Tôi đã thử với

set (CMAKE_EXE_LINKER_FLAGS -fexceptions ) or set (CMAKE_EXE_LINKER_FLAGS "fexceptions" )

set ( CMAKE_C_FLAGS "fexceptions")

Nó vẫn hiển thị một lỗi.


Ngay bây giờ tôi đang có cùng một vấn đề, và tôi đang thử những thứ khác nhau. Treo một chút và tôi gửi một câu trả lời. Đối với các cờ biên dịch, có một cách ô uế nhưng dễ dàng: add_def địnhs ("- truc")
Offirmo

Để thảo luận cập nhật hơn về câu hỏi này (đặc biệt nếu bạn đang sử dụng CMake 3.x hoặc mới hơn): Phương pháp hiện đại để đặt cờ biên dịch chung trong CMake là gì? .
Truyện tranh

Nếu các cờ liên kết mà bạn muốn nhắm đến để định cấu hình rpath thì hãy xem các lệnh rpath CMake cụ thể gitlab.kitware.com/cmake/community/wikis/doc/cmake/ trộm
Gabriel Devillers

Câu trả lời:


243

Giả sử bạn muốn thêm các cờ đó (tốt hơn để khai báo chúng trong một hằng số):

SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS    "-lgcov")

Có một số cách để thêm chúng:

  1. Cách dễ nhất (không sạch, nhưng dễ dàng và thuận tiện và chỉ hoạt động đối với các cờ biên dịch, C & C ++ cùng một lúc):

    add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
  2. Áp dụng cho các biến CMake tương ứng:

    SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
    SET(CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
  3. Sử dụng các thuộc tính mục tiêu, xem doc CMake biên dịch cờ thuộc tính đích và cần biết tên đích.

    get_target_property(TEMP ${THE_TARGET} COMPILE_FLAGS)
    if(TEMP STREQUAL "TEMP-NOTFOUND")
      SET(TEMP "") # Set to empty string
    else()
      SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content
    endif()
    # Append our values
    SET(TEMP "${TEMP}${GCC_COVERAGE_COMPILE_FLAGS}" )
    set_target_properties(${THE_TARGET} PROPERTIES COMPILE_FLAGS ${TEMP} )

Ngay bây giờ tôi sử dụng phương pháp 2.


4
Tại sao add_def địnhs () không sạch?
leinaD_natipaC

14
@leinaD_natipaC: Tài liệu chính thức cho biết: Lệnh này có thể được sử dụng để thêm bất kỳ cờ nào, nhưng nó được dùng để thêm các định nghĩa tiền xử lý . Tôi nghĩ đó là lý do tại sao.
Benoit Blanchon

Mặc dù đây là câu trả lời được chấp nhận nhưng đây thực sự thể hiện kiểu CMAKE rất cũ, hãy tham khảo câu trả lời của @vitaut để biết cách cấu trúc bất kỳ mã CMAKE mới nào liên quan đến các tham số thời gian biên dịch
Harald Scheirich

1
string(APPEND CMAKE_EXE_LINKER_FLAGS "new_value")ngắn hơn và sạch hơnset(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} new_value")
đẫm máu

165

Trong các phiên bản mới hơn của CMake, bạn có thể đặt cờ trình biên dịch và trình liên kết cho một mục tiêu duy nhất với target_compile_optionstarget_link_librariestương ứng (vâng, sau này cũng đặt các tùy chọn liên kết):

target_compile_options(first-test PRIVATE -fexceptions)

Ưu điểm của phương pháp này là bạn có thể kiểm soát việc truyền bá các tùy chọn sang các mục tiêu khác phụ thuộc vào mục tiêu này thông qua PUBLICPRIVATE.

Kể từ CMake 3.13, bạn cũng có thể sử dụng target_link_optionsđể thêm các tùy chọn liên kết giúp cho ý định rõ ràng hơn.


2
Tôi đã thử sử dụng nó: target_compile_options(main_static PRIVATE --static)nhưng nó dường như không hoạt động, có ý tưởng nào tại sao không?
Paweł Szczur

2
-staticcó lẽ là một liên kết, không phải tùy chọn trình biên dịch. Hãy thử chuyển nó đến target_link_libraries.
vitaut

9
Ồ, target_link_librariestôi đã bỏ lỡ phần tài liệu đó: "Chỉ định thư viện hoặc cờ sẽ sử dụng khi liên kết một mục tiêu nhất định.". Cảm ơn.
Paweł Szczur

3
Một bổ sung gần đây: CMake 3.13 giới thiệu target_link_optionsnhư một cách sạch hơn để chỉ định các cờ liên kết. Bạn nên tránh sử dụng target_link_librariescho các cờ liên kết trong tương lai và sử dụng target_link_optionsthay thế.
ComicSansMS


46

Hãy thử đặt biến CMAKE_CXX_FLAGSthay vì CMAKE_C_FLAGS:

set (CMAKE_CXX_FLAGS "-fexceptions")

Biến CMAKE_C_FLAGSchỉ ảnh hưởng đến trình biên dịch C, nhưng bạn đang biên dịch mã C ++.

Thêm cờ vào CMAKE_EXE_LINKER_FLAGSlà dư thừa.


tôi đã thử nhưng nó vẫn báo lỗi. Được đặt (CMAKE_CXX_FLAGS "-fexceptions") là cách duy nhất để chỉ định cờ trình biên dịch.
solti

3
tôi đã giải quyết vấn đề nhưng không phải là cách giải quyết tốt. Tôi đã tạo ra -DCMAKE_CXX_FLAGS = "-fexceptions" trong dòng lệnh. vì một số lý do, cmake không đọc cờ từ tệp .cmake. :( .. cảm ơn bạn vì câu trả lời của bạn ..
solti

8
-DCMAKE_CXX_FLAGS = "-fexceptions" KHÔNG nên có khoảng cách giữa = và "
evandrix

Về những gì bạn đã nói: "vì một số lý do, cmake không đọc cờ từ tệp .cmake." Hãy chắc chắn rằng bạn xóa bộ nhớ cache hiện có. Điều này có thể được thực hiện bằng cách xóa mọi thứ khỏi thư mục build trước khi cmake lại.
zaizen

1

Bạn cũng có thể thêm cờ liên kết vào một mục tiêu cụ thể bằng cách sử dụng thuộc LINK_FLAGStính:

set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${flag}")

Nếu bạn muốn tuyên truyền thay đổi này cho các mục tiêu khác, bạn có thể tạo một mục tiêu giả để liên kết đến.


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.