8
votes

Ajouter Boost au projet CMake?

Contexte

Je suis un novice complet avec C ++ et j'ai eu un mal de tête après l'autre, alors pardonnez-moi si c'est incroyablement simple et je suis juste que stupide em> ...

J'ai un projet qui devrait finalement être compilé et exécuté sous Linux. Malheureusement, après beaucoup de problèmes avec mon environnement de développement C ++ (toujours non résolus), j'ai renoncé à essayer à développer sous Linux et déplacé vers Windows Visual Studio 2017. Mon espoir était de faire fonctionner mon code sous Windows et ensuite, puisque C ++ est censé être un langage portable, il devrait simplement fonctionner sous Linux avec des changements minimes.

Pendant un jour ou deux, Visual Studio a semblé fonctionner. Je pourrais écrire du code, appuyer sur "compiler" et, comme par magie, il fonctionnerait. J'ai rassemblé quelques classes pour construire un graphe acyclique dirigé, utilisé la bibliothèque standard pour une table de hachage, puis j'ai essayé de créer une socket ...

Windows et Linux utilisent des bibliothèques différentes pour les sockets ( vs ) donc j'avais besoin d'un moyen d'abstraire les différences, et je préférais un standard bien établi. En cherchant sur Google, j'ai trouvé la bibliothèque Boost qui semblait répondre à mes besoins ... C'est alors que tout est allé en enfer.

Configuration de mon projet

Parce que ce projet sera développé sur une variété de plates-formes et d'EDI (certaines personnes utilisent Windows + Visual Studio, certaines personnes utilisent Mac + Eclipse et d'autres utilisent Linux + VIM) J'ai choisi d'en faire un projet CMake. Après plusieurs heures de lecture, d'apprentissage et de recherche, il semble que CMake devrait me donner ce que je veux (builds multiplateformes pratiques et reproductibles avec peu ou pas de problèmes de dépendance)

 Création d'un nouveau projet, pt 1 Création d'un nouveau projet, pt 2

Mon code source (directement à partir du Guide de démarrage Boost sous Windows ) est le suivant:

CMakeProject2.cpp

XXX

Conformément au Boost Getting Started sur le guide Windows , j'ai téléchargé Boost à partir d'ici:

https://dl.bintray.com/boostorg/release/1.67.0/source/boost_1_67_0.zip

(il est intéressant de noter que le guide de mise en route est intitulé " Boost Getting Started on Windows - 1.69.0 ", mais il était lié aux versions Boost 1.67.0)

Après avoir téléchargé et extrait le fichier ZIP, j'avais tout un tas de fichiers - mais n o idée où les mettre:

 Boost download directory

Tentatives pour le faire fonctionner jusqu'à présent

J'ai essayé de ajouter la bibliothèque Boost à mon projet , mais aucune des options de menu attendues n'était disponible:

 Clic droit sur le projet dans l'Explorateur de solutions

Bien que je n'a pas pu find un single a > page qui vous avertit de ce problème, apparemment Les projets CMake n'ont pas la fenêtre insaisissable "Propriétés" - et à la place, les bibliothèques tierces doivent en quelque sorte être incluses via le fichier CMakeLists.txt

Pour commencer, j'ai copié le entier em> Contenu de 540 Mo du fichier ZIP Boost dans mon projet sous le nom de dossier "Boost":

 Boost in project

J'ai ensuite essayé une série de différentes commandes CMakeList.txt:

Par Comment ajouter des bibliothèques Boost dans CMakeLists.txt? :

# CMakeList.txt : CMake project for CMakeProject2, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)

# Add source to this project's executable.
file(GLOB CMakeProject2_SRC
    "*.h"
    "*.cpp"
    "**/*.h"
    "**/*.cpp"
    "**/*.hpp"
    "boost/lambda/lambda.hpp"
)
add_executable (CMakeProject2 ${CMakeProject2_SRC})
#add_executable (CMakeProject2 "CMakeProject2.cpp" "CMakeProject2.h")

# TODO: Add tests and install targets if needed.

Par https : //www.selectiveintellect.net/blog/2016/7/29/using-cmake-to-add-third-party-libraries-to-your-project-1 :

#include "boost/lambda/lambda.hpp"
#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
    using namespace boost::lambda;
    typedef std::istream_iterator<int> in;

    std::for_each(
        in(std::cin), in(), std::cout << (_1 * 3) << " ");
}

Par https://cmake.org/pipermail/ cmake / 2009-novembre / 033249.html :

SET (Boost_FIND_REQUIRED TRUE)
SET (Boost_FIND_QUIETLY TRUE)
SET (Boost_DEBUG FALSE)
set (Boost_USE_MULTITHREADED TRUE)
set (Boost_USE_STATIC_LIBS TRUE)
SET (Boost_ADDITIONAL_VERSIONS "1.67" "1.67.0")

FIND_PACKAGE(Boost COMPONENTS  lambda)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})

J'ai essayé plusieurs autres incantations (ne connaissant pas le C ++ ou em > CMake en tant qu'outil) et a reçu des erreurs de CMakeLists.txt, ou de CMakeProject2.cpp à propos de ne peut pas ouvrir le fichier source "boost / lambda / lambda.hpp" . En fait, en ce qui concerne ces erreurs "CMakeLists.txt", après avoir ajouté assez lignes à mon fichier, j'ai commencé à planter Visual Studio régulièrement. Notez que j'ai un i7 de 8e génération, 32 gigaoctets de RAM et un disque dur M.2 NVMe - j'ai donc été plutôt impressionné que quelques lignes dans un fichier texte aient assez énervé Microsoft pour verrouiller mon ordinateur pendant 10 minutes à une fois.

À défaut de tout cela, j'ai essayé de copier les fichiers dont j'avais besoin directement dans mon projet:

 Nouvelle configuration du projet

Maintenant, encore une fois, je suis nouveau dans le développement C / C ++ et tout ce qui peut mal tourner a mal tourné. Jusqu'à présent, j'ai passé près de deux semaines et j'ai à peine réussi à compiler une seule application "Hello, World" sur deux ordinateurs, trois IDE et quatre compilateurs. Je n'ai pas encore eu de succès, y compris une bibliothèque tierce, de n'importe où, de n'importe quel niveau de popularité ou niveau de simplicité, et compile réellement un programme fonctionnel qui fait référence à la bibliothèque. Alors croyez-moi quand je dis: je ne connais pas la différence entre une "bibliothèque d'en-tête seulement" et ... quelle que soit l'alternative. Je sais juste que, selon le Boost Getting Started on Windows un> guide, la plupart de Boost est "en-têtes seulement" et donc je ne devrais pas avoir d'étape de construction - cela devrait être simple à utiliser. De plus, cet exemple (utilisant boost :: lambda ) est - selon leurs instructions - une bibliothèque d'en-tête uniquement, et devrait donc être extrêmement facile à utiliser.

J'ai maintenant mis à jour le code source légèrement pour regarder dans le répertoire courant, au lieu de chercher dans le répertoire d'inclusion du système (qui, pour autant que je sache à ce stade, n'existe pas dans Windows):

include("Boost")
add_subdirectory("Boost")
add_subdirectory("boost")
add_subdirectory("Boost/boost")
add_subdirectory("Boost/boost/lambda")

target_link_libraries(boost)
target_link_libraries(Boost)


6 commentaires

Essayez d'utiliser l'API basée sur la cible. target_link_libraries (you_exe PUBLIC boost :: lambda) Cette commande unique devrait ajouter le répertoire d'inclusion ainsi que les bibliothèques de liaison.


@GuillaumeRacicot imgur.com/ChwBo57 Pas de chance


Pour travailler avec target, vous devez d'abord trouver le package boost: find_package (Boost COMPONENT lambda REQUIRED)


Donc find_package (Boot COMPONENTS lambda REQUIRED) a renvoyé l'erreur "Impossible de trouver les bibliothèques Boost demandées. Veuillez définir BOOST_ROOT sur le répertoire racine ...". J'ai ensuite ajouté set (BOOST_ROOT "C: \\ local \\ boost_1_69_0") et pour la première fois j'ai vu "Boost version: 1.69.0" (en cours de progression!) Suivi brièvement de "Impossible de trouver les bibliothèques Boost suivantes: lambda. Aucune bibliothèque Boost n'a été trouvée. Vous devrez peut-être définir BOOST_LIBRARYDIR ... ". J'ai essayé set (BOOST_LIBRARYDIR "$ {BOOST_ROOT} \\ libs") (entre autres) mais pas encore de chance


J'ai eu une erreur similaire la première fois en essayant avec boost. Je ne suis pas avec mon ordinateur principal pour le moment, je vous préviendrai lorsque j'y aurai physiquement accès. Je sais que j'ai réussi à le faire fonctionner. D'après ce dont je me souviens, c'était cmake de ne pas détecter correctement les nouvelles versions de boost, mais je ne peux pas être sûr à 100% pour le moment.


Je tripote ma configuration, je pense que j'aurai une réponse pour vous. C'était bien la version (pour moi)


3 Réponses :


0
votes

Ajoutez un target_include_directories (CMakeProject2 PRIVATE.) dans votre CMakeList.txt .

Le. est le chemin relatif de boost / lambda / lambda.hpp depuis CMakeLists.txt

Et vous ne devez pas ajouter de fichier .hpp à la liste source.


6 commentaires

Eh bien, je regarde votre capture d'écran ... d'abord, la commande target_include_directories () consiste à ajouter un répertoire d'inclusion à une cible cmake (c'est-à-dire l'exécutable CMakeProject2). et doit être mis après add_executable (). Il est également préférable de mettre des noms de fichiers explicites dans add_executable (), pas dans un glob. Dans votre cas: add_executable (CMakeProject2 CMakeProject2.cpp).


Mais cela n'explique pas vraiment pourquoi boost / lambda / lambda.hpp ne peut pas être trouvé.


imgur.com/l7ywL6e - Une erreur persiste après avoir déplacé target_include_directories et remplacé le < code> glob avec des noms de fichiers explicites


Le problème m'intrigue ... Donc je viens de mettre en place un projet comme le vôtre ... testé avec cmake 3.6 (Linux) et 3.13 (macOS) - ok ce n'est pas vs2017 et windows. Et cela fonctionne, comme vous pouvez le deviner. github.com/rene-d/test-CMakeProject2 .


Cela ressemble aux problèmes que j'ai rencontrés avec Clang ++ (voir: stackoverflow.com/questions / 54521402 / locating-iostream-in-cl‌ ang ) J'ai fini par rejoindre l'IRC Clang et le débogage pendant plusieurs heures et personne ne pouvait le comprendre . Parfois, j'ai l'impression que c'est ma vie: xkcd.com/2083


continuons cette discussion dans le chat .



5
votes

La recette suivante devrait fonctionner

Téléchargez les binaires Boost à partir de emplacement officiel des binaires boost et installez pour dire C: \ Boost

La plupart du temps, vous n'avez pas besoin de créer Boost vous-même.

Votre CMakeLists.txt devrait ressembler à ce qui suit

cmake -H. -Bbuildit -G "Visual Studio 15 2017" -DBOOST_ROOT=C:\Boost 

Parce que nous avons utilisé REQUIRED lors de l'appel find_package , CMake échouera l'exécution et ignorera le reste du script s'il est introuvable . Donc pas besoin de vérifier Boost_FOUND . Vous devez le vérifier lorsque vous omettez REQUIRED .

Maintenant, à partir de l'appel en ligne de commande depuis le répertoire où réside votre script:

cmake_minimum_required (VERSION 3.8)

project(boostAndCMake)

set(BOOST_ROOT "C:\Boost") # either set it here or from the command line  
set(Boost_USE_STATIC_LIBS OFF) 
set(Boost_USE_MULTITHREADED ON)  
set(Boost_USE_STATIC_RUNTIME OFF) 
find_package(Boost REQUIRED COMPONENTS system) # header only libraries must not be added here

add_executable(CMakeProject2 CMakeProject2.cpp CMakeProject2.h) 
target_include_directories(CMakeProject2 PUBLIC ${Boost_INCLUDE_DIRS}) 
target_link_libraries(CMakeProject2 ${Boost_LIBRARIES})

Cela crée un répertoire de construction nommé buildit dans le répertoire courant, crée en outre une solution pour Visual Studio 2017 dans le répertoire de construction et fournit le paramètre de la variable BOOST_ROOT qui est utilisée dans l'appel find_package pour identifier le répertoire Boost sur votre ordinateur. Pour voir quelles options sont disponibles sur l'appel find_package (Boost ...) , voir FindBoost dans CMake.

Bibliothèques d'en-tête uniquement

Si vos bibliothèques ne sont que des en-têtes, vous devez les omettre du find_package (Boost ...) code > appeler. Pour voir quelles bibliothèques ne sont pas en-tête, consultez uniquement ce post .

Utilisation des nouvelles versions de Boost

Si votre installation CMake ne trouve pas la version demandée, par exemple 1.69.0, mais prend en charge le schéma de dénomination de la version plus récente de Boost, vous pouvez l'utiliser avec set (Boost_ADDITIONAL_VERSIONS "1.69.0" "1.69") . La dernière modification du schéma de dénomination Boost est passée de 1.65.1 à 1.66.


15 commentaires

D'après ce que je peux dire, le lien "Télécharger la dernière version" en haut ne fait que télécharger une version plus ancienne (1.66.0 contre 1.67.0) de ce que j'avais déjà - un répertoire contenant plusieurs fichiers d'en-tête Boost, des documents, etc. vous avez dit de télécharger le "binaire" Boost, je suppose que vous vouliez dire l'un des fichiers EXE qui se trouve dans les dossiers de version. En cliquant sur "1.69.0", il a révélé plusieurs EXE - comment savoir lequel télécharger? Je ne sais pas quelle est ma version MSVC (ou comment la comprendre): imgur.com/3TRTJgl


Il s'agit de MSVC 14.1 pour votre compilateur Visual Studio 15 2017. Voir ici: blogs.msdn.microsoft.com/vcblog/2017/11/15/…


Téléchargé boost_1_69_0-msvc-14.1-64 , double-cliqué sur l'exécutable, accepté d'exécuter une application d'un éditeur inconnu, Windows "Antimalware Service Executable" a commencé à verrouiller tout mon système. Si cela continue trop longtemps, je vais simplement désactiver l'antimalware / antivirus et réessayer. Pour le moment, explorer.exe ne répond pas


Si vous installez la version Boost 64 bits, vous devrez également adapter le générateur: il s'agit alors de Visual Studio 15 2017 Win64 . La taille de l'exécutable d'installation Boost est de plus de 200 Mo et contient littéralement des dizaines de fichiers de taille minuscule, petite et moyenne. Cela peut prendre du temps.


Après que mon ordinateur soit resté sans réponse pendant 20 minutes, j'ai coupé l'alimentation, redémarré et essayé à nouveau (sans désactiver d'abord l'antivirus, pour voir si c'était un hasard s'il a gelé pendant si longtemps). L'explorateur se figea à nouveau. 10 minutes plus tard, j'ai fait un autre arrêt dur, redémarré, désactivé l'antivirus et l'ai exécuté - a fonctionné immédiatement. Ensuite, j'ai essayé votre CMakeLists.txt, toujours pas bon: imgur.com/sz8mbnu


J'ai tendance à oublier d'ajouter le mot-clé PUBLIC , PRIVATE ou INTERFACE après la cible. Il devrait donc lire target_include_directories (CMakeProject2 PUBLIC $ {Boost_INCLUDE_DIRS})


Avec la ligne target_include_directories mise à jour, je suis maintenant au même point que j'étais avec la réponse de @ GuillaumeRacicot: "Aucune bibliothèque Boost n'a été trouvée. Vous devrez peut-être définir BOOST_LIBRARYDIR sur le répertoire contenant les bibliothèques Boost ou BOOST_ROOT t othe emplacement de Boost. "


UPDATE: Après avoir relu votre message (potentiellement avec vos nouvelles modifications), j'ai remarqué le message "Si vos bibliothèques ne sont que des en-têtes, vous devez les omettre du find_package (Boost ...) appel ". J'ai supprimé lambda de l'appel et cela a fonctionné! ... (double mise à jour: semble avoir fonctionné. Aucune erreur dans la console maintenant, mais quand j'essaye de compiler Visual Studio se bloque)


Ouais, c'est le problème avec les bibliothèques d'en-tête Boost uniquement. Ils ne doivent pas être mentionnés dans l'appel des composants! Je vais rendre cette phrase plus visible dans la réponse.


Donc, après avoir redémarré Visual Studio, j'ai un nouveau problème, je ne sais pas s'il est lié ou non ... Il n'y a plus d'erreurs dans la console d'erreur, mais je ne peux pas du tout générer le projet! Lorsque je sélectionne "Document actuel" (valeur par défaut), il affiche "Sélectionner l'élément de démarrage ..." et la tentative de création génère une erreur: imgur.com/r1MHXFw imgur.com/m7fy43o Lorsque je sélectionne "CMakeProject2.exe" I obtenez l'erreur "Le projet de démarrage n'a pas pu être lancé." imgur.com/9IwIKG9


Définissez dans l'explorateur de solutions le projet que vous essayez d'exécuter en tant que projet de démarrage. Par défaut, CMake définit ALL_BUILD qui n'est pas connecté à un exécutable ou à une bibliothèque.


Je ne sais pas comment définir le "projet de démarrage". Je n'utilise pas beaucoup Visual Studio :( En cliquant beaucoup, j'ai pu le réparer accidentellement, mais je ne sais pas pourquoi il l'a corrigé. J'ai cliqué sur le menu déroulant à côté de la cible de compilation et sélectionné "Gérer les configurations" et a créé une configuration x64-Release. Cela a fait disparaître la configuration x64-Debug et créé un nouveau fichier CMakeSettings.json . J'ai supprimé le fichier CMakeSettings.json , x64 -Debug est réapparu, et tout à coup "Document actuel" a fonctionné et j'ai pu construire le projet!


Je viens de regarder à nouveau les images. Avez-vous appelé CMake à partir de la ligne de commande ou avez-vous ouvert le fichier CMake à partir de Visual Studio. C'est une grosse différence. J'ai remarqué qu'à l'intérieur de ninja est appelé comme outil de construction alors qu'il devrait être MSBuild. (au moins dans Visual Studio 2015, c'est le cas, je ne sais pas pour 2017.) J'utilise toujours la ligne de commande pour CMake et j'ouvre plus tard la solution créée.


J'ai édité les fichiers CMake dans Visual Studio et chaque fois que je clique sur Enregistrer, il analyse à nouveau automatiquement le fichier met à jour Intellisense. En regardant la ligne de commande, je vois -G "Ninja" , quoi que cela signifie. Est-ce cela qui cassait ma construction?


Je ne sais pas, peut-être. Visual Studio a beaucoup changé de la version 2015 à 2017, donc je ne fais que deviner. Ils ont vraiment intégré le contenu de CMake, mais il y a quelques différences avec la version de ligne de commande IIRC.



2
votes

Voici une configuration fonctionnelle pour Boost 1.68 avec CMake 3.12. Boost 1.69 est apparemment "trop ​​nouveau" pour que cmake le détecte correctement. Puisque le boost n'est pas compilable par cmake, cmake lui-même doit fournir un module FindBoost.cmake qui doit suivre les changements de boost.

De toute façon, le CMakeLists.txt est aussi petit que ceci:

ls -l /c/local/
total 12
drwxr-xr-x 1 myself 197609 0 May 26  2018 boost_1_67_0/
drwxr-xr-x 1 myself 197609 0 Sep  5 02:02 boost_1_68_0/

Bien sûr, vous pouvez le diviser en plusieurs sous-répertoires.

L'appel de CMake dans la ligne de commande devrait ressembler à ceci:

cmake -DCMAKE_PREFIX_PATH=path_to_local_directory ..

path_to_local_directory est le chemin d'installation de toutes la bibliothèque dont vous voulez dépendre. Cela fonctionnera pour Boost, nlohmann_json, glfw3, Qt, nommez-le * (1). Pour mon cas, c'était C: / local / et un autre cas était ../external/ (oui, ça peut être un répertoire local au projet!) p>

Jetons un coup d'œil à mon propre C:/local/:

cmake_minimum_required(VERSION 3.11)

project(foobar)

find_package(Boost 1.68 REQUIRED)
add_executable(foo foo.cpp)
target_link_libraries(foo PUBLIC Boost::boost)

AVERTISSEMENT : assurez-vous que l'architecture de votre compilateur est la même que la version boost installée. Sinon, cmake ne le trouvera tout simplement pas.

J'y pense. La prochaine version de CMake (3.14) devrait fonctionner avec le dernier boost.


* (1) Cette bibliothèque devra soit exporter sa cible CMake, soit fournir un FindXXX.cmake p >


2 commentaires

Si votre version de CMake prend en charge le schéma de dénomination de la version Boost la plus récente, vous pouvez l'utiliser avec set (Boost_ADDITIONAL_VERSIONS "1.69.0" "1.69") . Le dernier changement du schéma de dénomination Boost est passé de 1.65.1 à 1.66.


@vre merci pour cette info, je vais l'essayer sur mon projet.