3

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
Z boson
  • 32,619
  • 11
  • 123
  • 226

2 Answers2

4

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)
Massimiliano
  • 7,842
  • 2
  • 47
  • 62
  • 1
    That looks reasonable. I'll check it out tomorrow. Basically I'm making a shared library on Linux and Windows. The other developers want as few dependencies as possible. I recently tested my library on a NUMA system with an older version of Linux and it aborted due to some missing version of a library. So now I'm trying to remove dependencies. Surprisingly, this was easy with MSVC (except for OpenMP which can't be linked statically, except on the Xbox). But so far it's been far more of a pain on Linux than I expected. – Z boson May 26 '14 at 19:30
2

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 }
Amos
  • 3,238
  • 4
  • 19
  • 41