Can I re-compile a file with new code? - c

I have a question. I was wondering if you could re-compile code with another piece of code. For example (theoretical):
main.c:
#include <stdio.h>
void showme();
int main()
{
showme();
}
void showme()
{
fprintf(stderr, "errtest, show me");
}
Compile this file to main. (So the main is compiled)
After this I want to add a piece of code.
addthis.c:
void test()
{
test();
}
Now I want to use the (compiled) main and re-compile it with addthis.c.
When running it (./mainWithAddthis) should show the print 2 times.
I hope I explained it clear. Anybody an idea?

You need a forward declaration for your void test() like you have one for the void showme(). Compile each .c file with -c (compile only) option:
gcc -c addthis.c -o addthis.o
gcc -c main.c -o main.o
Then link the two object files with:
gcc main.o addthis.o -o main
Then enjoy ./main :-)

Your first code will not compile since there's not definition of test();.
As I understand, you want to take the compiled main and add it with the code generated on addthis.o to create a 2nd application named mainWithAddthis. This is not possible!
You are either confused or trying to do some hardcore trick.

Building an executable is a two step process.
For every source file you specify (in your project/makefile), your compiler will build an object file
For every object file you specify (in your project/makefile), your linker will link them together and make your executable
One way to re-compile would be simply to re-build your entire project. You'd get more or less the same result.
But it sounds like what you want to do is recompile only the source file, addthis.c, then re-link the old version of main.o (the object file compiled for main.c) with the new version of addthis.o. How to do this is completely dependent on the compiler and build system you use.
Also, that solution will only work if you have main.o, addthis.c, and have the exact same compiler binaries/install, and compiler flags used to generate main.o. If this is all on your box, then you're probably okay.
If you only have the files addthis.c and main.exe, then no there is no portable way to do what you want.

You can't do what you are talking about after the fact without some hardcore time with a hex editor.
However, if you plan ahead and build it into your software, you can use dynamic loading to achieve the same effect, which is how a lot of software provides plugin functionality. Check out glib modules for a common way to do this in C.

main.c
void f();
int main()
{
f();
return 0;
}
addon1.c
#include <stdio.h>
void f()
{
printf("I am the ONE.\n");
}
addon2.c
#include <stdio.h>
void f()
{
printf("I am the TWO.\n");
}
Compilation
gcc -c main.c -o main.o
gcc -c addon1.c -o addon1.o
gcc -c addon2.c -o addon2.o
gcc main.o addon1.o -o main1
gcc main.o addon2.o -o main2
You will have ./main1 and ./main2 programs which will print ...ONE. and ...TWO..

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.

Shared library and rpath

I cannot make rpath work properly and make my binary to search for the library in the specified folder:
I have 3 very simple files:
main.c
#include <stdio.h>
#include <func.h>
int main() {
testing();
return 1;
}
func.h
void testing();
func.c
#include "func.h"
void testing(){
printf(testing\n");
}
Then I proceed to create a shared library as it follows:
gcc -c -fpic func.c -o ../release/func.o
gcc -shared -o ../release/lib/lib_func.so ../release/func.o
And then compile the program:
gcc main.c ../release/lib/lib_time_mgmt.so -Wl,-rpath=/home/root/ -o ../release/main
I receive the next warning:
main.c:7:2: warning: implicit declaration of function ‘testing’ [-Wimplicit-function-declaration]
testing();
But besides it, the program works fine.
However, my problem is that if now I want to move the library to /home/root (as specified in rpath) it does not work and the library is still searched only in the path specified when I compiled the main.c file which is ../release/lib/lib_time_mgmt.so
What am I doing wrong?
EDIT: After accepting the answer, I leave here the exact line as I used it and made it work for whoever might find it useful:
gcc main.c -L/home/root -Wl,-rpath,'/home/root/' -l:libtime_mgmt -o ${OUT_FILE}
Note: the rpath was used with the path betwen simple '. Not sure if that was the reason why it was not working before, but it worked this way now.
rpath is not used at compile time, but rather at link/runtime... thus you probably need to use both of these:
-L /home/root - to link correctly at build time
-Wl,-rpath=/home/root - to link correctly at run-time
You should use the -l ${lib} flag to link with libraries, don't specify their path as an input.
In addition to this, convention states that the libraries are named libNAME.so - e.g:
-l func will try to link with libfunc.so
-l time_mgmt will try to link with libtime_mgmt.so
Once you've addressed the above points, try the following:
gcc main.c -L/home/root -Wl,-rpath=/home/root -lfunc -ltime_mgmt -o ${OUT_FILE}
As a final point, I'd advise that you try not to use rpath, and instead focus on installing libraries in the correct places.
Unrelated to your question, but worth noting. Your use of #include <...> vs #include "..." is questionable. See: What is the difference between #include <filename> and #include "filename"?

Why I got "clang: error: cannot specify -o when generating multiple output files"?

I am a newbie in C. I have two simple source code files f1.c and f2.c.
f1.c looks like:
#include <stdio.h>
#include "f.h"
void f1(void) {
// some code ...
}
function f2() in f2.c relies on f1() in f1.c.
#include <stdio.h>
#include "f.h"
void f2(void) {
f1();
}
f1.c and f2.c share a same header f.h,
void f1(void);
void f2(void);
There are no main() access, I just want to compile these two file into a .o file without linker (using -c option),
gcc -c f1.c f2.c -o f2.o
then I got,
clang: error: cannot specify -o when generating multiple output files
but when I mentioned only f2.c, it works well,
gcc -c f2.c -o f2.o
So what's the problem? Thanks!
You should look into the compilation process for C. The first stage is compiling the .c source code into .o object files. The .c files do not need to see the other .c files; they are accepting as fact what you've told them about the existence of external functions. It's not until the linker comes in that it really needs to see the function because the implementation details don't matter to your .c file, just the interface, which you've presumably given it in the header.
What you can do, if you like, is drop the -o flag specifying the output file you want to create. Just compile with
gcc -c f1.c f2.c
and it will know to create f1.o and f2.o which will be able to link against each other when the time comes that you do want to go through with the linking process.
I am curious, however, what your intentions may be for wanting to compile these without linking. I only ask as you refer to yourself as a newbie, so I am wondering if maybe there is an end goal you have in mind and perhaps aren't asking the right question.

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

Including source files in C

So I get the point of headers vs source files. What I don't get is how the compiler knows to compile all the source files. Example:
example.h
#ifndef EXAMPLE_H
#define EXAMPLE_H
int example(int argument); // prototype
#endif
example.c
#include "example.h"
int example(int argument)
{
return argument + 1; // implementation
}
main.c
#include "example.h"
main()
{
int whatever;
whatever = example(whatever); // usage in program
}
How does the compiler, compiling main.c, know the implementation of example() when nothing includes example.c?
Is this some kind of an IDE thing, where you add files to projects and stuff? Is there any way to do it "manually" as I prefer a plain text editor to quirky IDEs?
Compiling in C or C++ is actually split up into 2 separate phases.
compiling
linking
The compiler doesn't know about the implementation of example(). It just knows that there's something called example() that will be defined at some point. So it just generated code with placeholders for example()
The linker then comes along and resolves these placeholders.
To compile your code using gcc you'd do the following
gcc -c example.c -o example.o
gcc -c main.c -o main.o
gcc example.o main.o -o myProgram
The first 2 invocations of gcc are the compilation steps. The third invocation is the linker step.
Yes, you have to tell the compiler (usually through a makefile if you're not using an IDE) which source files to compile into object files, and the compiler compiles each one individually. Then you give the linker the list of object files to combine into the executable. If the linker is looking for a function or class definition and can't find it, you'll get a link error.
It doesn't ... you have to tell it to.
For example, whe using gcc, first you would compile the files:
gcc file1.c -c -ofile1.o
gcc file2.c -c -ofile2.o
Then the compiler compiles those files, assuming that symbols that you've defined (like your example function) exist somewhere and will be linked in later.
Then you link the object files together:
gcc file1.o file2.o -oexecutable
At this point of time, the linker looks at those assumtions and "clarifies" them ie. checks whether they're present. This is how it basically works...
As for your IDE question, Google "makefiles"
The compiler does not know the implementation of example() when compiling main.c - the compiler only knows the signature (how to call it) which was included from the header file. The compiler produces .o object files which are later linked by a linker to create the executable binary. The build process can be controlled by an IDE, or if you prefer a Makefile. Makefiles have a unique syntax which takes a bit of learning to understand but will make the build process much clearer. There are lots of good references on the web if you search for Makefile.
The compiler doesn't. But your build tool does. IDE or make tool. The manual way is hand-crafted Makefiles.

Resources