When to compile files together and when to use a library [closed] - c

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Search didn't turn anything up.
If I have a file main.c and a pair aux.h and aux.c for useful functions when should I just compile main.c and aux.c together and when should I make a library out of aux (like aux.a).

when should I just compile main.c and aux.c together and when should I make a library out of aux (like aux.a).
When you have a single utility file, putting it into a library buys you nothing. It's only when you have a few separate files, which provide some common, but related functionality that it starts to make sense to put them into an archive (or shared) library.
You actually have 3 choices in building your program:
Compile and link everything together in a single step:
gcc -o main main.c aux.c
Write a proper Makefile. That will result in separate compilation:
gcc -c main.c
gcc -c aux.c
gcc -o main main.o aux.o
Write a Makefile that uses the library. This will also result in separate compilation, something like:
gcc -c main.c
gcc -c aux.c
ar cru libaux.a aux.o
gcc -o main main.o -laux
For anything other than the smallest toy program, you should at least do #2, because doing so eliminates the time wasted recompiling aux.c or main.c when either didn't change, while still ensuring that your program is built correctly.
As I said, doing #3 for a single file buys nothing at all (you just perform a few unnecessary steps).
Using a library is advised when:
You have several different programs that you build, and
You have several related utility files, some (but not all) of which are used in these programs.
Consider the case where you have prog1, prog2 and prog3, and aux1.c, aux2.c and aux3.c utility files. Suppose that prog1 uses code from aux1.c and aux2.c, prog2 uses code from aux1.c and aux3.c, and prog3 uses code from all aux*.c files.
In that situation, using case #2, you will have to write Makefile that looks something like this:
prog1: main1.o aux1.o aux2.o
prog2: main2.o aux1.o aux3.o
prog3: main3.o aux1.o aux2.o aux3.o
That's (potentially) a lot of management.
Compare to the Makefile that uses case #3 (i.e. a library):
prog1: main1.o libaux.a
prog2: main2.o libaux.a
prog3: main3.o libaux.a
Simpler, isn't it?
Also consider what happens if main1.c changes, and starts to use aux3.o as well. In case #2, you would have to adjust your Makefile, but in case #3 your Makefile is already correct!

if the aux.c is used frequently in many other places,you could consider to make it a static or dynamic library.
if it's just a one time run toy program,nothing matters

Related

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

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.

How does the computer know whether to use static or dynamic linking in this case

I'm getting thru Head First C, doing all the programming examples. Chap 8 starts with static linking. We use these four commands (Cygwin):
gcc -I./includes -c hfcal.c -o hfcal.o
gcc -I./includes -c elliptical.c -o elliptical.o
ar -rcs ./libs/libhfcal.a hfcal.o
gcc elliptical.o -L./libs -lhfcal -o elliptical
Assuming I typed that correctly, it prints out a few lines showing calories burned on an elliptical machine.
Next they introduce dynamic linking. It's not the clearest chapter in the book and I'm still a little fuzzy on it. Compounding that is the fact that I'm not sure whether the new code has typos or not. The text says the code is the same as before but leaves out the dot before the slash and even leaves off the s at the end of includes in one case. I put the dot back in and only changed the parts they said should be changed. (I went to their errata page and saw nothing relevant.) Here's the new code:
gcc -I./includes -fPIC -c hfcal.c -o hfcal.o //Got a warning, fPIC ignored, as book predicted
gcc -shared hfcal.o -o ./libs/libhfcal.dll
gcc -I./includes -c elliptical.c -o elliptical.o
gcc elliptical.o -L./libs -lhfcal -o elliptical
Notice that except for the the ignored -fPIC and the second line, these are the same commands as the first case, in slightly different order.
After I successfully ran ./elliptical, I wondered if I was supposed to in fact use a different directory and that maybe the missing dot was intentional. I never rm'd the archive .a file and it was in the same directory as the new dll file. How would the compiler know whether to use libhfcal.a or libhfcal.dll, since they are both there and I call them the same way? Is it because of the order?
Any good resources where I can read a clearer explanation, esp with code I can try?
I think is that the lack of the dot and the s are typos. Otherwise you would need to have an includes and an include directories on the root of your system with the header files needed.
It doesn't make much sense, since it's not specified elsewhere in the book, as far as I can tell.
But I think that when trying the dynamic linking you should delete the archive ./libs/libhfcal.a you created for the static linking case, and change the third line from:
gcc -shared hfcal.o -o ./libs/libhfcal.dll
to:
gcc -shared hfcal.o -o ./libs/libhfcal.dll.a

multiple small programs in one code::blocks project

I am new to Code::Blocks. For my studies I am programming several small programms in C (just to try things out).
I tried to put them all in one project, because they belong to the same topic, but that doesn't work because each of them has a main function.
Any ideas how I can put those files together somehow, but not depending on each other?
Suppose your source files are called
prog1.c
prog2.c
mylib.c
mylib.h
where prog1.c and prog2.c each contain a main() function and mylib.c (with the corresponding header file mylib.h) contains some library functions that should be linked to each program. In your Code::Blocks project you need to create multiple targets now. From the menu choose 'File/New/Build target...' and name them 'prog1' and 'prog2'. Now add all of your source files to the project (in case you haven't done so already).
Now right-click on prog1.c and select "Properties..." from the context menu. In the dialog box choose the 'Build' tab and make sure that under "Belongs to target" only "prog1" is checked. Do the same with prog2.c and the target "prog2". For "mylib.c" make sure that both "prog1" and "prog2" are checked.
Now you can easily choose in the UI which build target to build and run. Note that if you add another target, say "prog3", then you have to go to the build properties of prog1.c and prog2.c again and uncheck "prog3".
A C program should contain only one main function.. Divide all your separate programs as Functions and put them in a single C program or you can even put it in multiple files and compile them..
You can use a switch case for calling different functions..
Remove the main function from all the programs and convert them into functions..
Call them where ever required.. This will help you..
let's say that your project contains 3 c files and each c file is a separate program and it contains its own main function:
program1.c
program2.c
program3.c
So you can write a Makefile (its name in your computer should be "Makfile"). It will build the program you want separately
This is how your makefile looks:
all: program1 program2 program3
%.o: %.c
$(CC) $(CFLAGS) -c -o $# $^
program1: program1.o
$(CC) $(LDFLAGS) -o $# $^
program2: program2.o
$(CC) $(LDFLAGS) -o $# $^
program3: program3.o
$(CC) $(LDFLAGS) -o $# $^
clean:
rm -f *.o program1 program2 program3
with the above Makefile you can build each program separetly
example
$ make program1
will build only program1
or you can buil all programs with
$make all
It seems to me as if you are starting to build some nice utility functions. So follow the advice offered by raghu-srikanth-reddyce and create separate functions for each little program. However I would add that it would be better to create yourself a simple C library to keep them all in which you can link to at any time. Most professional programmers keep such libraries.
A simple makefile will enable you to build a final binary that you can link to.
Good luck with your programming ;)
If you want to compile in one file, you dont need a Project File then.
Just make a New File, then write all the code in a single file. Also use Function and Procedure if you need it.
This is quite late but since I was once here with the same question, and I believe most students had/ have/ will have this same question, let me elaborate where you have been played at.
In Educational Courses and in Real World, a project is (in general) some problem you work on, find a solution, then make a report (+ documentation) on it.
In Programming IDE, a project is the problem's solution itself. Hence, while you may have multiple individual problems within one project in any Python IDE, Any standard C/C++ IDE project must have only one 'main()' to rule them all (unless you know how to create makefiles).
What the AP tried to do is to put several different problem's solutions fit within one solution's space - not a possible thing to do in Code::Blocks. Even if all the problems may share the same topic (say, Graph Theory), they are individual problem (Dijkstra vs Floyd) themselves.

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