如何在Nix中用LLVM工具链静态链接libc++构建可执行文件
解决Nix下用LLVM/libc++构建静态可执行文件的链接错误
你遇到的问题是静态链接libc时缺少了它依赖的底层库,光加glibc.static不够——libc本身依赖libcxxabi(处理C++异常、静态初始化守卫等符号,比如__cxa_guard_acquire),还需要线程库(比如pthread)和数学库的静态版本。
解决方案:添加libc++和libcxxabi的静态依赖,并调整链接顺序
你可以直接从llvmPackages_10中引入对应的静态库包,同时在编译命令中显式指定依赖的库(静态链接对顺序要求很高,依赖库要放在被依赖的代码后面)。
修改后的Nix表达式如下:
let pkgs = import <nixpkgs> {}; llvmPkgs = pkgs.llvmPackages_10; stdenv = llvmPkgs.libcxxStdenv; in stdenv.mkDerivation { name = "my-app"; src = ./.; buildInputs = [ glibc.static llvmPkgs.libcxx.static llvmPkgs.libcxxabi.static ]; buildPhase = '' c++ -o main main.cpp -static -lc++ -lc++abi -lpthread -lm ''; installPhase = '' mkdir -p $out/bin cp main $out/bin/ ''; }
关键调整说明:
llvmPkgs.libcxx.static&llvmPkgs.libcxxabi.static:这两个包提供了libc++和其依赖的cxxabi静态库,解决你看到的__cxa_*系列未定义符号问题。-lpthread:修复线程相关的未定义符号(比如pthread_mutex_unlock、pthread_cond_destroy),因为libc++的部分组件依赖POSIX线程库。-lm:链接数学静态库,部分C++标准库函数(比如浮点运算相关)依赖它。- 链接顺序:要保证你的代码(
main.cpp)在前,然后是libc++,接着是libcxxabi,最后是系统级的pthread和数学库——静态链接器会按顺序解析符号,顺序错了会导致依赖符号找不到。
更符合Nix习惯的写法(用NIX_LDFLAGS)
你也可以把链接参数放到NIX_LDFLAGS中,让Nix的构建环境自动处理:
let pkgs = import <nixpkgs> {}; llvmPkgs = pkgs.llvmPackages_10; stdenv = llvmPkgs.libcxxStdenv; in stdenv.mkDerivation { name = "my-app"; src = ./.; buildInputs = [ glibc.static llvmPkgs.libcxx.static llvmPkgs.libcxxabi.static ]; NIX_LDFLAGS = "-static -lc++ -lc++abi -lpthread -lm"; buildPhase = "c++ -o main main.cpp $NIX_LDFLAGS"; installPhase = '' mkdir -p $out/bin cp main $out/bin/ ''; }
这样修改后,应该就能成功构建静态链接的可执行文件了。
内容的提问来源于stack exchange,提问作者majkrzak
相关产品推荐
相关产品推荐

