I recently lost 5 hours to figure out how I could write the makefile I need. I'm not an informaticien or programmer so I'd like some comments on what I managed to do. I already looked a lot on different sites but still...
I need a makefile that creates different executables: prog1, prog2...
To create the .o files, as I have many files with many dependencies, I don't want to specify them all. So I want/need to use automatic variables with a pattern rule. To speed up the compilation I also take care to only recompile the modified files. I achieved this by using the -MD flag that creates a .d file saved in the $(BUILD) directory.
What I still can't do is to detect automatically which .o files prog1 needs. So for now I have to specify them automatically... If you know how to do that automatically...
I also would like to save the .o files in the $(BUILD) directory, but I can't make it work.
Any advice are welcome !
Thx
CXX = g++
ERRORS = -Wall -Wextra -pedantic
LAPACK = -llapack -lblas
OPTION = -O3 -fopenmp
CXXFLAGS = $(LAPACK) $(ERRORS) $(OPTION)
LDFLAGS = $(LAPACK) $(ERRORS) $(OPTION)
BUILD=build
SRCS=(wildcard *.cpp)
all:prog1 prog2 ...
prog1:prog1.o dep_only_for_prog_1.o dep_for_all_progs.o dep_for_some_progs.o
$(CXX) -o $# $^ $(LDFLAGS) $(NOASSERT)
prog2:prog2.o dep_only_for_prog_2.o dep_for_all_progs.o dep_for_some_progs.o
$(CXX) -o $# $^ $(LDFLAGS) $(NOASSERT)
...
%.o:%.cpp
$(CXX) -MD -c $(CXXFLAGS) $(NOASSERT) $< -o $#
mv $(<:.cpp=.d) $(BUILD)
-include $(addprefix $(BUILD)/$(SRCS:.cpp=.d))
clean:
rm -f *.o $(BUILD)/*
You just can't get make to infer somehow which files belong to which programs, but you CAN make your makefile simpler to read and update. Also you have a few bad things here, such as adding $(LAPACK) (which contains linker flags) to $(CXXFLAGS) (which are passed to the compiler).
Try:
PROGRAMS = prog1 prog2
prog1_SOURCES = prog1.cpp dep_only_for_prog_1.cpp \
dep_for_all_progs.cpp dep_for_some_progs.cpp
prog2_SOURCES = prog2.cpp dep_only_for_prog_2.cpp \
dep_for_all_progs.cpp dep_for_some_progs.cpp
#----- Don't need to change below here
CXX = g++
ERRORS = -Wall -Wextra -pedantic
LAPACK = -llapack -lblas
OPTION = -O3 -fopenmp
CXXFLAGS = $(ERRORS) $(OPTION)
LDFLAGS = $(LAPACK) $(ERRORS) $(OPTION)
BUILD=build
SRCS := $(wildcard *.cpp)
all: $(PROGRAMS)
.SECONDEXPANSION:
$(PROGRAMS): $$($$#_SOURCES:%.cpp=%.o)
$(CXX) -o $# $^ $(LDFLAGS) $(NOASSERT)
%.o : %.cpp
$(CXX) -MD -c $(CXXFLAGS) $(NOASSERT) $< -o $#
mv $(<:.cpp=.d) $(BUILD)
-include $(addprefix $(BUILD)/$(SRCS:.cpp=.d))
clean:
rm -f *.o $(BUILD)/*
Or you can use eval if you want.
Related
I'm new on using Makefiles because I've been programming with VS2019 on Windows, solving all my compilation and linking problems.
This is the result:
BUILD_DIR:= ./build
SRC_DIRS := ./src
INCL_DIR := ./includes
CC := /usr/bin/g++ #Compiler used
LVERSION := -std=c++17 #Language Version
CXXFLAGS := -g #Cpp flags
CFLAGS := -Wall #Compiler Flags
LFLAGS := -lstdc++fs #Linker Flags
SRCS := Audio.cpp Song.cpp Visual.cpp VisualSong.cpp
LIBS :=
INCLUDES := $(SRCS:%.cpp=$(INCL_DIR)/%.h)
OBJS := $(SRCS:%.cpp=$(BUILD_DIR)/%.o)
PROG := progName.exe
progName: $(OBJS)
$(CC) $(CFLAGS) $(CXXFLAGS) -o $(INCLUDES) $(PROG) $(OBJS)
$(BUILD_DIR)/%.o: $(INCL_DIR)/%.h $(SRC_DIRS)/%.cpp
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $^
.PHONY: progName
clean:
/bin/rm -rf build/*.o $(PROG) includes/*.gch
This makefile works until is trying to look on objects file, supposedly created on build directory but, in the end, they're created in Makefile's directory, which is an inconvenient since all what i want is to have separated files for organization purposes.
I know that somehow using implicit rules that are using the dst's directory should do the trick, but i think that I'm missing something on the way...
I'm on a Windows 10 machine with WSL for Ubuntu, but this shouldn't be a problem at all for this problem.
Could anyone explain to me what am I missing?
Look at this rule:
$(BUILD_DIR)/%.o: $(INCL_DIR)/%.h $(SRC_DIRS)/%.cpp
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $^
Ostensibly it is the rule to build build/foo.o, but the recipe ($(CC)...) actually builds foo.o. There is an easy fix:
$(BUILD_DIR)/%.o: $(INCL_DIR)/%.h $(SRC_DIRS)/%.cpp
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $^ -o $#
Once that works I suggest you make one further change:
$(BUILD_DIR)/%.o: $(SRC_DIRS)/%.cpp $(INCL_DIR)/%.h
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $< -o $#
I have multiple source files in a directory, which some are responsible for a main executable, and some are responsible for a shared library, which then in turn is needed for the main executable. Thus I wrote the makefile in the following way:
CC=gcc
CXX=g++
CFLAGS=-I$(DIR) -fPIC -c -fopenmp
CXXLFLAGS=-I$(DIR) -fopenmp -O3 -g -march=native -std=gnu++17 -fPIC -c
CXXFLAGS=-I$(DIR) -fopenmp -O3 -g -march=native -std=gnu++17 -c
LDFLAGS=-lfftw3 -lgomp -lm -larmadillo -lpthread -lX11 -lboost_system -lboost_program_options -L/opt/intel/mkl/lib/intel64 -lmkl_rt
LDMAINFLAGS=-lfftw3 -lgomp -lm -larmadillo -lpthread -lX11 -lboost_system -lboost_program_options -L/opt/intel/mkl/lib/intel64 -lmkl_rt -lpulse_propagation
LIBSOURCES=source/image_processing.cpp source/pulse_propagation.cpp
LIBOBJECTS=source/image_processing.o source/pulse_propagation.o
MAINSOURCES=source/fftw.cpp source/fftw++.cc
MAINOBJECTS=source/fftw.o source/fftw++.o
EXECUTABLE=fftw
LIBRARY=libpulse_propagation.so
.PHONY: default all clean
default: all
all: $(LIBRARY) main
main: $(LIBRARY) $(MAINOBJECTS)
$(CXX) $(LDFLAGS) $(MAINOBJECTS) -o $(EXECUTABLE)
$(LIBRARY): $(LIBOBJECTS)
$(CXX) $(LDFLAGS) -shared $^ -o $#
$(LIBOBJECTS): $(LIBSOURCES)
$(CXX) $(CXXLFLAGS) $^ -o $#
$(MAINOBJECTS): $(MAINSOURCES)
$(CXX) $(CXXFLAGS) $^ -o $#
clean_compile:
rm -f source/*.o
clean:
rm -f source/*.o $(EXECUTABLE) $(LIBRARY)
with everything labeled with a MAIN belonging to the main executable and everything else to the library. I would like to loop over the files in LIBSOURCES/MAINSOURCES and compile each of them. I would prefer if I do not have to use the .cpp.o:-macro, after there are different flags depending if it is a library file or a main file. I tried using $<, which executed the compilation twice (ok), but always used the first value from the variable list. When using $^ instead, both files are used at once, also resulting in an error. How could I else do that?
Your source/fftw++.cc instead of source/fftw++.cpp makes everything uselessly complex. If you can rename it, then the following should do what you want:
$(LIBOBJECTS): CXXFLAGS := $(CXXLFLAGS)
$(LIBOBJECTS) $(MAINOBJECTS): %.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
The first line defines the value of variable CXXFLAGS for the $(LIBOBJECTS) targets. The following rule is a static pattern rule that translates into as many rules with one target and one prerequisite only. It is completely different from your rules that declares all source files of one kind as prerequisites of all corresponding object files. Not what you want normally.
If you cannot rename source/fftw++.cc you can split your sources and objects lists:
MAINCPPSOURCES=source/fftw.cpp
MAINCCSOURCES=source/fftw++.cc
MAINCPPOBJECTS=source/fftw.o
MAINCCOBJECTS=source/fftw++.o
$(LIBOBJECTS): CXXFLAGS := $(CXXLFLAGS)
$(LIBOBJECTS) $(MAINCPPOBJECTS): %.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
$(MAINCCOBJECTS): %.o: %.cc
$(CXX) $(CXXFLAGS) $< -o $#
Finally, it would probably be better (easier to maintain) if you were computing what can be, instead of hard-wiring it in your Makefile:
MAINCPPOBJECTS = $(patsubst %.cpp,%.o,$(MAINCPPSOURCES))
MAINCCOBJECTS = $(patsubst %.cc,%.o,$(MAINCCSOURCES))
...
I have a makefile for my program but I got everything recompiled every time I run it, even if I modify nothing.
Every time I run make it recompiles simHwIntf.cpp showHelp.cpp and sendFromFile.cpp
This is my make file:
IDIR = inc
LDIR = -L/usr/lib/x86_64-linux-gnu/
SDIR = src
ODIR = obj
BINDIR = bin
LDLIBS = -luhd
OBJ = $(patsubst %,$(ODIR)/%,$(O_FILES))
CC = g++
CFLAGS = -Wall -std=c++11 -I $(IDIR) #-Werror
BINARIES= main
C_FILES = simHwIntf.cpp showHelp.cpp sendFromFile.cpp
H_FILES = simHwIntf.h
O_FILES = $(C_FILES:.cpp=.o)
all: $(BINARIES)
#echo "Make file executed"
$(BINARIES): $(O_FILES)
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(OBJ) $(LDIR) $(LDLIBS)
fileCreator: fileCreator.o
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(ODIR)/fileCreator.o
fileHandler: fileHandler.o
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(ODIR)/fileHandler.o
backYard: backYard.o
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(ODIR)/backYard.o
%.o: $(SDIR)/%.cpp $(IDIR)/$(H_FILES)
$(CC) $(CFLAGS) -c -o $(ODIR)/$# $<
clean:
-rm -rf $(ODIR)/*.o *~
distclean: clean
-rm -rf $(BINDIR)/*
Each time the output in the shell is:
g++ -Wall -std=c++11 -I inc -c -o obj/simHwIntf.o src/simHwIntf.cpp
g++ -Wall -std=c++11 -I inc -c -o obj/showHelp.o src/showHelp.cpp
g++ -Wall -std=c++11 -I inc -c -o obj/sendFromFile.o src/sendFromFile.cpp
g++ -Wall -std=c++11 -I inc -o bin/main obj/simHwIntf.o obj/showHelp.o obj/sendFromFile.o -L/usr/lib/x86_64-linux-gnu/ -luhd
Make file executed
I've already search and read this: (How do I make Makefile to recompile only changed files?) but didn't help much.
Anybody that could give me a hand with this ?
I have a doubt with the directories, maybe one or several directories are re-created each time I run make and this causes everything inside to look like new to the compiler.
Thanks
You can see what triggered the build by echoing the dependencies that changed. Add this to your %.o target :
#echo [triggered by changes in $?]
You should also use the VPATH special variable instead of specifying the sources path in your %.o target. See GNU make VPATH documentation
Please try replacing
%.o: $(SDIR)/%.cpp $(IDIR)/$(H_FILES)
$(CC) $(CFLAGS) -c -o $(ODIR)/$# $<
with
$(ODIR)/%.o: $(SDIR)/%.cpp $(IDIR)/$(H_FILES)
$(CC) $(CFLAGS) -c -o $(ODIR)/$# $<
Directories matter when you define targets.
If a define a rule
myexec: objdir/myexec.o
$(CC) $(CFLAGS) -o bindir/myexec objdir/myexec.o $(LDFLAGS)
Make believes that that this would create the file myexec in the working directory. When you rerun make the target myexec wasn't found, so it will be created again. Add the paths in the targets and it should work.
Try replacing
BINARIES= main
with
BINARIES= $(BINDIR)/main
and the rule
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(OBJ) $(LDIR) $(LDLIBS)
with
$(CC) $(CFLAGS) -o $# $^ $(LDIR) $(LDLIBS)
And change the other rules similarly.
Note, in general it is a bad idea to use $# in combination with a path when creating the target in some rule (as in $(BINDIR)/$#), because this will never create the actual target file. A bare $# should be sufficient.
I'm trying to compile a simple program from the terminal that utilizes the condition_variable class. Upon building, I get the following error:
This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
In researching this error here, I added the necessary flag to my make file, but I'm still getting the same error.
Here is my makefile:
CXX= g++ $(CCFLAGS)
MAIN= main.o
DATACLASS= dataclass.o
OBJS = $(MAIN) $(DATACLASS)
LIBS= -pthread
CCFLAGS= -g -std=c++11
all: main
main: $(MAIN) $(DATACLASS)
$(CXX) -o main $(MAIN) $(DATACLASS) $(LIBS)
dataclass: $(DATACLASS)
$(CXX) -o dataclass $(DATACLASS) $(LIBS)
clean:
rm -f $(OBJS) $(OBJS:.o=.d)
realclean:
rm -f $(OBJS) $(OBJS:.o=.d) main
%.d: %.cc
$(SHELL) -ec '$(CC) -M $(CPPFLAGS) $< \
| sed '\''s/\($*\)\.o[ :]*/\1.o $# : /g'\'' > $#; \
[ -s $# ] || rm -f $#'
include $(OBJS:.o=.d)
I'm sure I'm missing something small and stupid as I'm new to makefiles, but any help would be greatly appreciated.
Rewrite CXX to CXX = g++
Change CCFLAGS to CXXFLAGS = -g -std=c++11, and
Rewrite your rules to $(CXX) $(CXXFLAGS) ....
$(CXX) $(CXXFLAGS) will then be replaced with g++ -g -std=c++11. This is more of a standard method for defining a makefile. Here is a snippet of the resulting makefile.
CXX = g++
MAIN = main.o
DATACLASS = dataclass.o
OBJS = $(MAIN) $(DATACLASS)
LIBS = -pthread
CXXFLAGS = -g -std=c++11
all: main
main: $(OBJS)
$(CXX) $(CXXFLAGS) $? -o $# $(LIBS)
As a side note, are you sure this rule should be defined as such?
dataclass: $(DATACLASS)
$(CXX) $(CXXFLAGS) $? -o $# $(LIBS)
Should the target not be dataclass.o or $(DATACLASS) and the prerequisite some other file?
Note: I've also included some make automatic variables to tidy up the makefile rules.
$? - is replaced by all prerequisites
$# - is replaced by the target name
Help me with makefile, please. I want `make' to recompile only files that have been changed. Here is my makefile:
ROOT_DIR= ..
BUILD_TYPE= Release
BUILD_DIR= $(ROOT_DIR)/$(BUILD_TYPE)
O_DIR= $(BUILD_DIR)/obj
TARGETS= ftp_auto_backup sftp_auto_backup
CXX= g++
CXXFLAGS= -DBOOST_THREAD_USE_LIB -O3 -Wall -fmessage-length=0
FTP_LDFLAGS= -static-libstdc++ -static-libgcc -s -L $(ROOT_DIR)/lib/Release -l:libboost_thread-mgw46-mt-1_49.a -l:libcommon.a \
-l:libfile.a -l:libfilesearcher.a -l:libftpclient.a -l:libftplib.a -l:libdbclient.a -l:libsqlite3.a -l:libscheduler.a -l:libws2_32.a
SFTP_LDFLAGS= -static-libstdc++ -static-libgcc -s -L $(ROOT_DIR)/lib/Release -l:libboost_thread-mgw46-mt-1_49.a -l:libcommon.a \
-l:libfile.a -l:libfilesearcher.a -l:libdbclient.a -l:libsqlite3.a -l:libscheduler.a -l:libsftpclient.a -l:libws2_32.a -l:libssh.dll
OBJECTS= appconfig.o backuplauncher.o clientbackup.o main.o
LD_OBJECTS= $(addprefix $(O_DIR)/,$(OBJECTS))
all: init $(TARGETS)
debug: CXXFLAGS= -O0 -g3 -Wall -fmessage-length=0
debug: BUILD_TYPE= Debug
debug: all
init:
#mkdir -p $(BUILD_DIR)
#mkdir -p $(O_DIR)
ftp_auto_backup: set_type_ftp $(OBJECTS)
$(CXX) -o $(BUILD_DIR)/$#.exe $(LD_OBJECTS) $(FTP_LDFLAGS)
sftp_auto_backup: set_type_sftp $(OBJECTS)
$(CXX) -o $(BUILD_DIR)/$#.exe $(LD_OBJECTS) $(SFTP_LDFLAGS)
set_type_ftp:
$(eval CXXFLAGS+=-DPROJECT_TYPE=FTP)
set_type_sftp:
$(eval CXXFLAGS+=-DPROJECT_TYPE=SFTP)
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $(O_DIR)/$#
clean:
rm -rf $(addprefix $(ROOT_DIR)/Release/obj/,$(OBJECTS)) $(addprefix $(ROOT_DIR)/Debug/obj/,$(OBJECTS))
rm -rf $(addprefix $(ROOT_DIR)/Release/,$(addsuffix .exe,$(TARGETS))) $(addprefix $(ROOT_DIR)/Debug/,$(addsuffix .exe,$(TARGETS)))
Yes, I know about Generating Prerequisites Automatically, but should I really use it?
Thanks in advance!
Your targets depend on objects in the current directory, not in obj/. Change to this:
ftp_auto_backup: set_type_ftp $(LD_OBJECTS)
$(CXX) -o $(BUILD_DIR)/$#.exe $(LD_OBJECTS) $(FTP_LDFLAGS)
sftp_auto_backup: set_type_sftp $(LD_OBJECTS)
$(CXX) -o $(BUILD_DIR)/$#.exe $(LD_OBJECTS) $(SFTP_LDFLAGS)
# (...)
$(O_DIR)/%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $#
And yes, if you want your object files to recompile not only when you change the .cpp file, but also when you change the header (.h) files, you need to generate those prerequisites...
I suppose that %.o : %.cpp is not enough, you should use VPATH to let know make where the sources are:
vpath %.cpp src