I'm using gcrypt, but my compiler seems to unable to find it. Here is my makefile. function.c is a function source file containing functions I defined; I also wrote a header file miao.h with function declaration, and gcrypt.h is included in it. main.c is a source file including miao.h. When I do make: .Could anyone help me? This bothers me so long.
CC = gcc
CFLAGS = 'libgcrypt-config --cflags'
LIBS = 'libgcrypt-config --libs'
OBJS = function.o main.o main
all: $(OBJS)
function.o: function.c
$(CC) -c function.c $(CFLAGS)
main.o: main.c
$(CC) -c main.c $(CFLAGS)
main: main.o function.o
$(CC) -o main main.o function.o $(LIBS)
clean:
rm $(OBJS)
the makefile should be written more like the following:
caveat: I was unable to test the makefile as I do not have libgcrypt-config available.
Per the web site: https://gnupg.org/documentation/manuals/gcrypt/Building-sources.html the libgcrypt-config is an executable so should be surrounded by back-ticks, not single quotes so it will be executed in the current shell.
(back ticks on stackoverflow will result in emphasised text but should still be visible as to where they should be placed.)
Note: where I have placed <tab> your actual makefile needs to have a tab character
Note: targets, like all and clean do not produce a file with the same name, so early in the file there needs to be the statement: .PHONY: all clean
when defining a macro, use := rather than = so the macro is only evaluated once.
Any calls to shell functions should be incorporated via a macro, so it is easy to make a change. In general it is best to include the path to the shell function: I wrote this on Linux, your path may be different. Specifying the actual path becomes very important when cross compiling or there are duplicate names visible via the $PATH statement (as can easily be the case with gcc)
Note: the actual libgcrypt-config executable must be in visible via your $PATH environment variable.
Note: all the individual compile statements could be reduced to the following two lines: (and nothing else needed for the compiles)
%.o: %.c
<tab>$(CC) -c $< -o $# -I. $(CFLAGS)
Note: do not place the contents of a rule where the dependencies is expected. This error was noted in the clean: target
the proposed makefile follows:
CC := /usr/bin/gcc
RM := /usr/bin/rm
CFLAGS := `libgcrypt-config --cflags`
LIBS := `libgcrypt-config --libs`
OBJS := function.o main.o main
TARGET := main
.PHONY: all clean
all: $(TARGET)
function.o: function.c
<tab>$(CC) -c function.c $(CFLAGS) -o function.o -I.
main.o: main.c
<tab>$(CC) -c main.c $(CFLAGS) -o main.o -I.
$(TARGET): $(OBJS)
<tab>$(CC) -o $(TARGET) $(OBJS) $(LIBS)
clean:
<tab>$(RM) -f $(OBJS)
Related
I have three files. main.c, graph.c, and graph.h.
I know the code works without a makefile because I tested it on the onlinegbd compiler. Everything runs smoothly.
When I try to run my makefile in terminal, I get an error of:
undefined reference to "function"
Where "function" is every function I call in main that is in graph.c.
So this leads me to think I'm not compiling graph.c in my makefile.
edit
I have confirmed it is the makefile. I compiled it using:
gcc -o xGraph main.c graph.c
And it ran without issue.
Here is the makefile:
CC = gcc
VPATH = SRC INCLUDE
TARGET = XGraph
CFLAGS = -g -Wall
all: $(TARGET)
$(TARGET): main.o graph.o
$(CC) main.o graph.o -o $(TARGET)
main.o: main.c graph.h
$(CC) $(CFLAGS) main.c
graph.o: graph.c graph.h
$(CC) $(CFLAGS) graph.c
clean:
rm *.o *~ $(TARGET)
When compiling C code the first stage is to generate .o files. Pass the -c flag to gcc to do this.
main.o: main.c graph.h
$(CC) $(CFLAGS) -c main.c
graph.o: graph.c graph.h
$(CC) $(CFLAGS) -c graph.c
In C, there are two types of undefined reference errors. The first results in an implicit declaration of function error, while the second gives your undefined reference. The first says gcc cannot find a definitition of your function. but the second means gcc sees nothing wrong with your code, then tries to link object files using ld and that crashes the code. Make sure that your source files are included in compilation and they have declarations, not just definitions. Also, providing a minimum reproducible example of your code might be helpful here.
Your simplest Makefile can be:
CFLAGS = -g -Wall
xGraph_objs = main.o graph.o
xGraph: $(xGraph_objs)
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $(xGraph_objs)
main.o graph.o: graph.h
as there are implicit rules (that use the $CFLAGS variable, so you don't need to add rules to do the compilation, just to specify the extra dependencies between the objects and the header file)
The structure I use frequently for small projects is very similar to yours:
targets = xGraph
toclean = $(targets)
xGraph_deps = # no dependencies to link the executable. (E.g. creating a library needed to link this)
xGraph_objs = main.o graph.o
xGraph_libs = # no libs to specify at link time. (E.g. -lm -lX11)
xGraph_ldfl = # no flags for the linker. (E.g. -L/usr/local/lib)
toclean += $(xGraph_objs)
all: $(targets)
clean:
$(RM) $(toclean)
xGraph: $(xGraph_deps) $(xGraph_objs)
$(CC) $(LDFLAGS) $(xGraph_ldfl) $(xGraph_objs) -o $# $(xGraph_libs)
My program is divided into 6 files:
list.h (Containing basic list struct info and function prototypes)
list.c (Containg the implementation of the above)
search_tree.h (Containing basic tree struct info and function prototypes)
search_tree.c (Containing the implementation of the above, and includes list.h)
search.h ( again, prototypes of functions )
search.c (implementation of the aobve functions)
main.c ( Requires all of the above in order to run )
I cant seem to figure out what the makefile should be, i've tried the one below but it doesnt work and i get errors of structs and functions not implemented.
myprog: list.o search_tree.o search.o main.o
gcc -o myprog list.o search_tree.o search.o main.o
list.o: list.c list.h
gcc -c list.c
search_tree.o: search_tree.c search_tree.h
gcc -c search_tree.c
search.o: search.c search.h
gcc -c search.c
main.o: search.h search_tree.h list.h hash_table.h
gcc -c main.c
You do not need to explicitly create a rule for each file - make has a number of implicit rules that already do 90% of what you need. Your makefile can be as simple as
CC=gcc
CFLAGS=-std=c11 -pedantic -Wall -Werror # my usual compiler flags
LDFLAGS= # specify additional libraries and library search paths here
myprog: main.o search.o search_table.o list.o
$(CC) -o $# $(LDFLAGS) $?
clean:
rm -rf myprog *.o
There's already an implicit rule to build .o files from .c files, so you don't need to create your own unless you want to override the default, which is
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#
You do need the explicit myprog rule to link the object files into the executable since the executable name doesn't match any of the source or object file names. $# expands to the target name, myprog, and $? expands to the list of prerequisites for the target (i.e., the object files). $< expands to the first name in the list of prerequisites.
This doesn't cover header file dependencies, but your project is small enough for that to not be too much of an issue. However, give this article a read for one way to handle that.
Similar to John's proposal with a small bug fixed ($^ automatic variable instead of $?), a bit more automation (wildcard to search for the C source files) and with dependencies added for the header files ($(OBJS): %.o: %.h static pattern rule):
EXEC := myprog
OBJS := $(patsubst %.c,%.o,$(wildcard *.c))
$(EXEC): $(OBJS)
$(CC) -o $# $(LDFLAGS) $^
$(OBJS): %.o: %.h
clean:
rm -f $(EXEC) $(OBJS)
I have a semi-large project that I am trying to debug and for some reason gdb is only willing to show the source code of the main.c file and refuses to list any of the other files.
Here are the relevant lines in my makefile:
DEFINES= #...
BASE_CFLAGS= #...
BASE_LIBS= #...
#Load the required source files
HEADERS=$(wildcard *.h) $(wildcard subdir/*.h)
SOURCES=$(HEADERS:.h=.c)
OBJECTS=$(SOURCES:.c=.o)
#Flags for each compilation type
CFLAGS=-Wall $(DEFINES)
main: CFLAGS+=$(BASE_CFLAGS) $(BASE_LIBS)
debug: CFLAGS+=$(BASE_CFLAGS) $(BASE_LIBS) -g -DDEBUG_MODE
#Compilation rules for objects
%.o: %.c %.h
$(CC) -c $(CFLAGS) $< -o $#
#main compilation
main:$(OBJECTS) main.c
$(CC) main.c $(OBJECTS) $(CFLAGS) -o ../main.out
#debug compilation
debug:$(OBJECTS) main.c
$(CC) main.c $(OBJECTS) $(CFLAGS) -o ../debug.out
clean:
rm $(OBJECTS)
For some reason when I run make debug then try to debug the resulting output it acts as though main.c is the only file compiled with the -g flag even though I ran make clean beforehand and inspected make's output to ensure that it did compile each object with the -g flag.
Before my most recent change I had a Makefile that looked more like this:
DEFINES= #...
BASE_CFLAGS= #...
BASE_LIBS= #...
#Load the required source files
HEADERS=$(wildcard *.h) $(wildcard subdir/*.h)
SOURCES=$(HEADERS:.h=.c)
OBJECTS=$(SOURCES:.c=.o)
#main compilation
main:$(SOURCES) main.c
$(CC) $(SOURCES) main.c -Wall $(DEFINES) $(BASE_CFLAGS) $(BASE_LIBS) -o ../main.out
#debug compilation
debug:$(SOURCES) main.c
$(CC) $(SOURCES) main.c -Wall $(DEFINES) $(BASE_CFLAGS) $(BASE_LIBS) -g -DDEBUG_MODE -o ../debug.out
Which was obviously less efficient than my new solution but it did have a few advantages. Firstly I didn't have to run make clean between each main and debug compilation (I actually have a total of 8 different compilation rules, so having to clean between most of them to get the individual sources to be recompiled with the new options is a pain). Secondly and most importantly, GDB was able to see all of the source files when I ran the debug compilation. Now, as I said, it can only see main.c and lists the rest as "No source file named ???.c".
Therefore I have two questions:
(not really important) Is there a way to compile each source independently, but force them to be recompiled with new options when a different compilation rule is selected in make.
(very important, please help!) Why can't gdb see my other source files and what can I do to have it load them?
the following makefile can be invoked with make or with make -Ddebug depending on if you want to produce the main.out file or the debug.out file.
Note: the <tab> will need to be replaced with an actual tab char in your makefile
CC := /usr/lib/gcc
RM := /usr/lib/rm
ifndef debug
target := main.out
debugInfo :=
else
target := debug.out
debugInfo := -g -DDEBUG_MODE
endif
#Load the required source files
HEADERS=$(wildcard *.h) $(wildcard subdir/*.h)
SOURCES=$(HEADERS:.h=.c)
OBJECTS=$(SOURCES:.c=.o)
#Flags for each compilation type
CFLAGS+= $(debugInfo) -c -Wall -Wextra -Wconversion -std=gnu99
.PHONY : all
all : $(TARGET)
$(TARGET):$(OBJECTS)
<tab>$(CC) $(debugInfo) $^ -o $# $(LFLAGS)
#Compilation rules for objects
%.o:%.c %.h
<tab>$(CC) $(CFLAGS) $< -o $#
.PHONY : clean
clean:
<tab>$(RM) $(OBJECTS)
For example:
There are 3 source files {main.c test1.c test2.c} in the directory
and a directory file named test3,
and there is a source file named test.c in the directory of test3.
Now I want to create a makefile to compile and link these four source files.
And this is my Makefile:
# Cancel statement "CC=gcc"
src:=$(wildcard *.c) test3.c
obj:=$(patsubst %.c,%.o,$(src))
main:$(obj)
gcc -o main $(obj)
.PHONY:clean
clean:
rm *.o *~
When I called make to compile them, I got a output like this:
cc -c -o main.o main.c
cc -c -o test1.o test1.c
cc -c -o test2.o test2.c
cc -c -o test3.o test3/test3.c
gcc -o main main.o test1.o test2.o test3.o
I know 'cc' is linked to 'gcc' in Linux.
What I don't understand is why did Make call cc to compile these four source files, but call gcc to link the object files?
You changed one rule: the one that links the program main from the object files. And when make did that link, you can see it used gcc.
You didn't do anything to change the built-in rules that make is using to compile the object files, so they use the default (the value of the variable CC) which is cc.
You wrote only the rule to link the object files, and allowed Make to use its default rule to decide how to build the object files from the source files.
GNU Make will expose its rules if you ask it with --print-data-base. In this case, it tells us
%.o: %.c
# recipe to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<
and
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
and finally
CC = cc
This explains why Make uses cc to compile your C sources. To change that, simply set CC = gcc. Here's a complete Makefile which does that and also makes best use of Make's built-in rules, to help when you need to extend it:
src := $(wildcard *.c) test3.c
obj := $(patsubst %.c,%.o,$(src))
CC = gcc
main: $(obj)
$(LINK.c) -o $# $^ $(LDLIBS)
.PHONY: clean
clean:
$(RM) *.o *~
I have three files: program.c, program.h and headers.h.
program.c includes program.h and headers.h.
I need to compile this on Linux using gcc compiler. I'm not sure how to do this. Netbeans created one for me, but it's empty.
Interesting, I didn't know make would default to using the C compiler given rules regarding source files.
Anyway, a simple solution that demonstrates simple Makefile concepts would be:
HEADERS = program.h headers.h
default: program
program.o: program.c $(HEADERS)
gcc -c program.c -o program.o
program: program.o
gcc program.o -o program
clean:
-rm -f program.o
-rm -f program
(bear in mind that make requires tab instead of space indentation, so be sure to fix that when copying)
However, to support more C files, you'd have to make new rules for each of them. Thus, to improve:
HEADERS = program.h headers.h
OBJECTS = program.o
default: program
%.o: %.c $(HEADERS)
gcc -c $< -o $#
program: $(OBJECTS)
gcc $(OBJECTS) -o $#
clean:
-rm -f $(OBJECTS)
-rm -f program
I tried to make this as simple as possible by omitting variables like $(CC) and $(CFLAGS) that are usually seen in makefiles. If you're interested in figuring that out, I hope I've given you a good start on that.
Here's the Makefile I like to use for C source. Feel free to use it:
TARGET = prog
LIBS = -lm
CC = gcc
CFLAGS = -g -Wall
.PHONY: default all clean
default: $(TARGET)
all: default
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) -Wall $(LIBS) -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
It uses the wildcard and patsubst features of the make utility to automatically include .c and .h files in the current directory, meaning when you add new code files to your directory, you won't have to update the Makefile. However, if you want to change the name of the generated executable, libraries, or compiler flags, you can just modify the variables.
In either case, don't use autoconf, please. I'm begging you! :)
For example this simple Makefile should be sufficient:
CC=gcc
CFLAGS=-Wall
all: program
program: program.o
program.o: program.c program.h headers.h
clean:
rm -f program program.o
run: program
./program
Note there must be <tab> on the next line after clean and run, not spaces.
UPDATE Comments below applied
all: program
program.o: program.h headers.h
is enough. the rest is implicit
The simplest make file can be
all : test
test : test.o
gcc -o test test.o
test.o : test.c
gcc -c test.c
clean :
rm test *.o
Depending on the number of headers and your development habits, you may want to investigate gccmakedep. This program examines your current directory and adds to the end of the makefile the header dependencies for each .c/cpp file. This is overkill when you have 2 headers and one program file. However, if you have 5+ little test programs and you are editing one of 10 headers, you can then trust make to rebuild exactly those programs which were changed by your modifications.