Hi llvm team!<div><br></div><div>I'm currently working on the extended version of llvm-ld, which has an ability to check if all the symbols present (and fail if some symbols are not resolved), treat archives in the right way (link all the object files in the archive if it's specified as the regular input, not as -l) and the most important to my project feature: to link against bitcode "shared objects". The semantics is pretty simple. The module treated as shared object is only used as the source of symbol names which be excluded from the list unresolved symbols. For example:</div>
<div><br></div><div>foo.c:</div><div><br></div><div>int main(void) {</div><div> return bar()<br>}</div><div><br></div><div>bar.c:</div><div><br></div><div>int bar() {</div><div> return 123;<br>}</div><div><br></div><div>
In the native case, you have three options to link these files.</div><div><br></div><div>1. Classic static linking:</div><div><br></div><div>$ clang foo.c bar.c</div><div><br></div><div><br></div><div><div>2. Static linking with the archive.</div>
<div><br></div><div>$ clang -c bar.c</div><div>$ ar q libbar.a bar.o</div><div>$ clang foo.c -lbar -L.</div></div><div><br></div><div><br></div><div>3. Dynamic linking:</div><div><br></div><div>$ clang -c foo.c</div><div>
$ clang -shared bar.c -o libbar.so</div><div>$ clang foo.c -lbar -L.</div><div>$ nm a.out</div><div>...</div><div>U bar</div><div>...</div><div>==========================================</div><div><br></div><div><br></div>
<div>Currently, lib/Linker supports first two cases, but not the third. I would like to be able add this functionality and it even exists as the prototype: <a href="https://github.com/krasin/bitlink">https://github.com/krasin/bitlink</a></div>
<div>To build, just place it under llvm/tools and register in tools/CMakefiles.txt</div><div><br></div><div>The utility itself is probably not interesting, because it's just a modified llvm-ld. At the same time, it uses lib/Linker with the added capability of dynamic linking with bitcode stubs:</div>
<div><br></div><div>$ clang -emit-llvm -c foo.c</div><div>clang -emit-llvm -c bar.c -o libbar.o</div><div><br></div><div># Fail if there're undefined symbols:</div><div><div>$ bin/llvm-bitlink foo.o</div><div>llvm-bitlink: undefined reference to bar</div>
<div>llvm-bitlink: Linker aborted due to undefined symbols</div></div><div><br></div><div># Add bitcode "shared object" and link against it:</div><div>$ bin/llvm-bitlink foo.o -shared-library bar.o</div><div><br>
</div><div>Check a.out.ll:</div><div>$ llvm-dis a.out</div><div>$ cat a.out.ll</div><div><div>...</div><div>define i32 @main(i32 %argc, i8** nocapture %argv) nounwind uwtable {</div><div>entry:</div><div> %call = call i32 (...)* @bar() nounwind</div>
<div> ret i32 %call</div><div>}</div><div><br></div><div>declare i32 @bar(...)</div></div><div>==========================================</div><div><br></div><div><br></div><div>I know, it's a basic example and it's not anyhow impressive, but hopefully it provides the clue what I'm talking about. Our plans include generating bitcode link-time stubs for glibc and doing the pure bitcode linking for PNaCl.</div>
<div>I feel like the similar functionality might be useful for other projects as well. For example, Emscripten (as of 3 months ago, when I have checked it) does not check for undefined symbols at link time, because it does not have a way to link against glibc (the symbols from which would be added at runtime as usual javascript functions). This adds additional overhead to the developer who ports the software to javascript using Emscripten.</div>
<div><br></div><div>Any objections? Comments?</div><div><br></div><div>Ivan Krasin</div><div><br></div>