C and C++ standard libraries in Linux, GCC and Clang

Rock-kun

Senior Member
Joined
Sep 10, 2007
Messages
991
Reaction score
1
Looking for some kind soul to explain some stuff to me.

I know that
  • GCC is the GNU compiler collection. Its most widely used components are gcc and g++.
  • LLVM is a collection of compiler and toolchain technologies. It has Clang / Clang++ as drop-in replacements for gcc and g++.
  • Glibc is the GNU C standard library that comes standard in Linux.
  • Libstdc++ is the GNU standard C++ library that comes standard in Linux
  • Libc++ is LLVM/Clang's standard C++ library
  • Glibc is a basic component for any Linux distribution and cannot be simply upgraded at whim or it breaks the entire distribution.

This leads me to the following questions:
- LLVM / Clang does not offer a C standard library. Does that mean that in a standard Linux distribution with glibc, Clang defaults to building and linking software against glibc? And there is no option around this?
- When compiling most known FOSS software with cc=clang, cxx=clang++ and CXXFLAGS='-stdlib=libc++', am I right to say that Clang will use both glibc and libc++? (assuming that the source is able to build against libc++)
- Glibc supposedly supports both c and c++. What makes glibc so critical to a Linux distribution while libstdc++ isn't? And if glibc has both C and C++ functions, why do most software written in c++ build and link against libstdc++, and not glibc?
 
Last edited:

davidktw

Arch-Supremacy Member
Joined
Apr 15, 2010
Messages
13,497
Reaction score
1,255
Looking for some kind soul to explain some stuff to me.

I know that
  • GCC is the GNU compiler collection. Its most widely used components are gcc and g++.
  • LLVM is a collection of compiler and toolchain technologies. It has Clang / Clang++ as drop-in replacements for gcc and g++.
  • Glibc is the GNU C standard library that comes standard in Linux.
  • Libstdc++ is the GNU standard C++ library that comes standard in Linux
  • Libc++ is LLVM/Clang's standard C++ library
  • Glibc is a basic component for any Linux distribution and cannot be simply upgraded at whim or it breaks the entire distribution.

This leads me to the following questions:
- LLVM / Clang does not offer a C standard library. Does that mean that in a standard Linux distribution with glibc, Clang defaults to building and linking software against glibc? And there is no option around this?
- When compiling most known FOSS software with cc=clang, cxx=clang++ and CXXFLAGS='-stdlib=libc++', am I right to say that Clang will use both glibc and libc++? (assuming that the source is able to build against libc++)
- Glibc supposedly supports both c and c++. What makes glibc so critical to a Linux distribution while libstdc++ isn't? And if glibc has both C and C++ functions, why do most software written in c++ build and link against libstdc++, and not glibc?

Let me try and explain to my knowledge

Do not be confused between LIBC and LIBC+, both of them are in charge of different functionalities.

Clang is just the frontend of the programming language. LLVM is the toolchain and infrastructure. Neither offers interfaces to the Linux kernel and the surrounding technologies. Interfaces to the Linux kernel is by the LIBC, doesn't matter if it's GLIBC or other implementation of LIBC. Read up https://stackoverflow.com/questions/11372872/what-the-role-of-libcglibc-in-our-linux-app

For C programs
Code:
# cat test.c
#include <stdio.h>

int main(int argv, char **argc) {
  printf("Hello World\n");
  return 0;
}
# ldd test
	linux-vdso.so.1 =>  (0x00007ffcbdffb000)
	[COLOR="red"]libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f57a7b2f000)[/COLOR]
	/lib64/ld-linux-x86-64.so.2 (0x00007f57a7ef8000)

For C++ applications
Code:
# cat test.cpp
#include <iostream>

using namespace std;

int main(int argv, char **argc) {
  cout << "Hello World\n";
  return 0;
}
# ldd test2
	linux-vdso.so.1 =>  (0x00007ffd854b5000)
	[COLOR="Blue"]libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1325c04000)[/COLOR]
	[COLOR="Red"]libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f132583b000)[/COLOR]
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1325535000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f1325f08000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f132531f000)

Linux is written in C, interface to it refers the use of the LIBC library. LIBC++ library are just functionalities provided by the C++ specifications. You still need the LIBC if your C++ program wanted to interface with the Linux kernel. https://www.reddit.com/r/linuxquest...what_is_the_relationship_between_gcc_libstdc/

A lot of times, a C++ program is not in its entirety just C++, it touches on C too if it uses some system calls to the kernel, and the LIBSTDC++ basically just provide a C++ wrapper around the C system library.

LIBC is one of the center piece to the OS is because there are so many utilities that are written in C and bind against C. Your BINUTILS, your BASH, even your PERL and RUBY. They are dynamically linked to the LIBC. Don't be confused between a LIBRARY and a PROGRAMMING LANGUAGE or the TOOLCHAIN. Each are in charge of different responsibilities. They work together to give you the platform.

Code:
# ldd /usr/bin/perl
	linux-vdso.so.1 =>  (0x00007ffde04d9000)
	libperl.so.5.18 => /usr/lib/libperl.so.5.18 (0x00007f1e41bea000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1e41821000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f1e4161d000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1e41317000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f1e410f9000)
	libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f1e40ec0000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f1e41f73000)

# ldd /usr/bin/ruby
	linux-vdso.so.1 =>  (0x00007ffd9015f000)
	libruby-1.9.1.so.1.9 => /usr/lib/libruby-1.9.1.so.1.9 (0x00007f292c616000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f292c24d000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f292c02f000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f292be27000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f292bc23000)
	libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f292b9ea000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f292b6e4000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f292ca30000)
 

Rock-kun

Senior Member
Joined
Sep 10, 2007
Messages
991
Reaction score
1
Let me try and explain to my knowledge

Do not be confused between LIBC and LIBC+, both of them are in charge of different functionalities.

Clang is just the frontend of the programming language. LLVM is the toolchain and infrastructure. Neither offers interfaces to the Linux kernel and the surrounding technologies. Interfaces to the Linux kernel is by the LIBC, doesn't matter if it's GLIBC or other implementation of LIBC. Read up https://stackoverflow.com/questions/11372872/what-the-role-of-libcglibc-in-our-linux-app

For C programs
Code:
# cat test.c
#include <stdio.h>

int main(int argv, char **argc) {
  printf("Hello World\n");
  return 0;
}
# ldd test
	linux-vdso.so.1 =>  (0x00007ffcbdffb000)
	[COLOR="red"]libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f57a7b2f000)[/COLOR]
	/lib64/ld-linux-x86-64.so.2 (0x00007f57a7ef8000)

For C++ applications
Code:
# cat test.cpp
#include <iostream>

using namespace std;

int main(int argv, char **argc) {
  cout << "Hello World\n";
  return 0;
}
# ldd test2
	linux-vdso.so.1 =>  (0x00007ffd854b5000)
	[COLOR="Blue"]libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1325c04000)[/COLOR]
	[COLOR="Red"]libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f132583b000)[/COLOR]
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1325535000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f1325f08000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f132531f000)

Linux is written in C, interface to it refers the use of the LIBC library. LIBC++ library are just functionalities provided by the C++ specifications. You still need the LIBC if your C++ program wanted to interface with the Linux kernel. https://www.reddit.com/r/linuxquest...what_is_the_relationship_between_gcc_libstdc/

A lot of times, a C++ program is not in its entirety just C++, it touches on C too if it uses some system calls to the kernel, and the LIBSTDC++ basically just provide a C++ wrapper around the C system library.

LIBC is one of the center piece to the OS is because there are so many utilities that are written in C and bind against C. Your BINUTILS, your BASH, even your PERL and RUBY. They are dynamically linked to the LIBC. Don't be confused between a LIBRARY and a PROGRAMMING LANGUAGE or the TOOLCHAIN. Each are in charge of different responsibilities. They work together to give you the platform.

Code:
# ldd /usr/bin/perl
	linux-vdso.so.1 =>  (0x00007ffde04d9000)
	libperl.so.5.18 => /usr/lib/libperl.so.5.18 (0x00007f1e41bea000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1e41821000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f1e4161d000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1e41317000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f1e410f9000)
	libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f1e40ec0000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f1e41f73000)

# ldd /usr/bin/ruby
	linux-vdso.so.1 =>  (0x00007ffd9015f000)
	libruby-1.9.1.so.1.9 => /usr/lib/libruby-1.9.1.so.1.9 (0x00007f292c616000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f292c24d000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f292c02f000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f292be27000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f292bc23000)
	libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f292b9ea000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f292b6e4000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f292ca30000)

That take a while to digest for non-developer me. But if I understand you correctly:
  1. For example, an application is written in C or C++
  2. The source is compiled with a compiler like gcc, g++, clang or clang++
  3. the C and C++ headers dictate what the source can or cannot define; if the source tries to define something non-existant or do something that is disallowed, the compilation fails with an error
  4. Successful compilation of the source generates a binary that uses the corresponding C and C++ libraries to run.

Am i correct?

Also, moving on to the toolchain:
  1. The compiler is just supposed to compile code based on the appropriate headers it is assigned to use
  2. Am i right to say that if I declare cc=clang, cxx=clang++ CXXFLAGS='-stdlib=libc++, the toolchain will use Clang and Clang++ as compilers, and both glibc's headers and LLVM's libc++ headers (instead of libstdc++) to compile the source, and the resulting binary will link against glibc and libc++?
 

davidktw

Arch-Supremacy Member
Joined
Apr 15, 2010
Messages
13,497
Reaction score
1,255
That take a while to digest for non-developer me. But if I understand you correctly:
  1. For example, an application is written in C or C++
  2. The source is compiled with a compiler like gcc, g++, clang or clang++
  3. the C and C++ headers dictate what the source can or cannot define; if the source tries to define something non-existant or do something that is disallowed, the compilation fails with an error
  4. Successful compilation of the source generates a binary that uses the corresponding C and C++ libraries to run.

Am i correct?

Also, moving on to the toolchain:
  1. The compiler is just supposed to compile code based on the appropriate headers it is assigned to use
  2. Am i right to say that if I declare cc=clang, cxx=clang++ CXXFLAGS='-stdlib=libc++, the toolchain will use Clang and Clang++ as compilers, and both glibc's headers and LLVM's libc++ headers (instead of libstdc++) to compile the source, and the resulting binary will link against glibc and libc++?

1) Nope, libraries are just codes, libraries or application using it does not necessarily need to be written in C/C++. In the earlier post, I have shown you how that Perl and Ruby are written in C and hence uses the LIBC library. BUt when you write any Perl or Ruby codes, and execute them, they are still going to indirectly uses the LIBC routines. Now this is one way of indirectly accessing the LIBC routines. Another way is writing an assembly language program. You can access the LIBC library using rather low level way of opening dynamic libraries, but still you do not need to be written as a C/C++ application.

2) C/C++ headers normally(not strictly) contains functions declarations, constants, structures, so forth, but nothing stop you from placing a fully written C/C++ routine in it. However the normal usage of headers are to be included in one or more C/CPP files, so that the code base (including function declarations) can be shared across the multiple C/CPP files. Function declarations are used by compilers to produce assembly and then eventually opcodes that perform a C/CPP way to passing parameters, frame pointers, return value while invoking routines either statically or dynamically. You are somewhat right that during compilation process, if the compiler cannot match up the declaration with definition either in another source or an included library, the compilation process will fail or with warning/errors produced.

3) Successful compilation, if for static libraries are included as the produced binary, but for shared libraries are dynamically binded during execution. The dynamic loading of the shared libraries is performed by the dynamic linking loader. It doesn't always need to be a specific library, just one that fits the interface/symbol defined.

4) You should be referring to CC, CXX, CXXFLAGS, CFLAGS. The environment variables are case sensitive. These envvar are used by the compiler, loaders, make tools or other utilities that are designed to use them. Defining CC=clang doesn't use the clang are compiler unless the tool is designed to utilise the value found in the CC envvar. Again linking against GLIBC or LIBC++ is up to the toolchain, but suppose after I compile the C program and ran it in another machine that doesn't use GLIBC, it can still works if there is a ABI compatible C library implementation.
 

Rock-kun

Senior Member
Joined
Sep 10, 2007
Messages
991
Reaction score
1
1) Nope, libraries are just codes, libraries or application using it does not necessarily need to be written in C/C++. In the earlier post, I have shown you how that Perl and Ruby are written in C and hence uses the LIBC library. BUt when you write any Perl or Ruby codes, and execute them, they are still going to indirectly uses the LIBC routines. Now this is one way of indirectly accessing the LIBC routines. Another way is writing an assembly language program. You can access the LIBC library using rather low level way of opening dynamic libraries, but still you do not need to be written as a C/C++ application.

2) C/C++ headers normally(not strictly) contains functions declarations, constants, structures, so forth, but nothing stop you from placing a fully written C/C++ routine in it. However the normal usage of headers are to be included in one or more C/CPP files, so that the code base (including function declarations) can be shared across the multiple C/CPP files. Function declarations are used by compilers to produce assembly and then eventually opcodes that perform a C/CPP way to passing parameters, frame pointers, return value while invoking routines either statically or dynamically. You are somewhat right that during compilation process, if the compiler cannot match up the declaration with definition either in another source or an included library, the compilation process will fail or with warning/errors produced.

3) Successful compilation, if for static libraries are included as the produced binary, but for shared libraries are dynamically binded during execution. The dynamic loading of the shared libraries is performed by the dynamic linking loader. It doesn't always need to be a specific library, just one that fits the interface/symbol defined.

4) You should be referring to CC, CXX, CXXFLAGS, CFLAGS. The environment variables are case sensitive. These envvar are used by the compiler, loaders, make tools or other utilities that are designed to use them. Defining CC=clang doesn't use the clang are compiler unless the tool is designed to utilise the value found in the CC envvar. Again linking against GLIBC or LIBC++ is up to the toolchain, but suppose after I compile the C program and ran it in another machine that doesn't use GLIBC, it can still works if there is a ABI compatible C library implementation.

Again, this will take time for me to digest since I am not a developer. Just a crazy guy on Linux who likes to compile his own binaries instead of getting them from the package manager.

But if I understand you correctly, what you are saying is that the source just defines what it needs from which headers and if the compiler + build environment cannot find that method / object in the header, the build just simply fails?

And again, back to the toolchain:
Let's say i have glibc, glibc-devel, libstdc++, libstdc++-devel, gcc and g++ installed from the package manager as is with most distributions. These will all be located in /usr/lib64, /usr/include and /usr/bin ,

And I also have llvm, clang, clang++ and llvm's libc++compiled from source into an external location in /home/test/External so that I have the following directories:
- /home/test/External/lib
- /home/test/External/lib64
- /home/test/External/bin
- /home/test/External/include

If I want to compile an application with the standard
Code:
./configure --prefix=<somewhere>
make 
make install
without specifying anything else, the default behavior is that gcc and g++ will be the compilers used, and the binary will build against the headers in /usr/include and eventually be linked against glibc and libstdc++

But if I want to use my self-built Clang, Clang++ and the headers in my self-built libc++, i will need to do this, right?
Code:
export LDFLAGS="-L/home/test/External/lib -L/home/test/External/lib64"
export CPPFLAGS="-I/home/test/External/include"
export CC=clang
export CXX=clang++ 
export CXXFLAGS='-stdlib=libc++'
 

davidktw

Arch-Supremacy Member
Joined
Apr 15, 2010
Messages
13,497
Reaction score
1,255
Again, this will take time for me to digest since I am not a developer. Just a crazy guy on Linux who likes to compile his own binaries instead of getting them from the package manager.

But if I understand you correctly, what you are saying is that the source just defines what it needs from which headers and if the compiler + build environment cannot find that method / object in the header, the build just simply fails?

During the compilation process, one of the step is linking. The compiler need to know that when you specify a particular symbol, may it be a function, class, structure, variable, constant or so forth can be located. Some of these symbols are found in the source code either in the same source code file, or in another source code file, or externally found in libraries during static or dynamic linking. If the compiler cannot link up the symbol to somewhere, it will either warn or fail depending on the kind of linking.

Code:
# cat header.abc
void a() {
  printf("I am in A\n");
}
# cat source.c
#include <stdio.h>
#include "header.abc"

int main(int argc, char **argv) {
  a();
  return 0;
}
# ./output
I am in A

Look at my codes above, did the header has to be header.h ? I purposely named it has header.abc and it will work just fine. What the compiler did is merely concatenate the source codes together before the actual preprocessing take place, then follow down the chain of compilation.

The code above could be just the same as
Code:
# cat source.c
#include <stdio.h> // <--- EXPAND THIS TOO
void a() {
  printf("I am in A\n");
}

int main(int argc, char **argv) {
  a();
  return 0;
}
# ./output
I am in A

I repeat again, headers and main source file are the same. At least in the case of C/C++, they are just a concept of how you organise your source code. The compiler don't differentiate.

And again, back to the toolchain:
Let's say i have glibc, glibc-devel, libstdc++, libstdc++-devel, gcc and g++ installed from the package manager as is with most distributions. These will all be located in /usr/lib64, /usr/include and /usr/bin ,

And I also have llvm, clang, clang++ and llvm's libc++compiled from source into an external location in /home/test/External so that I have the following directories:
- /home/test/External/lib
- /home/test/External/lib64
- /home/test/External/bin
- /home/test/External/include

If I want to compile an application with the standard
Code:
./configure --prefix=<somewhere>
make 
make install
without specifying anything else, the default behavior is that gcc and g++ will be the compilers used, and the binary will build against the headers in /usr/include and eventually be linked against glibc and libstdc++

The default is not GCC or G++. The default is what your /usr/bin/cc and /usr/bin/c++ is referring to

In the case of my Ubuntu 14.04 installation, you see this
Code:
# ls -al /usr/bin/cc
lrwxrwxrwx 1 root root 20 Jun 11  2015 /usr/bin/cc -> /etc/alternatives/cc
# ls -al /etc/alternatives/cc
lrwxrwxrwx 1 root root 12 Jun 11  2015 /etc/alternatives/cc -> /usr/bin/gcc
# ls -al /usr/bin/c++
lrwxrwxrwx 1 root root 21 Jun 11  2015 /usr/bin/c++ -> /etc/alternatives/c++
# ls -al /etc/alternatives/c++
lrwxrwxrwx 1 root root 12 Jun 11  2015 /etc/alternatives/c++ -> /usr/bin/g++

Most make will first look at the ENVVAR CC and CXX as the compiler to look for, if they are not defined, then make will look into the ENVVAR $PATH and find cc and c++

Read abit on GNU MAKE https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html


But if I want to use my self-built Clang, Clang++ and the headers in my self-built libc++, i will need to do this, right?
Code:
export LDFLAGS="-L/home/test/External/lib -L/home/test/External/lib64"
export CPPFLAGS="-I/home/test/External/include"
export CC=clang
export CXX=clang++ 
export CXXFLAGS='-stdlib=libc++'

This part you can refer to the above explanation and you will understand. :)
 
Important Forum Advisory Note
This forum is moderated by volunteer moderators who will react only to members' feedback on posts. Moderators are not employees or representatives of HWZ. Forum members and moderators are responsible for their own posts.

Please refer to our Community Guidelines and Standards, Terms of Service and Member T&Cs for more information.
Top