web-dev-qa-db-fra.com

CMake répertoire de sortie / construction

Je suis assez nouveau dans cmake et j'ai lu quelques tutoriels sur son utilisation. J'ai également écrit un script CMake compliqué de 50 lignes afin de créer un programme pour 3 compilateurs différents. Ceci conclut probablement toutes mes connaissances en cmake.

Maintenant, mon problème est que j'ai un code source dont je ne veux pas toucher le dossier lorsque je crée le programme. Je veux que tous les cmake et les fichiers de sortie et les dossiers soient insérés dans ../Compile/, j'ai donc modifié quelques variables dans mon script cmake pour cela, et cela a fonctionné pendant un moment où j'ai fait quelque chose comme ça sur mon ordinateur portable:

Compile$ cmake ../src
Compile$ make

Là où j’ai eu une sortie en clair dans le dossier dans lequel je me trouve, c’est exactement ce que je recherche.

Maintenant, j'ai déménagé sur un autre ordinateur et recompilé CMake 2.8.11.2, et je suis presque revenu à la case départ! Il compile toujours la chose dans le dossier src où se trouve mon CMakeLists.txt.

La partie où je choisis le répertoire dans mon script cmake est la suivante:

set(dir ${CMAKE_CURRENT_SOURCE_DIR}/../Compile/)
set(EXECUTABLE_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(LIBRARY_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dir})
set(CMAKE_BUILD_FILES_DIRECTORY ${dir})
set(CMAKE_BUILD_DIRECTORY ${dir})
set(CMAKE_BINARY_DIR  ${dir})
SET(EXECUTABLE_OUTPUT_PATH ${dir})
SET(LIBRARY_OUTPUT_PATH ${dir}lib)
SET(CMAKE_CACHEFILE_DIR ${dir})

Et maintenant, il se termine toujours par:

-- Build files have been written to: /.../src

Est-ce que je manque quelque chose?

91

Il est inutile de définir toutes les variables que vous définissez. CMake leur attribue des valeurs par défaut raisonnables. Vous devriez absolument pas modifier CMAKE_BINARY_DIR ou CMAKE_CACHEFILE_DIR. Traitez-les en lecture seule.

Commencez par supprimer le fichier de cache problématique existant dans le répertoire src:

cd src
rm CMakeCache.txt
cd ..

Ensuite, supprimez toutes les commandes set() et faites:

cd Compile
rm -rf *
cmake ../src

Tant que vous êtes en dehors du répertoire source lorsque vous exécutez CMake, cela ne modifiera pas le répertoire source à moins que votre CMakeList ne le lui indique explicitement.

Une fois que cela fonctionne, vous pouvez regarder où CMake met les choses par défaut, et ne modifiez que ceux dont vous avez besoin (par exemple, la valeur par défaut de EXECUTABLE_OUTPUT_PATH). Et essayez de les exprimer par rapport à CMAKE_BINARY_DIR, CMAKE_CURRENT_BINARY_DIR, PROJECT_BINARY_DIR etc.

Si vous consultez la documentation de CMake, vous verrez des variables partitionnées en sections sémantiques. À l'exception de très circonstances spéciales, vous devez traiter toutes les options répertoriées sous "Variables fournissant des informations" en lecture seule dans CMakeLists.

51
Angew

On dirait que vous voulez un build hors source . Vous pouvez créer une version hors source de plusieurs manières.

  1. Fais ce que tu faisais, cours

    cd /path/to/my/build/folder
    cmake /path/to/my/source/folder
    

    ce qui fera que cmake générera un arbre de compilation dans /path/to/my/build/folder pour le arbre source dans /path/to/my/source/folder.

    Une fois que vous l'avez créé, cmake se souvient de l'emplacement du dossier source. Vous pouvez ainsi réexécuter cmake sur l'arbre de construction avec

    cmake /path/to/my/build/folder
    

    ou même

    cmake .
    

    si votre répertoire actuel est déjà le dossier de construction.

  2. Utilisez certaines options non documentées pour définir les dossiers source et de construction :

    cmake -B/path/to/my/build/folder -H/path/to/my/source/folder
    

    qui fera exactement la même chose que (1), mais sans compter sur le répertoire de travail actuel.

CMake place toutes ses sorties dans le arbre de la construction par défaut. Ainsi, à moins que vous n'utilisiez libéralement ${CMAKE_SOURCE_DIR} ou ${CMAKE_CURRENT_SOURCE_DIR} dans vos fichiers cmake, il ne devrait pas toucher votre - arbre source.

Si vous avez déjà généré une arborescence de génération dans votre arborescence source (c’est-à-dire que vous avez une compilation in source), la plus grosse erreur peut survenir. Une fois que cela est fait, la deuxième partie de (1) ci-dessus commence et cmake n'apporte aucune modification aux emplacements source ou de construction. Ainsi, vous ne pouvez pas créer de construction hors source pour un répertoire source avec une construction dans la source . Vous pouvez résoudre ce problème assez facilement en supprimant (au minimum) CMakeCache.txt du répertoire source. CMake génère également d'autres fichiers (que vous devez également supprimer, la plupart du temps dans le répertoire CMakeFiles], mais ils ne permettront pas à cmake de traiter l'arborescence source comme une arborescence de génération.

Étant donné que les compilations hors source sont souvent plus souhaitables que les compilations in-source, vous pouvez modifier votre cmake pour exiger des constructions hors source:

# Ensures that we do an out of source build

MACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD MSG)
     STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
     "${CMAKE_BINARY_DIR}" insource)
     GET_FILENAME_COMPONENT(PARENTDIR ${CMAKE_SOURCE_DIR} PATH)
     STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
     "${PARENTDIR}" insourcesubdir)
    IF(insource OR insourcesubdir)
        MESSAGE(FATAL_ERROR "${MSG}")
    ENDIF(insource OR insourcesubdir)
ENDMACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD)

MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
    "${CMAKE_PROJECT_NAME} requires an out of source build."
)

La macro ci-dessus provient d'un module couramment utilisé appelé MacroOutOfSourceBuild. Il existe de nombreuses sources pour MacroOutOfSourceBuild.cmake sur Google, mais je n'arrive pas à trouver l'original et il est assez court pour l'inclure ici au complet.

Malheureusement, cmake a généralement écrit quelques fichiers au moment de l'appel de la macro. Par conséquent, même si cela vous empêchera d'exécuter la construction, vous devrez toujours supprimer CMakeCache.txt et CMakeFiles.

Vous pouvez trouver utile de définir les chemins vers lesquels les binaires, les bibliothèques partagées et statiques sont écrits - dans ce cas, voyez comment puis-je créer une sortie de cmake dans un répertoire 'bin'? (disclaimer, j’ai le haut voté réponse à cette question ... mais c'est comme ça que je sais à ce sujet).

94
Adam Bowen

Transformer mon commentaire en réponse:

Au cas où quelqu'un ferait ce que je faisais, il fallait commencer par mettre tous les fichiers de construction dans le répertoire source:

cd src
cmake .

cmake mettra un tas de fichiers de construction et de fichiers de cache (CMakeCache.txt, CMakeFiles, cmake_install.cmake, etc.) dans le répertoire src.

Pour passer à une version hors source, je devais supprimer tous ces fichiers. Ensuite, je pourrais faire ce que @Angew recommandait dans sa réponse:

mkdir -p src/build
cd src/build
cmake ..
6
Avi Tevet

À partir de CMake Wiki :

CMAKE_BINARY_DIR si vous créez in-source, il s'agit de la même chose que CMAKE_SOURCE_DIR, sinon c'est le répertoire de niveau supérieur de votre arborescence de génération.

Comparez ces deux variables pour déterminer si la construction hors source a été lancée.

6
damkrat

Tout d’abord, vous ne devez pas relayer le nom du répertoire de construction dans votre script. La ligne avec ../Compile doit être modifiée.

C'est parce qu'il appartient à l'utilisateur de compiler.

Au lieu de cela, utilisez l'une des variables prédéfinies: http://www.cmake.org/Wiki/CMake_Useful_Variables (recherchez CMAKE_BINARY_DIR et CMAKE_CURRENT_BINARY_DIR)

5
Michał Walenciak