make
macros across all the recipe files.
make
macrosHere is a list of the macros I've used, and how they fit together. We'll spell them as simply as possible first.
DESTDIR
=
install
to target an alternate
root directory. It is used by automation to build packages for later
deployment. Never set this to an non-empty value in
a recipe file.
It is only set by a build script, for example on the
make
/msrc
/mmsrc
/mk
command-line.
TOP
=/usr/local
/usr/local
might
become /opt/npcguild
. All of the non-variable
files are placed under this directory.
Never set TOP
to the empty string.
The shortest TOP
would be /
, which
would be apropos for sh
's platform recipe.
VTOP
=/var/local
BIN
=${DESTDIR}${TOP}/bin
SBIN
=${DESTDIR}${TOP}/sbin
CGIBIN
=${DESTDIR}${TOP}/cgi-bin
DOC
=${DESTDIR}${TOP}/man
man1
); so don't add a section
subdir
suffix.
INFODOC
=${DESTDIR}${TOP}/info
info
document library.
VAR
=${VTOP}
VAR
=${VTOP}/
subdir
subdir
) is specified a rule should be included
to build it with the correct modes.
LIB
=${DESTDIR}${TOP}/lib
LIB
=${DESTDIR}${TOP}/lib/
subdir
subdir
) is specified a rule should be included
to build it with the correct modes.
LIBEXEC
=${DESTDIR}${TOP}/libexec
LIBEXEC
=${DESTDIR}${TOP}/libexec/
subdir
LIBDATA
=${DESTDIR}${TOP}/libdata
LIBDATA
=${DESTDIR}${TOP}/libdata/
subdir
LIBDATA
, does not allow
any executable files at all.
ETC=
${DESTDIR}${TOP}/etc/
ETC=
${DESTDIR}${TOP}/etc/
subdir
SBIN
for any executables. Some things still
live under /etc
for historical compatibility,
but nothing new should be placed there. If I can move
to sbin
, then so can you.
SHARE
=${DESTDIR}${TOP}/share
SHARE
=${DESTDIR}${TOP}/share/
subdir
N.B. MAN
is not the same as
DOC
. MAN
is a list of
manual pages, DOC
is their target installation
hierarchy.
This separates the run path from the (possibly forced into an installation forced into aRUN_BIN
=${TOP}/bin
BIN
=${DESTDIR}/${RUN_BIN}
chroot
, or
jail
, or
a RPM staging directory) path.
You'll also need to pass that computed path down to the application,
since it may need it to call their peer applications:
Never build anyCDEFS
=-DMY_RUNBIN=\"${RUN_BIN}\"
RUN_
variants that
you don't need, or other macros you don't use. Always force recursive
TOP
and DESTDIR
rather than
forcing just what you think you need, like BIN
or
SHARE
.
That way later changes in the recipe to addall install ...: cd
subdir
&& make TOP=${TOP} DESTDIR=${DESTDIR} $@
SBIN
won't break your relocation spells.
This also allows automation to use grep
to
find re-target macros.
orMAN= %% the manual page for this tool %%
the text inside the double-percents is a mix of what to replace the markup with, andmsync: .PHONY%% 3dd unless level1, then D this markup %% rcsdiff -q -r\$$ RCS/*,v
vi
editor commands that would
delete the feature being suggested. The update commands I suggest
will be tuned for local site policy.
msrc
expects. See the HTML document.
Pick one of the master recipe files from the list below, copy it to the new
directory as Makefile
(or
Msrc.mk
). Then edit it to fill in the
double-percent parts. Whole lines can be deleted or replaced, but partial
lines need to be filled in with more care.
MAP
's recipe
The recipe used for most master source products. This is by far the most common organization. The master side sends all the work to the other side. Usually you'll want to build a `Makefile.host' file from one of the lower case recipe files below.
Since msrc
figures out
the disposition of each file automatically you don't need to set most of
the configuration macros. We include them in the file just in case you need to
set one, but for the most part you can just delete those lines.
MAP
'ing the recipe
The recipe that is both the master and the platform recipe. I hardly ever use this, as it may lead to triggering the platform targets on the master host. This can be used for file that are installed on every host, like /etc/motd. The recipe must work from the msrc side exactly the same way as it would on each platform. This is really quite rare.
msrc
from doing something untoward
When a source directory only represents a common management or ownership of sources we place this recipe in to prevent an accidental mass update of the otherwise unrelated projects.
The recipe used to a collection of related source directories, built
in a specific order.
[The one requires Msrc.hxmd as
well. See below.] This is not used as often as the common structure, because
most tasks don't require multiple subdirectories to do their work.
Large library structures (like mk
's library or op
's library) use this.
hxmd
to provide recursive updates
This template is used to loop control back to the master recipe to project subdirectories to build platforms. It may be tuned to local site policy at your site.
It works by building a HXMD_U_MERGED
file that
records the attributes required to push to each target client. Then
it provisions a PRE_CMD
that calls back to
the recipe file for either of 2 targets based on msrc
's
shell recursive support
(either local_descend
or
remote_descend
).
It passes some make
macros from the
command-line (DOWN_CFG
,
LINTO
, THOST
and
TINTO
) which provision the recursive call
with all the information to get the goods to the correct directory
on the correct host.
DOWN_CFG
=-C\ HXMD_U_MERGED`'
ifdef(`HXMD_OPT_Z',`\ -Z\ HXMD_OPT_Z')`'
ifdef(`HXMD_OPT_C',`\ -X\ HXMD_OPT_C')`'
ifdef(`HXMD_OPT_X',`\ -X\ HXMD_OPT_X')
LINTO
=${1}
THOST
=HOST
TINTO
=${5}
The 2 commands execute an xapply
loop over the
directory list in SUBDIR
, which looks like
either:
remote_descend
:
cd %1 && msrc ${DOWN_CFG} -E HOST=${THOST} -y INTO=${TINTO}/%1 -- \ ${MAKE} TOP=${TOP} DESTDIR=${DESTDIR} source
local_descend
:
cd %1 && mmsrc ${DOWN_CFG} -E HOST=${THOST} -y INTO=${LINTO}/%1 -- \ ${MAKE} TOP=${TOP} DESTDIR=${DESTDIR} source
TINTO
(msrc
's ${1}
), while
in the local case we target LINTO
(msrc
's ${5}
).
This selects the local cache directory for local revisions
(via mmsrc
, or msrcmux
) and
the remote cache for rdist
-driven distribution
(via msrc
or hxmd
).
make
macros, special recipe actions, and
distinct dependencies. All of these are build with m4
markup, based in the attribute macros hxmd
defines for each target host.
Here are the recipe templates:
lex
, yacc
, mkcmd
or some other code generator
mkcmd
driven
ksb tools use.
.a
),
lint
library files (.ln
),
and maybe even shared libraries (.so
).
The shared code is presently not included.
maketd
,
explode
, and calls
)
which your site my not install or support. I don't presently
distribute mkcat
, but I will again someday.
rpm
, or
source tar
file, or the like. That source
product has all the recipes and information required to build a
binary (aka. distribution) package (RPM, pkgsrc directory, ports directory,
depot file, or some local packaging system).
This completes the build from level 1 (files) to level 2 (products) to level 3 (packages). If your packages contain correct dependency meta-data, then the level 4 (running system) step is just package adds for the subscribing hosts. That leaves local site policy, which is totally your problem. See msrc base, if you forgot why you were here.
Note that these use some additional make
macros:
TMP
- a temporary directory, usually /tmp
or /var/tmp
RELEASE
- the product's current release number, e.g. 5.7
SUBDIR
- provision-ordered product directories, in the package provision template
SUBDIR
- build-ordered product directories, in the package build template
Here are the related make
targets:
stage
:
/tmp
as
a source hierarchy. It may have a target to build a compressed
tar
archive of the resulting directory. It is
a separate process to then construct the output from that package.
msync
:
msync
status of the
packaging recipe. This has been replaced by msync
's
-3
option, but some recipes still carry the logic.
sub_sync
:
msync
status of all the
level 2 products under this level 3 package.
tar
archive.
check
: - ad hoc check
Makefile
. If local site policy changes
that name the called to mk
(for example) will
not work.
This recipe also has some mk
markup for
msync
, level2s
, and
level3s
:
# $Msync(group):
- msync
# $Msync(target):
- msync
msync
's manual page and
HTML document.
These tunes allow msync
to accept a different
group owner, or provide a make
recipe to replace
the default logic.
# $Level2s:
- level3s
level3s
uses to find the list of
level 2 packages (by symbolic revision and path to the source directory).
$ mk -mLevel2s Makefile Eight /usr/Pkgs/install_base Eight ${MSRC}/local/lib/install.cf ...
op
ruleschown
the staged files (as the superuser).
So there is an op
rule installed that allows
anyone in group source
to
chown
a staging directory.
See the update action under the clean
and
stage
targets:
clean: -[ -d ${STAGE} ] && op -u $${USER:=$$LOGNAME} level2s-chown ${STAGE} rm -rf ${STAGE} stage: ${STAGE} ${STAGE}/Pkgs/${PKG} %% add all the dirs you wanted %% addlic ${STAGE} find ${STAGE} -type d -exec chmod g+w '{}' \; op -u source level2s-chown ${STAGE}
Your local site policy may not required common ownership of source files.
You may delete the 2 lines, or make the op
rule
do nothing but succeed.
This recipe becomes the package's
Makefile
as part of the process above.
That makes it the controlling recipe for the subsequent master build process
for the package data, which is effectively just a recursive level 2 build.
Quite often this is triggered from a package system specific file, like
the rpm
specific "spec" file. If you need one
of those, just include it as you would any other file. I always put
markup in it (mk
or the like) to remind me
how to trigger the build process. And I always call my spec file
ITO.spec, which is just local site policy.
The spec file does contain some mk
markup
for level2s
, which knows how to build at
least the source tar
for most level 2 products.
The markers are KeyFile
,
Level2
, and
Level3
.
See the level2s
manual page.
all
,
clean
, and install
are provisioned (unless you add more).
This is really the most trivial of recipes. The actual build logic is
left to the product recipes, which is as it should be. Either the packaging
system knows how to gather the built files from the source directory
(which is bad), or their is a target in the recipes to install into a
chroot
-like environment, from which the files
are recovered. This is where DESTDIR
and
TOP
come in handy.
The point of all of this is to give you a boost above the noise: so your group will focus on a repeatable process that can build anything you need. To do that, your team must start with something that works, then move to something better. This works, and it is better than starting from nothing.
The obvious things I almost never use are the autoconf
tools. That doesn't mean you shouldn't use them. I just have more
things to configure that have nothing to do with building programs.
(For example op
and sudo
rule-bases.) For my work-load msrc
-driven
m4
works far better than
./configure
.
And once you have a powerful tool, you find more ways to use it.
Any technology comes with good and bad elements, this is no exception. I've spent some time making this work for me and my peers. It has some "local flavor" which you might not think you'll like, but the power it enables is truly awesome.
You only have to follow a UNIX command learning curve, and most of
the learning is incremental (like you don't have to learn a whole
new way to spell or run chmod
).
Stay calm, and carry on.
-- ksb, Jan 2013
$Id: master.html,v 1.15 2013/01/04 15:55:58 ksb Exp $