Trouble creating a generic make file - c

Hey so I'm a little new to makefiles and I'm trying to make a generic makefile that will compile whatever files end with .c in the current directory, instead of specifically named files for a project. I've searched a few places, re-read my lecture notes, tried a few changes and I can't seem to get it working. Here's what I have:
CFLAGS= -Wall -g -o
%.o : %.c
gcc ${CFLAGS} .c $<
This is the error I keep getting when I try to run it:
make: *** No targets. Stop.
I would be grateful for any help really, I really despise typing in gcc over and over!
The file is named Makefile

a generic makefile that will compile whatever files end with .c in the current directory
This is an atypical use for make, but can be done using GNU make's text functions:
SOURCES = $(wildcard *.c)
OBJS = $(patsubst %.c,%.o,$(SOURCES))
all: $(OBJS)
If you have foo.c and bar.c in your directory, running make will produce foo.o and bar.o.
If you meant that you want the command make to compile and link each .c into an executable, try:
SOURCES = $(wildcard *.c)
EXECS = $(patsubst %.c,%,$(SOURCES))
all: $(EXECS)
What is more typical, is to want to compile and link a single program. In that case, you don't need any makefile whatsoever, just run these commands:
make foo
make bar

The wildcard function can be used to compile all C source files in the directory and then link them together.
CFLAGS= -Wall -g -o
SRC=$(wildcard *.c)
foo: $(SRC)
gcc -o $# $^ $(CFLAGS)

You have a couple of syntax errors, and your makefile builds the objects but doesn't link the objects into an executable.
myTest.c:
int main()
{
return 0;
}
makefile if your source file is "myTest.c":
CFLAGS= -Wall -g
all: myTest
myTest: myTest.o
gcc $(CFLAGS) $< -o $#
%.o : %.c
gcc $(CFLAGS) -c $<
Build with
make myTest
gcc -Wall -g -c myTest.c
gcc -Wall -g myTest.o -o myTest

Related

How to run a C program when it has multiple files?

In a program, I have a list.c file, list.h file and run.c file. In the run.c file, the code contains my main program and also "#include list.h". In my list.h file, my functions are just void and being defined. Finally, in my list.c file, I include list.h again and I have the meaning and code of what each function is going to do. I made a makefile that looks like so:
SOURCES = run.c list.c
OBJECTS= run.o list.o
HEADERS = list.h
CC = gcc
CFLAGS = -g -Wall
lab1: $(OBJECTS)
(tab) $(CC) $(CFLAGS) $(OBJECTS) -o lab1
clean:
(tab) rm -fR *o lab1
There is nothing wrong in any of my code because it is already finished and I am just copying code. However, I am unsure how to use the makefile to run these multiple files. I am only familiar with runner files after compiling with gcc and using "./". Is there something wrong with my makefile or is there a step for compiling these files in a different way?
Thank you for any help
The given makefile is working and generates an executable lab1 file. However, the .o files depend on the list.h file, and this dependency is not captured.
You should specify targets to build the .o files, as follows:
SOURCES = run.c list.c
OBJECTS= run.o list.o
HEADERS = list.h
CC = gcc
CFLAGS = -g -Wall
lab1: $(OBJECTS)
(tab) $(CC) $(CFLAGS) $(OBJECTS) -o lab1
%.o: %.c $(HEADERS)
$(CC) -c $(CFLAGS) $< -o $#
clean:
rm -fR *o lab1
Word of caution: With this makefile, if the list of HEADERS grows, a change in any of the headers will warrant a rebuild of all .o files.
For example, imagine we also have buf.c which uses buf.h. Now HEADERS = list.h buf.h. If we change buf.h, our makefile would rebuild both list.o and buf.o, even though a buf.o rebuild would suffice.
To remedy this, we could use a more verbose makefile which identifies the specific header prerequisites for each .o file with rules such as the following:
list.o: list.c list.h
$(CC) -c $(CFLAGS) $< -o $#
buf.o: buf.c buf.h
$(CC) -c $(CFLAGS) $< -o $#
Solution 1: Simply list each .c file separately as input and compile once
gcc list.c run.c -o lab1
Solution 2: Compile each .c file separately
gcc -c list.c
gcc -c run.c
gcc -o lab1 list.o run.o
Your project is small and simple enough that a fully generalized makefile is overkill:
SOURCES = run.c list.c
CC = gcc
CFLAGS = -g -Wall
all:
$(CC) $(CFLAGS) $(SOURCES) -o lab1
clean:
rm -fR *o lab1
The all: is a default target that executes when you simply type make with no arguments.
After compiling, it did end up making a lab1 file that I could run and everything worked. My makefile ended up working fine, I was just completely oblivious to the fact that it was making a file called lab1. I did change my makefile to the above options and that also worked. Thank you

GDB doesn't see source files other than main, caused by makefile?

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)

When I use "gcc" in makefile, after making it, I got a "cc" output

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 *~

Makefile for plugins compilation

I have this simple structure:
.
test.c
plugins/a.c
plugins/b.c
plugins/c.c
And I'm compiling this with a bash script:
gcc -o test test.c -std=gnu99 -ldl -Wl,--export-dynamic
gcc -c plugins/a.c -o plugins/a.o -pedantic -g -Wall -std=c99 -fpic -I.
gcc plugins/a.o -o plugins/a.so -shared
...same for b and c...
Anyways, I want to port that to a Makefile. Here's what I have:
CC = gcc
PLUGIN_DIR = plugins
PLUGINS_C = $(wildcard $(PLUGIN_DIR)/*.c)
PLUGINS_O = $(patsubst %.c,%.o, $(PLUGINS_C))
new: clean all
all: test plugins
test: test.o
$(CC) -o $# $^ -std=gnu99 -ldl -Wl,--export-dynamic
plugins:
???
$(PLUGIN_DIR)/*.c:
$(CC) -c $(PLUGIN_DIR)/$# $^ -pedantic -g -Wall -std=c99 -fpic -I.
$(PLUGIN_DIR)/*.o:
$(CC) $# $^ -shared
clean:
rm -rf test *.o *.a plugins/*.o plugins/*.so
But this won't work as the plugins rule is empty and I really can't find out what should I write in there to make it compile all the plugins inside the plugins folder.
Also, I'm not sure if I messed up things with $# and $^.
There are a number of problems with your makefile before we get to your question.
The wildcard character in a rule target is % not * (in lines like your $(PLUGIN_DIR)/*.c:).
Rules specify how the files named by the target/target pattern are built. So your %.c rule is telling make how to build .c files (which I trust you'll agree) isn't exactly what you meant. (Similarly your %.o rule is telling make how to build .o files).
You don't have any prerequisites (right-hand side of : in a target line) listed for your build rules so make cannot intelligently rebuild targets as their prerequisites are changed (and will never rebuild them instead).
To get to your question, you likely don't want anything in the body of the plugins target. Instead you want to list the desired plugins output files (the .so files) as the prerequisites of the plugins target. (You will also want to include .PHONY: plugins in your makefile to tell make that plugins is not a real file but instead a phony target.)
Your %.so rule wants to be more like:
$(PLUGINS_DIR)/%.so: $(PLUGINS_DIR)/%.o
$(CC) $^ -o $# -shared
and your %.o rule wants to be more like:
$(PLUGINS_DIR)/%.o: $(PLUGINS_DIR)/%.c
$(CC) -c $< -o $# -pedantic -g -Wall -std=c99 -fpic -I.

How can I write Makefile (with sub Makfile ) more concise

When I do practice , I have a practice path.
Under this path , I have an Include path named myInclude (I have some useful function is this folder and I always use it.)
And a code path named symbol_try.I always make add new folder (with a c file and main function in it) in symbol_try and compile it.
Each time I have to compile it by gcc in terminal .Its a boring work , so I write a Makefile.
Here is an example:
the main Makefile in practice path:
FOBJS=
include myInclude/Rule.mk
include symbol_try/codeList_13.1/Rule.mk
symbol:$(FOBJS) <==What exactly I what . A executable file.
gcc -o symbol $(FOBJS) -pthread -lpthread
subsystem:
cd myInclude/ && $(MAKE)
cd symbol_try/codeList_13.1/ &&$(MAKE)
clean:
rm -rf symbol
In the myInclude/Rule.mk
FOBJS+=myInclude/otherFunction.o myInclude/error.o \
myInclude/unit.o myInclude/unitTest.o\
In the symbol_try/codeList_13.1/Rule.mk
FOBJS+=symbol_try/codeList_13.1/codeList_13.1.o
In myInclude/Makefile:
OBJS=otherFunction.o error.o unit.o unitTest.o
ALL:$(OBJS)
.PHONY:ALL
$(OBJS):%.o:%.c
gcc -c $< -o $#
clean :
otherFunction.o error.o unit.o
In symbol_try/codeList_13.1/Makefile:
codeList_13.1.o:codeList_13.1.c
gcc -c codeList_13.1.c
Well.That can work. But as you see , I have to write a Rule.mk(to initialize the FOBJS) and a Makefile for each folder.
I am new for make , I want find a way more concise , witch I only need write one Makefile for each folder and a main Makefile.No Rule.mk any more.
PS: I always change the code in myInclude ,so I don't want to build it a library.
Thanks for any help.
Here's one way you can do it with just one Makefile:
CC = gcc
CPPFLAGS += -I myInclude/ (1)
CFLAGS += -std=c99 -Wall (2)
VPATH = myInclude/ \ (3)
symbol_try/codeList_13.1/
symbol: otherFunction.o error.o unit.o unitTest.o codeList_13.1.o (4)
$(CC) -o $# $^ (5)
.PHONY : clean
clean:
rm -f symbol *.o
Note that make knows how to build C files and has some standard macros: CC, CPPFLGAS, CFLAGS
Add the include paths of your headers. You presumably have some headers for the individual object files in the myInclude directory.
Put the compiler flags here.
Add the paths to the source files you want to build.
List the object files that the executable depends upon
As there is no file called symbol.c you need to tell make how to create symbol.o with a rule. $# means the target ('symbol', here), and $^ means all of the prerequisites (the object files listed).
Here's a list of all of the files in my test directories for this:
$ find . -type f
.
./Makefile
./myInclude/error.c
./myInclude/header.h
./myInclude/otherFunction.c
./myInclude/unit.c
./myInclude/unitTest.c
./symbol_try/codeList_13.1/codeList_13.1.c
And the build output:
$ make
gcc -std=c99 -Wall -I myInclude/ -c -o otherFunction.o myInclude/otherFunction.c
gcc -std=c99 -Wall -I myInclude/ -c -o error.o myInclude/error.c
gcc -std=c99 -Wall -I myInclude/ -c -o unit.o myInclude/unit.c
gcc -std=c99 -Wall -I myInclude/ -c -o unitTest.o myInclude/unitTest.c
gcc -std=c99 -Wall -I myInclude/ -c -o codeList_13.1.o symbol_try/codeList_13.1/codeList_13.1.c
gcc -o symbol otherFunction.o error.o unit.o unitTest.o codeList_13.1.o
Why don't you create a library from the objects in myInclude and do the linking in the Makefile in your code path (symbol_try/codeList_13.1). The latter is better anyway because the needed libraries (-pthread -lpthread in your case) might change as well for some other code.
The main Makefile now would have got nothing to do but call make in all needed subdirectories.
In each folder have a makefile with
SOURCES=sample.c sampletest.c
OBJECTS=$(SOURCES:%.c=$(OBJDIR)/%.o)
all: $(OBJECTS)
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -o $# $<
In the root directory of a project, create a makefile with a rule to compile every sub-folder like the below.
Dirs= path-to-rootdir
objs:
set -e ; \
for i in $(Dirs) ; do \
$(MAKE) CC="$(CC)" CFLAGS="$(CFLAGS_MODULE)" LDFLAGS="$(LDFLAGS)" OBJDIR="$(OBJDIR)" -C $$i; \
done
And then you could use it build the executable by adding a rule
EXE: objs
$(CC) -L./Path1 $(LIB_PATH) -llib1 -o $(EXE_NAME) $(wildcard $(OBJDIR)/*.o)
Hope this helps!!!

Resources