Bagaimana cara menambahkan tautan atau kompilasi flag dalam file CMake?

220

Saya menggunakan arm-linux-androideabi-g++kompiler. Ketika saya mencoba mengkompilasi sederhana "Halo, Dunia!" programnya kompilasi dengan baik. Ketika saya mengujinya dengan menambahkan penanganan pengecualian sederhana dalam kode itu juga berfungsi (setelah menambahkan -fexceptions.. Saya kira itu dinonaktifkan secara default).

Ini untuk perangkat Android, dan saya hanya ingin menggunakan CMake, bukan ndk-build.

Sebagai contoh - first.cpp

#include <iostream>

using namespace std;

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

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

Ia bekerja tanpa masalah ...

Masalahnya ... Saya mencoba mengkompilasi file dengan file CMake.

Saya ingin menambahkan -fexceptionssebagai bendera. Saya mencoba

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

dan

set ( CMAKE_C_FLAGS "fexceptions")

Itu masih menampilkan kesalahan.

solti
sumber
sekarang saya mengalami masalah yang sama, dan saya mencoba hal yang berbeda. Tunggu sebentar dan saya mengirim jawaban. Untuk mengompilasi flag, ada cara yang tidak bersih tetapi mudah: add_definitions ("- truc")
Offirmo
Untuk diskusi yang lebih terkini tentang pertanyaan ini (terutama jika Anda menggunakan CMake 3.x atau lebih baru): Apa metode modern untuk mengatur flag kompilasi umum di CMake? .
ComicSansMS
Jika flag tautan yang Anda inginkan bertujuan mengonfigurasi rpath, maka lihat perintah spesifik CMake rpath gitlab.kitware.com/cmake/community/wikis/doc/cmake/…
Gabriel Devillers

Jawaban:

243

Misalkan Anda ingin menambahkan bendera tersebut (lebih baik mendeklarasikannya dalam konstanta):

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

Ada beberapa cara untuk menambahkannya:

  1. Yang termudah (tidak bersih, tapi mudah dan nyaman, dan hanya berfungsi untuk mengompilasi flag, C&C ++ sekaligus):

    add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
  2. Menambahkan ke variabel CMake yang sesuai:

    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. Menggunakan properti target, lih. doc CMake kompilasi flag target property dan perlu tahu nama target.

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

Saat ini saya menggunakan metode 2.

Offirmo
sumber
4
mengapa add_definitions () tidak bersih?
leinaD_natipaC
14
@leinaD_natipaC: Dokumentasi resmi mengatakan: Perintah ini dapat digunakan untuk menambahkan flag, tetapi dimaksudkan untuk menambahkan definisi preprocessor . Saya pikir itu sebabnya.
Benoit Blanchon
Walaupun ini adalah jawaban yang diterima, ini benar-benar menunjukkan CMAKE gaya yang sangat lama, lihat jawaban oleh @vitaut untuk mengetahui susunan kode CMAKE baru apa pun terkait dengan kompilasi parameter waktu
Harald Scheirich
1
string(APPEND CMAKE_EXE_LINKER_FLAGS "new_value")lebih pendek dan lebih bersih daripadaset(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} new_value")
berdarah
165

Dalam versi CMake yang lebih baru Anda dapat mengatur flag compiler dan linker untuk satu target dengan target_compile_optionsdan target_link_librariesmasing - masing (ya, yang terakhir juga mengatur opsi linker):

target_compile_options(first-test PRIVATE -fexceptions)

Keuntungan dari metode ini adalah Anda dapat mengontrol penyebaran opsi ke target lain yang bergantung pada ini melalui PUBLICdan PRIVATE.

Pada CMake 3.13 Anda juga dapat menggunakan target_link_optionsuntuk menambahkan opsi tautan yang membuat maksudnya lebih jelas.

riwayat hidup
sumber
2
Saya sudah mencoba menggunakannya: target_compile_options(main_static PRIVATE --static)tetapi sepertinya tidak berhasil, tahu mengapa?
Paweł Szczur
2
-staticmungkin merupakan tautan, bukan opsi penyusun. Coba lewati target_link_libraries.
vitaut
9
Oh, target_link_librariessaya melewatkan bagian dokumen itu: "Tentukan perpustakaan atau bendera yang akan digunakan ketika menautkan target yang diberikan.". Terima kasih.
Paweł Szczur
3
Tambahan baru-baru ini: CMake 3.13 memperkenalkan target_link_optionssebagai cara yang lebih bersih untuk menentukan flag-flag linker. Anda harus menghindari menggunakan target_link_librariesuntuk bendera penghubung di masa depan dan menggunakannya target_link_optionssebagai gantinya.
ComicSansMS
1
Ada juga add_compile_options - lihat stackoverflow.com/questions/39501481/... dan baru-baru ini add_link_options
Bruce Adams
46

Coba atur variabel CMAKE_CXX_FLAGSalih-alih CMAKE_C_FLAGS:

set (CMAKE_CXX_FLAGS "-fexceptions")

Variabel CMAKE_C_FLAGShanya memengaruhi kompiler C, tetapi Anda mengkompilasi kode C ++.

Menambahkan bendera ke CMAKE_EXE_LINKER_FLAGSberlebihan.

sakra
sumber
saya mencobanya tetapi masih memberikan kesalahan. Diatur (CMAKE_CXX_FLAGS "-feksepsi") satu-satunya cara untuk menentukan flag kompiler.
solti
3
saya memecahkan masalah tetapi tidak dengan cara yang baik solusi yang buruk .. saya membuat -DCMAKE_CXX_FLAGS = "-fexceptions" di baris perintah. untuk beberapa alasan cmake tidak membaca flag dari file .cmake. :( .. terima kasih sakra atas jawaban Anda ..
solti
8
-DCMAKE_CXX_FLAGS = "-fexceptions" TIDAK boleh ada spasi antara = dan "
evandrix
Mengenai apa yang Anda katakan: "untuk beberapa alasan cmake tidak membaca flag dari file .cmake." Pastikan Anda membersihkan cache yang ada. Ini dapat dilakukan dengan menghapus semuanya dari direktori build sebelum cmake lagi.
zaizen
1

Anda juga dapat menambahkan bendera penghubung ke target tertentu menggunakan LINK_FLAGSproperti:

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

Jika Anda ingin menyebarkan perubahan ini ke target lain, Anda dapat membuat target tiruan untuk ditautkan.

Kaveish
sumber