Z boson
Z boson

Reputation: 33669

linking OpenMP statically with GCC

Given the following file print.cpp

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

I can link this statically like this

g++ -static print.cpp

or like this

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

But now let's add a little OpenMP and call the file print_omp.cpp

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

I can link this statically like this (I checked it with ldd)

g++ -fopenmp -static print_omp.cpp

However, this does not work

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

I have tried various combinations of -Wl,--whole-archive -lpthread -Wl,--no-whole-archive and -lgomp -lpthread but no luck (I get various problems linking to pthreads). Can someone explain how I can do this without using the -static option?

GCC says

On glibc-based systems, OpenMP enabled applications cannot be statically linked due to limitations of the underlying pthreads-implementation

However, since g++ -fopenmp -static print_omp.cpp works just fine this does not make sense to me.

Edit: I figured this out. The library GOMP comes with GCC whereas pthreads and libc come from GLIBC. So I can link GOMP statically like this

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

ldd shows

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)

However, if I the try this

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

It won't link. Pthreads and libc must be linked statically together. So once I add

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

ldd returns

not a dynamic executable

Upvotes: 4

Views: 13822

Answers (2)

Amos
Amos

Reputation: 3276

The most clean solution I've found for this is by modifying the libgomp.spec. Mine is at /usr/local/lib64/libgomp.spec. Change the content as follow:

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

Upvotes: 2

Massimiliano
Massimiliano

Reputation: 8032

I really don't get why you may want to link only libgomp statically, but having separate compilation and linking commands may help. For instance assume main.cpp contains:

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

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

Then:

~/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)

Upvotes: 4

Related Questions