Revised and updated to the new gnustep-make internals

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/tools/make/trunk@10575 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Nicola Pero 2001-07-26 11:27:45 +00:00
parent b9870c02e2
commit 7578b07663

View file

@ -10,23 +10,24 @@
\begin{document}
\title{GNUstep Makefile Package Internals}
\author{Nicola Pero n.pero@mi.flashnet.it}
\date{last days of June 2001}
\date{last days of June 2001 - revised end of July 2001}
\maketitle
\tableofcontents
\section{Introduction}
This short document attempts to explain simply how the gnustep
makefile package works internally. Since the mechanism involves
recursive invocations of make on the same makefiles (each time with
different targets and variables), it might be very confusing at the
beginning. In this document we concentrate on understanding the main
flow of processing, ignoring most of the little details. This should
hopefully allow you to start reading and understanding the
gnustep-make source code, and then you can learn about the little
details by yourself.
makefile package works internally. When I first wrote this document,
the mechanism used to be extremely complex, involving many recursive
make invocations; I have now simplified it so that it involves only a
single recursive make invocation per target/type/operation. As a
result, I hope that the mechanism is now so simple that you can figure
out how it works without reading this document, by just reading the
gnustep-make source code. Anyway, the thing might still not be still
totally trivial at a first approach, so this document might help you
to get familiar with the gnustep-make source code in a shorter time
and with less pain.
\section{From `make' to the internal-all rule}
Imagine for example that in your \texttt{ GNUmakefile} you include both
\texttt{tool.make} and \texttt{library.make}, as in the following example:
\begin{verbatim}
@ -97,23 +98,36 @@ decrypt.all.tool.variables
libDvd.all.library.variables
\end{verbatim}
\section{The \%.variables rule - dependencies}
The rule for building these targets is in the \texttt{rules.make} file,
it is the \texttt{\%.variables} rule:
\begin{verbatim}
%.variables:
@(target=$(basename $(basename $*)); \
operation=$(subst .,,$(suffix $(basename $*))); \
type=$(subst -,_,$(subst .,,$(suffix $*))); \
$(MAKE) -f $(MAKEFILE_NAME) --no-print-directory --no-keep-going \
TARGET_TYPE=$${type} \
OPERATION=$${operation} TARGET=$${target} \
PROCESS_SECOND_TIME=yes $${target}.build \
OBJCFLAGS="$(OBJCFLAGS)" CFLAGS="$(CFLAGS)" \
OPTFLAG="$(OPTFLAG)" )
\end{verbatim}
This rule matches all targets ending in \texttt{.variables}. The rule
parses the \texttt{.variables} string - for example when the rule
is applied to
%.variables: %.tools %.subprojects
@ \
target=$(basename $(basename $*)); \
operation=$(subst .,,$(suffix $(basename $*))); \
type=$(subst -,_,$(subst .,,$(suffix $*))); \
echo Making $$operation for $$type $$target...; \
$(MAKE) -f $(MAKEFILE_NAME) --no-print-directory --no-keep-going \
internal-$${type}-$$operation \
INTERNAL_$${type}_NAME=$$target \
TARGET=$$target \
_SUBPROJECTS="$($(basename $(basename $*))_SUBPROJECTS)" \
...
\end{verbatim}%$
This rule matches all targets ending in \texttt{.variables}. First of
all, the rule depends on the corresponding \texttt{\%.tools} and
\texttt{\%.subprojects} rules. This is because before processing the
target itself, gnustep-make needs to process the related subprojects
and (only for frameworks) the framework tools. We ignore this
complication of subprojects and framework tools for now; if you look
at the \texttt{\%.subprojects} and \texttt{\%.tools} rules you see
that they do nothing if you are not actually using subprojects or
framework tools in your makefile.
\section{The \%.variables rule - second make invocation}
The rule body parses the \texttt{\%.variables} string - for example when
the rule is applied to
\begin{verbatim}
decrypt.all.tool.variables
\end{verbatim}
@ -124,47 +138,26 @@ target=decrypt
operation=all
type=tool
\end{verbatim}
and then it runs a make subprocess with the \texttt{OPERATION} and
\texttt{TYPE} variables set, and a target built from the \texttt{target}
by appending \texttt{.build}.
\section{The second make invocation}
In our case, the \texttt{\%.variables} rules is executed twice, so it
runs two separate make processes:
and then it runs a make subprocess, specific to that target, type and
operation. In our case, the \texttt{\%.variables} rules is executed
twice, once to build
\begin{verbatim}
make OPERATION=all TYPE=tool decrypt.build PROCESS_SECOND_TIME=yes ...
make OPERATION=all TYPE=library libDvd.build PROCESS_SECOND_TIME=yes ...
decrypt.all.tool.variables
\end{verbatim}
where we have omitted the less interesting variables (as signified by the
\texttt{...}).
What this means is that for each target/type/operation, a separate
make process is run. For example, if you have two tools,
\texttt{decrypt} and \texttt{crypt}, and you want to both compile and install
them, it will run four make subprocesses:
and once to build
\begin{verbatim}
make OPERATION=all TYPE=tool decrypt.build PROCESS_SECOND_TIME=yes ...
make OPERATION=all TYPE=tool crypt.build PROCESS_SECOND_TIME=yes ...
make OPERATION=install TYPE=tool decrypt.build PROCESS_SECOND_TIME=yes ...
make OPERATION=install TYPE=tool crypt.build PROCESS_SECOND_TIME=yes ...
libDvd.all.tool.variables
\end{verbatim}
This is the `second make invocation'. The make package knows that it
is being invoked for the second time, because of the
\texttt{PROCESS\_SECOND\_TIME} flag.
\section{The \%.build rule}
Let's examine what happens in the make subprocess - for example in the
\texttt{decrypt.build} make subprocess. Make looks for a rule to
build \texttt{decrypt.build}. The rule is found in
\texttt{rules.make}; it is the \texttt{\%.build} rule. This rule is
too long to quote it here; but basically it runs yet another make
subprocess (which is the one which finally does the work). This last
make subprocess is run more or less as follows:
so the result is to run two separate make processes:
\begin{verbatim}
make INTERNAL_tool_NAME=decrypt \
internal-tool-all \
OBJC_FILES="{the list of OBJC_FILES specified using decrypt_OBJC_FILES
in the makefile}" ...
make internal-tool-all INTERNAL_tool_NAME=decrypt TARGET=decrypt \
_SUBPROJECTS="$(decrypt_SUBPROJECTS)" \
OBJC_FILES="$(decrypt_OBJC_FILES)" \
...
make internal-library-all INTERNAL_library_NAME=libDvd TARGET=libDvd \
_SUBPROJECTS="$(libDvd_SUBPROJECTS)" \
OBJC_FILES="$(libDvs_OBJC_FILES)" \
...
\end{verbatim}
where \texttt{...} stands for a lot of other variables, including all
variables needed to perform the final stage: \texttt{OBJC\_FILES},
@ -176,15 +169,28 @@ at this stage, before passing them to the submake process. For
example, some library flags are filtered through the
\texttt{WHICH\_LIB\_SCRIPT}.
\section{The third make subprocess}
This last make subprocess is the one which really builds the target.
What this means is that for each target/type/operation, a separate
make process is run. For example, if you have two tools,
\texttt{decrypt} and \texttt{crypt}, and you want to both compile and install
them, it will run four make subprocesses:
\begin{verbatim}
make internal-tool-all INTERNAL_tool_NAME=decrypt ...
make internal-tool-all INTERNAL_tool_NAME=crypt ...
make internal-tool-install INTERNAL_tool_NAME=decrypt ...
make internal-tool-install INTERNAL_tool_NAME=crypt ...
\end{verbatim}
This is the `second make invocation'. The make package knows that it
is being invoked for the second time, because of the
\texttt{INTERNAL\_tool\_NAME} being non-empty.
\section{Second make invocation}
Because of the \texttt{INTERNAL\_tool\_NAME} variable being a
non-empty string (while it was empty in all previous invocations),
\texttt{tool.make} will include the actual rules to build the tool; in
particular, the \texttt{internal-tool-all} rule, which is then
executed and builds the tool. All variables such as
\texttt{OBJC\_FILES} or the library flags are now available directly in
the makefiles, they have already been prepared and preprocessed, so
non-empty string (while it was empty in the previous top-level
invocation), \texttt{tool.make} will include the actual rules to build
the tool; in particular, the \texttt{internal-tool-all} rule, which is
then executed and builds the tool. All variables such as
\texttt{OBJC\_FILES} or the library flags are now available directly
in the makefiles, they have already been prepared and preprocessed, so
that the rules in \texttt{tool.make} can just plainly use these
variables naively to perform their job (compiling, installing, or
whatever).