erl_interface linker error - c

I need to use erl_interface in my C-program. There is Erlang R15B01 on Debian Wheezy.
I just do the following (for example).
// main.c
#include <ei.h>
#include <erl_interface.h>
int main() {
erl_init(NULL,0);
return 0;
}
Then i say:
cc -I/usr/lib/erlang/lib/erl_interface-3.7.7/include -L/usr/lib/erlang/lib/erl_interface-3.7.7/ -lei -lerl_interface -o prog main.c
Directory specified as -L contains libei.a and liberl_interface.a but linker abusing that reference to erl_init is undefined: undefined reference to erl_init
What may be wrong? Sorry for really stupid question.

Newest versions of the GNU toolchain require that the object files and libraries be specified in the same order their symbols depend on each other. So you should generally put the library flags to the end of the invocation, like this:
gcc -o prog main.c -L<libdir> -I<includedir> -lerl_interface -lei

Related

GCC link against .so file without souce code

I am trying to compile compile a simple "hello world" program for an Axis A210 (cris architecture). I managed to get download GCC from the vendor, but it came with glibc, and the camera is running uClibc-0.9.27. I pulled the file /lib/libuClibc-0.9.27.so from the device.
I managed to compile this program that segfaults:
#include <unistd.h>
int main(int argc, char** argv)
{
*((unsigned int*)0) = 0xDEAD;
}
and this program that just hangs:
#include <unistd.h>
int main(int argc, char** argv)
{
int a = 0;
}
with cris-gcc -g -static -nostdlib -o compiled main.c.
Now I'd like to use the functions in libuClibc, but I can't seem to get the linking to work: I've tried
cris-gcc -g -static -nostdlib -o compiled main.c -luClibc-0.9.27 -L.
but that just gives:
./libuClibc-0.9.27.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
Is there a way to link to this .so file or to otherwise get some standard functions like exit working?
regarding:
cris-gcc -g -static -nostdlib -o compiled main.c -luClibc-0.9.27 -L.
The linker works with libraries in the order they are encountered. So they must be listed in the order needed.
The linker needs to know where the library is located before knowing which library to examine. Suggest:
cris-gcc -g -static -nostdlib -o compiled main.c -L. -luClibc-0.9.27
However, a *.so library is NOT a static library. It is a dynamic library, so the option: -static should be removed However, that requires that the dynamic library be available at 'run time' if the related *.a (a static library) is available then it should be used in the compile/link statement.
Note: the function: exit() has its' prototype exposed via the stdlib.h header file, not the unistd.h header file.
regarding:
#include <unistd.h>
int main(int argc, char** argv)
{
*((unsigned int*)0) = 0xDEAD;
}
the parameters: argc and argv are not used, so the compiler will output two warning statements about 'unused parameters'. Suggest using the function signature: int main( void )
this code is trying to write to address 0. However, the application does not 'own' address 0, (an usually, such an address will be 'marked' as 'readonly' so the application will exit with a 'seg fault event')
it is poor programming practice to include header files those contents are not used. Suggest removing the statement: #include <unistd.h>
this statement: int a = 0; will result in the compiler outputting a warning message about a variable that is 'set' but never 'used'
regarding:
cris-gcc -g -static -nostdlib -o compiled main.c -L. -luClibc-0.9.27
When compiling, should always enable the warnings, then fix those warnings. Suggest:
cris-gcc -Wall -Wextra -Wconversion -pedantic -std=c99 -g -static -nostdlib -o compiled main.c -luClibc-0.9.27 -L.
Apart of all the problems noticed by #user3629249 in his answer (all of them are to be followed), the message:
./libuClibc-0.9.27.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
means that the libuClibc-0.9.27.so binary has been stripped its symbols or you have not privileges to read the file, and so, the symbol table. The linker is unable to use that binary and it can only be loaded into memory. Anyway, you need a nonstripped shared object, and as suggested by #user3629249, don't use -static (by the reason stated in his answer), put the parameters in order (library dir before the library to be linked, also stated by him). Even you can link the shared by specifying it as:
cris-gcc -nostdlib -o compiled main.c libluClibc-0.9.27.so
and another thing: You need not only the standard C library to link an executable... you normally use a crt0.o at the beginning of your program with the C runtime and the start code for your program. You have not included that, and probably the compiler is getting it from another place.
One question: If you got the compiler, why do you intend to supply your own version of the standard library? isn't provided by the compiler? If you change the libc, then you must change also the crt0.o file. It defaults to some compiler provided, and you haven't received the message no definition for start.
Try to compile with just a main function, as you did, but don't specify shared libraries or directories... just the main code:
cris-gcc -o compiled main.c
and see what happens.... this will be very illustrative of what you lack in your system.

Is there a way to have a linker pull part of an object file from a library for linking?

I have a project with thousands of C files, many libraries, and dozens of programs to link, and to speed up the compilation, I am combining C files into translation units that include multiple C files. This is sometimes referred to as single compilation unit, single translation unit, or unity build.
I have multiple of these translation units compiled into different libraries, and these libs were previously created by compiling each C file individually.
For example:
old library.lib:
file1.o
file2.o
file3.o
file4.o
file5.o
file6.o
new library.lib:
translation_unit_1.o
translation_unit_2.o
translation_unit_1.c:
#include "file1.c"
#include "file2.c"
#include "file3.c"
translation_unit_2.c:
#include "file4.c"
#include "file5.c"
#include "file6.c"
So these compile into: translation_unit_1.o and translation_unit_2.o. And the library is the new library.lib shown above.
Now say I have a program that I want to link to library.lib that refers to a function in file2.c. But has a different version of file1.c that it compiles that duplicates symbols in the file1.c in the library, so it only needs file2.c from the library.lib to link. Or perhaps I have a need to link code from file1.c but can't link file2.c because it has a dependency that I don't want to rely on (example below).
program:
main.o
file1.o
library.lib
Is there a way with any linker that you know of to get the linker to only pull the code from file2.c out of translation_unit_1.o object code and use that to link main.o to make the program?
An alternative would be to split the translation_unit_1.o out into file1.o, file2.o, file3.o if that is possible, then feed that to the linker.
Thanks for any help.
edit 1
This is for single code base that is compiled for both a bare metal ARM platform that uses ELF compiled with ARM ADS 1.2 toolchain and for a Windows platform that uses the Visual Studio toolchain. However thoughts on how to approach the problem on other platforms and toolchains are welcome.
Here is a concrete example on MacOS using clang.
example code below is here: https://github.com/awmorgan/single_translation_unit_lib_link
library:
file1.c this file is needed to link
file2.c this file is not used to link and has an unresolved dependency which could be in another library or object
main.c:
int main( void ) {
extern int file1_a( void );
int x = file1_a();
}
file1.c:
int file1_a(void) {
return 1;
}
file2.c:
int file2_a( void ) {
extern int file3_a( void );
return file3_a(); // file3_a() is located somewhere else
}
single_translation_unit.c:
#include "file1.c"
#include "file2.c"
this works to produce program1.out:
++ clang -c file1.c -o file1.o
++ clang -c file2.c -o file2.o
++ libtool -static file1.o file2.o -o library1.lib
++ clang -c main.c -o main1.o
++ clang main1.o library1.lib -o program1.out
this fails to produce program2.out:
++ clang -c single_translation_unit.c -o single_translation_unit.o
++ libtool -static single_translation_unit.o -o library2.lib
++ clang -c main.c -o main2.o
++ clang main2.o library2.lib -o program2.out
Undefined symbols for architecture x86_64:
"_file3_a", referenced from:
_file2_a in library2.lib(single_translation_unit.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
changing the link order does not work either:
++ clang library2.lib main2.o -o program2.out
Undefined symbols for architecture x86_64:
"_file3_a", referenced from:
_file2_a in library2.lib(single_translation_unit.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Is there a way with clang, gcc, microsoft or any linker
None of clang, gcc or microsoft is a linker (the first two are compilers, and the third is a corporation).
The answer also depends on the platform (which you didn't specify).
IF you are building on a Linux, or another ELF platform, you could compile your code with -ffunction-sections -fdata-sections, and the linker will automagically do what you want.
Is there a way to have a linker pull part of an object file from a library for linking?
In general, linkers operate on sections, and can't split sections apart (you get all or nothing).
Without -ffunction-sections, all functions in a single translation unit end up in a single .text section (this is an approximation -- template instantiations and out-of-line function definitions for inline functions usually end up in a section of their own). Therefore, the linker can't select some, but not all, parts of the .text.
With the GCC/binutils ELF toolchain, or suitably compatible tools, you can do this by:
Compiling single_translation_unit.c with the options -ffunction-sections, -fdata-sections
Linking program2.out with the linker option option -gc-sections.
E.g. (on Linux):
$ gcc -ffunction-sections -fdata-sections -c single_translation_unit.c -o single_translation_unit.o
$ ar rcs library2.a single_translation_unit.o # On Mac OS, use libtool to make the static library if you prefer.
$ gcc -c main.c -o main2.o
$ gcc main2.o library2.a -Wl,-gc-sections -o program2.out
You may replace gcc with clang throughout.
The linkage succeeds because:
In compilation, -ffunction-sections directed the compiler to emit each function definition
in a distinct code section of the object file, containing nothing else, rather than merging them all into
a single .text section, as per default.
In the linkage, -Wl,-gc-sections directed the linker to discard unused sections,
i.e. sections in which no symbols were referenced by the program.
The definition of the unreferenced function file2_a acquired a distinct code section,
containing nothing else, which was therefore unused. The linker was able to discard this unused section, and along with it
the unresolved reference to file3_a within the definition of file2_a.
So no references to file2_a or file3_a were finally linked, as we can see:
$ nm program2.out | egrep '(file2_a|file3_a)'; echo Done
Done
And if we re-do the linkage requesting a mapfile:
$ gcc main2.o library2.a -Wl,-gc-sections,-Map=mapfile -o program2.out
then the mapfile will show us:
...
...
Discarded input sections
...
...
.text.file2_a 0x0000000000000000 0xb library2.a(single_translation_unit.o)
...
...
that the function section text.file2.a originating in library2.a(single_translation_unit.o)
was indeed thrown away.
BTW...
Because of the way a static library is used in linkage,
there is no point in archiving the single object file single_translation_unit.o alone into a static library
library2 and then linking your program against library2, if you know that your program references any
symbol defined in single_translation_unit.o. You might as well skip creating library2 and just link single_translation_unit.o instead.
Given that symbols defined in single_translation_unit.o are needed, the linkage:
$ gcc main2.o library2.a [-Wl,-gc-sections] -o program2.out
is exactly the same linkage as:
$ gcc main2.o single_translation_unit.o [-Wl,-gc-sections] -o program2.out
with or without -Wl,-gc-sections.
And...
I trust you're aware that while a unity build well be fastest for your builds-from-clean,
it may equally well be slow for most incremental builds, as against an automated build system, typically Make based,
that is well-crafted to minimise the amount of rebuilding required per source change. Chances are if you can
benefit from a unity build, it's only from a unity build as well as an efficient incremental build.

C compiler gcc gives linker command failed error [duplicate]

I'm getting the following error and can't for the life of me figure out what I'm doing wrong.
$ gcc main.c -o main
Undefined symbols:
"_wtf", referenced from:
_main in ccu2Qr2V.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
main.c:
#include <stdio.h>
#include "wtf.h"
main(){
wtf();
}
wtf.h:
void wtf();
wtf.c:
void wtf(){
printf("I never see the light of day.");
}
Now, if I include the entire function in the header file instead of just the signature, it complies fine so I know wtf.h is being included. Why doesn't the compiler see wtf.c? Or am I missing something?
Regards.
You need to link wtf with your main. Easiest way to compile it together - gcc will link 'em for you, like this:
gcc main.c wtf.c -o main
Longer way (separate compilation of wtf):
gcc -c wtf.c
gcc main.c wtf.o -o main
Even longer (separate compilation and linking)
gcc -c wtf.c
gcc -c main.c
gcc main.o wtf.o -o main
Instead of last gcc call you can run ld directly with the same effect.
You are missing the fact that merely including a header doesn't tell the compiler anything about where the actual implementation (the definitions) of the things declared in the header are.
They could be in a C file next to the one doing the include, they could come from a pre-compiled static link library, or a dynamic library loaded by the system linker when reading your executable, or they could come at run-time user programmer-controlled explicit dynamic loading (the dlopen() family of function in Linux, for instance).
C is not like Java, there is no implicit rule that just because a C file includes a certain header, the compiler should also do something to "magically" find the implementation of the things declared in the header. You need to tell it.

Undefined symbols error when using a header file

I'm getting the following error and can't for the life of me figure out what I'm doing wrong.
$ gcc main.c -o main
Undefined symbols:
"_wtf", referenced from:
_main in ccu2Qr2V.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
main.c:
#include <stdio.h>
#include "wtf.h"
main(){
wtf();
}
wtf.h:
void wtf();
wtf.c:
void wtf(){
printf("I never see the light of day.");
}
Now, if I include the entire function in the header file instead of just the signature, it complies fine so I know wtf.h is being included. Why doesn't the compiler see wtf.c? Or am I missing something?
Regards.
You need to link wtf with your main. Easiest way to compile it together - gcc will link 'em for you, like this:
gcc main.c wtf.c -o main
Longer way (separate compilation of wtf):
gcc -c wtf.c
gcc main.c wtf.o -o main
Even longer (separate compilation and linking)
gcc -c wtf.c
gcc -c main.c
gcc main.o wtf.o -o main
Instead of last gcc call you can run ld directly with the same effect.
You are missing the fact that merely including a header doesn't tell the compiler anything about where the actual implementation (the definitions) of the things declared in the header are.
They could be in a C file next to the one doing the include, they could come from a pre-compiled static link library, or a dynamic library loaded by the system linker when reading your executable, or they could come at run-time user programmer-controlled explicit dynamic loading (the dlopen() family of function in Linux, for instance).
C is not like Java, there is no implicit rule that just because a C file includes a certain header, the compiler should also do something to "magically" find the implementation of the things declared in the header. You need to tell it.

Creating libraries in C/C++ - ld can't find my library

I'm trying to learn how to create a C/C++ library in a linux environment but I'm having a problem (probably a trivial one) that online tutorials had not helped to solve.
For definiteness let's say I have a foo.c file with the following code:
//file: foo.c
#include <stdio.h>
void hello(void)
{
printf("hello!\n");
}
a foo.h:
//file: foo.h
void hello(void);
and a program that uses the function hello() from foo.c, named prog.c:
//file: prog.c
#include "foo.h"
int main(void)
{
hello();
return 0;
}
The three files are all on the same directory. Then I compiled foo.c with:
gcc -fPIC -c foo.c
and got a foo.o file. Then I used ld to create the library file:
ld -G foo.o -o libfoo.so
But when I try to compile prog.c with:
gcc -o prog prog.c -lfoo
I got an error message:
/usr/bin/ld: cannot find -lfoo
collect2: ld returned 1 exit status
I'm convinced that this is some kind of trivial path problem, but I couldn't find the solution. So my question is really if this procedure above is wrong or if I have to put the libfoo.so file in a special path.
Another question is how this changes if I'm using g++ instead of gcc.
Thanks.
EDIT:
I know I can compile both prog.c and foo.c to prog.o and foo.o an then link them to make an executable. But in my original problem I want to compile foo.c in a way that I can distribute to people who will use my functions in their own programs.
ld doesn't search the current directory by default. If you want it to do this you need to use the -L command line option, so if your library is in the current directory you need to add -L. to the last gcc call. If the library is dynamically linked you also need to add the current directory to the environment variable LD_LIBRARY_PATH (I assume you're on linux).
Of course, if your library is in any other non-standard path you need to use that instead of the current directory.
Try
gcc -o prog prog.c -lfoo -L.
The -L switch adds its argument to the set of paths that ld looks in for library files. The syntax is identical for g++.

Resources