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

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.

Related

How can I add built-in rules to make?

Make(1) has built-in rules, such that for simple tasks you don't need a makefile at all. I can type make prog and if the current directory has a prog.c, make will do something useful.
I have a number of rules like this (e.g., how to make .pdf from .html) that apply in many projects. If I have a makefile in a directory, I can simply include my rules from a file. Is there a way to tell make to use this file always? Like a dot file that make would always include before doing anything else.
Make's rules are truly built-in, not read from a file. This has advantages (the entirety of make is one executable and you can copy it and install it anywhere and get identical behavior) and disadvantages (you can't modify the default rules without modifying the source code and recompiling--if you want to do that it's easy to do, though: see the default.c file in the sources).
You can specify an extra makefile (or makefiles) that should be parsed before the usual ones using an environment variable, though, so you can create a makefile with some extra rules, then (in your ~/.bashrc or whatever) set the MAKEFILES environment variable to the name of that file (or files) containing these extra rules (don't forget to export it).
Now every make invocation will load these rules as well.
You may discover, though, that this isn't quite what you'd hoped, because it could cause other makefiles to fail or act in bizarre ways (for example if you download open source packages and want to build them locally, etc.) If you do this just remember you did it, so in a few months if you run into issues you'll remember to try undoing it and see if it helps :-)

What is going on in this make file line?

Ok so im getting in to Kernel Module Development and the guides all pretty much use the same basic make file that contains this line:
make -C /lib/modules/`uname -r`/build M=$(PWD) modules
So my questions are:
Why is a make file calling make? that seems recursive
what is the M for? i cant find a make -M flag in any of the man pages
Recursive use of make is a common technique for introducing modularity into your build process. For example, in your particular case, you could support a new architecture by putting the relevant component in a folder whose name matches the uname -r output for that architecture, and you wouldn't have to change the master makefile at all. Another example, if you make one component modular, it makes it much easier to reuse in another project without making large changes to the new project's master makefile.
Just like it can be helpful to separate your code into files, modules, and classes (the latter for languages other than C, obviously), it can be helpful to separate your build process into separate modules. It's just a form of organization to make managing your projects easier. You might group related functionality into separate libraries, or plugins, and build them separately. Different individuals or teams could work on the separate components without all of them needing write access to the master makefile. You might want to build your components separately so that you can test them separately.
It's not impossible to do all of these things without recursive use of make, of course, but it's one common way of organizing things. Even if you don't use make recursively, you're still going to end up with a bunch of different component "makefiles" on a large project - they'll just be imported or included into the master makefile, rather than standing alone by themselves and being run via separate invocations of make.
Creating and maintaining a single makefile for a very large project is not a trivial matter. However, as the article Recursive make considered harmful describes, recursive use of make is not without its own problems, either.
As for your M, that's just overriding a variable at the command line. Somewhere in the makefile(s) the variable M will be used, and if you specify its value at the command line in this way, then the value you specify will override any other assignments to that variable that may occur in the makefile(s).

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:

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.

Is it a best practice to list down all the object files in a C++ makefile and are wildcards acceptable?

I'm a Java developer learning C++. I'm using eclipse as my IDE and MinGW as my toolset. Is it considered a best practice to list down every single object in a makefile? Also, is it just as acceptable to use wildcards to include all the files?
The use of wildcards is common, and accepted, but not really good practice.
If extra source files get into your source directories, they could wind up causing conflicts or -- worse -- riding silently in your libraries as useless baggage (introns?). Also, if a needed source file goes missing, your linker will complain about a missing {function|typename|whatever} and it might not be obvious what file has been lost (not really a problem if you have good source control, but still annoying). Finally, if your build system is expected to produce different targets using different subsets of the source files, wildcards will require you to either divide your source directories Venn-diagram-style, or resort to filename conventions that do the same thing (gah!).
Maintaining explicit lists of object files in a makefile really isn't that hard to do, and it keeps things simple.

Resources