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)
Related
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)
I am trying to write a Makefile for my project, all the *.c and *.h files are in a folder called src, and the Makefile looks like this --
CC := gcc
CFLAGS := -g -Wall -ansi -pedantic -std=gnu99
LDFLAGS := -lm
INCLUDES := $(wildcard src/*.h)
IFLAGS := $(addprefix -I/,$(INCLUDES))
SRC := $(wildcard src/*.c)
OBJS := $(patsubst %.c, %.o, $(SRC))
APP := app
all: $(OBJS)
$(APP): $(OBJS)
$(CC) $(CFLAGS) $< -o $# $(LDFLAGS)
$(OBJS): $(SRC) $(INCLUDES)
$(CC) $(CFLAGS) $(IFLAGS) -c $< -o $#
clean:
rm -rf $(OBJS)
rm -rf *.out
rm -f $(APP)
At this point I am not building the executable, just trying to compile them to object files, so when I run, I am getting this output --
gcc -g -Wall -ansi -pedantic -std=gnu99 -I/src/structure.h -I/src/rng.h -c src/allocate.c -o src/allocate.o
gcc -g -Wall -ansi -pedantic -std=gnu99 -I/src/structure.h -I/src/rng.h -c src/allocate.c -o src/auxiliary.o
gcc -g -Wall -ansi -pedantic -std=gnu99 -I/src/structure.h -I/src/rng.h -c src/allocate.c -o src/decode.o
gcc -g -Wall -ansi -pedantic -std=gnu99 -I/src/structure.h -I/src/rng.h -c src/allocate.c -o src/display.o
You can see that in each gcc invocation, the source file names do not change, they are all always src/allocate.c why ? However, the object names are correctly expanded like src/allocate.o, src/auxiliary.o and src/decode.oetc.
It seems you've mixed up some things here.
They are basically two type of rules you need to use here, and they both share the same syntax:
targets : prerequisites
recipe
When you write this:
$(APP): $(OBJS)
$(CC) $(CFLAGS) $< -o $# $(LDFLAGS)
You're saying to make that you want to create $(APP), and to do that you need $(OBJS) to exist or to be created.
Now when you write this:
$(OBJS): $(SRC) $(INCLUDES)
$(CC) $(CFLAGS) $(IFLAGS) -c $< -o $#
You're telling make you want to create a list of .o files, and for each individual file that you need all $(SRC) and $(INCLUDES).
Since in the recipe you're using $<, which is a shortcut for the first entry in the prerequisites list, you always end up with the same source file being compiled.
To do what you want, you must abstract things a little bit and tell make "Here is how I want you to build any .o file that depends on a corresponding .c". That is the job of pattern rules:
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -o $# -c $<
Ultimately, your Makefile should look like this:
APP := app
SRC := $(wildcard src/*.c)
OBJ := $(SRC:.c=.o)
CFLAGS := -W -Wall -g -std=c99 -pedantic
LDLIBS := -lm
all: $(OBJS)
$(APP): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean:
$(RM) $(APP) $(OBJ)
Note another couple of things here that you missed:
The -I preprocessor flag (that should be placed in the CPPFLAGS variable) accept a directory, not a file.
The -ansi compiler flag is a synonym of -std=c89. You're using -std=gnu99 right after so that one will be picked ultimately
You don't need to list your header files at all. Don't bother.
Don't use the -r flag of the rm command without care, you'll end up removing folders. It is not used to remove multiple files but to remove recursively, read up your man.
You used $< instead of $^ at the linking phase, so your executable will miss many object files.
To address the comments:
GNU make has a lot of predefined rules, functions and variables that you should be using before rolling your own. It has basic rules for compiling and linking C and C++ programs, among other, this is why your Makefile does not need te redefine the %.o: %c rule that already exists.
You can see all of these by typing this in your favorite shell:
$ make -p > predefined.mk
$(RM), $(CC) are one of these predefined variables, you can see by yourself what they actually contain.
Now, as many users are concerned with header files dependencies, let's adress this issue. You won't have to manually do that, modern compilers like GCC and Clang do this for you once you set them up.
The dependencies for each .c file will be generated in a .d file that must be included in the Makefile.
To tell the compiler to generate these files while compiling, you need to pass a preprocessor flag:
CPPFLAGS := -MMD
Now the dependencies are auto-generated, we need to include them:
DEP := $(OBJ:.o=.d)
-include $(DEP)
You'd also want to clean them:
clean:
$(RM) $(APP) $(OBJ) $(DEP)
Now your Makefile looks like this:
APP := app
SRC := $(wildcard src/*.c)
OBJ := $(SRC:.c=.o)
DEP := $(OBJ:.o=.d)
CPPFLAGS := -MMD
CFLAGS := -W -Wall -g -std=c99 -pedantic
LDLIBS := -lm
all: $(OBJS)
$(APP): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean:
$(RM) $(APP) $(OBJ) $(DEP)
-include $(DEP)
Last point: the syntax $(SRC:.c=.o) is a shortcut for $(SRC:%.c=%.o) which is also a shortcut for $(patsubst %.c,%.o,$(SRC)).
I have 4 files: 1.c, 1.h, 2.c, 2.h.
I need a makefile, which will create a dynamic library (.so) from those 4 files.
I have tried to write a makefile like this:
library.so : 1.c 1.h 2.c 2.h
but it did not work. It would be great, if someone helps me, thanks.
Something like
CC=gcc
CFLAGS= -Wall -g -O -fPIC
RM= rm -f
.PHONY: all clean
all: library.so
clean:
$(RM) *.o *.so
library.so: 1.o 2.o
$(LINK.c) -shared $^ -o $#
1.o: 1.c 1.h 2.h
2.o: 2.c 1.h 2.h
But this is untested! I am assuming Linux with GNU make, and a directory containing only the source code of your library (with the above Makefile), which might be bad practice -you might want a test case- (you could have a special Makefile rule for %.pic.o depending on %.c, etc...)
Hints: use make -p to understand the builtin rules. Then make --trace or (with remake) remake -x to understand a bit more what make is doing.
Read also Drepper's paper: How to Write Shared Libraries, documentation of GNU make, Program Library HowTo, this answer, ...
The simplest way is:
CXXFLAGS += -fPIC
CXXFLAGS += -O3
x.so: 1.o 2.o
$(LINK.cc) -shared $^ $(LOADLIBS) $(LDLIBS) -o $#
Slightly more advanced:
CC = gcc
FLAGS = # -std=gnu99 -Iinclude
CFLAGS = -fPIC -g #-pedantic -Wall -Wextra -ggdb3
LDFLAGS = -shared
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
TARGET = example.so
SOURCES = $(wildcard *.c)
HEADERS = $(wildcard *.h)
OBJECTS = $(SOURCES:.c=.o)
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(FLAGS) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(OBJECTS)
CC = gcc # C compiler
CFLAGS = -fPIC -Wall -Wextra -g # C flags
LDFLAGS = -shared # linking flags
RM = rm -f # rm command
TARGET_LIB = sh_main.so # target lib
SRCS = add.c sub.c main.c # source file
DEPS = header.h # header file
OBJS = $(SRCS:.c=.o) # object file
.PHONY: all
all: ${TARGET_LIB}
$(TARGET_LIB): $(OBJS)
$(CC) ${LDFLAGS} -o $# $^ # -o $# says, put the output of the compilation in the file named on the left side of the :
$(SRCS:.c=.d):%.d:%.c
$(CC) $(CFLAGS) -MM $< >$# # the $< is the first item in the dependencies list, and the CFLAGS macro is defined as above
include $(SRCS:.c=.d)
.PHONY: clean
clean:
-${RM} ${TARGET_LIB} ${OBJS} $(SRCS:.c=.d)
After the shared library created successfully. We need to install it.
Become the root user.
Copy the shared library into standard directory "/usr/lib".
Run ldcofig command.
Recompile your .c file with shared library.
root#Admin:~/C/SharedLibrary# gcc -c main.c
root#Admin:~/C/SharedLibrary# gcc -o main main.o sh_main.so
root#Admin:~/C/SharedLibrary# ldd main
Note: In my case.
main.c: main C file
sh_main.so: shared library.
I'm no gnu make expert, this seems reasonable to me
CFLAGS+=-fPIC
%.so: ; $(LINK.c) $(LDFLAGS) -shared $^ -o $#
library.so: 1.o 2.o # default target first
# changes to `1.h` imply `1.o` needs to be rebuilt
1.o: 1.h
2.o: 2.h
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 *~
all: run
run: test.o list.o matrix.o smatrix.o
gcc test.o list.o matrix.o smatrix.o -o matrix-mul
list.o: list.c list.h
gcc -g -c list.c
matrix.o: matrix.c matrix.h
gcc -g -std=c99 -c -o matrix.o matrix.c
smatrix.o: smatrix.c smatrix.h
gcc -g -c -o smatrix.o smatrix.c
test.o: test.c test.h
gcc -g -c test.c
I was having lots of problems to make a makefile and I finally got this working. And I just want to make sure these are ok (not just for making program running but in term of a good make file)
One question is that why do matrix.o and smatrix.o have .o files in the line gcc -g -c ... where as list.o and test.o don't have that line..
I had to add -std=c99 because I was getting some weird for loop error but still don't understand why I need to put matrix.o in the line..
The file is OK-ish. It is not very easily maintainable.
This website has a really good tutorial on how to make nice makefiles:
http://mrbook.org/blog/tutorials/make/
Especially look at the last example:
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
This should show you how to enhance maintainability (add extra files to SOURCES, and the rest is done automatically.
The below file supports make all make depend and make clean - you only need to change the first lines. Remember to make depend if you change includes in any file.
TARGET:=matrix-mul
SOURCES:=test.c list.c matrix.c smatrix.c
OBJECTS:=$(SOURCES:%.c=%.o)
CC=gcc
CFLAGS=-g -std=c99 -Wall
LD=gcc
LDFLAGS=
# First target - simply say that we want to produce matrix-mul
all: $(TARGET)
# To create the target we need all .o files, and we link with LD/LDFLAGS
# $# is the file we're making, aka matrix-mul
$(TARGET): $(OBJECTS)
$(LD) -o $# $(OBJECTS) $(LDFLAGS)
#Creating a .o from a .c
# $< is the c file, $# is the corresponding .o file
.c.o:
$(CC) $(CFLAGS) -c $< -o $#
# Regenerate dependencies
depend:
$(CC) $(CFLAGS) -MM $(SOURCES) > .depend
# Remove produced files
clean:
rm -rf $(OBJECTS) $(TARGET) .depend
# If there's no dependency file, create it
.depend: depend
# Include the autogenerated dependency file
include .depend
EDIT: If you want this even more generic, you can replace the SOURCE:= line with:
SOURCES:=$(wildcard *.c)
This makefile will then simply build TARGET from all .c files in the current directory.
One thing I would highly suggest here would be to add a clean target that deletes all your intermediate files (probably all the .o files), like so:
clean:
rm *.o
For extra credit, put all your *.o files in a make variable, and use that variable as the target of the run rule, and after the rm command above.
The reason I want you to do this is for debugging purposes. It could be that you have one of the above rules wrong, but since you already built all your .o files once, it is just picking up an old one every time. If you do a make clean before your build, it will catch that.