Jak dodać linker lub skompilować flagę w pliku CMake?

220

Korzystam z arm-linux-androideabi-g++kompilatora. Kiedy próbuję skompilować proste „Witaj, świecie!” program kompiluje się dobrze. Kiedy go testuję, dodając prostą obsługę wyjątków w tym kodzie, on również działa (po dodaniu -fexceptions.. Myślę, że jest domyślnie wyłączony).

To jest dla urządzenia z Androidem i chcę tylko używać CMake, a nie ndk-build.

Na przykład - first.cpp

#include <iostream>

using namespace std;

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

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

Działa bez problemu ...

Problem ... Próbuję skompilować plik z plikiem CMake.

Chcę dodać -fexceptionsjako flagę. Próbowałem z

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

i

set ( CMAKE_C_FLAGS "fexceptions")

Nadal wyświetla błąd.

solti
źródło
w tej chwili mam ten sam problem i próbuję różnych rzeczy. Zaczekaj trochę, a ja opublikuję odpowiedź. W przypadku flag kompilacyjnych istnieje nieczysty, ale prosty sposób: add_definitions ("- truc")
Offirmo
Aby uzyskać bardziej aktualną dyskusję na ten temat (szczególnie jeśli używasz CMake 3.x lub nowszej): Jaka jest nowoczesna metoda ustawiania ogólnych flag kompilacji w CMake? .
ComicSansMS
Jeśli flagi Link chcesz zmierzać do konfigurowania rpath następnie spojrzeć na konkretne CUpewnij rpath polecenia gitlab.kitware.com/cmake/community/wikis/doc/cmake/...
Gabriel Devillers

Odpowiedzi:

243

Załóżmy, że chcesz dodać te flagi (lepiej zadeklarować je na stałe):

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

Istnieje kilka sposobów ich dodania:

  1. Najłatwiejszy (nie czysty, ale łatwy i wygodny, działa tylko na flagi kompilacji, C i C ++ jednocześnie):

    add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
  2. Dołączanie do odpowiednich zmiennych CMake:

    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. Używając właściwości docelowych, por. doc CMUtwórz właściwość docelową flagi kompilacji i musisz znać nazwę celu.

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

Teraz używam metody 2.

Offirmo
źródło
4
dlaczego add_definitions () jest nieczyste?
leinaD_natipaC
14
@leinaD_natipaC: Oficjalna dokumentacja mówi: Komendy tej można użyć do dodania dowolnych flag, ale ma ona na celu dodanie definicji preprocesora . Myślę, że właśnie dlatego.
Benoit Blanchon
Chociaż jest to zaakceptowana odpowiedź, to naprawdę pokazuje bardzo stary styl CMAKE, zapoznaj się z odpowiedzią @vitaut, aby dowiedzieć się, jak powinien wyglądać każdy nowy kod CMAKE w odniesieniu do parametrów czasu kompilacji
Harald Scheirich
1
string(APPEND CMAKE_EXE_LINKER_FLAGS "new_value")jest krótszy i czystszy niżset(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} new_value")
cholerny
165

W nowszych wersjach CMake możesz ustawić flagi kompilatora i linkera dla pojedynczego celu odpowiednio target_compile_optionsi target_link_libraries(tak, ten drugi ustawia również opcje linkera):

target_compile_options(first-test PRIVATE -fexceptions)

Zaletą tej metody jest to, że można kontrolować propagację opcji do innych celów zależnych od tego za pośrednictwem PUBLICi PRIVATE.

Począwszy od CMake 3.13 możesz także użyć target_link_optionsopcji dodania linkera, dzięki czemu intencja jest bardziej przejrzysta.

vitaut
źródło
2
Próbowałem go użyć: target_compile_options(main_static PRIVATE --static)ale wydaje się, że to nie działa, jakiś pomysł, dlaczego?
Paweł Szczur,
2
-staticjest prawdopodobnie linkerem, a nie opcją kompilatora. Spróbuj przekazać to target_link_libraries.
vitaut
9
Och, target_link_librariestęskniłem za tą częścią dokumentu: „Określ biblioteki lub flagi, które mają być używane podczas łączenia danego celu”. Dzięki.
Paweł Szczur,
3
Niedawne uzupełnienie: CMake 3.13 wprowadza target_link_optionsjako czystszy sposób określania flag linkera. W target_link_librariesprzyszłości powinieneś unikać używania flag flag linkerów i target_link_optionszamiast tego używaj .
ComicSansMS
1
Istnieją również opcje add_compile_options - patrz stackoverflow.com/questions/39501481/... a ostatnio add_link_options
Bruce Adams,
46

Spróbuj ustawić zmienną CMAKE_CXX_FLAGSzamiast CMAKE_C_FLAGS:

set (CMAKE_CXX_FLAGS "-fexceptions")

Zmienna CMAKE_C_FLAGSwpływa tylko na kompilator C, ale kompilujesz kod C ++.

Dodanie flagi CMAKE_EXE_LINKER_FLAGSjest zbędne.

sakra
źródło
próbowałem, ale nadal daje błąd. Ustawiono (CMAKE_CXX_FLAGS „-fexceptions”) jedyny sposób na określenie flagi kompilatora.
solti
3
Rozwiązałem problem, ale nie w dobrym stopniu jest to słabe obejście. W wierszu poleceń ustawiłem -DCMAKE_CXX_FLAGS = "-fexceptions". z jakiegoś powodu cmake nie odczytuje flag z pliku .cmake. :( .. dziękuję Sakra za odpowiedź ..
solti
8
-DCMAKE_CXX_FLAGS = "-fexceptions" NIE powinno być spacji między = i "
evandrix
W odniesieniu do tego, co powiedziałeś: „z jakiegoś powodu cmake nie czyta flag z pliku .cmake”. Wyczyść istniejącą pamięć podręczną. Można to zrobić, usuwając wszystko z katalogu kompilacji przed cmake.
zaizen
1

Możesz także dodać flagi linkera do określonego celu, używając LINK_FLAGSwłaściwości:

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

Jeśli chcesz propagować tę zmianę do innych celów, możesz utworzyć fikcyjny cel, z którym chcesz się połączyć.

kaveish
źródło