1

I am cross compiling for a system with an OpenMP parallelized program, but when I run on the target, I get the error:

can't load library 'libgomp.so.1'

After looking around, I see that it's an OpenMP runtime library. Is there any was to statically link the library it on the compiler host machine, or does it need to be present on the target machine? If it can be statically linked, then what makes a runtime library different from a dynamic library? Could one statically or dynamically link any library, provided the environment was correct?

Spence123
  • 97
  • 1
  • 1
  • 10
  • When building, try adding the `-static` flag. But beware that *all* libraries possible will be linked statically. – Some programmer dude Nov 03 '15 at 15:05
  • When I tried that, I get an error about trying to statically link a dynamic object, one of my other libraries. Thanks for the idea, though. – Spence123 Nov 03 '15 at 15:36

3 Answers3

1

The term "runtime library" is usually used for the standard library and environment needed to run your program. In the case of a C program, it's the C standard library, maybe some other libraries specific for your compiler, and some object files linked to your program to set up the standard C environment.

A "runtime library" can be a dynamic library, or even a collection of multiple dynamic libraries. But it can also be one or more static libraries as well.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • So if a given runtime library is provided as part of an API on a host machine, I should be able to statically link it while cross-compiling, and run the output executable without any need for the library being on the target machine, correct? – Spence123 Nov 03 '15 at 15:22
1

Dynamic libraries are convenient way of providing runtime libraries, as many programs will potentially want to link against such a library. And this is why dynamic linking and dynamic libraries are out there - the first process that requires particular dynamic library will cause it to be loaded to memory. Later, this instance of dynamic library can be reused by many processes.

Imagine if you'd have tens of process running and each of them statically link against say C runtime library. I assume memory consumption would grow rather significantly compared to the case where each of these processes would link against single DLL.

In my opinion, if library will be used by many different processes (for example DirectX might be such library) it might be more efficient to provide it as dynamic library. Otherwise, static linking is preferable.

dbajgoric
  • 1,447
  • 11
  • 17
1

You can selectively statically link certain libraries by providing certain linker options. For libgomp it would be something like:

gcc -o executable foo.o bar.o -Wl,-static -lgomp -Wl,-Bdynamic -lpthread -lother -llibs

Any library listed between -Wl,-static and -Wl,-Bdynamic will be linked in statically. -fopenmp should not be present in the linking command as it expands to linker flags that get appended after the user supplied options, and therefore libpthread should be listed explicitly. It also means that even simple OpenMP programs have to be compiled and linked in two separate steps for static linking to work.

Example:

// foo.c
#include <stdio.h>
#include <omp.h>

int main(void)
{
   #pragma omp parallel
   printf("Hello world from thread %d\n", omp_get_thread_num());
   return 0;
}

Traditional compilation:

$ gcc -fopenmp -o foo foo.c
$ ldd foo
     linux-vdso.so.1 =>  (0x00007ffff5661000)
     libgomp.so.1 => /usr/lib64/libgomp.so.1 (0x0000003bcfa00000)
     libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003bc2600000)
     libc.so.6 => /lib64/libc.so.6 (0x0000003bc1e00000)
     librt.so.1 => /lib64/librt.so.1 (0x0000003bc3200000)
     /lib64/ld-linux-x86-64.so.2 (0x0000003bc1a00000)

The program is linked against the DSO version of libgomp.

Fully static linking:

$ gcc -fopenmp -static -o foo foo.c
$ ldd foo
     not a dynamic executable

With -static all libraries are linked in statically into the executable.

Linking only libgomp statically:

$ gcc -fopenmp -c foo.c
$ gcc -o foo foo.o -Wl,-static -lgomp -Wl,-Bdynamic -lpthread
$ ldd foo
     linux-vdso.so.1 =>  (0x00007ffdaaf61000)
     libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003bc2600000)
     libc.so.6 => /lib64/libc.so.6 (0x0000003bc1e00000)
     /lib64/ld-linux-x86-64.so.2 (0x0000003bc1a00000)

It is important to maintain the correct order of statically linked objects in that case. If foo.o is placed after -lgomp, a link error results:

$ gcc -o foo -Wl,-static -lgomp -Wl,-Bdynamic foo.o -lpthread
foo.o: In function `main':
foo.c:(.text+0x14): undefined reference to `GOMP_parallel_start'
foo.c:(.text+0x23): undefined reference to `GOMP_parallel_end'
foo.o: In function `main.omp_fn.0':
foo.c:(.text+0x3b): undefined reference to `omp_get_thread_num'
collect2: ld returned 1 exit status

Any object file resulting from source code that contains OpenMP constructs should be placed before -lgomp.

Hristo Iliev
  • 72,659
  • 12
  • 135
  • 186
  • Your example using static for gomp only does not work for me. I get many errors like `undefined reference to dlerror`. GCC 5.2.1, Ubuntu 15.10 64-bit. Mixing dynamic and static libraries has been a nightmare for me on Linux. – Z boson Nov 03 '15 at 21:58
  • `gcc -o foo foo.o -Wl,-static -lgomp -Wl,-Bdynamic -lpthread -ldl` works for me – Z boson Nov 03 '15 at 22:01
  • The fun starts when you try and use static pthread and dynamic libc. I don't think that's possible. – Z boson Nov 03 '15 at 22:02
  • It appears that on my system it use `dl` (which I see from ldd) instead of `rt`. In your case you don't need to explicitly link `rt` whereas I have to explicitly link `dl`. – Z boson Nov 03 '15 at 22:06
  • On my home system (Arch Linux with GCC 5.2.0) I don't even have a static version of `libgomp`. But there is a `libgomp.spec` file that contains `*link_gomp: -lgomp %{static: -ldl }`. Statically linking pthreads is an entirely different source of trouble. – Hristo Iliev Nov 03 '15 at 22:26
  • I like Arch. But since it's a rolling release how come you only have GCC 5.2.0 and not GCC 5.2.1? Surely Arch should have a more recent version than Ubuntu. Aren't you suppose to do `pacman -Syu` regularly with Arch? – Z boson Nov 03 '15 at 22:31
  • I do `pacman -Suy` as part of my morning routine. The current version of GCC in Arch is `5.2.0-2`. Also, 5.2.1 is still not officially released, at least not according to GCC's website. – Hristo Iliev Nov 03 '15 at 22:48
  • Strange, Ubuntu 15.1 is the latest release. It came out last week. Why would an official release use a version of GCC that's not released yet? `gcc --version` gives `gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010`. – Z boson Nov 04 '15 at 08:21
  • The latest tag in the GCC SVN repository is `gcc_5_2_0_release`. I guess, Ubuntu is either shipping a prerelease version or backporting features into 5.2.0 and calling it 5.2.1. – Hristo Iliev Nov 04 '15 at 08:50