experimental :: error del enlazador del sistema de archivos

95

Intento usar las nuevas funciones de c ++ 1z en la cabeza del desarrollo dentro de gcc 6.0.

Si pruebo este pequeño ejemplo:

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

    std::cout << "p1 = " << p1 << std::endl;
}

Tengo:

/ opt / linux-gnu_6-20151011 / bin / g ++ --std = c ++ 1z main.cpp -O2 -g -o ir
/tmp/ccaGzqFO.o: En la función \ `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: referencia indefinida a `std :: experimental :: filesystem :: v1 :: __ cxx11 :: path :: _ M_split_cmpts () '
collect2: error: ld devolvió 1 estado de salida

La versión gcc es la instantánea linux-gnu_6-20151011

¿Alguna sugerencia de cómo vincular las nuevas funciones de c ++ 1z?

Klaus
fuente

Respuestas:

154

Filesystem TS no tiene nada que ver con el soporte de C ++ 1z, es una especificación completamente separada que no forma parte del borrador de trabajo de C ++ 1z. La implementación de GCC (en GCC 5.3 y posteriores) incluso está disponible en el modo C ++ 11.

Solo necesitas enlazar con -lstdc++fspara usarlo.

(La biblioteca relevante,, libstdc++fs.aes una biblioteca estática, por lo que, al igual que con cualquier biblioteca estática, debe ir después de cualquier objeto que dependa de ella en el comando del vinculador).

Actualización de noviembre de 2017: además de Filesystem TS, GCC 8.x también tiene una implementación de la biblioteca C ++ 17 Filesystem, definida en <filesystem>y en el espacio de nombres std::filesystem(NB no "experimental" en esos nombres) cuando se usa -std=gnu++17o -std=c++17. El soporte para C ++ 17 de GCC aún no es completo o estable, y hasta que se considere listo para su uso en horario de máxima audiencia, también debe vincularse -lstdc++fspara las funciones del sistema de archivos C ++ 17.

Actualización de enero de 2019: a partir de GCC 9, los std::filesystemcomponentes de C ++ 17 se pueden usar sin ellos -lstdc++fs(pero aún necesita esa biblioteca std::experimental::filesystem).

Jonathan Wakely
fuente
2
¿Está esto documentado en alguna parte? Traté de determinarlo yo mismo y no encontré nada, ¿me perdí algún recurso aquí?
Shafik Yaghmour
2
@ShafikYaghmour, acabo de actualizar los documentos: gcc.gnu.org/onlinedocs/libstdc++/manual/… gcc.gnu.org/onlinedocs/libstdc++/manual/… gcc.gnu.org/onlinedocs/libstdc++/manual/… (en la parte inferior)
Jonathan Wakely
2
Cuando intento usar esto, obtengo el mismo error de vinculador. c++ -lstd++fs main.cpp. Estoy utilizandogcc version 5.3.1 20151207 (Red Hat 5.3.1-2) (GCC)
ALFC
15
ok, -lstdc++fstiene que estar al final de la línea (al menos después del archivo fuente). No entiendo por qué algunos -lxxxnecesitan estar al final y otros no.
alfC
5
@alfC porque así es como funcionan los enlazadores. Las referencias se resuelven de izquierda a derecha, por lo que debe enumerar las bibliotecas estáticas después de los objetos que las usan.
Jonathan Wakely
33

Si está utilizando cmake, agregue la siguiente línea a CMakeLists.txt:

link_libraries(stdc++fs)

Para que cmake pueda vincularse con la biblioteca correspondiente.

Searene
fuente
10
Lo hice target_link_libraries(hello_world_ stdc++fs)y lo compilé.
sunapi386
13

Con clang 4.0+, necesitas enlazar contra libc++experimental.a

Asegúrese de que está compilando con libc ++ (no libstdc ++) con -stdlib = libc ++ (como se menciona en los comentarios)

xaxxon
fuente
También necesitaba -stdlib = libc ++ porque mi versión clang usaba libstdc ++ inesperadamente.
Bowie Owens
@BowieOwens gracias, respuesta actualizada para dejar eso en claro.
xaxxon
Cuando dices "asegúrate de compilar con libc ++", ¿cómo hago esto? (Solución preferiblemente con CMake.). Gracias.
mannyglover
1
@mannyglover -stdlib=libc++ orset(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
xaxxon
3

Aquí hay una demostración que podría ser útil para alguien en el futuro:

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;
}

Los siguientes son compilación y prueba. Las banderas son -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

También funciona con banderas: -std=c++11

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

Lo siguiente tuvo error de compilación _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
caot
fuente