Does it matter whether a compiled C program ends in .o? - c

For a hello world program, hello.c, does it matter if I compile it to a file name ending in .o? Or is it just a convention? E.g. should I do this:
gcc -o hello.o hello.c
Or this:
gcc -o hello hello.c
In a Linux environment

The situation here is a bit confusing because there are two kinds of "object files" — those that are truly intermediate object files (the ones normally ending in .o), and final executables.
You can use a typical command-line C compiler in two ways. You can compile to an intermediate object file, using the -c option, and then "link" to a final executable as a second step:
cc -c -o hello.o hello.c # step 1
cc -o hello hello.o # step 2
Or you can compile and link in one fell swoop:
cc -o hello hello.c # step 3
In the first case, when you compile and link in separate steps, the extension .o for the intermediate object file is the very strong convention by which everybody knows that it is in fact an intermediate object file. Notice the difference between steps 2 and 3. In step 3, the way the compiler knows it has some compiling to do is the extension .c. In step 2, on the other hand, the extension .o tells it the file is already compiled, and merely needs to be linked.
(Footnotes: Actually the compiler might assume in step 2 that any unrecognized filename was an intermediate object file to be linked. Also, we're talking about Unix here. Under Windows, the conventional extension for intermediate object files is .obj.)
Also, as you may know, the extension .o is very much the default when compiling only. In step 1, it would have sufficed to just say cc -c hello.c.
The advantage to "separate compilation" is that it gives you a lot more flexibility. If you have a larger program, made from several source files, you could recompile everything, all at once, every time, like this:
cc -o program file1.c file2.c file3.c
But if you compile separately, like this:
cc -c file1.c
cc -c file2.c
cc -c file3.c
cc -o program file1.o file2.o file3.o
then later, when you make a change to, say, file2.c, you can take a shortcut and only recompile that one file. (This does come at the cost of some disk space, to keep all those intermediate .o files around, and some complexity and extra typing, which for larger programs you usually let a build program like make take care of for you.)
Another thing you can do is to compile the same file multiple ways. For example, I often find myself wanting to test a utility function in a "standalone" way. As an (unrealistically simple) example, suppose that file3.c contains a function to multiply a number by two:
int doubleme(int x)
{
return x * 2;
}
Suppose that, elsewhere in file1.c and file2.c, whenever I want to multiply an integer by 2, I call my doubleme function. (Obviously this is completely silly and unrealistic, but it's just an example.)
But suppose you want a way to test the doubleme function, in a standalone way. I will often do something like this. At the end of file3.c, I will add:
#ifdef TEST_MAIN
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int x = atoi(argv[1]);
printf("doubleme(%d) = %d\n", x, doubleme(x));
}
#endif
Now I can compile file3.c in two different ways. If I compile it normally, like this:
cc -c file3.c
then I get file3.o, containing the compiled version of the doubleme function, that I can link in when I build myprogram. Or, I can say
cc -c -DTEST_MAIN -o file3_test.o file3.c
cc -o file3_test file3_test.o
and then I can invoke things like
file3_test 55
to test out the function.

By convention extension (in linux at least) .o implies an Object File, not an executable. So, yes, you can use this extension, as in gcc -o hello.o hello.c, but it's misleading and a bad idea. Better to do gcc -o hello hello.c.
However, if you are building the object file (i.e. compile only, not link) you would use the -c option, as in gcc -c hello.c, which will create the object file hello.o.
(Just summarizing what's already in the comments.)

By convention extension (in linux at least) .o implies an Object File, not an executable. So, yes, you can use this extension, as in gcc -o hello.o hello.c, but it's misleading and a bad idea. Better to do gcc -o hello hello.c.

Related

is there any use for GCC -S flag with gcc -c

I wonder if there is any benefit for using the -S GCC option in my Makefiles.
I've been compiling C files like the following for quite some time now:
gcc -c a.c -o a.o
gcc -c b.c -o b.o
---
gcc a.o b.o -o a.out
Now would it be better going:
gcc -S a.c -o a.s
gcc -S b.c -o b.s
---
gcc -c a.s -o a.o
gcc -c b.s -o b.o
---
gcc a.o b.o -o a.out
Also there is apparently the option of skipping the .o phase, assembling directly .s files into a binary. Which option you think is the best and why?
-S flags asks gcc to produce human readable assembly code - .o files are nice for a linker but rather cryptic for most human beings...
It is mainly used when you need low level optimization of a (short) piece of code that has been identified by profiling as being a bottleneck. You can compare how the compiler will translate various versions and choose the one that will give the most efficient machine code for that specific implementation.
It is not intended to be used in standard makefiles.
Also there is apparently the option of skipping the .o phase, assembling directly .s files into a binary.
Plain assembly is never transformed directly to executable binary code, there is always in intermediate object-file step.
gcc a.s b.s -o ab.exe
will always call the assembler (twice) which produces object code for either units, and then the objects are linked. Add -v to the command line to see which sub-commands are executed by gcc. gcc is not actually a compiler, it is just a driver program calling jobs depending on options and file extensions. The compiler proper is cc1 (for C code), cc1plus (for C++ code), etc.
Which option you think is the best and why?
-S has the advantage to producing assembly code, however the compiler will always generate assembly code as intermediate step. It's just the case that it's written to temporary files, with 2 notable exceptions:
-save-temps: This will not use some temporary-file names (for example in /tmp), but save the intermediate code in the same place as the objects (there are two flavors actually, -save-temps=obj and -save-temps=src).
-pipe: This will used pipes to transfer code from one sup-program to the next instead of files (except with -save-temps which nullifies -pipe).
Thus, if you want to see the generated assembly, -save-temps might be the way to go. However, that option also applies to the pre-processed code which is saved in .i for C, .ii for C++ and .s for assembly. This is often very appreciated when working with C macros.
In the case you intend to inspect the compiler-generated assembly, you might enjoy -fverbose-asm which injects asm comments that indicate the C/C++ source associated to the assembly. And it might be a good idea not to clutter assembly with debug-info in that case.

compile multiple source file in c

I have written c program, Which has 3 file(.c ) , Main program has
two threads and one file has mysql connection function, One file has
thread functions definition. I don't know how to compile all these
codes, Normally I tried like this,
cc -pthread main.c
But if I compile like this I am getting error called mysql functions
are undefined But I have written thread as separate program and
mysql as separate program and complied individually , it complied
successfully and I got output. So please help me to compile my
project File names are,
main.c (2 threads are declared) functions.c (thread function
definition, and mysql func declared) db.c ( mysql function
definition)
please help to compile my code?
You have two basic options when compiling multiple .c files:
Option 1)
cc file1.c file2.c file3.c -o executable_name
Advantage: simple
Disadvantage: if all you change is one file you are recompiling all the files
Option 2)
cc file1.c -c -o file1.o
cc file2.c -c -o file2.o
cc file3.c -c -o file3.o
cc file1.o file2.o file3.o -o executable_name
Advantage: If you change one file you do not have to recompile everything
Disadvantage: Multiple commands (but you should use a Makefile at this point)
The -c flag tells the compiler to compiler but not link. You don't want to link as you have not compiled all of your files. The final invocation of cc links all the .o files into the executable executable_name
It is a little bit difficult to understand exactly what you need, but I can tell you from what you've stated that you'll need to include specific libraries in your compile statement you currently are not. Also, a -l flag needs to prefix your libraries.
Try something like this:
gcc -lpthread main.c functions.c db.c -o main $(mysql_config --libs)
To explain, mysql_config --libs returns all the configuration libraries needed to run mysql ddl inside your C program.
Given your updates on your file declarations I'm guessing you're a Java programmer. C is not Java. If you are declaring functions you are only going to use once in main.c you should put them inside main.c unless you need them to be portable.

What is wrong with my header files?

I've just completed a school assignment and I'm having a problem testing my code because I keep getting the following output after running make packetize (it's a makefile the professor gave us)
cc packetize.c -o packetize
/tmp/ccJJyqF6.o: In function `block_to_packet':
packetize.c:(.text+0xb1): undefined reference to `crc_message'
collect2: ld returned 1 exit status
make: *** [packetize] Error 1
block_to_packet is defined in a file called packetize.c, crc_message is defined in crc16.c (both of which contain an #include "data.h" line). data.h also has the function heading for crc_message in it All of these files are in the same directory. I've been trying to compile them for the past hour and a half and have searched Google endlessly with no avail. It has something to do with linking I've read, my instructor has not taught this and so I don't know how to compile these files to test their outputs. Can anyone let me know what's wrong?
Your header files are absolutely OK. What you have there is a linker error: The compilation of packetize.c ran without problems, but then you're trying to link an executable file packetize (since you did not give the -c option which states "compile to object file"). And the executable would need the compiled code from crc16.c as well.
Either you have to give all sources on the compiler line:
cc packetize.c crc16.c -o myApp
Or you have to compile into individual object files, eventually linked together:
cc -c packetize.c -o packetize.o
cc -c crc16.c -o crc16.o
cc packetize.o crc16.o -o myApp
The former is what you'd do in a one-shot command line, the latter is what a Makefile usually does. (Because you do not need to recompile crc16.c if all you did was modify packetize.c. In large projects, recompiles can take significant amounts of time.)
Edit:
Tutorial time. Take note of the existence / absence of -c options in the command lines given.
Consider:
// foo.c
int foo()
{
return 42;
}
A source file defining the function foo().
// foo.h
int foo();
A header file declaring the function foo().
// main.c
#include "foo.h"
int main()
{
return foo();
}
A source file referencing foo().
In the file main.c, the include makes the compiler aware that, eventually, somewhere, there will be a definition of the function foo() declared in foo.h. All the compiler needs to know at this point is that the function will exist, that it takes no arguments, and that it returns int. That is enough to compile the source to object code:
cc -c main.c -o main.o
However, it is not enough to actually compile an executable:
cc main.c -o testproc # fail of compile-source-to-exe
ld main.o -o testproc # fail of link-object-to-exe
The compiler was promised (by the declaration) that a definition of foo() will exist, and that was enough for the compiler.
The linker however (implicitly run by cc in the first example) needs that definition. The executable needs to execute the function foo(), but it is nowhere to be found in main.c. The reference to foo() cannot be resolved. "Unresolved reference error".
You need to either compile both source files in one go...
cc foo.c main.c -o testproc # compile-source-to-exe
...or compile foo.c as well and provide the linker with both object files so it can resolve all references:
cc -c foo.c -o foo.o
ld foo.o main.o -o testproc # link-objects-to-exe
Post Scriptum: Calling ld directly as pictured above most likely will not work just like that. Linking needs a couple of additional parameters, which cc adds implicitly -- the C runtime support, the standard C library, stuff like that. I did not give those parameters in the examples above as they would confuse the matter and are beyond the scope of the question.
You have to compile crc16.c as well and link these two object files to build the binary. Otherwise packetize.c, from where crc_message() is being called, has no knowledge of it.
Try using
cc packetize.c crc16.c -o packetize
Your call crc_message() from packetize.c would just be fine.
As Totland writes crc_message is defined in crc16.c; which means that packetize.c can't see the definition, no matter how many shared headers they have. You do not have a compile error but an error from the linker.
If you compile your c files first to object files and then link everything to an executable it will work.

compile .c with gcc

I'm trying to compile a program that have main.c and a lot of .c and .h files .
Is there any way to compile and link without passing all .c file in the gcc command
like
gcc main.c file.c file2.c -o main
Your shell can expand wildcards. So you can:
gcc *.c -o main
Of course, you'll have to make sure that you don't have any extra *.c files in the directory that you don't actually want compiled. A better option is to use a build system such as Make or SCons.
'make' is the tool for building C apps. Below is the hello world version.
$ cat main.c
#include <stdio.h>
int main (char *argv[], int argc) {
printf("Hello World\n");
return 0;
}
$ make main
cc main.c -o main
$ ./main
Hello World
Edited in deference to Shahbaz comment:
The original question was trying to simplify the command-line for gcc. The right direction for the programmer is to learn about make. Since there is a bit of a learning curve with make, I wanted to offer simple stepping stone which does something useful. By getting started in this way, you don't need a make file. Simply type 'make programname' as shown above. Make uses its default rules and associated varabiles. $(CC) -c $(CFLAGS) $(CPPFLAGS) The astute programmer can build on this by setting well-know variables.
From here one can tinker with a makefile. In the spirit of stepping stones, consider this trival makefile
$ cat makefile
SRCS = main.c
OBJ = ${SRCS:.c=.o}
CC=gcc
main: ${OBJ}
$ make
gcc main.o -o main
By setting the well-known make variable CC to control which compiler is used. OBJ is computed from the list of source files. The trival target starts one on the road to rules.
Anyway, my hope is this post and other answers get the original questioner on there way.
Regards,
-jk
If you're asking about the command-line, you can just use wildcards to specify all the .c files as #Man of One Way suggested. But in general, C applications of any-but-trivial-size are built using "makefiles" which are extremely helpful.
You might want to read a tutorial such as http://www.cs.umd.edu/class/fall2002/cmsc214/Tutorial/makefile.html
gcc -o main -I. `find . -name "*\.c"`
This way you could have the .c and .h files in subfolders if you wish.
However, this is not a good way of doing it. A better way would be to create a Makefile
As already said, make is the best way to go
Learn just what you need at every point
Besides, it is important to also use some flags that will help you out while coding:
-Wall -> sets all warning flags
-g, -ggdb -> generates debug code
-ansi, -std=c99
A really good book on how to use make is,
http://shop.oreilly.com/product/9780937175903.do

Compile multiple C files with make

(I am running Linux Ubuntu 9.10, so the extension for an executable is executablefile.out) I am just getting into modular programming (programming with multiple files) in C and I want to know how to compile multiple files in a single makefile. For example, what would be the makefile to compile these files: main.c, dbAdapter.c, dbAdapter.h? (By the way, If you haven't figured it out yet, the main function is in main.c) Also could someone post a link to the documentation of a makefile?
The links posted are all good. For you particular case you can try this. Essentially all Makefiles follow this pattern. Everything else is shortcuts and macros.
program: main.o dbAdapter.o
gcc -o program main.o dbAdapter.o
main.o: main.c dbAdapter.h
gcc -c main.c
dbAdapter.o dbAdapter.c dbAdapter.h
gcc -c dbAdapter.c
The key thing here is that the Makefile looks at rules sequentially and builds as certain items are needed.
It will first look at program and see that to build program, it needs something called main.o and dbAdapter.o.
It will then find main.o. However, to build main.o, it will need main.c and dbAdapter.h (I assume dbAdapter.h is included in main.c).
It will use those sources to build main.o by compiling it using gcc. The -c indicates the we only want to compile.
It does the same thing with dbAdapter.o. When it has those two object files, it is ready to link them. It uses the gcc compiler for this step as well. The -o indicates that we are creating a file called program.
GNU make should be what you're looking for.

Resources