web-dev-qa-db-fra.com

Optimiser dans CMake par défaut

J'ai un projet C++ qui utilise CMake comme système de construction. Je voudrais le comportement suivant:

Si cmake est appelé en tant que cmake .., Alors CMAKE_CXX_FLAGS Est -O3 -Wall -Wextra

Si cmake est appelé en tant que cmake .. -DCMAKE_BUILD_TYPE=Debug, Alors CMAKE_CXX_FLAGS Est -g -Wall -Wextra

J'ai essayé le suivant

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

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

Mais cela pose un gros problème. Tout d'abord, si le deuxième appel est utilisé, les deux indicateurs -O3 Et -g Sont transmis au compilateur. En outre, si j'utilise la deuxième invocation et la première par la suite, CMAKE_BUILD_TYPE Reste Debug bien que ce ne soit pas explicitement commandé - je reçois donc une version Debug bien que je souhaite une version optimisée.

Pourquoi? Que puis-je faire pour avoir le comportement souhaité?

20
marmistrz

Tout d'abord: l'utilisation recommandée de CMake est de toujours spécifier CMAKE_BUILD_TYPE explicitement sur la ligne de commande (si et seulement si vous utilisez un générateur à configuration unique). Votre cas d'utilisation s'écarte de cette meilleure pratique. Traitez donc cette réponse comme "comment vous pouvez le faire" et non pas nécessairement comme "comment vous devez le faire".

Pour résoudre le premier problème, vous devriez pouvoir le faire plus tôt dans votre 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")

Cela garantira que si vous ne spécifiez pas du tout le type de construction, il utilisera par défaut "Release" et donc CMAKE_CXX_FLAGS_RELEASE sera utilisé.

Le second est plus difficile à aborder. Variables transmises à partir de la ligne de commande (telles que CMAKE_BUILD_TYPE=Debug) sont mis en cache par CMake et sont donc réutilisés lors d'appels ultérieurs (nécessaire, car CMake peut se déclencher de nouveau si vous modifiez ses entrées entre les générations).

La seule solution est de faire changer explicitement le type de construction par l’utilisateur, en utilisant cmake .. -DCMAKE_BUILD_TYPE=Release.

Pourquoi est-ce nécessaire? Comme je l'ai dit, CMake peut se re-déclencher lui-même dans le cadre d'une construction si l'entrée de CMake (CMakeLists.txt fichiers ou leurs dépendances) a changé depuis la dernière exécution de CMake. Dans ce cas, il sera également exécuté sans argument de ligne de commande, tel que -DCMAKE_BUILD_TYPE=whatever, et comptera sur le cache pour fournir la même valeur que la dernière fois. Vous ne pouvez pas distinguer ce scénario de votre exécution manuelle cmake .. sans arguments supplémentaires.

Je pourrais fournir une solution de hacky pour toujours réinitialiser CMAKE_BUILD_TYPE to Release si non spécifié explicitement sur la ligne de commande. Cependant, cela signifierait également qu'un système de génération généré sous la forme Debug serait régénéré sous la forme Release si une régénération automatique se produisait. Je suis à peu près sûr que ce n'est pas ce que tu veux.

40
Angew

Pour les drapeaux CXX spécifiques à Release cible, vous devez définir
CMAKE_CXX_FLAGS_RELEASE
au lieu de
CMAKE_CXX_FLAGS

Dans votre cas, vous pouvez utiliser:

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

Une approche CMake plus moderne (que je suggère, si vous utilisez CMake version 2.8.12 ou plus récente), est bien décrite dans cette réponse StackOverflow et implique l'utilisation de target_compile_options .

8
roalz