mirror of
https://github.com/gnustep/tools-make.git
synced 2025-04-22 22:00:49 +00:00
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:
parent
b9870c02e2
commit
7578b07663
1 changed files with 74 additions and 68 deletions
|
@ -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).
|
||||
|
|
Loading…
Reference in a new issue