web-dev-qa-db-fra.com

Impossible de lier le programme à l'aide de Boost.Filesystem

J'essaie de lancer un programme en utilisant un exemple de code de boost :: filesystem sur Ubuntu 12.10, mais il ne veut pas construire.

#include <iostream>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
using namespace std;

void fun(const string& dirPath);
int main()
{
    fun("/home");
    return 0;
}

void fun(const string& dirPath)
{
    path p (dirPath); 

    if (exists(p))  
    {
        if (is_regular_file(p))   
            cout << p << " size is " << file_size(p) << '\n';

        else if (is_directory(p))    
            cout << p << "is a directory\n";

        else
            cout << p << "exists, but is neither a regular file nor a directory\n";
    }
    else
        cout << p << "does not exist\n";
}

Et code CMake:

project(tttest)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
FIND_PACKAGE(Boost 1.53 COMPONENTS filesystem system REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
link_directories(${Boost_LIBRARY_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${Boost_LIBRARIES})

Malheureusement, cela génère des erreurs

CMakeFiles/tttest.dir/main.cpp.o: In function `boost::filesystem::exists(boost::filesystem::path const&)':
main.cpp:(.text._ZN5boost10filesystem6existsERKNS0_4pathE[_ZN5boost10filesystem6existsERKNS0_4pathE]+0x19): undefined reference to `boost::filesystem::detail::status(boost::filesystem::path const&, boost::system::error_code*)'
CMakeFiles/tttest.dir/main.cpp.o: In function `boost::filesystem::is_directory(boost::filesystem::path const&)':
main.cpp:(.text._ZN5boost10filesystem12is_directoryERKNS0_4pathE[_ZN5boost10filesystem12is_directoryERKNS0_4pathE]+0x19): undefined reference to `boost::filesystem::detail::status(boost::filesystem::path const&, boost::system::error_code*)'
CMakeFiles/tttest.dir/main.cpp.o: In function `boost::filesystem::is_regular_file(boost::filesystem::path const&)':
main.cpp:(.text._ZN5boost10filesystem15is_regular_fileERKNS0_4pathE[_ZN5boost10filesystem15is_regular_fileERKNS0_4pathE]+0x19): undefined reference to `boost::filesystem::detail::status(boost::filesystem::path const&, boost::system::error_code*)'
CMakeFiles/tttest.dir/main.cpp.o: In function `boost::filesystem::file_size(boost::filesystem::path const&)':
main.cpp:(.text._ZN5boost10filesystem9file_sizeERKNS0_4pathE[_ZN5boost10filesystem9file_sizeERKNS0_4pathE]+0x19): undefined reference to `boost::filesystem::detail::file_size(boost::filesystem::path const&, boost::system::error_code*)'
collect2: error: ld returned 1 exit status

Quelle est la raison de ce problème et comment le résoudre?

18
adashie

Le système de fichiers Boost est l’une des bibliothèques Boost qui présente un problème ABI relatif au changement de signature de fonction dû à C++ 0x ou C++ 11. cf Boost ticket: https://svn.boost.org/trac/boost/ticket/6779

Vous avez trois solutions:

  1. Inhibez Cums 11 étendues énumérées dans les fichiers d'en-tête Boost inclus dans vos programmes avec #include (cf http://www.ridgesolutions.ie/index.php/2013/05/30/boost-link-error-undefined -reference-to-boostfilesystemdetailcopy_file/ ): 

    #define BOOST_NO_CXX11_SCOPED_ENUMS
    #include <boost/filesystem.hpp>
    #undef BOOST_NO_CXX11_SCOPED_ENUMS
    

    Mais cette solution n’est pas complète et j’ai lu que cela ne fonctionnait pas pour tout le monde.

  2. Construisez BOOST avec l'option C++ 11 (les mêmes options que pour votre application): http://hnrkptrsn.github.io/2013/02/26/c11-and-boost-setup-guide

    Je lis aussi que ça ne marche pas pour tout le monde.

  3. Configurez un compilateur croisé dédié à votre application, dans lequel vous reconstruisez toutes les bibliothèques dont vous avez besoin dans un environnement dédié. Cela garantit la cohérence, la stabilité et une plus grande facilité de maintenance. C’est certainement la solution à recommander. Je n’ai pas lu s’il a été testé - probablement oui, et probablement cela fonctionne. Quoi qu'il en soit, la compilation croisée est maintenant bien maîtrisée en informatique. Vous trouverez de nombreux bons tutoriels et un support pour cela. Dans Linux Gentoo, ils ont le merveilleux paquet sys-devel/crossdev qui le rend très facile.

Dans mon cas, la solution 1 a résolu le problème. Dès que j'en rencontrerai un autre, je passerai à la solution 3. Je ne l'ai donc pas encore testée.

23
lalebarde

Vous devez ajouter la bibliothèque libboost_filesystem lors de la liaison. Ou libboost_filesystem-mt si votre application est multi-threadée. Comme ça:

g++ -o file -lboost_filesystem-mt source_file.cpp
9
Nicolai Tufar

Vous devez ajouter les bibliothèques suivantes:

g++ -o file -lboost_system -lboost_filesystem sourcefile.cpp

Si vous utilisez un Makefile:

CC=gcc
CXX=g++
PROG = program
CXXFLAGS := -std=c++1y -g -Wall
LDFLAGS = -L/usr/local/lib -L/usr/lib/x86_64-linux-gnu
LIBS= -lboost_system -lboost_filesystem

SRCS= main.cpp

OBJS=$(subst .cpp,.o,$(SRCS))

all: $(OBJS)
     $(CXX) $(CXXFLAGS) -o $(PROG) $(OBJS) $(LIBS) $(LDFLAGS)
1
Akinna

Pour certains modules de boost, vous devez compiler les bibliothèques et les lier (en utilisant bootstrap.sh). Dans votre cas, vous devez compiler et lier Filesystem et probablement aussi System

Regardez ici

Par exemple:

  • ./bootstrap.sh (bjam)
  • rm -rf bin.v2 stage (entre 2 commandes bjam)
  • ./bjam release toolset = modèle d'adresse gcc = 64 cxxflags = -fPIC
  • ./bjam outils de débogage = gcc adresse-modèle = 64 cxxflags = -fPIC

Si vous liez sur Windows, vous n'avez pas à lier manuellement vos bibliothèques, car elles sont automatiquement liées à l'aide de pragma. Sous Linux, vous devez le faire.

Selon la documentation, ces modules nécessitent l’acquisition ou la construction d’une bibliothèque:

  • Boost.Filesystem
  • Boost.GraphParallel
  • Boost.IOStreams
  • Boost.MPI
  • Boost.ProgramOptions
  • Boost.Python
  • Boost.Regex
  • Boost.Serialization
  • Boost.Signals
  • Système Boost
  • Boost.Thread
  • Boost.Wave
1
Cyrille

La solution qui a fonctionné pour moi est de compiler avec "-c" puis de créer l'exécutable comme ceci:

g++ -c -o main.o main.cpp
g++ -o my_prog main.o -lboost_system -lboost_filesystem
1
Morad