1N/A# The contents of this file are subject to the terms of the
1N/A# Common Development and Distribution License (the "License").
1N/A# You may not use this file except in compliance with the License.
1N/A# See the License for the specific language governing permissions
1N/A# and limitations under the License.
1N/A# When distributing Covered Code, include this CDDL HEADER in each
1N/A# If applicable, add the following below this CDDL HEADER, with the
1N/A# fields enclosed by brackets "[]" replaced with your own identifying
1N/A# information: Portions Copyright [yyyy] [name of copyright owner]
1N/A# Copyright (c) 2001, 2012, Oracle
and/or its affiliates. All rights reserved.
Writing Library Makefiles in ON
===============================
This document guides you through the gnarly process of writing library
Makefiles for the ON consolidation. It assumes that you're comfortable with
make(1) and are somewhat familiar with the ON Makefile standards outlined in
Your library should consist of a hierarchical collection of Makefiles:
This is your library's top-level Makefile. It should contain rules
for building any ISA-independent targets, such as installing header
files and building message catalogs, but should defer all other
targets to ISA-specific Makefiles.
This is your library's common Makefile. It should contain rules
and macros which are common to all ISAs. This Makefile should never
be built explicitly, but instead should be included (using the make
include mechanism) by all of your ISA-specific Makefiles.
lib/<library>/<isa>/Makefile
These are your library's ISA-specific Makefiles, one per ISA
(usually sparc and i386, and often sparcv9 and amd64). These
Makefiles should include your common Makefile and then provide any
needed ISA-specific rules and definitions, perhaps overriding those
provided in your common Makefile.
To simplify their maintenance and construction, $(SRC)/lib has a handful of
provided Makefiles that yours must include; the examples provided throughout
the document will show how to use them. Please be sure to consult these
Makefiles before introducing your own custom build macros or rules.
This contains the bulk of the macros for building shared objects.
This contains macros for building 64-bit objects, and should be
included in Makefiles for 64-bit native ISAs.
This contains macro overrides for libraries that install into /lib
This contains rules for building shared objects.
The remainder of this document discusses how to write each of your Makefiles
in detail, and provides examples from the libinetutil library.
The Library Top-level Makefile
------------------------------
As described above, your top-level library Makefile should contain
rules for building ISA-independent targets, but should defer the
building of all other targets to ISA-specific Makefiles. The
ISA-independent targets usually consist of:
Install all library header files into the proto area.
Can be omitted if your library has no header files.
Check all library header files for hdrchk compliance.
Can be omitted if your library has no header files.
Build and install a message catalog.
Can be omitted if your library has no message catalog.
Of course, other targets (such as `cstyle') are fine as well, as long as
they are ISA-independent.
it easy for you to install and check your library's header files. To use
these targets, your Makefile must set the HDRS to the list of your library's
header files to install and HDRDIR to the their location in the source tree.
In addition, if your header files need to be installed in a location other
than $(ROOT)
/usr/include, your Makefile must also set ROOTHDRDIR to the
appropriate location in the proto area. Once HDRS, HDRDIR and (optionally)
ROOTHDRDIR have been set, your Makefile need only contain
to bind the provided targets to the standard `install_h' and `check' rules.
you to build and install message catalogs from your library's source files.
To install a catalog into the catalog directory in the proto area, define the
POFILE macro to be the name of your catalog, and specify that the _msg target
depends on $(MSGDOMAINPOFILE). The examples below should clarify this.
To build a message catalog from arbitrarily many message source files, use
MSGFILES = $(OBJECTS:%.o=%.i)
Note that this example doesn't use grep to find message files, since that can
mask unreferenced files, and potentially lead to the inclusion of unwanted
messages or omission of intended messages in the catalogs. As such, MSGFILES
should be derived from a known list of objects or sources.
It is usually preferable to run the source through the C preprocessor prior
to extracting messages. To do this, use the ".i" suffix, as shown in the
above example. If you need to skip the C preprocessor, just use the native
extracting messages is when you're extracting them from shell scripts; in
To build a message catalog from other message catalogs, or from source files
POFILES = $(SUBDIRS:%=%/_%.po)
The Makefile above would work in conjunction with the following in its
subdirectories' Makefiles:
MSGFILES = $(OBJECTS:%.o=%.i)
Since this POFILE will be combined with those in other subdirectories by the
parent Makefile and that merged file will be installed into the proto area
via MSGDOMAINPOFILE, there is no need to use MSGDOMAINPOFILE in this Makefile
(in fact, using it would lead to duplicate messages in the catalog).
When using any of these targets, keep in mind that other macros, like
XGETFLAGS and TEXT_DOMAIN may also be set in your Makefile to override or
augment the defaults provided in higher-level Makefiles.
As previously mentioned, you should defer all ISA-specific targets to your
ISA-specific Makefiles. You can do this by:
1. Setting SUBDIRS to the list of directories to descend into:
Note that if your library is also built 64-bit, then you should
$(BUILD64)SUBDIRS += $(MACH64)
so that SUBDIRS contains $(MACH64) if and only if you're compiling
2. Providing a common "descend into SUBDIRS" rule:
@cd $@; pwd; $(MAKE) $(TARGET)
3. Providing a collection of conditional assignments that set TARGET
clobber := TARGET= clobber
install := TARGET= install
stubinstall := TARGET= stub
The order doesn't matter, but alphabetical is preferable.
4. Having the aforementioned targets depend on SUBDIRS:
all clean clobber install lint stub stubinstall: $(SUBDIRS)
The `all' target must be listed first so that make uses it as the
default target; the others might as well be listed alphabetically.
As an example of how all of this goes together, here's libinetutil's
top-level library Makefile (license notice and copyright omitted):
$(BUILD64)SUBDIRS += $(MACH64)
clobber := TARGET = clobber
install := TARGET = install
stubinstall := TARGET = stubinstall
all clean clobber install lint stub stubinstall: $(SUBDIRS)
@cd $@; pwd; $(MAKE) $(TARGET)
In concept, your common Makefile should contain all of the rules and
definitions that are the same on all ISAs. However, for reasons of
maintainability and cleanliness, you're encouraged to place even
ISA-dependent rules and definitions, as long you express them in an
ISA-independent way (
e.g., by using $(MACH), $(TARGETMACH), and their kin).
(TARGETMACH is the same as MACH for 32-bit targets, and the same as MACH64
The common Makefile can be conceptually split up into four sections:
1. A copyright and comments section. Please see the prototype
copyright message properly. For brevity and clarity, this
section has been omitted from the examples shown here.
2. A list of macros that must be defined prior to the inclusion of
installed in /lib rather than the default
/usr/lib).
3. A list of macros that need not be defined prior to the inclusion
of
Makefile.lib (or which must be defined following the inclusion
of
Makefile.lib, to override or augment its definitions). This
section is conceptually terminated by the .KEEP_STATE directive.
The first section is self-explanatory. The second typically consists of the
Set to the name of the static version of your library, such
since pattern-matching rules in higher-level Makefiles rely on it,
even though static libraries are not normally built in ON, and
are never installed in the proto area. Note that the LIBS macro
(described below) controls the types of libraries that are built
when building your library.
If you are building a loadable module (
i.e., a shared object that
is only linked at runtime with dlopen(3dl)), specify the name of
Set to the version of your shared library, such as `.1'. You
actually do not need to set this prior to the inclusion of
Makefile.lib, but it is good practice to do so since VERS and
LIBRARY are so closely related.
Set to the list of object files contained in your library, such as
`
a.o b.o'. Usually, this will be the same as your library's source
files (except with .o extensions), but if your library compiles
source files outside of the library directory itself, it will
differ. We'll see an example of this with libinetutil.
The third section typically consists of the following macros:
Set to the list of the types of libraries to build when building
your library. For dynamic libraries, you should set this to
`$(DYNLIB) $(LINTLIB)' so that a dynamic library and lint library
are built. For loadable modules, you should just list DYNLIB,
since there's no point in building a lint library for libraries
that are never linked at compile-time.
If your library needs to be built as a static library (typically
to be used in other parts of the build), you should set LIBS to
`$(LIBRARY)'. However, you should do this only when absolutely
necessary, and you must *never* ship static libraries to customers.
INSTALL_LIBDIR / INSTALL_LIBDIR64
(if your library installs to a nonstandard directory)
INSTALL_LIBDIR and INSTALL_LIBDIR64 are set to the relative
path of the directories your 32 and 64-bit objects will install
to, respectively. INSTALL_LIBDIR64 is by default defined as
$(INSTALL_LIBDIR)/$(MACH64), and so, most libraries need only
define INSTALL_LIBDIR. For example, FMA objects are generally
INSTALL_LIBDIR and INSTALL_LIBDIR64 are in turn used by
ROOTLIBDIR / ROOTLIBDIR64
STUBROOTLIBDIR / STUBROOTLIBDIR64
LROOTLIBDIR / LROOTLIBDIR64
You should not set these macros directly. However, it is useful
to understand their purpose.
ROOTLIBDIR and ROOTLIBDIR64 are set to the directories your
32, and 64-bit objects will install to, respectively.
STUBROOTLIBDIR and STUBROOTLIBDIR64 are set to the directories
your stub objects are installed to.
LROOTLIBDIR and LROOTLIBDIR64 are set to the same values as
ROOTLIBDIR and ROOTLIBDIR64 when the lint target is in force,
and the values of STUBROOTLIBDIR and STUBROOTLIBDIR64 otherwise.
They are used when setting the -L flag for linking and lint
The use of INSTALL_LIBDIR ensures that these 6 macros are always
defined as a consistent unit. The default value of INSTALL_LIBDIR
is
usr/lib, meaning that the derived macros have the following
STUBROOTLIBDIR64 $(STUBROOT)
/usr/lib/$(MACH64)
LROOTLIBDIR64 $(LROOT)
/usr/lib/$(MACH64)
ROOTLIBDIR64 $(ROOT)/lib/$(MACH64)
STUBROOTLIBDIR $(STUBROOT)/lib
STUBROOTLIBDIR64 $(STUBROOT)/lib/$(MACH64)
LROOTLIBDIR64 $(LROOT)/lib/$(MACH64)
Set to the directory containing your library's source files, such
as `../common'. Because this Makefile is actually included from
your ISA-specific Makefiles, make sure you specify the directory
relative to your library's <isa> directory.
Set to the list of source files required to build your library.
This defaults to $(OBJECTS:%.o=$(SRCDIR)/%.c) in
Makefile.lib, so
you only need to set this when source files from directories other
than SRCDIR are needed. Keep in mind that SRCS should be set to a
list of source file *pathnames*, not just a list of filenames.
LINTLIB-specific SRCS (required if building a lint library)
Set to a special "lint stubs" file to use when constructing your
library's lint library. The lint stubs file must be used to
guarantee that programs that link against your library will be able
to lint clean. To do this, you must conditionally set SRCS to use
your stubs file by specifying `LINTLIB := SRCS= $(SRCDIR)/$(LINTSRC)'
in your Makefile. Of course, you do not need to set this if your
library does not build a lint library.
Appended with the list of libraries and library directories needed
to build your library; minimally "-lc". Note that this should
*never* be set, since that will inadvertently clear the library
search path, causing the linker to look in the wrong place for
Since lint targets also make use of LDLIBS, LDLIBS *must* only
contain -l and -L directives; all other link-related directives
should be put in DYNFLAGS (if they apply only to shared object
construction) or LDFLAGS (if they apply in general).
Any -L directive that references the workspace proto area
should use the $(LROOT) macro as follows:
LROOT resoves to ROOT or STUBROOT depending on whether the
lint target is in force when LROOT is evaluated. ROOT and STUBROOT
should not be directly used for -L options in LDLIBS.
Set to the list of mapfiles used to link each ISA-specific version
of your library. This defaults to `$(SRCDIR)/mapfile-vers' in
Makefile.lib, so you only need to change this if you have additional
mapfiles or your mapfile doesn't follow the standard naming
convention. If you have supplemental ISA-dependent mapfiles that
reside in the respective <isa> directories, you can augment
Appended with any flags that need to be passed to the C
preprocessor (typically -D and -I flags). Since lint macros use
CPPFLAGS, CPPFLAGS *must* only contain directives known to the C
preprocessor. When compiling MT-safe code, CPPFLAGS *must*
include -D_REENTRANT. When compiling large file aware code,
CPPFLAGS *must* include -D_FILE_OFFSET_BITS=64.
Appended with any flags that need to be passed to the C compiler.
Minimally, append `$(CCVERBOSE)'. Keep in mind that you should
add any C preprocessor flags to CPPFLAGS, not CFLAGS.
Appended with any flags that need to be passed to the C compiler
when compiling 64-bit code. Since all 64-bit code is compiled
$(CCVERBOSE), you usually do not need to modify CFLAGS64.
Set to control the optimization level used by the C compiler when
compiling 32-bit code. You should only set this if absolutely
necessary, and it should only contain optimization-related
COPTFLAG64 (if necessary)
Set to control the optimization level used by the C compiler when
compiling 64-bit code. You should only set this if absolutely
necessary, and it should only contain optimization-related
Appended with any flags that need to be passed to lint when
linting 32-bit code. You should only modify LINTFLAGS in
rare instances where your code cannot (or should not) be fixed.
LINTFLAGS64 (if necessary)
Appended with any flags that need to be passed to lint when
linting 64-bit code. You should only modify LINTFLAGS64 in
rare instances where your code cannot (or should not) be fixed.
Of course, you may use other macros as necessary.
The fourth section typically consists of the following targets:
Build all of the types of the libraries named by LIBS. Must always
be the first real target in common Makefile. Since the
higher-level Makefiles already contain rules to build all of the
different types of libraries, you can usually just specify
though it should be listed as an empty target if LIBS is set by your
ISA-specific Makefiles (see above).
actual library sources. Historically, this target has also been
used to build the lint library (using LINTLIB), but that usage is
now discouraged. Thus, this rule should be specified as
Conspicuously absent from this section are the `clean' and `clobber' targets.
be provided by your common Makefile. Instead, your common Makefile should
list any additional files to remove during a `clean' and `clobber' by
appending to the CLEANFILES and CLOBBERFILES macros.
Once again, here's libinetutil's common Makefile, which shows how many of
LIBS = $(DYNLIB) $(LINTLIB)
$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC)
The mapfile for libinetutil is named `mapfile-vers' and resides in $(SRCDIR),
so the MAPFILES definition is omitted, defaulting to $(SRCDIR)/mapfile-vers.
Note that for libinetutil, not all of the object files come from SRCDIR. To
support this, an alternate source file directory named COMDIR is defined, and
the source files listed in SRCS are specified using both COMDIR and SRCDIR.
Additionally, a special build rule is provided to build object files from the
sources in COMDIR; the rule uses
COMPILE.c and POST_PROCESS_O so that any
changes to the compilation and object-post-processing phases will be
The ISA-Specific Makefiles
--------------------------
As the name implies, your ISA-specific Makefiles should contain macros and
rules that cannot be expressed in an ISA-independent way. Usually, the only
rules you will need to put here are `install' and `stubinstall', which have
different dependencies for 32-bit and 64-bit libraries. For instance, here
are the ISA-specific Makefiles for libinetutil. As is often the case, the
32-bit Makefiles are the same for x86 and sparc, as are the 64-bit Makefiles,
so we only show their contents once here:
install: stubinstall all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
stubinstall: stub $(STUBROOTLIBS) $(STUBROOTLINKS)
install: stubinstall all $(ROOTLIBS64) $(ROOTLINKS64)
stubinstall: stub $(STUBROOTLIBS64) $(STUBROOTLINKS64)
Observe that there is no .KEEP_STATE directive in these Makefiles, since all
.KEEP_STATE directive. Also, note that the 64-bit Makefiles also include
higher level Makefiles included by the common Makefile so that 64-bit
By default, all position-independent objects are built with CTF data using
ctfconvert, which is then merged together using ctfmerge when the shared
object is built. All C-source objects processed via ctfmerge need to be
processed via ctfconvert or the build will fail. Objects built from non-C
sources (such as assembly or C++) are silently ignored for CTF processing.
Filter libraries that have no source files will need to explicitly disable
Other issues and questions will undoubtedly arise while you work on your
library's Makefiles. To help in this regard, a number of libraries of
varying complexity have been updated to follow the guidelines and practices
outlined in this document:
Example of a simple 32-bit only library.
Example of a simple 32-bit only library that obtains its sources
from multiple directories.
Example of a simple loadable module.
Example of a simple library that builds a message catalog.
Example of a Makefile hierarchy for a library and a collection
of related pluggable modules.
Example of a Makefile hierarchy for a collection of related
libraries and pluggable modules.
Also an example of a Makefile hierarchy that supports the
_dc target for domain and category specific messages.
Of course, if you still have questions, please do not hesitate to send email