Найти необязательный символ из статически связанного файла с gcc? - PullRequest
0 голосов
/ 01 ноября 2018

Я бы хотел поддержать некоторые ускоренные функции AVX / SSE, но я бы хотел, чтобы опционально включал их. Я мог бы использовать dlsym () вместе с разделяемым объектом, но я стараюсь избегать разделяемой связи, если это вообще возможно, в интересах более переносимых двоичных файлов.

Есть ли механизм, который я могу использовать, чтобы использовать статический символ, если он успешно связан, и в противном случае прибегнуть к универсальной функции?

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Если вы правильно поняли, у вас есть некоторые связи, такие как:

gcc -o prog main.o ...

, в котором вызывается какой-то avx_func, и вы бы хотели, чтобы если ... статически не связывает подлинное определение avx_func, то оно статически связывает общий суррогат.

Если это так, вы можете просто использовать тот факт, что компоновщик разрешит символ к первому определению, которое он находит в последовательности связей, и не будет связать любое другое определение, если оно не является обязательным (в этом случае множественное определение ошибка это обычный результат). Так, например,

main.cpp

extern void avx_func();

int main()
{
    avx_func();
    return 0;
}

avx_or_not.cpp

#ifdef HAVE_REAL_AVX
#include <iostream>

void avx_func()
{
    std::cout << "The real " << __PRETTY_FUNCTION__ << std::endl;
}
#endif

avx_fallback.cpp

#include <iostream>

void avx_func()
{
    std::cout << "The fallback " << __PRETTY_FUNCTION__ << std::endl;
}

Создать статическую библиотеку libavxfallback.a:

$ g++ -Wall -Wextra -c avx_fallback.cpp
$ ar rcs libavxfallback.a avx_fallback.o

Скомпилируйте другой источник, предполагая, что настоящий AVX:

$ g++ -Wall -Wextra -DHAVE_REAL_AVX -c avx_or_not.cpp  main.cpp

Ссылка на программу:

$ g++ -o prog main.o avx_or_not.o -L. -lavxfallback

Пробег:

$ ./prog
The real void avx_func()

Снова скомпилируйте другой источник, на этот раз при условии отсутствия реального AVX:

$ g++ -Wall -Wextra -c avx_or_not.cpp  main.cpp

Пересмотрите и повторите:

$ g++ -o prog main.o avx_or_not.o -L. -lavxfallback
$ ./prog
The fallback void avx_func()

Во время соединения вам не нужно знать, есть ли что-то в связь до -lavxfallback, которая вызывает avx_func() или определяет avx_func(): вы все еще знаете, что если он вызывается, первое определение в связи будет быть связанным, и это будет тот, что в libavxfallback, если его нет ранее.

0 голосов
/ 01 ноября 2018

Вы можете использовать слабый символ, помеченный __attribute__ ((weak)), объявленный так:

void avx_function (void) __attribute__ ((weak));

И затем вы проверяете NULL перед вызовом функции:

if (avx_function != NULL)
  avx_function ();
else
  fallback_implementation ();

Но на самом деле это не работает для альтернативных реализаций, только для необязательной функциональности, которая связана другими способами: вам нужен механизм для фактического извлечения avx_function, потому что слабый символ этого не сделает.

Но выбор функций во время компиляции или компоновки не даст вам переносимые двоичные файлы . Скорее всего, вам лучше выполнять проверки во время выполнения и косвенное обращение через указатели функций (для выбора сложных функций), если вам нужны переносимые двоичные файлы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...