So i have a somewhat large C++ project that I want to compile.Previously I used Code::Blocks, but now I want more control about what's happening behind the scenes. However making makefiles was just too complex for me!!
What I want is this: Can i create a python script that acts as a makefile, if so how?!
In the makefile I want to search for all *.cpp files on certain directories and then invoke g++ to compile/link them.
EDIT: sorry i forgot to mention i also have headers and want custom g++ parameters
Try scons
It looks like what you need
Try that:
#default target
all: prog
#auto dependency
include $(OBJ_FILES:.o=.d)
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $*.cpp -o $*.o
$(CXX) -MM $(CXXFLAGS) $*.cpp > $*.d
#mv -f $*.d $*.d.tmp
#sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d
#sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
#rm -f $*.d.
#set ld flags eg for libs
LDFLAGS = -lsdl2 -lglew -lgl
#set cxxflags for all debug options and others
CXXFLAGS= -g -Wall
#collect all cpp files:
CPP_FILES := $(shell find . -type f -name '*.cpp')
#get the object file names for them
OBJ_FILES := $(CPP_FILES:.cpp=.o)
#and link all togeter
prog: $(OBJ_FILES)
g++ $(CXXFLAGS) $(LDFLAGS) -o $# $^
Related
I'm working on a Makefile that i can use on most of my school projects.
I only did basics makefile before and never had a problem, but for this one i wanted to put some colors etc...
And it relink everytime i make it.
I think the relink come from my echos ? But i'm not sure.
Here is my makefile :
#GENERAL
CC = clang++
FLAGS = -Wall -Wextra -Werror -std=c++98
RM = rm -rf
#PROJET
EXEC = ClapTrap
#FILES
SRCS = ClapTrap.cpp main.cpp
OBJS = $(SRCS:.cpp=.o)
OBJSDIR = objects/
#REGLES
.cpp.o: $(SRCS)
mkdir -p $(OBJSDIR)
echo "$(BLUE)Compiling $^ ..$(CLEAR)"
$(CC) $(FLAGS) -c $< -o $(addprefix $(OBJSDIR), $#)
echo " $(YELLOW)$(addprefix $(OBJSDIR), $#)$(CLEAR) [$(GREEN)OK$(CLEAR)]"
all: $(EXEC)
$(EXEC): $(OBJS)
echo "$(BLUE)========================================$(CLEAR)"
echo "$(BLUE) Compiling binary file ..$(CLEAR)"
echo "$(BLUE)========================================$(CLEAR)"
$(CC) -o $(EXEC) $(addprefix $(OBJSDIR), $^) $(FLAGS)
echo "$(YELLOW)$(EXEC)$(GREEN) is now ready to use !$(CLEAR)"
clean:
#$(RM) $(OBJSDIR)
#echo "$(RED)Cleaning up..$(CLEAR)"
fclean: clean
#$(RM) $(EXEC)
#echo -n "$(RED)$(EXEC)$(CLEAR)"
re: fclean all
.PHONY: all
Thank's for reading !
EDIT :
So i removed SRCS from my .cpp.o rules dependencies, but still relinking.
Here the updated Makefile :
#FILES
SRCS = ClapTrap.cpp main.cpp
OBJS = $(SRCS:.cpp=.o)
OBJSDIR = objects
#REGLES
.cpp.o:
echo "$(BLUE)Compiling $(YELLOW)$^$(BLUE) ..$(CLEAR)"
mkdir -p $(OBJSDIR)
$(CC) $(FLAGS) -c $< -o $#
mv $# $(OBJSDIR)
echo "$(BLUE) - $(YELLOW)$#$(CLEAR) [$(GREEN)OK$(CLEAR)]"
all: $(EXEC)
$(EXEC): $(OBJS)
echo "$(BLUE)========================================$(CLEAR)"
echo "$(BLUE) Compiling binary file ..$(CLEAR)"
echo "$(BLUE)========================================$(CLEAR)"
$(CC) $(FLAGS) $(STD) $(addprefix $(OBJSDIR)/, $(OBJS)) -o $(EXEC)
echo "$(YELLOW)$(EXEC)$(GREEN) is now ready to use !$(CLEAR)"
This is wrong:
$(CC) $(FLAGS) -c $< -o $#
mv $# $(OBJSDIR)
When make runs your recipe it will put the file it expects you to build into the $# automatic variable. If your makefile builds some OTHER file, not the one it asked you to build, then the next time you run make it will see that the file it wants doesn't exist (because you didn't build it, you build some other file) and so it's always out of date.
Your rules must always build exactly the file $#, not some other file.
It's not actually possible to write a makefile that puts targets in a different directory, using suffix rules. They can only create files in the same directory. That's (one reason) why GNU make supports pattern rules which are much more flexible.
If you have to write a POSIX conforming makefile that doesn't support pattern rules, and you want to put the object files in some other directory, all you can do is write out all the targets and their rules explicitly.
I am trying to write a make file for the following program
MY file/folder structure is as follows
Folder/File structure
./demo/utilities.c
./demo/utilities.h
./demo/makefile
./include/GeographicLib/UTMUPS.h
./include/GeographicLib/Constant.h
./include/GeographicLib/xxxxxxx
in the file utilities.h
#include <GeographicLib/UTMUPS.h>
in the file UTMUPS.h
#include <GeographicLib/Constant.h>
in the makefile
# preprocessor
PREPROC_FLAGS += -DEIGEN_DONT_ALIGN_STATICALLY
INC_XTRA_DIR = ../include
CC=g++
CPPFLAGS= $(PREPROC_FLAGS)
CFLAGS=-O2 -g -Wall -W -I$(INC_XTRA_DIR)
CXXFLAGS=-O2 -g -Wall -W -fpic -std=c++11
# short hand
OBJDIR=obj
Utilities_h = utilities.h GeographicLib/UTMUPS.hpp
utilities.o: utilities.c $(Utilities_h)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
all: $(FINAL_TARGET)
$(FINAL_TARGET): $(OBJ)
$(CC) -g -o $# $^ $(LDFLAGS)
ifneq ($(wildcard ../databases/.),)
cp $# ../
endif
TargetList = $(FINAL_TARGET)
clean:
rm -f $(TargetList) *.o *~
echo Clean done.
The question I want to ask is
When I compile the following project, it say it can't find "#include 'GeographicLib/UTMUPS.h'". in the utilities.h. what should the naming be in this case. My thought is that by adding -I$(INC_XTRA_DIR), or ../include ... it should search for GeographicLib/UTMUPS.h
what about the file that UTMUPS.h is dependent on(in this case Constant.h), what should be the addressing
Edit: I run make at the root directory... maybe that's the reason for the error.
THanks
I found it obscure to use make utility to generate header dependencies makefile for the source file and using this build the library or create executable accordingly.
1)
As suggested in the manual:
http://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html#Automatic-Prerequisites
I tried with the approach mentioned over there (In my case dependency files are present under obj/):
obj/%.d:%.cpp
#set -e; rm -f $#; \
g++ -MM $(CPPFLAGS) ${INC_FLAGS} $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
But this throws a shell error:
/bin/sh: cannot create obj/xyz.d.23030: Directory nonexistent
However obj directory is present, I didn't understand the use of sed command. The manual explains that it replaces any ".obj : .cpp" rule to ".obj .dep : .cpp", But How ?
2)
I also tried the approach mentioned over here :
http://mad-scientist.net/make/autodep.html
obj/%.o : %.c
g++ -MMD ${CPPFLAGS} ${INC_FLAGS} -c $$< -o $$#
#cp obj/$*.d obj/$*.P; \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \
rm -f $*.d
Using this dependency file is generated but following error message is asserted:
"/bin/sh: cannot open obj/%.P: No such file"
sed: -e expression #2, char 4: unterminated `s' command
Again use of sed is not clear.
This becomes more obfuscate ... Here In the second approach if I don't add separate rule to create dependency files and generate them at the time of object creation, As "g++ -MP -MMD -c" creates both .o and .d. But how .o will be compiled again using the dependency makefile which is generated in the same command ?
I appreciate any help in resolving the errors occurred, And helping me in understanding this.
Or Please suggest some elegant approach to do the same.
EDIT : (As suggested in the comment)
In the second approach using both -MMD and -MP it works as expected, But I can't understand how it's working. Here sed comamnd is not required, and source gets rebuild if related header is modified:
obj/%.o : %.c
g++ -MMD -MP ${CPPFLAGS} ${INC_FLAGS} -c $$< -o $$#
But As described in gcc manual page , If I didn't interpreted it wrong -MMD used to generate the dependency(excluding system header) file and -MP used to generate empty rule for each header, But it only modifies the object rule:
i.e.,
obj/%.o obj/%.d : %.cpp (This is what sed is doing as mentioned in GNU make manual)
or something like,
obj/%.o : %.cpp (list of dependent headers for particular .cpp file)
What is the use of following two commands and how it works ?
a)sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#;
b)
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P;
However obj directory is present,
Apparently it isn't. That's the first thing you need to solve.
I didn't understand the use of sed command. The manual explains that it replaces any ".obj : .cpp" rule to ".obj .dep : .cpp", But How ?
The special make variable $* contains the stem that matched the pattern of the target, which will be the part of the target that matches the pattern %
The sed command replaces obj/%.o: with obj.o obj.d:, exactly as the Make manual says. To explain "how" you need to understand sed, but it's not a very complicated sed command.
Using this dependency file is generated but following error message is asserted:
That make recipe has a # character, which means everything after it is a comment, you need to escape it with \#
However, if you're using GCC it's easier to just add -MMD to the normal recipe for generating object files, which will produce the .d files as a side-effect of compilation, so you don't need a separate target for the .d files.
So this is a makefile I wrote for one of my modules at university, you can try using it, when you call make it generates all the files and links all the files without needing to define anything extra in the file. There is a lot of excess stuff here, but I did this quite a while ago, but you can take things out and play around with it to see what you can remove. Hope this helps =)
CC=g++
WARNING_FLAGS=-Wall -Wextra -Weffc++ -Winit-self -Wmissing-include-dirs \
-Wswitch-default -Wswitch-enum -Wunused-parameter -Wstrict-overflow=5 \
-Wfloat-equal -Wshadow -Wc++0x-compat -Wconversion -Wsign-conversion \
-Wmissing-declarations -Wstrict-null-sentinel -Woverloaded-virtual -Wsign-promo\
-Werror -pedantic
FORMATTING_FLAGS=-fno-pretty-templates -fmessage-length=80 -fdiagnostics-show-option
CFLAGS=${WARNING_FLAGS} ${FORMATTING_FLAGS} -g -std=c++0x -pipe -frepo
LDFLAGS=
LDLIBS=-lGL -lGLEW -lglut -lGLU -lX11 -lXi -lm -lpng
TARGET=main
OBJECTS=$(addsuffix .o, $(basename $(shell ls *.C | grep -v Test)))
HEADERS=$(addsuffix .h, $(basename $(shell ls *.h | grep -v Test)))
TEST_LDFLAGS=-lboost_unit_test_framework
TEST_LDLIBS=${LDLIBS}
TEST_TARGET=test
TEST_OBJECTS=$(addsuffix .o, $(basename $(shell ls *.C | grep -v main)))
CLEAN_TARGETS=$(addsuffix .o, $(basename $(shell ls *.C))) ${TARGET} ${TEST_TARGET} *.rpo *.gch makefile.dep
all: ${OBJECTS}
${CC} ${LDFLAGS} ${LDLIBS} $^ -o ${TARGET}
test: ${TEST_OBJECTS}
${CC} ${TEST_LDFLAGS} ${TEST_LDLIBS} $^ -o ${TEST_TARGET}
%.o:
${CC} ${CFLAGS} -c ${LDFLAGS} $< -o $#
Test.o: Test.C Makefile
${CC} -c $< -o $#
clean:
rm ${CLEAN_TARGETS}
makefile.dep: *.[Ch]
for i in *.C; do gcc -std=c++0x -MM "$${i}"; done > $#
include makefile.dep
On OS X Mavericks i am trying to build a project using the following Makefile:
CC=g++
EXECUTABLE=minigi
SRC_DIR=src
INTERM_DIR=obj
INCLUDES=-I $(SRC_DIR) -I /usr/local/Cg/examples/OpenGL/glew/include/
LIBS=-L/usr/local/lang/NVIDIA_GPU_Computing_SDK/sdk/C/common/lib/linux/ -lpng -stdc++ -lGL -lGLU -lGLEW -lSDLmain -lSDL -lgomp
CFLAGS_COMMON=$(INCLUDES)
CFLAGS=$(CFLAGS_COMMON) -O3 -DNDEBUG -fopenmp
#CFLAGS=$(CFLAGS_COMMON) -g -O0 -D_DEBUG
SOURCE_FILES=$(shell find $(SRC_DIR) -iname '*.cpp')
DEP_FILES=$(SOURCE_FILES:$(SRC_DIR)/%.cpp=./$(INTERM_DIR)/%.dep)
OBJ_FILES=$(SOURCE_FILES:$(SRC_DIR)/%.cpp=./$(INTERM_DIR)/%.o)
all: $(EXECUTABLE)
clean:
rm -rf obj $(EXECUTABLE)
.PHONY: clean all
.SUFFIXES:
.SUFFIXES:.o .dep .cpp .h
$(INTERM_DIR)/%.dep: $(SRC_DIR)/%.cpp
mkdir -p `dirname $#`
printf `dirname $#`/ > $#
$(CC) $(CFLAGS_COMMON) $< -MM | sed -r -e 's,^(.*)\.o\s*\:,\1.o $# :,g' >> $#
ifneq ($(MAKECMDGOALS),clean)
-include $(DEP_FILES)
endif
$(INTERM_DIR)/%.o: $(SRC_DIR)/%.cpp
mkdir -p $(INTERM_DIR)
$(CC) $(CFLAGS) -c $< -o $#
$(EXECUTABLE): $(OBJ_FILES)
$(CC) $^ $(LIBS) -o $#
However, when I type make I get the following error:
obj/app/sdl_gl_appliacation.dep:1: *** missing separator. Stop.
The file obj/app/sdl_gl_application.dep looks as follows:
-n obj/app/
As I know very little about makefiles (and did not write the posted one) every help would be appreciated.
P.S.
I modified the line printf dirname $#/ > $# . In the original file there was an echo -n but that is not working on OS X.
Well, let's clean this up a little bit.
The way the dependencies are handled really is ugly, GCC can do it for you automatically.
EXECUTABLE := minigi
SRC_DIR := src
OBJ_DIR := obj
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
OBJ_FILES := $(SRC_FILES:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
DEP_FILES := $(OBJ_FILES:.o=.d)
LDLIBS := -lpng -lstdc++ -lGL -lGLU -lGLEW -lSDLmain -lSDL -lgomp
LDFLAGS := -L/usr/local/lang/NVIDIA_GPU_Computing_SDK/sdk/C/common/lib/linux/
CPPFLAGS := -MMD -MP -DNDEBUG -fopenmp -I $(SRC_DIR) -I /usr/local/Cg/examples/OpenGL/glew/include/
CXXFLAGS := -O3
.PHONY: all clean
all: $(EXECUTABLE)
clean:
$(RM) -r $(OBJ_DIR) $(EXECUTABLE)
$(EXECUTABLE): $(OBJ_FILES)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(OBJ_DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
$(OBJ_DIR):
mkdir $#
ifeq "$(MAKECMDGOALS)" ""
-include $(DEP_FILES)
endif
Some quick notes :
You're using C++, so you should use $(CXX) instead of $(CC) which is used for C code.
Along with this, you should use $(CXXFLAGS) instead of $(CFLAGS).
$(CPPFLAGS) is meant for preprocessor flags (-I, -D, or -fopenmp which is a compile-time flag).
-MMD -MP preprocessor flags will auto-generate dependency files when compiling. Learn more.
$(LDFLAGS) is meant for linker flags such as -L flags.
$(LDLIBS) is meant for linker libs such as -l flags
Avoid using the $(shell ) function since it will be executed every time the variable is expanded when assigned with the = operator instead of the := operator. $(wildcard ) is more suited for the job of listing files.
Some time ago I had a need to create a makefile to work with a lot of small test projects that I was making. The whole scope was to simply compile all .cpp files in its directory, and to sort out object files and dependencies. However, one of those projects finally grew much enough that I'm in need of creating custom subfolders to keep all the code organized.
The problem is that I don't know all that much about makefiles, and the one I made is composed of bits and scraps I found around the internet. I was wondering how would I modify this code to be able to include files from different folders. What I have now is this:
SHELL=/bin/bash
CC=g++
EXECUTABLE=ruletheskies
CFLAGS=-std=c++0x -Wall -pedantic #-I/usr/include/boost_1_51_0/
LDFLAGS=-L./
LIBRARIES=-ljson_linux-gcc-4.6_libmt -lbprinter
WINLIBRARIES=-ljson_mingw_libmt -lbprinter_mingw
WINDEFINES=-DWINVER=0x0400 -D__WIN95__ -D__GNUWIN32__ -DSTRICT -DHAVE_W32API_H -D__WXMSW__ -D__WINDOWS__
WINLDFLAGS=-I./ # $(shell find /usr/include/ -maxdepth 1 -type d | sed 's/^/-I/g') #-L/usr/lib/ -I/usr/include/
WINBASELIBRARIES=-lodbc32 -lwsock32 -lwinspool -lwinmm -lshell32 -lcomctl32 -lctl3d32 -lodbc32 -ladvapi32 -lodbc32 -lwsock32 -lopengl32 -lglu32 -lole32 -loleaut32 -luuid
WINSTATIC=-static-libstdc++ -static-libgcc
WINOPTIONS=--verbose
SOURCES := $(wildcard *.cpp)
HEADERS := $(wildcard *.h)
OBJECTSFOLDER=objects
OBJECTS=$(addprefix $(OBJECTSFOLDER)/, $(SOURCES:.cpp=.o))
DEPFOLDER=dependencies
df=$(DEPFOLDER)/$(*F)
odf=$(OBJECTSFOLDER)/$(*F)
EXEFOLDER=bin
.PHONY : all
# Brute force compiling statement for simple compilation and no .o residual files
all: $(EXEFOLDER)
$(CC) $(CFLAGS) $(LDFLAGS) *.cpp $(LIBRARIES) -o $(EXEFOLDER)/$(EXECUTABLE)
.PHONY: debug
# Compiles using object files in OBJECTSFOLDER, only modified stuff
debug: folders $(SOURCES) $(EXEFOLDER)/$(EXECUTABLE)
.PHONY: windows
# cross-compilation: mingw has to be selected, adds libraries for windows, brute force
windows: $(EXEFOLDER)
$(CC) $(CFLAGS) $(WINDEFINES) $(WINSTATIC) $(LDFLAGS) $(WINLDFLAGS) *.cpp $(LIBRARIES) $(WINLIBRARIES) $(WINBASELIBRARIES) -o $(EXEFOLDER)/$(EXECUTABLE).exe $(WINOPTIONS)
# Final linking of the executable
$(EXEFOLDER)/$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBRARIES) -o $#
# Creation of object files
# ( Actual compilation is only last instruction, the rest is creating dependency header rules )
$(OBJECTSFOLDER)/%.o: %.cpp
#$(CC) -MMD -c $(CFLAGS) -o $# $<
#cp $(odf).d $(df).P; \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(odf).d >> $(df).P; \
rm -f $(odf).d
$(CC) -c $(CFLAGS) $< -o $#
-include $(DEPFOLDER)/*.P
# Creation of folders
.PHONY : folders
folders: $(OBJECTSFOLDER) $(DEPFOLDER) $(EXEFOLDER)
$(OBJECTSFOLDER):
mkdir $#
$(DEPFOLDER):
mkdir $#
$(EXEFOLDER):
mkdir $#
# Cleanup of object files
# ( .PHONY is to avoid calling the rule in case a file named clean exists )
.PHONY : clean
clean:
rm -rf $(OBJECTSFOLDER)
rm -rf $(DEPFOLDER)
I imagine I'll have to modify the SOURCES := $(wildcard *.cpp) line, but how would I include the subdirectories I have to look into, whatever they may be? I'm planning to keep corresponding header and source files together, if that simplifies things.