Удалить мертвый код перед установкой ссылки
В проекте, который состоит из нескольких статически связанных объектных файлов, я заменяю один из них отдельной реализацией. Я хотел бы проверить свой код еще до того, как реализовал каждый символ, предоставленный замененным объектным файлом, поэтому я использую -Wl,--unresolved-symbols=ignore-all
чтобы компоновщик не жаловался на отсутствующие символы.
Но когда я тестирую код, он просто вылетает при попытке использовать один из неопределенных символов. Поэтому я ищу способ сообщить компоновщику: "Пожалуйста, удалите весь код без ссылок перед связыванием, а затем скажите мне, если в коде, доступном с точки входа, все еще есть символы без ссылок". Это возможно?
1 ответ
Тщательно составив ответ, основываясь на комментариях, я нашел это в своей собственной кодовой базе и проверил, что метод работает нормально для меня.
int do_things(void);
int application_main(void)
{
return do_things();
}
int test_main(void)
{
return 42;
}
int main(void)
{
return test_main();
}
Макет примерно отражает мой вариант использования. Данный блок IR может иметь две точки входа, одну для выполнения модульных тестов и одну для выполнения того, для чего используется код. Модульные тесты нуждаются в подмножестве символов, необходимых для всего модуля. Преимущество состоит в том, что вы можете собрать часть для модульного тестирования, не создавая ничего другого.
Deadstripping - это определенное улучшение по сравнению с моим предыдущим методом -Wl,--unresolved-symbols=ignore-all
clang demo.c # undefined reference to `do_things'
clang -O3 demo.c # undefined reference to `do_things'
clang demo.c -c -emit-llvm -o demo.bc # OK
llvm-nm demo.bc
---------------- T application_main
U do_things
---------------- T main
---------------- T test_main
clang demo.bc # undefined reference to `do_things'
opt -o stripped.bc -internalize -internalize-public-api-list=main -globaldce demo.bc
llvm-nm stripped.bc
---------------- T main
---------------- t test_main
clang stripped.bc # OK
Список открытых символов может быть получен из файлов ir (по крайней мере, в моем случае), поэтому вызов opt на самом деле
opt -internalize -internalize-public-api-list=`llvm-nm -extern-only -defined-only -just-symbol-name some-file.bc` -globaldce -O2