2016-12-28 37 views
5

Mam projekt C++, który używa CMake jako system kompilacji. Chciałbym następujące zachowanie:Optymalizacja domyślnie w CMake

Jeśli cmake jest wywoływana jako cmake .., następnie CMAKE_CXX_FLAGS jest -O3 -Wall -Wextra

Jeśli cmake jest wywoływana jako cmake .. -DCMAKE_BUILD_TYPE=Debug, następnie CMAKE_CXX_FLAGS jest -g -Wall -Wextra

Próbowałem następujące

message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") 

set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra") 
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra") 

Ale to ma duży problem. Po pierwsze, jeśli używane jest drugie wywołanie, wówczas oba znaczniki -O3 i -g są przekazywane do kompilatora. Poza tym, jeśli użyjemy drugiej inwokacji, a pierwsza po niej, CMAKE_BUILD_TYPE pozostaje Debug, chociaż nie jest jawnie uporządkowana, więc otrzymuję kompilację Debug, ale chcę zoptymalizowanej kompilacji.

Dlaczego? Co mogę zrobić, aby uzyskać pożądane zachowanie?

Odpowiedz

10

Po pierwsze: zalecane użycie CMake polega na tym, aby zawsze jawnie określać CMAKE_BUILD_TYPE w wierszu poleceń (tylko wtedy, gdy używany jest generator z jedną konfiguracją). Twój przypadek użycia różni się od tej najlepszej praktyki, więc traktuj tę odpowiedź jako "jak możesz to zrobić", niekoniecznie jako "jak powinieneś to zrobić".

Aby rozwiązać pierwszy problem, powinieneś być w stanie to zrobić na początku swojej CMakeList:

if(NOT CMAKE_BUILD_TYPE) 
    set(CMAKE_BUILD_TYPE Release) 
endif() 

set(CMAKE_CXX_FLAGS "-Wall -Wextra") 
set(CMAKE_CXX_FLAGS_DEBUG "-g") 
set(CMAKE_CXX_FLAGS_RELEASE "-O3") 

To będzie upewnić się, że jeśli nie zostanie określony typ kompilacji w ogóle, to będzie domyślnie " Zwolnij "i tym samym użyjemy CMAKE_CXX_FLAGS_RELEASE.

Ten drugi jest trudniejszy do rozwiązania. Zmienne przekazane z wiersza poleceń (takie jak CMAKE_BUILD_TYPE=Debug) są buforowane przez CMake iw ten sposób ponownie użyte w kolejnych wywołaniach (jest to konieczne, ponieważ CMake może ponownie wyzwalać się, jeśli modyfikuje swoje wejścia między kompilacjami).

Jedynym rozwiązaniem jest wyraźne ponowne ustawienie typu budowy za pomocą cmake .. -DCMAKE_BUILD_TYPE=Release.

Zastanów się, dlaczego jest to konieczne: tak jak powiedziałem, program CMake może ponownie wywołać samą siebie jako część kompilacji, jeśli dane wejściowe programu CMake (pliki CMakeLists.txt lub ich zależności) uległy zmianie od ostatniego uruchomienia programu CMake. W takim przypadku będzie on również uruchamiany bez argumentów wiersza polecenia, takich jak -DCMAKE_BUILD_TYPE=whatever i będzie polegał na pamięci podręcznej, aby dostarczyć tę samą wartość, co ostatnio. Ten scenariusz jest nie do odróżnienia od ręcznego uruchamiania cmake .. bez dodatkowych argumentów.

Mogę zapewnić hacky rozwiązanie, aby zawsze resetować CMAKE_BUILD_TYPE do Release, jeśli nie jest określony jawnie w wierszu polecenia. Jednakże oznaczałoby to również, że system wygenerowany jako Debug zostałby ponownie wygenerowany jako Release, jeśli nastąpi automatyczne ponowne generowanie. Jestem prawie pewien, że nie tego chcesz.

+0

Działa to dopóki nie wykonam kompilacji debugowania. Po jednej kompilacji debugowania wszystkie kolejne są kompilacjami debugowania, nawet jeśli używa się 'cmake ..' – marmistrz

+0

Nie pamiętam, gdzie ją przeczytałem, ale uważam, że niewłaściwa jest konfiguracja CMAKE_BUILD_TYPE z wewnątrz CMakeLists.txt . Wolisz przekazać go z wiersza poleceń CMake. – roalz

+0

@marmistrz Dodałem aktualizację, dlaczego tak się dzieje i jak ją "zresetować". Próbuję wymyślić sposób na uzyskanie niejawnego resetu, ale nie jest to łatwe. – Angew

4

Dla CXX flagi specyficzne dla celu wydania, należy ustawić
CMAKE_CXX_FLAGS_RELEASE
zamiast
CMAKE_CXX_FLAGS

w twoim przypadku można użyć:

zestaw (CMAKE_CXX_FLAGS „-Wall -Wextra ")
Zestaw (CMAKE_CXX_FLAGS_DEBUG" -g ")
Zestaw (CMAKE_CXX_FLAGS_RELEASE" -O3 ")

Bardziej nowoczesne podejście CUpewnij (co sugeruję, jeśli używasz wersji 2.8.12 CUpewnij lub nowszą), jest dobrze opisana w this StackOverflow answer i wymaga użycia target_compile_options.

+0

Powiedziałbym "-g -O0". –

+0

Ale wtedy '-O3' nie jest przekazywane do kompilatora, gdy' cmake ..' – marmistrz

+1

@ n.m. gcc nie optymalizuje w ogóle domyślnie – marmistrz