Including static library and header Makefile questions (C) - c

My file stacking is as follows
dir1/
mylib.a
myheader.h
file.c
executable
dir2/
dependentfile.c // depends on functions in myheader.h implemented in mylib.a
I would like to link my static library file in my Makefile WITHOUT using its name, but just indicating its path. What I have is as follows:
Makefile for dir2/
CC = gcc
CFLAGS = -g -Wall $(INCLUDES)
INCLUDES = -I../dir1
LDFLAGS = -g -L../dir1
exec: dependentfile.o
dependentfile.o: dependentfile.c
Running 'make' just gives me a bunch of implicit declaration errors, and undefined references because it's not looking in the paths I have specified with -L and -I. My dependentfile.c also has the line
#include "myheader.h"
which it can't find.
How should I modify the makefile in order to make this work? I have tried multiple things, even specifying the lib file with -l and writing the complete path to no avail.
Any help is appreciated!
#
EDIT: Figured it out!
Turns out I was forgetting LDLIBS. So for everyone else, the makefile ended up looking like:
CC = gcc
CFLAGS = -g -Wall $(INCLUDES)
INCLUDES = -I../dir1
LDFLAGS = -g -L../dir1
LDLIBS = -lmylib (my actual file was named libmylib.a, forgo the "lib")
exec: dependentfile.o
dependentfile.o: dependentfile.c

I think you should use
#include "myheader.h"
Your header file name should be quoted.

Related

C Link External Library in Makefile

I am having issues linking a library (termbox) when compiling. I get the error:
make: *** No rule to make target `termbox.h', needed by `test.o'. Stop.
Makefile:
edit: test.o
gcc -Wall -o edit test.o
test.o: test.c termbox/src/termbox.h
gcc -Wall -c test.c -ltermbox/src
Include:
#include "termbox/src/termbox.h"
I have also tried using the compiled library but ran into similar issues. Do I have to use some sort of combination of specifying the header file and the location of the compiled library?
The directory of my termbox folder is in the same directory as test.c.
Thanks!
You have managed to compile and include the header file for the library, but you did not yet tell the compiler where the code (definitions) are - i.e. you did not tell it to link in the library yet.
You will need to do that next, this is done in a similar way to telling the linker what files to link, but with some extra syntax. It appears to be a static library (.a suffix) so you can link like this:
test.o: test.c termbox/src/termbox.h
gcc -Wall -c test.c -Itermbox/src -Lsrc -ltermbox
Where -L... specifies where libraries can be found and -l... specifies the library name to link to minus the lib prefix and the .a or .so suffix. Also note that order is important, so leave the library linkage at the end.
More on library linking order here
UPDATE
Sorry I added the linking to the wrong line! - here is the updated answer:
# The linker stage
edit: test.o
gcc -Wall -o edit test.o -Lsrc -ltermbox
# Compile stage
test.o: test.c termbox/src/termbox.h
gcc -Wall -c test.c -ltermbox/src

Compiling error with errors like "multiple definition"

I am trying to compile my C program and I am getting some weird compiling errors and I have no idea where it is coming from. I already found similar posts, but their solution of specifying the output with -o is not working.
SO this is how my makefile looks like (shortened up):
CC = gcc -O3 -Wextra -Wall -pg -g -std=c99
OBJ = ./src/main.o ./src/FUNC.o ./src/getRoot.o ./src/getTree.o
out: $(OBJ)
g++ -std=c99 -g -o ./myProgramm $(OBJ)
./src/FUNC.o: src/FUNC.c
$(CC) -c src/FUNC.c -o ./src/FUNC.o
./src/main.o: src/main.c
$(CC) -c src/main.c -o ./src/main.o
./src/getRoot.o: src/getRoot.c
$(CC) -c src/getRoot.c -o ./src/getRoot.o
./src/getTree.o: src/getTree.c
$(CC) -c src/getTree.c -o ./src/getTree.o
This is a part of the errors i am getting:
./src/FUNC.o:(.rodata+0x78): multiple definition of `khStrInt'
./src/main.o:(.rodata+0x0): first defined here
./src/FUNC.o: In function `get_nbr_edge_kmer':
/home/Documents/EXAMPLE_CODE/src/FUNC.c:126: multiple definition of `DISTANCE_MAX'
./src/main.o:(.rodata+0x4): first defined here
./src/getRoot.o:(.rodata+0x0): multiple definition of `DISTANCE_MAX'
./src/main.o:(.rodata+0x4): first defined here
./src/main.o:(.rodata+0x4): first defined here
./src/getTree.o:(.rodata+0x0): multiple definition of `DISTANCE_MAX'
./src/main.o:(.rodata+0x4): first defined here
./src/getRoot.o:(.rodata+0x0): multiple definition of `khStrInt'
Does someone maybe have some idea what i am doing wrong here :/
Inside your header file, you should declare your variable like:
extern const int khStrInt;
Then in a .c file, you should define it like:
const int khStrInt = 33;
This means the variable definition is only generated once by the compiler when compiling the .c file and so the linker doesn't see multiple definitions. Also, having the declaration in the header file allows other files which include the header to be able to use the variable.
Quite likely the problem is caused by lack of #include guards.
To prevent a file from being included more than once
#ifndef myheader_h
#define myheader_h
#define DISTANCE_MAX 1000
#endif

CCCOMSTR/LINKCOMSTR for SharedLibrary in SConscript will not work

I'm pretty new to SCons and noticed that CCCOMSTR and LINKCOMSTR will not work when I'm building a shared library in the SConscript.
Here is the simplified version of my SConstruct:
CFLAGS = ["-Wall", "-pedantic", "-std=c99"]
# building environment
env = Environment(CFLAGS = CFLAGS, CPPDEFINES = ["DEBUG"])
# checking dependencies
conf = env.Configure()
conf.CheckHeader("stdlib.h")
conf.CheckHeader("string.h")
conf.CheckLib("libdl")
env["CCCOMSTR"] = "Compiling $SOURCE ..."
env["LINKCOMSTR"] = "Linking $TARGET ..."
SConscript(dirs = ["lib1", "lib2"], exports=["env", "conf"], name = "SConscript")
# main function
env.Program(target = "prog", LIBS=["libdl"], source = Glob("*.c"))
and the library SConscript would look like:
Import("env", "conf")
env.SharedLibrary(target = "test1", source = Glob("*.c"))
My expectation is that the env["CCCOMSTR"] and env["LINKCOMSTR"] should be propagated via Import and displayed properly. This however isn't happening and I see a gcc/clang command instead.
Setting these variables in the SConscript does not make any difference either.
The output is as follows:
scons: Reading SConscript files ...
Checking for C header file stdlib.h... (cached) yes
Checking for C header file string.h... (cached) yes
Checking for C library libdl... (cached) yes
scons: done reading SConscript files.
scons: Building targets ...
Compiling log.c ...
Compiling main.c ...
clang -o lib1/test1.os -c -Wall -pedantic -std=c99 -g -fPIC -DDEBUG lib1/test1.c
clang -o lib1/libtest1.so -shared lib1/test1.os -ldl
clang -o lib2/test2.os -c -Wall -pedantic -std=c99 -g -fPIC -DDEBUG lib2/test2.c
clang -o lib2/libtest2.so -shared lib2/test2.os -ldl
Compiling xalloc.c ...
Linking prog ...
scons: done building targets.
Is it just a SCons bug or something that I am doing wrong here? Could not find much info about it in the net, hence asking here. :)
(SCONS versions that I've tried and that displayed the behaviour above are v2.1.0, v2.3.4)
After some research I found the answer and now it displays it properly:
...
env["SHCCCOMSTR"] = "SHCC $SOURCE"
env["SHLINKCOMSTR"] = "SHLINK $TARGET"
env["CCCOMSTR"] = "CC $SOURCE"
env["LINKCOMSTR"] = "LINK $TARGET"
...
I thought I had tried this before and it didn't work, but obviously something was wrong since it works now. So the output is as follows after the change (as expected):
...
CC log.c
CC main.c
SHCC lib1/test1.c
SHLINK lib1/libtest1.so
SHCC lib2/test2.c
SHLINK lib2/libtest2.so
CC util.c
CC xalloc.c
LINK prog
Oh well - SCons appears to work correctly and in fact rocks!

How to include static library in makefile

I have the following makefile
CXXFILES = pthreads.cpp
CXXFLAGS = -O3 -o prog -rdynamic -D_GNU_SOURCE -L./libmine
LIBS = -lpthread -ldl
all:
$(CXX) $(CXXFILES) $(LIBS) $(CXXFLAGS)
clean:
rm -f prog *.o
I am trying to include the ./libmine library within CXXFLAGS, but it seems like it is not the right way to include a static library, because when I compile the program, I get many undefined references error. So what is actually the right way to include a static library in the makefile?
use
LDFLAGS= -L<Directory where the library resides> -l<library name>
Like :
LDFLAGS = -L. -lmine
for ensuring static compilation you can also add
LDFLAGS = -static
Or you can just get rid of the whole library searching, and link with with it directly.
Say you have main.c, fun.c and a static library libmine.a.
Then you can just do in your final link line of the Makefile
$(CC) $(CFLAGS) main.o fun.o libmine.a
CXXFLAGS = -O3 -o prog -rdynamic -D_GNU_SOURCE -L./libmine
LIBS = libmine.a -lpthread
Make sure that the -L option appears ahead of the -l option; the order of options in linker command lines does matter, especially with static libraries. The -L option specifies a directory to be searched for libraries (static or shared). The -lname option specifies a library which is with libmine.a (static) or libmine.so (shared on most variants of Unix, but Mac OS X uses .dylib and HP-UX used to use .sl). Conventionally, a static library will be in a file libmine.a. This is convention, not mandatory, but if the name is not in the libmine.a format, you cannot use the -lmine notation to find it; you must list it explicitly on the compiler (linker) command line.
The -L./libmine option says "there is a sub-directory called libmine which can be searched to find libraries". I can see three possibilities:
You have such a sub-directory containing libmine.a, in which case you also need to add -lmine to the linker line (after the object files that reference the library).
You have a file libmine that is a static archive, in which case you simply list it as a file ./libmine with no -L in front.
You have a file libmine.a in the current directory that you want to pick up. You can either write ./libmine.a or -L . -lmine and both should find the library.
The -L merely gives the path where to find the .a or .so file. What you're looking for is to add -lmine to the LIBS variable.
Make that -static -lmine to force it to pick the static library (in case both static and dynamic library exist).
Addition: Suppose the path to the file has been conveyed to the linker (or compiler driver) via -L you can also specifically tell it to link libfoo.a by giving -l:libfoo.a. Note that in this case the name includes the conventional lib-prefix. You can also give a full path this way. Sometimes this is the better method to "guide" the linker to the right location.

How to write makefile for C program in UNIX

I have a program test.c which needs to include a header file common.h. I am new to writing make files and so far I have the right make file for just test.c (it uses openssl):
INC=/usr/local/ssl/include/
LIB=/usr/local/ssl/lib/
all:
gcc -I$(INC) -L$(LIB) -o test test.c -lcrypto -ldl
How do I edit the above file to also compile common.h ?
Thanks.
You don't compile header files directly. They will be included by #include in the C files. If common.h is located in the same directory as the make file, you won't need to add anything. Otherwise, you might want to edit the makefile to add other folders that include header files:
INC=-I/usr/local/ssl/include/ \
-I/path/to/another/folder/to/include
LIB=/usr/local/ssl/lib/
all:
gcc $(INC) -L$(LIB) -o test test.c -lcrypto -ldl

Resources