I have a project where I have my main file and two modules in their own files such that main.f95, mod1.f95, mod2.f95. Initially, I designed my Makefile to run in this fashion
# PROGRAM NAME
main = main
# MODULE NAME
mod1 = mod1
mod2 = mod2
########################################
cmplr = gfortran
flags = -g -Wall
objects1 = $(mod1).o $(mod2).o $(main).o
$(main) : $(objects1)
$(cmplr) $(flags) -o $(main) $(objects1)
$(mod1).o : $(mod1).f95
$(cmplr) -c $(mod1).f95
$(mod2).o : $(mod2).f95
$(cmplr) -c $(mod2).f95
$(main).o : $(main).f95 $(mod1).f95 $(mod2).f95
$(cmplr) -c $(main).f95
clean :
rm -f *.mod *.pcl *.pc *.o $(main) *.inc *.vo *.d *.out
This has worked for my initial design, but now my project's complexity is getting to the point where mod1 will be used in mod2 and the main file, so I need to relink the files.
I tried this change to the Makefile
$(mod2).o : $(mod2).f95 $(mod1).f95
$(cmplr) -c $(mod2).f95
I essentially followed how the main.o compilation structure is defined in the Makefile and followed that design since it seemed similar, but it doesn't seem to work for me trying to link mod1 into mod2. Any help or advice is appreciated!
As noted in the comments, the Makefile will compile if the order is switched such that
$(mod2).o : $(mod1).f95 $(mod2).f95
$(cmplr) -c $(mod2).f95
Related
I have created a Makefile for the below code structure
work
├── code
| |
| ├──inc/
| | └── main.h and test.h files here
| |
| ├──src/
│ └── main.c and test.c files here
├── _Build/
│ └── Makefile here
Here is the Makefile
# All path are referenced with the directory path of Makefile
# Directory Path for workspace
WORKSPACE = ..
# Directory path for code
PATH_DIR_CODE = $(WORKSPACE)/code
# Directory path for c source files
PATH_DIR_C_SOURCES = $(PATH_DIR_CODE)/src
# Directory path for c header files
DIR_PATH_C_HEADERS = $(PATH_DIR_CODE)/inc
# Directory path for obj files
DIR_PATH_OBJ = $(WORKSPACE)/obj
# Directory path for executables
DIR_PATH_BIN = $(WORKSPACE)/bin
# Executable name declaration
FILE_PATH_EXE = $(DIR_PATH_BIN)/main
# Command mkdir
MKDIR = mkdir
FILE_PATH_C_HEADER = $(shell find $(PATH_DIR_CODE) -name *.h)
DIR_PATH_C_HEADER = $(patsubst %/,%,$(sort $(dir $(FILE_PATH_C_HEADER))))
FILE_PATH_C_SRC = $(shell find $(PATH_DIR_CODE) -name *.c)
DIR_PATH_C_SRC = $(patsubst %/,%,$(sort $(dir $(FILE_PATH_C_SRC))))
INC_FILE_C_HEADER = $(addprefix -I, $(DIR_PATH_C_HEADER))
FILE_PATH_OBJ = $(patsubst $(DIR_PATH_C_SRC)/%.c, $(DIR_PATH_OBJ)/%.o, $(FILE_PATH_C_SRC))
CC = gcc
CFLAGS = -Werror -Wall
CDEPS = -MMD -MP -MF $(#:.o=.d)
LDFLAGS = -Llib
LDLIBS = -lm
MKDIR = mkdir
-include $(FILE_PATH_OBJ:.o=.d)
all : $(FILE_PATH_EXE)
.PHONY : all
$(FILE_PATH_EXE) : $(FILE_PATH_OBJ) | $(DIR_PATH_BIN)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(DIR_PATH_OBJ)/%.o : $(DIR_PATH_C_SRC)/%.c | $(DIR_PATH_OBJ)
$(CC) $(CFLAGS) -c $< $(CDEPS) -o $#
$(DIR_PATH_BIN) $(DIR_PATH_OBJ):
$(MKDIR) -p $#
clean :
$(RM) -rv $(DIR_PATH_BIN) $(DIR_PATH_OBJ)
Based on tutorial for dependencies I have used the flags
CDEPS = -MMD -MP -MF $(#:.o=.d)
and
-include $(FILE_PATH_OBJ:.o=.d)
still I am getting the following error
mkdir -p ../obj
gcc -Werror -Wall -c ../code/src/main.c -MMD -MP -MF ../obj/main.d -o ../obj/main.o
../code/src/main.c:4:10: fatal error: test.h: No such file or directory
#include "test.h"
^~~~~~~~
compilation terminated.
make: *** [Makefile:56: ../obj/main.o] Error 1
To remove this error what should be included in the Makefile?
Dependencies should be removed by this logic or some other logic should be used?
You are conflating two different things.
The .d files tell make where to look for prerequisites of the target. In this case the target is an object file (.o) and the prerequisite is a header file, but to make they're just "targets" and "prerequisites". Make is not restricted to just compiling C programs: it can do essentially any task where changing some files means that some other files need to be updated: compiling programs (not just C programs) is one common use but it can build documentation, web sites, run tests, etc. Make does its job by running commands, just as you would do it yourself from the command line (except make never forgets to add an option and doesn't make typos). It doesn't really know anything about "compilers" and "linkers", internally.
The error you are getting is from the compiler (or to be pedantic, the preprocessor), not make, and the compiler has to be told where to look for the header files it needs to include. Those are two completely different things and require different operations: the compiler requires that you provide the directories to search using the -I command line option.
I suppose it might be nice if the compiler could parse make's .d files and figure out where to look for headers, but it can't. You have to specify the flags yourself.
In your situation it's even more clear: you are actually using the compiler to generate the .d files! So there's a chicken-and-egg problem: if the compiler could get the paths from the .d files, but the .d files are being created from the compiler, then where do the paths come from in the first place?
My Makefile compiles all the files everytime I run it though the files have not been changed. I know that this question has been asked several times but none of the provided solutions seem to work for me. I am new to Makefile and most of the times I do not understand the jargon used in the solution. Also, I want to save all the generated .o files under the folder 'obj'
Here is my folder structure
project (-)
gen (-)
display (-)
.c and .h files
logic (-)
.c and .h files
lib (-)
include (-)
.h files
.lib files
man (-)
.c and .h files
obj (-)
want to save all the .o files here
I am running this on Windows OS using MinGW
Here is my Makefile:
ALL: demo
SRCS:= filename1.o filename2.o filename3.o filename4.o and so on till filename27.o
demo: display.o logic.o man.o
gcc $(SRCS) -lglut32 -loglx -lopengl32 -Llib -o demo
display.o:
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/display/*.c -lglut32 -loglx -lopengl32 -Llib -c
logic.o:
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/logic/*.c -lglut32 -loglx -lopengl32 -Llib -c
man.o:
gcc -Igen/display -Igen/logic -Iman -Ilib/include man/*.c -lglut32 -loglx -lopengl32 -Llib -c
clean:
#echo "Cleaning up.."
-rm -rf *.o
-rm *.exe
NOTE: glut and oglx files are present in the lib folder. Display.o, lib.o and man.o do not have corresponding .c files. They are just folder names with many c files in them.
I understand this could be the problem. As there are no display.o, logic.o and man.o files created, MAKE complies the rule associated with it eveytime. SO how do I tell it to check for the actual .o filename1.o, filename2.o etc for the timestamp and recompile ONLY if they are older than the corresponding c files and h files maybe even the lib files they depend on.
I tried the following to create dependencies and avoid compiling of files everytime. But this did not help.
%.d: %.c
#set -e; rm -f $#; \
$(CC) -M $(CFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
At a basic level, make is looking for lines like:
target: dependency
command
If target does not exist, it calls the rule for dependency and then runs command. If target does exist, it tests if dependency is newer or does not exist. If so, it calls the rule for dependency and then runs command. Otherwise, it stops.
Significantly, the rule for dependency will only be called if (a) dependency doesn't exist, or (b) dependency is newer than target.
In the question, assume we run make demo. Then make looks for the line that begins demo: and notices it declares dependencies. So it looks at each dependency in turn to see if they require action. It first discovers display.o. It notices that display.o: does not exist, so it runs the associated rule. It does the same for the other *.o.
To avoid the *.o rules always being run because no associated file exists, you could rewrite like:
ALL: demo
SRCS:= filename1.o filename2.o filename3.o filename4.o and so on till filename27.o
demo: display.ts logic.ts man.ts
gcc $(SRCS) -lglut32 -loglx -lopengl32 -Llib -o demo
display.ts: gen/display/*.c
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/display/*.c -lglut32 -loglx -lopengl32 -Llib -c
echo . > display.ts
logic.ts: gen/logic/*.c
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/logic/*.c -lglut32 -loglx -lopengl32 -Llib -c
echo . > logic.ts
man.ts: man/*.c
gcc -Igen/display -Igen/logic -Iman -Ilib/include man/*.c -lglut32 -loglx -lopengl32 -Llib -c
echo . > man.ts
clean:
#echo "Cleaning up.."
-rm -rf *.o *.ts
-rm *.exe
Problem is that your binary object targets (like display.o) do not actually match files produced by their rules. If you tell make it needs to make target display.o, it (normally, except for phony targets, but those always rerun) expect the corresponding file to be produced by the rule's recipe and it can track if the target needs to be remade. If no such file is produces, this target always evaluates as outdated and needing remaking.
A bit of a silly example of this would be the following tree:
.
├── Makefile
├── main.c
└── test
└── file.c
and Makefile:
main: test.o main.o
$(CC) -o main *.o
test.o:
$(CC) $(CFLAGX) -c test/*.c
There is no test.o file and target needs to be remade... the rule runs, produces file.o (again). Since this target was remade and is prerequisite of main... everything always gets remade.
Now with this small modification:
main: test.o main.o
$(CC) -o main *.o
test.o:
$(CC) $(CFLAGX) -o $# -c test/*.c
test.o target indeed produces test.o file and the rule needs no remaking if test.c does not change... and with test.o unchanged and main.c perhaps as well, we get:
$ make
make: 'main' is up to date.
It still is not entirely correct as it really should read:
main: test.o main.o
$(CC) -o main $+
test.o: test/*.c
$(CC) $(CFLAGX) -o $# -c $^
Where I declare depend prerequisites of test.o and reference both them and the target by automatic variable in the rule's recipe. And Same goes for prerequisites for linking. Of course in this simple example I could just rely on implicit pattern rules and do this:
main: test/file.o main.c
test/file.o: test/*.c
What does this mean for your makefile? When you compile your object files, have a look what do they actually produce and match your target to that or (with -o $# for instance) tell them to produce exactly the file matching your target.
I've extended the silly example a bit and there are now two files in test/:
.
├── Makefile
├── main.c
└── test
├── file.c
└── other.c
And the Makefile can look something like this:
main: obj/file.o obj/other.o main.c
obj/%.o: test/%.c
mkdir -p obj
$(CC) $(CFLAGS) -c -o $# $^
It now stores object files in obj/ and make still understand what needs what and can track changes. Of course your setup is more complex and will require more rules, perhaps also divining actual sources or intermediate targets from the directory tree and define few variables to work with that information, e.g.:
OBJS := $(patsubst test/%.c,obj/%.o,$(wildcard test/*.c))
main: $(OBJS) main.c
obj/%.o: test/%.c
mkdir -p obj
$(CC) $(CFLAGS) -c -o $# $^
But the principles remain the same.
This question already has answers here:
makefile unexpectedly removes target
(2 answers)
Closed 6 years ago.
I'm trying to write a makefile which generates assembly files
(by calling gcc with the -S flag), then modifies the generated s.-files
and then compiles it. To find an approach I made a short sample
makefile which works fine when I list the name of the .s-sourcefiles precisely (main.s, mod1.s etc.).
objects = main.o mod1.o
assembly = main.s mod1.s
app : $(objects)
gcc -o app $(objects)
chmod +x app
%.s : %.c
gcc -S $<
# here some code will be called to modify
# the .s file for some experimental purpose ..
main.o : main.s
gcc -c main.s
mod1.o : mod1.s
gcc -c mod1.s
cleanobj :
rm app $(objects)
cleanass :
rm $(assembly)
cleanall : cleanobj cleanass
This works as intended.
But when when I define the dependecy
a little more generic ("%.o : %.s")
the assembly (.s) files are not generated any more:
objects = main.o mod1.o
assembly = main.s mod1.s
app : $(objects)
gcc -o app $(objects)
chmod +x app
%.s : %.c
gcc -S $<
# here some code will be called to modify
# the .s file for some experimental purpose ..
%.o : %.s
gcc -c $<
cleanobj :
rm app $(objects)
cleanass :
rm $(assembly)
cleanall : cleanobj cleanass
Any explanation i.e. idea how to implement these steps?
You need to mark assembler files as precious:
.PRECIOUS: %.s
or just mark add following to forcedly keep all intermediate outputs:
.SECONDARY:
Also see this question.
Thanks a lot yugr, the -r flag was the relevant hint!
To anyone struggeling the same behaviour:
The following makefile (compared to the above, .PRECIOUS: %.s has been added) produces the desired output (.s and .o files):
objects = main.o mod1.o
assembly = main.s mod1.s
.PRECIOUS: %.s
app : $(objects)
gcc -o app $(objects)
chmod +x app
%.s : %.c
gcc -S $<
# here some code will be called to modify
# the .s file for some experimental purpose ..
%.o : %.s
gcc -c $<
cleanobj :
rm app $(objects)
cleanass :
rm $(assembly)
cleanall : cleanobj cleanass
produces, called with
make
cc -c -o main.o main.c
cc -c -o mod1.o mod1.c
gcc -o app main.o mod1.o
chmod +x app
but when called with
make -r
gcc -S main.c
gcc -c main.s
gcc -S mod1.c
gcc -c mod1.s
gcc -o app main.o mod1.o
chmod +x app
ie. the demanded .s files were created, also leading to an executable 'app'.
Be aware no .o or .s file are existing in the target folders.
I would like to develop a little kernel for my new raspberry pi and used this course : http://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/
to understand it. Well when I download a example from this site with more than one source file it compiles the first correctly and then tell me the following: make *** no rule to build target 'build/', needed by 'build/gpio.o'.Stop.
Let me explain. There is a folder sources which contains all source files.In the makefile these files are compiled to .o files in the build folder, but the build folder is ALSO set as dependency when compiling a assembler file. So when the first file is compilied and the build folder created, the folders timestamp is outdated and the second compiling file cant use this directory as a dependency. That is the problem to solve, but I have no idea how.
Here is the makefile:
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 = kernel.img
# The name of the assembler listing file to generate.
LIST = kernel.list
# The name of the map file to generate.
MAP = kernel.map
# The name of the linker script to use.
LINKER = kernel.ld
# 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))
# 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) $(LINKER)
$(ARMGNU)-ld --no-undefined $(OBJECTS) -Map $(MAP) -o $(BUILD)output.elf -T $(LINKER)
# Rule to make the object files.
$(BUILD)%.o: $(SOURCE)%.s $(BUILD)
$(ARMGNU)-as -I $(SOURCE) $< -o $#
$(BUILD):
mkdir $#
# Rule to clean files.
clean :
-rm -rf $(BUILD)
-rm -f $(TARGET)
-rm -f $(LIST)
-rm -f $(MAP)
PS::
YEEAAYY I've got it.Are working for that for days but now :)
Look again at the page with this example: `OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir $(OBJDIR)`
I just deleted the $(BUILD) folder dependency from the targets and wrote:
$(OBJECTS): | $(BUILD)
So now it works perfect here the few lines I changed:
$(BUILD)%.o: $(SOURCE)%.s
$(ARMGNU)-as -I $(SOURCE) $< -o $#
$(OBJECTS): | $(BUILD)
What you want to do is make $(BUILD) an order-only prerequisite:
$(BUILD)%.o: $(SOURCE)%.s | $(BUILD)
I'm trying to create a generic makefile to build static libraries that my project uses. I've used the expertise on this site, as well as the GNU Make manual to help write the following makefile. It is working well apart from one annoying problem.
# Generic makefile to build/install a static library (zlib example)
ARCH = linux
CFLAGS = -O3 -Wall
# List of source code directories
SOURCES = src test utils
# List of header files to install
INCLUDES = src/zlib.h src/zconf.h
# Library to create
LIBNAME = libz.a
############################################################
BUILD_DIR = build/$(ARCH)
# Full path to the built library
TARGET = $(BUILD_DIR)/$(LIBNAME)
prefix = ../..
exec_prefix = prefix
libdir = $(prefix)/lib/$(ARCH)
includedir = $(prefix)/include
INSTALL_PROGRAM = install -D
INSTALL_DATA = $(INSTALL_PROGRAM) -m 644
CFILES := $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.c))
OBJECTS := $(addprefix $(BUILD_DIR)/,$(CFILES:.c=.o))
DEPENDS := $(OBJECTS:.o=.d)
.PHONY: all installdirs install uninstall clean
# Default
all: $(DEPENDS) $(TARGET)
# Build the dependency files
# (GNU Make Manual 4.14 Generating Prerequisites Automatically)
$(BUILD_DIR)/%.d: $(BUILD_DIR)
#echo "build dep for $*.c as $#"
#$(CC) -M $(CFLAGS) $*.c > $#.tmp
#sed s~.*:~"$(BUILD_DIR)/$*.o $#:"~ $#.tmp > $#
#rm $#.tmp
# Link all changed object files into static library
$(TARGET): $(OBJECTS)
$(AR) -rc $(TARGET) $?
# Compile C source to object code
$(BUILD_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
# Create the necessary directory tree for the build
$(BUILD_DIR):
#for p in $(SOURCES); do mkdir -p $(BUILD_DIR)/$$p; done
# Create the necessary directory tree for installation
installdirs:
#mkdir -p $(libdir)
#mkdir -p $(includedir)
# Install the library and headers
install: all installdirs
$(INSTALL_DATA) $(TARGET) $(libdir)
for p in $(INCLUDES); do $(INSTALL_DATA) $$p $(includedir); done
# Remove the library and headers
uninstall:
rm -f $(libdir)/$(LIBNAME)
for p in $(notdir $(INCLUDES)); do rm -f $(includedir)/$$p; done
# Remove all build files
clean:
rm -fr $(BUILD_DIR)
# Pull in the dependencies if they exist
# http://scottmcpeak.com/autodepend/autodepend.html
-include $(DEPENDS)
The problem is that the dependency files are built when they don't need to be. e.g. make install shown below rebuilds the .d files before installing.
$make --version
GNU Make 3.81
$make
build dep for utils/utils.c as build/linux/utils/utils.d
build dep for test/test.c as build/linux/test/test.d
build dep for src/zutil.c as build/linux/src/zutil.d
...
{ continues on making the other .d files, then the .o files }
...
cc -O3 -Wall -c src/zutil.c -o build/linux/src/zutil.o
cc -O3 -Wall -c test/test.c -o build/linux/test/test.o
cc -O3 -Wall -c utils/utils.c -o build/linux/utils/utils.o
ar rc { ... .o files ... }
All good up to this point! But a 'make install' now will rebuild the .d files
$make install
build dep for utils/utils.c as build/linux/utils/utils.d
build dep for test/test.c as build/linux/test/test.d
build dep for src/zutil.c as build/linux/src/zutil.d
{ ... }
install -D -m 644 build/linux/libz.a ../../lib/linux
for p in src/zlib.h src/zconf.h; do install -D -m 644 $p ../../include; done
I tried to 'touch' the .d files when the objects are built, so the update time is newer than the .o files, but that had no effect. What's wrong with my makefile?
The problem is that you include the dependency files (whatever.d), and you also have a rule for building these files. So every time you use this makefile, no matter what target you specify, it will rebuild them, include them, and execute again.
Try this for an approach to dependency handling that solves this problem. Basically, you don't need a separate rule for foo.d, just make it a side effect of the foo.o rule (it takes some thought to realize that this will work).