The term mk-files refers to a collection of *.mk files.
You need bmake or a recent NetBSD make.
Many years ago, when building large software projects, I used GNU make (or my own patched version of it), and had developed a set of macros to simplify developing complex build trees.
Since the early 90's my main development machines, run BSD (NetBSD to be precise), and the BSD source tree is good example of a large software project. It quickly became clear that /usr/share/mk/*.mk were a great model, but were quite tightly linked to building the BSD tree.
Much as I liked using NetBSD, my customers were more likely to be using SunOS, HP-UX etc, so I started on bmake and a portable collection of mk-files (mk.tar.gz). NetBSD provided much of the original structure.
Since then I've added a lot of features to NetBSD's make and hence to bmake which is kept closely in sync. The mk-files however have diverged quite a bit, though ideas are still picked up from NetBSD.
The BSD build model is very simple. A directory produces one component, which is generally either a library or a program. Library makefiles include lib.mk and programs include prog.mk and they do the right thing.
A simple library makefile might look like:
LIB = sig SRCS = \ sigaction.c \ sigcompat.c \ sighdl.c .include <lib.mk>
a simple program makefile:
PROG = cat SRCS = cat.c .include <prog.mk>
in such cases even the SRCS line is unnecessary as prog.mk will default it to ${PROG}.c.
It is the sensible use of defaults and the plethora of macro modifiers provided by bmake that allow simple makefiles such as the above just work on many different systems.
This section provides a brief description of some of the *.mk files.
When bmake starts, it looks for sys.mk and reads it before doing anything else. Thus, this is the place to setup the environment for everyone else.
In this distribution, sys.mk avoids doing anything platform dependent. It is quite short, and includes a number of other files (which may or may not exists)
If it exists, is expected to do things like conditioning the environment. Since it will only be included by the initial instance of bmake, it should .export anything that sub-makes might need.
For example (the following requires bmake-20091118 or later):
.if ${.MAKE.LEVEL} == 0 # we save any env var that starts with these MAKE_SAVE_ENV_PREFIX += SB MK MAKE NEED_ CCACHE SSH env_vars != env | egrep '^(${MAKE_SAVE_ENV_PREFIX:ts|})' | sed 's,=.*,,'; echo MAKE_SAVE_ENV_VARS += \ PATH HOME USER \ SRCTOP OBJTOP \ ${env_vars} _export_list = .for v in ${MAKE_SAVE_ENV_VARS:O:u} .if !empty($v) _export_list += $v # save the original value, preserving any var references $v != env | sed -n '/^$v=/{ s,$v=,,;s,\$$,$$$$,g;p;q; }' .endif .endfor # now clobber the environment .unexport-env # export our selection .export ${_export_list} .endif
The above arrangement makes it easy for the mk files to be part of a src tree on an NFS volume and to allow building on multiple platforms.
This file is used to build a number of different libraries from the same SRCS.
A shared library. The value of LD_so is very platform specific. For example:
# SunOS 5 and most other ELF systems libsslfd.so.1 # Darwin libsslfd.1.dylib
This library will only be built if SHLIB_MAJOR has a value, and MKPIC is not set to "no".
There is a lot of platform specific tweaking in lib.mk, largely the result of the original distributions trying to avoid interfering with the system's sys.mk.
This is included by both prog.mk and lib.mk and tries to include *.libnames.mk of which:
does not exist unless you create it. It is a handy way for you to customize without touching the distributed files. For example, on a test machine I needed to build openssl but not install it, so put the following in local.libnames.mk:
.if ${host_os} == "sunos" LIBCRYPTO = ${OBJTOP}/openssl/lib/crypto/libcrypto${DLIBEXT} LIBSSL = ${OBJTOP}/openssl/lib/ssl/libssl${DLIBEXT} INCLUDES_libcrypto = -I${OBJ_libcrypto} .endif
The makefile created an openssl dir in ${OBJ_libcrypto} to gather all the headers. dpadd.mk did the rest.
Each file above gets an opportunity to define things like:
LIBSSLFD ?= ${OBJTOP}/ssl/lib/sslfd/libsslfd${DLIBEXT} INCLUDES_libsslfd = -I${SRC_libsslfd}/h -I${OBJ_libslfd}
these are used by dpadd.mk and will be explained below.
This file looks like line noise, and is best considered read-only. However it provides some very useful functionality, which simplifies the build.
Makefiles can use the LIB* macros defined via libnames.mk or anywhere else in various ways:
# indicate that we need to include headers from LIBCRYPTO # this would result in ${INCLUDES_libcrypto} being added to CFLAGS. SRC_LIBS += ${LIBCRYPTO} # indicate that libsslfd must be built already. # it also has the same effect as SRC_LIBS DPADD += ${LIBSSLFD} # indicate that not only must libsslfd be built, # but that we need to link with it. # this is exactly equivalent to # DPADD += ${LIBSSLFD} # LDADD += -L${LIBSSLFD:H} -lsslfd # and mostly serves to ensure that DPADD and LDADD are in sync. DPLIBS += ${LIBSSLFD}
Any library (referenced by its full path) in any of the above, is added to DPMAGIC_LIBS with the following results, for each lib foo.
What to add to CFLAGS to find the public headers. The default varies. If ${SRC_libfoo}/h exists, it is assumed to be the home of all public headers and thus the default is -I${SRC_libfoo}/h
Otherwise we make no assumptions and the default is -I${SRC_libfoo} -I${OBJ_libfoo}
Compiles the specified SRCS and links them and the nominated libraries into a program. Prog makefiles usually need to list the libraries that need to be linked. We prefer use of DPLIBS but the more traditional DPADD and LDADD work just as well. That is:
DPLIBS += ${LIBCRYPTO}
is exactly equivalent to:
DPADD += ${LIBCRYPTO} LDADD += -lcrypto
One of the cool aspects of BSD make, is its support for separating object files from the src tree. This is also the source of much confusion to some.
Traditionally one had to do a separate make obj pass through the tree. If MKOBJDIRS is "auto", we include auto.obj.mk.
This leverages the .OBJDIR target introduced some years ago to NetBSD make, to automatically create the desired object dir.
This is the traditional means of walking the tree. A makefile sets SUBDIR to the list of sub-dirs to visit.
If SUBDIR_MUST_EXIST is set, missing directories cause an error, otherwise a warning is issued. If you don't even want the warning, set MISSING_DIR=continue.
Traditionally, subdir.mk prints clue as it visits each subdir:
===> ssl ===> ssl/lib ===> ssl/lib/sslfd
you can suppress that - or enhance it by setting ECHO_DIR:
# suppress subdir noise ECHO_DIR=: # print time stamps ECHO_DIR=echo @ `date "+%s [%Y-%m-%d %T] "`
Provides rules for processing lists of LINKS and SYMLINKS. Each is expected to be a list of link and target pairs (link -> target).
The logic is generally in a _*_SCRIPT which is referenced in a _*_USE (.USE) target.
The _BUILD_* forms are identical, but do not use ${DESTDIR} and so are useful for creating symlinks during the build phase. For example:
SYMLINKS += ${.CURDIR}/${MACHINE_ARCH}/include machine header_links: _BUILD_SYMLINKS_USE md.o: header_links
would create a symlink called machine in ${.OBJDIR} pointing to ${.CURDIR}/${MACHINE_ARCH}/include before compiling md.o
Deals with running (or generating) GNU autoconf configure scripts.
Deals with collecting dependencies. Another useful feature of BSD make is the separation of this sort of information into a .depend file. MKDEP needs to point to a suitable tool (like mkdeps.sh)
If USE_AUTODEP_MK is "yes" includes autodep.mk
Leverages the -MD feature of recent GCC to collect dependency information as a side effect of compilation. With this GCC puts dependency info into a .d file.
Unfortunately GCC bases the name of the .d file on the name of the input rather than the output file, which causes problems when the same source is compiled different ways. The latest GCC supports -MF to name the .d file and -MT to control the name to put as the dependent.
Recent bmake allows dependencies for the .END target (run at the end if everything was successful), and autodep.mk uses this to post process the .d files into .depend.
Normally included by init.mk (included by lib.mk and prog.mk etc), sets macros for default ownership etc.
It includes ${MAKECONF} if it is defined and exists.
Deals with man pages.
This provides a means of fine grained control over warnings on a per ${MACHINE} or even file basis.
A makefile sets WARNINGS_SET to name a list of warnings and individual W_* macros can be used to tweak them. For example:
WARNINGS_SET = HIGH W_unused_sparc = -Wno-unused
would add all the warnings in ${HIGH_WARNINGS} to CFLAGS, but on sparc, -Wno-unused would replace -Wunused.
You should never need to edit warnings.mk, it will include warnings-sets.mk if it exists and you use that to make any local customizations.
You can use the content of mk.tar.gz without installing at all.
The script install-mk takes care of copying *.mk into a destination directory, and unless told not to, create bsd.*.mk links for lib.mk etc.
Author: | sjg@crufty.net |
---|---|
Revision: | $Id: mk-files.txt,v 1.6 2010/01/05 22:03:54 sjg Exp $ |
Copyright: | Crufty.NET |