I am writing an application that has multiple subdirectories. I have created a Makefile structure such that the subdirectories compile the file and do "ar rvs" and "ranlib libxxx.a" to create archives into the parent directory for linking.
However the "ld" command is running into the following problem.
ld: warning: ignoring file ./libxxx.a, file was built for archive which is not
the architecture being linked (x86_64):
./libxxx.a Undefined symbols for architecture x86_64:
I am using gcc on Mac OS X 10.10.1
I read many posts on this. I tried "gcc -arch i386", then I encounter the same error for i386
Undefined symbols for architecture i386:
I installed gcc-4.9.2 and tried using it instead of the default gcc, with no luck. I tried using x86_64-apple-darwin14.0.0-g++-4.9.2 and that did not help either.
The errors you are seeing mean that you have a mixture of i386 and x86_64 code in the build, and you need to be consistent. Unless there's a compelling reason to do otherwise (I'd be curious to know what it is), you should be compiling everything for 64-bit only. Using gcc on Mac, that is normally the default, but you can force it by adding a -m64 flag to the compilations. One way of doing that is to set CC="gcc -m64" on the make command line; there are other better ways too, but the details depend on your makefile contents.
To resolve: first, remove all the libraries and object code you've built in your project area (maybe make clean will do it — if you wrote a clean target). Then, fettle the value of CC or its flags (CFLAGS ultimately, but how CFLAGS is built depends on the makefile) so that 64-bit compilation is enforced. Then make sure you're using that in all compilations. If you don't see the -m64, you've got a problem.
If you must use 32-bit, substitute -m32 for -m64.
The discussion above assumes you are using gcc to run the ld command. If you are not, then you're on your own until you use gcc to run the ld command. In my view, you've got better things to do with your life than work out how to run the ld command correctly; I certainly have.
Related
I stumbled over a weird behavior of ld (compile time linking) in Manjaro-Linux.
Assuming I want to compile test.c which is dependent on libprimary.so and libprimary.so is dependent on libsecondary.so, which are installed in non standard paths.
I could compile like this (both are working):
gcc test.c -L/path/to/primaryLibDir -lprimary -L/path/to/secondaryLibDir -lsecondary -o test
or like this:
gcc test.c -L/path/to/primaryLibDir -lprimary -Wl,-rpath-link=/path/to/secondaryLibDir -o test
A look into ld manual under the -rpath-link option is telling that if -rpath-link is not used and the not directly dependent library is not given with -lsecondary, the file is (among other methods with higher prioriry tried before), also searched using the paths in /etc/ld.so.conf (priority 7).
I tried this in my Manjaro-Linux dsitribution and in the Ubuntu WSL.
And it works in all of them when writing the path directly into /etc/ld.so.conf.
If I write the path into a /etc/ld.so.conf.d/test.conf file (which is included via include /etc/ld.so.conf.d/*.conf in /etc/ld.so.conf) it works only in the Ubuntu WSL. In Manjaro Linux, it does not find the library anymore then.
Can anyone imagine, why this is not working? I think it must have something to do with the Manjaro setup.
I'm using cmake to generate a gstreamer library. In the end cmake uses the following command for linking:
/usr/bin/cc -fPIC -shared -Wl,-soname,libmacq-gstmelpi.so -o libmacq-gstmelpi.so <OBJECT_FILES> -lmacq-melpi -lmacq-icar-tools -lmacq-gstmecimeta -lgstreamer-1.0 -lgobject-2.0 -lglib-2.0 -lgstvideo-1.0
Note the -lgstvideo-1.0 flag at the end. The command runs fine, no error is produced, and the resulting library is created just fine. However when I use the library, I get undefined symbol error. So I use ldd to check; and amongst all the output of ldd; libgstvideo-1.0.so is not to be found.
This problem occurs on Ubuntu 14.04 on a armhf architecture. The problem does not occur on opensuse 13.1 (i586) nor on opensuse 13.1 (armv7hl), since in that case ldd libmacq-gstmelpi.so | grep gstvideo gives:
libgstvideo-1.0.so.0 => /usr/lib/libgstvideo-1.0.so.0 (0xb715f000)
EDIT :
I have another library, very similar where a very similar command works just fine; the resulting library is correctly linked to libgstvideo-1.0.so
/usr/bin/cc -fPIC -shared -Wl,-soname,libmacq-gstplugins.so -o libmacq-gstplugins.so <OBJECT_FILES> -lmacq-icar-tools -lmacq-gstmecimeta -lgstapp-1.0 -lgstbase-1.0 -lgstreamer-1.0 -lgobject-2.0 -lglib-2.0 -lgstvideo-1.0
Some remarks on what I have checked and tried:
/usr/lib/arm-linux-gnueabihf/libgstvideo-1.0.so exists. (the other libraries in /usr/lib/arm-linux-gnueabihf/ are found without problem, libmacq-gstmelpi.so is linked to /usr/lib/arm-linux-gnueabihf/libgstreamer-1.0.so.0 without problem)
I tried changing the order, and putting the -lgstvideo-1.0 flag before all other -l flags; no succes.
replacing cc with c++ or gcc; the commands work, but output is the same
removing -lgstvideo-1.0 on a system where the build worked. The resulting library builds (links) without error; yet upon execution I have the same undefined symbol error as on Ubuntu. This proves that the missing symbol is in libgstvideo-1.0.so, and that I need it.
Are you actually using symbols from that particular library or do you just want to link to it to avoid linking it in the application that uses the library later on?
It could be a default compiler behavior that it skips linking of libraries when no symbol from these are actually used.
Try -Wl,--no-as-needed to your flags. In this case the library should get linked - not checking whether its symbols are actually used or not.
EDIT:
After chatting it turned out that the actual desired symbols are in gstbase-1.0 and not gstvideo-1.0. Since gstvideo-1.0 pulls in gstbase-1.0 as a dependency this worked but would cause problem as the linker may remove this dependency since no symbols from this particular library are being used. Linking directly to gstbase-1.0 seemed to solve all issues.
I am trying to create a dynamic library which is meant to be linked and loaded into a host environment at runtime (e.g. similar to how class loading works in Java). As such, I want the dynamic library to be left with a few "dangling" references, which I expect it to pick up from its host environment when it is loaded into that environment.
My problem is that I cannot figure out how to create the dynamic library without explicitly linking it to existing symbols. I am hoping to produce a dynamic library that does not depend on a specific host executable (or host library), rather one that is able to be loaded (e.g. by dlopen) in any host as long as the host makes a couple symbols available for use.
Right now, any linking command I've tried results in a complaint of missing symbols. I'd like it to allow symbols to be missing (ideally, just particularly specified symbols).
For example, here's a transcript with the error on OS X:
$ cat frotz.c
void blort(void);
void run(void) {
blort();
}
$ cc -c -o frotz.o frotz.c
$ cc -dynamiclib -o libfrotz.dylib frotz.o
Undefined symbols for architecture x86_64:
"_blort", referenced from:
_run in frotz.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
If I do the same thing using a GNU toolchain (on Linux), it helpfully tells me:
$ gcc -shared -o libfrotz.so frotz.o
/usr/bin/ld: frotz.o: relocation R_X86_64_PC32 against undefined symbol `blort'
can not be used when making a shared object; recompile with -fPIC
and indeed, adding -fPIC to the C compile command seems to fix the problem in that environment. However, it doesn't seem to have any effect in OS X.
All the other dynamic-linking questions I could find on SO seem to be about the more usual arrangement of libraries, where a library is being built to be linked into an executable before that executable runs, rather than the other way around. The closest related question I found was this:
Can an executable be linked to a dynamic library after its built?
which unfortunately has very little info, none of it relevant to the question I'm asking here.
UPDATE: I distilled the info from the answer along with everything else I'd figured
out, and put together this example:
https://github.com/danfuzz/dl-example
As far as my knowledge goes, you want to use weak linkage:
// mark function as weakly-linked
extern void foo() __attribute__((weak));
// inform the linker about that too
clang -dynamiclib -o bar.dylib bar.o -flat_namespace -undefined dynamic_lookup
If a weak function can be resolved at runtime, it will then be resolved. If it can't, it will be NULL, instead of generating a runtime (or, obviously, link-time) error.
I'm trying to compile a code (not mine) that consists of mixed Fortran and C source files, which are compiled into a library. This library can either be linked against directly, or (more usefully) driven from a python class. I have previously successfully built the code as 32-bit with g77 and gcc, but I've encountered a situation in which the code uses big chunks of memory, and needs to be 64-bit.
I've attempted to build as both 64-bit only, or as a universal binary, with gfortran 4.2.3 (binary dist from the AT&T R project) and the system gcc (4.2). The source files build correctly, but when I attempt to link against the library, I get many "Undefined Symbols" errors for a number of the Fortran functions. An nm on the library shows that the symbols appear to exist, but obviously the linker isn't finding them.
Here are two (of many) of the compile commands (which produce no errors):
/usr/local/bin/gfortran -arch ppc -arch i386 -arch x86_64 -fPIC -fno-strength-reduce -fno-common -ff2c -Wall -c lsame.f
gcc -c -I/Users/keriksen/Research/atomic_data/fac -I/Users/keriksen/Research/atomic_data/fac/faclib -O2 -fPIC -fno-strength-reduce -fno-common pmalloc.c
And the link step, which bombs:
gcc -o sfac sfac.c stoken.c -I/Users/keriksen/Research/atomic_data/fac -I/Users/keriksen/Research/atomic_data/fac/faclib -O2 -fPIC -fno-strength-reduce -fno-common -L/Users/keriksen/Research/atomic_data/fac -lfac -lm -lgfortran -lgcc
A sample Undefined Symbol:
"_acofz1", referenced from:
_HydrogenicDipole in libfac.a(coulomb.o)
_HydrogenicDipole in libfac.a(coulomb.o)
and the corresponding nm that shows that symbol exists:
niobe:atomic_data/fac[14] nm libfac.a | grep acof
0000000000000000 T _acofz1_
0000000000002548 S _acofz1_.eh
U _acofz1
Am I doing something stupid, like not including a necessary switch to the linker, or is something more subtle going on here?
Per Yuji's suggestion:
The cfortran.h header file (available on the Web, and apparently fairly widely used) that handles the C/Fortran compatibility issues does not handle gfortran out of the box. I hacked it (incorrectly) to ignore this fact, and paid for my insolence.
The specific issue is that gfortran emits object code containing symbols with a trailing underscore, gcc does not.
The correct thing to do was to set the environment variable CPPFLAGS to -Df2cFortran. Once this macro is set, cfortran.h adds the necessary underscore to the symbols in the calling C functions' object code, and the linker is happy.
The other surprising thing in this particular instance was the configure script looks at the F77 environment variable for the name of the fortran compiler. Once I set F77 to "/usr/local/bin/gfortran -arch x86_64" the generated Makefile was correct, and it produced 64-bit only object code. I'm not sure if this is standard configure behavior, or if it a peculiarity of this particular script.
The upshot is that I now have a 64-bit shared library which plays nicely with a 64-bit python I downloaded. I'm half-considering going back and trying to produce a universal library that will work with the system python, but I'm not sure I want to tempt fate.
I am attempting to cross-compile on AIX with the xlc/xlC compilers.
The code compiles successfully when it uses the default settings on another machine. The code actually successfully compiles with the cross-compilation, but the problem comes from the linker. This is the command which links the objects together:
$(CHILD_OS)/usr/vacpp/bin/xlC -q32 -qnolib -brtl -o $(EXECUTABLE) $(OBJECT_FILES)
-L$(CHILD_OS)/usr/lib
-L$(CHILD_OS)/usr/vacpp/lib/profiled
-L$(CHILD_OS)/usr/vacpp/lib
-L$(CHILD_OS)/usr/vac/lib
-L$(CHILD_OS)/usr/lib
-lc -lC -lnsl -lpthread
-F$(CHILD_OS)$(CUSTOM_CONFIG_FILE_LOCATION)
When I attempt to link the code, I get several Undefined symbols:
.setsockopt(int,int,int,const void*,unsigned long), .socket(int,int,int), .connect(int,const sockaddr*,unsigned long), etc.
I have discovered that the symbols missing are from the standard c library, libc.a. When I looked up the symbols with nm for the libc.a that is being picked up, the symbols do indeed exist. I am guessing that there might be a problem with the C++ being unable to read the C objects, but I am truly shooting in the dark.
Sound like it might be a C++ name mangling problem.
Run nm on the object files to find out the symbols that they are looking for. Then compare the exact names against the libraries.
Then check the compilation commands, to ensure that the right version of the header files is being included - maybe it's including the parent OS's copy by mistake?
I was eventually able to get around this. It looks like I was using the C++ compiler for .c files. Using the xlc compiler instead of the xlC compiler for C files fixed this problem.