I have written a Makefile to generate a kernel image from both ASM and C sources however it fails to compile the C sources. I think the error is in using two object lists one for ASM and one for C. If there are other issues with the file please feel free to tell me.
Terminal Output
arm-none-eabi-as -I source/ source/maths.s -o build/maths.o
arm-none-eabi-as -I source/ source/tags.s -o build/tags.o
make: *** No rule to make target 'build/firstCFile.o', needed by 'build/output.elf'. Stop.
Makefile
# The toolchain to use. arm-none-eabi works, but there does exist
# arm-bcm2708-linux-gnueabi.
ARMGNU ?= arm-none-eabi
# The intermediate directory for compiled object files.
BUILD = build/
# The directory in which source files are stored.
SOURCE = source/
# The name of the output file to generate.
TARGET = bin/kernel.img
# The name of the assembler listing file to generate.
LIST = bin/kernel.list
# The name of the map file to generate.
MAP = bin/kernel.map
# The name of the linker script to use.
LINKER = kernel.ld
# The names of libraries to use.
LIBRARIES := csud
# The names of all object files that must be generated. Deduced from the
# assembly code files in source.
OBJECTS := $(patsubst $(SOURCE)%.s,$(BUILD)%.o,$(wildcard $(SOURCE)*.s))
OBJECTS2 := $(patsubst $(SOURCE)%.c,$(BUILD)%.o,$(wildcard $(SOURCE)*.c))
# Rule to make everything.
all: $(TARGET) $(LIST)
# Rule to remake everything. Does not include clean.
rebuild: all
# Rule to make the listing file.
$(LIST) : $(BUILD)output.elf
$(ARMGNU)-objdump -d $(BUILD)output.elf > $(LIST)
# Rule to make the image file.
$(TARGET) : $(BUILD)output.elf
$(ARMGNU)-objcopy $(BUILD)output.elf -O binary $(TARGET)
# Rule to make the elf file.
$(BUILD)output.elf : $(OBJECTS) $(OBJECTS2) $(LINKER)
$(ARMGNU)-ld --no-undefined $(OBJECTS) $(OBJECTS2) -L. $(patsubst %,-l %,$(LIBRARIES)) -Map $(MAP) -o $(BUILD)output.elf -T $(LINKER)
# Rule to make the object files.
$(BUILD)%.o: $(SOURCE)%.s
$(ARMGNU)-as -I $(SOURCE) $< -o $#
$(BUILD):
mkdir $#
I think you need a rule to make from the c source:
$(BUILD)%.o : $(SOURCE)%.c
$(ARMGNU)-gcc -c -I $(SOURCE) $< -o $#
Related
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.
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.
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).
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 $#
I'm at my wits end here because of this extremely stupid error I'm getting from my makefile.
I finally gave up stripped the makefile down to just two lines:
%.o: %.c
gcc -c -o $# $< -I../inc
Command: make . The output:
make: *** No targets. Stop.
The spaces at the beginning are real tabs instead of spaces. The c files are in the same directory. If instead of %.o I give, say, file1.o and file1.c instead of %.c, all is well (file1.o gets created). I see plenty of examples on the 'net that use the % operator, though. If I include a clean: target, it is promptly found, like so:
%.o: %.c
gcc -c -o $# $< -I../inc
clean:
echo "this is clean!"
Command: make . The output:
echo "this is clean!"
this is clean!
Please help me out here as I'm totally clueless about what's wrong with my targets. In the second sample (the one with clean target), I guess the clean target is found and acted upon as the first one is 'invalid' somehow.
Looks like you forgot to write a target. You have just written rules of how to compile, but not what to do with those objects. I mean, I miss something like:
my_executable_file: *.o
gcc -o my_executable_file *.o
EDIT:
What is set before is true, you need a target. But as you want only to compile, your target should be something like:
OBJECTS = file.o #and whatever objects you need, as a list separated by commas
And then your target:
my_objects: $(OBJECTS)
So putting it all together:
OBJECTS = file.o #and whatever objects you need, as a list separated by commas
my_objects: $(OBJECTS)
%.o: %.c
gcc -c -o $# $< -I../inc
Below is the Makefile that will enable to any number of targets to compile
OBJ := file.o
all: $(OBJ)
%.o: %.c
gcc -c -o $# $< -I../inc
clean:
echo "this is clean!"
Here, OBJ will be the list of the files that you want to compile , like here it is file.c
Add the file name you want to compile to OBJ, when make is called it will build the target all first which depends on the OBJ.
To build OBJ the gcc command is used.
When an explicit target is not given to make, then the first (non-pattern?) target in the Makefile is used. In the case above, it is the clean target.
I see your intention to make only .o files (can be needed for creation of libraries).
You can modify your Makefile to build only .o files or build only executable by using the same Makefile
For the below directory structure (using tree command)
# tree .
.
|-- include
| `-- head.h
|-- Makefile
|-- obj
`-- src
`-- main.c
Makefile
# GNU Makefile #
# Some Variables #
CC := gcc
RM := rm
MV := mv
# Phony Targets #
.PHONY: clean
.PHONY: move
# Path for Source, Object and Include #
SRC_PATH := ./src/
OBJ_PATH := ./obj/
INCLUDE_PATH := ./include/
# Source and Object File Names #
SRC := $(SRC_PATH)main.c
OBJ := $(SRC:c=o) # Substitutes all SRC but with .c as .o (main.c becomes main.o) #
# Executable Name #
TARGET := exe
# Building Binary - use 'make' #
binary: $(TARGET) move
$(TARGET): $(OBJ)
$(CC) -o $(TARGET) $^
# Building only Object Files - use 'make object_only' #
object_only : $(OBJ) move
$(OBJ): $(SRC)
$(CC) -c -o $# $< -I $(INCLUDE_PATH)
# This rule is for moving .o files to ./obj directory (More Organised) #
move:
$(MV) $(SRC_PATH)*.o $(OBJ_PATH)
# For Cleaning - use 'make clean' #
clean:
echo "Cleaning Up!"
$(RM) -rfv $(TARGET) $(OBJ_PATH)*.o $(SRC_PATH)*.o # Delete .o and executable #
Execution:
To build only object files use
$ make object_only
To build object files and executable, use
$ make