I have large number of .ml and .cpp files in a same directory which are totally independent of each other. Is there any way I can compile them with Makefile without using external bash / shell scripts?
CC=g++
CFLAGS=-Wall -std=c++14 -Wno-unused-variable
CCML=ocamlc
SHELL := '/bin/bash'
.SUFFIXES = .cpp .ml
cpp_objs:=$(wildcard *.cpp)
ml_objs:=$(wildcard *.ml)
cpp_targets:=$(cpp_objs:.cpp= )
ml_targets:=$(ml_objs:.ml= )
targets:=$(cpp_targets) $(ml_targets)
.PHONY:all
all: $(targets)
# all: $(cpp_targets)
.ml:
$(CCML) -o $# $<
.cpp:
$(CC) $(CFLAGS) -o $# $<
What's wrong with this Makefile that only recognises my .cpp files :
make: *** No rule to make target `[ML-FILES]', needed by `all'. Stop.
Update: All the *.ml and *.cpp files has unique name in the directory.
Thanks.
According to the manual you are supposed to configure .SUFFIXES like a target, not like a variable:
.SUFFIXES: .cpp .ml
However, the better approach is to use pattern rules so you can drop the use of .SUFFIXES entirely.
%: %.ml
$(CCML) -o $# $<
Related
I have the following makefile that I use to build a program (a kernel, actually) that I'm working on. Its from scratch and I'm learning about the process, so its not perfect, but I think its powerful enough at this point for my level of experience writing makefiles.
AS = nasm
CC = gcc
LD = ld
TARGET = core
BUILD = build
SOURCES = source
INCLUDE = include
ASM = assembly
VPATH = $(SOURCES)
CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions \
-nostdinc -fno-builtin -I $(INCLUDE)
ASFLAGS = -f elf
#CFILES = core.c consoleio.c system.c
CFILES = $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
SFILES = assembly/start.asm
SOBJS = $(SFILES:.asm=.o)
COBJS = $(CFILES:.c=.o)
OBJS = $(SOBJS) $(COBJS)
build : $(TARGET).img
$(TARGET).img : $(TARGET).elf
c:/python26/python.exe concat.py stage1 stage2 pad.bin core.elf floppy.img
$(TARGET).elf : $(OBJS)
$(LD) -T link.ld -o $# $^
$(SOBJS) : $(SFILES)
$(AS) $(ASFLAGS) $< -o $#
%.o: %.c
#echo Compiling $<...
$(CC) $(CFLAGS) -c -o $# $<
#Clean Script - Should clear out all .o files everywhere and all that.
clean:
-del *.img
-del *.o
-del assembly\*.o
-del core.elf
My main issue with this makefile is that when I modify a header file that one or more C files include, the C files aren't rebuilt. I can fix this quite easily by having all of my header files be dependencies for all of my C files, but that would effectively cause a complete rebuild of the project any time I changed/added a header file, which would not be very graceful.
What I want is for only the C files that include the header file I change to be rebuilt, and for the entire project to be linked again. I can do the linking by causing all header files to be dependencies of the target, but I cannot figure out how to make the C files be invalidated when their included header files are newer.
I've heard that GCC has some commands to make this possible (so the makefile can somehow figure out which files need to be rebuilt) but I can't for the life of me find an actual implementation example to look at. Can someone post a solution that will enable this behavior in a makefile?
EDIT: I should clarify, I'm familiar with the concept of putting the individual targets in and having each target.o require the header files. That requires me to be editing the makefile every time I include a header file somewhere, which is a bit of a pain. I'm looking for a solution that can derive the header file dependencies on its own, which I'm fairly certain I've seen in other projects.
As already pointed out elsewhere on this site, see this page:
Auto-Dependency Generation
In short, gcc can automatically create .d dependency files for you, which are mini makefile fragments containing the dependencies of the .c file you compiled.
Every time you change the .c file and compile it, the .d file will be updated.
Besides adding the -M flag to gcc, you'll need to include the .d files in the makefile (like Chris wrote above).
There are some more complicated issues in the page which are solved using sed, but you can ignore them and do a "make clean" to clear away the .d files whenever make complains about not being able to build a header file that no longer exists.
You could add a 'make depend' command as others have stated but why not get gcc to create dependencies and compile at the same time:
DEPS := $(COBJS:.o=.d)
-include $(DEPS)
%.o: %.c
$(CC) -c $(CFLAGS) -MM -MF $(patsubst %.o,%.d,$#) -o $# $<
The '-MF' parameter specifies a file to store the dependencies in.
The dash at the start of '-include' tells Make to continue when the .d file doesn't exist (e.g. on first compilation).
Note there seems to be a bug in gcc regarding the -o option. If you set the object filename to say obj/_file__c.o then the generated _file_.d will still contain _file_.o, not obj/_file_c.o.
This is equivalent to Chris Dodd's answer, but uses a different naming convention (and coincidentally doesn't require the sed magic. Copied from a later duplicate.
If you are using a GNU compiler, the compiler can assemble a list of dependencies for you. Makefile fragment:
depend: .depend
.depend: $(SOURCES)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^>>./.depend;
include .depend
There is also the tool makedepend, but I never liked it as much as gcc -MM
You'll have to make individual targets for each C file, and then list the header file as a dependency. You can still use your generic targets, and just place the .h dependencies afterwards, like so:
%.o: %.c
#echo Compiling $<...
$(CC) $(CFLAGS) -c -o $# $<
foo.c: bar.h
# And so on...
Basically, you need to dynamically create the makefile rules to rebuild the object files when the header files change. If you use gcc and gnumake, this is fairly easy; just put something like:
$(OBJDIR)/%.d: %.c
$(CC) -MM -MG $(CPPFLAGS) $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(#D)/\1.o $(#D)/\1.d:,' >$#
ifneq ($(MAKECMDGOALS),clean)
include $(SRCS:%.c=$(OBJDIR)/%.d)
endif
in your makefile.
Over and above what #mipadi said, you can also explore the use of the '-M' option to generate a record of the dependencies. You might even generate those into a separate file (perhaps 'depend.mk') which you then include in the makefile. Or you can find a 'make depend' rule which edits the makefile with the correct dependencies (Google terms: "do not remove this line" and depend).
Simpler solution: Just use the Makefile to have the .c to .o compilation rule be dependent on the header file(s) and whatever else is relevant in your project as a dependency.
E.g., in the Makefile somewhere:
DEPENDENCIES=mydefs.h yourdefs.h Makefile GameOfThrones.S07E01.mkv
::: (your other Makefile statements like rules
::: for constructing executables or libraries)
# Compile any .c to the corresponding .o file:
%.o: %.c $(DEPENDENCIES)
$(CC) $(CFLAGS) -c -o $# $<
None of the answers worked for me. E.g. Martin Fido's answer suggests gcc can create dependency file, but when I tried that it was generating empty (zero bytes) object files for me without any warnings or errors. It might be a gcc bug. I am on
$ gcc --version gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
So here's my complete Makefile that works for me; it's a combination of solutions + something that wasn't mentioned by anyone else (e.g. "suffix replacement rule" specified as .cc.o:):
CC = g++
CFLAGS = -Wall -g -std=c++0x
INCLUDES = -I./includes/
# LFLAGS = -L../lib
# LIBS = -lmylib -lm
# List of all source files
SRCS = main.cc cache.cc
# Object files defined from source files
OBJS = $(SRCS:.cc=.o)
# # define the executable file
MAIN = cache_test
#List of non-file based targets:
.PHONY: depend clean all
## .DEFAULT_GOAL := all
# List of dependencies defined from list of object files
DEPS := $(OBJS:.o=.d)
all: $(MAIN)
-include $(DEPS)
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
#suffix replacement rule for building .o's from .cc's
#build dependency files first, second line actually compiles into .o
.cc.o:
$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$#) $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $# $<
clean:
$(RM) *.o *~ $(MAIN) *.d
Notice I used .cc .. The above Makefile is easy to adjust for .c files.
Also notice importance of these two lines :
$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$#) $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $# $<
so gcc is called once to build a dependency file first, and then actually compiles a .cc file. And so on for each source file.
I believe the mkdep command is what you want. It actually scans .c files for #include lines and creates a dependency tree for them. I believe Automake/Autoconf projects use this by default.
I have a problem with building cpp files when I move them out of Makefile folder. Anyone knows why?
Snippet from the makefile:
CC = qcc -Vgcc_nto$(PLATFORM)
CXX = qcc -lang-c++ -Vgcc_nto$(PLATFORM)
LD = $(CXX)
DEPS = -Wp,-MMD,$(#:%.o=%.d),-MT,$#
CFLAGS=-Wall -g -ggdb -O0
DIR_SRC =./
DIR_OBJ =./
SRCS := $(wildcard $(DIR_SRC)/*.cpp)
OBJECTS := $(SRCS:$(DIR_SRC)/%.cpp=$(DIR_OBJ)/%.o)
all: hello_world_test
$(DIR_OBJ)/%.o : $(DIR_SRC)/%.c
$(CXX) $(CFLAGS) ${CPPFLAGS} ${DEPS} -c $< -o $#
hello_world_test: hello_world_test.o
$(CXX) hello_world_test.o $(LDFLAGS) $(LIBPATH) $(LDLIBS) -o $#
So in this way, everything is fine but when I move sources to one folder back called "test"
DIR_SRC =../test
it doesnt work anymore with the message:
make: *** No rule to make target 'hello_world_test.o', needed by 'hello_world_test'. Stop.
Because:
hello_world_test: hello_world_test.o
your hello_world_test depends on hello_world_test.o. But your rule tells make how to build $(DIR_OBJ)/%.o and hello_world_test.o doesn't match that pattern. Pattern matching in targets is simple string matching, it doesn't do pathname simplification. You should write your prerequisite as:
hello_world_test: $(DIR_OBJ)/hello_world_test.o
Note that you have two slashes here: one in DIR_OBJ and one after it. But anyway.
The reason it worked before is that make was using its built-in recipe to build object files, not your recipe; the built-in recipe has the pattern:
%.o : %.c
which matched your object file. If you run make with the -r option to remove all built-in rules, you would have seen a failure there as well.
Thank you for your answer. I found out that the problem was in the rule, like you said.
I changed to $(DIR_OBJ)/%.o : $(DIR_SRC)/%.cpp (before it was .c instead of .cpp :) ) and it works now with changing the DIR_SRC.
I didn't observe this since I was able to build from the current directory but realized after your answer about built-in rule.
Another questions:
1) Does this rule:
$(DIR_OBJ)/%.o : $(DIR_SRC)/%.cpp
$(CXX) $(CFLAGS) ${CPPFLAGS} ${DEPS} -c $< -o $#
says next: do compile all .cpp files and make .o files out of it and put the .o files in DIR_OBJ?
2) Why I cant change DIR_OBJ location to for instance:
DIR_OBJ =../test and then use hello_world_test: $(DIR_OBJ)/hello_world_test.o to build the executable?
When I do it I get an error: cannot find hello_world_test.o: No such file or directory.
I see that .o and .d files are created in the directory where DIR_OBJ is defined (either in ./ or in ../test) and then it makes me quite confused why hello_world_test cant fine prerequisite $(DIR_OBJ)/hello_world_test.o but it only looks in the current folder where the Makefile is.
I realized what was the problem:
I haven't added $(DIR_OBJ)/hello_world_test.o in
$(CXX) hello_world_test.o $(LDFLAGS) $(LIBPATH) $(LDLIBS) -o $#
but now still confused, if my understanding is right that $(DIR_OBJ)/%.o : $(DIR_SRC)/%.cpp will create $(DIR_OBJ)/hello_world_test.o how come that hello_world_client: $(DIR_OBJ)/hello_world_client.o couldn't find prerequisite?
I want to compile all the files located in src/ directory to bc/%.bc.
Because I use the std=c++17 flags which can not be used with .c files, I tried this :
bc/%.bc: src/%.*
ifeq '$(suffix $^)' '.c'
emcc $^ -o $#
else
em++ $^ -o $# -std=c++17
endif
But it does not work, the condition ifeq is always false (same when I replace '.c' with '.cpp').
Is there a way to achieve a separate compilation based on file suffix ?
There's more than one way to do it. The best is probably to separate the rule into two rules, one for .c and one for .cpp:
bc/%.bc: src/%.c
emcc $< -o $#
bc/%.bc: src/%.cpp
em++ $^ -o $# -std=c++17
Then you need a way to construct a list of the files you want. (You need this anyway, since that src/%.* doesn't work the way you think.)
SRC_FILES := $(wildcard src/%.*)
TARTGETS := $(patsubst src/%, bc/%.bc, $(basename $(SRC_FILES)))
And a default rule to build everything:
$(TARGETS):
My Makefile:
compiler=g++
cflags=-g -Wall -I.
src=$(shell find . -name *.cc) #find all .cc files, with path name
srcBaseName=$(shell basename -a $(src)) # extract base names by stripping off the path
header=$(shell find . -name *.h) # all header files
obj=$(patsubst %.cc, %.o, $(srcBaseName)) # Problematic line
bin=bin/myProgram
all: $(bin)
$(bin): $(obj)
$(compiler) $^ -o $#
%.o: %.cc
$(compiler) $(cflags) -c $^ -o $#
clean:
rm $(obj) $(bin)
results in the following error:
make: *** No rule to make target 'SomeObjectFile.o', needed by
'bin/myProgram'. Stop.
The problematic line:
obj=$(patsubst %.cc, %.o, $(srcBaseName))
If I change $(srcBaseName) to $(src), then everything builds fine. But in that case the .o files are going to be scattered in the corresponding folders with .cc files, which I don't want.
I'd like to have a dedicated (obj/) folder to store all the .o files.
How can I do it?
First try:
obj=$(patsubst %.cc, %.o, obj/$(srcBaseName))
Second try:
obj=$(patsubst %.cc, %.o, obj\/$(srcBaseName))
Why did they NOT work?
/**********************Edited on 16th Feb 2015**********************/
Based on the suggestions in the answers, I updated my Makefile to be this:
compiler=g++
# source compilation flags
cflag=-g -Wall -std=gnu++0x -I./header/
# source link flags
lflag=
# lib used by proj
lib=
tflag=-g -Wall -std=gnu++0x
# test link flags
tlflag=
# test libs
testLib=lib/libgtest.a
# source code
src=$(shell find "./src" -name "*.cc")
srcBaseName=$(shell basename -a $(src))
obj=$(addprefix obj/, $(patsubst %.cc, %.o, $(srcBaseName)))
vpath %.cc $(dir $(src))
# header files
header=$(shell find "./header" -name "*.h")
# test files
testSrc=$(shell find "./test" -name "*.cc")
testSrcBase=$(shell basename -a $(testSrc))
testObj=$(addprefix obj/, $(patsubst %.cc, %.o, $(testSrcBase)))
vpath %.cc $(dir $(testSrc))
# binary files
bin=bin/Driver
testBin=bin/Test
all: prog test
prog: $(bin)
$(bin): $(obj)
$(compiler) $(lflag) $^ $(lib) -o $#
#$(obj): $(src) $(header)
obj/%.o: %.cc $(header)
$(compiler) $(cflag) -c $< -o $#
test: $(testBin)
$(testBin): $(testObj)
$(compiler) $(tlflag) $^ $(testLib) -o $#
obj/%.o: %.cc
$(compiler) $(tflag) -c $< -o $#
clean:
rm $(obj) $(bin) $(testObj) $(testBin)
Here's the intention behind the make:
make prog:
make should find all the source files(.cc) under ./src directory, and produce an .o file with the same file name in the ./obj directory, insensitive to the levels of subdirectories so that I can freely add new cc files without the need to update the Makefile. Each .o file depends on the corresponding(just the one with the same name, not all) .cc file and ALL headers(make does not automatically know what header files a cc file includes without parsing the file; if you have a clever method to achieve this, do let me know!). For example, ./src/subdirectory1/sample1.cc should produce ./obj/sample1.o and ./obj/sample1.o depends on ./src/subdirectory1/sample1.cc + ./header/sample1.h + ./header/sample2.h + ...
make test:
it should do similar things to the test source files in the ./test folder, with the exception that there's no header involved. In case this detail helps, I'm using Google Test.
However, my Makefile is not quite working in the intended way because it has the following problems:
1, if I run make test, the recipe $(compiler) $(tflag) -c $< -o $# is not executed(tflag means 'test compilation flag', which doesn't have the -I./header/ part; cflag means 'source code compilation flag', it has the -I./header/ part). Instead, the recipe in phony prog $(compiler) $(cflag) -c $< -o $# is executed. This observation comes from the output in which '-I./header/' shows up. I guess this is because the cflag pattern rule in phony prog overrides the tflag one in phony test? I vaguely remember make picks the best matching pattern rule - the two are essentially the same(I have the intention that the pattern rule under a specific phony should get executed when that phony is executed, which doesn't seem to be feasible?), so make will always pick the first one. This conclusion is verified by swapping the order of two pattern rules in the Makefile, and this time the tflag rule always gets picked. So a natural question to ask is, how do I execute the pattern rule under a specific phony when that phone is executed?
2, Assuming it's not feasible to do what I wanted to do in point 1, I start to think about alternatives. Can I do something like: #$(obj): $(src) $(header) so that I can get rid of the pattern rule to work around the way make picks the pattern rule. However, this is obviously not correct as it's saying, each .o file in $(obj) depends on ALL src files and ALL header files. Is it at all a right direction?
Thanks a lot, looking forward to hearing from you.
3 key questions have been highlighted in bold and italicized.
Your problem is this line:
%.o: %.cc
That line tells make that to create some/path/file.o you will use some/path/file.cc.
If you want all .o files in one single directory, but still want to have the source files in different directories you will need one such rule for each source directory. Or, you could add all directories to the VPATH variable, something like:
VPATH=$(dir $(src))
Or maybe better:
VPATH=$(dir $(SRC))
Usuing capital letters for your variables in a Makefile is a good way to avoid confusing them with function names.
I will do my best to also answer your new questions:
1) As you are using the gnu compilers it is possible to automatic find the dependencies of .h files in .c files. You could add rules like this to your Makefile:
# Where .d-files will be created for dependencies
DEP=dep
# Dependency files
DEPS = $(srcBaseName:%.cc=$(DEP)/%.d)
# Before compiling object file, also make sure dependency file is
# created to test the need for future recompilation
obj/%.o: %.cc $(DEP)/%.d
$(compiler) $(cflags) -c $< -o $#
# Use gnu compiler to create dependency files
$(DEPS): $(DEP)/%.d: %.cc $(filter-out $(wildcard $(DEP)), $(DEP))
$(compiler) -MM $(cflags) -MT $# $< > $#
# Create directories which might be needed
$(DEP) $(OBJ) $(BIN) $(MO):
mkdir -p $#
# Let Makefile use any generated dependency files
ifneq ($(wildcard $(DEPS)),)
include $(wildcard $(DEPS))
endif
Please note that in the compilation rule I replaced $^ with $< as we don't want to compile the dependency file.
2) I would avoid two pattern rules looking the same. Instead I would change cflag depending on the target, something like this:
ifeq ($(MAKECMDGOALS),debug)
CFLAGS += -g
else
CFLAGS += -O2
endif
I hope these answers will guide you in the right direction
The main problem is that make cannot use the pattern rule
%.o: %.cc
$(compiler) $(cflags) -c $^ -o $#
to build obj since it cannot find common stems between your .o files and your .cc files to match %. An easy way to fix this is to tell make where those files are through the vpath directive, e.g. by adding
vpath %.cc $(dir $(src))
vpath %.o obj/ #not a good idea for .o files though, see below
and changing the pattern rule (needed by the use of vpath %.o) into
%.o: %.cc
$(compiler) $(cflags) -c $^ -o obj/$#
EDIT: MadScientist has made a very good point that I completely missed, based on which, a better solution that does not involve vpath %.o is
vpath %.cc $(dir $(src))
obj=$(addprefix obj/,$(patsubst %.cc, %.o, $(srcBaseName)))
obj/%.o: %.cc
$(compiler) $(cflags) -c $^ -o $#
i wrting a simple makefile for c++ files but here is a problem i do not understand.
I have 2 folders
/src for .cpp files
main.cpp
check cpp
/include for .hpp files
check.hpp
My Makefiles looks like this
LIBS = -lsfml-graphics -lsfml-window -lsfml-system
CC = g++
VPATH = src include
CPPFLAGS = -I include
### Files ###
OBJ = main.o check.o
### Rules ###
all: sfml-app
sfml-app: $(OBJ)
$(CC) -o sfml-app $(OBJ) $(LIBS)
%.o: %.c
$(CC) -c $<
clean:
rm -rf *o $(OBJ)
if i use my makefile likes this, everything works fine.
But if i change %.o: %.c to %.o: %.cpp he said
src/main.cpp:2:21: critical error: check.hpp: file or folder not found
is it wrong to write .cpp instead of .c even it is a c++ project? This confused me a bit. Why .c works finde and .cpp not.
thanks for your help :) !
Because make is trying to build a .o from a .cpp file, when you write a rule like %.o : %.c it has no effect on make because make is not trying to build a .o from a .c. Because of that, make is using its own built-in rules to compile the .cpp file into the .o file and the built-in rule works fine.
When you change the rule to be %.o : %.cpp, now your rule matches what make wants to build and so make uses your rule instead of its own built-in rule. Obviously your rule is broken and does not work.
Why does it not work? Because you are not using $(CPPFLAGS), and so the -I include flags are not passed to the compiler, and so the compiler cannot find your header files.
The flags variable for the C++ language is called CXXFLAGS, and you should be using $(CXX) instead of $(CC) in your code. CPPFLAGS is the variable for preprocessor arguments.
Use standard make file flags
CXX for g++
CPP for cpp files
and try:
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $<
The default rules are:
For C files:
$(CC) -c $(CPPFLAGS) $(CFLAGS) $?
For C++ files
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $?
For linking:
$(CC) $(LDFLAGS) $^ $(LOADLIBES)
CPPFLAGS is supposed to be pre-processor flags. The other two (CFLAGS CXXFLAGS) are flags for the specific languages. You should adjust your usage as such.
Also it is unusual to exlicitly define the object files:
OBJ = main.o check.o
It is more usual to define the source files. Then define object files in terms of the source files
OBJ = $(patsubst %.cpp, %.o, $(SRC))
Personally I like to build everything in the directory so use
SRC = $(wildcard *.cpp)
But this will depend a lot on the project.