Je suis nouveau dans les projets CMake et je souhaite utiliser la bibliothèque du système de fichiers dans mon projet. J'utilise Ubuntu 18.04 avec GCC 8.2 et CMake 3.13. Pour ce faire, j'ai essayé deux options:
Option 1
cmake_minimum_required(VERSION 3.13) project(TheFsProject) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_executable(TheFsProject main.cpp) target_link_libraries(TheFsProject stdc++fs)
Cela n'aide pas car le compilateur ne trouve toujours pas le système de fichiers bibliothèque pendant la compilation.
Option 2 (copiée à partir de: https://www.scivision.co/cmake-cpp-17-filesystem/ a>)
(CHECK_CXX_SYMBOL_EXISTS): CHECK_CXX_SYMBOL_EXISTS Macro invoked with incorrect arguments for macro named: CHECK_CXX_SYMBOL_EXISTS
Cela n'aide pas non plus car j'obtiens une erreur CMake que je n'ai pas comprendre.
make_minimum_required(VERSION 3.13) project(TheFsProject) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_REQUIRED_FLAGS -std=c++17) include(CheckCXXSymbolExists) CHECK_CXX_SYMBOL_EXISTS(std::filesystem::path::preferred_separator cxx17fs) if(cxx17fs) add_executable(TheFsProject main.cpp) set_property(TARGET TheFsProject PROPERTY CXX_STANDARD 17) endif()
Je me sens hors de ma profondeur sur ce sujet, c'est pourquoi je suis venu ici. Cela ne me dérange pas de travailler davantage pour en savoir plus, mais je ne sais plus où chercher. Toute aide serait appréciée!
Merci pour les réponses à ce jour! J'ai créé l ' Option 3 sur la base de vos commentaires:
cmake_minimum_required(VERSION 3.13) project(TheFsProject) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS "-std=c++17 -lstdc++fs")
Malheureusement, cela ne résout pas mon problème. Il émet toujours une erreur lors de la compilation qu'il ne trouve pas l'en-tête de compilation.
Merci pour toutes les réponses jusqu'à présent. Tout cela aide. J'ai essayé Ashkan sa réponse en dernier (parce que cela semblait intimidant). Celui-ci retourne
Le compilateur ne dispose pas de fonctionnalités de système de fichiers.
donc je suppose que quelque chose ne va pas à cette fin. Ceci est utile dans le sens où je sais maintenant que ce n'est probablement pas dû à mon fichier CMake. Je dois maintenant découvrir pourquoi le compilateur prend en charge l'en-tête du système de fichiers ...
À proprement parler, cette question est répondue parce que ma question concerne le fichier CMake. Je vais marquer Ashkan sa réponse comme la solution simplement parce qu'elle a produit l'étape suivante dans ma recherche de dépannage. Si je pouvais, je marquerais également sa réponse car je pense que c'est aussi une très bonne réponse. Merci à tous!
4 Réponses :
CHECK_CXX_SYMBOL_EXISTS
prend trois arguments, pas deux:
CHECK_CXX_SYMBOL_EXISTS(std::filesystem::path::preferred_separator filesystem cxx17fs)
Vous avez oublié d'indiquer à CMake où chercher les symboles (l'en-tête qui les déclare). p>
Malheureusement sur GCC-8, cela retournera vrai dans cxx17fs
même si stdc ++ fs
peut être nécessaire pour une liaison réussie.
Y a-t-il un autre symbole que nous pouvons vérifier pour cela? Heureux de mettre à jour ma réponse, ou heureux de voter pour votre réponse avec un test fonctionnel pour gcc-8 (et plus, je suppose).
Aucune idée, c'est la première fois que je joue avec ça. J'oserais deviner que std :: filesystem :: path :: prefer_separator
peut être trouvé car il compile des en-têtes dans l'exécutable cible ou même que certains de ces symboles sont déjà dans libstdc ++
. J'envisagerai d'essayer un autre symbole stdc ++ fs
la prochaine fois que je serai dans cette branche.
Gcc 8.2. est livré avec
, il n'est donc pas nécessaire d'enquêter sur la disponibilité. Ensuite, l'option 1 est suffisante, mais nécessite une correction:
set(CMAKE_CXX_STANDARD 17) # no need to manually adjust the CXXFLAGS add_executable(yourExecutable yourSourceFile.cpp) target_link_libraries(yourExecutable stdc++fs)
Cela devrait aboutir à la compilation des sources avec -std = c ++ 17
ou - std = gnu ++ 17
et en ajoutant -lstdc ++ fs
lors de la liaison.
Modifier: notez que comme @Ashkan l'a souligné dans les commentaires, le paramètre CMAKE_CXX_STANDARD_REQUIRED à true
résultats dans une erreur immédiate au moment de la configuration si C ++ 17 n'est pas pris en charge par le compilateur, au lieu d'une erreur de compilation (en raison de l'en-tête
manquant) ou au moment du lien (en raison de l'absence bibliothèque partagée). Cela pourrait être souhaitable.
Je pense que vous avez également besoin de cet indicateur -DCMAKE_CXX_STANDARD_REQUIRED = ON
Cela entraînerait l'échec immédiat de l'étape de configuration si le compilateur ne prend pas en charge le paramètre standard requis, non? Je dirais alors que c'est facultatif, car la compilation ne réussirait pas si C ++ 17 n'est pas pris en charge.
C'est vrai, mais si vous pouvez obtenir l'erreur au bon endroit, il est plus facile de la résoudre. De cette façon, cmake quitterait au lieu de laisser make donner une erreur de compilation.
En plus de la réponse de @ lubgr. Je pense qu'un moyen plus complet est également de faire try_compile pour voir que vous pouvez réellement utiliser l'en-tête du système de fichiers. C'est à mon avis mieux car certains compilateurs ne prennent pas encore en charge std :: filesystem. Aussi dans gcc 7.x vous avez le système de fichiers sous l'espace de noms experimental
. De cette façon, vous pouvez avoir un try_compile séparé dans la clause else
et le détecter.
Voici le cmake associé
#include <filesystem> namespace fs = std::filesystem; int main() { fs::path aPath {"../"}; return 0; }
Le fichier tests / has_filesystem.cc est très simple
# set everything up for c++ 17 features set(CMAKE_CXX_STANDARD 17) # Don't add this line if you will try_compile with boost. set(CMAKE_CXX_STANDARD_REQUIRED ON) # test that filesystem header actually is there and works try_compile(HAS_FS "${CMAKE_BINARY_DIR}/temp" "${CMAKE_SOURCE_DIR}/tests/has_filesystem.cc" CMAKE_FLAGS -DCMAKE_CXX_STANDARD=17 -DCMAKE_CXX_STANDARD_REQUIRED=ON LINK_LIBRARIES stdc++fs) if(HAS_FS) message(STATUS "Compiler has filesystem support") else() # .... You could also try searching for boost::filesystem here. message(FATAL_ERROR "Compiler is missing filesystem capabilities") endif(HAS_FS)
Vous pouvez dans votre clause else try_compile pour boost :: filesystem et passer une directive qui peut être utilisée dans votre fichier source où vous décidez si vous voulez utiliser le système de fichiers c ++ 17 ou boost.
J'ai trouvé un cas où try_compile
n'était pas suffisant: lors de l'utilisation du compilateur Intel C ++ ( icpc (ICC) 19.1.1.216 20200306
) en mode C ++ 17 fonctionnant sous MacOS "Mojave" 10.14.6. Le programme de test recommandé par @Ashkan s'est compilé sans erreur, et il a même fonctionné. Cependant, mon code utilise fs :: path :: filename ()
à un moment donné et qui a entraîné une erreur de l'éditeur de liens d'exécution ( dyld: lazy symbol binding failed: Symbol not found:
). En d'autres termes: l'en-tête est là, l'implémentation n'est apparemment pas (?). Je n'ai pas étudié cela plus en détail.
La solution est d'utiliser try_run
au lieu de try_compile
et (dans mon cas) de revenir à boost :: système de fichiers
si std :: filesystem
n'est pas encore pris en charge.
Voici la section de code CMake appropriée:
// == PROGRAM has_stdfs.cc == // Check if std::filesystem is available // Source: https://stackoverflow.com/a/54290906 // with modifications #include <filesystem> namespace fs = std::filesystem; int main(int argc, char* argv[]) { fs::path somepath{ "dir1/dir2/filename.txt" }; auto fname = somepath.filename(); return 0; }
Notez que la variable RUNS_WITH_STDFS
n'est pas mise à NO
en cas d'échec mais à "FAILED_TO_RUN"
qui n'est pas interprétée comme un FALSE
Boolean (voir CMake if ()
docs :
if () True si la constante est 1, ON, YES, TRUE, Y ou a nombre différent de zéro. Faux si la constante est 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, la chaîne vide ou se termine par le suffixe -NOTFOUND.
j'ai donc dû comparer sa valeur.
Le petit programme de test a également un peu changé par rapport à la solution de @ Ashkan:
try_run(RUNS_WITH_STDFS COMPILES_WITH_STDFS "${CMAKE_BINARY_DIR}/try" "${CMAKE_SOURCE_DIR}/cmake/has_stdfs.cc" CMAKE_FLAGS CMAKE_CXX_STANDARD=17 CMAKE_CXX_STANDARD_REQUIRED=ON ) if (RUNS_WITH_STDFS STREQUAL "FAILED_TO_RUN") message(STATUS "Using boost::filesystem instead of std::filesystem") set(_boost_components ${_boost_components} filesystem system) add_definitions(-DUSE_BOOST_FILESYSTEM) else() message(STATUS "std::filesystem supported") endif()
Pour ceux qui sont intéressés, j'ai fait une erreur en pensant que j'avais GCC et G ++ 8.2. J'ai fait cette erreur parce que CLion rapporte qu'il a GDB 8.2 et je pensais que cela impliquerait que GCC 8.2 et G ++ 8.2 sont installés. De plus, je m'attendais à ce qu'ils soient installés car je ne vois pas vraiment pourquoi cela ne serait pas mis à jour automatiquement par le gestionnaire de paquets. J'avais tort; Ubuntu 18.04 est livré avec la version 7.3 et ne la met pas à jour automatiquement. Vous devez résoudre ce problème manuellement.
Certaines versions de Boost utilisent l'indicateur
Boost_INCLUDE_DIR
et d'autres utilisent l'indicateurBoost_INCLUDEDIR
( sans le trait de soulignement ). Vous pouvez vérifier le bon pour votre cas en lisant le fichierFindBoost.cmake
, souspath-to-cmake / Modules / FindBoost.cmake