Name Date Size

.. 2012-09-28 00:00:56 8

abi 2012-04-19 18:27:59 6

auditd_plugins 2012-02-29 02:20:34 7

brand 2011-09-29 18:19:17 9

c_synonyms 2011-09-29 18:19:17 10

cfgadm_plugins 2012-02-25 00:21:55 14

common 2011-09-29 18:19:18 9

crypt_modules 2012-04-19 18:27:59 10

efcode 2012-04-19 18:27:59 17

extendedFILE 2011-09-29 18:19:18 7

fm 2012-04-19 18:27:59 22

gss_mechs 2011-09-29 18:19:28 6

hal 2012-09-27 22:35:36 8

hbaapi 2012-09-27 22:35:34 11

inc.flg 2011-09-29 18:19:28 1.3 KiB

krb5 2012-04-19 18:27:59 12

libadm 2011-09-29 18:19:28 10

libadr 2012-05-18 20:59:29 9

libadt_jni 2011-09-29 18:19:28 11

libadutils 2011-09-29 18:19:28 9

libaio 2011-09-29 18:19:30 9

libast 2011-07-18 04:52:02 12

libavl 2011-09-29 18:19:32 12

libbe 2011-09-29 18:19:32 8

libbootmgmt 2012-03-29 03:10:22 9

libbrand 2011-09-29 18:19:32 10

libbsdmalloc 2011-09-29 18:19:32 11

libbsm 2012-06-28 20:11:46 19

libc 2012-05-08 02:11:56 19

libc_db 2011-09-29 18:19:34 9

libcfgadm 2011-09-29 18:19:34 10

libcmd 2012-09-27 22:35:35 12

libcmdutils 2012-05-17 19:02:19 10

libcommputil 2011-09-29 18:19:34 9

libcontract 2011-09-29 18:19:34 9

libcpc 2011-09-29 18:19:34 9

libcrypt 2011-09-29 18:19:34 10

libcryptoutil 2012-03-15 17:55:32 10

libctf 2011-09-29 18:19:34 9

libcurses 2011-09-29 18:19:34 9

libdevalloc 2011-09-29 18:19:34 9

libdevice 2011-09-29 18:19:34 12

libdevid 2011-09-29 18:19:34 13

libdevinfo 2012-07-02 23:12:41 28

libdhcpagent 2012-05-31 06:17:52 10

libdhcpdu 2012-04-19 18:27:59 8

libdhcpsvc 2011-09-29 18:19:34 10

libdhcputil 2012-05-31 06:17:52 12

libdiagcode 2011-09-29 18:19:34 3

libdisasm 2011-09-29 18:19:34 10

libdiskmgt 2011-09-29 18:19:34 9

libdladm 2012-05-31 06:17:52 10

libdll 2011-07-18 04:52:13 12

libdlpi 2011-09-29 18:19:34 9

libdns_sd 2011-09-29 18:19:34 13

libdoor 2011-09-29 18:19:34 9

libds 2011-09-29 18:19:34 7

libdscfg 2011-09-29 18:19:34 7

libdscp 2012-04-19 18:27:59 10

libdtrace 2011-11-15 21:10:24 9

libdtrace_jni 2011-09-29 18:19:35 10

libecp 2012-03-23 21:38:16 7

libefi 2011-09-29 18:19:35 9

libelfsign 2012-03-21 01:07:12 8

libeti 2011-09-29 18:19:35 7

libexacct 2011-09-29 18:19:35 11

libfcoe 2011-09-29 18:19:35 9

libfdisk 2011-09-29 18:19:35 7

libfedfs 2012-05-18 01:29:24 9

libfru 2011-09-29 18:19:35 19

libfruutils 2011-09-29 18:19:35 11

libfsmgt 2011-09-29 18:19:35 7

libfstyp 2011-09-29 18:19:35 7

libfuse 2012-09-27 22:35:34 13

libgen 2011-09-29 18:19:35 10

libgss 2012-02-09 17:52:17 52

libhotplug 2011-09-29 18:19:36 9

libidmap 2011-09-29 18:19:36 9

libilb 2011-09-29 18:19:36 9

libima 2012-09-27 22:35:35 11

libinetsvc 2011-09-29 18:19:36 7

libinetutil 2011-09-29 18:19:36 9

libinstzones 2012-02-24 03:08:11 8

libintl 2011-09-29 18:19:36 9

libiov 2012-04-11 16:37:41 9

libipadm 2012-05-31 06:17:52 10

libipmi 2011-09-29 18:19:36 9

libipmp 2011-09-29 18:19:36 7

libipp 2011-09-29 18:19:36 12

libipsecutil 2011-09-29 18:19:36 9

libiscsit 2011-09-29 18:19:36 9

libkmf 2012-09-28 00:43:39 10

libkrb5 2011-09-29 18:19:36 9

libkstat 2011-09-29 18:19:36 10

libkvm 2011-09-29 18:19:36 10

libldap4 2012-09-27 22:35:34 16

libldap5 2012-09-27 22:35:36 13

liblgrp 2011-09-29 18:19:36 9

liblldp 2011-09-29 18:19:36 9

liblm 2011-09-29 18:19:36 9

libmail 2011-10-28 03:40:28 10

libmalloc 2011-09-29 18:19:36 9

libmapid 2012-04-19 18:27:59 7

libmapmalloc 2011-09-29 18:19:36 9

libmd 2012-07-02 22:27:57 12

libmd5 2011-09-29 18:19:36 9

libmp 2011-11-30 21:00:43 9

libmtmalloc 2011-09-29 18:19:36 10

libndmp 2011-09-29 18:19:36 9

libndr 2011-09-29 18:19:36 9

libnetcfg 2012-05-31 06:17:52 10

libnisdb 2011-09-29 18:19:37 87

libnls 2011-09-29 18:19:37 9

libnsctl 2011-09-29 18:19:37 7

libnsl 2012-02-07 19:11:45 24

libntfs 2012-09-27 22:35:36 10

libntsvcs 2012-05-17 22:23:58 9

libnvpair 2011-09-29 18:19:37 14

libnwam 2012-05-31 06:17:52 11

libpam 2012-07-10 23:39:49 17

libparted 2012-09-27 22:35:35 11

libpcp 2011-09-29 18:19:37 6

libpctx 2011-09-29 18:19:37 9

libpicl 2011-09-29 18:19:37 13

libpicltree 2011-09-29 18:19:37 12

libpkg 2011-09-29 18:19:37 9

libplot 2011-09-29 18:19:37 10

libpool 2011-09-29 18:19:37 10

libpower 2011-11-23 18:56:39 7

libpp 2011-07-18 04:52:26 10

libpri 2011-09-29 18:19:37 7

libproc 2011-10-28 03:40:28 9

libproject 2011-09-29 18:19:37 9

libprtdiag 2012-02-25 00:21:55 7

libprtdiag_psr 2011-09-29 18:19:37 4

libpthread 2011-09-29 18:19:37 9

libradproto 2012-05-18 20:59:29 9

libraidcfg 2011-09-29 18:19:37 9

librcm 2011-09-29 18:19:37 15

librdc 2011-09-29 18:19:37 7

libreparse 2011-09-29 18:19:37 9

libresolv 2011-09-29 18:19:37 17

libresolv2 2012-09-06 23:13:12 14

librestart 2012-02-07 19:11:45 9

librpcsvc 2011-09-29 18:19:38 9

librstp 2012-09-27 22:35:35 7

librt 2011-09-29 18:19:38 9

libsasl 2011-09-29 18:19:38 14

libscf 2011-09-29 18:19:38 12

libsched 2011-09-29 18:19:38 9

libsctp 2011-09-29 18:19:38 9

libsec 2011-09-29 18:19:38 10

libsecdb 2012-08-06 11:59:41 17

libsendfile 2011-09-29 18:19:38 9

libshadowfs 2012-04-19 18:27:59 9

libshadowtest 2011-09-29 18:19:38 9

libshare 2012-05-19 00:58:39 9

libshare_plugins 2011-09-29 18:19:38 9

libshell 2011-08-24 03:59:52 15

libsip 2011-09-29 18:19:38 9

libsldap 2011-10-28 03:40:28 10

libslp 2011-09-29 18:19:38 11

libsmb 2012-03-24 23:06:14 9

libsmbfs 2012-05-17 22:23:58 9

libsmbios 2011-09-29 18:19:38 9

libsmbns 2012-04-19 18:27:59 9

libsmbrp 2012-04-19 18:27:59 9

libsmedia 2011-09-29 18:19:38 5

libsocket 2011-09-29 18:19:39 11

libsoftcrypto 2012-07-02 22:27:57 11

libsqlite 2011-09-29 18:19:39 14

libsrpt 2011-09-29 18:19:39 9

libstmf 2011-09-29 18:19:39 9

libstmfproxy 2011-09-29 18:19:39 9

libsum 2011-07-18 04:52:37 12

libsun_ima 2011-10-28 03:40:28 9

libsuri 2012-05-16 23:04:52 9

libsys 2011-09-29 18:19:39 8

libsysevent 2011-09-29 18:19:39 14

libthread 2011-09-29 18:19:39 9

libtsalarm 2011-09-29 18:19:39 6

libtsnet 2011-09-29 18:19:39 9

libtsol 2011-09-29 18:19:39 9

libuefi_rt 2012-03-29 03:10:22 7

libumem 2011-10-28 03:40:28 10

libunistat 2011-09-29 18:19:39 7

libuuid 2011-09-29 18:19:39 9

libuutil 2011-09-29 18:19:39 11

libuvfs 2012-02-09 17:52:17 9

libv12n 2011-09-29 18:19:39 7

libvdp 2012-03-23 21:38:16 7

libvolmgt 2011-09-29 18:19:39 10

libvrrpadm 2011-09-29 18:19:39 10

libvscan 2012-04-19 18:27:59 7

libw 2011-09-29 18:19:39 9

libwanboot 2011-09-29 18:19:39 9

libwanbootutil 2012-04-19 18:27:59 9

libwrap 2011-09-29 18:19:39 32

libxcurses 2012-04-19 18:27:59 10

libxcurses2 2012-04-19 18:27:59 11

libxnet 2011-09-29 18:19:39 9

libxprop 2012-05-19 00:58:39 9

libzfs 2012-05-19 00:58:39 10

libzfs_jni 2011-09-29 18:19:39 9

libzonecfg 2012-06-25 12:48:29 10

libzoneinfo 2011-09-29 18:19:39 7

libzonestat 2011-09-29 18:19:39 9

libzpool 2012-05-19 00:58:39 9

lvm 2012-06-14 22:12:33 7

madv 2011-09-29 18:19:40 9

Makefile 2012-06-14 22:12:33 10.3 KiB

Makefile.filter.com 2011-09-29 18:19:17 2.9 KiB

Makefile.filter.targ 2011-09-29 18:19:17 1.4 KiB

Makefile.lib 2012-04-19 18:27:59 10.8 KiB

Makefile.lib.64 2011-09-29 18:19:17 1.1 KiB

Makefile.mach 2011-09-29 18:19:17 1.7 KiB

Makefile.rootfs 2012-04-19 18:27:59 1,007

Makefile.stub.targ 2011-09-29 18:19:17 2.2 KiB

Makefile.targ 2012-06-21 19:12:50 3.6 KiB

mpapi 2012-09-27 22:35:34 5

mpss 2011-09-29 18:19:40 9

nametoaddr 2011-09-29 18:19:40 4

ncad_addr 2011-09-29 18:19:40 9

nsswitch 2012-09-06 23:13:12 16

pam_modules 2012-09-27 22:35:34 30

passwdutil 2012-08-22 12:46:40 27

pkcs11 2012-09-27 22:35:35 11

policykit 2012-09-27 22:35:36 8

pybootmgmt 2012-09-27 22:35:36 7

pylibbe 2012-09-27 22:35:35 7

pysolaris 2012-09-27 22:35:34 8

pyzfs 2012-06-21 19:12:50 7

rad 2012-05-18 20:59:29 7

raidcfg_plugins 2011-09-29 18:19:40 3

README.Makefiles 2012-04-19 18:27:59 23.9 KiB

README.mapfiles 2012-05-15 18:33:01 22.4 KiB

req.flg 2011-09-29 18:19:40 1.2 KiB

rpcsec_gss 2011-09-29 18:19:40 13

sasl_plugins 2012-04-19 18:27:59 10

scsi 2011-09-29 18:19:40 10

smhba 2012-09-27 22:35:35 11

storage 2011-09-29 18:19:41 6

sun_fc 2011-10-28 03:40:28 9

sun_sas 2011-09-29 18:19:41 9

udapl 2011-09-29 18:19:41 5

watchmalloc 2011-09-29 18:19:41 9

README.Makefiles

#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
#
Writing Library Makefiles in ON
===============================
Introduction
------------
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
/shared/ON/general_docs/make_std.txt.
Makefile Overview
-----------------
Your library should consist of a hierarchical collection of Makefiles:
lib/<library>/Makefile:
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.
lib/<library>/Makefile.com
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.
lib/Makefile.lib:
This contains the bulk of the macros for building shared objects.
lib/Makefile.lib.64
This contains macros for building 64-bit objects, and should be
included in Makefiles for 64-bit native ISAs.
lib/Makefile.rootfs
This contains macro overrides for libraries that install into /lib
(rather than /usr/lib).
lib/Makefile.targ
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_h
Install all library header files into the proto area.
Can be omitted if your library has no header files.
check
Check all library header files for hdrchk compliance.
Can be omitted if your library has no header files.
_msg
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.
The ROOTHDRS and CHECKHDRS targets are provided in lib/Makefile.lib to make
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
install_h: $(ROOTHDRS)
check: $(CHECKHDRS)
to bind the provided targets to the standard `install_h' and `check' rules.
Similar rules are provided (in $(SRC)/Makefile.msg.targ) to make it easy for
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
the BUILDPO.msgfiles macro.
include ../Makefile.lib
POFILE = libfoo.po
MSGFILES = $(OBJECTS:%.o=%.i)
# ...
$(POFILE): $(MSGFILES)
$(BUILDPO.msgfiles)
_msg: $(MSGDOMAINPOFILE)
include $(SRC)/Makefile.msg.targ
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
(.[ch]) suffix.
The only time you shouldn't use BUILDPO.msgfiles as the preferred means of
extracting messages is when you're extracting them from shell scripts; in
that case, you can use the BUILDPO.pofiles macro as explained below.
To build a message catalog from other message catalogs, or from source files
that include shell scripts, use the BUILDPO.pofiles macro:
include ../Makefile.lib
SUBDIRS = $(MACH)
POFILE = libfoo.po
POFILES = $(SUBDIRS:%=%/_%.po)
_msg := TARGET = _msg
# ...
$(POFILE): $(POFILES)
$(BUILDPO.pofiles)
_msg: $(MSGDOMAINPOFILE)
include $(SRC)/Makefile.msg.targ
The Makefile above would work in conjunction with the following in its
subdirectories' Makefiles:
POFILE = _thissubdir.po
MSGFILES = $(OBJECTS:%.o=%.i)
$(POFILE): $(MSGFILES)
$(BUILDPO.msgfiles)
_msg: $(POFILE)
include $(SRC)/Makefile.msg.targ
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:
SUBDIRS = $(MACH)
Note that if your library is also built 64-bit, then you should
also specify
$(BUILD64)SUBDIRS += $(MACH64)
so that SUBDIRS contains $(MACH64) if and only if you're compiling
on a 64-bit ISA.
2. Providing a common "descend into SUBDIRS" rule:
$(SUBDIRS): FRC
@cd $@; pwd; $(MAKE) $(TARGET)
FRC:
3. Providing a collection of conditional assignments that set TARGET
appropriately:
all := TARGET= all
clean := TARGET= clean
clobber := TARGET= clobber
install := TARGET= install
lint := TARGET= lint
stub := TARGET= stub
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):
include ../Makefile.lib
HDRS = libinetutil.h
HDRDIR = common
SUBDIRS = $(MACH)
$(BUILD64)SUBDIRS += $(MACH64)
all := TARGET = all
clean := TARGET = clean
clobber := TARGET = clobber
install := TARGET = install
lint := TARGET = lint
stub := TARGET = stub
stubinstall := TARGET = stubinstall
.KEEP_STATE:
all clean clobber install lint stub stubinstall: $(SUBDIRS)
install_h: $(ROOTHDRS)
check: $(CHECKHDRS)
$(SUBDIRS): FRC
@cd $@; pwd; $(MAKE) $(TARGET)
FRC:
include ../Makefile.targ
The Common Makefile
-------------------
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
for 64-bit targets).
The common Makefile can be conceptually split up into four sections:
1. A copyright and comments section. Please see the prototype
files in usr/src/prototypes for examples of how to format the
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
Makefile.lib. This section is conceptually terminated by the
inclusion of Makefile.lib, followed, if necessary, by the
inclusion of Makefile.rootfs (only if the library is to be
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.
4. A list of targets.
The first section is self-explanatory. The second typically consists of the
following macros:
LIBRARY
Set to the name of the static version of your library, such
as `libinetutil.a'. You should always specify the `.a' suffix,
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
the loadable module with a `.a' suffix, such as `devfsadm_mod.a'.
VERS
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.
OBJECTS
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:
LIBS
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
installed under /usr/lib/fm, and so, define:
INSTALL_LIBDIR= usr/lib/fm
INSTALL_LIBDIR and INSTALL_LIBDIR64 are in turn used by
the following macros:
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
operations.
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
default values.
ROOTLIBDIR $(ROOT)/usr/lib
ROOTLIBDIR64 $(ROOT)/usr/lib/$(MACH64)
STUBROOTLIBDIR $(STUBROOT)/usr/lib
STUBROOTLIBDIR64 $(STUBROOT)/usr/lib/$(MACH64)
LROOTLIBDIR $(LROOT)/usr/lib
LROOTLIBDIR64 $(LROOT)/usr/lib/$(MACH64)
If you include Makefile.rootfs, these defaults change to
ROOTLIBDIR $(ROOT)/lib
ROOTLIBDIR64 $(ROOT)/lib/$(MACH64)
STUBROOTLIBDIR $(STUBROOT)/lib
STUBROOTLIBDIR64 $(STUBROOT)/lib/$(MACH64)
LROOTLIBDIR $(LROOT)/lib
LROOTLIBDIR64 $(LROOT)/lib/$(MACH64)
SRCDIR
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.
SRCS (if necessary)
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.
LDLIBS
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
the libraries.
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:
-L$(LROOT)/...
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.
MAPFILES (if necessary)
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
MAPFILES like this:
MAPFILES += mapfile-vers
CPPFLAGS (if necessary)
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.
CFLAGS
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.
CFLAGS64 (if necessary)
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.
COPTFLAG (if necessary)
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
settings (or -g).
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
settings (or -g).
LINTFLAGS (if necessary)
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:
all
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
all: stub $(LIBS)
though it should be listed as an empty target if LIBS is set by your
ISA-specific Makefiles (see above).
lint
Use the `lintcheck' rule provided by lib/Makefile.targ to lint the
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
lint: lintcheck
Conspicuously absent from this section are the `clean' and `clobber' targets.
These targets are already provided by lib/Makefile.targ and thus should not
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
these directives go together. Note that Makefile.rootfs is included to
cause libinetutil.so.1 to be installed in /lib rather than /usr/lib:
LIBRARY = libinetutil.a
VERS = .1
OBJECTS = octet.o inetutil4.o ifspec.o ifaddrlist.o eh.o tq.o
include ../../Makefile.lib
include ../../Makefile.rootfs
LIBS = $(DYNLIB) $(LINTLIB)
SRCDIR = ../common
COMDIR = $(SRC)/common/net/dhcp
SRCS = $(COMDIR)/octet.c $(SRCDIR)/inetutil4.c \
$(SRCDIR)/ifspec.c $(SRCDIR)/eh.c $(SRCDIR)/tq.c \
$(SRCDIR)/ifaddrlist.c
$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC)
LDLIBS += -lsocket -lc
CFLAGS += $(CCVERBOSE)
CPPFLAGS += -I$(SRCDIR)
.KEEP_STATE:
all: stub $(LIBS)
lint: lintcheck
pics/%.o: $(COMDIR)/%.c
$(COMPILE.c) -o $@ $<
$(POST_PROCESS_O)
include ../../Makefile.targ
include ../../Makefile.stub.targ
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
automatically picked up.
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:
i386/Makefile and sparc/Makefile:
include ../Makefile.com
install: stubinstall all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
stubinstall: stub $(STUBROOTLIBS) $(STUBROOTLINKS)
amd64/Makefile and sparcv9/Makefile:
include ../Makefile.com
include ../../Makefile.lib.64
install: stubinstall all $(ROOTLIBS64) $(ROOTLINKS64)
stubinstall: stub $(STUBROOTLIBS64) $(STUBROOTLINKS64)
Observe that there is no .KEEP_STATE directive in these Makefiles, since all
of these Makefiles include libinetutil/Makefile.com, and it already has a
.KEEP_STATE directive. Also, note that the 64-bit Makefiles also include
Makefile.lib.64, which overrides some of the definitions contained in the
higher level Makefiles included by the common Makefile so that 64-bit
compiles work correctly.
CTF Data in Libraries
---------------------
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
CTF by setting CTFMERGE_LIB to ":"; see libw/Makefile.com for an example.
More Information
----------------
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:
lib/libdhcputil
Example of a simple 32-bit only library.
lib/libdhcpagent
Example of a simple 32-bit only library that obtains its sources
from multiple directories.
lib/ncad_addr
Example of a simple loadable module.
lib/libipmp
Example of a simple library that builds a message catalog.
lib/libdhcpsvc
Example of a Makefile hierarchy for a library and a collection
of related pluggable modules.
lib/lvm
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
to the ON gatekeepers.

README.mapfiles

#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
#
Mapfiles and versioning in ON
=============================
1.0 Objective of this README
This README describes the engineering practices of creating and updating
visible library interfaces. It describes various kinds of actions that
typically occur as libraries are evolved, and shows how interface
specifications are affected or updated in accordance. It tells you what
you must do as a shared library developer if you:
1. Make interface additions to an existing library
- add a Public interface
- add a Private interface
2. Update an interface in an existing library
- remove an existing interface
- promote a Private interface to Public
- scope a Private interface to local
- move an interface from one library to another
- copy interfaces which are part of the standard to a new or
existing library
3. Introduce a new library
- source directory hierarchy
- creation of the "mapfile-vers" file
- Makefiles
4. Need to specify the mapfile information that allows a library
to be buildable as a stub object:
- enable the stub object feature
- specify ASSERT information for data symbols
-------------------------------------------------------------------------------
2.0 What's a mapfile?
Mapfiles are used to tell the link-editor ("ld") all sorts of things about
how to generate an executable file or a shared object from a collection of
relocatable objects, such as generated by a compiler. For all the gory
details, see the Solaris Linker and Libraries Guide, which can be found
under http://docs.sun.com.
There are two versions of the mapfile language accepted by the link-editor.
Version 1 derives from AT&T System V Release 4 Unix. Version 2 is a newer
syntax specific to Solaris. All mapfiles in the OSnet (ON consolidation) are
required to use version 2 syntax. Note that every mapfile using version 2
syntax must start with the line:
$mapfile_version 2
Here, we are only concerned with specifying externally-visible interfaces
for shared libraries (shared objects) and with specifying their versions
for ABI (Application Binary Interface) purposes. For these purposes, we
only need to deal with a subset of the mapfile language.
There should be a "mapfile-vers" file associated with every shared library
and it should reside in the common source directory for that library, most
often in a "common" directory. This is the usual layout of a library's
top-level directory (usr/src/lib/libwombat):
Makefile amd64/ i386/ sparcv9/
Makefile.com common/ sparc/
The "common" directory contains the source files and other common files
for the library:
bat.c libwombat_impl.h mapfile-vers wom.c
libwombat.h llib-lwombat util.c wombat.c
The mapfile's name is, by convention, "mapfile-vers" because it is used
for only two purposes: to specify externally-visible interface names while
suppressing visibility of all other names, and to specify their respective
unique version names.
-------------------------------------------------------------------------------
3.0 Contents of mapfile-vers
The structure of mapfile-vers is best explained by an example
(the license notification and copyright notice is omitted here
for brevity):
$mapfile_version 2
STUB_OBJECT;
SYMBOL_VERSION SUNWpublic { # public libwombat symbols
global:
wb_read;
wb_readv;
wb_stat;
wb_write;
wb_writev;
};
SYMBOL_VERSION SUNWprivate { # private libwombat symbols
global:
wb_add;
wb_delete;
wb_search;
local:
*;
};
The STUB_OBJECT directive specifies that this library can be
built as a stub object as well as a normal object. STUB_OBJECT
enables additional tests and sanity checking within the link-editor
(ld) to ensure that the stub object will be a faithful representation
of the object for linking purposes. All libraries in the OSnet
(ON consolidation) must be buildable both ways, so the use of
STUB_OBJECT is not optional for ON mapfiles.
All new public symbols are added to version SUNWpublic.
All new private symbols are added to version SUNWprivate.
Existing Solaris objects may have public versions with numbered
names (e.g. SUNW_1.1). These versions date from older versions of
the OS, which used a different set of versioning rules. All such
versions must be preserved to ensure backward compatibility.
In this case, the SUNWpublic version must inherit all symbols
from the highest numbered SUNW_x.y version. The libwombat mapfile
might then look like:
$mapfile_version 2
STUB_OBJECT;
SYMBOL_VERSION SUNWpublic { # public libwombat symbols
global:
wb_readv;
wb_stat;
wb_writev;
} SUNW_1.1;
SYMBOL_VERSION SUNW_1.1 { # first release of libwombat, Solaris 9
global:
wb_read;
wb_write;
};
SYMBOL_VERSION SUNWprivate { # private libwombat symbols
global:
wb_add;
wb_delete;
wb_search;
local:
*;
};
The two lines in SUNWprivate:
local:
*;
ensure that no symbols other than those listed in the mapfile are
visible to clients of the library. If there is no SUNWprivate,
these two lines should appear in SUNWpublic.
For maintainability, the list of names in each version block should
be sorted in dictionary order (sort -d). Please comply.
The version 2 mapfile language supports a simple mechanism for conditional
input, in which lines in the mapfile apply only to a specific platform or
ELFCLASS (32/64-bit). This mechanism works very much like the #if/#endif
feature of the C preprocessor. For instance, the following mapfile declares
a version SUNWpublic that always exports a symbol foo, and also exports
the symbol bar on 32-bit sparc platforms:
$mapfile_version
SYMBOL_VERSION SUNWpublic {
foo;
$if _sparc && _ELF32
bar;
$endif
};
Conditional input can be used if there are ISA-specific library interfaces
not common to all instances of the library. It is the preferred method for
expressing platform specific items, as long as the differences are simple
(which is almost always the case). For example, see libproc, or, if you
are masochistic, libc or libnsl.
In addition to conditional input, there is a second heavier weight mechanism
for expressing ISA-specific differences. In addition to the common mapfile:
common/mapfile-vers
some libraries may have ISA-specific supplemental mapfiles, one in each
of the ISA directories:
amd64/mapfile-vers
i386/mapfile-vers
sparc/mapfile-vers
sparcv9/mapfile-vers
The ISA-specific mapfiles look like the common mapfile, except that only
the ISA-specific names appear. The version names are the same as those
in the common mapfile, but only non-empty version instances are present
and no inheritance specification is present. The link-editor reads the
information from the common and ISA-specific mapfiles and merges them
in memory into a single description used to create the resulting object.
ISA-specific mapfiles were used with the version 1 mapfile language, which
lacked conditional input. Their use is rare now, as conditional input is
generally preferred. However, it is important to use conditional input
carefully, or the resulting mapfile can be extremely difficult to read.
-------------------------------------------------------------------------------
4.0 Making interface additions to an existing library
4.1 Adding a Public interface
All new public symbols are assigned to the SUNWpublic version. If the
existing mapfile-vers does not have this version, the engineer adding
the new symbol must add it. If the library contains any existing public
versions of the form SUNW_x.y, then the new SUNWpublic version inherits
from the highest such SUNW_ version. If there are no SUNW_x.y versions, then
the SUNWpublic versions stands alone, and does not inherit.
Incompatible changes to an existing interface within a given library are not
allowed. If an API changes so dramatically as to invalidate dependencies, it
becomes necessary to change the suffix of the shared object from, say, .so.1
to .so.2 and to introduce code to continue to ship the .so.1 version of the
library. This rarely occurs in practice, and is discouraged. A better solution
is to introduce the new functionality under a new name, and retain the old
interface with the old behavior for the benefit of existing applications.
4.2 Adding a Private interface
Private interfaces are the non-ABI interfaces of the library, and are added
to the SUNWprivate version. If this interface happens to be the first
Private interface introduced into the library, the SUNWprivate version must
be created. It inherits nothing and nothing inherits from it.
If the library already has Private interfaces, they may have numbered version
names like SUNWprivate_m.n (due to errors of the past). If so, just use the
highest numbered private version name to version the new interface. There
is no need to introduce a new private version name. Be careful not to use
a lower numbered private version name; doing so can cause runtime errors
(as opposed to load time errors) when running an application with older
versions of the library.
There are libraries in the OSnet consolidation that contain only private
interfaces. In such libraries, the SUNWprivate_m.n may be incremented
to ensure that the programs that depend on them are built and delivered as a
integrated unit. A notable example of this is libld.so (usr/src/cmd/sgs/libld),
which contains the implementation of the link-editor, the public interface to
which is provided by the ld command. When making a modification to the interface
of such a library, you should follow the convention already in place.
4.3 Adding new public interfaces in an update release
Public symbols must appear in the same version in all Solaris releases.
Therefore, when porting a new public interface to an update release,
you must ensure that the symbol is assigned to the same version as
in the release you are porting from. If the library in the update
release already has this version, you simply add the new symbol to it.
If the version does not already exist, you must create it, along with
any missing versions it may inherit from, and then assign the new interface
to the newly created version.
When adding a new public interface to an update, both the mapfiles of the
update release and next marketing release must be consistent. This means
that all new functionality must be first integrated in the marketing gate,
and then ported to the update afterwards.
-------------------------------------------------------------------------------
5.0 How to update an interface in an existing library
5.1 Removing an existing interface
5.1.1 Moving a Public interface
No Public interfaces should ever be removed from any mapfile.
To move an interface from one library to (say) libc, the code has to be
deleted from the library and added to libc, then the mapfile for the
library has to have the interface's entry changed from:
getfoobar;
to:
getfoobar { TYPE = FUNCTION; FILTER = libc.so.1 };
See, for example, libnsl's common/mapfile-vers file.
Follow the rules for adding a new interface for the necessary changes
to libc's mapfile to accommodate the moved interface. In particular,
the new interface must be added to SUNWpublic in the libc mapfile-vers.
To move an entire library into libc, look at what has already been done
for libthread, libaio, and librt.
5.1.2 Removing a Private interface
Deletion of Private interfaces is allowed, but caution should be taken;
it should first be established that the interface is not being used.
To remove a Private interface, simply delete the corresponding entry
for that symbol from the mapfile's SUNWprivate section.
Do not forget to delete these Public or Private interfaces from the library's
header files as well as from the code that implements the interfaces.
5.2 Promoting a Private interface to Public
This is similar to what's done when adding a Public interface. Promoting an
existing Private interface to a Public one only requires a change to the
existing interface definition. Private interfaces have the symbol version name
"SUNWprivate" associated with them. To make the interface a Public one, the
interface must be moved to the SUNWpublic version for the library.
5.3 Scoping a Private interface local
Any interfaces not present in the mapfile-vers file will be scoped local
due to the presence of the
local:
*;
lines discussed earlier. This ensures that such interfaces will not be visible
outside the library. To move an interface from Private to local scope, simply
remove the Private interface from the mapfile-vers file and the header file
to prevent it from being exported. This may require moving the Private
interface into a library-private header file. Scope reduction of Public
interfaces is not allowed without specific ARC review and approval.
For the interface to be used in more than one file within the library, it
should be in a header file that can be included by each file in the library
that uses the interface. For example:
#include "libprivate.h"
-------------------------------------------------------------------------------
6.0 Introducing a new library
6.1 Directories
The normal discipline for introducing a new library in OS/Net is to create a
new subdirectory of /usr/src/lib. The interface definition discipline is to
create a common/mapfile-vers file for the new library. If we were introducing
a new foo library, libfoo, we'd create /usr/src/lib/libfoo containing:
Makefile amd64/ i386/ sparcv9/
Makefile.com common/ sparc/
The common subdirectory would contain the normal source files plus the
mapfile-vers file. See usr/src/lib/README.Makefiles for directions on
how to organize the Makefiles.
6.2 The mapfile
The new common/mapfile-vers file would contain:
$mapfile_version 2
STUB_OBJECT;
SYMBOL_VERSION SUNWpublic {
global:
...
};
SYMBOL_VERSION SUNWprivate {
global:
...
local:
*;
};
If there are no Public interfaces, the SUNWpublic section would be omitted.
If there are no Private interfaces, the SUNWprivate section would be
omitted and the two lines:
local:
*;
would be moved into SUNWpublic.
To decide which interfaces are Public (part of the ABI) and which are Private
(unstable interfaces not intended to be used by third party applications or
unbundled products), the heuristic which works to a first approximation is
that if it has a man page then it's Public. Also, it is really the ARC case
for the new interfaces that prescribes which interfaces are Public and
which are not (hence, which interfaces have man pages and which do not).
For maintainability, the list of names in each version block should
be sorted in dictionary order (sort -d). Please comply.
-------------------------------------------------------------------------------
8.0 Specify Stub Object Details
Stub objects are shared objects, built entirely from their mapfiles,
that are, for the purposes of linking, identical to the actual
shared objects that would result if you built them in the usual
manner. Unlike the real objects:
- Stub objects can be built extremely quickly. Stub objects
for all of usr/src/lib and usr/src/ucblib can be built in
a couple of minutes on a modest desktop system.
- Stub objects are self contained, and are built without requiring
input objects or the existence of any dependency shared objects.
Therefore, all stub objects for the OSnet can be built in parallel,
without ordering or synchronization.
- Real objects can be built using stub objects to stand in for their
real dependencies. Using stub objects in this way, an object,
and the other objects it requires, can be built in parallel, in
any arbitrary order.
Stub objects are a fundamental part of how we build ON, so every library
in the OSnet (ON consolidation) must be buildable as a stub object:
1) Before any objects are built in an ON nightly build, a
stub proto area is established, referenced as $(STUBROOT) in
our makefiles.
2) A stub object for every library is built and installed under
$(STUBROOT).
3) All libraries and executables are linked to the objects found
under $(STUBROOT).
This approach allows every library and command in Solaris to be built
in parallel, and (with a small number of exceptions), without any
explicit ordering or serialization between them.
To enable the possibility of building a library as a stub object, the
library mapfile must specify the STUB_OBJECT directive.
If your library exports only function symbols, then the use of STUB_OBJECT
is all that is required, and you can skip the remainder of this section.
There are many reasons why shared objects should not export global data
directly, and we have long discouraged it. New libraries should never
do this. It is usually easy enough to expose global data via a functional
interface. For instance, Solaris usually exposes the errno global variable
to via the following macro definition found in <errno.h>
extern int *___errno();
#define errno (*(___errno()))
So the prohibition on global data symbols is not the same thing as
prohibiting global data --- we simply recommend that it be exposed
via a functional interface.
Good advice aside, there are two important cases in which you will
need to cope with global data symbols in ON mapfiles:
1) Existing libraries with historical interfaces that must be maintained
2) Third party code, which is out of our control and not subject to
our rules.
Data symbols exported by shared objects built with the STUB_OBJECT
mapfile directive are required to provide mapfile symbol ASSERT directives
for each data symbol, for the following attributes:
- That the symbol is a data symbol.
- The size of the symbol, in bytes.
- The symbol binding, if it is not GLOBAL.
- If the symbol resides in a bss (NOBITS) section in the object.
- If the symbol is an alternative name (ALIAS) for another symbol.
These ASSERT directives serve 2 related purposes:
1) The generation of the stub object is done without access to the symbol
information usually provided with any input relocatable objects.
Instead, the ASSERT directives supply the necessary information
required to generate the correct symbol table entry.
2) When building the normal non-stub version of the object, the
attributes of the real object are compared to the ASSERT values,
and any deviation result in fatal link-time errors.
As a result, the stub and normal versions of the object are guaranteed
to present a completely equivalent linking interface. You can therefore safely
link against the stub, and then run against the non-stub.
The libc mapfile (usr/src/lib/libc/port/mapfile-vers) contains a large
number of historical data symbols, and serves as a good example of how
to write these ASSERT directives. The environ data symbol serves as a
useful example
SYMBOL_VERSION SYSVABI_1.3 {
...
global:
...
environ {
ASSERT {
TYPE=data;
$if __GNUC
SH_ATTR=nobits;
$endif
SIZE=addrsize;
BINDING=weak;
};
};
...
};
Note that it usually suffices to specify TYPE and SIZE --- environ is
a bit more complex than the usual case.
TYPE=data
All data symbols must explicitly assert that they
are expected to be data symbols.
SIZE
All data symbols must assert their size, in bytes. This can
be a decimal, or hexadecimal value. The symbolic name
'addrsize' can also be used, to represent a machine word (pointer)
sized variable. The link-editor automatically substitutes the value
4 for 'addrsize' when building 32-bit objects, and 8 for 64-bit objects.
In addition, SIZE values can specify a repeat count, which is
convenient for describing arrays. All of the following are
valid SIZE values:
Value Meaning
----------------------------------------------------------
SIZE=4 4 bytes
SIZE=0x209 521 bytes
SIZE=addrsize 4 bytes in a 32-bit object,
8 bytes in a 64-bit object.
SIZE=4[4] 16 bytes (4, 4 byte elements)
SIZE=addrsize[3] 12 bytes in a 32-bit object,
24 bytes in a 64-bit object
----------------------------------------------------------
BINDING
Most global symbols have the GLOBAL binding, and the BINDING
assert attribute need not be specified. However, data with WEAK
binding must be explicitly declared.
SH_ATTR
In rare situations, the link-editor will produce different
results when linking against a shared object with global
data, depending on whether the data resides in a regular
section, or a BSS (NOBITS) section. Data that resides in
BSS must therefore contain an assertion to that effect.
This example with the environ symbol is especially interesting,
as the native Oracle Studio compilers do not place environ in
BSS, while gcc does, hence the use of the $if __GNUC to
conditionalize the SH_ATTR attribute.
Another complication involves multiple symbols that all reference the
same physical data address, often with differing global and weak binding.
In order to produce an accurate stub object, the mapfile must include
ALIAS assertions. The lone symbol in libc provides an example of this:
lone { ASSERT { TYPE=data; SIZE=8 } };
_lone {
FLAGS = NODYNSORT;
ASSERT { ALIAS=lone; BINDING=weak };
};
When ALIAS is used, TYPE and SIZE are omitted, as their values are taken
from the source symbol.
-------------------------------------------------------------------------------
9.0 Documentation
For further information, please refer to the following documents:
"Solaris Linker and Libraries Guide", the latest version of
which is available internally from http://linkers.us.oracle.com/
/shared/ON/general_docs/scoping-rules.fm.ps
For information on the now-obsolete spec files, used in Solaris releases
7 through 10, see:
/shared/ON/general_docs/README.spec
/shared/ON/general_docs/libspec-rules.ps
/shared/ON/general_docs/spectrans/*