How can i make a Makefile for a GMP project - c

I have a problem while attempting to generate a Makefile for my C project. It contains 3 files alea.c crypto.c and main.c. Here is my Makefile :
SHELL = /bin/bash
CC = gcc
RM = rm -rf
TAR = tar
MKDIR = mkdir
CHMOD = chmod
CP = cp
MV = mv
PROGNAME = Crypto_ivsk
EXEC = Crypt
PACKAGE = $(PROGNAME)
VERSION = 0.3
DISTDIR = $(PACKAGE)-$(VERSION)
HEADERS = alea.h crypto.h gmp.h
SOURCES = alea.c crypto.c main.c
LDFLAGS = -lgmp
CFLAGS = -Wall
OBJ = $(SOURCES:.c=.o)
DISTFILES = $(SOURCES) Makefile $(HEADERS)
all: $(EXEC)
$(EXEC): $(OBJ)
$(CC) $(OBJ) -o $(LDFLAGS) $(EXEC)
%.o:%.c $(HEADERS)
$(CC) -c $< $(CFLAGS)
dist: distdir
$(CHMOD) -R a+r $(DISTDIR)
$(TAR) zcvf $(DISTDIR).tar.gz $(DISTDIR)
$(RM) $(DISTDIR)
distdir: $(DISTFILES)
$(RM) $(DISTDIR)
$(MKDIR) $(DISTDIR)
$(CHMOD) 777 $(DISTDIR)
$(CP) -rf $(DISTFILES) $(DISTDIR)
clean:
$(RM) $(PROGNAME) $(OBJ) *~ $(DISTDIR).tar.gz
but when i type "make" in my shell the following error appears :
"no rule to make target gmp.h needed by alea.o STOP"
I can't do anything about this with my low level, can someone please help me ?
Thank you :)

You have said that all your %.o files depend of the file of same name with extension .c and from the header files they include.
You have put gmp.h as an include in this directory that make does not find (I imagine you refer to the GNU Multiprecision library include file) which is a file you should not put in your $(HEADER) variable. Why?
Very simple, because you are never going to change that file, so the files dependent of it have to be recompiled, as it is a system file.
There are some recommendations I'm givin to you to avoid problems in the future.
Don't define variables you are not going to use, or variables you don't plan to change. Variables work in make as constants. You define them in a single place, but you repeat them here and there on your Makefile. These are the candidates to use.
make has a bunch of already defined rules (indeed, the rule to build an object .o file from a .c file is already included in almost any of the make implementations actually in use. So you have better to respect the already installed rule, than provide you yours, because this rule is normally adapted to your system, and the Makefile contents is more portable.
The same applies to variables that represent system programs, like CC, RM, LEX, YACC, etc. Normally, one redefines it when the program has special compilation needs (which is not your case)
You have an error in the final link phase of your makefile as you specify options -o $(LDFLAGS) $(EXEC) to the linker, while it should be $(LDFLAGS) -o $(EXEC) (better if you put $(LDFLAGS) first, as the linking options will be applied once all object files have been processed)
With this premises, this is the suggested Makefile for your project.
PACKAGE = Crypto_ivsk
VERSION = 0.3
DISTNAME = $(PACKAGE)-$(VERSION)
# don_t include system headers, because 1) you are never to
# modify them and 2) because they are in a different
# directory and make will not find them, and then it will
# try to create them in the local dir, if you put any in a
# dependency rule.
headers = alea.h cripto.h main.h
# This variable is understood by the C source compilation rule.
CFLAGS = -Wall
# targets holds the list of programs we are to build.
targets = Crypt
# toclean is a variable we initialize to the programs we are
# to build and for each program we add all the objects we
# compile of it.
toclean = $(targets)
# put here programs that must be built before linking Crypt,
# e.g. program resource files, that are not used in the linking. In this case we have none.
Crypt_deps =
# Put here things that must be built before linking Crypt,
# e.g. object files, that ***are*** used to link it.
Crypt_objs = alea.o cripto.o main.o
# Place for the libraries to build Crypt.
Crypt_libs = -lgmp
# For each program we add to toclean the object files that
# compose it, so we can erase just doing $(RM) $(toclean)
# Pay special attention to the += operator.
toclean += $(Crypt_objs)
# If we have more programs to build, add (prefixed) groups
# of variables like the above.
DISTFILES = $(Cryp_objs:.o=.c) Makefile $(headers)
# all should be a .PHONY target.
.PHONY: all clean dist
all: $(targets)
#echo Build finished at: `date`
# repeat this for each file in $(targets)
# $# is the target of the rule
Crypt: $(Crypt_deps) $(Crypt_objs)
$(CC) $(LDFLAGS) $(Crypt_ldfl) -o $# $(Crypt_objs) $(Crypt_libs)
dist: $(DISTNAME).tar.gz
# we link the files in $(DISTFILES) so we don_t consume
# disk space with the copies.
$(DISTNAME).tar.gz: $(DISTFILES)
mkdir $(DISTNAME)
ln $(DISTFILES) $(DISTNAME)/.
tar cvfz $# $(DISTNAME)
$(RM) $(DISTNAME)
# this cleans everything built.
clean:
$(RM) $(toclean)
# this can be written as
# alea.o cripto.o main.o: $(headers)
# but in case they include different lists of header is
# better to put it this way.
alea.o: $(headers)
cripto.o: $(headers)
main.o: $(headers)
This Makefile schema will give you better results, and it is easily extensible to build several programs or libraries.
As you see, there's no compilation rule for the sources to object files. This is because there's a builtin rule in make. There's also a default definition for RM (in GNU make) and for CC.
It's important that you don't redefine CC to gcc, as your code will be more portable if you don't force everybody to build your program with gcc.
In any case, if you use optional assignments,
CFLAGS ?= -O -Wall -std=c98 -pedantic
instead, then you'll allow the builder to specify a different value for CFLAGS in the command line (or through the environment) and your script will be more flexible.

Related

filter-out is not filtering file? Makefile for C

so ive got a make file here and my project currently has a master.c and slave.c which both have main functions. therefore i just want to filter the slave.c file out of the building process. so I used fliter-out when defining the source files. but when run make the project keeps turning up with the "multiple definitions of main" error. why is this when filter-out should be hiding the slave.c file?
########################################################################
####################### Makefile Template ##############################
########################################################################
#Compiler settings - Can be customized.
CC = gcc
CXXFLAGS = -std=c11 -Wall
LDFLAGS =
# Makefile settings - Can be customized.
APPNAME = master
SUBAPPNAME = slave
EXT = .c
SRCDIR = .
OBJDIR = .
############## Do not change anything from here downwards! #############
SRC := $(filter-out slave.c, $(wildcard $(SRCDIR)/*$(EXT)))
OBJ := $(SRC:$(SRCDIR)/%$(EXT)=$(OBJDIR)/%.o)
DEP := $(OBJ:$(OBJDIR)/%.o=%.d)
#UNIX-based OS variables & settings
RM = rm
DELOBJ = $(OBJ)
# Windows OS variables & settings
DEL = del
EXE = .exe
WDELOBJ = $(SRC:$(SRCDIR)/%$(EXT)=$(OBJDIR)\\%.o)
########################################################################
####################### Targets beginning here #########################
########################################################################
all: $(APPNAME)
# Builds the app
$(APPNAME): $(OBJ)
$(CC) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
# Creates the dependecy rules
%.d: $(SRCDIR)/%$(EXT)
#$(CPP) $(CFLAGS) $< -MM -MT $(#:%.d=$(OBJDIR)/%.o) >$#
# Includes all .h files
-include $(DEP)
# Building rule for .o files and its .c/.cpp in combination with all .h
$(OBJDIR)/%.o: $(SRCDIR)/%$(EXT)
$(CC) $(CXXFLAGS) -o $# -c $<
################### Cleaning rules for Unix-based OS ###################
# Cleans complete project
.PHONY: clean
clean:
$(RM) $(DELOBJ) $(DEP) $(APPNAME)
# Cleans only all files with the extension .d
.PHONY: cleandep
cleandep:
$(RM) $(DEP)
# Clean only all files with the extension .o
.PHONY: cleanobj
cleanobj:
$(RM) $(DELOBJ)
# Cleans both files with .d and .o extensions
.PHONY: cleanod
cleanod:
$(RM) $(DELOBJ) $(DEP)
The call
SRC := $(filter-out slave.c, $(wildcard $(SRCDIR)/*$(EXT)))
is just a string operation, that is, make is unaware of the underlying file tree and tries to throw out the string slave.c from the liste yoursrcdir/slave.c yoursrcdir/master.c which obviously fails. Although you may disagree at first, this is a good thing because the semantic of filter operations on filetrees is by no means universal or easy to document or transport. Therefore make just looks at the presented strings and decides on the character-for-character comparison which to take and which to drop.
That said, the rewrite to
SRC := $(filter-out $(SRCDIR)/slave.c, $(wildcard $(SRCDIR)/*$(EXT)))
will do the trick in your case.
For wider reaching functionality look up the two functions abspath and realpath to get file names in a canonical format, which prevent filter et.al. from stumbling on differences in OS nomenclature.

About generating makefile prerequisites automatically

I'm working on Stanford CS107 assignment 3, in which we implement a C version "vector". In the end I have some files in my directory,
.
├── Makefile
├── bool.h
├── vector.c
├── vector.h
└── vectortest.c
My question is about the handout Makefile, which looks like that,
CC = gcc
CFLAGS = -g -Wall -std=gnu11 -Wpointer-arith
LDFLAGS =
VECTOR_SRCS = vector.c
VECTOR_HDRS = $(VECTOR_SRCS:.c=.h)
VECTOR_TEST_SRCS = vectortest.c $(VECTOR_SRCS)
VECTOR_TEST_OBJS = $(VECTOR_TEST_SRCS:.c=.o)
SRCS = $(VECTOR_SRCS) vectortest.c
HDRS = $(VECTOR_HDRS)
EXECUTABLES = vector-test
default: $(EXECUTABLES)
vector-test: Makefile.dependencies $(VECTOR_TEST_OBJS)
$(CC) $(CFLAGS) -o $# $(VECTOR_TEST_OBJS) $(LDFLAGS)
# The dependencies below make use of make's default rules,
# under which a .o automatically depends on its .c and
# the action taken uses the $(CC) and $(CFLAGS) variables.
# These lines describe a few extra dependencies involved.
Makefile.dependencies:: $(SRCS) $(HDRS)
$(CC) $(CFLAGS) -MM $(SRCS) > Makefile.dependencies
-include Makefile.dependencies
.PHONY: clean
clean:
-rm -fr $(EXECUTABLES) *.o core Makefile.dependencies
When I run make vector-test, a file Makefile.dependencies was generated, in which lies some "default rules" of make,
vector.o: vector.c vector.h bool.h
vectortest.o: vectortest.c vector.h bool.h
My question is: professor keep the result of preprocess in another file is just to show us what the "default rules" is, or it's for some efficiency reason? For example GNU-GCC-3.22 Using Precompiled Headers can save times by preventing compile from processing header files over and over again? Because normally we don't have to list all .h files, and simply do gcc -c vector.c, or leave everything to the implicit rules. Am I right?
Another question is why he use :: instead of : here? I didn't find some useful information online talking about that. Thanks guys!
professor keep the result of preprocess in another file
Not true. According to your makefile, preprocessing result is not stored in any files. Preprocessing is a result of running preprocessor on your source files, i.e. it will substitute the contents of header files in place of #include directives and evaluate and substitute macros.
Instead, in your makefile, a header dependency rules are generated and stored in Makefile.dependencies. The -MM key of gcc generates header dependency rules, so that in case you edit one of the header files on which your source files depend, those source files will be recompiled next time you invoke make.
In your makefile you then include the generated dependency rules with -include Makefile.dependencies, so that make picks up header dependency rules generated by previous make invocation.
The contents of Makefile.dependencies, as you have noticed, are a valid makefile syntax.
See https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html for more info.
So, this is kind of efficiency reasons, so that you can avoid rebuilding all, by cleaning first in case some of the header files are edited. But also, it is a convenience reason, that you don't have to worry about remembering to clean and rebuild all in case you have edited some of the header files. The make utility will rebuild only affected source files.
Precomiled headers is not related to that.
Thanks #igagis and #MadScientist for following great references:
Mad-Scientist.net - Auto-Dependency Generation
GNU - Generating Prerequisites Automatically
GNU - How Makefiles Are Remade
The follow content is just a simple conclusion of Mad-Scientist.net - Auto-Dependency Generation, for more information please check the original link.
In short, there are two conventional practices to generate prerequisites automatically,
Old-school way is to use gcc -MM to create a single dependencies file.
vector.o: vector.c vector.h bool.h
vectortest.o: vectortest.c vector.h bool.h
The code snippet looks like,
depend:: $(SRCS) $(HDRS)
$(CC) $(CFLAGS) -MM $(SRCS) $(LDFLAGS) > $(DEP_FILE)
-include $(DEP_FILE)
This practice has two main problems:
You have to explicitly run make depend to keep dependencies file up to date.
It is inefficient to rebuild all dependencies if any tiny change is made in source code, especially when you have a large scale project to manage.
A second modern way solves above problems by separating each dependency rule into one .d file.
In vector.d:
vector.o vector.d: vector.c vector.h bool.h
In vectortest.d
vectortest.o vectortest.d: vectortest.c vector.h bool.h
The point here is that when make read the above rule in .d file, before it does anything, it will try to rebuild included .d file automatically, and that makes the difference. People don't have to explicitly run make depend.
The following snippet is not the final version but to give you a little taste about what the code looks like. There are some little tricks hiding behind, check the references above for complete solution.
%.d: %.c
#set -e; rm -f $#; \
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
-include $(wildcard $(SRCS:.c=.d))
Currently I feel comfortable with the first practice, because it's quite simple and good enough for most of my personal use case. And here is the complete Makefile for this assignment.
# 1. C11 is the newest version of C language
# 2. -Wpointer-arith request a warning when addtion and subtraction are done
# on pointers to void and to functions, which is supported in GNU C.
CC = gcc
CFLAGS = -g -Wall -std=gnu11 -Wpointer-arith
LDFLAGS =
VECTOR_SRCS = vector.c
VECTOR_HDRS = $(VECTOR_SRCS:.c=.h)
VECTOR_OBJS = $(VECTOR_SRCS:.c=.o)
VECTOR_TEST_SRCS = vectortest.c $(VECTOR_SRCS)
VECTOR_TEST_OBJS = $(VECTOR_TEST_SRCS:.c=.o)
SRCS = $(VECTOR_SRCS) vectortest.c
HDRS = $(VECTOR_HDRS)
OBJS = $(SRCS:.c=.o)
EXES = vectortest
DEP_DIR = ./deps
DEP_FILE = $(DEP_DIR)/Makefile.dependencies
.PHONY: default depend clean
default: $(EXES)
# 1. The dependencies below make use of make's default rules,
# under which a .o automatically depends on its .c and
# the action taken uses the $(CC) and $(CFLAGS) variables.
# These lines describe a few extra dependencies involved.
#
# 2. -MMD means write a dependencies file containing user headers.
# -MM likes -MMD, but also implies -E only do preprocess,
# and write to stand out by default.
depend:: $(SRCS) $(HDRS)
$(CC) $(CFLAGS) -MM $(SRCS) $(LDFLAGS) > $(DEP_FILE)
-include $(DEP_FILE)
vectortest: $(VECTOR_TEST_OBJS) depend
$(CC) $(CFLAGS) -o $# $(VECTOR_TEST_OBJS) $(LDFLAGS)
clean:
-rm -f *.o $(EXES) $(DEP_FILE)

How to generate dependency files when generating object files of c sources with make

I am implementing a build system using the GNU tools, GCC and make to compile multiple targets, link them together and create a final executable. All these support two platforms; the host environment and the embedded system MSP432.
I am taking an introductory course on embedded systems and doing an assignment that I am fighting with some days ago. I was trying by myself reading over the internet, also reading here in stackoverflow but I don’t get it yet, I am still a rookie on this, so I hope someone can explain me or giving me a hint about how to fix the issue
As said, the build system must support the two platforms so at first step, I focus on making sure all works for the host environment.
In the makefile I have created rules for the following targets:
build - Generates executable file, object files, dependency files and map file
%.o: %.c ... - Generates object files and its dependencies
compile-all - Compiles all objects but do not link them
%.i: %.c - Generates preprocessed output of C source files
%.asm: %.C - Generates assembly output of C source files
clean - Clean all generated files
The issue is when executing make build PLATFORM=HOST
Running the command, we get:
.../src$ sudo make build PLATFORM=HOST
gcc -Wall -Werror -g -std=c99 -DHOST -Wl,-O0,-Map=c1m2.map main.c memory.c -I../includes/common -o c1m2.out
make: *** No rule to make target 'main.o', needed by 'build'. Stop.
I notice that the error comes because the line 132 were we have
%.o: %.c
This line is intended for disabling the built-in rule and using the user defined one that comes next line, but it is not doing it, so I try commenting this line and executing the build again and we get:
.../src$ sudo make build PLATFORM=HOST
gcc -Wall -Werror -g -std=c99 -DHOST -Wl,-O0,-Map=c1m2.map main.c memory.c -I../includes/common -o c1m2.out
gcc -Wall -Werror -g -std=c99 -DHOST -E -c -o main.o main.c
main.c:23:22: fatal error: platform.h: No such file or directory
compilation terminated.
< builtin >: recipe for target 'main.o' failed
make: *** [main.o] Error 1
Now it says that it does not find “platform.h” despite it being indicated by the INCLUDES variable that contains the location of the header file. Also, it is using the built-in recipe for generating the object files and fails.
So I am stuck at this point, the idea is building the output executable, the map file, the object files and its dependencies files when executing “make build PLATFORM=HOST”.
At the beginning I wrote the build target just for generating the output, the map and object files and did work and then after doing the modifications for generating the dependency files I got lost with this error.
The other recipes for generating preproceessed files, assembly files and doing a clean were working ok.
You can clone the folder with all the needed files from: https://github.com/Fornaso/C1M2.git
Thank you all in advance.
Here is my Makefile:
#******************************************************************************
# Copyright (C) 2017 by Alex Fosdick - University of Colorado
#
# Redistribution, modification or use of this software in source or binary
# forms is permitted as long as the files maintain this copyright. Users are
# permitted to modify this and use it to learn about the field of embedded
# software. Alex Fosdick and the University of Colorado are not liable for any
# misuse of this material.
#
#******************************************************************************
# Modified on April 2020 by Adrián Fornaso
#------------------------------------------------------------------------------
# Simple Makefile for multitarget build system
#
# Use: make [TARGET] [PLATFORM-OVERRIDES]
#
# Build Targets:
#
# build - Builds and links all source files and genereates:
#
# c1m2.map - Map file for the full build
# *.d - Dependency Files for each source file
# *.o - Individual object files
# c1m2.out - Output Executable file
#
#<FILE>.i - Builds <FILE>.i preprocessed file.
#<FILE>.asm - Builds <FILE>.i assembly file.
#<FILE>.o - Builds <FILE>.o object file.
#compile-all - Compile all objects but do NOT link them.
#clean - Removes all generated files.
#
# Platform Overrides: Conditionally assign the appropriate compiler flags,
# linker flags, and architecture flags. The target platform
# must be provided at the command line with the make
# command to set the platform you are compiling for.
#
# PLATFORM = MSP432 - The target embedded system will use
# the cross compiler, arm-none-eabi-gcc.
# PLATFORM = HOST - The host embedded system will use the
# native compiler, gcc.
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
#General Flags (Both Platforms)
#
# -Wall Enable All Warning Messages (CFLAGS)
# -Werror Treats All Warnings as Errors(CFLAGS)
# -g Generate Debugging Info in Executable (CFLAGS)
# -O0 The level of optimization (-O0, -O1, -O2, -O3)) (LDFLAGS)
# -std=c99 The C standard set (CFLAGS)
#
#------------------------------------------------------------------------------
#Target name
BASENAME = c1m2
TARGET = $(BASENAME).out
#General Flags
COMMONCFLAGS = -Wall -Werror -g -std=c99
COMMONLDFLAGS = -Wl,-O0,-Map=$(BASENAME).map
#No spaces after commas after -Wl option.
CPPFLAGS = -E
# -E flag makes the compiler stop in the preprocessed output
#Compile time switches
ifeq ($(PLATFORM), MSP432)
INCLUDES = -I../includes/common \
-I../includes/msp432 \
-I../includes/CMSIS
SOURCES = main.c \
memory.c \
interrupts_msp432p401r_gcc.c \
startup_msp432p401r_gcc.c \
system_msp432p401r.c
LINKER_FILE = msp432p401r.lds
CPU = cortex-m4
ARCH = armv7e-m
SPECS = nosys.specs
CC = arm-none-eabi-gcc
LD = arm-none-eabi-ld
LDFLAGS = $(COMMONLDFLAGS), -T=$(LINKER_FILE)
CFLAGS = $(COMMONCFLAGS) -D$(PLATFORM) -mcpu=$(CPU) \
-march=$(ARCH) --specs=$(SPECS)
OBJDUMP = arm-none-eabi-objdump
endif
ifeq ($(PLATFORM), HOST)
INCLUDES = -I../includes/common
SOURCES = main.c \
memory.c
CC = gcc
LD = ld
LDFLAGS = $(COMMONLDFLAGS)
CFLAGS = $(COMMONCFLAGS) -D$(PLATFORM)
OBJDUMP = objdump
endif
#Listing object files:
OBJECTS = $(SOURCES:.c=.o)
# 1. --------------------------------------------------------------------------
# Complete build: c1m2.map - Map file for the full build
# *.d - Dependency Files for each source file
# *.o - Individual object files
# c1m2.out - Output Executable file
# LDFLAGS contains the flags for creating the *.map file
.PHONY: build
build: $(TARGET) $(OBJECTS)
$(TARGET):
$(CC) $(CFLAGS) $(LDFLAGS) $(SOURCES) $(INCLUDES) -o $#
# 2. --------------------------------------------------------------------------
# //// Generates the object files of all c-program implementation files and its
# dependecies. ///////////////////////////////////////////////////////////
#This implementation places dependency files into a subdirectory named .deps.
DEPDIR := .deps
DEPFLAGS = -MT $# -MD -MP -MF $(DEPDIR)/$*.d
# Delete the built-in rules for building object files from .c files, so that
# our rule is used instead.
#%.o: %.c
# Our rule for building object files with its dependency
%.o: %.c $(DEPDIR)/%.d | $(DEPDIR)
$(CC) $(DEPFLAGS) -c $(CFLAGS) $(INCLUDES) -o $# $^
# Declare a rule for creating the dependency directory if it doesn’t exist.
$(DEPDIR): ; #mkdir -p $#
# Generate a list of all the dependency files that could exist.
DEPFILES := $(SRCS:%.c=$(DEPDIR)/%.d)
# Mention each dependency file as a target, so that make won’t fail if the file
# doesn’t exist.
$(DEPFILES):
# 2 bis. ----------------------------------------------------------------------
# /// Generates the object file of all c-program implementation files. ////////
#%.o: %.c
# $(CC) -c $(CFLAGS) $(INCLUDES) -o $# $^
# 3. --------------------------------------------------------------------------
# /// Compile all objects but do NOT link them. ///////////////////////////////
.PHONY: compile-all
compile-all: $(SOURCES)
$(CC) -c $(CFLAGS) $(INCLUDES) $^
# 4. --------------------------------------------------------------------------
# /// Generates the preprocessed output of all c-program implementation files.
%.i: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDES) -o $# $^
# 5. --------------------------------------------------------------------------
# /// Create assembler file of a C source. ////////////////////////////////////
%.asm: %.c
$(CC) -S $(CFLAGS) $(INCLUDES) $< -o $#
# -S flag tells the compiler just generate the assembly file
# 6. --------------------------------------------------------------------------
# /// Removes all compiled objects, preprocessed outputs, assembly outputs,
# executable files and build output files. ////////////////////////////////
.PHONY: clean
clean:
rm -f $(OBJECTS) $(TARGET) $(BASENAME).map *.asm *.i
rm -r .dep
#End of file
There are two small mistakes which took me quite a while to see:
DEPFILES := $(SRCS:%.c=$(DEPDIR)/%.d) has to be DEPFILES := $(SOURCES:%.c=$(DEPDIR)/%.d) - otherwise DEPFILES is empty since SRCS is undefined.
In $(CC) $(DEPFLAGS) -c $(CFLAGS) $(INCLUDES) -o $# $^ the $^ (all the prerequisites) expands to e. g. main.c .deps/main.d, so a not yet existing .deps/main.d is passed as an input file; we want $*.c instead of $^.
Another minor error is:
rm -r .dep should be rm -r .deps or rm -r $(DEPDIR).

How do I tell Make to ignore files which haven't been updated?

I am new to using Make and I am having some trouble figuring out the syntax. I went through a few examples and I essentially combined a few of them to create my own file. I am not sure how to tell make to ignore already compiled source or header files that haven't changed. How can I get make to compile only the files that have changed?
I looked on the GNU website: https://www.gnu.org/software/make/manual/html_node/Avoiding-Compilation.html
I tried some of those flags, but I still am not getting the results I wanted.
# specify compiler
CC=gcc
# set compiler flags
CFLAGS=-Igen/display -Igen/logic -Iman -Ilib/include -pipe -march=native
# set linker flags
LDFLAGS=-lglut32 -loglx -lopengl32 -Llib
# include all sources
SOURCES=gen/display/*.c gen/logic/*.c man/*.c
# create objects from the source files
OBJECTS=$(SOURCES:.cpp=.o)
# specify the name and the output directory of executable
EXECUTABLE=win32/demo
all: $(SOURCES) $(EXECUTABLE)
# compile the target file from sources
# $# = placeholder for target name
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) $(LDFLAGS) -o $#
.c.o:
$(CC) $(CFLAGS) $< -o $#
I have a number of header and source files in different directories that are being compiled, but no matter what I do everything recompiles.
Okay, let's do it, as it ought to be done ;-)
# set up our variables
# note: you may also prefer := or ?= assignments,
# however it's not that important here
CC=gcc
CFLAGS=-Igen/display -Igen/logic -Iman -Ilib/include -pipe -march=native
# linker's flags are different from compiler's
LDFLAGS=
# these are really libs, not flags
LDLIBS=-Llib -lglut32 -loglx -lopengl32
# 1) make is not your shell - it does not expand wildcards by default
# 2) use := to force immediate wildcard expansion;
# otherwise make could perform it several times,
# which is, at the least, very ineffective
SOURCES:=$(wildcard gen/display/*.c gen/logic/*.c man/*.c)
# use the right extensions here: .c -> .o
OBJECTS=$(SOURCES:.c=.o)
# note: it's okay to omit .exe extension if you're using "POSIX"-like make
# (e.g. cygwin/make or msys/make). However, if your make was built on Windows
# natively (such as mingw32-make), you'd better to add '.exe' here
EXECUTABLE=win32/demo
# don't forget to say to make that 'all' is not a real file
.PHONY: all
# *.c files are what you write, not make
# note: in fact, you don't need 'all' target at all;
# this is rather a common convention
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
# note: 1) suffix rules are deprecated; use pattern rules instead
# 2) this doesn't add much to the built-in rule, so you can even omit it
# 3) .o files are created in the same directories where .c files reside;
# most of the time this is not the best solution, although it's not
# a mistake per se
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#

how to manage c files dependencies in make

i'm starting with make and i was searching how to automaticly generate dependencies for my c files, i found this piece of code :
# pull in dependency info for *existing* .o files
-include $(OBJS:.o=.d)
# compile and generate dependency info
%.o: %.c
gcc -c $(CFLAGS) $*.c -o $*.o
gcc -MM $(CFLAGS) $*.c > $*.d
what i don't understand is when i generate the dependencies file %.d, i already have built the %.o file, so what it the point to creating this dependencies file, and the -include i executed before everything so no dependencies file will exist.
-include means to include the dep file if it is there but not fail if it isn't.
The trick, and this is common in make dependency tracking, is that your dependencies are actually one build out of date. You're including, if they are there, the dependency files that were built the last time around.
This is not a problem because for dependencies to change, changes have to be made to something that the target depended on during the last build -- so even though make doesn't know the full new dependencies, it knows that it has to rebuild the target (and generate a new dependency file in the process).
Addendum: By the way, gcc and clang have a -MD option that can generate a dependency file while building the .o (by default with a .d suffix). This means that you can do automatic dependency tracking with implicit rules and cut down your Makefile to the bare minimum like so (for a simple project with .c files in a flat directory):
#!/usr/bin/make -f
# name of the binary to build
TARGET = target
CC = gcc
# These flags are used by the implicit rules for C preprocessor flags,
# C compiler flags, linker flags, and libraries to link (-lfoo options)
# -MD in CPPFLAGS means that the implicit rules for .o files will also
# generate a corresponding .d file that contains the dependencies.
# The values here are just examples (thank you, Rear Admiral Obvious!)
CPPFLAGS = -MD -I somewhere/include
CFLAGS = -O2 -g
LDFLAGS = -L somewhere/lib
LDLIBS = -lsomelibrary
# SRCS is a list of all .c files in the directory, the other two are
# pattern substitution expressions that take SRCS and replace the .c with .o
# and .d, respectively
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
DEPS = $(OBJS:.o=.d)
all: $(TARGET)
$(TARGET): $(OBJS)
# Look, Ma, no explicit rules for .o files!
clean:
rm -f $(TARGET) $(OBJS)
.PHONY: all clean
# include dep files (if available).
-include $(DEPS)
I usually add phony target depend, like this:
depend: $(SOURCES)
makedepend -Y. $(CFLAGS) $^ 2>/dev/null
and run make depend time to time to update depenencies.
See man makedepend for details.

Resources