I don't know how to link multiple files - c

I'm learning how to use header files and I have a problem while linking these 3 files:
f.c:
#include "f.h"
int getfavoritenumber(void)
{
return 3;
}
f.h:
#ifndef _f_H_
#define _f_H_
int getfavoritenumber(void);
#endif
main.c:
#include <stdio.h>
#include "f.h"
int main (void)
{
printf("%d\n", getfavoritenumber());
return 0;
}
Compiling gcc main.c -o f I get this error:
Undefined symbols for architecture x86_64:
"_getfavoritenumber", referenced from:
_main in main-7be23f.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
But if I include the f.c file with gcc main.c f.c -o f it works.
So, when compiling, should I include each C file that I used in my project, or am I missing something? Because adding each single file to gcc is very annoying.

When you have multiple source files that together make an executable, they must be each compiled and then linked together. This is done by specifying each source file when the compiler is invoked as you've discovered.
Note also that you can either do the compiling and linking in one step as you've done, or you can separate them as follows:
gcc -c main.c
gcc -c f.c
gcc -o f main.o f.o
Managing multiple source files and their dependencies is where using a makefile comes into play.

You need to understand there are three stages from c source code to run able binary. For etch and every file this stages must be followed except for header file or .h file.
First Stage : Source to assembly. gcc -S -o source.s source.c
Second Stage : assembly to Compiled Binary Object. Which can not be runned directly. gcc -c source.s -o source.o
Third Stage : In this stage we marge all the compiled binary to a single compiled binary where an input binary object holds an entry function int main().This the file which we can run on our operating system.gcc -o OutputFile source1.o source2.o source3.o ......
After this three stages we can run our program by ./OutputFile. You can avoid making assembly file and directly make object file.
Yeah you must include all the file for compilation in you project. You can use automation tools like automake or linux shell script for doing this job.

Related

Steps of compilation

I am trying to compile simple Hello World C program in a sequential manner. First creating the preprocessed file, then creating the assembly file, then creating the object file and finally invoking the linker to create the ELF.
The problem is I am not able to execute the ELF being created.
I have tried following steps
gcc -E hello.c 1>hello.i
gcc -S hello.i
gcc -c hello.s
ld -o hello hello.o -lc
At this step I got a warning saying
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400260
But an executable with the name hello is created.
When I try to execute the output using
./hello
I am getting the error
bash: ./hello: No such file or directory
//hello.c contains following code
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("\tHello World \n");
return (0);
}
I would suggest that you link your object files (however they are produced) with gcc, not ld.
gcc will call ld with the appropriate options, since it knows more about the source code and will create whatever is necessary for the assumptions that ld makes.

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.

Proper way to include C code from directories other than the current directory

I have two directories, sorting and searching (children of the same directory), that have .c source files and .h header files:
mbp:c $ ls sorting
array_tools.c bubble_sort.c insertion_sort.c main selection_sort.c
array_tools.h bubble_sort.h insertion_sort.h main.c selection_sort.h
mbp:c $ ls searching
array_tools.c array_tools.h binary_search.c binary_search.h linear_search.c linear_search.h main main.c
Within searching, I am building an executable that needs to use insertion_sort function, declared in insertion_sort.h and defined in insertion_sort.c inside sorting. The following compilation successfully produces an executable:
mbp:searching $ clang -Wall -pedantic -g -iquote"../sorting" -o main main.c array_tools.c binary_search.c linear_search.c ../sorting/insertion_sort.c
However, I would like to be able to include functions from arbitrary directories by including a header using #include and then providing the compiler with the search path. Do I need to precompile the .c files to .o files beforehand? The man page for clang lists the following option:
-I<directory>
Add the specified directory to the search path for include files.
But the following compilation fails:
mbp:searching $ clang -Wall -pedantic -g -I../sorting -o main main.c array_tools.c binary_search.c linear_search.c
Undefined symbols for architecture x86_64:
"_insertion_sort", referenced from:
_main in main-1a1af0.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
main.c has the following includes:
#include <stdio.h>
#include <stdlib.h>
#include "linear_search.h"
#include "binary_search.h"
#include "array_tools.h"
#include "insertion_sort.h"
I do not understand the link between header files, source files, and object files. To include a function defined in a .c file, is it sufficient to include the homonymous header file, given that the .c file is in the same directory as the header? I have read multiple answers here on SO, the man page for clang and a number of tutorials, but was unable to find a definitive, clear answer.
In response to #spectras:
One by one, you give the compiler a source file to work on. For instance:
cc -Wall -Ipath/to/some/headers foo.c -o foo.o
Running
mbp:sorting $ clang -Wall insertion_sort.c -o insertion_sort.o
produces the following error:
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Okay, it's mixed up a bit. Let's see how one typically compiles a simple multi-file project.
One by one, you give the compiler a source file to work on. For instance:
cc -c -Wall -Ipath/to/some/headers foo.c -o foo.o
The -c flag tells the compiler you want an object file, so it should not run the linker.
The compiler runs the preprocessor on the source file. Among other things, every time it sees a #include directive, it searches the include paths for named file and basically copy-pastes it, replacing the #include with the content. This is done recursively.
This is the step where all .h you include get merged into the source file. We call the whole thing a translation unit.
You can see the result of this step by using -E flag and inspect the result, for instance:
cc -Wall -Ipath/to/some/headers foo.c -E -o foo.test
Let's make this short as other steps are not relevant to your question. The compiler then creates an object file from the resulting source code. The object file contains binary version of all code and data that was in the translation unit, plus metadata that will be used to put everything together and some other stuff (like debugging info).
You can inspect the contents of an object file using objdump -xd foo.o.
Note that as this is done for each source file, this means that headers get parsed and compiled again and again and again. That's the reason they should only declare stuff and not contain actual code: you would end up with that code in every object file.
Once done, you link all the object files into an executable, for instance:
cc foo.o bar.o baz.o -o myprogram
This step will gather all, resolve dependencies and write everything into an executable binary. You may also pull in external object files using -l, like when you do -lrt or -lm.
For instance:
foo.c includes bar.h
bar.h contains a declaration of function do_bar: void do_bar(int);
foo.c can use it, and compiler will generate foo.o correctly
foo.o will have placeholders and the information that it requires do_bar
bar.c defines the implementation of do_bar.
so bar.o will have the information “hey if anyone needs do_bar, I got it here”.
linking step will replace placeholders with actual calls to do_bar.
Finally, when you pass multiple .c files to the compiled like you do in your question, the compiler does basically the same thing, only it won't generate the intermediate object files. Overall process behaves the same though.
So, what about your error?
Undefined symbols for architecture x86_64:
"_insertion_sort", referenced from:
_main in main-1a1af0.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
See? It says linking step failed. That means previous step went well. The #include worked. It's just in the linking step, it's looking for a symbol (data or code) called _insertion_sort, and does not find it. That's because that symbol was declared somewhere (otherwise source using it would not have compiled), but its definition is not available. Either no source file implemented it, or the object file that contains it was not given to the linker.
=> You need to make _insertion_sort's definition available. Either by adding ../sorting/insertion_sort.c to the source lists you pass or by compiling it into an object file and passing that. Or by building it into a library so it can be shared by your two binaries (otherwise they'll each have a copy embedded).
When you get there, usually starting to use a build toolsuite such as CMake is a good idea. It will take care of all the details for you.

How to use asm procedure and take return value in C

i've got a gcc version 2.95.2 19991024 (release) toolchain and now i need to use an Assembly function that is in a file positioned in the same folder of the makefile.
I've tried tons of ways to put that file in my toolchain, with no luck.
Basically i declare that in ASM:
.globl util_MyFunc
util_MyFunc:
...
And in the main void of C file:
extern void util_MyFunc();
int main(void) {
util_MyFunc();
...
When i compile i got the error related to not recognized:
/cygdrive/c/MyDev/tmp/main.o(.text+0x8bc): undefined reference to `util_MyFunc'
make: *** [test.o] Error 1
Thanks!
EDIT:
i've tried to use following to generate the ".o" file from the asm file
C:\MyDev>gcc -c test.asm -o test.o
It results:
gcc: utils.asm: linker input file unused since linking not done
or:
C:\MyDev>gcc test.asm -o test.o
but...:
ld: cannot open crt0.o: No such file or directory
The canonical extension for assembly files that gcc expects is .s. You should use that (or assemble using as directly). Also possibly put the -o test.o before the input file name. Finally, you will need libc development files if you want to use libc. Otherwise use -nostdlib switch.
You should try: gcc -o test main.c utils.s

Compiling multiple C files with gcc

I have two files, main.o and modules.o, and I'm trying to compile them so that main.o can call functions in modules.o. I was explicitly told not to try #include module.o. I really don't know what I should be doing instead. I tried a few different versions of gcc (such as gcc -x c driver main.o modules.o), but nothing I get works: the compiler continuously returns
error: called object is not a function
The .o files are my source code files (I was instructed to put my source code in files with extension .o.) What do I do to compile this?
If you have your two source files, you can compile them into object files without linking, as so:
gcc main.c -o main.o -c
gcc module.c -o module.o -c
where the -c flag tells the compiler to stop after the compilation phase, without linking. Then, you can link your two object files as so:
gcc -o myprog main.o module.o
This is all perfectly normal behavior, you'll usually get your makefile to compile things separately and link them at the end, so you don't have to recompile every single source file every time you change one of them.
Talking about main.o "calling functions in" module.o is perfectly fine, but an .o file is not a source file, it's a compiled object file. If "put my source code in files with extension .o" actually meant "compile my source code into files with extension .o" then the situation would make a whole lot more sense.
You should define the functions that you want to call from modules.c into main.c into a header file, let us say modules.h, and include that header file in main.c. Once you have the header file, please compile both of the files together: gcc main.c modules.c -o output
Two additional notes. First, modules.o is an object file and it should not be included in a C source file. Second, we cannot have a C file have a .o extension. You should actually get an error when compiling a .o file. Something like:
$ cat t.o
int main() {
int x = 1;
return 0;
}
$
$ gcc t.o
ld: warning: in t.o, file is not of required architecture
Undefined symbols:
"_main", referenced from:
start in crt1.10.6.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
$
program: main.o
gcc -o main main.c anotherSource.c
This works for me.
You should be including .h files which are "headers". So if your main file is using modules then you should include module's header file.

Resources