エリアでオススメの おみやげ・グルメ BISTRO TOKI (ビストロ トキ) 丁寧な仕込みを必要とする料理を、日々の作業で身に付けた技術で情熱と手間をかけおつくりします。.
prorab is a non-recursive
GNU make
-based build system. Essentially it just providesconvenient definitions for writing clean makefiles.The main feature of prorab is that it allows having independent makefilesin several subdirectories of the project and at the same time there can bea main makefile in root directory of the project which builds all those subprojects.And parallel building is still supported in that case.
Also, prorab provides some predefined rules for easy building of C/C++ applicationsand libraries.
Including prorab into the makefile
Including prorab in the make file is simple and obvious, just add the following directivein the beginning of the
makefile
Basically, all makefiles in the project are supposed to use prorab and have this include directive as a first include.
Right after inclusion of
prorab.mk
there will be following variables defined:d
- directory where thismakefile
residesos
- operating system where makefile is run, can belinux
,macosx
,windows
. Note, thatwindows
is when building underCygwin
orMsys
.soext
- typical extension for dynamically linked libraries in the OS (windows:.dll
, linux:.so
, macosx:.dylib
)exeext
- typical executable extension (windows:.exe
, linux: empty, macosx: empty).RECIPEPREFIX
- this is a built-in variable ofGNU make
, but by default it is empty which means the default recipe prefix will be the tab character. Prorab explicitly sets the value of this variable to tab character, so that this variable could be used in user's makefiles.Q
- this variable is either empty or set to@
depending on value ofverbose
orv
variables. See about verbosity below.
Prorab macros and variables naming conventions
- Prorab macros are named using hyphen-case and start with
prorab-
prefix. - Output variables are named using snake case and start with
prorab_this_
prefix. - Input variables are named using snake case and start with
this_
prefix.
Building subprojects with prorab
As said before, prorab allows 'cascading' of makefiles. Say, you have two subdirectories in your project:
app
and test
. And both those directories contain some subproject which can be built independently. So, in both those directories there are project makefiles.Now, if we want to have a makefile in project root directory which builds both of those subprojects, we can use
prorab-build-subdirs
macro and then the root makefile would look like this:And that's it. This will invoke the same target on every subdirectory which has file named
makefile
. Note, that parallel build is still supported since it is a non-recursive technique.Prorab macros and input variables
Before invoking most of the prorab macros one has to set some input variables for the macro.For example:
After invoking some prorab macro there might be some output variables defined like, for example,
prorab_this_name
which represents the resulting filename of the created binary.Including other makefiles
In order to include some other makefile one can use
prorab-include
macro. This macro will check if the makefile was already included or not and only include it if necessary.Example:
Echoing commands from recipes
All commands in prorab recipes are prefixed with @ by default, but it is possible to make it to be verbose by setting the
verbose
variable to true
, like this:Valid values for
verbose
are true
or false
or not set.The
v
is a shorthand alias for verbose
. If v
is not set or set to 0
or false
then it is equivalent to verbose=false
. Otherwise, if v
is set to any other value it is same as verbose=true
.Set verbose
variable has higher priority than set v
variable.Prorab uses value of
Q
variable to prefix all recipe lines. The Q
variable is set by prorab to @
or to empty value depending on verbosity.Defining several builds in one makefile
It is possible to define several builds in a single
makefile
. Right before starting definition of the next build one has to clear all this_
prefixed varibales, so that those do not go to the next build from previous build. To do that, there is a prorab-clear-this-vars
macro which can be invoked using $(eval ...)
as usual. Note, that this macro is automatically invoked inside of prorab.mk
, so it is not necessary to invoke it for the very first build of the makefile
.Adding all source files from all subdirectories to the build
It is often needed in the build to use all source files from a certain directory subtree. There is a
prorab-src-dir
function for that. The directory to search for source files is relative to the makefile
directory. Only .c
and .cpp
files are searched.Using automatic number of parallel jobs
Sometimes it is needed to have number of parallel jobs exactly as the number of physical processors on the system. prorab allows to do that. Just pass the
autojobs
variable set to true
to the make
command.Valid valies for
autojobs
are true
or false
or not set.The
aj
is a shorthand alias for autojobs
. If aj
is not set or set to 0
or false
then it is equivalent to autojobs=true
. Otehrwise, if aj
is set to any other value then it is same as autojobs=true
.Set autojobs
variable has higher priority than set aj
variable.Adding prorab.mk to project tree
If there is no possibility to install prorab to the system then it is possible to just add the
prorab.mk
to the project file tree. Then all includes of the prorab.mk
have to be done with relative path and using the $(d)
variable as path prefix.![Version Version](http://stroimdom24.com/wp-content/uploads/2018/10/1-2.jpg)
It is good to take a note in some
readme
file, or as a comment right in prorab.mk
about which version of prorab you copied, so that you know if it needs update or not when new version of prorab comes out.Defining custom rules
It is often necessary to add custom rules.
GNU make
expands variables in makefile
in two phases. During first phase it expands all variables in makefiles, except recipes. During second phase it starts executing the recipes and it expands variables in recipes right before executing, see GNU make: Using Variables in Recipes. So, in order to use correct values of context dependent variables, like $(d)
, one has to use the trick to substitue those variable values to the custom rule's recipe right away during the first phase. This is achieved by wrapping the custom rule with recipe into some temporary variable, let's say this_rules
, and then evaluating the value of that variable.Note, the use of double dollar sign in
$$^
variable, this is escaping of dollar sign so that $^
will actually appear in the this_rules
value at the moment of $(eval $(this_rules))
invocation.User can override the value of
.RECIPEPREFIX
variable to any character he/she wants. I personally recommend to explicitly use the .RECIPEPREFIX
when writing custom rules to avoid possible errors: