🐮
clangでオプションでリンカを指定する
はじめに
この前以下の記事を書きました。clang
を実行すると
デフォルト(?)でGNU ldが呼ばれると書きました。
引数でリンカを指定する方法がないかを調べてみました。
しらべる
とりあえず、clang --help | grep -E "ld|linker
で見てみる。
$ clang --help | grep -E "ld|linker"
--emit-static-lib Enable linker job to emit a static library.
-faapcs-bitfield-load Follows the AAPCS standard that all volatile bit-field write generates at least one load. (ARM only).
-faapcs-bitfield-width Follow the AAPCS standard requirement stating that volatile bit-field width is dictated by the field container type. (ARM only).
-fallow-editor-placeholders
Treat editor placeholders as valid source code
-fbuild-session-file=<file>
Use the last modification time of <file> as the build session timestamp
-fbuild-session-timestamp=<time since Epoch in seconds>
Time when the current build session started
Require member pointer base types to be complete if they would be significant under the Microsoft ABI
-fdiagnostics-hotness-threshold=<value>
Prevent optimization remarks from being output if they do not have at least this profile count. Use 'auto' to apply the threshold from profile summary
-fembed-bitcode-marker Embed placeholder LLVM IR data as a marker
-ffine-grained-bitfield-accesses
Use separate accesses for consecutive bitfield runs with legal widths and alignments.
-fmodule-name=<name> Specify the name of the module to build
Ignore the definition of the given macro when building and loading modules
-fmodules-user-build-path <directory>
Specify the module user build path
-fmodules-validate-once-per-build-session
Don't verify input files for the modules if the module has been successfully validated or loaded during this build session
-fno-aapcs-bitfield-width
Do not follow the AAPCS standard requirement stating that volatile bit-field width is dictated by the field container type. (ARM only).
-fno-allow-editor-placeholders
-fno-autolink Disable generation of linker directives for automatic library linking
Do not require member pointer base types to be complete if they would be significant under the Microsoft ABI
-fno-fine-grained-bitfield-accesses
Use large-integer access for consecutive bitfield runs.
-fno-rtlib-add-rpath Do not add -rpath with architecture-specific resource directory to the linker flags
-fno-temp-file Directly create compilation output files. This may lead to incorrect incremental builds if the compiler crashes
Instantiate templates already while building a PCH
-frtlib-add-rpath Add -rpath with architecture-specific resource directory to the linker flags
-fsanitize-address-field-padding=<value>
Level of field padding for AddressSanitizer
Enable linker dead stripping of globals in AddressSanitizer
-fsystem-module Build this module as a system module. Only used with -emit-module
Compute and store the hash of input files used to build an AST. Files with mismatching mtime's are considered valid if both contents is identical
-fxray-instruction-threshold= <value>
-membedded-data Place constants in the .rodata section instead of the .sdata section even if they meet the -G <size> threshold (MIPS)
-mextern-sdata Assume that externally defined data is in the small data if it meets the -G <size> threshold (MIPS)
-mincremental-linker-compatible
(integrated-as) Emit an object file which can be used with an incremental linker
-mms-bitfields Set the default structure layout to be compatible with the Microsoft compiler standard
-mno-embedded-data Do not place constants in the .rodata section instead of the .sdata if they meet the -G <size> threshold (MIPS)
-mno-extern-sdata Do not assume that externally defined data is in the small data if it meets the -G <size> threshold (MIPS)
-mno-incremental-linker-compatible
(integrated-as) Emit an object file which cannot be used with an incremental linker
-mno-ms-bitfields Do not set the default structure layout to be compatible with the Microsoft compiler standard
-mno-relax Disable linker relaxation
-mrelax Enable linker relaxation
-relocatable-pch Whether to build a relocatable precompiled header
-T <script> Specify <script> as linker script
-Wl,<arg> Pass the comma separated arguments in <arg> to the linker
-Xlinker <arg> Pass <arg> to the linker
-z <arg> Pass -z <arg> to the linker
それっぽいものは見つからず。
念の為(?) -Xlinker
オプションを付けて実行してみる。
最近知ったのですが、-###
をつけると、dry runとなります。
(gccでも同じオプションがあるみたい)
$ clang -### -Xlinker lld hello.c
clang version 12.0.0 (https://github.com/llvm/llvm-project/ b978a93635b584db380274d7c8963c73989944a1)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir:
<省略>
"/usr/bin/ld" "-z" "relro" "--hash-style=gnu" "--eh-frame-hdr" "-m" "elf_x86_64" "-dynamic-linker" "/lib64/ld-linux-x86-64.so.2" "-o" "a.out" "/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crt1.o" "/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o" "/usr/lib/gcc/x86_64-linux-gnu/9/crtbegin.o" "-L/usr/lib/gcc/x86_64-linux-gnu/9" "-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu" "-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib64" "-L/lib/x86_64-linux-gnu" "-L/lib/../lib64" "-L/usr/lib/x86_64-linux-gnu" "-L/usr/lib/../lib64" "-L/usr/lib/x86_64-linux-gnu/../../lib64" "-L/usr/lib/gcc/x86_64-linux-gnu/9/../../.." "-L/home/saitoyutaka/clang/clang+llvm-12.0.0-x86_64-linux-gnu-ubuntu-20.04/bin/../lib" "-L/lib" "-L/usr/lib" "lld" "/tmp/hello-ec9dab.o" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "/usr/lib/gcc/x86_64-linux-gnu/9/crtend.o" "/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o"
GNU ldが呼ばれていました。
しらべてみる(コードを)
カンでld
とかでgrepしたら何かわかるかと思いやってみたら
以下の処理が引っかかりました。
コメントを見ると、
ToolChain.cpp
// Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is
// considered as the linker flavor, e.g. "bfd", "gold", or "lld".
const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER;
-fuse-ld
というオプションがあるっぽい。
(clang --help
では出なかったけど)
オンラインドキュメントには記載があった。
"-fuse-ld=lld"をつけてみる
-fuse-ld=lld
をつけてみた実行結果は以下。
$ cat hello.c
#include <stdio.h>
int main(void) {
printf("Hello world\n");
return 0;
}
$ clang -### -fuse-ld=lld hello.c
clang version 12.0.0 (https://github.com/llvm/llvm-project/ b978a93635b584db380274d7c8963c73989944a1)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir:
<省略>
"<省略>bin/ld.lld" "-z" "relro" "--hash-style=gnu" "--eh-frame-hdr" "-m" "elf_x86_64" "-dynamic-linker" "/lib64/ld-linux-x86-64.so.2" "-o" "a.out" "/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crt1.o" "/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o" "/usr/lib/gcc/x86_64-linux-gnu/9/crtbegin.o" "-L/usr/lib/gcc/x86_64-linux-gnu/9" "-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu" "-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib64" "-L/lib/x86_64-linux-gnu" "-L/lib/../lib64" "-L/usr/lib/x86_64-linux-gnu" "-L/usr/lib/../lib64" "-L/usr/lib/x86_64-linux-gnu/../../lib64" "-L/usr/lib/gcc/x86_64-linux-gnu/9/../../.." "-L/home/saitoyutaka/clang/clang+llvm-12.0.0-x86_64-linux-gnu-ubuntu-20.04/bin/../lib" "-L/lib" "-L/usr/lib" "/tmp/hello-4520a6.o" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "/usr/lib/gcc/x86_64-linux-gnu/9/crtend.o" "/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o"
ld.lld
が呼ばれるようになった。
-###
を外してみる。ちゃんと実行もできた。
$ clang -fuse-ld=lld hello.c
$ ./a.out
Hello world
$
補足gccのオンラインドキュメント
gccのオンラインドキュメントには以下のように記載がされている。
-fuse-ld=bfd
Use the bfd linker instead of the default linker.-fuse-ld=gold
Use the gold linker instead of the default linker.-fuse-ld=lld
Use the LLVM lld linker instead of the default linker.
まとめ
clangコマンドの引数でリンカの指定をするには
-fuse-ld
オプションを使う。
(たぶん)gccのドキュメントもヒントになる。
Discussion