【问题标题】:linking OpenMP statically with GCC将 OpenMP 与 GCC 静态链接
【发布时间】:2014-05-26 12:16:03
【问题描述】:

给定以下文件 print.cpp

#include <stdio.h>
int main() { 
    printf("asdf\n");
}

我可以像这样静态链接这个

g++ -static print.cpp

或者像这样

g++ -static-libgcc -Wl,-Bstatic -lc print.cpp -o print

但现在让我们添加一点 OpenMP 并调用文件 print_omp.cpp

#include <omp.h>
#include <stdio.h>
int main() { 
    printf("%d\n", omp_get_num_threads());
}

我可以像这样静态链接它(我用ldd检查过)

g++ -fopenmp -static print_omp.cpp

但是,这不起作用

g++ -fopenmp -static-libgcc -Wl,-Bstatic -lc print_omp.cpp -o print

我尝试了-Wl,--whole-archive -lpthread -Wl,--no-whole-archive 和 -lgomp -lpthread 的各种组合,但没有运气(我在链接到 pthread 时遇到各种问题)。有人可以解释我如何在不使用 -static 选项的情况下做到这一点吗?

GCC says

在基于 glibc 的系统上,由于底层 pthreads 实现的限制,支持 OpenMP 的应用程序无法静态链接

但是,由于 g++ -fopenmp -static print_omp.cpp 工作得很好,这对我来说没有意义。

编辑: 我想通了。 GOMP 库来自 GCC,而 pthreads 和 libc 来自 GLIBC。所以我可以像这样静态链接GOMP

ln -s `g++ -print-file-name=libgomp.a`
g++ foo.cpp -static-libgcc -static-libstdc++ -L. -o foo -O3 -fopenmp

ldd 节目

linux-vdso.so.1 =>  (0x00007fff71dbe000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc231923000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc23155c000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc231b5c000)

但是,如果我尝试这个

ln -s `g++ -print-file-name=libpthread.a`
g++ foo.cpp -static-libgcc -static-libstdc++ -L. -o foo -O3 -fopenmp

它不会链接。 Pthreads 和 libc 必须静态链接在一起。所以一旦我添加了

ln -s `g++ -print-file-name=libc.a`
g++ foo.cpp -static-libgcc -static-libstdc++ -L. -o foo -O3 -fopenmp

ldd 返回

not a dynamic executable

【问题讨论】:

  • libgcc 不是全部,libgomp 不是其中的一部分。

标签: gcc openmp static-linking


【解决方案1】:

我真的不明白为什么您可能只想静态链接libgomp,但是单独的编译和链接命令可能会有所帮助。例如假设 main.cpp 包含:

#include <omp.h>
#include <stdio.h>

int main() { 
#pragma omp parallel
  {
    printf("%d\n", omp_get_thread_num());
  }
}

然后:

~/tmp$ ls
main.cpp
~/tmp$ g++  -Wall -Werror -pedantic  -fopenmp main.cpp  -c
~/tmp$ ls
main.cpp  main.o
~/tmp$ locate libgomp.a
${SOME_PATH_TO_LIBGOMP}/libgomp.a
~/tmp$ g++  -Wall -Werror -pedantic main.o -o main.x ${SOME_PATH_TO_LIBGOMP}/libgomp.a -pthread
~/tmp$ ls
main.cpp  main.o  main.x
~/tmp$ ldd main.x
    linux-gate.so.1 =>  (0xb7747000)
    libstdc++.so.6 => /production/install/gnu/compiler/gcc/lib/libstdc++.so.6 (0xb765c000)
    libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb75fa000)
    libgcc_s.so.1 => /production/install/gnu/compiler/gcc/lib/libgcc_s.so.1 (0xb75de000)
    libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb75c2000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7413000)
    /lib/ld-linux.so.2 (0xb7748000)

【讨论】:

  • 这看起来很合理。我明天去看看。基本上我正在 Linux 和 Windows 上创建一个共享库。其他开发人员希望尽可能少的依赖项。我最近在具有旧版本 Linux 的 NUMA 系统上测试了我的库,但由于缺少某些库版本而中止。所以现在我正在尝试删除依赖项。令人惊讶的是,使用 MSVC 很容易做到这一点(除了不能静态链接的 OpenMP,Xbox 除外)。但到目前为止,Linux 上的痛苦比我预期的要严重得多。
【解决方案2】:

我为此找到的最干净的解决方案是修改libgomp.spec。我的地址是/usr/local/lib64/libgomp.spec。修改内容如下:

*link_gomp: -l:libgomp.a %{static: -ldl }

【讨论】:

  • 您能解释一下为什么这是最干净的解决方案吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多