Unable to pass additional flags to gcc through mpicc - c

I have a C program that uses OpenMPI libraries. I am also using functions from libm and have included math.h in my program. When compiling using mpicc, like so
mpicc -lm program.c -o program.out
compilation succeeds, but linking fails, with ld unable to link libm and the following three lines of error
/usr/bin/ld: /tmp/cct0O5Yv.o: undefined reference to symbol 'log10##GLIBC_2.2.5'
/usr/bin/ld: /lib/x86_64-linux-gnu/libm.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
From what I understand, mpicc is just a wrapper for gcc whose job is to pass compilation and linking flags to gcc. Why is it not passing -lm to gcc? How do I make it pass additional flags to gcc? I couldn't fine anything in the man pages.
I used --showme:compiler and --showme:linker with mpicc and passed those flags to gcc along with -lm, and it generates the final executable just fine.

It turns out that the order of the command line arguments passed to mpicc matters. In order to make mpicc pass additional flags to gcc, place them before the source file
mpicc -lm program.c -o program.out
Flags placed after the source file will be treated as flags to the wrapper and not the "kernel" (in this case gcc).

Related

Problem compiling C progtam from command line gcc with math.h

I am new to the command line and I am trying to run a C program containing the function log10.
If I give
gcc -o -lm randomVamp random\ vampire.c
I get the error
gcc: error: randomVamp: No such file or directory
but randomVamp is the name I wanted to give to the executable, of course it doesn't exist yet.
If I prompt just
gcc -o -lm random\ vampire.c
then I get the error
/usr/bin/ld: /tmp/ccbWivPU.o: in function `main':
random vampire.c:(.text+0x312): undefined reference to `log10'
collect2: error: ld returned 1 exit status
Anyone knows what's going on?
I don't know if it's relevant, but the program also includes stdlib.h and time.h should I use some flag or link them in some way?
-o means that the next argument is the output file name. Replace -o -lm randomVamp with something like -o randomVamp -lm.
Also, note that -l... have no effect if specified before the .c/.cpp/.o/... files. So, the command could look like this:
gcc -o randomVamp random\ vampire.c -lm

Properly Linking a static library with the C math library

I have a library which uses the log function from math.h. When I compile and package this library, I get no compilation errors, which is normal (I think).
Now when I try to use the library in an application, gcc gives me linker errors:
Compiling mytestlist using "mytestlist.o":
gcc mytestlist.o -I/student/cmpt332/pthreads -I. -std=c99 -Wall -pedantic -L. -L/student/cmpt332/pthreads/lib/linuxx86_64/ -llist -o mytestlist
./liblist.a(list_adders.o): In function `NodeCreate':
list_adders.c:(.text+0x343): undefined reference to `log'
./liblist.a(list_adders.o): In function `ListCreate':
list_adders.c:(.text+0x62f): undefined reference to `log'
./liblist.a(list_adders.o): In function `ListFree':
list_adders.c:(.text+0xdcc): undefined reference to `log'
list_adders.c:(.text+0xe55): undefined reference to `log'
list_adders.c:(.text+0xefb): undefined reference to `log'
./liblist.a(list_adders.o):list_adders.c:(.text+0xf96): more undefined references to `log' follow
collect2: error: ld returned 1 exit status
Makefile:47: recipe for target 'mytestlist' failed
make: *** [mytestlist] Error 1
Why is this happening? The only solution that works is that I have to supply the -lm option to gcc when I compile the program that uses the library (even though the program itself makes no use of math.h), however I find this cumbersome to do.
I've also tried supplying the -lm option when compiling the library, but when the application is compiled using the library, I get the same linker errors.
Is there a way to compile the library with math.h without having to supply -lm to other programs that make use of the library?
In case you're wondering, I compile each object that makes up the library using:
gcc -std=c99 -Wall -pedantic -static -I. -c list_adders.c -o list_something.o -lm
And the library is packaged using:
ar cvfr liblist.a list_something.o ...
In your gcc -c command, the -lm isn't doing anything. It's a linker option, and -c means "don't link".
The proper place to put -lm is in fact after the -llist whenever you use it. That's how static library dependencies are done. Put it in the documentation for liblist.
If you want something fancier, there's pkg-config. With the appropriate configuration files, pkg-config --static --libs liblist will output -llist -lm.

Linking with shared libraries

I'm trying to compile and link some .c file. I have been using Eclipse IDE for C/C++ developers, and in my local machine i can compile without problems. However, when i try to compile and link the same file in a RedHat OS (gcc version is 4.9.2-6 in this OS) i'm having problems. I get some warnings at compile time, but those are fine, i think, i just ignored and the application still runs fine. Here are the commands i executed and the associated output:
gcc -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -MMD -MP -MF"example.d" -MT"example.d" -o "example.o" "example.c"
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
warning: implicit declaration of function ‘wait’ [-Wimplicit-function-declaration]
This generates two files, example.d and example.o. Then, i try to link them, without luck, with the following command:
gcc -Xlinker -L/usr/lib -lrt -static -pthread example.o -o example
/usr/bin/ld: cannot find -lrt
/usr/bin/ld: cannot find -lpthread
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
The commands are taken directly from the ones that Eclipse generates, and work just fine in my local computer (Ubuntu OS) but not in the RedHat environment. The last command didn't work, with and without the -L option. I suppose the directory in -L is fine, as i run, for example,
locate libpthread.so
And one of the locations i get is /usr/lib (also /usr/lib64, but neither work).
Any help will be greatly appreciated!! :)
If you try to link a static executable, it will look for the *.a versions of the libraries, not what you usually want. Remove the -static flag. Or you can install the static libraries if you really want to. It also should not be necessary to add -L/usr/lib explicitly.

DSO missing from command line although it is available

I am working with c++ code for a physics simulation, which uses a lot of external libraries (like GSL and cern`s ROOT). Trying to recompile project I encountered problems with linking. When running compilation of final file via:
g++ -fno-inline -O2 -fpic -o main.out ${ROOTINCS} main.o ext.o ${ROOTLIBS} $(objects2)
with :
objects2= many .o files made by us
ROOTLIBS=-L/usr/local/lib/root -lTree -lRIO -lNet -lHist -lMathCore -lCore -lGraf -lGraf3d -lGpad -lMatrix -lThread -lCint -lPhysics -lPostscript -lRint -lSpectrum -lg
ROOTINCS=-pthread -m64
I get annoying error:
/usr/bin/ld: /usr/local/lib/root/libHist.so: undefined reference to symbol 'gRandom'
/usr/local/lib/root/libMathCore.so: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
The problem is nm -C run on libMathCore states 'gRandom' is declared there. Also -lMathCore is present in my command line.
When I run ld to check if it understands the flag:
ld -L/usr/local/lib/root -lMathCore --verbose 2>/dev/null
it does not complain and tries to link properly.
According to https://stackoverflow.com/a/24675715/3602168 order of libraries is correct in my linking (libHist uses libMathCOre and therefore is stated first).
Compilation runs under g++ 4.8.2 on ubuntu 14.04, 64 bit
Converting comment to answer:
Have you tried moving $(objects2) before ${ROOTLIBS}? I think the issue may be that you have libraries specified before the object files that use them.

Why am I getting a gcc "undefined reference" error trying to create shared objects?

Why am I getting an "undefined reference" error using gcc?
I am trying to create a shared object (.so) that exports one function, "external()". I then try to link against the .so but get "undefined reference 'external'". What am I doing wrong here?
File: external.c
int external() {
return 5;
}
File: program.c
int external();
int main(char** argv, int* argc) {
return external();
}
Commands:
$ gcc -fPIC -c external.c
$ gcc -shared -o libexternal.so external.o
$ gcc -L. -lexternal -o program program.c
/tmp/cc3MmhAE.o: In function `main':
program.c:(.text+0x7): undefined reference to `external'
collect2: ld returned 1 exit status
I can even run nm and see that the .so is defining 'external':
Command:
$ nm libexternal.so | grep external
0000040c T external
What am I missing here?
Recent versions of gcc/ld default to linking with --as-needed.
This means if you write -lexternal before the C file the library will automatically get excluded (the order matters when testing if things are "needed" like this)
You can fix this with either of:
gcc -L. -o program program.c -lexternal
gcc -L. -Wl,--no-as-needed -lexternal -o program program.c
The latter of which passes --no-as-needed to the linker, which would cause the library to still be linked, even if you didn't call external() from it.
Note: -Wl,--no-as-needed isn't applied globally to everything that's linked, it's only applied to things that follow it in the command line order. So -lexternal -Wl,--no-as-needed also wouldn't work. This does mean that you can mix and match behaviours though, for example gcc -L. -Wl,--no-as-needed -lexternal -Wl,--as-needed -o program program.c -lmightneed would always link against external, but only link against mightneed if one or both of program.c/libexternal.so caused it to be needed.

Resources