6

I was looking in the gcc manual on linux (man gcc), for the -c option (gcc -c infile) which states:

-c: Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file.
By default, the object file name for a source file is made by replacing the suffix .c, .i, .s, etc., with .o.

more so, while inspecting an ELF file and an object file( with file comand ) the output is the same:

file ./out/main.o: ELF 32-bit LSB relocatable, Atmel AVR 8-bit, version 1 (SYSV), not stripped
file ./out/main.elf: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, not stripped

So they both have same description. My questions are:

  • What is the practical difference between both files, or in case I have multiple source file?
  • What is the correct file to run, and how to generate it?
  • Do I need object files, or they are only intermediary files?
  • If I compile some source files with -c option and some flags( -Wall -g -std=c99 -Os ) and get the object files from them, does the flags persist on ELF file generation( can I skip the flags while generating ELF file if I used them on Object files )?
pfx
  • 20,323
  • 43
  • 37
  • 57
Upgrade
  • 75
  • 1
  • 9

2 Answers2

10

Let's make a simple example. You have three files:

cnt.h

void inc_counter();
void print_counter();

cnt.c

#include <stdio.h>
#include <cnt.h>

static int counter= 0;

void inc_counter() {
    couner++;
}

void print_counter() {
    printf("Counter: %d\n", counter);
}

main.c

#include <counter.h>

int main(char** args) {
    inc_counter();
    print_counter();
    return 0;
}

You then compile cnt.c and main.c to create cnt.o and main.o.

  • cnt.o will contain the executable code for get_counter and inc_counter. For each one it has an entry point. But the code is not executable. The call of printf will not work as the address of printf is not yet know. So the file contains information that this will need to be fixed later.
  • main.o will contain the executable code for main and an entry point for it. Again, the references for inc_counter and print_counter will not work.

In the second step, the files cnt.o, main.o and the standard C library will be linked and an executable output file will be created (with the .elf or no extension). The linker will create the missing links between the call of inc_counter and the function inc_counter. And it will do the same for print_counter and printf, thereby including the code of printf from the standard libary.

So while both file types mainly consist of executable code, .o files only contain pieces of code and .elf files contain a full program.

Note: There are additional variations when you create or use dynamically linked libraries. But for the sake of simplicity, I've excluded them.

Codo
  • 75,595
  • 17
  • 168
  • 206
  • As I asked above, can you help me/point me to some documentation for generating the .map files? More so what are the files with *.out extension? – Upgrade Nov 08 '18 at 15:25
1
  • What is the practical difference between both files, or in case I have multiple source file?

A .o file contains the compiled code from one source (compilation unit) but it is not ready to run: it can contain references to external symbols from libraries or other object files.

  • What is the correct file to run, and how to generate it?

That is the executable file (.exe in windows). It is generated by the linking stage (by the linker) which searches libraries and other object files to resolve external references from the .o files.

  • Do I need object files, or they are only intermediary files?

yes, you need them in order to link them, but they are intermediate files.

  • If I compile some source files with -c option and some flags( -Wall -g -std=c99 -Os ) and get the object files from them, does the flags persist on ELF file generation( can I skip the flags while generating ELF file if I used them on Object files )?

Some flags "persist" in the sense that they detemine the .o files, but not all. -Wall only gives warnings during compilation, -Os specifies some type of optimization, which will result in a .o file with some optimization on the code performed.

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41