graphitemaster / incbin

Include binary files in C/C++
The Unlicense
966 stars 90 forks source link

It does not work with clang, lld, and -flto=thin with include paths. #61

Open alexey-milovidov opened 1 year ago

alexey-milovidov commented 1 year ago
git clone git@github.com:graphitemaster/incbin.git
cd incbin

Create a source file:

$ cat test.cpp
#include <incbin.h>
#include <unistd.h>

INCBIN(test_txt, "test.txt");

int main(int, char **)
{
    write(1, gtest_txtData, gtest_txtSize);
    return 0;
}

Create a data file to include in a separate directory:

$ mkdir data
$ cat data/test.txt
Hello, world!

This works perfectly:

$ clang++ --version
clang version 17.0.0 (git@github.com:llvm/llvm-project.git 91ae1f5d08d98daae2122b0ab3779b8e1603a045)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin

$ clang++ -I. -Idata test.cpp && ./a.out 
Hello, world!

But this does not:

$ clang++ -I. -Idata -flto=thin -fuse-ld=lld test.cpp && ./a.out 
error: Could not find incbin file 'test.txt'
.incbin "test.txt"
        ^
error: Could not find incbin file 'test.txt'
.incbin "test.txt"
        ^
ld.lld: error: /tmp/test-e5faa6.o <inline asm>:6:9: Could not find incbin file 'test.txt'
.incbin "test.txt"
        ^

clang++: error: linker command failed with exit code 1 (use -v to see invocation)

The culprit is LTO, and the include path. If I remove LTO or specify the absolute path inside the INCBIN macro, it works.

The issue found by ClickHouse in https://github.com/ClickHouse/ClickHouse/pull/52489

We include binary data into the executable, but recently we did it with llvm-objcopy and used it by iterating over symbols of the binary at runtime. Changing it to INCBIN is a nice improvement!