Makefile doesn't check for updates in header file [duplicate] - c++

This question already has answers here:
How to make Makefile recompile when a header file is changed?
(3 answers)
Closed 3 months ago.
I thought my makefile is pretty good but then I tried to update only a header file and recompile my library, but it doesn't change anything.
How can I make it work and recompile also the code in the h file.
My makefile:
SHELL = /bin/sh
SOURCE_FILES_DIRS = -I./../frmwrk/ -I./../Utils/
CXX = g++
CXXFLAGS = $(SOURCE_FILES_DIRS) -std=c++17 -rdynamic -fPIC -g -Wall
LDFLAGS = -shared
LIBS_DIR = ../../libs/
LIB_NAME = libIni.so
TARGET = $(LIBS_DIR)$(LIB_NAME)
SOURCES = $(shell echo *.cpp)
HEADERS = $(shell echo *.h)
OBJECTS = $(SOURCES:.cpp=.o)
LINK_LIBS = -lFrmwrk -lUtils
PREFIX = $(DESTDIR)/usr/local
BINDIR = $(PREFIX)/bin
all: $(TARGET)
$(TARGET): $(OBJECTS) $(HEADERS)
$(CXX) $(CXXFLAGS) -L$(LIBS_DIR) $(LDFLAGS) -o $(TARGET) $(OBJECTS) $(HEADERS) $(LINK_LIBS)
clean:
rm -f *.o $(TARGET)/*.so
rm -rf $(TARGET)

$(TARGET): $(OBJECTS) $(HEADERS)
[relink command]
This forces only a relink when the header file is changed. make has no idea, whatsoever, which C++ source file includes which header file. make knows only about dependencies explicitly declared in the header file. The only dependency stated here is that $(TARGET), the executable, has a dependency on the header file.
In order to force, for example, main.o to be recompiled when declarations.h are included, because main.cpp #includes declarations.h, you have to be explicit:
main.o: declarations.h
This directs make to rebuild main.o, from main.cpp, whenever declarations.h changes, which is what you want.
Manually tracking which object modules need to be rebuilt due to changes to which header files does not scale. make, of course, has no knowledge about anything C++ related, so you'll have to manually keep track of all the dependencies, manually, but that again doesn't scale.
The solution here is to migrate to some higher level build tools, like GNU autoconf and automake which will write the Makefile for you, complete with a bunch of rules that use compiler flags to dump the dependencies, and update the rules automatically, for you. You can always use the same compiler flags (there are flags that, and build all the scaffolding yourself, without autoconf and automake. But why bother, when autoconf automake will do it for you?

I know that this might be totally late but a quick solution to this would simply be to run a make clean such that you rm (remove command) remove the executables. By doing this I found a quick solution to this sort of problem.

Related

How to avoid forgetting dependencies in make/CMake?

I am new to C++ and am trying to get the hang of build systems like make/CMake. Coming from Go, it seems that there is a constant risk that if you forget to do a little thing, your binaries will become stale. In particular, I can't find a best practice for remembering to keep dependencies/prerequisites updated in make/CMake. I'm hoping I am missing something obvious.
For example, suppose I have a basic makefile that just compiles main.cpp:
CFLAGS = -stdlib=libc++ -std=c++17
main: main.o
clang++ $(CFLAGS) main.o -o main
main.o: main.cpp
clang++ $(CFLAGS) -c main.cpp -o main.o
main.cpp:
#include <iostream>
int main() {
std::cout << "Hello, world\n";
}
So far so good; make works as expected. But suppose I have some other header-only library called cow.cpp:
#include <iostream>
namespace cow {
void moo() {
std::cout << "Moo!\n";
}
}
And I decide to call moo() from within main.cpp via `include "cow.cpp":
#include <iostream>
#include "cow.cpp"
int main() {
std::cout << "Hello, world\n";
cow::moo();
}
However, I forget to update the dependencies for main.o in makefile. This mistake is not revealed during the obvious testing period of running make and rerunning the binary ./main, because the whole cow.cpp library is directly included in main.cpp. So everything seems fine, and Moo! is printed out as expected.
But when I change cow.cpp to print Bark! instead of Moo!, then running make doesn't do anything and now my ./main binary is out of date, and Moo! is still printed from ./main.
I'm very curious to hear how experienced C++ devs avoid this problem with much more complicated codebases. Perhaps if you force yourself to split every file into a header and an implementation file, you'll at least be able to quickly correct all such errors? This doesn't seem bulletproof either; since header files sometimes contain some inline implementations.
My example uses make instead of CMake, but it looks like CMake has the same dependency listing problem in target_link_libraries (though transitivity helps a bit).
As a related question: it seems like the obvious solution is for the build system to just look at the source files and infer dependencies (it can just go one level in and rely on CMake to handle transitivity). Is there a reason this doesn't work? Is there a build system that actually does this, or should I write my own?
Thanks!
First of all you will need to reference the dependencies file in your Makefile.
This can be done with the function
SOURCES := $(wildcard *.cpp)
DEPENDS := $(patsubst %.cpp,%.d,$(SOURCES))
wich will take the name of all *.cpp files and substitute and append the extension *.d to name your dependency.
Then in your code
-include $(DEPENDS)
- tells the Makefile to not complain if the files do not exist. If they exist they will be included and recompile your sources properly according to the dependencies.
Finally the dependencies can be created automatically with the options: -MMD -MP for the rules to create the objects file. Here you can find a complete explanation. What generates the dependencies is MMD; MP is to avoid some errors. If you want to recompile when system libraries are updated use MD instead of MMD.
In your case you can try:
main.o: main.cpp
clang++ $(CFLAGS) -MMD -MP -c main.cpp -o main.o
If you have more files it is better to have a single rule to create object files. Something like:
%.o: %.cpp Makefile
clang++ $(CFLAGS) -MMD -MP -c $< -o $#
You can take a look also at this 2 great answers:
one
two
In your case a more suitable Makefile should look like the following (there might be some errors but let me know):
CXX = clang++
CXXFLAGS = -stdlib=libc++ -std=c++17
WARNING := -Wall -Wextra
PROJDIR := .
SOURCEDIR := $(PROJDIR)/
SOURCES := $(wildcard $(SOURCEDIR)/*.cpp)
OBJDIR := $(PROJDIR)/
OBJECTS := $(patsubst $(SOURCEDIR)/%.cpp,$(OBJDIR)/%.o,$(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.cpp,$(OBJDIR)/%.d,$(SOURCES))
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
all: main
clean:
$(RM) $(OBJECTS) $(DEPENDS) main
# Linking the executable from the object files
main: $(OBJECTS)
$(CXX) $(WARNING) $(CXXFLAGS) $^ -o $#
#include your dependencies
-include $(DEPENDS)
#create OBJDIR if not existin (you should not need this)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.cpp Makefile | $(OBJDIR)
$(CXX) $(WARNING) $(CXXFLAGS) -MMD -MP -c $< -o $#
EDIT to answer comments
As another question, is there any problem with rewriting the DEPENDS definition as just DEPENDS := $(wildcard $(OBJDIR)/*.d)?
Nice question, it took me a while to see your point
From here
$(wildcard pattern…) This string, used anywhere in a makefile, is
replaced by a space-separated list of names of existing files that
match one of the given file name patterns. If no existing file name
matches a pattern, then that pattern is omitted from the output of the
wildcard function.
So wildcard return a list of the file names matching the pattern. patsubst acts on strings, it does not care about what are those strings: it is used as a way to create the file names of the dependencies, not the files themselves. In the Makefile example that I posted DEPENDS is actually use in two cases: when cleaning with make clean and with include so in this case they both work because you are not using DEPENDS in any rule. There are some differences (I tried to run and you should too to confirm). With DEPENDS := $(patsubst $(SOURCEDIR)/%.cpp,$(OBJDIR)/%.d,$(SOURCES)) if you run make clean dependencies *.d that do not have a correspondent *.cpp file will not be removed while they will with your change. On the contrary you might include dependencies not relevant to your *.cpp file.
I asked this questions: let's see the answers.
If the .d files get deleted from carelessness but the .o files remain, then we are in trouble. In the original example, if main.d is deleted and then cow.cpp is subsequently changed, make won't realize it needs to recompile main.o and thus it will never recreate the dependency file. Is there a way to cheaply create the .d files without recompiling the object files? If so then we could probably recreate all the /.d files on every make command?
Nice question again.
Yes, you are right. Actually it was an error of mine. This happens because of the rule
main: main.o
$(CXX) $(WARNING) $(CFLAGS) main.o -o main
actually should have been:
main: $(OBJECTS)
$(CXX) $(WARNING) $(CXXFLAGS) $^ -o $#
so that it got relinked (the executable is updated) whenever one of the objects change and they will change whenever one their cpp file change.
One problem remains: if you delete your dependencies but not the objects, and change only one or more header files (but not the sources) then your program is not updated.
I corrected also the previous part of the answer.
EDIT 2
To create the dependencies you can also add a new rule to your Makefile:
here is an example.

How to write simple generic build script for C++ project?

I'm writing C++ project made of few files on Linux. The project have no subdirectories.
I wanted like to have some as simple as possible, generic build script.
By generic, I mean that I don't want to hardcode file names, so that when I put new .cpp file into project, I don't have to modify build script. It should find and compile all modyfied source files in current directory, and link object files into executable. Nothing more.
I don't care about tool you'll use, since I don't know any yet.
I don't want to learn a tool from basics to write something as simple as that. For now, I just need a code, I'll learn when I'll need something more fancy.
What I tryed
make:
a.out: %.o
$(CXX) %.o
%.o: %.cpp
$(CXX) -Wall -c %.cpp
with no success:
make: *** Brak reguł do zrobienia obiektu `%.o', wymaganego przez `a.out'. Stop.
my translation of this message:
make: *** No rules to make object `%.o', required by `a.out'. Stop.
Before someone will ask, I'll answer: yes, my makefile is indented with 1 tab, not with spaces.
make -d prints out 664 lines, so I won't paste it here.
scons:
Program("main.cpp")
It's copyed from some StackOverflow answer, but it is definietly intended to build a executable from one source file, because I get linker errors when I want use it.
I ended us using bash:
g++ -Wall *.cpp
Simple. Does the job well... for now. I don't think it's elegant and I know it's probably inefficent, because it recompiles everything, even unmodyfied files.
I guess that you have a directory full of single-source C++ programs (e.g. each program has one single C++ source file) named .cpp (e.g. foo.cpp & bar.cpp), each independently compiled to an executable (e.g. foo & bar). You might try the following (untested) Makefile for GNU make.
CXX= g++
CXXFLAGS= -Wall -Wextra -g -O
RM= rm -vf
SOURCES= $(wildcard *.cpp)
BINARIES= $(patsubst %.cpp, %, $(SOURCES))
.PHONY: all clean
all: $(BINARIES)
clean:
$(RM) *~ *.o $(BINARIES)
Read the documentation of GNU make and try make -p to find the builtin rules. See also these two examples of Makefile-s: this & that
If on the contrary you want one single executable myprogram from all the *.cpp files (like foo.cpp & bar.cpp etc....), you still can use $(wildcard *.cpp) in your Makefile (and you'll better not name a.out your executable, but something more meaningful), something like (in addition of common stuff like CXXFLAGS= above):
SOURCES= $(wildcard *.cpp)
OBJECTS= $(patsubst %.cpp, %.o, $(SOURCES))
all: myprogram
myprogram: $(OBJECTS)
$(LINK.cc) $^ -o $# $(LIBES)
In all cases, using $(wildcard *.cpp) is enough to have a Makefile generic enough on the list of sources. You may want to generate autodependencies (using gcc -M things, to some of your header files), see this.
Notice that you might have some C++ source or header files generated by some other means (e.g. your own awk or python script, or a _timestamp.c file generated with date, or some C++ files produced by a code generator like GNU bison or gperf, etc, etc...). Then you need to add specific rules into your Makefile.
So in practice, I don't believe in fully generic build files, but I am trying to show you that a Makefile can be almost generic and short. At some time you'll adapt it to your particular needs.
SRC := $(wildcard src/*.c)
DEP := $(SRC:src/%.c=lib/%.d)
OBJ := $(SRC:src/%.c=lib/%.o)
CFLAGS := -Wall -Wextra -O2 -MMD
# Executable
lib/mines: lib/assets.o $(OBJ)
${CC} $^ -o $#
# Object files
lib/%.o:: src/%.c
${CC} -c $< -o $# ${CFLAGS}
# Dependencies
# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
-include $(DEP)
.PHONY: clean
clean:
rm lib/*

How to make */* for many folders of self-contained cpp files?

I'm playing around some tutorial code from this OpenCV 2 Cookbook. The code doesn't come with any Makefiles, and I'd like to create a Makefile that can Make all of the files in the codebase. My plan is to compile all the files with profiling, and then make a script that runs all the executables and collects the gprof results. Then, I can get some intuition for the computation time of various OpenCV functions.
The codebase is arranged like this: tutorial_code/Chapter[1-10]/*.cpp
Each .cpp file is self-sufficient and can be compiled without linking against other modules in this codebase. (There are a few small header-only libraries, though.)
Here are a couple things that I'm stuck up on:
Typically, the $(EXEC) in a Makefile represents a file that is the culmination of much of the building effort. However, in my case, I want to create a separate $(EXEC) for each .cpp file. I think I'm close to getting this right, but so far my Makefile just generates *.o but not *.out
I understand that SOURCES = $(wildcard *.cpp) is a way to "collect" the set of cpp files in the current directory. It would make sense that SOURCES = $(wildcard */*.cpp) would drill down and grab all .cpp files in the subdirectories. It doesn't seem to work, though.
Starting from this tutorial, I set up a Makefile that implements the proposed functionality. It doesn't quite work... $(wildcard */*.cpp) doesn't seem to drill down into directories, and I'm not sure how to do something like $< and $# to refer to basefilename.o and to create basefilename.out.
CC = g++
CC_FLAGS = -w `pkg-config opencv --cflags`
LINK = g++
LINKOPTS = -pg `pkg-config opencv --libs`
SOURCES = $(wildcard */*.cpp)
OBJECTS = $(SOURCES:.cpp=.o)
EXEC = $(SOURCES:.cpp=.out)
%.out: %.o
$(LINK) $< $(LINKOPTS) -o $#
%.o: %.cpp
$(CC) -c $(CC_FLAGS) $< -o $#
clean:
rm -f $(EXEC) $(OBJECTS)
I'm fairly familiar with Makefiles and OpenCV, and I haven't had a problem compiling my own projects by hand-coding the lists of dependencies, objects, etc in Makefiles. However, for the matter at hand, it'd be fantastic to just automatically make everything without much user intervention.
Feel free to comment, email, or message me for a copy of the codebase that I'm trying to compile.
I've also thought of making a script that iterates through the tutorial_code/Chapter[1-10] directories and creates one Makefile for each directory. Then, I'd make an other function in the script to call Make once in each directory. The idea of doing one grand Makefile sounds like more fun, though.
EDIT: This does work if I use SOURCES = $(wildcard *.cpp) and place the Makefile in the same directory where cpp files are located. However, I'm still trying to figure out how to have $(wildcard */*.cpp) drill down into subdirectories.
EDIT 2: The Makefile shown above now works properly. To see the earlier version, feel free to scroll through the edit history.
You can write a version of wildcard that works recursively to any depth using only make functions:
find-recursive = \
$(wildcard $1/$2) \
$(foreach f,$(wildcard $1/*/.),\
$(call find-recursive,$(patsubst %/.,%,$f),$2))
SOURCES = $(call find-recursive,.,*.cpp)

Simple makefile generation utility?

Does anyone know of a tool that generates a makefile by scanning a directory for source files?
It may be naive:
no need to detect external dependencies
use default compiler/linker settings
You can write a Makefile that does this for you:
SOURCES=$(shell find . -name "*.cpp")
OBJECTS=$(SOURCES:%.cpp=%.o)
TARGET=foo
.PHONY: all
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $#
.PHONY: clean
clean:
rm -f $(TARGET) $(OBJECTS)
Just place this in root directory of your source hierarchy and run make (you'll need GNU Make for this to work).
(Note that I'm not fluent in Makefileish so maybe this can be done easier.)
CMake does it and it even creates makefiles and Visual Studio projects. http://www.cmake.org/
All you need to do is creating a CMakeLists.txt file containing the follwing lines:
file(GLOB sources *.h *.c *.cxx *.cpp *.hxx)
add_executable(Foo ${sources})
Then go into a clean directory and type:
cmake /path/to/project/
That will create makefiles on that clean build directory.
This is what I would use for a simple project:
CC = $(CXX)
CXXFLAGS += -ansi -pedantic -W -Wall -Werror
CPPFLAGS += -I<Dir Where Boost Lives>
SOURCES = $(wildcard *.cpp)
OBJECTS = $(patsubst %.cpp,%.o,$(SOURCES))
all: myApp
myApp: $(OBJECTS)
The only restriction is that if you are building an executable called myApp. Then one of the source files should be named myApp.cpp (which is where I put main).
There's a very old script called 'makedepend' that used to make very simple makefiles. I've since switched over to cmake for almost everything.
Here's the wiki article http://en.wikipedia.org/wiki/Makedepend, note the list of Alternatives at the bottom including depcomp in automake, and the -M flag in gcc.
EDIT: As someone pointed out to me in another question, gcc -MM *.cpp > Makefile produces a rather nice simple makefile. You only have to prepend your CPPFLAGS and a rule for constructing the entire binary... which will take the form:
CPPFLAGS=-Wall
LDFLAGS=-lm
all: binary_name
binary_name: foo.o bar.o baz.o biff.o
no need to detect external dependencies
use default compiler/linker settings
Why script then? Provided that all your project source files are *.cpp and in current directory:
all: $(notdir $(CURDIR))
$(notdir $(CURDIR)): $(subst .cpp,.o,$(wildcard *.cpp))
$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $#
The Makefile would build the all the source files with default compiler/linker settings into an executable named after the name of the current directory.
Otherwise, I generally recommend people to try SCons instead of make where it is much simpler and intuitive. Added bonus that there is no need to code manually clean targets, source/header dependency checking is built-in, it is natively recursive and supports properly libraries.
As described in the linked discussion, HWUT is a tool that
can generate pretty Makefiles, searching for dependencies and include files in directories that you tell it. On windows you need to install MinGW and Ctags. Under Linux gcc and ctags are most likely present. It is OpenSource and free to use.
Especially, when generating Unit Tests for some already existing modules of some larger project with bad cohesion, this feautures easily spares you hours or even days.

minimum c++ make file for linux

I've looking to find a simple recommended "minimal" c++ makefile for linux which will use g++ to compile and link a single file and h file. Ideally the make file will not even have the physical file names in it and only have a .cpp to .o transform. What is the best way to generate such a makefile without diving into the horrors of autoconf?
The current dir contains, for example
t.cpp
t.h
and I want a makefile for that to be created. I tried autoconf but its assuming .h is gcc instead of g++. Yes, while not a beginner, I am relearning from years ago best approaches to project manipulation and hence am looking for automated ways to create and maintain makefiles for small projects.
If it is a single file, you can type
make t
And it will invoke
g++ t.cpp -o t
This doesn't even require a Makefile in the directory, although it will get confused if you have a t.cpp and a t.c and a t.java, etc etc.
Also a real Makefile:
SOURCES := t.cpp
# Objs are all the sources, with .cpp replaced by .o
OBJS := $(SOURCES:.cpp=.o)
all: t
# Compile the binary 't' by calling the compiler with cflags, lflags, and any libs (if defined) and the list of objects.
t: $(OBJS)
$(CC) $(CFLAGS) -o t $(OBJS) $(LFLAGS) $(LIBS)
# Get a .o from a .cpp by calling compiler with cflags and includes (if defined)
.cpp.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $<
Here is a generic makefile from my code snippets directory:
SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
DEPS=$(SOURCES:.cpp=.d)
BINS=$(SOURCES:.cpp=)
CFLAGS+=-MMD
CXXFLAGS+=-MMD
all: $(BINS)
.PHONY: clean
clean:
$(RM) $(OBJECTS) $(DEPS) $(BINS)
-include $(DEPS)
As long as you have one .cpp source producing one binary, you don't need anything more. I have only used it with GNU make, and the dependency generation uses gcc syntax (also supported by icc). If you are using the SUN compilers, you need to change "-MMD" to "-xMMD". Also, ensure that the tab on the start of the line after clean: does not get changed to spaces when you paste this code or make will give you a missing separator error.
Have you looked at SCons?
Simply create a SConstruct file with the following:
Program("t.cpp")
Then type:
scons
Done!
Assuming no preconfigured system-wide make settings:
CXX = g++
CPPFLAGS = # put pre-processor settings (-I, -D, etc) here
CXXFLAGS = -Wall # put compiler settings here
LDFLAGS = # put linker settings here
test: test.o
$(CXX) -o $# $(CXXFLAGS) $(LDFLAGS) test.o
.cpp.o:
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
test.cpp: test.h
a fairly small GNU Makefile, using predefined rules and auto-deps:
CC=c++
CXXFLAGS=-g -Wall -Wextra -MMD
LDLIBS=-lm
program: program.o sub.o
clean:
$(RM) *.o *.d program
-include $(wildcard *.d)
Have you looked at OMake ?
OMakeroot
open build/C
DefineCommandVars()
.SUBDIRS: .
OMakefile
.DEFAULT: $(CXXProgram test, test)
Then on Linux or Windows, simply type:
omake
As a bonus, you automatically get:
parallel builds with the -j option (same as make).
MD5 checksums instead of timestamps (build becomes resilient to time synchronization failures).
Automatic and accurate C/C++ header dependencies.
Accurate inter-directory dependencies (something that recursive make does not offer).
Portability (1 build chain to rule them all, immune to path style issues).
A real programming language (better than GNU make).
Some good references on creating a basic Makefile
http://en.wikipedia.org/wiki/Make_(software)
http://mrbook.org/tutorials/make/
http://www.opussoftware.com/tutorial/TutMakefile.htm
http://www.hsrl.rutgers.edu/ug/make_help.html
The first couple in particular have minimal example Makefiles like you were describing. Hope that helps.
SConstruct with debug option:
env = Environment()
if ARGUMENTS.get('debug', 0):
env.Append(CCFLAGS = ' -g')
env.Program( source = "template.cpp" )
florin has a good starting point. I didn't like gnu autoconf so I started there and took the concept further and called it the MagicMakefile. I have 3 versions of it from simple to more complex. The latest is now on github: https://github.com/jdkoftinoff/magicmake
Basically, it assumes you have a standard layout for the source files of your project and uses the wildcard function to create the makefile rules on the fly which are then eval'd, handling header file dependancies, cross compiling, unit tests, install, and packaging.
[edit] At this point I use cmake for all my projects since it generates useful project files for many build systems.
jeff koftinoff
I was hunting around for what a minimal Makefile might look like other than
some_stuff:
#echo "Hello World"
I know I am late for this party, but I thought I would toss my hat into the ring as well. The following is my one directory project Makefile I have used for years. With a little modification it scales to use multiple directories (e.g. src, obj, bin, header, test, etc). Assumes all headers and source files are in the current directory. And, have to give the project a name which is used for the output binary name.
NAME = my_project
FILES = $(shell basename -a $$(ls *.cpp) | sed 's/\.cpp//g')
SRC = $(patsubst %, %.cpp, $(FILES))
OBJ = $(patsubst %, %.o, $(FILES))
HDR = $(patsubst %, -include %.h, $(FILES))
CXX = g++ -Wall
%.o : %.cpp
$(CXX) $(HDR) -c -o $# $<
build: $(OBJ)
$(CXX) -o $(NAME) $(OBJ)
clean:
rm -vf $(NAME) $(OBJ)
If your issues are because autoconf thinks the .h file is a c file, try renaming it to .hpp or .h++