Boost::Filesystem kompilieren und linken in der Konsole mit GCC



  • Hallo zusammen,

    während ich mit Boost keinerlei Schwierigkeiten in Entwicklungs-IDE's wie Xcode (Mac) oder VS.NET habe, bekomme ich die Code-Beispiele vom Boost::Filesystem (in diesem Fall z.B. simple_ls.cpp, siehe unten) in der Konsole nicht kompiliert. Bin auch kein Experte in Konsolen-Kompilier-Session geschweige denn von Makefiles 🙄 Folgendes gebe ich in der Konsole unter Mac OS X ein, <include-dir> bzw. <library-dir> sind Platzhalter für meine spezifischen Pfade:

    g++ -I<include-dir> -L<library-dir> -lboost_filesystem simple_ls.cpp

    Die Pfade sind definitiv gültig. Entsprechende Beispiele in denen ich keine Library linken muss, quasi die Header-Only Libs, lassen sich problemlos kompilieren. Der obige Befehl inkl. Linken wird mir allerdings folgendermaßen quittiert:

    /usr/bin/ld: Undefined symbols:
    boost::filesystem::detail::remove_api(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
    boost::filesystem::detail::status_api(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int&)
    boost::filesystem::detail::dir_itr_close(void*&, void*&)
    boost::filesystem::detail::dir_itr_first(void*&, void*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, boost::filesystem::file_status&, boost::filesystem::file_status&)
    boost::filesystem::detail::not_found_error
    boost::filesystem::detail::dir_itr_increment(void*&, void*&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, boost::filesystem::file_status&, boost::filesystem::file_status&)
    boost::filesystem::detail::symlink_status_api(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int&)
    boost::filesystem::detail::create_directory_api(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
    boost::filesystem::detail::get_current_path_api(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
    collect2: ld returned 1 exit status

    //  simple_ls program  -------------------------------------------------------//
    
    //  Copyright Jeff Garland and Beman Dawes, 2002
    
    //  Use, modification, and distribution is subject to the Boost Software
    //  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    //  http://www.boost.org/LICENSE_1_0.txt)
    
    //  See http://www.boost.org/libs/filesystem for documentation.
    
    #include "boost/filesystem/operations.hpp"
    #include "boost/filesystem/path.hpp"
    #include "boost/progress.hpp"
    #include<boost/tokenizer.hpp>
    #include <iostream>
    #include <fstream>
    #include <string>
    
    int main(int argc, char* argv[])
    {
    	boost::progress_timer t( std::clog );
    
    	boost::filesystem::path startpath( boost::filesystem::initial_path<boost::filesystem::path>() );
    	std::cout << "Program is executed in " << startpath.native_directory_string() << std::endl << std::endl;
    
    	char *pathvar = NULL;
    	pathvar = getenv( "PATH" );
    
    	std::string *sPathvar = NULL;
    	sPathvar = new std::string[1];
    	sPathvar->assign(pathvar);
    
    	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
    	boost::char_separator<char> sep(":");  // separator unter windows ";"
    	tokenizer tokens(*sPathvar,sep);
    	unsigned int uiQtyOfPaths=0;
    	for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter, ++uiQtyOfPaths)
    	{
    		std::cout << *tok_iter << "\n";
    	}
    	std::cout << "\nFound " << uiQtyOfPaths << " elements\n";
    
    	unsigned int i=0;
    	std::string **sPathSplitted = NULL;
    	sPathSplitted = new std::string*[uiQtyOfPaths];
    	for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter)
    	{
    		sPathSplitted[i] = new std::string[1];
    		sPathSplitted[i]->assign(*tok_iter);
    
    		boost::filesystem::path dirpath(*sPathSplitted[i]);
    		if (is_directory(dirpath))
    		{
    			std::cout << "Valid directory:: " << dirpath.native_directory_string() << std::endl;
    		}
    		else
    		{
    			std::cout << "Invalid directory " << std::endl;
    		}
    
    		i++;
    	}
    
    	for (i=0; i<uiQtyOfPaths; i++)
    	{
    		sPathSplitted[i]->append("\\bjam.exe");
    
    		boost::filesystem::path filepath(*sPathSplitted[i]);
    		if ( !boost::filesystem::exists( filepath ) )
    		{
    			std::cout << "Not found ";
    		}
    		else
    		{
    			std::cout << "<< File found >> ";
    		}
    		std::cout << sPathSplitted[i]->c_str() << std::endl;
    	}
    
    	unsigned long file_count = 0;
    	unsigned long dir_count = 0;
    	unsigned long other_count = 0;
    	unsigned long err_count = 0;
    	boost::filesystem::directory_iterator end_iter;
    	for ( boost::filesystem::directory_iterator dir_itr("/SourceCode/BoostFilesystem");
              dir_itr != end_iter;
              ++dir_itr )
        {
            if ( boost::filesystem::is_directory( dir_itr->status() ) )
            {
    			++dir_count;
    			std::cout << dir_itr->path().leaf() << " [directory]\n";
            }
            else if ( boost::filesystem::is_regular( dir_itr->status() ) )
            {
    			++file_count;
    			std::cout << dir_itr->path().leaf() << "\n";
            }
            else
            {
    			++other_count;
    			std::cout << dir_itr->path().leaf() << " [other]\n";
            }
    
    	}
    
    	std::cout << std::endl << std::endl;
    	// Erstellen eines Directories
    	boost::filesystem::path createdir("/SourceCode/BoostFilesystem/temp");
    	if (boost::filesystem::is_directory(createdir))
    	{
    		std::cout << "Directory already exists !" << std::endl;
    		std::cout << "Removing directory " << createdir.native_directory_string() << std::endl;
    		boost::filesystem::remove(createdir);
    	}
    
    	if (boost::filesystem::create_directory(createdir))
    	{
    		std::cout << "Creating directory " << createdir.native_directory_string() << std::endl;
    	}
    	else
    	{
    		std::cout << "Unable to create directory " << createdir.native_directory_string() << std::endl;
    	}
    	// // fprintf(stderr,"The path variable contains :: %s \n\n",pathvar);
    
    	return 0;
    }
    


  • kontrollier nochmal, ob deine boostlib auch wirklich in deinem libdir liegt. Soweit ich weiß, zeigt gcc nicht an, wenn er eine lib nicht finden kann sondern spuckt nur die undefined references aus.



  • Also ich bin kein GCC-User, aber muß man nicht den genauen Lib-Namen angeben??? Ich bezweifel mal, das die Libdatei einfach nur boost_filesystem.a heißt. Ich wette sie heißt irgendwie boost_filesystem_1.34.0_s.a oder so...



  • Schau das du die passende Version versuchst zu linken. Lass dir vielleicht mal durch die -v-Option beim kompilieren anzeigen, was er an den Linker weiterreicht.

    btw. Wenn es mit XCode klappt, dann schau dir doch an, wie XCode den GCC aufruft 🙄)



  • rüdiger schrieb:

    Schau das du die passende Version versuchst zu linken. Lass dir vielleicht mal durch die -v-Option beim kompilieren anzeigen, was er an den Linker weiterreicht. btw. Wenn es mit XCode klappt, dann schau dir doch an, wie XCode den GCC aufruft )

    Xcode kann man leider detailliert beim Kompilieren zu schauen. Trotzdem - Sehr guter Flag, damit konnte ich schonmal nachvollziehen, was GCC da macht und mich wundern, was er woher auch immer an Informationen und Pfaden bezieht...

    Artchi schrieb:

    Also ich bin kein GCC-User, aber muß man nicht den genauen Lib-Namen angeben??? Ich bezweifel mal, das die Libdatei einfach nur boost_filesystem.a heißt. Ich wette sie heißt irgendwie boost_filesystem_1.34.0_s.a oder so...

    ...in meinem Library Pfad hatte ich nicht nur die libboost_filesystem.a sondern auch die libboost_filesystem-1_34_1.a und nur mit dieser funktionierte auch das Linken. Aber den Unterschied verstehe ich nicht ? Außerdem habe ich nun die Schwierigkeit, daß er zwar kompiliert, aber das Executable terminiert sich mit

    console$ ./simple_ls
    dyld: Library not loaded: stage/lib/libboost_filesystem-1_34_1.dylib
    Referenced from: /SourceCode/BoostFilesystem/./simple_ls
    Reason: image not found
    Trace/BPT trap

    Der Pfad unter der das Executable "simple_ls" sucht ist falsch, er müßte " stage_gcc/lib/libboost_filesystem-1_34_1.dylib" heißen, wo steht dieser ? wo kann ich es ändern ? 🙄



  • Artchi schrieb:

    Also ich bin kein GCC-User, aber muß man nicht den genauen Lib-Namen angeben??? Ich bezweifel mal, das die Libdatei einfach nur boost_filesystem.a heißt. Ich wette sie heißt irgendwie boost_filesystem_1.34.0_s.a oder so...

    Da wird meistens nen Link gesetzt von boost_filesystem auf boost_filesystem_1.3.4.0 gesetzt.

    Unter Mac OS habe ich auch Probleme gehabt Boost in der Console zu linken. So klappt's aber:

    g++ main.cpp -o appl -I/opt/local/include 
        -Xlinker /opt/local/lib/libboost_serialization.dylib 
        -Xlinker /opt/local/lib/libboost_date_time.dylib
    


  • Konrad schrieb:

    Unter Mac OS habe ich auch Probleme gehabt Boost in der Console zu linken. So klappt's aber:

    g++ main.cpp -o appl -I/opt/local/include 
        -Xlinker /opt/local/lib/libboost_serialization.dylib 
        -Xlinker /opt/local/lib/libboost_date_time.dylib
    

    Haa, auch ein Mac-User 🙂 Damit liess es sich schonmal anstandlos kompilieren, aber :S er sucht die Shared-Library an der falsches Stelle (siehe unten), statt "stage**_gcc**/lib/libboost_filesystem-1_34_1.dylib" sucht er bei "stage/lib/libboost_filesystem-1_34_1.dylib" ... wo kann ich das nun umstellen ?

    console$ ./simple_ls
    dyld: Library not loaded: stage/lib/libboost_filesystem-1_34_1.dylib
    Referenced from: /SourceCode/BoostFilesystem/./simple_ls
    Reason: image not found
    Trace/BPT trap



  • Theoretisch mit der Umgebungsvariable DYLD_LIBRARY_PATH. Das globaler (also über .MacOSX/environment.plist) zu setzen solltest du aber nur in Erwägung ziehen, wenn es nur um wenige Bibliotheken geht oder wenn du ein Case-Sensitive HFS+ hast. (Damit habe ich Probleme mit portage-prefix, da libTIFF,JPEG,PNG (von OSX) mit libtiff,jpeg,png („Standard-Unix“) kollidiert, was einem den Finder ganz schön töten kann ;))

    /edit, Es gibt auch noch DYLD_LIBRARY_FALLBACK_PATH glaub ich. Mehr dazu steht in 'man dyld'



  • .filmor schrieb:

    Theoretisch mit der Umgebungsvariable DYLD_LIBRARY_PATH.

    Und praktisch auch, gg !! Besten Dank an Euch alle - endlich hat es funktioniert.... immer wieder toll dieses Forum 🙂

    Letztendlich habe ich nun in meinem User-Verzeichnis das ".profile"-File mittels vi in der Konsole DYLD_LIBRARY_PATH für die dylib-Files, LD_LIBRARY_PATH für die lib<bib>.so Files, LIBRARY_PATH für die lib<bib>.a Files und letztendlich die CPATH für die include Header-Files über den EXPORT-Befehl gesetzt.



  • .so? Seit wann kann der Mac das denn (abgesehen vom manuellen Laden mit dlopen)? Und .a-Dateien musst du eh nur zur Compile-Zeit finden, genau wie die Header, dafür brauchst du keine Umgebungsvariable. Und wenn doch, dann solltest du sie vielleicht auch so machen, dass dein gesamtes System sie findet (= in .MacOS/environment.plist einfügen).

    Außerdem hoffe ich, dass ich dir die Gefahren klar gemacht habe 😉


Anmelden zum Antworten