Reputation: 41
I'm new to C, and Makefiles are giving me a hard time. Within the Makefile, I want to make an executable that links to a static library. My understanding is that to generate an executable from test.c
located in src/project
the command would be gcc src/project/test.c -o test
, and this executable would be named test. If I wanted to have the executable also link with a static library, lib.a
how would I do that?
Upvotes: 0
Views: 2490
Reputation: 1765
If I wanted to have the executable also link with a static library, lib.a how would I do that?
Short answer is: just include the library in the gcc
command using
gcc src/project/test.c -o test libstuff.a
Or use
gcc src/project/test.c -o test -lstuff -Llibfolder
-L
adds the libfolder
to the list of folders where search for libraries are done. There is a folder search sequence for libraries similar to what happens with #include
processing.
I will show a minimal example of how to build and use an static library in C and manage its use via a very short makefile, under Linux Ubuntu 20.
This is minimal and just for demonstration purposes. There are better ways to write this but I hope that writing this way will make easier for you to follow the logic.
Note: ar
is the archiver in Linux
, just like LIB
in Windows
. The program that manages creation of libraries.
Take a folder with these 4 files
Makefile myLib.c myLib.h testing.c
We want to build a library libmyLib.a
from myLib.c
and use it in testing
For the library:
// myLib.h
int twice(int);
// myLib.c
#include <stdio.h>
int twice(int value) { return value + value; }
The test program
// testing.c
#include <stdio.h>
#include "myLib.h"
int main(void)
{ int x = 42;
printf("x = %d, twice(%d) = %d\n", x, x, twice(x) );
return 0;
}
testing
just calls twice(42)
and outputs 84
x = 42, twice(42) = 84
makefile
We want to type make
and have libmyLib.a
built, testing.c
compiled and testing
generated.
Something like (with make
output suppressed by now):
so_user@DSK-2009:~/projects/so0802$ ls -ltr
total 32
-rw-r--r-- 1 so_user so_user 266 Aug 2 17:46 Makefile
-rw-r--r-- 1 so_user so_user 26 Aug 2 18:23 myLib.h
-rw-r--r-- 1 so_user so_user 155 Aug 2 18:23 testing.c
-rw-r--r-- 1 so_user so_user 79 Aug 2 18:23 myLib.c
so_user@DSK-2009:~/projects/so0802$ make
// supressed output //
so_user@DSK-2009:~/projects/so0802$ ls -ltr
total 44
-rw-r--r-- 1 so_user so_user 266 Aug 2 17:46 Makefile
-rw-r--r-- 1 so_user so_user 26 Aug 2 18:23 myLib.h
-rw-r--r-- 1 so_user so_user 155 Aug 2 18:23 testing.c
-rw-r--r-- 1 so_user so_user 79 Aug 2 18:23 myLib.c
-rw-r--r-- 1 so_user so_user 1792 Aug 2 18:42 testing.o
-rw-r--r-- 1 so_user so_user 1368 Aug 2 18:42 myLib.o
-rw-r--r-- 1 so_user so_user 1510 Aug 2 18:42 libmyLib.a
-rwxr-xr-x 1 so_user so_user 16760 Aug 2 18:42 testing
so_user@DSK-2009:~/projects/so0802$ ./testing
x = 42, twice(42) = 84
so_user@DSK-2009:~/projects/so0802$
make
is an absurdly clever program that takes into account the last modification time of the files to, yes, make things up to date. make
is based on so called makefiles, whose name defaults to Makefile. In the makefile things to be updated are called targets
.
A makefile
, even for a short project, can be a complex thing. But is always easier than not using one.
make
run do?you can present the so called targets
to make
. If you just type make
the program will search for a file named Makefile
and inside the file for a target named all
.
The first command below only updates the library, while the second will try the target all
make libMylib.a
make
make -n
You can always try -n
and make
will list what the program will do to update the targets.
Following the example above...
so_user@DSK-2009:~/projects/so0802$ make -n
make: Nothing to be done for 'all'.
so_user@DSK-2009:~/projects/so0802$
As the targets are all updated. Now suppose testing.c
is changed:
so_user@DSK-2009:~/projects/so0802$ touch testing.c
so_user@DSK-2009:~/projects/so0802$ ls -ltr
total 44
-rw-r--r-- 1 so_user so_user 266 Aug 2 17:46 Makefile
-rw-r--r-- 1 so_user so_user 26 Aug 2 18:23 myLib.h
-rw-r--r-- 1 so_user so_user 79 Aug 2 18:23 myLib.c
-rw-r--r-- 1 so_user so_user 1792 Aug 2 18:42 testing.o
-rw-r--r-- 1 so_user so_user 1368 Aug 2 18:42 myLib.o
-rw-r--r-- 1 so_user so_user 1510 Aug 2 18:42 libmyLib.a
-rwxr-xr-x 1 so_user so_user 16760 Aug 2 18:42 testing
-rw-r--r-- 1 so_user so_user 155 Aug 2 18:57 testing.c
so_user@DSK-2009:~/projects/so0802$ make -n
gcc -c -Wall testing.c
gcc -o testing testing.o libmyLib.a
so_user@DSK-2009:~/projects/so0802$
And you see that, as testing.c
is newer, but as the library has not changed, we need to compile the program and link it with the library:
-rw-r--r-- 1 toninho toninho 266 Aug 2 17:46 Makefile
-rw-r--r-- 1 toninho toninho 26 Aug 2 18:23 myLib.h
-rw-r--r-- 1 toninho toninho 79 Aug 2 18:23 myLib.c
-rw-r--r-- 1 toninho toninho 1368 Aug 2 18:42 myLib.o
-rw-r--r-- 1 toninho toninho 1510 Aug 2 18:42 libmyLib.a
-rw-r--r-- 1 toninho toninho 155 Aug 2 18:57 testing.c
-rw-r--r-- 1 toninho toninho 1792 Aug 2 19:00 testing.o
-rwxr-xr-x 1 toninho toninho 16760 Aug 2 19:00 testing
But now we change myLib.c
and try make -n
:
so_user@DSK-2009:~/projects/so0802$ touch myLib.c
so_user@DSK-2009:~/projects/so0802$ make -n
gcc -c -Wall testing.c
gcc -c -Wall myLib.c
ar rcs libmyLib.a myLib.o
gcc -o testing testing.o libmyLib.a
so_user@DSK-2009:~/projects/so0802$
since the library changed, the header file could have also changed so we need to compile testing.c
also. And call ar
to rebuild the library, before generating a new testing
executable.
all: testing
clean:
rm *.o
rm *.a
rm testing
testing: testing.o libmyLib.a
gcc -o testing testing.o libmyLib.a
testing.o: testing.c myLib.c myLib.h
gcc -c -Wall testing.c
myLib.o: myLib.c myLib.h
gcc -c -Wall myLib.c
libmyLib.a: myLib.o
ar rcs libmyLib.a myLib.o
I hope it is a bit clear how things go with make
. Fell free to ask back about this.
the things before :
are the targets
clean
target is usual, and you see here it just removes thingsmake
is deeply recursive in the search of targets to updateUpvotes: 1
Reputation: 69276
First of all, lib.a
is not a canonically "valid" static library filename, library filenames should start with lib
and continue with the actual name of the library, e.g. libsomething.a
. You would then link such library with -lsomething
, assuming it is in the appropriate system directories. If not, you can add -Lpath/to/directory
to make the linker also look into path/to/directory
for libsomething.a
. See also: Order in which library directories are searched and linked. Alternatively, in case of a static library you could also add the library directly to the GCC command line: gcc prog.c libsomething.a
.
In a very basic Makefile
I would do something like this:
test: src/project/test.c path/to/libsomething.a
gcc $^ -o $@
Upvotes: 2