make: invalidate object file when dependency is missing - makefile

I have a situation where I've refactored some code, and moved an include file.
Attempting to build the source tree yields an error:
make: *** No rule to make target `cmd/dispatcher.h', \
needed by `/tmp/test/dispatcher/main.o'. Stop.
If I do a make clean (which removes the outdated main.o file), and then rebuild I get a different error:
...src/test/dispatcher/main.cpp:3:28: fatal error: cmd/dispatcher.h: \
No such file or directory
Question:
Is there any way to invalidate main.o when one of its dependencies is missing?

There's no magic in make. If main.o depends on dispatcher.h, then it is written somewhere.
I suspect your Makefile runs gcc with the -MD or -MDD option that creates a dependency file. Usually they are named with a .d suffix. These dependencies files are automatically created by gcc as Makefile content: target: dependencies.
These files are then included into the main Makefile to provide the full automagic dependencies.
You should look for these .d files and remove them.

Related

Automatic dependency detection not working in GFortran

I the GCC Wiki it is stated that support for auto-detection of dependencies has been available since version 4.6:
Support the generation of Makefile dependencies via the -M... flags of GCC; you may need to specify additionally the -cpp option. The dependencies take modules, Fortran's include, and CPP's #include into account. Note: Using -M for the module path is no longer supported, use -J instead.
In my program I have two Fortran files: module_1.f08 and main.f08, where main uses module_1. I am using the following command to try to auto-detect dependencies of main:
gfortran -cpp -M main.f08
If module_1 has been already compiled, the command above returns a list of dependencies as expected, though if module_1 has not been compiled yet, I get an error message instead saying that module_1.mod does not exist.
The way I'm seeing this is that every time a new module is added to the code, it has to be compiled separately before running make all (or we might run make all before using the module in any other file, then use the module and compile again) or else any dependency of it might be compiled before the module itself and a compilation error will be returned.
Another thing is that dependency files have to be created gradually and one-by-one as the project grows, and if .mod files and dependency files got deleted at some point (with a make clean command for example), there will be no way to generate dependency files all at once using the auto-detection feature.
Is there a way to get around these limitations? Is there a way for auto-detection to work even if .mod files do not exist yet?
To start with, you need to add snippets to your Makefile to actually use the dependency generation feature. Additionally, you can use the -MD option to generate dependency files automatically for each target, so you don't need a special target to regenerate your dependencies. For an example project like yours above with a main.f90 that uses a module defined in mod1.f90 a simple Makefile using dependencies could look like:
FC := gfortran
FFLAGS := -O2 -g
LIBS := # Needed libs like -lopenblas
SRCS := mod1.f90 main.f90
OBJS := ${SRCS:f90=o}
DEPS := ${OBJS:o=d}
myprog: $(OBJS)
$(FC) $(FFLAGS) -o $# $^ $(LIBS)
.PHONY: clean
clean:
-rm -f $(OBJS) *.mod
-include $(DEPS)
%.o: %.f90
$(FC) $(FFLAGS) -cpp -MD -c -o $# $<
When you run make you'll see that it generates files main.d and mod1.d containing the dependencies for the corresponding source file.
A (minor?) problem here is that your SRCS variable containing your list of source files must be listed in an order that allows the files to be compiled from left to right before you have any .d files. So the dependency stuff as it's done here doesn't help with ordering a build before the .d files have been generated. (Thus I'd recommend distributing the .d files as part of the source package.)

OMNET++ 5.1 opp_makemake

I installed OMNET++ 5.1 on my Ubuntu 16 OS and imported my project into the Eclipse IDE. But I can not compile my project as before. Make is giving me error:
make1: *** No rule to make target 'msgheaders'. Stop.
I have a folder called loggingWindow that has its own custom makefile and is excluded from the source.
But I noticed that the generated makefile is not correct:
The makefile is calling msgheaders and smheaders targets in the logginWindow folder. The loggingWindow is a completely separate application with its own makefile and has no idea about mshheader!
Also make clean does not work!
The clean window stuck without any progress:
As a temporary workaround, I have added phony targets (msgheaders, smheaders) in order to compile my project.
As a workaround you can add these targets to your own Makefile in logginWindow, for example:
msgheaders:
echo Do nothing
smheaders:
make all
# content from your existing Makefile
all:
...

Is it safe to remove the object files if I keep the binary?

After compiling a (C/C++) code with GNU Make (or SCons) and successfully creating a binary, is there any reason to keep the .o object files?
Can I always safely remove them or are there cases where they are referenced by the binary?
Once you have created your executable by linking the object files (and
the libraries on which they depend) the object files are waste material as far
your executable is concerned. You can safely delete them.
However, if you build your executable with a build system such as GNU Make
or Scons it is certainly inadvisable to make that build system delete the
object files of a successful build.
The main purpose of such a build system is to rebuild your executable,
when it needs rebuilt, with the smallest amount of rebuilding that is
necessary. If the executable prog requires object files a.o, b.o and c.o to
be linked and you change only the source file c.c, then the build system
will know that it can rebuild prog merely by recompiling c.c
and then relinking prog with the new c.o plus the old a.o and b.o.
But it can only deliver this economy if the old a.o and b.o still exist.
If you've deleted them with your last successful build then prog must
be rebuilt from scratch, although the new a.o and b.o will be the same
as the old ones: a waste of time.
There will of course be occasions when you want to rebuild from scratch, and
to do so you must first delete all the object files. To support that
need in GNU Make you provide your project with a phony target,
conventionally called clean, that does nothing but delete the object files
and any other intermediate by-products of the build. You invoke it explictly with:
make clean
In Scons, you don't need to write anything extra in your build project to
clean out intermediate prodpucts. You just run scons -c or scons --clean.
But in either case, you do not want to delete the object files of a successful
build by default, as that defeats the purpose of the build system.

How to create a non-transitive dependency list (GCC)

Is there a way to generate dependencies of a C(++) source file similar to using the -MM option of GCC that only include the direct dependencies of said file, i.e. only the files directly included by this source file?
More context on why I'm looking for this functionality - maybe there is a completely different solution to my problem: I have a generic makefile with auto-detection of dependencies that suffices my needs but is slow. The basic structure is as follows:
Full dependencies of main.cpp are retrieved with gcc -MM
All *.h dependencies for which a corresonding *.cpp exists are changed to *.o dependencies
the altered dependencies are included in the makefile
All *.o targets are built, dependencies are retrieved with gcc -MM and included
All *.o targets are linked to create the executable
So far, this makefile has worked fine but -as said before- it is slow. I analyzed its execution path for one project and included all the generated dependencies by hand to try and optimize its speed. The result was by removing all transitive dependencies, the makefile retained its functionality but got much faster (also reflected in the number of lines of the debug output of make -d).
First of all, the method you are using is slightly confusing. All .h files used in the compilation of one .cpp file must be kept in its dependencies, and the automatic collection of *.o files shouldn't be that slow. I'd advise to go with classic -MM and to build the list of cpp files that are to be compiled by hand. automake does it that way, and if there was a really reliable way of figuring out the list of compilation units automatically, these guys would have found it :-).
Nevertheless, the -H option of the gcc helps you. It prints the names of all used files to stderr, with . prefixed for the level of inclusion. So,
cpp -I $< >/dev/null | sed -n -e 's/^\. //p'
should do the trick. Caveat: If a header file is included deeper in the hierarchy first and then later in the main file, it is not found. However, your dependency system should be able to handle that if you keep the 1-to-1 of .h and .cpp files.

Why does make think the target is up to date?

This is my Makefile:
REBAR=./rebar
REBAR_COMPILE=$(REBAR) get-deps compile
all: compile
compile:
$(REBAR_COMPILE)
test:
$(REBAR_COMPILE) skip_deps=true eunit
clean:
-rm -rf deps ebin priv doc/*
docs:
$(REBAR_COMPILE) doc
ifeq ($(wildcard dialyzer/sqlite3.plt),)
static:
$(REBAR_COMPILE) build_plt analyze
else
static:
$(REBAR_COMPILE) analyze
endif
I can run make compile multiple times and get
aromanov#alexey-desktop:~/workspace/gm-controller/lib/erlang-sqlite$ make compile
./rebar get-deps compile
==> erlang-sqlite (get-deps)
==> erlang-sqlite (compile)
However, for some reason running make test always gives
aromanov#alexey-desktop:~/workspace/gm-controller/lib/erlang-sqlite$ make test
make: `test' is up to date.
even if the files are not compiled. The question is, why?
Running the same command directly works:
aromanov#alexey-desktop:~/workspace/gm-controller/lib/erlang-sqlite$ ./rebar get-deps compile skip_deps=true eunit
==> erlang-sqlite (get-deps)
==> erlang-sqlite (compile)
Compiled src/sqlite3_lib.erl
Compiled src/sqlite3.erl
==> erlang-sqlite (eunit)
...
Maybe you have a file/directory named test in the directory. If this directory exists, and has no dependencies that are more recent, then this target is not rebuild.
To force rebuild on these kind of not-file-related targets, you should make them phony as follows:
.PHONY: all test clean
Note that you can declare all of your phony targets there.
A phony target is one that is not really the name of a file; rather it is just a name for a recipe to be executed when you make an explicit request.
It happens when you have a file with the same name as Makefile target name in the directory where the Makefile is present.
EDIT: This only applies to some versions of make - you should check your man page.
You can also pass the -B flag to make. As per the man page, this does:
-B, --always-make Unconditionally make all targets.
So make -B test would solve your problem if you were in a situation where you don't want to edit the Makefile or change the name of your test folder.
my mistake was making the target name "filename.c:" instead of just "filename:"

Resources