2010-08-03 5 views
3

Я знаю, что по умолчанию неопределенные символы игнорируются во время компиляции. Тем не менее, я также хотел бы, чтобы их игнорировали во время выполнения. Мне нужно распространять .so, который будет работать с MPI и без него. Я буду знать заранее, если это MPI-работа, и если это не так, я не буду делать никаких вызовов MPI_ *. Если это не прогон MPI, мне нужно, чтобы приложение не заботилось о том, что оно не может разрешить символы MPI_ *.Как игнорировать undefined символы во время выполнения в Linux?

Возможно ли это? Я мог бы поклясться, что сделал это раньше, но я не могу заставить его работать. Everytime я бегу я сразу получаю следующее, хотя логика в моем коде никогда не позволит, что символ ссылаться:

undefined symbol: hpmp_comm_world 

Для чего это стоит, я использую Intel Fortran Compiler для создания .so файла.

EDIT

Я нашел флаг компоновщика: «-z ленивым», который, как предполагается, для разрешения ссылок на функции, когда вызывается функция, которая является то, что я хочу. Это не исправляет мою проблему, но hpmp_comm_world - это переменная, а не функция. Должно ли это иметь значение?

+0

У вас нет LD_BIND_NOW в вашей среде? – mvds

ответ

6

Вы можете определить символ, который должен быть слабым ссылкой к его определению. Тогда значение символа будет равно нулю, если определение отсутствует.

Например, предположим, что приведено ref.c, которое ссылается на функцию и переменную, которые могут быть или не быть; мы будем использовать его для создания libref.so (соответствует вашей библиотеке, в вашем вопросе):

#include <stdio.h> 

void global_func(void); 
void global_func(void) __attribute__ ((weak)); 

extern int global_variable __attribute__((weak)); 

void ref_func() { 
    printf("global_func = %p\n", global_func); 
    if (&global_variable) 
    global_variable++; 
    if (global_func) 
    global_func(); 
} 

Здесь global_func и global_variable являются слабые ссылки на возможно-доступных функций и переменных. Этот код печатает адрес функции, приращает переменную, если она присутствует, и вызывает функцию, если она присутствует. (Обратите внимание, что адреса работы функции и переменной равны нулю, когда они не определены, поэтому &global_variable, что вы должны сравнить с нулем.)

И пусть это def.c, который определяет global_func и global_variable; мы будем использовать его для создания libdef.so (соответствующий MPI, в вашем вопросе):

#include <stdio.h> 

int global_variable; 

void global_func(void) { 
    printf("Hi, from global_func! global_variable = %d\n", global_variable); 
} 

И, наконец, предположим, что у нас есть основной программы, main.c, который вызывает ref_func из libref.so:

#include <stdio.h> 

extern void ref_func(void); 

int main(int argc, char **argv) { 
    printf("%s: ", argv[0]); 
    ref_func(); 
    return 0; 
} 

Вот Makefile, который строит libref.so и libdef.so, а затем строит два исполняемых файла, оба из которых связывают с libref.so, но только один из которых будет связан с libdef.so:

all: ref-absent ref-present 
ref-absent: main.o libref.so 
    $(CC) $(CFLAGS) $(LDFLAGS) $^ -o [email protected] 
ref-present: main.o libref.so libdef.so 
    $(CC) $(CFLAGS) $(LDFLAGS) $^ -o [email protected] 

lib%.so: %.o 
    $(CC) $(CFLAGS) $(LDFLAGS) -shared $^ -o [email protected] 

ref.o def.o: CFLAGS += -fpic 

clean: 
    rm -f *.o *.so ref-absent ref-present 

Выполните сборку:

$ make 
cc -c -o main.o main.c 
cc -fpic -c -o ref.o ref.c 
cc -shared ref.o -o libref.so 
cc main.o libref.so -o ref-absent 
cc -fpic -c -o def.o def.c 
cc -shared def.o -o libdef.so 
cc main.o libref.so libdef.so -o ref-present 
$ 

Обратите внимание, что обе исх отсутствовавший и реф-настоящее связаны без проблем, даже если нет определения для global_name в реф-отсутствующим.

Теперь мы можем запускать программы и видеть, что ref-missing пропускает вызов функции, а ref-present использует его.(Мы должны установить LD_LIBRARY_PATH, чтобы динамический компоновщик, чтобы найти наши общие библиотеки в текущем каталоге.)

$ LD_LIBRARY_PATH=. ./ref-absent 
./ref-absent: global_func = (nil) 
$ LD_LIBRARY_PATH=. ./ref-present 
./ref-present: global_func = 0x15d4ac 
Hi, from global_func! global_variable = 1 
$ 

Хитрости для вас будет получать атрибут ((weak)), прикрепленный к каждой декларации каждой MPI действуют ваши ссылки библиотеки , Однако, как показано в Ref.c, может быть несколько объявлений, и до тех пор, пока один из них упоминает слабый атрибут, все готово. Таким образом, вы, вероятно, сказать что-то вроде этого (я не знаю, MPI):

#include <mpi.h> 

mpi_fake_type_t mpi_function_foo(mpi_arg_type_t) __attribute__((weak)); 
mpi_fake_type_t mpi_function_bar(mpi_other_arg_type_t) __attribute__((weak)); 

Каждая ссылка на функции MPI должен находиться в области видимости ((слабой)) декларации о том, что функция; вот как компилятор решает, какую ссылку на символ помещать в объектный файл. Вы хотите иметь автоматические тесты, чтобы убедиться, что вы случайно не создали никаких слабых ссылок.

Смежные вопросы