在Linux上,一般情况下都会使用GCClibstdc++,因为他们之间有特殊优化,如果使用Clang编译,性能不会比GCC高,因为默认情况下Clang编译出来的程序也是链接的libstdc++,而Clang的正统在libc++

运行环境

docker run -it --rm ubuntu bash

apt update && apt install -y clang make cmake ninja libc++-dev libc++abi-dev llvm-dev

使用VSCode附加到容器

  1. 创建test文件夹,在VSCode中打开

  2. Ctrl+Shift+P 选择 CMake: Quick Start

  3. 输入项目名称test

  4. VSCode中选择编译器为Clang

    image-20240905170645035

编译生成

  • 默认clang会使用libstdc++.so作为C++的运行时库,libstdc++.so是属于GNU的,GCC同属于GNU组织
cmake_minimum_required(VERSION 3.5.0)
project(test VERSION 0.1.0 LANGUAGES C CXX)

add_executable(test main.cpp)
root@49d525b221f5:~/test/build# ldd test
        linux-vdso.so.1 (0x00007ffd5bdd8000)
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fdf8c330000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fdf8c247000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fdf8c21a000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdf8c008000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fdf8c5b8000)
  • Clang属于LLVM,如果想在Linux上使用libc++.so,需要手动指定,Clanglibc++.so都是属于LLVM
cmake_minimum_required(VERSION 3.5.0)
project(test VERSION 0.1.0 LANGUAGES C CXX)

add_executable(test main.cpp)

target_compile_options(test PUBLIC -stdlib=libc++)
target_link_libraries(test PUBLIC c++ -rtlib=compiler-rt -unwindlib=libunwind -stdlib=libc++)
# 一定要加 -rtlib=compiler-rt -unwindlib=libunwind -stdlib=libc++  否则会同时链接libc++和libstdc++
root@49d525b221f5:~/test/build# ldd test
        linux-vdso.so.1 (0x00007ffcf736a000)
        libc++.so.1 => /lib/x86_64-linux-gnu/libc++.so.1 (0x00007fee9680f000)
        libc++abi.so.1 => /lib/x86_64-linux-gnu/libc++abi.so.1 (0x00007fee967d3000)
        libunwind.so.1 => /lib/x86_64-linux-gnu/libunwind.so.1 (0x00007fee967c5000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fee966dc000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fee964ca000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fee96918000)

如果要静态链接运行时,在target_link_libraries 中加入-static即可。

使用MUSL的libc库

上面编译出来的程序,始终都链接了系统的glibc,如果想要完全去除GNU相关的东西,最简单的办法就是使用Alpine系统

FROM alpine:edge

RUN sed -i 's#https\?://dl-cdn.alpinelinux.org/alpine#https://mirrors.tuna.tsinghua.edu.cn/alpine#g' /etc/apk/repositories

RUN apk add --no-cache cmake ninja clang musl-dev llvm-dev libc++-dev llvm-libunwind-dev lld libc-dev compiler-rt libc++-static llvm-libunwind-static linux-headers lldb

系统需要使用alpine:edgealpine最新版本的libc++已经不依赖libgcc了,3.20版本的libc++库还是会依赖libgcc

edge libc++

3.20 libc++

cmake文件

cmake_minimum_required(VERSION 3.5.0)
project(test VERSION 0.1.0 LANGUAGES C CXX)

add_executable(test main.cpp)

target_compile_definitions(test PUBLIC _LARGEFILE64_SOURCE)
target_compile_options(test PUBLIC --stdlib=libc++)
target_link_libraries(test PUBLIC --rtlib=compiler-rt --unwindlib=libunwind --stdlib=libc++ -fuse-ld=lld c++ c++abi)
# 需要静态链接 后面加 -static

编译器选择clang

root@f7f43530e56b:~/test/build# ldd test
        /lib/ld-musl-x86_64.so.1 (0x7fa9fb884000)
        libc++.so.1 => /usr/lib/libc++.so.1 (0x7fa9fb6fb000)
        libc++abi.so.1 => /usr/lib/libc++abi.so.1 (0x7fa9fb6c4000)
        libunwind.so.1 => /usr/lib/libunwind.so.1 (0x7fa9fb6b5000)
        libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7fa9fb884000)

参考:

Assembling a Complete Toolchain — Clang 20.0.0git documentation (llvm.org)

libc++ 13.0 still depends on "libgcc_s.so" even when it's built with "-DLIBCXX_USE_COMPILER_RT=ON" · 议题 #51425 · llvm/llvm-project (github.com)