我知道默认情况下,在编译时会忽略未定义的符号.但是,我也希望它们在运行时被忽略.我需要分发一个使用和不使用MPI运行的.so.我会提前知道它是否是MPI工作,如果不是,我将不会进行任何MPI_ *调用.如果它不是MPI运行,我需要应用程序不关心它无法解析MPI_ *符号.
这可能吗?我本来可以发誓我之前做过这件事,但是我无法让它发挥作用.我每次运行时都会立即得到以下内容,即使我的代码中的逻辑永远不会允许引用该符号:
undefined symbol: hpmp_comm_world
为了我的价值,我使用英特尔Fortran编译器来构建.so文件.
编辑
我找到了链接器标志:“-z lazy”,它应该在调用函数时解析函数的引用,这就是我想要的.这不能解决我的问题,但是hpmp_comm_world是一个变量 – 而不是一个函数.这应该有所作为吗?
解决方法:
您可以将符号定义为对其定义的弱引用.然后,如果定义不存在,则符号的值将为零.
例如,假设以下是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\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
int global_variable;
void global_func(void) {
printf("Hi, from global_func! global_variable = %d\n", 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函数的引用都需要在该函数的((弱))声明的范围内;这就是编译器决定放入目标文件的符号引用类型的方式.您需要进行自动化测试,以验证您是否未意外生成任何非弱引用.
标签:linux,linker
来源: https://codeday.me/bug/20190827/1739792.html