Ghi đè cờ biên dịch cho các tệp đơn lẻ


109

Tôi muốn sử dụng một bộ cờ chung để biên dịch một dự án, nghĩa là ở tệp CMakeLists.txt cấp cao nhất của tôi, tôi đã chỉ định:

ADD_DEFINITIONS ( -Wall -Weffc++ -pedantic -std=c++0x )

Tuy nhiên, đối với một tệp cụ thể (giả sử "foo.cpp") trong thư mục con, tôi muốn chuyển các cờ biên dịch để không áp dụng -Weffc ++ (tôi không thể thay đổi thư viện thương mại đi kèm). Để đơn giản hóa tình huống để chỉ sử dụng -Wall, tôi đã thử:

 SET_SOURCE_FILES_PROPERTIES( foo.cpp PROPERTIES COMPILE_FLAGS -Wall )
 ADD_EXECUTABLE( foo foo.cpp )

, không hoạt động. Tôi cũng đã thử

SET_PROPERTY( SOURCE foo.cpp PROPERTY COMPILE_FLAGS -Wall )
ADD_EXECUTABLE( foo foo.cpp )

ADD_EXECUTABLE( foo foo.cpp )
SET_TARGET_PROPERTIES( foo PROPERTIES COMPILE_FLAGS -Wall )

, trong đó không hoạt động.

Cuối cùng, tôi đã thử loại bỏ độ lệch này:

REMOVE_DEFINITIONS( -Weffc++ )
ADD_EXECUTABLE( foo foo.cpp )
ADD_DEFINITIONS( -Weffc++ )

, mà cũng không hoạt động (có nghĩa là, tôi nhận được rất nhiều cảnh báo về phong cách về thư viện thương mại). (** Lưu ý: Cảnh báo sẽ bị loại bỏ nếu tôi KHÔNG đưa lại chỉ thị -Weffc ++ sau khi tệp thực thi được tạo.)

Tôi cũng đã thử tạm thời xóa các cờ biên dịch: http://www.cmake.org/pipermail/cmake/2007-June/014614.html , nhưng điều đó không giúp được gì.

Không có một giải pháp thanh lịch cho điều này?


1
Chờ đã, nếu nỗ lực cuối cùng của bạn hoạt động, nhưng chỉ sau khi nó được xây dựng, đây có thể không phải là vấn đề bộ nhớ đệm? Thử xóa CMakeCache sau khi thực hiện (các) thay đổi của bạn.
Cameron

Liên quan, hãy xem Cách thay đổi cờ trình biên dịch cho chỉ một tệp thực thi trong CMake? Câu trả lời của Andre cho thấy những gì dường như là một cách để thay thế các tùy chọn hiện tại bằng các tùy chọn mới.
jww

Câu trả lời:


126

Những nỗ lực của bạn ở trên đang thêm các cờ khác vào tệp / đích của bạn thay vì ghi đè như bạn mong đợi. Ví dụ: từ tài liệu dành cho Thuộc tính trên Tệp Nguồn - COMPILE_FLAGS :

Các cờ này sẽ được thêm vào danh sách các cờ biên dịch khi tệp nguồn này được tạo.

Bạn sẽ có thể chống lại -Weffc++cờ cho foo.cpp bằng cách thực hiện

set_source_files_properties(foo.cpp PROPERTIES COMPILE_FLAGS -Wno-effc++)

Điều này sẽ có tác dụng thêm -Wno-effc++sau -Weffc++trong lệnh trình biên dịch và cài đặt sau sẽ thắng. Để xem toàn bộ lệnh và kiểm tra xem đây có đúng là trường hợp này không, bạn có thể làm

make VERBOSE=1

Là một sang một bên, một trong các nhà bảo trì của ++ thư viện chuẩn GNU C trình bày một quan điểm tiêu cực khá trên -Weffc++trong câu trả lời này .

Một điểm khác là bạn đang lạm dụng add_definitionstheo nghĩa là bạn đang sử dụng điều này cho các cờ trình biên dịch hơn là các định nghĩa dành cho bộ xử lý trước.

Nó sẽ được ưu tiên sử dụng add_compile_options

add_compile_options(-Wall -Weffc++ -pedantic -std=c++0x)

hoặc đối với các phiên bản CMake <3.0 để làm điều gì đó giống như:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Weffc++ -pedantic -std=c++0x")

Để trả lời các câu hỏi khác trong phần nhận xét bên dưới, tôi tin rằng không thể xóa cờ trên một tệp một cách đáng tin cậy . Lý do là đối với bất kỳ tệp nguồn nhất định nào, nó có áp dụng COMPILE_OPTIONS1 trong số các mục tiêu của nó, nhưng chúng không hiển thị trong bất kỳ thuộc tính nào của tệp nguồn đó.COMPILE_FLAGS

Bạn có thể xem xét việc loại bỏ cờ vấn đề khỏi mục tiêu COMPILE_OPTIONS, sau đó áp dụng nó cho từng nguồn của mục tiêu riêng lẻ, bỏ qua nó khỏi tệp nguồn cụ thể theo yêu cầu.

Tuy nhiên, trong khi điều này có thể hoạt động trong nhiều trường hợp, nó có một vài vấn đề.

Thuộc tính của tệp nguồn đầu tiên không bao gồm COMPILE_OPTIONS, chỉ COMPILE_FLAGS. Đây là một vấn đề vì COMPILE_OPTIONSmục tiêu có thể bao gồm các biểu thức trình tạo , nhưng COMPILE_FLAGSkhông hỗ trợ chúng. Vì vậy, bạn phải điều chỉnh các biểu thức trình tạo trong khi tìm kiếm cờ của mình và thực sự bạn thậm chí có thể phải "phân tích cú pháp" các biểu thức trình tạo nếu cờ của bạn được chứa trong một hoặc nhiều để xem liệu nó có nên được áp dụng lại cho phần còn lại các tệp nguồn.

Thứ hai - kể từ CMake v3.0, các mục tiêu có thể chỉ định INTERFACE_COMPILE_OPTIONS. Điều này có nghĩa là một phần phụ thuộc của mục tiêu của bạn có thể thêm hoặc ghi đè mục tiêu của bạn COMPILE_OPTIONSthông qua nó INTERFACE_COMPILE_OPTIONS. Vì vậy, bạn sẽ phải lặp lại đệ quy tất cả các phụ thuộc của mục tiêu (không phải là một nhiệm vụ đặc biệt dễ dàng vì danh sách của LINK_LIBRARIESmục tiêu cũng có thể chứa các biểu thức trình tạo) để tìm bất kỳ biểu thức nào đang áp dụng cờ sự cố và thử xóa nó khỏi mục tiêu ' INTERFACE_COMPILE_OPTIONSquá.

Ở giai đoạn phức tạp này, tôi đang tìm cách gửi một bản vá cho CMake để cung cấp chức năng xóa cờ cụ thể khỏi tệp nguồn một cách vô điều kiện.


1: Lưu ý rằng không giống như thuộc COMPILE_FLAGStính trên tệp nguồn, thuộc COMPILE_FLAGStính trên đích không được dùng nữa.


6
Nhưng làm thế nào để bạn thực sự đặt cờ biên dịch cho các tệp một cách riêng biệt mà không cần thêm chúng. Ví dụ: tôi muốn sử dụng các cờ biên dịch khác nhau cho đích kết quả hơn là cho các tệp nhưng vì chúng được nối thêm nên tôi sẽ phải xóa chúng theo cách thủ công. Có thuộc tính nào không nối thêm nhưng thực sự chỉ đặt chúng cho tệp / đích được chỉ định không?
Baradé

2
Chúng ta có thể làm gì khi -fno-flag không khả dụng (và -fflag được đặt)?
gnzlbg

@ Baradé Bạn không thể - không phải đối với tệp nguồn.
Fraser

@gnzlbg Một lần nữa, chúng tôi đang gặp khá nhiều khó khăn. Tôi đã cập nhật câu trả lời của mình để cung cấp thêm một chút thông tin (và một giải pháp khả thi có thể hoạt động trong một số trường hợp).
Fraser

Thực sự không có giải pháp nào cho cài đặt tùy chọn biên dịch tệp đơn? Tôi phải tắt tính năng tạo vùng phủ gcc cho một số tệp đang gặp sự cố gcov.
Lothar

5

Chỉ thêm vào câu trả lời đúng của @ Fraser.

Trong trường hợp nếu bạn muốn thêm cờ đặc biệt vào các thư mục cụ thể, bạn có thể làm:

file(GLOB SPECIAL_SRC_FILES
        "path/one/src/*.cpp"
        "path/two/src/*.cpp")
set_property(SOURCE ${SPECIAL_SRC_FILES} PROPERTY COMPILE_FLAGS -Wno-effc++)

hoặc là

file(GLOB SPECIAL_SRC_FILES
        "path/one/src/*.cpp"
        "path/two/src/*.cpp")
set_source_files_properties(${SPECIAL_SRC_FILES} PROPERTIES COMPILE_FLAGS -Wno-effc++)

Lưu ý rằng không nên sử dụng GLOB như đã thảo luận ở đây


0

Sử dụng câu trả lời @Fraser, tôi đã tạo phần sau để xử lý Qt bao gồm vì biến bao gồm nhiều đường dẫn được phân tách bằng dấu chấm phẩy. Điều này có nghĩa là trước tiên tôi phải thêm một foreach()vòng lặp và tạo các cờ bao gồm bằng tay . Nhưng điều đó cho phép tôi có một ngoại lệ: foo.cpp (một tệp sử dụng Qt bây giờ nhưng lâu dài tôi muốn loại bỏ sự phụ thuộc đó và tôi muốn đảm bảo rằng Qt không len lỏi vào bất kỳ nơi nào khác).

find_package(Qt5Core REQUIRED)
set(QT_INCLUDE_PROPERTIES "")
foreach(DIR ${Qt5Core_INCLUDE_DIRS})
    set(QT_INCLUDE_PROPERTIES "${QT_INCLUDE_PROPERTIES} -isystem ${DIR}")
endforeach()
set_source_files_properties(foo.cpp PROPERTIES
    COMPILE_FLAGS
        ${QT_INCLUDE_PROPERTIES}
)

Cũng lưu ý rằng tôi sử dụng -isystemthay vì -Iđể tránh một số cảnh báo mà tiêu đề Qt tạo ra (tôi đã bật rất nhiều cảnh báo).

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.