"/usr/bin/ld: cannot find -lstdc++: No such file or directory" on running flutter linux app

21.5k views Asked by At

getting this error on flutter run for a linux desktop application

Running "flutter pub get" in proj...            5.3s
Launching lib/main.dart on Linux in debug mode...
CMake Error at /usr/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake:62 (message):
  The C++ compiler

    "/usr/bin/clang++"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: /media/kingbob/Dvolve/EData/proj/build/linux/x64/debug/CMakeFiles/CMakeTmp

    Run Build Command(s):/usr/bin/ninja cmTC_5f1b6 && [1/2] Building CXX object CMakeFiles/cmTC_5f1b6.dir/testCXXCompiler.cxx.o
    [2/2] Linking CXX executable cmTC_5f1b6
    FAILED: cmTC_5f1b6 
    : && /usr/bin/clang++   CMakeFiles/cmTC_5f1b6.dir/testCXXCompiler.cxx.o -o cmTC_5f1b6   && :
    /usr/bin/ld: cannot find -lstdc++: No such file or directory
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    ninja: build stopped: subcommand failed.





  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:2 (project)


Building Linux application...                                           
Exception: Unable to generate build files

output of flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.3.8, on Ubuntu 22.04.1 LTS 5.15.0-53-generic, locale en_IN)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Android Studio (version 2021.3)
[✓] Connected device (2 available)
[✓] HTTP Host Availability

• No issues found!

output of clang++ --version

Ubuntu clang version 14.0.0-1ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

I noticed that /usr/lib/libstdc++.so was missing, so manually created a symlink sudo ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6 /usr/lib/libstdc++.so.

Then I ended up in this error on flutter run

Launching lib/main.dart on Linux in debug mode...
/usr/include/glib-2.0/glib/glib-typeof.h:39:10: fatal error: 'type_traits' file not found
/usr/include/glib-2.0/glib/glib-typeof.h:39:10: fatal error: 'type_traits' file not found
/usr/include/glib-2.0/glib/glib-typeof.h:39:10: fatal error: 'type_traits' file not found
/usr/include/glib-2.0/glib/glib-typeof.h:39:10: fatal error: 'type_traits' file not found
/usr/include/glib-2.0/glib/glib-typeof.h:39:10: fatal error: 'type_traits' file not found
/usr/include/glib-2.0/glib/glib-typeof.h:39:10: fatal error: 'type_traits' file not found
3

There are 3 answers

4
Kevin On

I ran into a similar problem after a system upgrade. After a while, I realized that it was because nvidia-driver-520-open installed gcc-12. I use clang-15 that I installed with the script installClang15.sh. clang-15 depends and hence installs libstdc++-11-dev and gcc-11. The problem is that once gcc-12 was installed, clang++ picked it up automatically instead of gcc-11. This can be confirmed with clang++ --verbose which outputs something like

Ubuntu clang version 15.0.6
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Candidate multilib: .;@m64
Selected multilib: .;@m64

Solution 1: Install libstdc++-12-dev

I thought about this solution thanks to this GitHub comment. This is the easiest solution, but it has a few drawbacks. On Ubuntu, you can install the package with

sudo apt install libstdc++-12-dev

The drawbacks that I faced are:

  • I'd then be using a newer version of gcc (version 12). This might required (actually this did require) me to update my code. This is very problematic within the context of this question, where one doesn't necessarily control the code.
  • What if in 6 months, nvidia-driver-520-open requires gcc-13? I would have to figure out again why I'm having this error, and then install libstdc++-13-dev, which might potentially require some code updates again.

Solution 2: Fix the gcc installation that clang++ uses

I did not find any clean and easy way to do that, but there are ways. clang-16, not yet released as of November 28th 2022 but available when building clang, has a new option --gcc-install-dir described here. This fixes compilation:

$HOME/src/llvm-project/staging/bin/clang++ --gcc-install-dir=/usr/lib/gcc/x86_64-linux-gnu/11 a.cpp

where a.cpp is a trivial C++ "Hello World!" program

#include <iostream>
int main() { std::cout << "Hello World!" << std::endl; }

Older versions of clang have the option --gcc-toolchain, which is not quite as useful for reasons described on llvm's discourse. However, you can still be ingenious and do what this Stack Overflow answer suggest. The TL;DR is

sudo mkdir --parents /opt/gcc-root/lib/gcc/x86_64-linux-gnu
sudo ln --symbolic /usr/lib/gcc/x86_64-linux-gnu/11 /opt/gcc-root/lib/gcc/x86_64-linux-gnu/11
sudo ln --symbolic /usr/include /opt/gcc-root/

The ln --symbolic /usr/include /opt/gcc-root/ is important, otherwise I encountered problems with incremental build. Then, you should be able to compile with

clang++ --gcc-toolchain=/opt/gcc-root a.cpp

This leaves one question open: "How do I integrate this compiler option system wide?" I didn't find any satisfying answers here.

  • You could use export CCC_OVERRIDE_OPTIONS=^--gcc-toolchain=/opt/gcc-root as described here and documented on GitHub. This might be the best solution within the context of this question.
  • You could create a shell script named clang++ that contains
    #!/usr/bin/env bash
    /usr/local/bin/clang++ --gcc-toolchain=/opt/gcc-root "$@"
    
    and then use export CXX=<PATH_TO_SCRIPT>/clang++. This work well enough in practice: it's been my quick and dirty fix. However, I'm worried that other tools in the toolchain (like clang-tidy or clangd) might have problems if they're not passed the option --gcc-toolchain. Depending on how you are setup, they might not see the option since it would not be in the file compile_commands.json created with the CMAKE_EXPORT_COMPILE_COMMANDS CMake variable.
  • You could use clang's configuration files. The TL;DR is that you symbolically link clang++ as, for instance, fixed-gcc-root-clang++, and then you create a file fixed-gcc-root-clang++.cfg in the proper place (for clang-15, it is /usr/lib/llvm-15/bin) that contains the option --gcc-toolchain=/opt/gcc-root. Finally, you use export CXX=fixed-gcc-root-clang++. A problem is that if somebody or something (for instance an IDE) uses clang++ directly, your configuration file won't be read. You'll also have problems if a new symbolic link to fixed-gcc-root-clang++ is created, for instance c++ -> fixed-gcc-root-clang++, since in this case, the configuration file would not be read.
  • The best solution I found requires to control the build system, so it doesn't apply within the context of this question. The solution is to modify your build system toolchain. I find this unsatisfying since a packaging problem (remember, this is all because nvidia-driver-520-open installed a new transitive dependency) finds its solution in the C++ build system. Hence, the separation of concerns principle is not respected.
1
Bhikkhu Subhuti On

Install this:

Reinstall all dependencies (it is included here now)

sudo apt-get install clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev libstdc++-12-dev

You can read the last two entries here https://github.com/flutter/flutter/issues/115909

0
wuniu On

Non-native speaker here. Apologies for any misunderstandings.

Install libstdc++-12-dev will resolve this on Ubuntu 22.04 and derivatives.

sudo apt install libstdc++-12-dev

This is mainly because,

  1. Ubuntu basically use gcc-11-based toolchain, so that /usr/bin/gcc is a symlink to /usr/bin/gcc-11.
  2. The system-wide shared library is libstdc++.so.6 compiled by gcc 12.3.0, which provided by libstdc++6 package, the package depends on gcc-12-base.
  3. I think because of 2., clang (clang-14 by default) will search /usr/lib/gcc/x86_64-linux-gnu/12 for shared lib rather than /usr/lib/gcc/x86_64-linux-gnu/11 which gcc-11 will do.

ld only treats *.so as shared lib, so libstdc++.so.6 won't be queried by it. To include libstdc++.so.6 into linker's search-path, *-dev packages need to create symlink from *.so.6 to *.so under its path.

Package libstdc++-11-dev will put the symlink libstdc++.so under /usr/lib/gcc/x86_64-linux-gnu/11/ and libstdc++-12-dev will it under /usr/lib/gcc/x86_64-linux-gnu/12/.

clang depends on libstdc++-11-dev, so only libstdc++-11-dev will be shipped with clang by default.

Cited from How to print the ld(linker) search path, ld search-path could be found as

$ /usr/bin/ld --verbose | grep SEARCH_DIR | tr -s ' ;' \\012
SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu")
SEARCH_DIR("=/lib/x86_64-linux-gnu")
SEARCH_DIR("=/usr/lib/x86_64-linux-gnu")
SEARCH_DIR("=/usr/lib/x86_64-linux-gnu64")
SEARCH_DIR("=/usr/local/lib64")
SEARCH_DIR("=/lib64")
SEARCH_DIR("=/usr/lib64")
SEARCH_DIR("=/usr/local/lib")
SEARCH_DIR("=/lib")
SEARCH_DIR("=/usr/lib")
SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64")
SEARCH_DIR("=/usr/x86_64-linux-gnu/lib")

, which do not contain any paths under /usr/lib/gcc/x86_64-linux-gnu.

Both gcc and clang passes a few extra -L paths to the linker, as

$ clang -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,;  ,g' | tr \; \\012
libraries:
  /usr/lib/llvm-14/lib/clang/14.0.0:/usr/lib/gcc/x86_64-linux-gnu/12:/usr/lib64:/lib/x86_64-linux-gnu:/lib64:/usr/lib/x86_64-linux-gnu:/usr/lib64:/usr/lib/llvm-14/lib:/lib:/usr/lib
$ gcc-11 -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,;  ,g' | tr \; \\012
libraries:
  /usr/lib/gcc/x86_64-linux-gnu/11/:/usr/x86_64-linux-gnu/lib/x86_64-linux-gnu/11/:/usr/x86_64-linux-gnu/lib/x86_64-linux-gnu/:/usr/x86_64-linux-gnu/lib/:/usr/lib/x86_64-linux-gnu/11/:/usr/lib/x86_64-linux-gnu/:/usr/lib/:/lib/x86_64-linux-gnu/11/:/lib/x86_64-linux-gnu/:/lib/:/usr/lib/x86_64-linux-gnu/11/:/usr/lib/x86_64-linux-gnu/:/usr/lib/:/usr/x86_64-linux-gnu/lib/:/usr/lib/:/lib/:/usr/lib/
$ gcc-12 -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,;  ,g' | tr \; \\012
libraries:
  /usr/lib/gcc/x86_64-linux-gnu/12/:/usr/x86_64-linux-gnu/lib/x86_64-linux-gnu/12/:/usr/x86_64-linux-gnu/lib/x86_64-linux-gnu/:/usr/x86_64-linux-gnu/lib/:/usr/lib/x86_64-linux-gnu/12/:/usr/lib/x86_64-linux-gnu/:/usr/lib/:/lib/x86_64-linux-gnu/12/:/lib/x86_64-linux-gnu/:/lib/:/usr/lib/x86_64-linux-gnu/12/:/usr/lib/x86_64-linux-gnu/:/usr/lib/:/usr/x86_64-linux-gnu/lib/:/usr/lib/:/lib/:/usr/lib/

Only gcc-11 (which is default on Ubuntu 22.04) passes /usr/lib/gcc/x86_64-linux-gnu/11/ to linker ld, so that only gcc-11 (/usr/bin/gcc is a symlink to /usr/bin/gcc-11 by default) will work.

As a result, installing libstdc++-12-dev will make gcc-12 and clang available anyway. Also, it is workable to create a symlink libstdc++.so to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 under any path mentioned above.