web-dev-qa-db-fra.com

Créer un répertoire de construction pour plusieurs projets

Je suis un utilisateur débutant de CMake. Mon environnement a plusieurs projets comme:

project
  |------ CMakeLists.txt (The main Cmake)
  |------ ProjectA
  |          |----- .cpp files
  |          |----- .hpp files
  |          |----- CMakeList.txt
  |------ ProjectB
  |          |----- .cpp files
  |          |----- .hpp files
  |          |----- CMakeList.txt
  | 
  |------ build
  |         |-----  CMakeStuff
  |------ bin
  |        |---- executables
  |------ lib
  |        |---- libwhatever.a
  |------ db 
           |---- Database stuff

Je voudrais utiliser un seul répertoire de construction pour chaque projet, comme indiqué ci-dessus. De préférence, il peut être divisé en plusieurs sous-projets, comme build/projectA, build/ProjectB afin que si je dois reconstruire un seul projet, je puisse supprimer l'ensemble build/Project fichier et tout est parti et un nouveau Cmake le reconstruira.

J'ai des difficultés à configurer CMAKE.

Mon CMakeList.txt d'origine sur le dossier du projet:

cmake_minimum_required(VERSION 3.2.2.)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../bin)

project(projectA)
set(CMAKE_BUILD_TYPE Debug)

file(GLOB SOURCES "*.cpp")

add_library(commonmessage SHARED ${SOURCES})

install(TARGETS commonmessage DESTINATION ../lib)

Mes questions sont:

A) Que se passera-t-il si j'exécute cmake sur un seul répertoire de construction - est-ce possible et quelle serait la configuration CMAKE correcte?

B) Ma compilation pour ProjectA doit inclure des fichiers de ProjectB - comment puis-je définir cela dans le CMakeLists.txt pour chaque projet individuel?

C) À la fin, j'ai besoin d'un seul makefile pour tout construire, ainsi que l'option de construire chaque projet individuellement. Cela sera-t-il possible avec un seul répertoire de construction?

Merci pour ton aide.

21
Mendes

Tout d'abord, il ne semble pas que le code CMake que vous avez publié appartient au fichier CMakeList.txt supérieur, car il fait directement référence aux fichiers .cpp et "projectA". Il y a aussi quelques choses qui ne sont pas idiomatiques:

cmake_minimum_required(VERSION 3.2.2.)

pourquoi le point de fuite ici? Je ne sais pas si cmake se plaindra, mais cela ne sert à rien.

set(CMAKE_BUILD_TYPE Debug)

Ne fais pas ça. Appelez plutôt cmake à l'aide de l'indicateur de ligne de commande -DCMAKE_BUILD_TYPE=Debug, Utilisez ccmake ou une interface graphique ou modifiez le fichier CMakeCache.txt.

file(GLOB SOURCES "*.cpp")

Ne fais pas ça non plus. Il est recommandé de répertorier explicitement les fichiers source dans CMake, car la globalisation ne permet pas à cmake de détecter automatiquement les fichiers nouvellement ajoutés ou supprimés. Certaines personnes pourraient cependant être en désaccord.

Maintenant, pour le cœur du sujet, voici comment les choses se font généralement:

Fichier CMakeLists.txt supérieur:

cmake_minimum_required(VERSION 3.2.2)
project(globalProject)

add_subdirectory(projectA)
add_subdirectory(projectB)

Fichier ProjectA CMakeLists.txt (en supposant que projectA est un exécutable):

add_executable(projectA file1.cpp file2.cpp ... )
include_directories(${CMAKE_SOURCE_DIR}/projectB) # include files from ProjectB
target_link_libraries(projectA projectB)

install(TARGETS projectA RUNTIME DESTINATION bin)

Fichier ProjectB CMakeLists.txt (en supposant que projectB est une bibliothèque):

add_library(projectB file1.cpp file2.cpp ... )

install(TARGETS projectB
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib)

Veuillez noter que cette configuration nécessite l'étape make install Pour créer bin et lib à l'emplacement de votre choix comme indiqué dans l'invocation de cmake -DCMAKE_INSTALL_PREFIX=.. En ligne de commande (en supposant que make est exécuté à partir du répertoire de construction) .

De plus, cette configuration vous permet de choisir si vous souhaitez créer des bibliothèques statiques ou partagées, en utilisant: -DBUILD_SHARED_LIBS=ON. Pour construire les deux, vous devez avoir deux appels add_library Avec deux noms différents, l'un STATIC, l'autre SHARED.

Pour résumer les étapes nécessaires au bon fonctionnement:

$ mkdir build && cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=.. -DBUILD_SHARED_LIBS=ON
$ make
$ make install

Vous pouvez mettre ces commandes dans un script pour les réutiliser.

Maintenant, vous pouvez répondre à vos questions:

A) c'est possible et recommandé, voir le code ci-dessus, un seul répertoire de build est nécessaire.

B) Voir le code du projectA/CMakeLists.txt, vous devez appeler include_directories()

C) Oui c'est possible. Chaque cible de votre projet peut être générée individuellement à partir du répertoire de génération en utilisant make et le nom de la cible: make projectB Et make projectA

35
SirDarius

A) Vous pouvez faire 1 CMakeLists.txt pour N projets. Lorsque vous définissez une bibliothèque, vous pouvez l'utiliser dans un exécutable défini dans le cmake (add_executable et target_link_libraries pour voir).

B) voir target_include_directories

C) il semble que vous puissiez appeler cmake --target target pour générer le Makefile pour une seule des cibles de votre fichier cmakelists.txt.