您可以将符号定义为对其定义的弱引用.然后,如果定义不存在,则符号的值将为零.
例如,假设以下是ref.c,它引用可能存在或不存在的函数和变量;我们将用它来构建libref.so(对应于你的库,在你的问题中):
#include
void global_func(void);
void global_func(void) __attribute__ ((weak));
extern int global_variable __attribute__((weak));
void ref_func() {
printf("global_func = %p
", 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
int global_variable;
void global_func(void) {
printf("Hi, from global_func! global_variable = %d
", global_variable);
}
最后,假设我们有一个主程序main.c,它从libref.so调用ref_func:
#include
extern void ref_func(void);
int main(int argc, char **argv) {
printf("%s: ", argv[0]);
ref_func();
return 0;
}
这是构建libref.so和libdef.so的Makefile,然后构建两个可执行文件,这两个可执行文件都链接到libref.so,但只有一个链接libdef.so:
all: ref-absent ref-present
ref-absent: main.o libref.so
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
ref-present: main.o libref.so libdef.so
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
lib%.so: %.o
$(CC) $(CFLAGS) $(LDFLAGS) -shared $^ -o $@
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
$
请注意,ref_ubsent和ref-present都没有问题链接,即使在ref_ubsent中没有global_name的定义.
现在我们可以运行程序,并看到ref-absent跳过函数调用,而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
$
你的诀窍是将((弱))属性附加到你的库引用的每个MPI函数的每个声明.但是,正如ref.c所示,可以有多个声明,只要其中一个提到弱属性,就完成了.所以你可能不得不说这样的话(我真的不知道MPI):
#include
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函数的引用都需要在该函数的((弱))声明的范围内;这就是编译器决定放入目标文件的符号引用类型的方式.您需要进行自动化测试,以验证您是否未意外生成任何非弱引用.