130

I try to use the new c++1z features actually on the head of development within gcc 6.0.

If I try this little example:

#include <iostream> #include <experimental/filesystem> namespace fs = std::experimental::filesystem; int main() { fs::path p1 = "/home/pete/checkit"; std::cout << "p1 = " << p1 << std::endl; } 

I got:

 /opt/linux-gnu_6-20151011/bin/g++ --std=c++1z main.cpp -O2 -g -o go /tmp/ccaGzqFO.o: In function \`std::experimental::filesystem::v1::__cxx11::path::path(char const (&) [36])': /opt/linux-gnu_6-20151011/include/c++/6.0.0/experimental/bits/fs_path.h:167: undefined reference to `std::experimental::filesystem::v1::__cxx11::path::_M_split_cmpts()' collect2: error: ld returned 1 exit status 

gcc version is the snapshot linux-gnu_6-20151011

Any hints how to link for the new c++1z features?

0

6 Answers 6

218

The Filesystem TS is nothing to do with C++1z/C++17 support, it is a completely separate specification not part of the C++1z working draft or the final C++17 standard. GCC's implementation of the Filesystem TS (in GCC 5.3 and later) is even available in C++11 mode.

To use it, you just need to link with -lstdc++fs (or for GCC 13.3 and later, you can use -lstdc++exp instead).

(The relevant library, libstdc++fs.a, is a static library, so as with any static library it should come after any objects that depend on it in the linker command.)

Update Nov 2017: as well as the Filesystem TS, GCC 8.x also has an implementation of the C++17 Filesystem library, defined in <filesystem> and in namespace std::filesystem (N.B. no "experimental" in those names). The new C++17 features are available when using -std=gnu++17 or -std=c++17. In GCC 8, the C++17 support was not complete or stable, so for GCC 8 you also need to link to -lstdc++fs for the C++17 Filesystem features.

Update Jan 2019: starting with GCC 9, the C++17 std::filesystem components are considered stable and can be used without -lstdc++fs (but you still need that library for std::experimental::filesystem).

Update Apr 2024: starting with GCC 13.3 the std::experimental::filesystem symbols are also available in -lstdc++exp (along with the other experimental definitions, such as a contract violation handler, and std::stacktrace symbols).

Sign up to request clarification or add additional context in comments.

15 Comments

Is this documented anywhere, I tried to determine this myself and came up w/ nothing, did I miss some resource here?
When I try to use this I get the same linker error. c++ -lstd++fs main.cpp. I am using gcc version 5.3.1 20151207 (Red Hat 5.3.1-2) (GCC)
ok, -lstdc++fs has to be at the end of the line (after the source file at least). I don't understand why some -lxxx need to be at the end and others don't.
@alfC because that's how linkers work. References are resolved left to right, so you need to list static libraries after the objects that use them.
|
59

If you are using cmake, add the following line to CMakeLists.txt:

link_libraries(stdc++fs) 

So that cmake can link against the corresponding library.

2 Comments

I did target_link_libraries(hello_world_ stdc++fs) and it compiled.
target_link_libraries did not work for me in g++-8. This worked
14

With clang 4.0+, you need to link against libc++experimental.a

Make sure you're building with libc++ (not libstdc++) with the -stdlib=libc++ (as mentioned in the comments)

4 Comments

I also needed -stdlib=libc++ because my clang version was unexpectedly using libstdc++.
@BowieOwens thanks, updated answer to make that clear.
When you say "make sure you're building with libc++", how do I do this? (Solution preferably with CMake.) . Thanks.
@mannyglover -stdlib=libc++ or set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
7

Here is a demo that might be helpful to someone in the future:

env: el6, gcc/5.5.0

#include <iostream> #include <string> #include <experimental/filesystem> int main() { std::string path = std::experimental::filesystem::current_path(); std::cout << "path = " << path << std::endl; } 

The following are compiling and testing. The flags are -std=c++17 -lstdc++fs:

$ g++ -v Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/apps/gcc-5.5.0/bin/../libexec/gcc/x86_64-unknown-linux-gnu/5.5.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: ../configure --prefix=/apps/gcc-5.5.0 --disable-multilib --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-languages=all Thread model: posix gcc version 5.5.0 (GCC) $ ls -lrt /apps/gcc-5.5.0/lib64 | grep libstdc -rwxr-xr-x. 1 root root 11272436 Jun 25 10:51 libstdc++.so.6.0.21 -rw-r--r--. 1 root root 2419 Jun 25 10:51 libstdc++.so.6.0.21-gdb.py -rwxr-xr-x. 1 root root 976 Jun 25 10:51 libstdc++.la -rwxr-xr-x. 1 root root 11272436 Jun 25 10:51 libstdc++.so -rw-r--r--. 1 root root 10581732 Jun 25 10:51 libstdc++fs.a -rw-r--r--. 1 root root 28985412 Jun 25 10:51 libstdc++.a -rwxr-xr-x. 1 root root 916 Jun 25 10:51 libstdc++fs.la -rwxr-xr-x. 1 root root 11272436 Jun 25 10:51 libstdc++.so.6 $ g++ filesystem-testing.cpp -lstdc++fs -std=c++17 $ ./a.out $ g++ -std=c++17 filesystem-testing.cpp -lstdc++fs $ ./a.out path = /home/userid/projects-c++/filesystem-testing 

It also works with flags: -std=c++11

$ g++ -std=c++11 filesystem-testing.cpp -lstdc++fs $ ./a.out path = /home/userid/projects-c++/filesystem-testing 

The follows had compiling error _ZNSt12experimental10filesystem2v112current_pathB5cxx11Ev

$ g++ -std=c++17 -lstdc++fs filesystem-testing.cpp /tmp/ccA6Q9oF.o: In function `main': filesystem-testing.cpp:(.text+0x11): undefined reference to `_ZNSt12experimental10filesystem2v112current_pathB5cxx11Ev' collect2: error: ld returned 1 exit status 

Extra Notes:

The following link might be helpful

How to install gcc8 using devtoolset-8-gcc

Comments

1

For

dyld: lazy symbol binding failed: Symbol not found: __ZNSt3__14__fs10filesystem4path17replace_extensionERKS2_ 

and

Undefined symbols for architecture x86_64: "std::__1::__fs::filesystem::__current_path(std::__1::error_code*)", referenced from: sys::path::get_cwd() in Path.cc.o ld: symbol(s) not found for architecture x86_64 

.. try the following:

For LLVM clang >= 10, link with libc++.1.0.dylib supplied by LLVM.

add_link_options("-Wl,-rpath,location_of_llvm_install/lib;location_of_llvm_install/lib/libc++.1.0.dylib") 

This is not for Apple Clang, but for LLVM clang installed from official https://releases.llvm.org or by a package manager.

Xcode < 11 doesn't have filesystem header. macOS < 10.15 doesn't have std::filesystem::path symbols in the system dylib at /usr/lib/libc++.1.0.dylib

Comments

0

You can easily try my code online.

// currentPath.cpp // https://stackoverflow.com/questions/33149878#65128193 #include <experimental/filesystem> #include <iostream> using namespace std; int main() { cout << "path = " << experimental::filesystem::current_path() << endl; } 

Compile and run:

clang++ currentPath.cpp -lstdc++fs && ./a.out # Linux clang++ currentPath.cpp -lstdc++fs && ./a.exe # MSYS2, Windows 

Note: -lstdc++fs is a linker flag, not a compiler flag. (Important when you write a makefile.)

Expected output:

path = "/path/to/the/current/directory" 

1 Comment

If you try to compile and run my code, I believe you will see a good reason to upvote my answer. If you do compile and run, and still don't want to upvote, please consider letting my know why in a comment below. - Admittedly, my answer does have similarities with the answer by @caot, but there are also some significant differences. This is why I prefer to publish an answer of my own rather than suggesting edits to caot's answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.