makefile flatten objects into one directory - makefile

Recently our project structure changed and now we have subdirectories. My old makefile assumed that and just said:
SOURCES := $(wildcard $(SRCDIR)/*.cpp)
OBJECTS := $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
Now with arbitrary deep nested directories it changed to
SOURCES := $(wildcard $(SRCDIR)/**/*.cpp)
But I still want all objects to land in the same directory, how would I have to change the OBJECTS ( or compile? ) definition so that it does not fail, because the given subdirectories don't exist in the objectdirectory.
edit:
Someone flagged this as a duplicate of
Getting make to create object files in a specific directory
Now I am asked as to say how this is different. Which i find insulting, since why should I provide the reason as to why this is a duplicate. Whoever flagged this as duplicate should provide the reason.
I don't even know where to begin as to why it is different. You might as well have linked me to some excel-question and ask my why it is different.
Explain to me why the linked question should answer my question and then I will tell you how it is or not is.

No problem, just use a couple of the text manipulation functions:
OBJECTS := $(patsubst %.cpp,$(OBJDIR)/%.o,$(notdir $(SOURCES)))

Related

Makefile: how to detect changes within the makefile itself?

I'm aware of the idea of using recursive makefiles. Will the subsequent makefiles such as the following be called be updated solely on any changes to the subsequent makefiles themselves?
e.g.:
#parent makefile. no changes here.
subsystem:
cd subdir && $(MAKE)
If the makefile within subdir was changed such that the following does not hold (e.g. only a gcc flag was changed), then will the object files be updated?
The recompilation must be done if the source file, or any of the
header files named as dependencies, is more recent than the object
file, or if the object file does not exist.
The only reason that, as written, make even runs that rule at all is because subsystem and subdir do not match.
If a subsystem file or directory were ever to be created in that directory that rule would cease to function.
If .PHONY: subsystem1 were added that problem would be fixed and that rule would always be run when listed on the command line (i.e. make subsystem). (As indicated in the comments .PHONY is a GNU Make extension. The section following the linked section discusses a portable alternative. Though it is worth noting that they are not completely identical in that .PHONY has some extra benefits and some extra limitations.)
In neither of those cases is the subsystem target paying any attention to modification dates of anything (as it lists no prerequisites).
To have a target depend on changes to a makefile you need to list the makefile(s) as prerequisites like anything else (i.e. subsystem: subdir/Makefile). Listing it as .PHONY is likely more correct and more what you want.
No, nothing in make itself tracks non-prerequisites. So flag changes/etc. do not trigger rebuilds. There are ways to make that work for make however (they involve storing the used flags in files that themselves are prerequisites of the targets that use those flags, etc.). There are questions and answers on SO about doing that (I don't have them ready offhand though).
Other tools do handle flag changes automatically however. I believe Electric Cloud's tools do this. I believe CMake does as well. There might also be others.
Recursive makefiles are executed whether or not anything changed. This is exactly one of the objections pointed out by Paul Miller in his Recursive make considered harmful paper from almost 20 years ago.
With that said, a makefile is just like any other dependency and can be added to a production rule to trigger that rule if the makefile is altered.
You can include the makefile as a dependency, the same as any other file:
mytarget.o: mytarget.c Makefile

Writing a Makefile to be includable by other Makefiles

Background
I have a (large) project A and a (large) project B, such that A depends on B.
I would like to have two separate makefiles -- one for project A and one for project B -- for performance and maintainability.
Based on the comments to an earlier question, I have decided to entirely rewrite B's makefile such that A's makefile can include it. This will avoid the evils of recursive make: allow parallelism, not remake unnecessarily, improve performance, etc.
Current solution
I can find the directory of the currently executing makefile by including at the top (before any other includes).
TOP := $(dir $(lastword $(MAKEFILE_LIST)))
I am writing each target as
$(TOP)/some-target: $(TOP)/some-src
and making changes to any necessary shell commands, e.g. find dir to find $(TOP)/dir.
While this solves the problems it has a couple disadvantages:
Targets and rules are longer and a little less readable. (This is likely unavoidable. Modularity has a price).
Using gcc -M to auto-generate dependencies requires post-processing to add $(TOP) everywhere.
Is this the usual way to write makefiles that can be included by others?
If by "usual" you mean, "most common", then the answer is "no". The most common thing people do, is to improvise some changes to the includee so the names do not clash with the includer.
What you did, however, is "good design".
In fact, I take your design even futher.
I compute a stack of directories, if the inclusion is recursive, you need to keep the current directories on a stack as you parse the makefile tree. $D is the current directory - shorter for people to type than $(TOP)/,
and I prepend everything in the includee, with $D/, so you have variables:
$D/FOOBAR :=
and phony targets:
$D/phony:

Compilation order in make rule

I have a compilation rule as follows,
$(compiled_objs) : $(obj_dir)/%.o: $(src_base)/%.cpp
It creates .o dso objects from specific .cpp files in src_base and works fine.
Question:
My question is that is there a way in gnu Makefiles to sort the order in which %.cpp files are processed. For example, in each src_base, i have a file called xxxLast.cpp and i want to create the object for *Last.cpp after all other .cpp files from $src_dir directory has already been processed.
Use-Case:
My use case is not common but i want to embedd the md5sum of all other .o objects in xxxLast.cpp file for which i can add additional handling in my rule.
I haven't done much work on makefiles. Help will be highly appreciated and thanks in advance.
Somewhere else in your makefile you'll have a target that depends on $(compiled_objs):
all_objects: $(compiled_objs)
Make will build the prerequisites of any target in the order they are listed. So if you want a particular object to be built last, then you just put it at the end of the compiled_objs macro.
Be aware that during parallel builds make will still walk the commands to run in the same order, BUT due to parallelization effects they may actually run in a different order, or at least you can't know that the last one will be started after all the previous ones have completed.
For your situation I really don't recommend just stucking the last object at the end and hoping. You should define this relationship explicitly using make rules, so:
all_objects: xxxLast.o
xxxLast.o: $(compiled_objs-but-not-xxxLast.o)
...generate md5sums for $^...
xxxLast.o $(compiled_objs-but-not-xxxLast.o): $(obj_dir)/%.o: $(src_base)/%.cpp

How to organize the build-process with Makefiles for Code in several directories

My Fortran-Code is structured as follows:
There are two folders (with several subdirectories)
1.
/home/user/general_part
where some very general files are located and which should be used in several versions of the program.
files: (with relative path)
- mainsubdir/main.F
- subdir1/file1.F
- subdir1/headerfile1.h
2.
/home/user/special_part/special_case1
where the files located which are case-dependend.
files: (with relative path)
- subdir2/file2.F
- subdir2/headerfile2.h
- subdir3/file3.F
How could I organize the build-process?
Should I use several makefiles in each of the directories?
Where should the object-files be located (especially the ones from the general files)?
My aim would be that I can start the build-process from the directory:
/home/user/special_part/special_case
with a simple make or a little script.
So at the end it should be possible that I can build a program always with the general files from 1. and several special-case files located in:
/home/user/special_part/special_case1
/home/user/special_part/special_case2
...
The reason why nobody is answering, is probably because the question is too general. Be more specific.
Say something like: "this is the program I want to build, and this is my makefile, please critique my makefile".
You can organize it any way you like, as long as it's logical and consistent. I put some beginner guidelines at
https://stackoverflow.com/questions/19816058/makefile-fibonacci/19821801#19821801
No. Make is really designed and works best, with a single makefile. You can have relevant makefile fragments in each directory, which are included in the main makefile. Do not have complete makefiles in each subdirectory. Google for the classic paper "Recursive make considered harmful" to see why that is so.
You can place your result anywhere you want, some people, place results alongside sources, some, in a separate directory. Just place results in some logical and consistent way. Same goes for intermediate files, such as object files.

Makefile.am process SUBDIRS in parallel

We have unit tests in our project, and they run very slowly. The main reason for this, as far as I can tell is that each subdir runs serially. There is no reason for this and I'd like to modify things so each subdirectory is processed in parallel.
I found this question but it seems that the accepted answer is for how to specify this in your makefile, and not the makefile.am. I tried just adding the solution to my Makefile.am and it didn't seem to make a difference. Is this the correct way to do it at a Makefile.am level? If so, any advice for what I could be doing wrong? If not, please show me the path of truth :-)
In answer to my question, things from Makefile.am are translated fairly directly to the Makefile, so the changes in the original question can be made in Makefile.am. The only part I'm not 100% confident on is whether or not SUBDIRS (as it has special meaning) can get mangled in the autotools process. At any rate, processing the SUBDIRS in parallel is perhaps not typically the answer.
I solved this was to use a separate target for the directories I wanted processed in parallel, and I bet that this is typically the correct answer. There may well be some way to get the SUBDIRs to be processed this way, but using a separate target was pretty easy to get working for me, and at least for what I was trying to do a separate target was more appropriate.

Resources