<?xml version='1.0' encoding='iso-8859-1'?>
<!DOCTYPE book SYSTEM "docbookx.dtd">
<book>
<title>OpenSolaris Developer's Reference</title>
<info>
<authorgroup>
<author>

<personname>Keith Wesolowski</personname>
</author>
</authorgroup>
<releaseinfo>
</releaseinfo>
<pubdate>June 2007</pubdate>
<publisher>
<publishername>Sun Microsystems, Inc.</publishername>
<address>
<street>4150 Network Circle</street>
<city>Santa Clara
</city>
<state>CA
</state>
<postcode>95054</postcode>
<country>U.S.A.</country>
</address>
</publisher>
<copyright>
<year>2007</year>
<holder>Sun Microsystems, Inc.</holder>
</copyright>
<legalnotice>
<para>The contents of this Documentation are subject to the 
Public Documentation License Version 1.01 (the "License"); 
you may only use this Documentation if you comply with the terms of this License. 
A copy of the License is available at 
http://www.opensolaris.org/os/community/documentation/license.
            </para>
</legalnotice> 
</info>           
<chapter id='_1_Introduction' xreflabel='Introduction'>
<title>Introduction</title>
<para>
Welcome to OpenSolaris!
</para>
<para>
This guide is intended to provide developers with comprehensive
information about working with OpenSolaris tools and sources.  This
chapter provides a brief overview of what OpenSolaris is and provides
pointers to additional information.
</para>
<sect1 id='_1_1_Overview' xreflabel='1.1 Overview'>
<title>1.1 Overview</title>
<para>
This chapter serves as an introduction both to OpenSolaris and to the
guide itself.  Because much of the information in the guide will change
over time, we always recommend reading the latest version.  Section 1.2
covers where you can find the current guide and other documents, and
additional resources including answers to common questions, ways to
contact other developers, and information about the sources.  While we
strongly recommend reading the parts of this guide that are relevant to
your interests, it is not necessary in order to participate.  See
section 1.3 &quot;Quick Start&quot; for ways you can start working with
OpenSolaris right now.  Section 1.4 details the typographic conventions
used in the rest of this guide.
</para>
<para>
This guide currently has a fairly strong focus on the OS and Networking
(ON) consolidation.  Expect similar information on other consolidations
to be integrated here over time.
</para>
</sect1>
<sect1 id='_1_2_Getting_Help' xreflabel='1.2 Getting Help'>
<title>1.2 Getting Help</title>
<para>
The OpenSolaris web site offers numerous ways to find answers to your
questions.  A set of technical and non-technical frequently asked
questions is maintained at
<ulink url='http://opensolaris.org/os/about/faq/'>http://opensolaris.org/os/about/faq/</ulink>.  A larger and more
in-depth set of technical documentation is maintained at
<ulink url='http://opensolaris.org/os/community/documentation/'>http://opensolaris.org/os/community/documentation/</ulink>.
</para>
<para>
If your question is not answered in the FAQs or in any of the
documentation, or you don't know where to look, you can ask using the
mailing lists of fora.  There are many available; for a current list of
discussions and to sign up, see
<ulink url='http://opensolaris.org/os/discussions/'>http://opensolaris.org/os/discussions/</ulink>.
</para>
<para>
If you are having difficulty using the OpenSolaris web site itself,
please send a message to <ulink url='mailto:webmaster@opensolaris.org'>mailto:webmaster@opensolaris.org</ulink>.  Note
that this address should not be used for technical questions about
OpenSolaris itself.
</para>
<para>
Finally, if you have any questions or comments about this document,
please send a message to  or join the OpenSolaris docs discussion at
<ulink url='http://opensolaris.org/os/community/documentation/discussions/'>http://opensolaris.org/os/community/documentation/discussions/</ulink>.
</para>
<para>
You can always find the latest version of this document at
<ulink url='http://opensolaris.org/os/community/onnv/devref_toc'>http://opensolaris.org/os/community/onnv/devref_toc</ulink>.
</para>
</sect1>
<sect1 id='_1_3_Quick_Start' xreflabel='1.3 Quick Start'>
<title>1.3 Quick Start</title>
<para>
This section bypasses most of the important material you'll find later
in this document and makes a lot of assumptions about your development
and build environment.  The intent is to offer a set of step-by-step
instructions that will help you begin development in less than an hour,
even if you have no previous Solaris development experience.  Although
this procedure will work for most people, it cannot work for all.  There
are dozens of tools and utilities used in developing OpenSolaris, and
most have at least a few options and arguments.  This tremendous
flexibility exists for a reason: each developer has unique needs.  If
you encounter difficulty in following these instructions, don't give up!
Each instruction lists the relevant sections you can read to learn more
about the commands and procedures used in that step.  If all else fails,
please see <xref linkend='_1_2_Getting_Help' /> to learn about the many resources
available to the OpenSolaris developer community.
</para>
<sect2 id='_1_3_1_Example_Environment' xreflabel='1.3.1 Example Environment'>
<title>1.3.1 Example Environment</title>
<para>
The instructions in the remainder of section 1.3 cover building and
installing on both x86 (32-bit only or 64-bit capable; there are no
differences) and SPARC environments.  They have been tested and verified
to work.  Because it is impossible to test on every imaginable hardware,
software, and policy configuration, our testing was limited to the
environments described here.  While we expect these instructions will be
broadly applicable, the more similar your environment is, the more
likely you will be able to use them without modification.
</para>
<sect3 id='_1_3_1_1_x86_Environment' xreflabel='1.3.1.1 x86 Environment'>
<title>1.3.1.1 x86 Environment</title>
<para>
We assume that the entire system is dedicated to an OpenSolaris-based
distribution, such as Solaris Express.  Our test machine is a dual Intel
Pentium 4 Xeon 2.8 GHz with hyperthreading enabled, 512MB memory, a
standard ATA controller, and a Broadcom 57xx ethernet adapter.  The
machine has 2 40GB ATA disks, partitioned as follows:
</para>
<para>
Both c0d0p0 and c1d0p0 have a fdisk single partition which assigns the
entire disk to Solaris.
</para>
<programlisting><![CDATA[
c0d0s0 contains a 35GB UFS filesystem mounted on /.
c0d0s1 contains a 2GB swap space.
c0d0s8 is a 1MB boot slice.
]]></programlisting>
<programlisting><![CDATA[
c1d0s0 contains a 37GB UFS filesystem mounted on /aux0.
]]></programlisting>
<para>
Your system does not need to be identical or even similar to this one in
order for it to work; this configuration is merely an example of a
supported system.  Please see <xref linkend='_2_Prerequisites' /> for more information
about the requirements for installing, developing, and building parts of
OpenSolaris.  Some consolidations may have additional requirements, so
be sure to consult the latest release notes.
</para>
</sect3>
<sect3 id='_1_3_1_2_SPARC_Environment' xreflabel='1.3.1.2 SPARC Environment'>
<title>1.3.1.2 SPARC Environment</title>
<para>
Our SPARC test environment is a Sun Fire V210 server with 2 1.0 GHz
UltraSPARC-IIIi CPUs and 2 GB memory.  The machine has two 36GB SCSI
disks, partitioned as follows:
</para>
<programlisting><![CDATA[
c1t0d0s0 contains a 8GB UFS filesystem mounted on /.
c1t0d0s1 contains a 4GB swap space.
c1t0d0s3 contains a 22GB UFS filesystem mounted on /export1.
]]></programlisting>
<programlisting><![CDATA[
c1t1d0s0 contains a 35GB UFS filesystem mounted on /export2.
]]></programlisting>
<para>
Your system does not need to be identical or even similar to this one in
order for it to work; this configuration is merely an example of a
supported system.  Please see <xref linkend='_2_Prerequisites' /> for more information
about the requirements for installing, developing, and building
OpenSolaris.
</para>
</sect3>
</sect2>
<sect2 id='_1_3_2_Installing_a_Binary_Dist' xreflabel='1.3.2 Installing a Binary Distribution'>
<title>1.3.2 Installing a Binary Distribution</title>
<para>
Before building your own source or installing the provided binary
archives, you will have to install a complete OpenSolaris-based
distribution.  This is because you most likely will need drivers,
packaging tools, and other components that aren't in the Operating
System and Networking components released with OpenSolaris.  As of this
writing, the only distribution on which OpenSolaris binaries can be
built or installed is Solaris Express, build 22 or newer.
</para>
<para>
If you are an ON developer and want to run the very latest bits or have
made changes to the kernel or core libraries, you will also need to
update your system to a set of binaries newer than the latest available
build of your distribution.  The process for doing this is called
<xref linkend='_BFU' /> and is described in detail below.  The BFU process uses CPIO
<xref linkend='_archives' /> containing the binaries built from ON; you can download
these archives at <ulink url='http://opensolaris.org/os/downloads/on/'>http://opensolaris.org/os/downloads/on/</ulink> or you
can build them yourself (if you have made large changes to the system,
you will be install those you built yourself).  If your interest in
making changes is limited to simple user-level applications, you can
usually get by by building those applications individually and copying
them over the system's existing binaries rather than BFUing.
</para>
<para>
Both parts of this process - the initial system install (sometimes
referred to as <xref linkend='_suninstall' /> to distinguish it from <xref linkend='_BFU' />) and BFUing are documented here; all users and
developers will need to perform the steps described in <xref linkend='_1_3_2_1_Installing_an_OpenSola' />, while
only developers interested in using the very latest ON bits or making
significant modifications to core system components will need to read
<xref linkend='_1_3_4_Upgrading_to_the_Latest_' />.
</para>
<para>
As new distributions are created which can be used as a base for
building and installing OpenSolaris bits, each will have its own section
below similar to 1.3.2.1.  If your favorite distribution isn't mentioned
here, please contribute a section explaining how to install it.
</para>
<sect3 id='_1_3_2_1_Installing_an_OpenSola' xreflabel='1.3.2.1 Installing an OpenSolaris-based Distribution (Solaris Express)'>
<title>1.3.2.1 Installing an OpenSolaris-based Distribution (Solaris Express)</title>
<para>
The Solaris installation procedure is well documented at
<ulink url='http://docs.sun.com/app/docs/coll/1236.1'>http://docs.sun.com/app/docs/coll/1236.1</ulink>.  While most of the
default options presented in the interactive installation procedure are
acceptable for creating a development or build system, you should take
note of the following:
</para>
<itemizedlist>
<listitem><para>Locales are not needed.</para>
<para>
You do not need to install any locales unless you need them for other
reasons.  Selecting the C (POSIX) locale as default is recommended.
</para>
</listitem>
<listitem><para>Follow local policies,</para>
<para>
Network configuration, time zone, use of IPv6 and Kerberos, name
service, and other environment-specific parameters must be set according
to local policy.  OpenSolaris development is not directly affected by
them.
</para>
</listitem>
<listitem><para>Reserve space for sources (and optionally builds).</para>
<para>
To install the sources, you will need at least 300MB of free space (more
is recommended).  If you also wish to build OpenON, you will need
several GB.  It is recommended that you create a separate local
filesystem to store these sources and objects as well as user home
directories and other standalone data if appropriate to your
configuration; our example system mounts this filesystem at /aux0.  See
<xref linkend='_2_1_Hardware' /> for more detailed information.
</para>
</listitem>
<listitem><para>Install the Entire Distribution package cluster.</para>
<para>
If you do not have enough disk space to install the Entire Distribution,
you will need to upgrade to a disk at least 9GB in size.  You may also
be able to install the Developer package metacluster instead, but this
has not been tested and may not be sufficient to build successfully.
See <xref linkend='_2_2_Operating_Environment_Pack' /> for more information on
software requirements.
</para>
</listitem>
</itemizedlist>
</sect3>
<sect3 id='_1_3_2_2_Installing_Required_To' xreflabel='1.3.2.2 Installing Required Tools'>
<title>1.3.2.2 Installing Required Tools</title>
<para>
There are two sets of tools required to build OpenON: compilers and
ON-specific build tools.  See <xref linkend='_2_3_Obtaining_and_Installing_C' />
and <xref linkend='_2_4_Obtaining_and_Installing_C' /> for detailed
information.  Here we assume you want to use the Studio 10 compiler (you
cannot yet use Studio 11 to build OpenON).  Note that many of the ON
build tools are also used by other consolidations, including SFW and
Network Storage (NWS).
</para>
<para>
Download the installed image (not the full product) into a scratch area,
such as <code>/var/tmp</code>.  The file is normally called
<code>sunstudio10-DATE.PLATFORM.tar.bz2</code>.  Before you start, be sure you
have at least 900MB free in <code>/opt</code>.  You can do this by examining the
output of:
</para>
<programlisting><![CDATA[
$ df -klh /opt
Filesystem             size   used  avail capacity  Mounted on
/dev/dsk/c1t0d0s0      7.9G   3.8G   4.0G    50%    /
]]></programlisting>
<para>
If the 'avail' field is 900M or larger, you have enough space to
continue.
</para>
<programlisting><![CDATA[
$ su
Password:
# cd /opt
# bzip2 -dc /var/tmp/sunstudio10-20050614.sparc.tar.bz2 | tar xf -
]]></programlisting>
<para>
Note that your filename may differ slightly depending on your platform
and future compiler releases.
</para>
<para>
Next, download the ON-specific build tools.  This file is normally
called <code>SUNWonbld-DATE.PLATFORM.tar.bz2</code> and contains a SVR4 package.
Assuming you downloaded it to <code>/var/tmp</code>, you'll now want to do:
</para>
<programlisting><![CDATA[
$ cd /var/tmp
$ bzip2 -dc SUNWonbld-DATE.PLATFORM.tar.bz2 | tar xf -
$ su
Password:
# pkgadd -d onbld SUNWonbld
]]></programlisting>
<para>
Note that if you have installed a previous version of the tools, you
will need to use pkgrm(1m) to remove them first.
</para>
<para>
Once you have installed your distribution, the compilers, and
ON-specific build tools, you're ready to build from source or install
from binaries.  If you're building from source, continue on to the next
section.  Otherwise, skip ahead to <xref linkend='_1_3_4_Upgrading_to_the_Latest_' />.
</para>
</sect3>
</sect2>
<sect2 id='_1_3_3_Building_ON_from_Source' xreflabel='1.3.3 Building ON from Source'>
<title>1.3.3 Building ON from Source</title>
<sect3 id='_1_3_3_1_Creating_a_Source_Work' xreflabel='1.3.3.1 Creating a Source Workspace'>
<title>1.3.3.1 Creating a Source Workspace</title>
<para>
Suppose you are using <code>/aux0/testws</code> as your <xref linkend='_workspace' />.
</para>
<para>
First, cd to <code>/aux0/testws</code> and unpack the sources and closed binaries,
e.g.,
</para>
<programlisting><![CDATA[
$ mkdir /aux0/testws
$ cd /aux0/testws
$ bzip2 -dc opensolaris-src-DATE.tar.bz2 | tar xf -
$ bzip2 -dc opensolaris-closed-bins-DATE.PLATFORM.tar.gz | tar xf -
]]></programlisting>
<para>
The sources will unpack into <code>usr/src</code> and the binaries will unpack
into <code>closed/root_PLATFORM</code> (i.e., <code>closed/root_i386</code> or
<code>closed/root_sparc</code>).
</para>
</sect3>
</sect2>
<sect2 id='_1_3_3_2_Performing_a_Basic_Bui' xreflabel='1.3.3.2 Performing a Basic Build'>
<title>1.3.3.2 Performing a Basic Build</title>
<para>
First, Create an environment file to guide tools like nightly(1) and
bldenv(1).
</para>
<itemizedlist>
<listitem><para>Copy in the template environment file</para>
<para>
Copy <code>/aux0/testws/usr/src/tools/env/opensolaris.sh</code> to /aux0/testws.
It doesn't have to go in /aux0/testws, but that's a convenient place to
put it.  Nor do you have to keep the name opensolaris.sh, but that's the
name we'll use in these notes.
</para>
<programlisting><![CDATA[
$ cp /aux0/testws/usr/src/tools/env/opensolaris.sh /aux0/testws
]]></programlisting>
</listitem>
<listitem><para>Make required changes</para>
<para>
First, add <code>/opt/onbld/bin</code> to your PATH environment variable.  You may
wish to make this change permanent by editing your <code>.login</code> or
<code>.profile</code> files (as appropriate for your shell).
</para>
<para>
Then, using your favorite text editor, make the following changes to
<code>opensolaris.sh</code>:
</para>
<para>
Change GATE to the name of the top-level directory (e.g., <code>testws</code>).
</para>
<para>
Change CODEMGR_WS to the top-level path (e.g., <code>/aux0/testws</code>).
</para>
<para>
Change STAFFER to your login.
</para>
</listitem>
<listitem><para>(optional) Customize VERSION.</para>
<para>
VERSION is the string that &quot;uname -v&quot; will print.
</para>
</listitem>
</itemizedlist>
<para>
Then, To build a complete set of BFU archives, cd to <code>/aux0/testws</code>,
utter
</para>
<programlisting><![CDATA[
$ nightly ./opensolaris.sh &
]]></programlisting>
<para>
and find something else to work on for a few hours.  You can monitor the
build's progress using ptree(1).  nightly(1) will send mail to $MAILTO
when it has finished.  The mail will have an overview of the build
results. A copy of the mail text and a more detailed log file will be
available in the <xref linkend='_workspace' /> (e.g.,
<code>/aux0/testws/log/log.MMDD/nightly.log</code>, where MMDD is the build date).
The log file is also available (in a slightly different location) during
the build; to monitor the progress of your build in real time, you can
do:
</para>
<programlisting><![CDATA[
$ tail -f /aux0/testws/log/nightly.log
]]></programlisting>
<para>
The location of the log is controlled by the LOGFILE and ATLOG
variables; see nightly(1) for more details.
</para>
<para>
If your build fails, you can correct the problem, then use the '-i'
option to nightly to run an incremental build, bypassing the initial
clobber.  See the nightly(1) manual and <xref linkend='_4_Building_OpenSolaris' /> for
more information.
</para>
<para>
To build a specific component, first use bldenv(1) to set up various
environment variables, then cd to the subtree that you want to build.
For example:
</para>
<programlisting><![CDATA[
$ cd /aux0/testws
$ bldenv ./opensolaris.sh
[status information from bldenv]
$ cd usr/src/cmd/vi
$ dmake all
]]></programlisting>
<para>
To build the kernel, run dmake(1) from <code>usr/src/uts</code>.
</para>
<para>
See <xref linkend='_4_Building_OpenSolaris' /> for more information on the build process
and tools.  Once you have successfully completed a build, see <xref linkend='_5_Installing_and_Testing_ON' /> for more information on what to do with it.
</para>
</sect2>
<sect2 id='_1_3_4_Upgrading_to_the_Latest_' xreflabel='1.3.4 Upgrading to the Latest ON Bits'>
<title>1.3.4 Upgrading to the Latest ON Bits</title>
<para>
<emphasis role='bold'>WARNING!</emphasis>  The steps described in this section are optional for
advanced developers only and are not required to view and edit the
sources.  Performing this process unnecessarily will result in reduced
system manageability and exposes you to the greater risks associated
with the use of development software.  <emphasis role='bold'>If in doubt, SKIP THIS STEP.</emphasis>
See <xref linkend='_5_3_Using_BFU_to_Install_ON' /> for more details on the risks and
benefits of this process.
</para>
<para>
If you wish to build one or more OpenSolaris consolidations, you may in
some cases be required to update all or part of your system's software
before doing so.  Such requirements are listed for each build in the
relevant consolidation's release notes; in most cases your existing
installation will be sufficient to build and use the latest sources.  In
general, it is both safer and more effective to use the official
suninstall, upgrade, or LiveUpgrade process to install a more recent
Solaris Express build than to use the BFU process; the official upgrade
upgrades all of your system software, while BFU upgrades only a few
parts.  Unless you need to use the very latest ON bits, you should skip
this step.
</para>
<para>
Before proceeding, please read <xref linkend='_5_3_Using_BFU_to_Install_ON' /> in its
entirety.  The remainder of this section provides an example usage of
bfu(1), but you must understand how BFU works, what BFU conflicts are,
and how to resolve them before you can successfully use BFU.  It's
impossible to overemphasize this: <emphasis role='bold'>You almost certainly want to let
acr(1) resolve conflicts for you</emphasis>.  Resolving conflicts by hand can be
difficult, time-consuming, and error-prone.  Errors in conflict
resolution will often leave your machine in a nonworking state.  We
assume here that you will be resolving conflicts automatically.
</para>
<para>
First, download the BFU archives for your system architecture from
<ulink url='http://opensolaris.org/os/downloads/on/'>http://opensolaris.org/os/downloads/on/</ulink>.  Then, unpack the archives
into a temporary directory of your choice.  In this example, we will use
<code>/var/tmp/bfu</code> to store the archives and LATEST to be the build you
want to install.
</para>
<programlisting><![CDATA[
# mkdir /var/tmp/bfu
# cd /var/tmp/bfu
# bzip2 -dc /path/to/opensolaris-bfu-LATEST.sparc.tar.bz2 | tar xf -
]]></programlisting>
<para>
This will create the directory and
<code>/var/tmp/bfu/archives-LATEST/sparc</code>.  In it will be a set of CPIO
archives; these are used by bfu(1) to overwrite your system binaries.
Next, exit the window system, log in on the console as root, and issue
the command:
</para>
<programlisting><![CDATA[
# /opt/onbld/bin/bfu /var/tmp/bfu/archives-LATEST/sparc
]]></programlisting>
<para>
You may see warnings about upgrading non-ON packages; if you have not
already done so, you will need to upgrade these before you can safely
use BFU.  If BFU fails because it tries to upgrade a package that is not
available, please check the release notes for your build for information
on the cause and solution to the problem.  If you don't find what you
need, send a message to <ulink url='mailto:opensolaris-help@opensolaris.org'>mailto:opensolaris-help@opensolaris.org</ulink>
describing the messages and the circumstances.
</para>
<para>
After BFU completes, you must resolve conflicts in configuration files
The BFU will complete, and if successful will leave you with some
warnings and a <code>bfu#</code> prompt.  <emphasis role='bold'>YOU ARE NOT DONE!</emphasis>  You must now
resolve conflicts and reboot:
</para>
<programlisting><![CDATA[
bfu# acr
]]></programlisting>
<para>
If <code>acr</code> fails or prints out warnings or errors, you will need to
resolve conflicts manually before rebooting.  See &lt;5.3 Using BFU to
Install ON&gt; for full details.  Otherwise, reboot:
</para>
<programlisting><![CDATA[
bfu# reboot
]]></programlisting>
<para>
As your system comes up, note the new kernel version.  The ON bits on
your system have been upgraded.
</para>
</sect2>
<sect2 id='_1_3_5_Mini_Projects' xreflabel='1.3.5 Mini-Projects'>
<title>1.3.5 Mini-Projects</title>
<para>
These activities are intended to help developers gain familiarity with
the OpenSolaris tools and environment while at the same time making
useful contributions toward meeting their own needs and those of the
community.  We hope that by engaging in some of these mini-projects, new
developers will be exposed to OpenSolaris from a variety of directions
and will find inspiration for new improvements in the large body of
existing work.  The project suggestions are roughly ordered from
simplest to most complex; less experienced developers should find the
first several projects to be a good introduction to OpenSolaris, while
more experienced developers may wish to take on some of the more
challenging tasks.  Of course, all of these are only suggestions; you
are always free to work on any part of the system you wish.  We ask only
that you utilize the mailing lists to coordinate your activities with
others to reduce duplication of effort.
</para>
<itemizedlist>
<listitem><para>1 Start a blog</para>
<para>
Many developers keep notes, bookmarks, pointers to useful documentation,
and other historical materials in a notebook or journal.  As you become
more familiar with OpenSolaris, your notes and experiences along the way
will be valuable to you and to others in the community.  You can create
your own blog at any of a number of free blogging sites.  Suggestions
for topics include any observations you make, difficulties you
encounter, or ideas you dream up for improving OpenSolaris.  Writing
about your ideas and experiences in your blog forms a focal point for
wider community involvement and discussion, filing of bugs or RFEs, or
the creation of a new development project.
</para>
</listitem>
<listitem><para>2 Fix a simple bug</para>
<para>
Many bugs we track in OpenSolaris are low-priority issues that have
remained unfixed over a long period of time; they are not especially
difficult to fix, and their effects tend to be annoying rather than
catastrophic.  We have also identified bugs which are easily fixed with
the 'oss-bite-size' keyword, so that new developers can obtain up to
date starting points.
</para>
<para>
You can view information about these bugs and search for bite-sized bugs
at <ulink url='http://bugs.opensolaris.org'>http://bugs.opensolaris.org</ulink>.
</para>
</listitem>
<listitem><para>3 Enhance cstyle(1)</para>
<para>
Improve the automated C/C++ style checking tools cstyle(1) and hdrchk(1)
to implement more of the style guide requirements.  For example,
cstyle(1) could be improved to detect poor declarations of initialized
variables.  See <xref linkend='_7_2_1_Automated_Style_Tools' /> for more information.
</para>
</listitem>
<listitem><para>4 Clean up and modernize code</para>
<para>
Make more commands and libraries <xref linkend='_lint' />-clean.  Although the entire
kernel (uts/...) lints without warnings, many commands and libraries are
excluded from linting because they contain lint errors.  Correcting
these errors is usually not difficult; start by enabling lint (see
<xref linkend='_3_3_3_Modifying_the_ON_Build_S' />) and re-linting the command or
library in question.  In some cases it may be difficult or impossible to
fix a particular lint error, and that error must be disabled instead.
You can discuss such situations on the relevant mailing list.
</para>
</listitem>
<listitem><para>5 Simplify Install(1) usage</para>
<para>
Improve Install(1)'s '-i' option to use official platform names in
addition to code names when building kernel packages for specific
platforms.  See <xref linkend='_5_2_Using_Cap_Eye_Install_to_I' /> for more
information.
</para>
</listitem>
<listitem><para>6 Fix something that bothers you</para>
<para>
Search for and fix a bug in a program you use frequently, or that you
have noticed yourself.  You can search for bugs at
<ulink url='http://bugs.opensolaris.org'>http://bugs.opensolaris.org</ulink>.  Many bugs may already be undergoing
fixes, so you should avoid duplication of effort by mailing
<ulink url='mailto:request-sponsor@opensolaris.org'>mailto:request-sponsor@opensolaris.org</ulink> when you start working on a
bug fix.  The sponsors make sure nobody else is working on the bug, and
help you make sure you follow the right process to get your fix
integrated.
</para>
</listitem>
</itemizedlist>
</sect2>
</sect1>
<sect1 id='_1_4_Conventions' xreflabel='1.4 Conventions'>
<title>1.4 Conventions</title>
<para>
The typographic conventions for this document are not yet finalized.  As
the document grows and improves it will eventually be typeset in
multiple formats, and each will have specific conventions.  Information
about those conventions goes here.
</para>
</sect1>
<sect1 id='_1_5_Contributors' xreflabel='1.5 Contributors'>
<title>1.5 Contributors</title>
<para>
Many people have contributed to this document.  This section contains a
partial list of sources used in its compilation.  If you are aware of
additional sources, please add them here.
</para>
<para>
Note: Some references may be to SWAN-internal URLs.  If this content is
made public at a later time, these URLs should be updated.  In all
cases, however, the intent is to document sources as well as possible
rather than provide a fully usable bibliography.
</para>
<para>
Adams, Jonathan; Bustos, David; Rhyason, Jeff.  &quot;Creating an Install
Archive with Install.&quot;
<ulink url='http://on-faq.eng.sun.com/onbld-serve/cache/94.html'>http://on-faq.eng.sun.com/onbld-serve/cache/94.html</ulink>.
</para>
<para>
Unknown.  &quot;What are BFU Conflicts and How Do I Resolve Them?&quot;
<ulink url='http://on-faq.eng.sun.com/onbld-serve/cache/189.html'>http://on-faq.eng.sun.com/onbld-serve/cache/189.html</ulink>
</para>
<para>
Unknown.  &quot;BFU.&quot;  /ws/onnv-gate/public/bfu.README.
</para>
<para>
ARC Chairs, Interface Taxonomy.
<ulink url='http://opensolaris.org/os/community/arc/policies/interface-taxonomy/'>http://opensolaris.org/os/community/arc/policies/interface-taxonomy/</ulink>.
</para>
<para>
Miscellaneous Sources:
</para>
<para>
/shared/ON/general_docs/keyword_info.txt,
/shared/ON/general_docs/lint_tips.txt, usr/src/uts/README,
usr/src/lib/README.Makefiles, /ws/onnv-gate/public/README
</para>
<para>
Ben Rockwood contributed much to early drafts of this document.  Alan
Burlison added the initial POD tags.  Mike
Sullivan, Mike Kupfer, John Beck, and Shanon Loveridge provided review
comments.
</para>
</sect1>
</chapter>
<chapter id='_2_Prerequisites' xreflabel='Prerequisites'>
<title>Prerequisites</title>
<para>
This chapter describes the hardware and software requirements for
developing, building, and testing OpenSolaris.  Most of these
requirements can easily be met on any Solaris Express installation
(other distributions may work as well).  Depending on your interests,
you may need to test your work with hardware or software which is not
readily available to you.  If this is the case, please ask your project
leader for assistance.  Sun and other companies and organizations
sponsor various facilities which may be available to OpenSolaris
community developers.  If you are a project leader, please contact
<ulink url='mailto:community_liaison@opensolaris.org'>mailto:community_liaison@opensolaris.org</ulink> for information about
resources your project can use.
</para>
<sect1 id='_2_1_Hardware' xreflabel='2.1 Hardware'>
<title>2.1 Hardware</title>
<para>
This section details hardware requirements for developing and building
OpenSolaris.  Because some projects may have additional requirements
(for example, driver development obviously requires the device in
question), this information is intended to be a guide rather than a
definitive set of rules.  It is possible, for example, to develop on a
system which cannot run any OpenSolaris-based distribution, transferring
diffs or other work to a remote environment for building and testing.
For purposes of this section, however, we will assume that your
development and build systems will run Solaris or some other fully
compatible OpenSolaris-based distribution.
</para>
<sect2 id='_2_1_1_Development_Environment' xreflabel='2.1.1 Development Environment'>
<title>2.1.1 Development Environment</title>
<para>
The simplest set of requirements applies to a development environment:
you need only have sufficient space to store the source tree and enough
CPU and memory to run text editors and tools such as cscope.  The
current source tree occupies approximately 300MB without source code
management metadata, so you should budget at least that amount of space
for each tree you wish to store (about 1.9GB is required for a tree with
a full set of SCCS metadata).  Note that if you plan to build the tree
on the same system, you will need additional space; see section 2.1.2
below.
</para>
<para>
In general, any computer which will run Solaris 10, Solaris Express, or
another OpenSolaris-based distribution is adequate for this purpose.  As
of this writing, all SPARC systems with UltraSPARC-II or newer CPUs
(that is, all CPUs which have faster clock rates than 200 MHz) are
supported; the specific list of supported SPARC platforms for Solaris 10
can be found at
<ulink url='http://docs.sun.com/source/817-6337-06/install-solaris.html'>http://docs.sun.com/source/817-6337-06/install-solaris.html</ulink>.  For
i386 and amd64 systems, hardware support is somewhat more complex; you
can find out more about x86 hardware compatibility at
<ulink url='http://www.sun.com/bigadmin/hcl/'>http://www.sun.com/bigadmin/hcl/</ulink>.  Be sure to check the latest
release notes for Solaris for information about current and future
hardware support; these notes can be found at <ulink url='http://docs.sun.com/'>http://docs.sun.com/</ulink>.
</para>
<para>
Note that other OpenSolaris-based distributions may at times support a somewhat different set of
hardware from the latest Solaris release or update; the latest
information about hardware support can always be found in your vendor's
release notes.
</para>
<para>
Table: Development system requirements
</para>
<programlisting><![CDATA[
----------------------------------------------------------------
CPU		Any supported CPU
----------------------------------------------------------------
Memory		128MB recommended
----------------------------------------------------------------
Swap		No requirement
----------------------------------------------------------------
Storage	300MB to 1.9GB per copy of the source tree (*)
----------------------------------------------------------------
]]></programlisting>
<para>
(*) The total size will vary depending on the type of source management
you use.  With no source management data, a built tree requires
approximately 3.5GB; CVS and SCCS add 50MB or more, depending on the
amount of revision history.
</para>
</sect2>
<sect2 id='_2_1_2_Build_Environment' xreflabel='2.1.2 Build Environment'>
<title>2.1.2 Build Environment</title>
<para>
Building a large, complex piece of software such as ON or any other
OpenSolaris consolidation is a memory-, compute-, and space-intensive
process.  Although it is possible to build OpenSolaris on almost any
computer, it may take prohibitively long to do so on small
configurations.  It is especially important to have enough swap space if
you will be using dmake to perform highly parallel builds.  Inadequate
swap will cause your build to fail.  Following are the hardware
requirements for a system on which you intend to build ON:
</para>
<para>
Table: Build system requirements
</para>
<programlisting><![CDATA[
----------------------------------------------------------------
CPU		300 MHz UltraSPARC or x86 CPU
		AMD Opteron or UltraSPARC-III recommended
----------------------------------------------------------------
Memory		256MB minimum, 1GB recommended (+)
----------------------------------------------------------------
Swap		1GB minimum, 2GB recommended (+)
----------------------------------------------------------------
Storage	3.5 to 5GB per copy of the source tree (*) (**)
----------------------------------------------------------------
]]></programlisting>
<para>
On a minimal build system as described above, expect a full build to
take at least 14 hours.  Incremental builds will take somewhat less
time; a good rule of thumb is one-third of the full build time.
</para>
<para>
This table shows some approximate full build times for several
representative systems.  These are current as of 5 April 2006; as
more code as added and the number of closed components decreases,
build times will increase.  Of course, the actual time to build will
vary from system to system as well.
</para>
<programlisting><![CDATA[
System		CPU			Memory		Time
----------------------------------------------------------------
Ultra 2	2x300MHz UltraSPARC-II	512M		5h9m
----------------------------------------------------------------
Generic	AMD Athlon64 3200	1GB		1h23m
----------------------------------------------------------------
]]></programlisting>
<para>
The build system can take advantage of multiple CPUs or even distribute
the work of compiling across multiple machines.  See <xref linkend='_4_Building_OpenSolaris' /> for more information about configuring parallel and
distributed builds.
</para>
<para>
(*) The total size will vary depending on the type of source management
you use.  With no source management data, a built tree requires
approximately 3.5GB; CVS and SCCS add 50MB or more, depending on the
amount of revision history.
</para>
<para>
(+) If you use dmake(1) in parallel mode and run more than 4 jobs on the
same machine, you may need additional memory and/or swap space.
</para>
<para>
(**) Compilers and tools are installed in /opt and will require an
additional 300MB on x86 or 800MB on SPARC.
</para>
</sect2>
<sect2 id='_2_1_3_Test_Environment' xreflabel='2.1.3 Test Environment'>
<title>2.1.3 Test Environment</title>
<para>
The requirements for testing your changes will vary greatly.  Some
changes do not affect architecture-specific code at all and can simply
be tested by building and running a test suite on any supported system
of each architecture.  For example, if you have added a new STREAMS
module to the network stack, it is probably sufficient to build and test
on one x86 system (test 32- and 64-bit kernels and user programs), and
one SPARC system.  In other cases, for example modifications to the x86
boot code, it will be necessary to test on the widest possible array of
hardware to ensure you have not broken some obscure piece of
functionality.
</para>
<para>
Some hardware variables you should consider testing include:
</para>
<programlisting><![CDATA[
- Architecture: i386, amd64, SPARC
- Memory size: does your change work with 32MB?  With 32GB?
- Multiprocessor versus uniprocessor
- Graphical console versus serial console versus system LOM console
- Diskless versus "normal" systems
]]></programlisting>
<para>
Not all these variables will be applicable to your particular change, so
you will need to consider, being as conservative as possible, what
effects your changes could cause.  In general, changes to core kernel
code such as the VM subsystem or filesystem support require the broadest
testing.  Changes to add-on drivers or machine-specific code need only
be tested on the relevant hardware in most cases.  See Chapter 5 for
more details.
</para>
<para>
Quite often you may want to make a change which you cannot completely
test on the hardware available to you.  If you find yourself in this
situation, please contact us via <ulink url='http://opensolaris.org/'>http://opensolaris.org/</ulink>.  The
OpenSolaris community includes several organizations, including Sun, who
may be able to provide you with access to additional hardware for the
purpose of testing your changes.
</para>
</sect2>
</sect1>
<sect1 id='_2_2_Operating_Environment_Pack' xreflabel='2.2 Operating Environment Packages'>
<title>2.2 Operating Environment Packages</title>
<para>
The rest of this chapter discusses the software needed to build and
package OpenSolaris.  If you are only interested in looking at the
sources, editing them, and sending your patches to others, you can skip
this material; no special packages are required to view and edit the
sources.  We do recommend, however, that if you are installing Solaris
for the first time on a system you plan to use for
development, you install the &quot;Entire&quot; cluster (SUNWCall) because this
will save you a good deal of time if you later decide you want to build
OpenSolaris components.  Other distributions may offer different
installation options; consult your vendor's documentation.
</para>
<para>
We strongly recommend installing the &quot;Entire&quot; package cluster (SUNWCall)
on all development, build, and test systems.  Although systems with the
Developer (SUNWCdev) package cluster installed may work, this
configuration has not been tested and will not be evaluated or
recommended.  Additionally, you should obtain and install the SUNWonbld
package, which contains prebuilt versions of the tools in usr/src/tools
needed to build OpenSolaris components.  If you prefer, you can instead
use nightly(1) with the '-t' option to build these tools (see <xref linkend='_4_2_Using_nightly_and_bldenv' />) when building ON, but installing the package
is recommended to avoid dependency problems and is required for other
consolidations.  SUNWonbld can be downloaded from
<ulink url='http://opensolaris.org/os/downloads/on/'>http://opensolaris.org/os/downloads/on/</ulink>.  Finally, you will need to
obtain and install the Sun Studio compilers, dmake, and other tools.
You can obtain these tools from
<ulink url='http://opensolaris.org/os/community/tools/sun_studio_tools/'>http://opensolaris.org/os/community/tools/sun_studio_tools/</ulink>.
</para>
<para>
If you install and use a full installation (for example, Solaris or
Solaris Express CDs or DVDs), you will have a complete matching set of
programs, libraries, and kernel components.  However, if you later
upgrade the ON bits using a method such as BFU (see <xref linkend='_5_3_Using_BFU_to_Install_ON' />) or Install (see <xref linkend='_5_2_Using_Cap_Eye_Install_to_I' />), or want to build and copy in your own updated versions of a
few files, you may need to install newer versions of one or more system
packages first.  When this happens, it is known as a Flag Day.  You can
find more information about Flag Days in <xref linkend='_5_1_3_Flag_Days_and_Other_Haza' />.
</para>
</sect1>
<sect1 id='_2_3_Obtaining_and_Installing_C' xreflabel='2.3 Obtaining and Installing Compilers'>
<title>2.3 Obtaining and Installing Compilers</title>
<para>
The compilers needed may depend on the consolidation you are building
and the platform(s) on which you wish to build.  Prior to build 19, an
x86 build of ON used both the Sun One Studio 8 and GNU compilers by
default.  This is because 32-bit objects are built with cc and CC, while
gcc is used for 64-bit objects.  As of build 19, Sun Studio 10 compilers
are used by default for all objects.  And effective beginning in build
38, all ON builds on all platforms require both Sun Studio 10 and a
recent version of gcc (from /usr/sfw in Solaris Express).  Other
consolidations may require slightly different compilers and/or compiler
patches, so always check the latest release notes.
</para>
<para>
Because compilers used to build OpenSolaris may require special patches,
links to current Studio compiler binaries will always be maintained at
the OpenSolaris web site.  Using other versions of compilers,
assemblers, linkers, make(1), or dmake(1) is not supported and may fail
to build or create binaries that do not function correctly.  Therefore,
you must use the compilers listed in your consolidation's release notes
to ensure a successful build.  From time to time the required tools will
be updated; notices will be posted and newer versions made available as
appropriate.
</para>
<para>
The only compilers that can be used to build the mainline OpenSolaris
sources are the Sun Studio 10 tools available at
<ulink url='http://opensolaris.org/os/community/tools/sun_studio_tools/'>http://opensolaris.org/os/community/tools/sun_studio_tools/</ulink> and the
GNU Compiler Collection shipped with Solaris Express build 22 and later.
If you wish to use gcc as your primary compiler (that is, if you wish
the archives to contain objects built with gcc), see
<ulink url='http://opensolaris.org/os/community/tools/gcc/'>http://opensolaris.org/os/community/tools/gcc/</ulink>.  Regardless of the
compiler you use, you will need a set of ON-specific build tools
(onbld).  You can find these tools for both SPARC and x86 platforms at
<ulink url='http://opensolaris.org/os/downloads/on/'>http://opensolaris.org/os/downloads/on/</ulink>.
</para>
<para>
The Studio 10 compilers can be installed in two ways: from an installed
image, or as a complete product.  The installed image is simply a
compressed tar file containing many, but not all, of the contents of the
Studio 10 product, with patches already applied and a valid license key.
The contents are sufficient to build <xref linkend='_ON' />; you can learn more about
exactly what's included at
<ulink url='http://opensolaris.org/os/community/tools/sun_studio_tools/faqs/'>http://opensolaris.org/os/community/tools/sun_studio_tools/faqs/</ulink>.
The installed image will be extracted to <code>opt/SUNWspro</code> beneath the
directory in which you extract it; if you extract it in the root
directory as described below, which is recommended, it will install in
the same location as the full product would.  Please note that there is
no way to apply additional patches to the installed image.
</para>
<sect2 id='_Example_1__Installing_Studio_1' xreflabel='Example 1: Installing Studio 10 compilers, installed image'>
<title>Example 1: Installing Studio 10 compilers, installed image</title>
<itemizedlist>
<para>
Suppose you have downloaded the installed image into
<code>/var/tmp/sunstudio10-sparc.tar.bz2</code>, and want to install it into
<code>/opt/SUNWspro</code> (recommended).  You could install as follows:
</para>
<programlisting><![CDATA[
$ su
Password:
# cd /
# bzip2 -dc /var/tmp/sunstudio10-sparc.tar.bz2 | tar xf -
]]></programlisting>
</itemizedlist>
<para>
The complete product install has its own installer and a complete manual
that includes installation instructions.  See
<ulink url='http://docs.sun.com/app/docs/doc/819-0485'>http://docs.sun.com/app/docs/doc/819-0485</ulink> for detailed installation
instructions, including how to use the graphical and text installation
methods.  You will need to install the required patches before you can
build OpenSolaris components if you use the full product; normally these
are included with the product download.  See
<ulink url='http://opensolaris.org/os/community/tools/sun_studio_tools/'>http://opensolaris.org/os/community/tools/sun_studio_tools/</ulink> for
more information on required patches.  By default, the Studio 10 product
installs into <code>/opt/SUNWspro</code>.  You should not change this unless you
have an existing installation of Sun Workshop/Forte/Studio that you need
to preserve.
</para>
</sect2>
<sect2 id='_Example_2__Installing_Studio_1' xreflabel='Example 2: Installing Studio 10 compilers, full product'>
<title>Example 2: Installing Studio 10 compilers, full product</title>
<itemizedlist>
<para>
Suppose you have downloaded the product into
<code>/var/tmp/sunstudio10-x86.tar</code>, you wish to unpack it in
<code>/var/tmp/studio-install</code>, and you received a license key 'ABC123'.
You could install as follows:
</para>
<programlisting><![CDATA[
$ mkdir /var/tmp/studioinstall
$ cd /var/tmp/studioinstall
$ tar xf /var/tmp/sunstudio10-x86.tar
$ su
Password:
# ./batch_installer -s ABC123
...
# cd patches
# patchadd -M . patchlist
...
]]></programlisting>
</itemizedlist>
<para>
The version of gcc needed is installed by default as part of Solaris
Express builds 22 and later.  If using a different distribution, consult
your vendor's documentation to determine whether your version of gcc is
sufficient.
</para>
</sect2>
</sect1>
<sect1 id='_2_4_Obtaining_and_Installing_C' xreflabel='2.4 Obtaining and Installing Custom Tools'>
<title>2.4 Obtaining and Installing Custom Tools</title>
<para>
In addition to the general development tools and compilers, a set of
custom tools called &quot;onbld&quot; is also required.  This includes scripts and
programs that handle compiler and assembler compatibility, <xref linkend='_CTF' />
data, ABI auditing, installation of <xref linkend='_ON' /> bits, and more.  Many of
these utilities are platform-specific; therefore, we deliver a version
of the SUNWonbld package for all supported platforms (currently x86 and
SPARC).  Note that these tools are built from sources in the
usr/src/tools subdirectory of the ON source <xref linkend='_gate' />.  Refer to the Tour
of Your ON Workspace in section 3.2 for more information about location
of the sources.  If you have the sources available, you can get by
without installing SUNWonbld; however, you may encounter dependency
problems when bootstrapping your ON installation.  You can obtain this
package from <ulink url='http://opensolaris.org/os/downloads/on/'>http://opensolaris.org/os/downloads/on/</ulink>.  Be aware
that certain versions of onbld may be required to build certain ranges
of ON sources; if you need to work with an older version of the source,
be sure to check the onbld version requirements for that version.
</para>
<para>
The ON-specific build tools are delivered as a SVR4 (<code>pkgadd(1M)</code>)
package for each supported build machine architecture.  The package
installs into <code>/opt/onbld</code>.
</para>
<sect2 id='_Example_3__Installing_the_ON_b' xreflabel='Example 3: Installing the ON build tools'>
<title>Example 3: Installing the ON build tools</title>
<itemizedlist>
<para>
Suppose you have downloaded the build tools package into
<code>/var/tmp/SUNWonbld-20050613.tar.bz2</code> and you wish to install it.  You
could do so as follows:
</para>
<programlisting><![CDATA[
$ cd /var/tmp
$ bzip2 -dc SUNWonbld-20050613.i386.tar.bz2 | tar xf -
$ su
Password:
# pkgadd -d . SUNWonbld
]]></programlisting>
</itemizedlist>
</sect2>
</sect1>
<sect1 id='_2_5_Environment_Variables' xreflabel='2.5 Environment Variables'>
<title>2.5 Environment Variables</title>
<para>
In order to use the source code management and build tools successfully,
you will need to set several environment variables correctly.  Most of
these variables are either <xref linkend='_workspace' />-specific (see section 3.3.1) or
build-specific (see section 4.1).  However, in order to successfully use
the installed tools, you will need to set your PATH environment variable
correctly.  This should normally be done as part of your login scripts
so that it will be done automatically.
</para>
<para>
You can always get the latest information about recommend PATH
components from the gate's public/README file.  You can find a copy of
this file at
<ulink url='http://opensolaris.org/os/community/onnv/gate_info/README'>http://opensolaris.org/os/community/onnv/gate_info/README</ulink>.
</para>
<para>
PATH is used by your shell and other programs to determine where to find
programs.  This functionality has nothing to do with OpenSolaris, but in
order to find the various programs needed by the build tools, PATH
requires several elements in addition to the standard system
directories.  In general, these are:
</para>
<programlisting><![CDATA[
/opt/SUNWspro/bin
/opt/onbld/bin
/opt/onbld/`uname -p`/bin
]]></programlisting>
<para>
If you have installed your compilers or onbld tools in nonstandard
locations (which is not recommended), you will need to modify these
locations accordingly.  Also, you must be certain to include
/usr/ccs/bin in your PATH, and even more specifically, it must come
before /usr/ucb if that directory is included in your PATH.  As an
example of putting all this together, a working PATH might look like:
</para>
<programlisting><![CDATA[
$ echo $PATH
/usr/bin:/usr/sbin:/usr/ccs/bin:/usr/dt/bin:/usr/openwin/bin: \
    /opt/onbld/bin:/opt/onbld/bin/sparc:/opt/sfw/bin:/usr/sfw/bin
]]></programlisting>
<para>
See the gate's public/README file for details.
</para>
<para>
Including /usr/ucb in your PATH is not recommended, and the build
process does not require any programs located there.  If you must
include it for some other reason, be sure it is the last component.
Otherwise, including /usr/ucb will cause your build to fail, especially
if it is before /usr/sbin.
</para>
<para>
Note that the paths to some tools are explicitly set in
usr/src/Makefile.master and other makefiles, so changing your PATH may
not by itself have the effect you intend.  Specifically, compiler paths
are fixed.  If you need to change this, you must override the make
macros specifying the compiler locations.  You can learn more about this
in section 4.1.
</para>
<para>
In addition to PATH, you may find it helpful to add /opt/onbld/man and
/opt/SUNWspro/man to your MANPATH.  This will make it easier to read the
manual pages associated with the many utilities discussed in this
document.  Alternately, you will need to add '-M /opt/onbld/man' or '-M
/opt/SUNWspro/man' to your invocation of man(1) in order to view these
pages.
</para>
</sect1>
</chapter>
<chapter id='_3_The_Source_Tree' xreflabel='The Source Tree'>
<title>The Source Tree</title>
<para>
This chapter discusses obtaining, managing, and modifying OpenSolaris.
As with most of this document, we focus on the <xref linkend='_ON' /> consolidation.
However, most other consolidations require very similar steps.  Always
consult your consolidation's release notes for the latest information.
Contributions to this reference for non-ON consolidations are always
welcome.
</para>
<sect1 id='_3_1_Retrieving_the_Sources' xreflabel='3.1 Retrieving the Sources'>
<title>3.1 Retrieving the Sources</title>
<para>
Most consolidations are available as tarballs; within the next few
months, a few will also begin to offer read-only Subversion
repositories.  Regardless of the method used to obtain the source, the
contents are the same.
</para>
<sect2 id='_3_1_1_Obtaining_Sources_via_Ta' xreflabel='3.1.1 Obtaining Sources via Tarball'>
<title>3.1.1 Obtaining Sources via Tarball</title>
<para>
You can obtain the tarballs for all released consolidations at
<ulink url='http://opensolaris.org/os/downloads/'>http://opensolaris.org/os/downloads/</ulink>.  If you plan to build the
source, and wish to produce complete installation sets, you may also
need the closed binaries (if the consolidation of interest is not
entirely open), which you can obtain from the same location.  Be sure to
obtain the appropriate binaries for your platform.  Once you have done
so, create your <xref linkend='_workspace' /> as follows:
</para>
<programlisting><![CDATA[
$ mkdir /path/to/workspace
$ cd /path/to/workspace
$ bzip2 -dc /path/to/tarball/on-src-<ver>.tar.bz2 | tar xf -
$ bzip2 -dc /path/to/tarball/on-bins-<ver>.{x86,sparc}.tar.gz | tar xf -
]]></programlisting>
</sect2>
</sect1>
<sect1 id='_3_2_Tour_of_Your_ON_Workspace' xreflabel='3.2 Tour of Your ON Workspace'>
<title>3.2 Tour of Your ON Workspace</title>
<para>
After creating and populating your <xref linkend='_workspace' />, you can begin to
investigate the contents of the source tree.  This section describes the
layout and contents of your <xref linkend='_ON' /> workspace.
</para>
<sect2 id='_3_2_1_Organization' xreflabel='3.2.1 Organization'>
<title>3.2.1 Organization</title>
<para>
Initially, your <xref linkend='_workspace' /> will have only one directory: usr.  Once
you have completed a build, you may have several additional directories,
including archives, log, packages, and proto.  We include here a diagram
showing all these directories and their subdirectories.  We also include
the build subdirectories, which contain object files and are described
in greater detail in subsections 2-4 below.
</para>
<para>
If you have done a nightly(1) build, you will also have a log directory
at the top level.  It will contain the complete output from the
nightly(1) build process.  See <xref linkend='_4_2_Using_nightly_and_bldenv' /> for more
information on nightly(1) and the log files it generates.
</para>
<para>
All sources are found under usr/src.  This includes both the sources
used to build the <xref linkend='_ON' /> consolidation and sources for tools and other
peripheral utilities needed to build but not shipped as part of Solaris.
Because it includes only ON sources, it does not contain Java, the
windowing system, or packaging and installation tools.  Because of
contractual obligations, it may not include all code from third-party
hardware vendors.  The usr/src directory has several subdirectories
which are described here.
</para>
<itemizedlist>
<listitem><para>cmd</para>
<para>
This directory contains sources for the executable programs and scripts
that are part of ON.  It includes all the basic commands, daemons,
startup scripts, and related data.  Most subdirectories are named for
the command or commands they provide; however, there are some exceptions
listed here.
</para>
</listitem>
<listitem><para>cmd/Adm</para>
<para>
Miscellaneous key system files, such as crontabs and data installed in /etc.
</para>
</listitem>
<listitem><para>cmd/cmd-crypto</para>
<para>
Basic cryptographic utilities, such as elfsign and kcfd.
</para>
</listitem>
<listitem><para>cmd/cmd-inet</para>
<para>
Network commands and daemons, including the Berkeley r-commands, PPP,
telnet, the inetd super-server, and other network-related utilities.
</para>
</listitem>
<listitem><para>cmd/fs.d</para>
<para>
Utilities for checking, mounting, unmounting, and analyzing filesystems.
</para>
</listitem>
<listitem><para>cmd/netfiles</para>
<para>
IP port definitions and name service switch configuration files
installed into /etc.
</para>
</listitem>
<listitem><para>cmd/ptools</para>
<para>
Utilities for manipulating and observing processes; these are based
on proc(4) and libproc interfaces.
</para>
</listitem>
<listitem><para>cmd/sgs</para>
<para>
Software Generation System.  This directory contains binary utilities,
such as ld(1), ar(1), and mcs(1), and development tools such as lex(1),
yacc(1), and m4(1).  Note that this directory also includes several
libraries and headers used by these tools.
</para>
</listitem>
<listitem><para>common</para>
<para>
Files which are common among cmd, lib, stand, and uts.  These
typically include headers and sources to basic libraries used by both
the kernel and user programs.
</para>
</listitem>
<listitem><para>head</para>
<para>
Userland header files (kernel headers are in uts/).  Note that only libc
headers should be stored here; other libraries should have their headers
in their own subdirectories under lib/.
</para>
</listitem>
<listitem><para>lib</para>
<para>
Libraries.  Most subdirectories are named for the library whose
sources they contain or are otherwise self-explanatory.
</para>
</listitem>
<listitem><para>pkgdefs</para>
<para>
Contains one subdirectory for each package generated from the ON
sources.  Each subdirectory contains packaging information files; see
pkginfo(4), depend(4), prototype(4), pkgmap(1), and pkgproto(1) for more
information about the contents of these files.
</para>
</listitem>
<listitem><para>prototypes</para>
<para>
Sample files showing format and copyright notices.
</para>
</listitem>
<listitem><para>psm</para>
<para>
Platform-specific modules.  Currently this contains only OBP and most of
the boot code.
</para>
</listitem>
<listitem><para>stand</para>
<para>
Standalone environment code.  This is used for booting; for example,
code for reading from UFS and the network is here.
</para>
</listitem>
<listitem><para>tools</para>
<para>
Development tools and sources.  See README.tools for more information
about each tool; the file should be updated as tools are added or
removed.
</para>
</listitem>
<listitem><para>ucbcmd</para>
<para>
Commands and daemons installed into /usr/ucb (for SunOS 4.x
compatibility).
</para>
</listitem>
<listitem><para>ucbhead</para>
<para>
Header files installed into /usr/ucb (for SunOS 4.x compatibility).
</para>
</listitem>
<listitem><para>ucblib</para>
<para>
Libraries installed into /usr/ucb (for SunOS 4.x compatibility).
</para>
</listitem>
<listitem><para>uts</para>
<para>
Kernel sources are here (UTS == UNIX Time Sharing).  There are numerous
subdirectories of uts which are of interest:
</para>
</listitem>
<listitem><para>uts/adb</para>
<para>
adb contained the obsolete kernel debugger macros; it is no longer
supported, and this directory is now empty.  Use mdb(1) instead, and
write mdb dcmds instead of adb macros.
</para>
</listitem>
<listitem><para>uts/common</para>
<para>
All platform-independent kernel sources.  Nearly all of the Solaris
kernel is here; only a few small parts are architecture-dependent.
</para>
</listitem>
<listitem><para>uts/common/c2</para>
<para>
Auditing code to support the C2 U.S. government security standard.
</para>
</listitem>
<listitem><para>uts/common/conf</para>
<para>
System configuration parameters.
</para>
</listitem>
<listitem><para>uts/common/contract</para>
<para>
Code to support process contracts.  See contract(4) and
libcontract(3LIB) for more information on process contracts.
</para>
</listitem>
<listitem><para>uts/common/cpr</para>
<para>
CheckPoint-and-Resume support.  This implements suspend and resume
functionality.
</para>
</listitem>
<listitem><para>uts/common/crypto</para>
<para>
Kernel cryptographic framework.  See kcfd(1M) and cryptoadm(1M) for
more information.
</para>
</listitem>
<listitem><para>uts/common/ctf</para>
<para>
Code for handling Compact C Type Format data.
</para>
</listitem>
<listitem><para>uts/common/des</para>
<para>
Implements the old Data Encryption Standard.  This is used by KCF.
</para>
</listitem>
<listitem><para>uts/common/disp</para>
<para>
Dispatcher, thread handling, and scheduling classes.
</para>
</listitem>
<listitem><para>uts/common/dtrace</para>
<para>
CPU-independent dtrace(7D) kernel support.
</para>
</listitem>
<listitem><para>uts/common/exec</para>
<para>
Code for handling userland binary executable types (a.out, ELF, etc).
</para>
</listitem>
<listitem><para>uts/common/fs</para>
<para>
Filesystems.
</para>
</listitem>
<listitem><para>uts/common/ssapi</para>
<para>
Generic Security Services API.
</para>
</listitem>
<listitem><para>uts/common/inet</para>
<para>
IP networking subsystem, including IPv6.
</para>
</listitem>
<listitem><para>uts/common/io</para>
<para>
I/O subsystem.  Most of the code in this directory is device drivers
(and pseudo-device drivers).
</para>
</listitem>
<listitem><para>uts/common/ipp</para>
<para>
IP policy framework; includes QoS and other traffic management.
</para>
</listitem>
<listitem><para>uts/common/kmdb</para>
<para>
Kernel modular debugger.  See kmdb(1).
</para>
</listitem>
<listitem><para>uts/common/krtld</para>
<para>
Kernel runtime linker/loader.  This is responsible for handling
loadable modules and symbol resolution; it is analogous to ld.so.1,
and shares code with it.
</para>
</listitem>
<listitem><para>uts/common/ktli</para>
<para>
Kernel TLI (Transport Layer Interface).
</para>
</listitem>
<listitem><para>uts/common/net</para>
<para>
Header files; most are shipped in /usr/include/net.
</para>
</listitem>
<listitem><para>uts/common/netinet</para>
<para>
Header files; most are shipped in /usr/include/netinet.
</para>
</listitem>
<listitem><para>uts/common/nfs</para>
<para>
Network File System headers shipped in /usr/include/nfs.
</para>
</listitem>
<listitem><para>uts/common/os</para>
<para>
Core operating system implementation.  This includes such varied
aspects as privileges, zones, timers, the DDI/DKI interfaces, and
high-level locking mechanisms.
</para>
</listitem>
<listitem><para>uts/common/pcmcia</para>
<para>
PCMCIA I/O subsystem and drivers.
</para>
</listitem>
<listitem><para>uts/common/rpc</para>
<para>
Remote Procedure Call subsystem used by services such as NFS and NIS.
</para>
</listitem>
<listitem><para>uts/common/rpcsvc</para>
<para>
Generated RPC header files shipped in /usr/include/rpcsvc.
</para>
</listitem>
<listitem><para>uts/common/sys</para>
<para>
Header files shipped in /usr/include/sys.  These same headers are used
to build the kernel as well (if the _KERNEL preprocessor symbol is
defined).
</para>
</listitem>
<listitem><para>uts/common/syscall</para>
<para>
System call implementations.  Most syscalls are implemented in files
matching their names.  Note that some system calls are implemented
in os/ or other subdirectories instead.
</para>
</listitem>
<listitem><para>uts/common/tnf</para>
<para>
Old tracing subsystem, not related to dtrace(7D).
</para>
</listitem>
<listitem><para>uts/common/vm</para>
<para>
Virtual memory subsystem.
</para>
</listitem>
<listitem><para>uts/common/zmod</para>
<para>
Compression/decompression library.
</para>
</listitem>
<listitem><para>uts/i86pc</para>
<para>
Architecture-dependent files for x86 machines.  The
architecture-dependent directories (i86pc, sun, sun4, sun4u) all have
a set of subdirectories similar to common/ above.
</para>
</listitem>
<listitem><para>uts/intel</para>
<para>
ISA-dependent, architecture-independent files for x86 machines.  Note
that all architecture-independent source files are built into objects
in this hierarchy.
</para>
</listitem>
<listitem><para>uts/sfmmu</para>
<para>
Code specific to the SpitFire memory management unit (UltraSPARC).
</para>
</listitem>
<listitem><para>uts/sparc</para>
<para>
ISA-dependent, architecture-independent files for SPARC machines.
Note that all architecture-independent source files are built into
objects in this hierarchy.
</para>
</listitem>
<listitem><para>uts/sun</para>
<para>
Sources common to all Sun implementations.  Currently this contains a
small number of device drivers and some headers shipped in
/usr/include/sys.
</para>
</listitem>
<listitem><para>uts/sun4</para>
<para>
Sources common to all sun4* machine architectures.
</para>
</listitem>
<listitem><para>uts/sun4u</para>
<para>
Architecture-dependent sources for the sun4u architecture.  Each
system implementation has a subdirectory here:
</para>
<programlisting><![CDATA[
* blade		Serverblade1
* chalupa		Sun-Fire-V440
* cherrystone		Sun-Fire-480R
* daktari		Sun-Fire-880
* darwin		Ultra-5_10
* enchilada		Sun-Blade-2500
* ents		Sun-Fire-V250
* excalibur		Sun-Blade-1000
* fjlite		UltraAX-i2
* grover		Sun-Blade-100
* javelin		Ultra-250
* littleneck		Sun-Fire-280R
* lw2plus		Netra-T4
* lw8			Netra-T12
* makaha		UltraSPARC IIe-NetraCT-40, UltraSPARC IIe-NetraCT-60
* montecarlo		UltraSPARC IIi-NetraCT
* mpxu		Sun-Fire-V240
* quasar		Ultra-80
* serengeti		Sun-Fire
* snowbird		Netra-CP2300
* starcat		Sun-Fire-15000
* starfire		Ultra-Enterprise-10000
* sunfire		Ultra-Enterprise
* taco		Sun-Blade-1500
* tazmo		Ultra-4
]]></programlisting>
</listitem>
</itemizedlist>
</sect2>
<sect2 id='_3_2_2_Object_Directories' xreflabel='3.2.2 Object Directories'>
<title>3.2.2 Object Directories</title>
<para>
There are two basic strategies that can be used in the creation of
object files and finished binaries (executables and libraries):
</para>
<para>
(a) place objects in a dedicated directory hierarchy parallel to the
sources
</para>
<para>
(b) place objects in the same directories as the sources they are
built from
</para>
<para>
ON actually uses each of these approaches in different parts of the
tree.  Strategy (a) must be used for all kernel code and many libraries,
is preferred for new code, and will be described in detail here.  There
are several legacy variations on strategy (a) as well as instances in
which strategy (b) is still used; the majority of these are in the cmd
hierarchy.  The entire uts hierarchy has been converted to strategy (a)
as described below, and you will see this same approach used throughout
much of the rest of the tree.
</para>
<sect3 id='_3_2_2_1_General_Strategy_for_K' xreflabel='3.2.2.1 General Strategy for Kernel Objects'>
<title>3.2.2.1 General Strategy for Kernel Objects</title>
<para>
First, each platform-independent module has zero or one build directory
per architecture.  An architecture in this case can be a machine (sun4u,
i86pc) or a processor architecture (intel, sparc).  The path to this
location is always usr/src/uts/&lt;platform&gt;/&lt;module&gt;.  The module name in
this case is what's found in /kernel/drv or a similar location, and in
the case of device drivers or STREAMS modules should always match the
name of the man page describing that driver or module.
</para>
<para>
The only files normally present in this directory for a clean tree are
makefiles.  After a build, these directories contain one or more of
obj32, obj64, debug32, and debug64 directories.  These directories
contain the object files and finally linked modules that are later
installed into the kernel directory and other locations in the
prototype.
</para>
<para>
&quot;Implementation architecture&quot;-independent modules are produced in
individual directories (one per module) under the &quot;instruction-set
architecture&quot; directory (i.e.: sparc). Similarly, &quot;implementation
architecture&quot;-dependent modules are produced in individual directories
under the &quot;implementation architecture&quot; directory (i.e.: sun4, sun4u,
i86pc).
</para>
<para>
Platform-dependent modules (including &quot;unix&quot;) may be built more than
once in different locations.  Platform-dependent modules are discussed
in greater detail in &lt;section&gt;.
</para>
<para>
The sources are not contained in these build directories.
</para>
</sect3>
<sect3 id='_3_2_2_2_General_Strategy_for_C' xreflabel='3.2.2.2 General Strategy for Command/Library Objects'>
<title>3.2.2.2 General Strategy for Command/Library Objects</title>
<para>
Most libraries and some commands and daemons are built using makefiles
very similar to those used to build the kernel.  Accordingly,
intermediate objects, shared objects, libraries, and executables are
built by small makefile fragments and placed in dedicated ISA-specific
subdirectories.
</para>
<para>
Other commands' build systems place objects in the same directories as
the sources.  See sections 3.2.2.3, 3.2.3.2, and 3.2.5 for more information
on how commands are built.
</para>
</sect3>
<sect3 id='_3_2_2_3_Exceptions_in_cmd_and_' xreflabel='3.2.2.3 Exceptions in cmd and lib'>
<title>3.2.2.3 Exceptions in cmd and lib</title>
<para>
Most of the cmd tree is directly based on the original System V
Release 4 source, which uses strategy (b) described above.  Since
most commands and daemons do not need to provide both 32- and 64-bit
versions, or do anything special when building for different
architectures, this strategy is adequate and appropriate for most
commands and has been applied even to new subdirectories.  In
situations in which architecture-dependent build options are needed or
multiple ISA versions of a program must be delivered, this strategy is
unworkable and the more general approach of multiple per-ISA object
directories must be used instead.  This latter approach is similar to
the approach used for kernel modules.
</para>
<para>
The lib hierarchy is somewhat simpler; nearly all subdirectories must
use per-ISA object file locations and makefiles.
</para>
<para>
A few directories do not appear to follow any rule or pattern, such as
cmd/cmd-inet and cmd/agents.  These are primarily historical artifacts
of Sun's internal project organization.
</para>
</sect3>
</sect2>
<sect2 id='_3_2_3_Makefile_Layout' xreflabel='3.2.3 Makefile Layout'>
<title>3.2.3 Makefile Layout</title>
<para>
This discussion is intended to provide a step-by-step explanation of
what targets exist and how they are built by the makefiles.  I ignore
the platform-specific module architecture because it is unlikely to be
of significant interest except to hardware support engineers.  The three
main subtrees of interest are the kernel (uts), commands and daemons
(cmd), and libraries (lib).  The next three subsections cover these
three subtrees in turn.  There are also a handful of makefiles which
apply to all builds:
</para>
<itemizedlist>
<listitem><para>usr/src/Makefile</para>
<para>
This is the top-level makefile.  It drives builds for various targets in
each subdirectory.  It is aware of the specific targets that need to be
built in each subdirectory in order to perform a complete build, and
itself knows how to create a skeleton proto area for later use by
install and install_h targets.
</para>
</listitem>
<listitem><para>usr/src/Makefile.lint</para>
<para>
All linting from the top level is driven by this makefile.  It contains
long lists of directories known to be <xref linkend='_lint' />-clean and contains simple
recursive rules for rebuilding each subdirectory's lint target.  The
actual linting is driven by the lower-level makefiles.
</para>
</listitem>
<listitem><para>usr/src/Makefile.master</para>
</listitem>
<listitem><para>usr/src/Makefile.master.64</para>
<para>
These two makefiles contain generic definitions, such as build and
installation tools locations, template macros for compilers, linkers,
and other tools to be used by other makefiles in defining rules, and
global definitions such as the ISA and machine names that apply to this
build.  Makefile.master.64 contains definitions specific to 64-bit
builds that override the generic definitions.
</para>
</listitem>
<listitem><para>usr/src/Makefile.msg.targ</para>
<para>
Common targets for building message catalogues are defined here. Message
catalogues provide translations of messages for g11n purposes.
</para>
</listitem>
<listitem><para>usr/src/Makefile.psm</para>
<para>
This makefile defines the installation locations for platform-specific
modules.  These are analogous to the other kernel module install
locations /kernel and /usr/kernel (see section 3.2.6 below for more
information on kernel module installation).
</para>
</listitem>
<listitem><para>usr/src/Makefile.psm.targ</para>
<para>
Installation target definitions for platform-specific modules are
defined here.  This instructs the build system how to install files into
the directories defined by Makefile.psm.
</para>
</listitem>
<listitem><para>usr/src/Targetdirs</para>
<para>
This is a set of definitions for the owner, group, and permissions of
each directory that will be created by the installation process. It also
contains information about special symbolic links to be installed for
some 64-bit library versions.
</para>
</listitem>
</itemizedlist>
<sect3 id='_3_2_3_1_Kernel_Makefile_Layout' xreflabel='3.2.3.1 Kernel Makefile Layout'>
<title>3.2.3.1 Kernel Makefile Layout</title>
<para>
The driving makefile for any module is located in the leaf directory
(build directory) where the module and its component objects are built.
After a 'make clobber' operation, the makefile should be the only file
remaining in that directory.  There are two other types of makefiles in
the tree: suffixed and non-suffixed.  Common definitions and rules
needed by all leaf makefiles are contained in the suffixed makefiles;
these are included by leaf makefiles.  Non-suffixed makefiles generally
invoke multiple lower-level makefiles with the same target so that many
modules can be built with a single make invocation.
</para>
<itemizedlist>
<listitem><para>uts/Makefile</para>
</listitem>
<listitem><para>uts/sparc/Makefile</para>
</listitem>
<listitem><para>uts/sun4u/Makefile</para>
</listitem>
<listitem><para>uts/intel/Makefile</para>
</listitem>
<listitem><para>uts/intel/ia32/Makefile</para>
</listitem>
<listitem><para>uts/i86pc/Makefile</para>
<para>
These makefiles generally are cognizant of the components
made in subdirectories and invoke makefiles in those sub-
directories to perform the actual build. Some targets (or
pseudo-targets) may be directly built at this level (such
as the cscope databases).
</para>
</listitem>
<listitem><para>uts/Makefile.uts</para>
<para>
Contains common definitions for all possible architectures.
</para>
</listitem>
<listitem><para>uts/Makefile.targ</para>
<para>
Contains common targets for all possible architectures.
</para>
</listitem>
<listitem><para>uts/common/Makefile.files</para>
</listitem>
<listitem><para>uts/sun/Makefile.files</para>
</listitem>
<listitem><para>uts/sparc/Makefile.files</para>
</listitem>
<listitem><para>uts/sun4/Makefile.files</para>
</listitem>
<listitem><para>uts/sun4u/Makefile.files</para>
</listitem>
<listitem><para>uts/intel/Makefile.files</para>
</listitem>
<listitem><para>uts/intel/ia32/Makefile.files</para>
</listitem>
<listitem><para>uts/i86pc/Makefile.files</para>
<para>
These makefiles are divided into two sections. The first
section defines the object lists which comprise each module.
The second section defines the appropriate header search paths
and other machine-specific global build parameters.
</para>
</listitem>
<listitem><para>uts/common/Makefile.rules</para>
</listitem>
<listitem><para>uts/sun/Makefile.rules</para>
</listitem>
<listitem><para>uts/sparc/Makefile.rules</para>
</listitem>
<listitem><para>uts/sun4/Makefile.rules</para>
</listitem>
<listitem><para>uts/sun4u/Makefile.rules</para>
</listitem>
<listitem><para>uts/intel/Makefile.rules</para>
</listitem>
<listitem><para>uts/intel/ia32/Makefile.rules</para>
</listitem>
<listitem><para>uts/intel/amd64/Makefile.rules</para>
</listitem>
<listitem><para>uts/i86pc/Makefile.rules</para>
<para>
The files provide build rules (targets) which allow make to
function in a multiple directory environment. Each source tree
below the directory containing the makefile has a build rule
in the file.
</para>
</listitem>
<listitem><para>uts/sun4/Makefile.sun4</para>
</listitem>
<listitem><para>uts/sun4u/Makefile.sun4u</para>
</listitem>
<listitem><para>uts/intel/Makefile.intel</para>
</listitem>
<listitem><para>uts/intel/ia32/Makefile.ia32</para>
</listitem>
<listitem><para>uts/i86pc/Makefile.i86pc</para>
<para>
These makefiles contain the definitions specific (defaults) to
the obvious &quot;implementation architecture&quot;. These rules can be
overridden in specific leaf node makefiles if necessary.
</para>
</listitem>
<listitem><para>Makefile.*.shared</para>
<para>
These makefiles provide settings that are shared between the
open-source makefiles and the closed-source makefiles that are
internal to Sun.  See <xref linkend='_3_2_8_Source_Files_not_Include' /> for more
details.
</para>
</listitem>
<listitem><para>uts/sun4u/unix/Makefile</para>
</listitem>
<listitem><para>uts/i86pc/unix/Makefile</para>
<para>
Main driving makefile for building unix.
</para>
</listitem>
<listitem><para>uts/sun4u/MODULE/Makefile (for MODULE in cgsix, cpu, kb, ...)</para>
<para>
Main driving makefile for building MODULE.
</para>
</listitem>
<listitem><para>uts/sun4u/genunix/Makefile</para>
</listitem>
<listitem><para>uts/i86pc/genunix/Makefile</para>
<para>
Main driving makefile for building genunix.
</para>
</listitem>
</itemizedlist>
<para>
Issuing the command 'make' in the uts directory will cause all
supported, modularized kernels and modules to be built.
</para>
<para>
Issuing the command 'make' in a uts/ARCHITECTURE directory (i.e.:
uts/sparc) will cause all supported, &quot;implementation
architecture&quot;-independent modules for ARCHITECTURE to be built.
</para>
<para>
Issuing the command 'make' in a uts/MACHINE directory (i.e.:
uts/sun4u) will cause that kernel and all supported, &quot;implementation
architecture&quot;- dependent modules for MACHINE to be built.
</para>
<para>
The makefiles are verbosely commented. It is desired that they should
stay this way.
</para>
</sect3>
<sect3 id='_3_2_3_2_Command_Makefile_Layou' xreflabel='3.2.3.2 Command Makefile Layout'>
<title>3.2.3.2 Command Makefile Layout</title>
<para>
Most command and daemon subdirectories follow one of two general layout
rules, depending on where object files will be located (see sections
3.2.2.2 and 3.2.2.3).  For ISA-dependent programs, the layout is similar
to that used by the kernel.  Programs which do not need ISA-dependent
build behavior use a simplified makefile layout.  In the description
here, we use the example of a generic command called &quot;foocmd&quot; whose
sources are located in usr/src/cmd/foocmd.  The makefiles relevant to
building foocmd are:
</para>
<itemizedlist>
<listitem><para>usr/src/cmd/Makefile</para>
<para>
Top-level driving makefile for all commands/daemons.  This is
a simple recursive makefile which is aware of which
subdirectories should be built and will cause the given target
to be rebuilt in each of them.
</para>
</listitem>
<listitem><para>usr/src/cmd/Makefile.cmd</para>
<para>
This makefile defines the installation directories and rules
for installing executables into them.
</para>
</listitem>
<listitem><para>usr/src/cmd/Makefile.cmd.64</para>
<para>
Additional definitions specific to 64-bit builds are provided
here.
</para>
</listitem>
<listitem><para>usr/src/cmd/Makefile.cmd.bsm</para>
<para>
This specialty makefile is used only by auditstat and dminfo.
It provides some generic boilerplate rules.
</para>
</listitem>
<listitem><para>usr/src/cmd/Makefile.targ</para>
<para>
Basic target definitions for clobber, lint, and installation.
</para>
</listitem>
<listitem><para>usr/src/cmd/foocmd/Makefile</para>
<para>
Driving makefile for foocmd.  Normally defines PROG but otherwise
contains only boilerplate definitions and targets.  This is almost
always copied from another similar makefile.  If foocmd does not require
ISA-dependent build behavior, rules will normally be specified directly,
including those for the install target.  If foocmd does require
ISA-dependent build behavior, this makefile will instead define SUBDIRS
to include the ISA-specific versions that must be built, and define
targets recursively.  This will usually leave the install target
definition for each ISA makefile and cause a link to $(ISAEXEC) to be
created.  See section 3.2.5 for more information on platform
dependencies and $(ISAEXEC).
</para>
</listitem>
<listitem><para>usr/src/cmd/foocmd/Makefile.com</para>
<para>
Defines PROG, OBJS, SRCS, and includes Makefile.cmd.  May also
contain additional flags for compilation or linking.  This makefile
normally defines targets for all, $(PROG), clean, and lint; this
portion is usually generic and would be copied from another similar
makefile.
</para>
</listitem>
<listitem><para>usr/src/cmd/foocmd/*/Makefile</para>
<para>
ISA-specific makefiles, which may define additional
ISA-specific flags or targets, and will generally include its
own install target to install the ISA-specific program(s) it
builds.
</para>
</listitem>
</itemizedlist>
</sect3>
<sect3 id='_3_2_3_3_Library_Makefile_Layou' xreflabel='3.2.3.3 Library Makefile Layout'>
<title>3.2.3.3 Library Makefile Layout</title>
<para>
Most library subdirectories follow the same general layout, which is
similar to the command layout.  Unlike commands, most libraries are
built for both 32- and 64-bit architecture variants, so ISA-specific
directories will almost always be present.  Therefore, the overall build
structure for each library is similar to that of the kernel.  See
<xref linkend='_3_3_3_3_Adding_New_Libraries' /> for more detailed information on library
makefiles.
</para>
</sect3>
</sect2>
<sect2 id='_3_2_4_Makefile_Operation' xreflabel='3.2.4 Makefile Operation'>
<title>3.2.4 Makefile Operation</title>
<para>
This section describes in detail how make dependencies and rules are
built up, and how each individual makefile contributes to the build
process.  Once you understand how the makefiles work, modifying
existing build rules and creating new ones are mainly an exercise in
copying existing files and making minor modifications to them.  We
begin with the kernel makefiles, then address the very similar command
and library makefiles.
</para>
<sect3 id='_3_2_4_1_Kernel_Makefile_Operat' xreflabel='3.2.4.1 Kernel Makefile Operation'>
<title>3.2.4.1 Kernel Makefile Operation</title>
<para>
There are two parts to the make dependencies: a set of targets and a
set of rules.
</para>
<para>
The rules are contained in the Makefile.rules files in each directory
under uts.  They cover how to compile a source file in some other
directory (common/io for example) into an object file in the build
directory described above.  They also describe which sources are
needed to build a given object file.  The order in which they are
specified determines which source file is needed if there are multiple
source files matching the same basename.  The key to all this is
understanding that all rules and targets are static and
module-independent, but variables set in each module's build directory
(leaf) makefile define the module-specific build information.
</para>
<para>
The targets are of two kinds: the first are &quot;make targets,&quot; generic
directives you can give make like &quot;all&quot; or &quot;install&quot; which are
executed in each build directory.  The build directory makefiles in
turn include other makefiles that contain rules for building objects
and modules.  The second type of target is more interesting - they are
the actual module names (directories, in fact) that must be built.
These variables are called KMODS and XMODS.
</para>
<para>
If KMODS contains, for example, &quot;aac ata asy&quot;, then for each of the
aac, ata, and asy build directories, the make system will cd to that
directory and rerun make with whatever target (all, install, etc) is
given.  The rules for that module are derived from all the included
makefiles; the crucial variables to look for are of the form XXX_OBJS,
where XXX is the module name.  More than one makefile may contain
definitions adding to each of these object lists, because building a
module may require different objects on each platform.
</para>
<para>
XMODS is used only for building export versions of the commercial
Solaris product; it is not used in building ON.
</para>
<para>
So for example we see:
</para>
<programlisting><![CDATA[
common/Makefile.files:ASY_OBJS +=      asy.o
]]></programlisting>
<para>
This indicates that the asy.o object is needed to build the ASY
module.  The makefile in the &lt;platform&gt;/asy directory will reference
ASY_OBJS and thus know what to build.  So in intel/asy/Makefile we
see:
</para>
<programlisting><![CDATA[
MODULE          = asy
OBJECTS         = $(ASY_OBJS:%=$(OBJS_DIR)/%)
]]></programlisting>
<para>
So, what good is this?  Plenty.  Because our ALL_TARGET is also
defined:
</para>
<programlisting><![CDATA[
ALL_TARGET      = $(BINARY) $(SRC_CONFILE)
]]></programlisting>
<para>
Makefile.uts defines BINARY as follows:
</para>
<programlisting><![CDATA[
BINARY             = $(OBJS_DIR)/$(MODULE)
]]></programlisting>
<para>
And OBJS_DIR is the individual module build directory I described at
the beginning.  So, make knows we need to build
usr/src/uts/intel/asy/obj32/asy.  Makefile.targ defines the rules for
doing so, too:
</para>
<programlisting><![CDATA[
$(BINARY):              $(OBJECTS)
	$(LD) -r $(LDFLAGS) -o $@ $(OBJECTS)
	$(CTFMERGE_UNIQUIFY_AGAINST_GENUNIX)
	$(POST_PROCESS)
	$(ELFSIGN_MOD)
]]></programlisting>
<para>
We're almost there - OBJECTS have to come from somewhere.  We find
this defined in intel/asy/Makefile:
</para>
<programlisting><![CDATA[
OBJECTS         = $(ASY_OBJS:%=$(OBJS_DIR)/%)
]]></programlisting>
<para>
And that's that.  We have a module (asy) that has a BINARY (obj32/asy)
which depends on OBJECTS made from ASY_OBJS.  The rules for each entry
in ASY_OBJS is in one of the Makefile.rules files; they look something
like this:
</para>
<programlisting><![CDATA[
$(OBJS_DIR)/%.o:                $(UTSBASE)/common/io/%.c
	$(COMPILE.c) -o $@ $<
	$(CTFCONVERT_O)
]]></programlisting>
<para>
Each object is built in accordance with these rules.  The rule for
$(BINARY) then links them into the module.
</para>
<para>
We can now put it all together.  The extensive use of macros and local
per-module definitions provides much greater flexibility, but in the
example given, the equivalent makefile fragment would look very
familiar:
</para>
<programlisting><![CDATA[
KMODS +=	asy
]]></programlisting>
<programlisting><![CDATA[
all:	$(KMODS)
]]></programlisting>
<programlisting><![CDATA[
asy:	obj32/asy.o
	$(LD) -r $(LDFLAGS) -o $@ obj32/asy.o
	...
]]></programlisting>
<programlisting><![CDATA[
obj32/asy.o:	../../common/io/asy.c
	$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
	...
]]></programlisting>
</sect3>
<sect3 id='_3_2_4_2_Command_Makefile_Opera' xreflabel='3.2.4.2 Command Makefile Operation'>
<title>3.2.4.2 Command Makefile Operation</title>
<para>
Command makefiles vary widely, as described above.  Therefore it is
impossible to provide a &quot;representative example&quot; of a command makefile.
However, understanding the material in sections 3.2.4.1 and 3.3.3.3 will
provide you with the necessary knowledge to work with command makefiles.
As always, if you are looking for information about a specific command,
it is usually best to use the mailing lists and other community
resources.
</para>
</sect3>
<sect3 id='_3_2_4_3_Library_Makefile_Opera' xreflabel='3.2.4.3 Library Makefile Operation'>
<title>3.2.4.3 Library Makefile Operation</title>
<para>
Section 3.3.3.3 describes library makefile operation in detail.
</para>
</sect3>
</sect2>
<sect2 id='_3_2_5_ISA_Dependencies' xreflabel='3.2.5 ISA Dependencies'>
<title>3.2.5 ISA Dependencies</title>
<para>
Most code in OpenSolaris is generic and platform- and ISA-independent;
that is, it is portable code that can be compiled and run on any
system for which a suitable compiler is available.  However, even
portable code must sometimes deal with specific attributes of the
system on which it runs, or must be provided compiled for multiple
supported architectures so that users can run or link with the
architecture-specific version of their choosing.
</para>
<para>
There are two distinct situations in which multiple
architecture-specific builds must be shipped: commands that, by their
nature, must have visibility into the system's hardware characteristics,
and libraries, which must be built separately for each architecture a
developer may wish to target.  Each case is discussed in its own
subsection below.
</para>
<sect3 id='_3_2_5_1_ISA_Dependent_Commands' xreflabel='3.2.5.1 ISA-Dependent Commands'>
<title>3.2.5.1 ISA-Dependent Commands</title>
<para>
Commands (normally executable programs or daemons) usually do not depend
on the ISA on which they are executed; that is, they will be built and
installed in the same way regardless of the ISA they are built for.
Some commands, however, mainly those which operate on other processes or
manipulate binary objects, must behave differently depending on the
ISA(s) supported by the system and/or their targets.  The
/usr/lib/isaexec wrapper program provides this behavior in the following
way:
</para>
<para>
First, one or more ISA-specific programs are installed into
ISA-specific directories in the system.  These are subdirectories of
those directories which ordinarily contain executable programs, such
as /usr/bin.  On SPARC systems, ISA subdirectories might include
/usr/bin/sparcv7 and /usr/bin/sparcv9 to contain 32- and 64-bit
binaries, respectively.  Other ISAs may be supported by other systems;
you can find out which your system supports by using isalist(1).
</para>
<para>
Next, a hard link is installed into the ordinary binary directory
(in the example above, /usr/bin) targeting /usr/lib/isaexec.  This
will cause isaexec to be invoked with the name of the ISA-dependent
program the user has executed.
</para>
<para>
When this happens, isaexec will select the most appropriate
ISA-specific program installed in the first step and exec(2) it.  This
is transparent, so a user will not notice that a separate program has
been invoked.
</para>
<para>
A similar mechanism (/usr/lib/platexec) exists for platform-specific
programs; these are much less common even than ISA-specific programs.
</para>
<para>
Because it needs to interact both with user processes and kernel data
structures, dtrace(1) is an example of a command that must provide
multiple ISA-specific versions.
</para>
<para>
cmd/dtrace contains two makefiles: Makefile and Makefile.com.  It also
contains a single source file, dtrace.c, and four ISA directories:
amd64, i386, sparc, and sparcv9.  Each contains a single makefile.
The top-level makefiles should look very familiar after our tour of
the uts makefiles; Makefile is mainly boilerplate, customized only to
specify that the program produced is ISA- specific and therefore a
link to the isaexec program needs to be installed into /usr/sbin in
the proto area:
</para>
<programlisting><![CDATA[
install:        $(SUBDIRS)
	-$(RM) $(ROOTUSRSBINPROG)
	-$(LN) $(ISAEXEC) $(ROOTUSRSBINPROG)
]]></programlisting>
<para>
Otherwise, it simply leaves all building and installation to the
makefiles in the ISA subdirectories.  Makefile.com is also
boilerplate; it specifies the name of the program to build and the
objects from which it must be built:
</para>
<programlisting><![CDATA[
PROG = dtrace
OBJS = dtrace.o
]]></programlisting>
<para>
It then transforms the objects into sources:
</para>
<programlisting><![CDATA[
SRCS = $(OBJS:%.o=../%.c)
]]></programlisting>
<para>
and includes the generic top-level Makefile.cmd fragment to pick up
build rules.
</para>
<para>
Compilation and linkage flags are specified:
</para>
<programlisting><![CDATA[
CFLAGS += $(CCVERBOSE)
CFLAGS64 += $(CCVERBOSE)
LDLIBS += -ldtrace -lproc
]]></programlisting>
<para>
and the remainder consists of a handful of generic build rules.  One
feature is noteworthy: an extra ../ is prepended to all paths in this
fragment.  This is because it is always included by makefiles
interpreted from the ISA-specific build directory, which is one level
deeper than Makefile.com itself.
</para>
<para>
The makefiles in the ISA-specific build directories are even simpler;
they each consist of only two lines:
</para>
<programlisting><![CDATA[
include ../Makefile.com
]]></programlisting>
<programlisting><![CDATA[
install: all $(ROOTUSRSBINPROG32)
]]></programlisting>
<para>
The first line picks up all common definitions in the makefile we just
examined, and the second specifies (indirectly) the location in which
the program is to be installed.  To complete the picture, we need to
briefly examine usr/src/cmd/Makefile.cmd, which defines the various
locations in which programs can be installed.  Since we have not
defined ROOTUSRSBINPROG32, it must be defined there, and indeed it is:
</para>
<programlisting><![CDATA[
ROOTUSRSBIN=    $(ROOT)/usr/sbin
ROOTUSRSBINPROG=$(PROG:%=$(ROOTUSRSBIN)/%)
ROOTUSRSBIN32=  $(ROOTUSRSBIN)/$(MACH32)
ROOTUSRSBINPROG32=      $(PROG:%=$(ROOTUSRSBIN32)/%)
]]></programlisting>
<para>
Note that the program is actually installed in /usr/sbin/$(MACH32),
which is not normally in a user's search path.  But remember that we
also created a link from $(ROOTUSRSBINPROG) to $(ISAEXEC); expanding
these variables shows that we will actually install two separate
files:
</para>
<programlisting><![CDATA[
$(ROOT)/usr/sbin/dtrace		-> $(ROOT)/usr/lib/isaexec
$(ROOT)/usr/sbin/$(MACH32)/dtrace	(our executable program)
]]></programlisting>
<para>
Since the isaexec program is responsible for selecting an ISA-specific
program from among several options depending on the system's supported
instruction sets, we can see that a typical system will have one or
more dtrace(1) binaries installed and that when dtrace(1) is run by
the user, isaexec will select the appropriate one from those installed
in the ISA-specific subdirectories of /usr/sbin.  As we might expect,
other ISA-specific makefiles under cmd/dtrace install their binaries
into ROOTUSRSBIN64, also defined in usr/src/cmd/Makefile.cmd.
</para>
</sect3>
<sect3 id='_3_2_5_2_ISA_Dependent_Librarie' xreflabel='3.2.5.2 ISA-Dependent Libraries'>
<title>3.2.5.2 ISA-Dependent Libraries</title>
<para>
Libraries, unlike commands, must almost always be built for all
supported ISAs and have separate ISA-specific versions installed on,
at minimum, every system that supports that ISA.  In practice,
libraries for each ISA in the system's processor family are installed.
This allows developers on that system to write programs using any
supported ISA and link them with the appropriate system libraries (it
is not possible, for example, to link 32-bit object files and 64-bit
libraries, nor vice versa).
</para>
<para>
Libraries use a build system very similar to that used by commands
which must provide multiple ISA-specific executable programs.  We
examine here the makefiles used by dtrace(1)'s library counterpart
libdtrace(3LIB) and how they support building and installing multiple
ISA-specific versions of the dtrace library.
</para>
<para>
lib/libdtrace contains two makefiles: Makefile and Makefile.com.  It
also contains a directory for common code and four ISA directories:
amd64, i386, sparc, and sparcv9.  Each ISA directory contains a single
makefile and in some cases some ISA-specific sources.  The top-level
Makefile should once again look very familiar; is very similar to the
uts and cmd makefiles and is mainly boilerplate.  There are a few
customizations to add a yydebug target and to tell top-level makefiles
that lex and yacc generated files should not have cross-references
built against them.
</para>
<programlisting><![CDATA[
yydebug := TARGET = yydebug
...
lint yydebug: $(SUBDIRS)
]]></programlisting>
<para>
and
</para>
<programlisting><![CDATA[
XRDIRS = common i386 sparc sparcv9
XRDEL = dt_lex.c dt_grammar.c Makefile*
]]></programlisting>
<para>
Otherwise, it simply leaves all building and installation to the
makefiles in the ISA subdirectories.  Makefile.com is somewhat more
interesting.  It first specifies the name of the library to build (in
static format; shared library names are translated as we shall see
below), and the library version.  These are common to all library
makefiles.  Next, we see long lists of source files used to build the
library, and an OBJECTS specification.  This particular library also has
some unique characteristics, including the D runtime init code, built as
a separate object file (drti.o), and a number of D &quot;header&quot; files which
are installed into a separate directory /usr/lib/dtrace.  You can see
these unique features here:
</para>
<programlisting><![CDATA[
DRTISRC = drti.c
DRTIOBJ = $(DRTISRC:%.c=%.o)
]]></programlisting>
<programlisting><![CDATA[
DLIBSRCS += \
	errno.d \
	io.d \
	procfs.d \
	regs.d \
	sched.d \
	signal.d \
	unistd.d
...
ROOTDLIBDIR = $(ROOT)/usr/lib/dtrace
ROOTDLIBDIR64 = $(ROOT)/usr/lib/dtrace/64
...
$(ROOTDLIBDIR):
	$(INS.dir)
]]></programlisting>
<programlisting><![CDATA[
$(ROOTDLIBDIR64): $(ROOTDLIBDIR)
	$(INS.dir)
]]></programlisting>
<programlisting><![CDATA[
$(ROOTDLIBDIR)/%.d: ../common/%.d
	$(INS.file)
]]></programlisting>
<programlisting><![CDATA[
$(ROOTDLIBDIR)/%.d: ../$(MACH)/%.d
	$(INS.file)
]]></programlisting>
<programlisting><![CDATA[
$(ROOTDLIBDIR)/%.d: %.d
	$(INS.file)
]]></programlisting>
<para>
Note that some of the D &quot;headers&quot; are in turn generated from other
files; this makefile includes rules for performing these
transformations.
</para>
<para>
Once the LIBSRCS and OBJECTS have been defined, the generic library
makefile fragment Makefile.lib is included to provide target and
directory definitions.
</para>
<para>
Binary objects are built in the pics/ subdirectory.  pics stands for
position- independent code(s), referring to the fact that dynamic shared
libraries are built in such a way as to be loaded at any address.  This
is an historical artifact; static linking of system libraries is not
supported by OpenSolaris-based distributions, so the non-PIC objects
which would have been used to build an archive-style library are not
built.  The rules for building are given as:
</para>
<programlisting><![CDATA[
pics/%.o: ../$(MACH)/%.c 
	$(COMPILE.c) -o $@ $<
	$(POST_PROCESS_O)
]]></programlisting>
<programlisting><![CDATA[
pics/%.o: ../$(MACH)/%.s
	$(COMPILE.s) -o $@ $<
	$(POST_PROCESS_O)
]]></programlisting>
<programlisting><![CDATA[
%.o: ../common/%.c
	$(COMPILE.c) -o $@ $<
	$(POST_PROCESS_O)
]]></programlisting>
<para>
Note that because this makefile fragment is included by each ISA's
makefile, the objects produced will be placed relative to that
makefile, in each ISA directory.  Once again, this also means that
included makefile fragments include an additional ../ component.
</para>
<para>
The libdtrace Makefile.com also contains a large number of custom
rules to accommodate building a lexer and parser from lex(1) and
yacc(1) definitions; these sources are then compiled specially using
the custom rules and are removed when the clean or clobber target is
executed.
</para>
<para>
The makefiles in the ISA-specific build directories are once again
very simple.  The SPARC-specific makefile, for example, defines
additional assembler flags, specifies the directory where the library
interface map is located, and then includes the common makefile:
</para>
<programlisting><![CDATA[
ASFLAGS += -D_ASM -K PIC -P
]]></programlisting>
<programlisting><![CDATA[
MAPDIR = ../spec/sparc
include ../Makefile.com
]]></programlisting>
<para>
The makefile may also add a few ISA-specific sources to the build
list; for example, sparc/Makefile includes:
</para>
<programlisting><![CDATA[
SRCS += dt_asmsubr.s
OBJECTS += dt_asmsubr.o
]]></programlisting>
<para>
And once again, a separate install target is provided to indicate the
directories where these specific libraries and headers should be
installed:
</para>
<programlisting><![CDATA[
install yydebug: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) \
	$(ROOTDLIBS) $(ROOTDOBJS)
]]></programlisting>
<para>
To support building a separate set of 64-bit objects, sparcv9/Makefile
includes slightly different definitions and a different install
target:
</para>
<programlisting><![CDATA[
MAPDIR = ../spec/sparcv9
include ../Makefile.com
include ../../Makefile.lib.64
]]></programlisting>
<programlisting><![CDATA[
CPPFLAGS += -D_ELF64
...
install yydebug: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) \
	$(ROOTDLIBS) $(ROOTDOBJS64)
]]></programlisting>
<para>
Note the additional inclusion of Makefile.lib.64 and the additional
flag for 64-bit ELF targets.  Also, the 64-bit-specific versions of
the installation files are used, which as we can see in Makefile.lib
cause them to be installed into /usr/lib/sparcv9:
</para>
<programlisting><![CDATA[
ROOTLIBDIR=     $(ROOT)/usr/lib
ROOTLIBDIR64=   $(ROOT)/usr/lib/$(MACH64)
...
ROOTLIBS=       $(LIBS:%=$(ROOTLIBDIR)/%)
ROOTLIBS64=     $(LIBS:%=$(ROOTLIBDIR64)/%)
]]></programlisting>
<para>
The linker (ld(1)) and runtime loader (ld.so.1(1)) know which of these
directories to search for libraries depending on the bitness of the
objects being linked or the program being run, respectively.  For more
information about 32- versus 64-bit linking, consult the Solaris Linkers
and Libraries Guide, which can be found at
<ulink url='http://docs.sun.com/db/doc/816-1386'>http://docs.sun.com/db/doc/816-1386</ulink>.
</para>
</sect3>
</sect2>
<sect2 id='_3_2_6_Understanding_Kernel_Mod' xreflabel='3.2.6 Understanding Kernel Module Installation'>
<title>3.2.6 Understanding Kernel Module Installation</title>
<para>
The install target causes binaries and headers to be installed into a
hierarchy called the prototype or proto area (see section 4.4.1 for more
information on the prototype area's contents and purpose).  The root of
the proto area is defined by the environment variable ROOT.  This
variable is used in defining ROOT_MOD_DIR and USR_MOD_DIR in
usr/src/uts/Makefile.uts:
</para>
<programlisting><![CDATA[
ROOT_MOD_DIR               = $(ROOT)/kernel
USR_MOD_DIR                = $(ROOT)/usr/kernel
]]></programlisting>
<para>
All modules are installed below one of these directories.  The exact
subdirectory used depends on the definition of ROOTMODULE in the
module build directory, which is discussed below.
</para>
<para>
Additional files to be installed may be given by the INSTALL_TARGET
definition in this makefile.  For example, the asy makefile
(usr/src/uts/intel/asy/Makefile) specifies:
</para>
<programlisting><![CDATA[
INSTALL_TARGET  = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
]]></programlisting>
<para>
Since this is a common set of installation targets, let's look at how
each component is derived.
</para>
<para>
$(BINARY) is simply the module itself; we've discussed its
dependencies and rules in detail above.  Including it here requires it
to be fully built before any installation is attempted.
</para>
<para>
$(ROOTMODULE) is a name transform on the name of the module, relocating it
into the prototype area.  For example, usr/src/uts/intel/asy/Makefile defines:
</para>
<programlisting><![CDATA[
ROOTMODULE      = $(ROOT_DRV_DIR)/$(MODULE)
]]></programlisting>
<para>
ROOT_DRV_DIR requires a bit of additional explanation; it is one of
many module installation subdirectories defined in Makefile.uts.
Because the ending location of binary kernel modules depends on the
machine type, specifically its 32 versus 64 bitness, there are really
several definitions.  First, the subdirectory definition for each
64-bit machine type:
</para>
<programlisting><![CDATA[
SUBDIR64_sparc          = sparcv9
SUBDIR64_i386           = amd64
SUBDIR64                = $(SUBDIR64_$(MACH))
]]></programlisting>
<para>
Next, the 32- and 64-bit installation directories for each type of
module:
</para>
<programlisting><![CDATA[
ROOT_KERN_DIR_32        = $(ROOT_MOD_DIR)
ROOT_DRV_DIR_32         = $(ROOT_MOD_DIR)/drv
ROOT_DTRACE_DIR_32      = $(ROOT_MOD_DIR)/dtrace
ROOT_EXEC_DIR_32        = $(ROOT_MOD_DIR)/exec
...
]]></programlisting>
<programlisting><![CDATA[
ROOT_KERN_DIR_64        = $(ROOT_MOD_DIR)/$(SUBDIR64)
ROOT_DRV_DIR_64         = $(ROOT_MOD_DIR)/drv/$(SUBDIR64)
ROOT_DTRACE_DIR_64      = $(ROOT_MOD_DIR)/dtrace/$(SUBDIR64)
ROOT_EXEC_DIR_64        = $(ROOT_MOD_DIR)/exec/$(SUBDIR64)
...
]]></programlisting>
<para>
And finally the selection of either the 32- or 64-bit directory based
on the actual bitness of this build:
</para>
<programlisting><![CDATA[
ROOT_KERN_DIR           = $(ROOT_KERN_DIR_$(CLASS))
ROOT_DRV_DIR            = $(ROOT_DRV_DIR_$(CLASS))
ROOT_DTRACE_DIR         = $(ROOT_DTRACE_DIR_$(CLASS))
ROOT_EXEC_DIR           = $(ROOT_EXEC_DIR_$(CLASS))
...
]]></programlisting>
<para>
There are similar definitions for USR_XXX_DIR based in
$(ROOT)/usr/kernel.  See usr/src/uts/Makefile.uts for the complete
list of possible ROOT_ and USR_ installation directories.
</para>
<para>
The rules for installing files into each of these directories are
given in usr/src/uts/Makefile.targ:
</para>
<programlisting><![CDATA[
$(ROOT_MOD_DIR)/%:      $(OBJS_DIR)/% $(ROOT_MOD_DIR) FRC
	$(INS.file)
]]></programlisting>
<programlisting><![CDATA[
$(ROOT_DRV_DIR)/%:      $(OBJS_DIR)/% $(ROOT_DRV_DIR) FRC
	$(INS.file)
...
]]></programlisting>
<para>
These rules install the file currently located in $(OBJS_DIR),
described in detail above, into the appropriate directory in the proto
area.
</para>
<para>
$(ROOT_CONFFILE) is the module's configuration file (most commonly
used for drivers), transformed into the proto area.  The CONFFILE
variables are defined in usr/src/uts/Makefile.uts:
</para>
<programlisting><![CDATA[
CONFFILE                = $(MODULE).conf
SRC_CONFFILE            = $(CONF_SRCDIR)/$(CONFFILE)
ROOT_CONFFILE_32        = $(ROOTMODULE).conf
ROOT_CONFFILE_64        = $(ROOTMODULE:%/$(SUBDIR64)/$(MODULE)=%/$(MODULE)).conf
ROOT_CONFFILE           = $(ROOT_CONFFILE_$(CLASS))
]]></programlisting>
<para>
Each module's Makefile defines CONF_SRCDIR to specify the location of
the configuration file that should be installed on this platform.  The
asy makefile defines:
</para>
<programlisting><![CDATA[
CONF_SRCDIR     = $(UTSBASE)/common/io
]]></programlisting>
<para>
which causes usr/src/uts/common/io/asy.conf to be installed in the
proto area as /kernel/drv/asy.conf.  Note that the configuration file
installation directory does not depend on whether this is a 32- or
64-bit build.
</para>
<para>
Note that although it is confusing, installation targets are always
named ROOTMODULE, ROOT_CONFFILE, and so on, even if they are actually
installed into one of the USR_ directories.  This simplifies the
higher-level makefiles.
</para>
</sect2>
<sect2 id='_3_2_7_Finding_Sources_for_a_Mo' xreflabel='3.2.7 Finding Sources for a Module'>
<title>3.2.7 Finding Sources for a Module</title>
<para>
As we've seen, the sources are derived from $(XXX_OBJS) and the included
rules.  Now, here's the tricky part - finding where those sources are.
The easiest way by far is to run make from the module's object directory
and observe the compilation commands that are run.  The path to each
source file will be included in the output.  This is the simplest and
recommended way to find which source files are needed to build a module.
However, if this does not work (perhaps the makefile itself is buggy) or
if you want to gain greater understanding, the rest of this section
describes logical processes for finding source files.
</para>
<para>
Since you know the basenames (they are simply the XXX_OBJS entries with
.o replaced by .c) you can use a simple
</para>
<programlisting><![CDATA[
$ find usr/src/uts -name asy.c
]]></programlisting>
<para>
Suppose you find two source files with the same name - which is
actually used?  There are two ways to figure this out.  The lazy way
is to use make -d to show you the exact dependencies being used.
Alternatively, you could reason it out, starting with the fact that
not all source files are used on your platform (i.e.,
usr/src/uts/sparc/* is not used by x86 builds), and then looking at
the specific order of the rules in each Makefile.rules.  The more
specific rules are listed first and take precedence over later rules
(in fact they all add a dependency to the specific object file in
question, but since the rules all use $&lt;, only the first dependency is
actually used).
</para>
<para>
Non-kernel source files are easier to locate, since the cmd and lib
directories are generally organized with one subdirectory for each
library or command, named accordingly.  The major exceptions are
cmd/sgs, which contains the entire binary tools subsystem, and
cmd/cmd-inet, which contains most of the Berkeley networking commands
and daemons as well as some additional network-related utilities, laid
out in a BSD-style directory structure.
</para>
</sect2>
<sect2 id='_3_2_8_Source_Files_not_Include' xreflabel='3.2.8 Source Files not Included'>
<title>3.2.8 Source Files not Included</title>
<para>
Some sources used to build the branded Solaris product are not included in
OpenSolaris.  There are two main reasons for this:
</para>
<itemizedlist>
<listitem><para>The source could be subject to third-party rights.</para>
<para>
Sun's lawyers won't let anyone talk about this.  Not even a little bit.
They do love explaining it themselves, though, so you should contact
Sun's legal department and ask there.  We can't help you.  Sorry.
</para>
</listitem>
<listitem><para>The consolidation may not yet have been released.</para>
<para>
OpenSolaris does not yet include all consolidations in Solaris, and some
consolidations are still incomplete.  See the program roadmap at
<ulink url='http://www.opensolaris.org/os/about/roadmap/'>http://www.opensolaris.org/os/about/roadmap/</ulink> and the downloads page
at <ulink url='http://www.opensolaris.org/os/downloads/'>http://www.opensolaris.org/os/downloads/</ulink> for information on the
consolidations that interest you.
</para>
</listitem>
</itemizedlist>
<para>
To accommodate fully functional builds even though some sources are
missing, a set of closed binaries are available, and the build system
has been modified to make use of them.  The makefile variable
CLOSED_BUILD controls whether the build system will use the prebuilt
closed binaries or look for the closed sources.
</para>
<para>
CLOSED_BUILD is typically used in makefile lines that build up the
list of modules or subdirectories that are to be built.  Makefile
lines that start with CLOSED_BUILD, e.g.,
</para>
<programlisting><![CDATA[
$(CLOSED_BUILD)DCSUBDIRS += \
	$(CLOSED)/cmd/pax
]]></programlisting>
<para>
are for use only when the closed sources are present.
</para>
<para>
Sometimes a separate closed module list is built up, rather than
adding to the open module list.  This approach is used extensively in
the kernel, as in
</para>
<programlisting><![CDATA[
$(CLOSED_BUILD)CLOSED_DRV_KMODS	+= chxge
]]></programlisting>
<para>
Because this approach requires additional variables, the first
approach is usually preferred.  The second approach is used when the
list needs to contain individual component names, rather than paths.
For example, the kernel makefiles use the module names to construct a
series of &quot;-l&quot; clauses for linting; that would be a lot messier if
paths were used instead of module names.
</para>
<para>
You shouldn't normally need to set CLOSED_BUILD.  Instead, bldenv(1)
and nightly(1) set the environment variable CLOSED_IS_PRESENT, and the
ON makefiles use this to set CLOSED_BUILD.
</para>
<para>
The kernel provides an additional challenge, which is that many
makefile rules and declarations are practically the same for both
the open and closed source trees.  To avoid duplication of code, the
common text was put in shared makefiles (e.g., Makefile.sun4u.shared).
When used for open code, the makefile variable $(UTSTREE) is set to
$(UTSBASE).  For closed code, it is set to $(UTSCLOSED).
</para>
</sect2>
</sect1>
<sect1 id='_3_3_Using_Your_Workspace' xreflabel='3.3 Using Your Workspace'>
<title>3.3 Using Your Workspace</title>
<para>
This section describes how to perform common operations on your
<xref linkend='_workspace' />, such as editing files and modifying the build system.
</para>
<sect2 id='_3_3_1_Getting_Ready_to_Work' xreflabel='3.3.1 Getting Ready to Work'>
<title>3.3.1 Getting Ready to Work</title>
<para>
Once you have brought over a <xref linkend='_workspace' />, you must set up both the
workspace itself and your environment before you can safely use it.
</para>
<para>
First, you must set your environment variables appropriately so that the
build tools will work properly.  This must be done once in any shell
which will run commands that affect the workspace.  Although there are
numerous variables which must be set, nearly all of them are set by
bldenv(1), which accepts a nightly-style environment file.  For example,
if your workspace's environment file is in /aux0/testws/opensolaris.sh,
you would need to run the following command in each shell from which you
will run commands that affect the workspace:
</para>
<programlisting><![CDATA[
$ bldenv /aux0/testws/opensolaris.sh
]]></programlisting>
<para>
It may be tempting to run this command from your shell initialization
scripts; however, if you have more than one workspace, it can be
inconvenient and even dangerous, as you may inadvertently perform an
operation on the wrong workspace.
</para>
</sect2>
<sect2 id='_3_3_2_Editing_Files' xreflabel='3.3.2 Editing Files'>
<title>3.3.2 Editing Files</title>
<para>
You can use any text editor you like to edit source files.  Although
choice of editor is a personal matter, not all editors are equal.  In
particular, there are two types of editor behavior which are certain to
cause problems.  First, some editors such as pico and nano wrap lines
longer than 72 characters or so.  While this is fine for documents, it
causes havoc in source files.  If you must use such an editor, be sure
to turn off line wrapping; otherwise your diffs will include large
quantities of noise and the resulting file may not compile.  Second,
some editors, especially on non-Unix systems which may have different
conventions, will change newline characters from '\n' to something else.
If you must edit sources on a foreign system, be absolutely certain your
editor outputs Unix-style newlines.  Source files containing foreign
newline characters cannot be integrated into any OpenSolaris
consolidation and may not compile.
</para>
<para>
When you edit source files, be sure that you are familiar with the style
guide; see section 7.2 for more details.  Once again, not all editors
are equal: some may offer the ability to set parameters that will help
you to write conformant code, while others may enforce fixed settings
which conflict with our style.  Regardless of your choice of editor, you
will need to be sure that your code conforms to the style guidelines.
</para>
</sect2>
<sect2 id='_3_3_3_Modifying_the_ON_Build_S' xreflabel='3.3.3 Modifying the ON Build System'>
<title>3.3.3 Modifying the ON Build System</title>
<para>
This section provides detailed, step-by-step instructions for common
build-related tasks, such as adding or moving kernel modules and adding
new libraries.  You should also read the sections regarding makefile
layout and operation to gain a better understanding of the overall build
system.
</para>
<sect3 id='_3_3_3_1_Adding_a_New_Kernel_Mo' xreflabel='3.3.3.1 Adding a New Kernel Module'>
<title>3.3.3.1 Adding a New Kernel Module</title>
<para>
The most common build-related operation developers need to perform is
adding a new kernel module to the <xref linkend='_gate' />.  In this section, we describe
the process of adding build instructions for foofs, whose sources are
located under usr/src/uts/common/fs/foofs.  Adding related commands and
libraries (in usr/src/cmd and usr/src/lib) is not covered here.
</para>
<para>
0) Create the usr/src/uts/common/fs/foofs directory and populate it with
your sources.
</para>
<para>
1) Edit uts/*/Makefiles.files to define the set of objects. By
convention the symbolic name of this set is of the form MODULE_OBJS,
where MODULE is the module name (foofs). The files in each subtree
should be defined in the Makefile.files in the root directory of that
subtree. Note that they are defined using the += operator, so that the
set can be accumulated across multiple makefiles. As example:
</para>
<programlisting><![CDATA[
FOOFS_OBJS +=	foovfs.o foovno.o
]]></programlisting>
<para>
Each source file needs a build rule in the corresponding Makefile.rules
file (compilation and linting). A typical pair of entries would be:
</para>
<programlisting><![CDATA[
$(OBJS_DIR)/%.o:		$(UTSBASE)/common/fs/foofs/%.c
	$(COMPILE.c) -o $@ $<
	$(CTFCONVERT_O)
]]></programlisting>
<programlisting><![CDATA[
$(LINTS_DIR)/%.ln:		$(UTSBASE)/common/fs/foofs/%.c
	@($(LHEAD) $(LINT.c) $< $(LTAIL))
]]></programlisting>
<para>
In this case, these are added to usr/src/uts/common/Makefile.rules.  If
the module being added is architecture-specific, they must instead be
added to the appropriate architecture-specific Makefile.rules file.  See
section 3.2.3 for more information about specific makefiles.
</para>
<para>
2) Create build directories in the appropriate places. If the module can
be built in a platform-independent way, this would be in the
&quot;instruction set architecture&quot; directory (i.e.: sparc, intel). If not,
these directories would be created for all appropriate &quot;implementation
architecture&quot;-dependent directories (i.e.: sun4u).  In this case, foofs
is common code, so two build directories are needed:
usr/src/uts/sparc/foofs and usr/src/uts/intel/foofs.
</para>
<para>
3) In each build directory, create a makefile. This can usually be
accomplished by copying a Makefile from a parallel directory and editing
the following lines (in addition to comments).
</para>
<programlisting><![CDATA[
MODULE		= foofs
OBJECTS		= $(FOOFS_OBJS:%=$(OBJS_DIR)/%)
LINTS		= $(FOOFS_OBJS:%.o=$(LINTS_DIR)/%.ln)
ROOTMODULE	= $(ROOT_FS_DIR)/$(MODULE)
]]></programlisting>
<para>
- replace directory part with the appropriate installation directory
name (see Makefile.uts)
</para>
<para>
If a custom version of modstubs.o is needed to check the undefineds for
this routine, the following lines need to appear in the makefile (after
the inclusion of Makefile.plat (i.e.: Makefile.sun4u)).
</para>
<programlisting><![CDATA[
MODSTUBS_DIR	 = $(OBJS_DIR)
$(MODSTUBS_O)	:= AS_CPPFLAGS += -DFOOFS_MODULE
]]></programlisting>
<para>
- replace &quot;-DFOOFS_MODULE&quot; with the appropriate flag for the modstubs.o
assembly.
</para>
<programlisting><![CDATA[
CLEANFILES	+= $(MODSTUBS_O)
]]></programlisting>
<para>
4) Edit the parent Makefile.mach (i.e.: Makefile.sparc, Makefile.intel)
to know about the new module:
</para>
<programlisting><![CDATA[
FS_KMODS	+= foofs
]]></programlisting>
<para>
Note that if your module only applies to a subset of the supported
architectures, you will only need to perform this step for the makefiles
that are used for those architectures.
</para>
<para>
Any additional questions can be easily answered by looking at the many
existing examples or by using the mailing lists and fora at
<ulink url='http://opensolaris.org/'>http://opensolaris.org/</ulink>.
</para>
</sect3>
<sect3 id='_3_3_3_2_Making_a_Kernel_Module' xreflabel='3.3.3.2 Making a Kernel Module Architecture-Independent'>
<title>3.3.3.2 Making a Kernel Module Architecture-Independent</title>
<para>
In some cases, a module which was specific to a particular
implementation architecture is adapted to be more general, often
because the hardware it supports has become available on more
platforms.  Once the module itself is able to be used across multiple
platforms, its build parameters should be updated to reflect this.
Its location in the source tree will also need to change.
</para>
<para>
0) Create the build directory under the appropriate &quot;instruction
set architecture&quot; build directory (i.e.: sparc/MODULE).
</para>
<para>
1) Move the makefile from the &quot;implementation architecture&quot; build
directory (i.e.: sun4u/MODULE) to the directory created above.
Edit this makefile to reflect the change of parent (trivial:
comments, paths and includes).
</para>
<para>
2) Edit the &quot;implementation architecture&quot; directory makefile
(i.e.: Makefile.sun4u) to *not* know about this module and
edit the &quot;instruction set architecture&quot; directory makefile
(i.e.: Makefile.sparc) to know about it.
</para>
<para>
3) Since the install locations may have changed (as well as the
set of systems on which these files are installed) you may also
need to adjust the package prototypes in usr/src/pkgdefs to
reflect that such changes.
</para>
</sect3>
<sect3 id='_3_3_3_3_Adding_New_Libraries' xreflabel='3.3.3.3 Adding New Libraries'>
<title>3.3.3.3 Adding New Libraries</title>
<para>
This section describes the overall layout and operation of the library
makefiles and provides detailed step-by-step instructions for adding new
libraries and enhancing existing library makefiles.  This is based very
closely on the file usr/src/lib/README.Makefiles and will be updated
from time to time to match its contents.
</para>
<para>
Your library should consist of a hierarchical collection of Makefiles:
</para>
<itemizedlist>
<listitem><para>lib/&lt;library&gt;/Makefile:</para>
<para>
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.
</para>
</listitem>
<listitem><para>lib/&lt;library&gt;/Makefile.com</para>
<para>
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.
</para>
</listitem>
<listitem><para>lib/&lt;library&gt;/&lt;isa&gt;/Makefile</para>
<para>
These are your library's ISA-specific Makefiles, one per ISA
(usually sparc and i386, and sometimes sparcv9 and ia64).
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.
</para>
<para>
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.
</para>
</listitem>
<listitem><para>lib/Makefile.lib:</para>
<para>
This contains the bulk of the macros for building shared objects.
</para>
</listitem>
<listitem><para>lib/Makefile.lib.64</para>
<para>
This contains macros for building 64-bit objects, and should
be included in Makefiles for 64-bit native ISAs.
</para>
</listitem>
<listitem><para>lib/Makefile.rootfs</para>
<para>
This contains macro overrides for libraries that install
into /lib (rather than /usr/lib).
</para>
</listitem>
<listitem><para>lib/Makefile.targ</para>
<para>
This contains rules for building shared objects.
</para>
</listitem>
</itemizedlist>
<para>
The remainder of this document discusses how to write each of your
Makefiles in detail, and provides examples from the libinetutil
library.
</para>
<para>
<emphasis role='bold'>The Library Top-level Makefile</emphasis>
</para>
<para>
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:
</para>
<itemizedlist>
<listitem><para>install_h</para>
<para>
Install all library header files into the proto area.  Can
be omitted if your library has no header files.
</para>
</listitem>
<listitem><para>check</para>
<para>
Check all library header files for hdrchk compliance.  Can
be omitted if your library has no header files.
</para>
</listitem>
<listitem><para>_msg</para>
<para>
Build and install a message catalog.  Can be omitted if your
library has no message catalog.
</para>
</listitem>
</itemizedlist>
<para>
Of course, other targets are (such as `cstyle') are fine as well, as
long as they are ISA-independent.
</para>
<para>
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
</para>
<programlisting><![CDATA[
install_h: $(ROOTHDRS)
]]></programlisting>
<programlisting><![CDATA[
check: $(CHECKHDRS)
]]></programlisting>
<para>
to bind the provided targets to the standard `install_h' and `check'
rules.
</para>
<para>
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.
</para>
<para>
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.
</para>
<para>
To build a message catalog from arbitrarily many message source files,
use the BUILDPO.msgfiles macro.
</para>
<programlisting><![CDATA[
include ../Makefile.lib
]]></programlisting>
<programlisting><![CDATA[
POFILE =	  libfoo.po
MSGFILES =	  $(OBJECTS:%.o=%.i)
]]></programlisting>
<programlisting><![CDATA[
# ...
]]></programlisting>
<programlisting><![CDATA[
$(POFILE): $(MSGFILES)
		$(BUILDPO.msgfiles)
]]></programlisting>
<programlisting><![CDATA[
_msg: $(MSGDOMAINPOFILE)
]]></programlisting>
<programlisting><![CDATA[
include $(SRC)/Makefile.msg.targ
]]></programlisting>
<para>
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.
</para>
<para>
It is usually preferable to run the source through the C preprocessor
prior to extracting messages.  To do this, use the &quot;.i&quot; suffix, as
shown in the above example.  If you need to skip the C preprocessor,
just use the native (.[ch]) suffix.
</para>
<para>
The only time you shouldn't use BUILDPO.msgfiles as the preferred
means of extracting messages in when you're extracting them from shell
scripts; in that case, you can use the BUILDPO.pofiles macro as
explained below.
</para>
<para>
To build a message catalog from other message catalogs, or from source
files that include shell scripts, use the BUILDPO.pofiles macro:
</para>
<programlisting><![CDATA[
include ../Makefile.lib
]]></programlisting>
<programlisting><![CDATA[
SUBDIRS =	  $(MACH)
]]></programlisting>
<programlisting><![CDATA[
POFILE =	  libfoo.po
POFILES =	  $(SUBDIRS:%=%/_%.po)
]]></programlisting>
<programlisting><![CDATA[
_msg :=	  TARGET = _msg
]]></programlisting>
<programlisting><![CDATA[
# ...
]]></programlisting>
<programlisting><![CDATA[
$(POFILE): $(POFILES)
		$(BUILDPO.pofiles)
]]></programlisting>
<programlisting><![CDATA[
_msg: $(MSGDOMAINPOFILE)
]]></programlisting>
<programlisting><![CDATA[
include $(SRC)/Makefile.msg.targ
]]></programlisting>
<para>
The Makefile above would work in conjunction with the following in its
subdirectories' Makefiles:
</para>
<programlisting><![CDATA[
POFILE =	  _thissubdir.po
MSGFILES =	  $(OBJECTS:%.o=%.i)
]]></programlisting>
<programlisting><![CDATA[
$(POFILE):	  $(MSGFILES)
		  $(BUILDPO.msgfiles)
]]></programlisting>
<programlisting><![CDATA[
_msg:		  $(POFILE)
]]></programlisting>
<programlisting><![CDATA[
include $(SRC)/Makefile.msg.targ
]]></programlisting>
<para>
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).
</para>
<para>
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.
</para>
<para>
As previously mentioned, you should defer all ISA-specific targets to
your ISA-specific Makefiles.  You can do this by:
</para>
<itemizedlist>
<listitem><para>1 Setting SUBDIRS to the list of directories to descend into:</para>
<programlisting><![CDATA[
SUBDIRS = $(MACH)
]]></programlisting>
<para>
Note that if your library is also built 64-bit, then you
should also specify
</para>
<programlisting><![CDATA[
$(BUILD64)SUBDIRS += $(MACH64)
]]></programlisting>
<para>
so that SUBDIRS contains $(MACH64) if and only if you're
compiling on a 64-bit ISA.
</para>
</listitem>
<listitem><para>2 Providing a common &quot;descend into SUBDIRS&quot; rule:</para>
<programlisting><![CDATA[
spec $(SUBDIRS): FRC
	@cd $@; pwd; $(MAKE) $(TARGET)
]]></programlisting>
<programlisting><![CDATA[
FRC:
]]></programlisting>
</listitem>
<listitem><para>3 Providing a collection of conditional assignments that set
TARGET appropriately:</para>
<programlisting><![CDATA[
all	:= TARGET= all
clean	:= TARGET= clean
clobber := TARGET= clobber
install := TARGET= install
lint	:= TARGET= lint
]]></programlisting>
<para>
The order doesn't matter, but alphabetical is preferable.
</para>
</listitem>
<listitem><para>4 Having the aforementioned targets depend on SUBDIRS:</para>
<programlisting><![CDATA[
all clean clobber install: spec .WAIT $(SUBDIRS)
]]></programlisting>
<programlisting><![CDATA[
lint: $(SUBDIRS)
]]></programlisting>
</listitem>
</itemizedlist>
<para>
A few notes are in order here:
</para>
<para>
* The `all' target must be listed first; the others
might as well be listed alphabetically.
</para>
<para>
* The `lint' target is listed separately because there
is nothing to lint in the spec subdirectory.
</para>
<para>
* The .WAIT between spec and $(SUBDIRS) is suboptimal
but currently required to make sure that two
different make invocations don't simultaneously
build the mapfiles.  It will likely be replaced with
a more sophisticated mechanism in the future.
</para>
<para>
As an example of how all of this goes together, here's libinetutil's
top-level library Makefile (copyright omitted):
</para>
<programlisting><![CDATA[
include ../Makefile.lib
]]></programlisting>
<programlisting><![CDATA[
HDRS =		libinetutil.h
HDRDIR =	common
SUBDIRS =	$(MACH)
$(BUILD64)SUBDIRS += $(MACH64)
]]></programlisting>
<programlisting><![CDATA[
all :=		TARGET = all
clean :=	TARGET = clean
clobber :=	TARGET = clobber
install :=	TARGET = install
lint :=		TARGET = lint
]]></programlisting>
<programlisting><![CDATA[
.KEEP_STATE:
]]></programlisting>
<programlisting><![CDATA[
all clean clobber install: spec .WAIT $(SUBDIRS)
]]></programlisting>
<programlisting><![CDATA[
lint:		$(SUBDIRS)
]]></programlisting>
<programlisting><![CDATA[
install_h:	$(ROOTHDRS)
]]></programlisting>
<programlisting><![CDATA[
check:		$(CHECKHDRS)
]]></programlisting>
<programlisting><![CDATA[
$(SUBDIRS) spec: FRC
	@cd $@; pwd; $(MAKE) $(TARGET)
]]></programlisting>
<programlisting><![CDATA[
FRC:
]]></programlisting>
<programlisting><![CDATA[
include ../Makefile.targ
]]></programlisting>
<para>
<emphasis role='bold'>The Common Makefile</emphasis>
</para>
<para>
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), $(TRANSMACH), and their
kin).
</para>
<para>
The common Makefile can be conceptually split up into four sections:
</para>
<itemizedlist>
<listitem><para>1 A copyright and comments section.</para>
<para>
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.
</para>
</listitem>
<listitem><para>2 A list of macros that must be defined prior to the inclusion of Makefile.lib.</para>
<para>
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).
</para>
</listitem>
<listitem><para>3 A list of macros that need not be defined prior to the
	   inclusion of Makefile.lib</para>
<para>
(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.
</para>
</listitem>
<listitem><para>4 A list of targets.</para>
</listitem>
</itemizedlist>
<para>
The first section is self-explanatory.  The second typically consists
of the following macros:
</para>
<para>
<code>LIBRARY</code>
</para>
<para>
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 <xref linkend='_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.
</para>
<para>
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'.
</para>
<para>
<code>VERS</code>
</para>
<para>
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.
</para>
<para>
<code>OBJECTS</code>
</para>
<para>
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.
</para>
<para>
The third section typically consists of the following macros:
</para>
<para>
<code>LIBS</code>
</para>
<para>
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.
</para>
<para>
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.
</para>
<para>
<code>ROOTLIBDIR</code> (if your library installs to a nonstandard directory)
</para>
<para>
Set to the directory your 32-bit shared objects will install into with
the standard $(ROOTxxx) macros.  Since this defaults to $(ROOT)/usr/lib
($(ROOT)/lib if you included Makefile.rootfs), you usually do not need
to set this.
</para>
<para>
<code>ROOTLIBDIR64</code> (if your library installs to a nonstandard directory)
</para>
<para>
Set to the directory your 64-bit shared objects will install into with
the standard $(ROOTxxx64) macros.  Since this defaults to
$(ROOT)/usr/lib/$(MACH64) ($(ROOT)/lib/$(MACH64) if you included
Makefile.rootfs), you usually do not need to set this.
</para>
<para>
<code>SRCDIR</code>
</para>
<para>
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 &lt;isa&gt; directory.
</para>
<para>
<code>SRCS</code> (if necessary)
</para>
<para>
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.
</para>
<para>
LINTLIB-specific SRCS (required if building a <xref linkend='_lint' /> library)
</para>
<para>
Set to a special &quot;lint stubs&quot; 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.
</para>
<para>
<code>LDLIBS</code>
</para>
<para>
Appended with the list of libraries and library directories needed to
build your library; minimally &quot;-lc&quot;.  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.
</para>
<para>
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).
</para>
<para>
<code>MAPDIR</code>
</para>
<para>
Set to the directory in which your library mapfile is built.  If your
library builds its mapfile from specfiles, set this to
`../spec/$(TRANSMACH)' (TRANSMACH is the same as MACH for 32-bit
targets, and the same as MACH64 for 64-bit targets).
</para>
<para>
<code>MAPFILE</code> (required if your mapfile is under source control)
</para>
<para>
Set to the path to your library mapfile.  If your library builds its
mapfile from specfiles, this need not be set.  If you set this, you must
also set DYNFLAGS to include `-M $(MAPFILE)' and set DYNLIB to depend on
MAPFILE.
</para>
<para>
<code>SPECMAPFILE</code> (required if your mapfile is generated from specfiles)
</para>
<para>
Set to the path to your generated mapfile (usually `$(MAPDIR)/mapfile').
If your library mapfile is under source control, you need not set this.
Setting this triggers a number of features in higher-level Makefiles:
</para>
<para>
* Your shared library will automatically be linked with `-M $(SPECMAPFILE)'.
</para>
<para>
* A `make clobber' will remove $(SPECMAPFILE).
</para>
<para>
* Changes to $(SPECMAPFILE) will cause your shared library to be rebuilt.
</para>
<para>
* An attempt to build $(SPECMAPFILE) will
automatically cause a `make mapfile' to be done in
MAPDIR.
</para>
<para>
<code>CPPFLAGS</code> (if necessary)
</para>
<para>
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.
</para>
<para>
<code>CFLAGS</code>
</para>
<para>
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.
</para>
<para>
<code>CFLAGS64</code> (if necessary)
</para>
<para>
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.
</para>
<para>
<code>COPTFLAG</code> (if necessary)
</para>
<para>
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).
</para>
<para>
<code>COPTFLAG64</code> (if necessary)
</para>
<para>
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).
</para>
<para>
<code>LINTFLAGS</code> (if necessary)
</para>
<para>
Appended with any flags that need to be passed to lint(1) when linting
32-bit code.  You should only modify LINTFLAGS in rare instances where
your code cannot (or should not) be fixed.
</para>
<para>
<code>LINTFLAGS64</code> (if necessary)
</para>
<para>
Appended with any flags that need to be passed to lint(1) when linting
64-bit code.  You should only modify LINTFLAGS64 in rare instances where
your code cannot (or should not) be fixed.
</para>
<para>
Of course, you may use other macros as necessary.
</para>
<para>
The fourth section typically consists of the following targets:
</para>
<itemizedlist>
<listitem><para>all</para>
<para>
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
</para>
<programlisting><![CDATA[
all: $(LIBS)
]]></programlisting>
<para>
though it should be listed as an empty target if LIBS is set by your
ISA-specific Makefiles (see above).
</para>
</listitem>
<listitem><para>lint</para>
<para>
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
</para>
<programlisting><![CDATA[
lint: lintcheck
]]></programlisting>
</listitem>
</itemizedlist>
<para>
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.
</para>
<para>
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:
</para>
<programlisting><![CDATA[
LIBRARY =	libinetutil.a
VERS =		.1
OBJECTS =	octet.o inetutil4.o ifspec.o
]]></programlisting>
<programlisting><![CDATA[
include ../../Makefile.lib
include ../../Makefile.rootfs
]]></programlisting>
<programlisting><![CDATA[
LIBS =		$(DYNLIB) $(LINTLIB)
SRCS =		$(COMDIR)/octet.c $(SRCDIR)/inetutil4.c \
		$(SRCDIR)/ifspec.c
$(LINTLIB):=	SRCS = $(SRCDIR)/$(LINTSRC)
LDLIBS +=	-lsocket -lc
]]></programlisting>
<programlisting><![CDATA[
SRCDIR =	../common
COMDIR =	$(SRC)/common/net/dhcp
MAPDIR =	../spec/$(TRANSMACH)
SPECMAPFILE =	$(MAPDIR)/mapfile
]]></programlisting>
<programlisting><![CDATA[
CFLAGS +=	$(CCVERBOSE)
CPPFLAGS +=	-I$(SRCDIR)
]]></programlisting>
<programlisting><![CDATA[
.KEEP_STATE:
]]></programlisting>
<programlisting><![CDATA[
all: $(LIBS)
]]></programlisting>
<programlisting><![CDATA[
lint: lintcheck
]]></programlisting>
<programlisting><![CDATA[
pics/%.o: $(COMDIR)/%.c
	$(COMPILE.c) -o $@ $<
	$(POST_PROCESS_O)
]]></programlisting>
<programlisting><![CDATA[
include ../../Makefile.targ
]]></programlisting>
<para>
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.
</para>
<para>
<emphasis role='bold'>The ISA-Specific Makefiles</emphasis>
</para>
<para>
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 rule you will need to put here is `install', which
has different dependencies for 32-bit and 64-bit libraries.  For
instance, here are the ISA-specific Makefiles for libinetutil:
</para>
<programlisting><![CDATA[
sparc/Makefile:
]]></programlisting>
<programlisting><![CDATA[
include ../Makefile.com
]]></programlisting>
<programlisting><![CDATA[
install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
]]></programlisting>
<programlisting><![CDATA[
sparcv9/Makefile:
]]></programlisting>
<programlisting><![CDATA[
include ../Makefile.com
include ../../Makefile.lib.64
]]></programlisting>
<programlisting><![CDATA[
install: all $(ROOTLIBS64) $(ROOTLINKS64)
]]></programlisting>
<programlisting><![CDATA[
i386/Makefile:
]]></programlisting>
<programlisting><![CDATA[
include ../Makefile.com
]]></programlisting>
<programlisting><![CDATA[
install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
]]></programlisting>
<para>
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
Makefile also includes 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.
</para>
<para>
<emphasis role='bold'>CTF Data in Libraries</emphasis>
</para>
<para>
By default, all position-independent objects are built with <xref linkend='_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.
</para>
<para>
Filter libraries that have no source files will need to explicitly
disable CTF by setting CTFMERGE_LIB to &quot;:&quot;; see libw/Makefile.com for an
example.
</para>
<para>
<emphasis role='bold'>More Information</emphasis>
</para>
<para>
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:
</para>
<itemizedlist>
<listitem><para>lib/libdhcputil</para>
<para>
Example of a simple 32-bit only library.
</para>
</listitem>
<listitem><para>lib/libdhcpagent</para>
<para>
Example of a simple 32-bit only library that obtains its
sources from multiple directories.
</para>
</listitem>
<listitem><para>lib/ncad_addr</para>
<para>
Example of a simple loadable module.
</para>
</listitem>
<listitem><para>lib/libipmp</para>
<para>
Example of a simple library that builds a message catalog.
</para>
</listitem>
<listitem><para>lib/libdhcpsvc</para>
<para>
Example of a Makefile hierarchy for a library and a
collection of related pluggable modules.
</para>
</listitem>
<listitem><para>lib/lvm</para>
<para>
Example of a Makefile hierarchy for a collection of related
libraries and pluggable modules.
</para>
<para>
Also an example of a Makefile hierarchy that supports the
_dc target for domain and category specific messages.
</para>
</listitem>
</itemizedlist>
</sect3>
</sect2>
</sect1>
<sect1 id='_3_4_Keeping_Your_Workspace_in_' xreflabel='3.4 Keeping Your Workspace in Sync'>
<title>3.4 Keeping Your Workspace in Sync</title>
<para>
Over time, other developers will put back their work into the main
<xref linkend='_gate' />, and your <xref linkend='_workspace' /> will become out of date with respect to
these changes.  By keeping your workspace in sync as much as possible,
you will save time in two ways.
</para>
<para>
First, you will have less merging to do when you are ready to put
back, which will reduce or eliminate conflict resolution and simplify
testing.
</para>
<para>
Second, the risk of missing semantic changes in other parts of the
code will be reduced.  If an interface you use is changed, you want to
know about it as soon as possible so you will not continue to
implement your features on the basis of a deprecated or nonexistent
interface.  This will save much work and grief; you do not want to be
preparing to put back and only then discover that your code no longer
compiles because a crucial interface has been removed.
</para>
<para>
Keeping your workspace in sync is not difficult, and should be done as
often as practical.  However, there is one drawback, which may limit the
frequency at which you choose to sync your workspace.  Pulling in
changes unrelated to your work exposes you to the risk of breakage
caused by those changes.  If an unrelated change breaks your workspace,
you could waste time trying to identify the cause of breakage by
assuming it is in your changes rather than someone else's.  Also, it is
possible that an unrelated change will render your workspace unable to
boot or perform any useful work at all, which would make it impossible
for you to test your changes until the original bugs are fixed.  For
these reasons, you will want to carefully consider your synchronization
process to minimize risk while keeping as up to date as possible.
Merging with recent, tested build snapshots on a biweekly basis rather
than merging daily with the gate is often a good compromise.
</para>
<para>
Until the main gate is accessible to all developers, the Sun engineer
who is carrying the fix will have to do any final merges with the
internal gate.  If you have submitted a change that causes this merge to
get too hairy, you should be ready to answer questions about the change
and provide assistance during the merge.  In extreme cases, the Sun
engineer may ask that you do the merge externally (i.e., after the next
snapshot has been released) and resubmit your source patch.  This
reduces the chance that your change will break other changes being made
to the same area of code.
</para>
</sect1>
</chapter>
<chapter id='_4_Building_OpenSolaris' xreflabel='Building OpenSolaris'>
<title>Building OpenSolaris</title>
<para>
This chapter discusses two commonly-used ways to build OpenSolaris,
nightly(1)/bldenv(1) and make(1)/dmake(1).  The former provides a high
degree of automation and fine-grained control over each step in a full
or incremental build of the entire <xref linkend='_workspace' />.  Using make(1) or
dmake(1) directly provides much less automation but allows you to build
individual components more quickly.  Section 4.1 is common to both
methods; 4.2 describes nightly(1) and bldenv(1), and 4.3 describes the
use of low-level make(1) targets.  Finally, section 4.4 describes what
results from a full build and how these intermediate products can be
used.  The instructions in this chapter apply to ON and similar
consolidations, including SFW and Network Storage (NWS).  Other
consolidations may have substantially different build procedures, which
should be incorporated here.
</para>
<sect1 id='_4_1_Environment_Variables' xreflabel='4.1 Environment Variables'>
<title>4.1 Environment Variables</title>
<para>
This section describes a few of the environment variables that affect
all ON builds, regardless of the build method.  See <xref linkend='_4_2_Using_nightly_and_bldenv' /> for information on environment variables and files that
affect nightly(1) and bldenv(1).
</para>
<itemizedlist>
<listitem><para>CODEMGR_WS</para>
<para>
This variable is normally used by TeamWare (Sun's internal source code
management system).  Although a <xref linkend='_workspace' /> that does not use TeamWare
does not need this variable, you will occasionally see it referenced
when setting other variables.  It should be set to the root of your
workspace. It is highly recommended to use bldenv(1) to set this
variable as it will also set several other important variables at the
same time.  See section 1.3.3.2 for more information on bldenv(1).
</para>
</listitem>
<listitem><para>SRC</para>
<para>
This variable must be set to the root of the <xref linkend='_ON' /> source tree within
your workspace; that is, ${CODEMGR_WS}/usr/src.  It is used by numerous
makefiles and by nightly(1).  This is only needed if you are building.
bldenv(1) will set this variable correctly for you.
</para>
</listitem>
<listitem><para>MACH</para>
<para>
The instruction set architecture of the machine as given by uname -p,
e.g.  sparc, i386.  This is only needed if you are building.  bldenv(1)
will set this variable correctly for you; it should not be changed.  If
you prefer, you can also set this variable in your dot-files, and use it
in defining PATH and any other variables you wish.  If you do set it
manually, be sure not to set it to anything other than the output of
'/usr/bin/uname -p' on the specific machine you are using:
</para>
<para>
Good:
</para>
<programlisting><![CDATA[
MACH=`/usr/bin/uname -p`
]]></programlisting>
<para>
Bad:
</para>
<programlisting><![CDATA[
MACH=sparc
]]></programlisting>
</listitem>
<listitem><para>ROOT</para>
<para>
Root of the proto area for the build.  The makefiles direct the
installation of header files and libraries to this area and direct
references to these files by builds of commands and other targets.  It
should be expressed in terms of $CODEMGR_WS.  See section 4.4.1 for more
information on the proto area.  If bldenv(1) is used, this variable will
be set to ${CODEMGR_WS}/proto/root_${MACH}.
</para>
</listitem>
<listitem><para>PARENT_ROOT</para>
<para>
PARENT_ROOT is the proto area of the parent workspace.  This can be used
to perform partial builds in children by referencing already-installed
files from the parent.  Setting this variable is optional.
</para>
</listitem>
<listitem><para>MAKEFLAGS</para>
<para>
This variable has nothing to do with OpenSolaris; however, in order for
the build to work properly, make(1) must have access to the contents of
the environment variables described in this section.  Therefore the
MAKEFLAGS environment variable should be set and contain at least &quot;e&quot;.
bldenv(1) will set this variable for you; it is only needed if you are
building.  It is possible to dispense with this by using 'make -e' if
you are building using make(1) or dmake(1) directly, but use of
MAKEFLAGS is strongly recommended.
</para>
</listitem>
<listitem><para>SPRO_ROOT</para>
<para>
By default, it is expected that a working compiler installation exists
in <code>/ws/onnv-tools/SUNWspro/SOS8</code> (this path is used internally at
Sun).  This variable can be set to override that location; since you
probably do not have compilers installed in the default location, you
will need to set this, normally to <code>/opt/SUNWspro</code>.  You can see how
this works by looking at <code>usr/src/Makefile.master</code>; if you need to
override the default, however, you should do so via the environment
variable.  Note that <code>opensolaris.sh</code> has this variable already set to
this value.
</para>
</listitem>
<listitem><para>SPRO_VROOT</para>
<para>
The 'V' stands for version.  At Sun, multiple versions of the compilers
are installed under <code>${SPRO_ROOT}</code> to support building older sources.
The compiler itself is expected to be in <code>${SPRO_VROOT}/bin/cc</code>, so you
will most likely need to set this variable to <code>/opt/SUNWspro</code>.  Note
that <code>opensolaris.sh</code> has this variable already set to this value.
</para>
</listitem>
<listitem><para>GNU_ROOT</para>
<para>
The GNU C compiler is used by default to build the 64-bit kernel for
amd64 systems.  By default, if building on an x86 host, the build system
assumes there is a working amd64 gcc installation in <code>/usr/sfw</code>.
Although it is not recommended, you can use a different gcc by setting
this variable to the gcc install root.  See <code>usr/src/Makefile.master</code>
for more information.
</para>
</listitem>
<listitem><para>__GNUC, __GNUC64</para>
<para>
These variables control the use of gcc.  __GNUC controls the use of gcc
to build i386 and sparc (32-bit) binaries, while __GNUC64 controls the
use of gcc to build amd64 and sparcv9 (64-bit) binaries.  Setting these
variables to the empty value <emphasis>enables</emphasis> the use of gcc to build the
corresponding binaries.  Setting them to <code>'#'</code> enables Studio as the
primary compiler.  The default settings use Studio, with gcc invoked in
parallel as a 'shadow' compiler (to ensure that code remains warning and
error clean).
</para>
</listitem>
<listitem><para>CLOSED_IS_PRESENT</para>
<para>
This variable tells the ON makefiles whether to look for the closed
source tree.  Normally this is set automatically by nightly(1) and
bldenv(1).  See <xref linkend='_3_2_8_Source_Files_not_Include' /> for more details.
</para>
</listitem>
</itemizedlist>
</sect1>
<sect1 id='_4_2_Using_nightly_and_bldenv' xreflabel='4.2 Using nightly and bldenv'>
<title>4.2 Using nightly and bldenv</title>
<para>
There are many steps in building any consolidation; ON's build process
entails creation of the proto area, compiling and linking binaries,
generating <xref linkend='_lint' /> libraries and linting the sources, building packages
and BFU archives, and verifying headers, packaging, and proto area
changes.  Fortunately, a single utility called nightly(1) automates all
these steps and more.  It is controlled by a single environment file,
the format of which is shared with bldenv(1).  This section describes
what nightly(1) does for you, what it does not, and how to use it.
</para>
<para>
nightly(1) can automate most of the build and source-level checking
processes.  It builds the source, generates BFU archives,
generates packages, runs lint(1), does syntactic checks, and creates and
checks the proto area.  It does not perform any runtime tests such as
unit, functional, or regression tests; you must perform these
separately, ideally on dedicated systems.
</para>
<para>
Despite its name, nightly(1) can be run manually or by cron(1M) at any
time; you must run it yourself or arrange to have it run once for each
build you want to do.  nightly(1) does not start any daemons or
repetitive background activities: it does what you tell it to do, once,
and then stops.
</para>
<para>
After each run, nightly(1) will leave a detailed log of the commands it
ran and their output; this is normally located in
$CODEMGR_WS/log/log.MMDD/nightly.log, where MMDD is the date, but can be
changed as desired.  If such a log already exists, nightly(1) will
rename it for you.
</para>
<para>
In addition to the detailed log, you (actually, the address specified in
the MAILTO environment variable) will also receive an abbreviated
completion report when nightly(1) finishes.  This report will tell you
about any errors or warnings that were detected and how long each step
took to complete.  It will list errors and warnings as differences from
a previous build (if there is one); this allows you to see what effect
your changes, if any, has had.  It also means that if you attempt a
build and it fails, and you then correct the problems and rebuild, you
will see information like:
</para>
<programlisting><![CDATA[
< dmake: Warning: Command failed for target `yppasswd'
< dmake: Warning: Command failed for target `zcons'
< dmake: Warning: Command failed for target `zcons.o'
< dmake: Warning: Command failed for target `zdump'
]]></programlisting>
<para>
Note the '&lt;' - this means this output was for the previous build.  If
the output is prefaced with '&gt;', it is associated with the most recent
build.  In this way you will be able to see whether you have corrected
all problems or introduced new ones.
</para>
<sect2 id='_4_2_1_Options' xreflabel='4.2.1 Options'>
<title>4.2.1 Options</title>
<para>
nightly(1) accepts a wide variety of options and flags that control its
behavior.  Many of these options control whether nightly(1) performs
each of the many steps it can automate for you.  These options may be
specified in the environment file or on the command line; options
specified on the command line take precedence.  See nightly(1) for the
complete list of currently accepted options and their effect on build
behavior.
</para>
</sect2>
<sect2 id='_4_2_2_Using_Environment_Files' xreflabel='4.2.2 Using Environment Files'>
<title>4.2.2 Using Environment Files</title>
<para>
nightly(1) reads a file containing a set of environment definitions for
the build.  This file is a simple shell script, but normally just
contains variable assignments.  All variables described in section <xref linkend='_2_5_Environment_Variables' /> and below in <xref linkend='_4_2_3_Variables' /> can be set in the
nightly(1) environment file; however, common practice is to use the
developer, or gatekeeper, or opensolaris environment files, as
appropriate, and modify one of them to meet your needs.  The name of the
resulting environment file is then passed as the final argument to
nightly(1).  The sample environment files are available in
usr/src/tools/env.
</para>
</sect2>
<sect2 id='_4_2_3_Variables' xreflabel='4.2.3 Variables'>
<title>4.2.3 Variables</title>
<para>
Although any environment variables can be set in a nightly(1)
environment file, this section lists those which are used directly by
nightly(1) to control its operation and which are commonly changed.  The
complete list of variables and options is found in nightly(1).
</para>
<itemizedlist>
<listitem><para>NIGHTLY_OPTIONS</para>
</listitem>
<listitem><para>CODEMGR_WS</para>
</listitem>
<listitem><para>CLONE_WS</para>
</listitem>
<listitem><para>STAFFER</para>
</listitem>
<listitem><para>MAILTO</para>
</listitem>
<listitem><para>MAKEFLAGS</para>
</listitem>
</itemizedlist>
</sect2>
</sect1>
<sect1 id='_4_3_Using_Make' xreflabel='4.3 Using Make'>
<title>4.3 Using Make</title>
<para>
Although nightly(1) can automate the entire build process, including
source-level checks and generation of additional build products, it is
not always necessary.  If you are working in a single subdirectory and
wish only to build or lint that subdirectory, it is usually possible to
do this directly without relying on nightly(1).  This is especially true
for the kernel, and if you have not made changes to any other part of
your <xref linkend='_workspace' />, it is advantageous to build and install only the
kernel during intermediate testing.  See section 5.2 for more
information on installing test kernels.
</para>
<para>
You will need to set up your environment properly before using make(1)
directly on any part of your workspace.  You can use bldenv(1) to
accomplish this; see <xref linkend='_3_3_1_Getting_Ready_to_Work' /> and <xref linkend='_4_2_Using_nightly_and_bldenv' /> for more information on this command.
</para>
<para>
Because the makefiles use numerous make(1) features, some versions of
make will not work properly.  Specifically, you cannot use BSD make or
GNU make to build your workspace.  The dmake(1) included in the
OpenSolaris tools distribution will work properly, as will the make(1)
shipped in /usr/ccs/bin with Solaris and some other distributions.  If
your version of dmake is older (or, in some cases, newer), it may fail
in unexpected ways.  While both dmake(1) and make(1) can be used,
dmake(1) is normally recommended because it can run multiple tasks in
parallel or even distribute them to other build servers.  This can
improve build times greatly.
</para>
<para>
The entire uts directory allows you to run make commands in a particular
build subdirectory (see sections 3.3.2 though 3.3.6) to complete only
the build steps you request on only that particular subdirectory.  Most
of the cmd and parts of the lib subdirectories also allow this; however,
some makefiles have not been properly configured to regenerate all
dependencies.  All subdirectories which use the modern object file
layout (see section 3.3.2) should generally work without any problems.
</para>
<para>
There are several valid targets which are common to all directories;
to find out which ones apply to your directory of interest and which
additional targets may be available, you will need to read that
directory's makefile.
</para>
<para>
Here are the generic targets:
</para>
<para>
<emphasis role='bold'>all</emphasis>
</para>
<para>
Build all derived objects in the object directory.
</para>
<para>
<emphasis role='bold'>install</emphasis>
</para>
<para>
Install derived objects into the proto area defined by ${ROOT}.
</para>
<para>
<emphasis role='bold'>install_h</emphasis>
</para>
<para>
Install header files into the proto area defined by ${ROOT}.
</para>
<para>
<emphasis role='bold'>clean</emphasis>
</para>
<para>
Remove intermediate object files, but do not remove &quot;complete&quot;
derived files such as executable programs, libraries, or kernel modules.
</para>
<para>
<emphasis role='bold'>clobber</emphasis>
</para>
<para>
Remove all derived files.
</para>
<para>
<emphasis role='bold'>check</emphasis>
</para>
<para>
Perform source-specific checks such as source and header style conformance.
</para>
<para>
<emphasis role='bold'>lint</emphasis>
</para>
<para>
Generate lint libraries and run all appropriate lint passes
against all code which would be used to build objects in the
current directory.
</para>
</sect1>
<sect1 id='_4_4_Build_Products' xreflabel='4.4 Build Products'>
<title>4.4 Build Products</title>
<para>
A fully-built source tree is not very useful by itself; the binaries,
scripts, and configuration files that make up the system are still
scattered throughout the tree.  The makefiles provide the install
targets to produce a proto area and package tree, and other utilities
can be used to build additional conglomerations of build products in
preparation for integration into a full Wad Of Stuff build or
installation on one or more systems for testing and further development.
The nightly(1) program can automate the generation of each build
product.  Alternately, the Install program (see section 5.2) can be used
to construct a kernel installation archive directly from a fully-built
usr/src/uts.
</para>
<para>
Section 4.4.1 describes the proto area, the most basic collection of
built objects and the first to be generated by the build system.
Section 4.4.2 describes BFU archives, which are used to upgrade a system
with a full OpenSolaris-based distribution installation to the latest
<xref linkend='_ON' /> bits.  Section 4.4.3 describes the construction of the
package tree for ON deliverables.
</para>
<sect2 id='_4_4_1_Proto_Area' xreflabel='4.4.1 Proto Area'>
<title>4.4.1 Proto Area</title>
<para>
The install target causes binaries and headers to be installed into a
hierarchy called the prototype or proto area.  Since everything in the
proto area is installed with its usual paths relative to the proto area
root, a complete proto area looks like a full system install of the ON
bits.  However, a proto area can be constructed by arbitrary users, so
the ownership and permissions of its contents will not match those in a
live system.  The root of the proto area is defined by the environment
variable ROOT, which defaults to /proto.  If you use bldenv(1) to set up
your environment, ROOT defaults instead to
${CODEMGR_WS}/proto/root_${MACH}.
</para>
<para>
The proto area is useful if you need to copy specific files from the
build into your live system.  It is also compared with the parent's
proto area and the packaging information by tools like protocmp and
checkproto to verify that only the expected shipped files have changed
as a result of your source changes.
</para>
<para>
protocmp does not include a man page.  Its invocation is as
follows:
</para>
<programlisting><![CDATA[
protocmp [-gupGUPlmsLv] [-e <exception-list> ...] -d <protolist|pkg dir>
    [-d <protolist|pkg dir> ...] [<protolist|pkg dir>...]|<root>]
]]></programlisting>
<para>
Where:
</para>
<programlisting><![CDATA[
-g       : don't compare group
-u       : don't compare owner
-p       : don't compare permissions
-G       : set group
-U       : set owner
-P       : set permissions
-l       : don't compare link counts
-m       : don't compare major/minor numbers
-s       : don't compare symlink values
-d <protolist|pkg dir>:
           proto list or packaging to check
-e <file>: exceptions file
-L       : list filtered exceptions
-v       : verbose output
]]></programlisting>
<para>
If any of the -[GUP] flags are given, then the final argument must be
the proto root directory itself on which to set permissions according
to the packaging data specified via -d options.
</para>
<para>
A protolist is a text file with information about each file in a proto
area, one per line.  The information includes: file type (plain,
directory, link, etc.), full path, link target, permissions, owner uid,
owner gid, i-number, number of links, and major and minor numbers.  You
can generate protolists with the protolist command, which does not
include a man page.  Its invocation is as follows:
</para>
<programlisting><![CDATA[
$ protolist <protoroot>
]]></programlisting>
<para>
where protoroot is the proto area root (normally $ROOT).  Redirecting
its output yields a file suitable for passing to protocmp via the -d
option or as the final argument.
</para>
<para>
The last argument to protocmp always specifies either a protolist or
proto area root to be checked or compared.  If a -d option is given with
a protolist file as its argument, the local proto area will be compared
with the specified reference protolist and lists of files which are
added, missing, or changed in the local proto area will be provided.  If
a -d option is given with a package definitions directory as its
argument, the local proto area will be checked against the definitions
provided by the package descriptions and information about discrepancies
will be provided.
</para>
<para>
The exceptions file (-e) specifies which files in the proto area are not
to be checked.  This is important, since otherwise protocmp expects that
any files installed in the proto area which are not part of any package
represent a package definition error or spurious file in the proto area.
</para>
<para>
This comparison is automatically run as part of your nightly(1) build
so long as the -N option is not included in your options.  See
nightly(1) and section 4.2 for more information on automating proto
comparison as part of your automatic build.
</para>
<para>
As a shortcut to using protolist and protocmp, you can use the
'checkproto' command found in the SUNWonbld package.  This utility does
not include a man page, but has a simple invocation syntax:
</para>
<programlisting><![CDATA[
$ checkproto [-X] <workspace>
]]></programlisting>
<para>
The exception files and packaging information will be selected for you,
and the necessary protolists will be generated automatically.  Use of
the -X option, as for nightly(1), will instruct checkproto to check the
contents of the realmode subtree, which normally is not built.
</para>
<para>
You can find the sources for protolist, protocmp, and checkproto in
usr/src/tools.  The resulting binaries are included in the SUNWonbld
package.
</para>
</sect2>
<sect2 id='_4_4_2_BFU_Archives' xreflabel='4.4.2 BFU Archives'>
<title>4.4.2 BFU Archives</title>
<para>
BFU archives are cpio-format archives (see cpio(1) and archives(4)) used
by bfu(1) to install <xref linkend='_ON' /> binaries into a live system.  The actual
process of using bfu(1) is described in greater detail in the man page
and in section 5.3.
</para>
<para>
BFU archives are built by mkbfu, which does not include a man page.  Its
invocation is as follows:
</para>
<programlisting><![CDATA[
$ mkbfu [-f filter] [-z] proto-dir archive-dir
]]></programlisting>
<para>
The -f option allows you to specify a filter program which will be
applied to the cpio archives.  This is normally used to set the proper
permissions on files in the archives, as discussed in greater detail
below.
</para>
<para>
The -z option causes the cpio archives to be compressed with gzip(1).
If both -f and -z are given, the compression will occur after the
filter specified by -f is applied.
</para>
<para>
proto-dir is the proto area root described in section 4.4.1 and
normally given by the ROOT environment variable.
</para>
<para>
archive-dir is the directory in which the archives should be created.
If it does not exist it will be created for you.
</para>
<para>
However, 'mkbfu' is rarely used.  Instead, 'makebfu' offers a much
simpler alternative.  It has no man page, but the invocation is simple:
</para>
<programlisting><![CDATA[
$ makebfu [filename]
]]></programlisting>
<para>
If an argument is given, it refers to an environment file suitable for
nightly(1) or bldenv(1).  Otherwise, 'makebfu' assumes that bldenv(1) or
equivalent has already been used to set up the environment
appropriately.
</para>
<para>
'makebfu' is a wrapper around 'mkbfu' that feeds package and environment
information to 'cpiotranslate' to construct an appropriate filter for
the archives.  This filter's purpose is to set the correct mode, owner,
and group on files in the archives.  This is needed to allow builds run
with ordinary user privileges to produce BFU archives with the correct
metadata.  Without root privileges, there is no way for the build user to set
the permissions and ownership of files in the proto area, and without
filtering, the cpio archives used by BFU would be owned by the build
user and have potentially incorrect permissions.  'cpiotranslate' uses
package definitions to correct both.  See
usr/src/tools/protocmp/cpiotranslate.c to learn how this works.
</para>
<para>
Each archive contains one subset of the proto area.  Platform-specific
directories are broken out into separate archives (this can simplify
installing on some systems since only the necessary platform-specific
files need to be installed), as are /, /lib, /sbin, and so on.  The
exact details of the files included in the archives can be found only
by reading the latest version of mkbfu.
</para>
<para>
BFU archives are built automatically as part of your nightly(1) build if
-a is included in your options.  Also, if -z is included in your
options, it will be passed through to mkbfu.  See nightly(1) and section
4.2 for more information on automating BFU archive construction as part
of your automatic build.
</para>
<para>
mkbfu and makebfu are Korn shell scripts included in the SUNWonbld
package.  Their sources are located in usr/src/tools/scripts.
</para>
<para>
cpiotranslate is a C program included in the SUNWonbld package.  Its
source is located in usr/src/tools/protocmp/cpiotranslate.c.
</para>
</sect2>
<sect2 id='_4_4_3_Packages' xreflabel='4.4.3 Packages'>
<title>4.4.3 Packages</title>
<para>
Ordinary SVR4 packages can be built from the files installed into the
proto area (see section 4.4.1).  This is done automatically by the main
makefile's all and pkg_all targets (see usr/src/Makefile) as part of a
successful build.  The definitions located in usr/src/pkgdefs are used
to build all packages; each subdirectory contains the package
definitions and a makefile fragment used to build that package.  Built
packages are rooted in usr/src/packages and are in the standard format.
See pkgmk(1) for more information on how packages are built.
</para>
<para>
Packages are built automatically as part of your nightly(1) build if
-p is included in your options.  See nightly(1) and section 4.2 for
more information on automating package construction as part of your
automatic build.
</para>
<para>
SVR4 packages are similar to those delivered by other operating systems;
they contain the files to be installed, metadata about those files,
scripts to perform tasks during installation and removal, and
information about the package itself.  Although the exact data formats
used may differ, all the general concepts are the same.  However,
packages delivered by OpenSolaris tend to be coarser-grained than those
that make up most GNU/Linux distributions.  For example, SUNWcsu
contains a large portion of the core system commands and kernel
components; a typical GNU/Linux distribution might deliver equivalent
functionality in ten or more different packages.  Most OpenSolaris
packages are separated based on the files' location, whether in the root
filesystem or the /usr subdirectory.  This is primarily to accommodate
installation for diskless clients, which may have a shared /usr located
on a file server.  Distributions other than Solaris may package system
components differently.
</para>
<para>
pkgmk(1) is part of the SUNWpkgcmdsu package.  Its sources are not part
of the <xref linkend='_ON' /> <xref linkend='_consolidation' />.
</para>
</sect2>
</sect1>
</chapter>
<chapter id='_5_Installing_and_Testing_ON' xreflabel='Installing and Testing ON'>
<title>Installing and Testing ON</title>
<para>
This chapter describes several flexible methods for installing your ON
bits.  Please note that because ON does not include all the programs
needed for a working system, you must have an existing full install
(typically Solaris or Solaris Express) before you can perform these
procedures successfully.
</para>
<para>
Additionally, some of the common testing procedures for the kernel and
core userland components are covered.  Although these tests are intended
to cover as much of the system as possible, and to be flexible enough
that additional tests can be written and added to the infrastructure,
most testing is still done by project-specific test suites.  When
fixing bugs or adding new features, you are well-advised to contact the
owner(s) of the code you are changing to obtain any existing tests.  You
should also contribute new tests that detect the bug you are fixing or
verify the functionality of your new features.
</para>
<sect1 id='_5_1_Installation_Overview' xreflabel='5.1 Installation Overview'>
<title>5.1 Installation Overview</title>
<para>
Other than manually copying specific files from your proto area into
your live system, there are three main ways to install your bits on your
system.  Which one you use will depend on what you have changed: if you
have changed only the kernel, see section 5.1.1 to learn about Install.
If you have changed the kernel and userland components of <xref linkend='_ON' /> and
your changes must be applied together, you must either hand-copy your
userland changes before using Install, or use BFU; see section 5.3 for
information on BFU.
</para>
<para>
To accommodate fully functional builds even though some sources are
missing, a set of closed binaries is available, and the build system has
been modified to make use of them.  You will need to use the
closed-bins.&lt;platform&gt;.tar.gz components along with your build products
to build either Install or BFU archives that work.  Please see <xref linkend='_4_Building_OpenSolaris' /> and the latest Release Notes for more information
on building and the use of the closed binaries.
</para>
<para>
Each of these installation methods is progressively more complex and
time-consuming, but upgrades a larger part of your system.  Because most
ON developers only modify the ON sources and are not responsible for
integration testing, BFU is by far the most popular method for
performing system upgrades.  Developers working heavily on the kernel
will often make use of Install during development and use BFU to keep
current between testing phases.
</para>
<para>
Each method is described briefly in this section.  Detailed
instructions are provided in sections 5.2 and 5.3.
</para>
<sect2 id='_5_1_1_Cap_Eye_Install' xreflabel='5.1.1 Cap-Eye-Install'>
<title>5.1.1 Cap-Eye-Install</title>
<para>
Install (pronounced cap-eye-install) is used to update only the kernel
and its associated modules on a specific system.  It will place the
new kernel in a nonstandard location and install only the
platform-specific modules for your particular host.  This allows you
to test your changes without removing the normal kernel; if your new
kernel does not boot or crashes, this makes recovery much easier.
</para>
</sect2>
<sect2 id='_5_1_2_BFU' xreflabel='5.1.2 BFU'>
<title>5.1.2 BFU</title>
<para>
BFU is used to update all <xref linkend='_ON' /> bits, both kernel and userland.  It
is capable of updating some configuration files and is aware of the
impact of the changes that have been made to ON.  BFU is more thorough
than Install, and takes longer.  Also, unlike Install, the new kernel
will be installed over the existing one, so if it does not work properly
you may have to boot from alternate media to recover.
</para>
</sect2>
<sect2 id='_5_1_3_Flag_Days_and_Other_Haza' xreflabel='5.1.3 Flag Days and Other Hazards'>
<title>5.1.3 Flag Days and Other Hazards</title>
<para>
In some cases, you will need to install newer versions of one or more
system packages before you will be able to use a new version of the
<xref linkend='_ON' /> bits.  When this happens, it is known as a Flag Day.  Flag Day
notices will be posted at <ulink url='http://opensolaris.org/os/community/onnv/'>http://opensolaris.org/os/community/onnv/</ulink>
and will include instructions for building and/or installing the newer
software you will need.  It should be noted that this installation
procedure is not guaranteed to interoperate cleanly with the standard
packaging tools such as pkgadd(1M).  In particular, use of BFU (see
section 4.1.4) or ad-hoc replacement of Solaris components means that
those components can no longer be updated using Solaris packages.  If
this is of concern to you, we recommend that you utilize exclusively
Solaris Express for managing your system package installation, and build
and test only against the source tree current at the time of the latest
Express build.  You can
</para>
</sect2>
</sect1>
<sect1 id='_5_2_Using_Cap_Eye_Install_to_I' xreflabel='5.2 Using Cap-Eye-Install to Install Kernels'>
<title>5.2 Using Cap-Eye-Install to Install Kernels</title>
<para>
First, you must have a <xref linkend='_workspace' /> containing a built kernel.  If you
need more information on building kernels, see chapter 4 and especially
section 4.3.  Once you have built a kernel, you need to make an Install
tarball using the Install command.
</para>
<para>
The Install(1) utility creates a tar file that can be extracted into an
appropriate machine's root directory.  It utilizes an existing built
kernel tree and the kernel makefiles to determine the correct contents
of the tar file.  See Install(1) or the output of 'Install -h' for a
complete list of options; only the most commonly-used options are
described here.
</para>
<para>
The tar file constructed by Install is specific to an architecture, such
as sun4u or i86pc.  There are two ways to specify the architecture for
which you want Install to create an archive. The first is to be in the
architecture's subdirectory (usr/src/uts/&lt;arch&gt;) when running Install;
the second and preferred method is to use the -k &lt;arch&gt; option.  Note
that current releases of ON support only one architecture in each ISA:
sun4u on SPARC and i86pc on x86/amd64.
</para>
<para>
Another setting which is usually specified is the &quot;glomname&quot;, using the
-G option.  This is the name of the subdirectory in /platform/&lt;arch&gt;/
that the binaries will go into, and is generally of the form
&quot;kernel.something&quot;.  If you don't use a glomname, you will overwrite the
current kernel and modules on the target machine, and are likely to make
BFUing the machine later a more difficult task, as well as running the
risk of having to boot from alternate media to fix your machine if the
new kernel does not boot.
</para>
<para>
A simple invocation of Install might look like:
</para>
<programlisting><![CDATA[
$ Install -G kernel.foo -k sun4u
... lots of spew ...
Creating tarfile /tmp/Install.username/Install.sun4u.tar
Install complete
]]></programlisting>
<para>
You can now copy /tmp/Install.username/Install.sun4u.tar to your test
machine and extract it in the root directory.  It's best to use the '-o'
option when extracting so that file ownership will be correct.
</para>
<para>
On x86 with build 14 or newer, you will need to add your kernel to the
boot archive before you will be able to boot it.  To do this, add the
line:
</para>
<programlisting><![CDATA[
platform/i86pc/kernel.foo
]]></programlisting>
<para>
to <code>/boot/solaris/filelist.ramdisk</code>, where <code>kernel.foo</code> is the
glomname (the argument to <code>-G</code>).  This requirement is eliminated in
build 18 and newer, and does not apply to SPARC.
</para>
<para>
After installing your kernel, reboot the test machine and have it use
the new kernel by running:
</para>
<programlisting><![CDATA[
(SPARC)
# reboot -- 'kernel.foo/sparcv9/unix'
]]></programlisting>
<programlisting><![CDATA[
(AMD64)
# reboot -- 'kernel.foo/amd64/unix'
]]></programlisting>
<programlisting><![CDATA[
(x86)
# reboot -- 'kernel.foo/unix'
]]></programlisting>
<para>
Note that you will need to use either this reboot syntax each time you
wish to boot the test kernel, or use similar arguments to the bootloader
or OBP.  Otherwise, the normal kernel installed by BFU or the regular
installation will be booted.
</para>
<sect2 id='_5_2_1_Caveats' xreflabel='5.2.1 Caveats'>
<title>5.2.1 Caveats</title>
<para>
Although Install is useful for developers who have changed only kernel
code, it is of limited value for others.  In particular, if a recent
flag day notice indicates that newer kernels are incompatible with
existing userland libraries or commands, Install cannot be used to test
the updated kernel until you have upgraded your userland via BFU or some
other mechanism such as the regular installation or upgrade procedure.
</para>
<para>
Like bfu (see section 5.3), Install is rather closely attached to its
particular release, so you should use the current version from the
<xref linkend='_gate' /> matching the release you are building.  Normally this is in the
public/bin subdirectory of the gate; however, for installations outside
Sun it is located in /opt/onbld/bin.
</para>
<para>
It is critical that Install users install the correct set of
platform-specific modules, especially on SPARC systems.  Failure to do
so can result in an unbootable system.  See section 5.2.2 below for more
information on how platform-specific modules relate to Install.
</para>
<para>
One major advantage of Install over BFU is the ability to keep your
existing kernel in place so that you can still boot if the test kernel
proves toxic.  We strongly recommend that if you use Install to test
kernels, you take advantage of this feature and use distinct locations
(see the -G option described in section 5.2.1 above) for each new kernel
you test.  Otherwise, you will likely have to boot from alternate media
to repair your system following the installation of a bad kernel.
</para>
</sect2>
<sect2 id='_5_2_2_Platform_Specific_Inform' xreflabel='5.2.2 Platform-Specific Information'>
<title>5.2.2 Platform-Specific Information</title>
<para>
Ordinarily, Install does not generate archives with
implementation-specific modules.  If these archives are installed onto a
system which requires the missing modules, the system may fail to boot
or work properly.  If you do this, you will need to boot from a
known-working kernel and correct the problem.
</para>
<para>
An example symptom of the problem (on an Enterprise 3500):
</para>
<programlisting><![CDATA[
SunOS Release on81 Version jrhyason_[ws-vmstat]_05/15/01 64-bit
Copyright 1983-2001 Sun Microsystems, Inc.  All rights reserved.
DEBUG enabled
obpsym: symbolic debugging is available.
Read 297063 bytes from misc/forthdebug
  ====>  WARNING: consconfig: consconfig_util_openvp failed: err 6 vnode
 0x2803c80
  ====>  WARNING: consconfig: consconfig_util_link I_PLINK failed: error
 22
configuring IPv4 interfaces: hme0.
...
]]></programlisting>
<para>
The console is gone!
</para>
<para>
To include the needed modules in your Install tarball, make sure to use
</para>
<programlisting><![CDATA[
$ Install -i <implementation>
]]></programlisting>
<para>
to include implementation-specific modules.  But how do you know what
sun4u implementation you need?  First, obtain your machine's &quot;official&quot;
implementation name from the output of 'uname -i'.  Then, in
usr/src/uts/sun4u, run &quot;grep IMPLEMENTED_PLATFORM */Make*&quot; to see a list
of implementations and the corresponding platform name reported by
uname(1).
</para>
<para>
In the example above, the E3500 reports:
</para>
<programlisting><![CDATA[
$ uname -i
SUNW,Ultra-Enterprise
]]></programlisting>
<para>
And we see from the grep output:
</para>
<programlisting><![CDATA[
$ grep IMPLEMENTED_PLATFORM */Make*
...
sunfire/Makefile:IMPLEMENTED_PLATFORM   = SUNW,Ultra-Enterprise
...
]]></programlisting>
<para>
In this case, the &quot;-i sunfire&quot; argument must be added to get the correct
behavior.
</para>
<para>
Additionally, one of the easiest ways to get tripped up with Install
wads comes from the fact that not all drivers are delivered by <xref linkend='_ON' />.
This has been particularly noticeable with x86, but it also happens with
SPARC, especially framebuffer drivers.  One way to work around this is
to do:
</para>
<programlisting><![CDATA[
# cd /platform/{sun4u,i86pc}
# mkdir glomname
# (cd kernel; tar cf - .) | (cd glomname; tar xf -)
]]></programlisting>
<para>
and then install the Install glom image.  This will copy your existing
drivers to the new kernel installation, ensuring that the drivers which
are not part of ON (or OpenSolaris as a whole) are available when you
reboot.
</para>
</sect2>
</sect1>
<sect1 id='_5_3_Using_BFU_to_Install_ON' xreflabel='5.3 Using BFU to Install ON'>
<title>5.3 Using BFU to Install ON</title>
<para>
The Blindingly Fast Upgrade (or Bonwick-Faulkner Upgrade) is a process
used to update <xref linkend='_ON' /> bits on a system.  The ordinary Solaris upgrade
procedure requires the complete <xref linkend='_WOS' /> and takes at least 30 minutes
(usually much longer).  To save time, BFU uses a set of cpio(1) archives
to directly overwrite the existing contents of the system.  BFU often
takes less than 10 minutes to run to completion, and if you are
upgrading from a recent build, conflict resolution will usually take
only a few minutes.  Over the course of a year, using BFU can save
dozens of hours of development time.
</para>
<para>
In order to use BFU, you will need to set three additional environment
variables first.  You can set these in your login dot-files, or on the
command line.  If you prefer, you could create a local wrapper for
bfu(1) that sets them first.  The environment variables are:
</para>
<itemizedlist>
<listitem><para>FASTFS</para>
<para>
This should normally be set to /opt/onbld/bin/`uname -p`/fastfs.
</para>
</listitem>
<listitem><para>BFULD</para>
<para>
This should normally be set to /opt/onbld/bin/`uname -p`/bfuld.
</para>
</listitem>
<listitem><para>GZIPBIN</para>
<para>
This should normally be set to /usr/bin/gzip.
</para>
</listitem>
</itemizedlist>
<para>
BFU is simple to use and normally takes only a single argument: a path
to the set of archives you wish to install.  For example, if your
<xref linkend='_workspace' /> is located in /home/jdoe/workspace, and you have completed
a nightly(1) build, you would invoke bfu(1) as follows:
</para>
<programlisting><![CDATA[
# bfu /home/jdoe/workspace/archives/`uname -p`/nightly
]]></programlisting>
<para>
Note that, since it modifies the system software installation, bfu(1)
must always be run as root.
</para>
<para>
When bfu completes there's no guarantee that the new commands and
libraries are compatible with the currently running (old) kernel.
Therefore, instead of exiting, bfu puts you into a subshell in which
PATH=/tmp/bfubin and LD_LIBRARY_PATH=/tmp/bfulib.  These directories
contain the old versions of the commands and libraries commonly needed
to resolve conflicts and reboot the system.  They have also been
modified to work with a saved copy of the old dynamic linker.
</para>
<para>
Note that you may receive warnings from BFU about being unable to copy
files from &quot;greenline.eng&quot; or other systems or locations.  In general,
these warnings should be reported as bugs.  However, at the time of this
writing, they are harmless provided that your system is running at least
Solaris 10 build 74 prior to your BFU attempt.  See the latest release
notes for any additional requirements and restrictions.
</para>
<sect2 id='_5_3_1_Caveats' xreflabel='5.3.1 Caveats'>
<title>5.3.1 Caveats</title>
<para>
Although it saves time, BFU is not a panacea.  This section contains
information about BFU's drawbacks.  You should carefully evaluate these
drawbacks against the benefits and decide whether BFU is appropriate to
your needs.  In general, unless you are an active developer, we
recommend that you do not use BFU.
</para>
<para>
BFU does not update package information.  Therefore you will most likely
be unable to install official Solaris patches or run a full system
upgrade procedure on a system which has been BFU'd.  The importance of
this cannot be overemphasized: <emphasis role='bold'>IF YOU BFU YOUR SYSTEM, DO NOT ATTEMPT
TO USE &quot;NORMAL&quot; SYSTEM MANAGEMENT PROCEDURES TO UPDATE IT IN THE FUTURE.
USE BFU OR REINSTALL</emphasis>.
</para>
<para>
BFU does not update non-<xref linkend='_ON' /> packages, even if newer versions of
those packages are required in order to successfully install or run the
version of ON you are installing.  You may need to update those packages
before and/or after running BFU.  To understand what package updates may
be needed, consult <ulink url='http://opensolaris.org/os/community/onnv/'>http://opensolaris.org/os/community/onnv/</ulink> for
the full list of flag days between the build you are currently running
and the build you wish to BFU to.  Each flag day notice will instruct
you as to what package updates, if any, are needed, and whether they
must be completed before or after BFUing.  It is critical that you read,
understand, and follow these instructions exactly before running BFU.
If you fail to do so you will almost certain <xref linkend='_brickify' /> your system.
See section 5.1.3 for more information about flag days.
</para>
<para>
Although the core functionality of BFU consists of the simple activity
of unpacking cpio(1) archives into the running system, it also performs
numerous other tasks related to the update of your system.  Many of
these tasks are specific to particular changes that have been made in
the sources over a period of years.  If your system has unusual
characteristics, these additional updates can fail, which may result in
a nonfunctional system.  Because these updates vary greatly, it is
impossible to know in advance which updates could fail, or what failure
modes are possible.  Although such failures are rare, they can occur.
If you use BFU, you should follow the development of ON to understand
changes being made that could have an adverse effect on your system.  If
you have doubts as to how well BFU will update a particular aspect of
your system following a major change to ON, read bfu(1) and consult with
the engineers who made the change.
</para>
<para>
When bfu finishes, it invokes ksh with a limited PATH.  The PATH
contains programs which have been specially modified to work regardless
of what changes the BFU archives may contain.  You can use these
programs to resolve conflicts (see section 5.3.2).  In particular,
&quot;reboot&quot; works, but &quot;init 6&quot; does not.  You can exit from this protected
environment if you want, but it is not advisable unless you are sure
that there have not been any &quot;flag days&quot; (synchronized kernel/userland
changes) since your last bfu.
</para>
<para>
Never BFU in a window; always use the system console.  If BFU or the
system crashes in midstream, or you use the window system and it crashes
or hangs, your system will be in an inconsistent state.  You may be
unable to boot.  Therefore, you should ensure that as much of the system
as possible is quiescent before starting a BFU, and be sure you have a
copy of suitable system software media handy to reinstall if necessary.
</para>
<para>
Never BFU a production system.  Production systems should always be
updated to approved releases using the supported upgrade mechanism.
</para>
</sect2>
<sect2 id='_5_3_2_Resolving_Conflicts' xreflabel='5.3.2 Resolving Conflicts'>
<title>5.3.2 Resolving Conflicts</title>
<para>
Every machine has several configuration files which get modified from
the default installation; bfu keeps a list of these.  This list is known
as the conflicts database.
</para>
<para>
BFU saves a copy of each configuration file it would overwrite under
/bfu.child; likewise, it stores a copy of each such file from the cpio
archives it is extracting under /bfu.parent, having moved the previous
BFU's /bfu.parent (if any) to /bfu.ancestor.  We refer to the files
saved under those directories as the child, parent and ancestor
respectively.
</para>
<para>
When the extraction is complete, BFU diffs the various versions of
these configuration files and acts according to the following rules:
</para>
<para>
* If the file is unchanged (i.e., there is no difference between
the child and the parent), there is nothing to do or report.
</para>
<para>
* If the file was accepted from the parent the previous run
(i.e., the child is identical to the ancestor) then the parent
is accepted automatically this time; such files are marked as
&quot;update:&quot;.
</para>
<para>
* If the file is the same as the beginning of the previous file,
it is assumed that the user has added lines to the end (i.e.,
the child consists of the parent plus some added lines); the
child version is restored; such files are marked as
&quot;restore:&quot;.
</para>
<para>
* If the file differs between the parent and the child, but the
parent and ancestor are identical, then it is deemed an old
conflict; such files are marked as &quot;old:&quot;.
</para>
<para>
* Lastly, if the file differs between the parent and the child,
and the parent and ancestor differ as well, then it is deemed
a NEW conflict; such files are marked as &quot;NEW:&quot;.
</para>
<para>
So now we know that a NEW conflict means a file which was already
different from the default, where the default has been updated. To
resolve this difference, whatever changes were introduced in the new
build must be ported to the existing file on the system.
</para>
<para>
Although it is possible to blindly accept the parent, this will cause
any customizations in the child to be lost.  As it is very common for
these files to have such customizations made automatically by class
action scripts from non-<xref linkend='_ON' /> packages, this is usually a mistake,
which can lead to hours of lost productivity.  Therefore, there are two
forms of conflict resolution which are discussed in the following two
sections.  They are automatic and manual conflict resolution.
</para>
<para>
If you elect to resolve conflicts manually, or if the automatic tools
are unable to resolve all conflicts, you will benefit from having a
proper BFU baseline installation.  To establish such a baseline, you
should install BFU archives corresponding to your distribution
immediately after installing it.  It is strongly recommended that you
begin this process only if your installation is sufficiently recent that
such BFU archives are available.  In particular, <emphasis role='bold'>BFUing a system older
than Solaris 11 build 16 will fail and may render your system
unbootable.</emphasis>
</para>
<para>
When BFUing to the same build as your distribution include, you can
ignore all conflicts, since your existing installed configuration files
are known to work correctly for this build.  You must then reboot before
BFUing to a later build.
</para>
<sect3 id='_5_3_2_1_Automatic_Conflict_Res' xreflabel='5.3.2.1 Automatic Conflict Resolution'>
<title>5.3.2.1 Automatic Conflict Resolution</title>
<para>
Automatic conflict resolution is performed by a script called <emphasis>acr</emphasis>.  This
script is available in /opt/onbld/bin and in the usr/src/tools/scripts
directory of the <xref linkend='_ON' /> workspace.  In the usr/src/tools/scripts directory,
the acr executable gets made from acr.sh if you do a nightly(1) build with
the -t option.  There is man page, acr.1, in /opt/onbld/man/man1 and in the
usr/src/tools/scripts directory of the <xref linkend='_ON' /> workspace.
</para>
<para>
The standard way to use acr is to invoke it while still in the protected
environment after a BFU is performed.  In this mode there is no need to
specify any command line parameters.
</para>
<para>
For more specialized applications, acr accepts one or two parameters.  The
first parameter is the name of an alternate root directory.  The second
parameter, if specified, is the name of the directory containing the
archives.
</para>
<para>
acr uses a file called conflict_resolution.gz in the directory containing
the BFU cpio archives.  This conflict resolution file is constructed
whenever nightly(1) creates archives.  That is to say whenever nightly(1)
is run with the -a option.
</para>
<para>
When acr runs, it lists the files that it is processing to standard out.
Detailed results are written to a file called <emphasis>allresults</emphasis> in a
subdirectory of /tmp.  When acr exits, it prints the full path name of the
allresults file.  The allresults should be examined to ensure that no
errors occurred during acr processing.  If errors occurred, you will need
to resort to manual conflict resolution discussed in the next section.
</para>
</sect3>
<sect3 id='_5_3_2_2_Manual_Conflict_Resolu' xreflabel='5.3.2.2 Manual Conflict Resolution'>
<title>5.3.2.2 Manual Conflict Resolution</title>
<para>
Manual conflict resolution requires you to resolve each of the conflicts by
hand.  The general way to resolve conflicts is:
</para>
<programlisting><![CDATA[
% diff /bfu.ancestor/$file /bfu.parent/$file
]]></programlisting>
<para>
then manually apply the diffs to /$file.  Note that you will not have
<code>/bfu.ancestor</code> if you have not previously BFU'd; therefore you will
find manual conflict resolution easier if you have established a
baseline as described above.  For many files, a short-cut can be
employed.  BFU drops you in /bfu.conflicts when it completes, and most
changes are additions or modifications, so doing:
</para>
<programlisting><![CDATA[
% diff $file /$file
]]></programlisting>
<para>
and making sure the diffs all point to the right (i.e., &quot;&gt;&quot; rather
than &quot;&lt;&quot;) will do the trick.  This will not work in all cases,
however; some notable exceptions are detailed below.
</para>
<para>
<emphasis role='bold'>etc/name_to_major</emphasis>
</para>
<para>
This file matches device names with major numbers; it is critical that
each device have a unique major number.  Diffing the ancestor with the
parent is a good start -- just remember that the name is important, but
the major number may vary.  Old devices which have been removed in the
parent should be deleted, but if you're not sure, just leave them alone
as they are generally harmless.  New devices should be added with an
unused major number (if it's available, use the one from the diffs).
Never change the number for an existing entry unless you are sure you
know what you are doing.  If you are in doubt as to what changed, you
can consult the history of the files directly from your <xref linkend='_workspace' />
(e.g. usr/src/uts/{intel|sparc}/os/name_to_major).
</para>
<para>
Once finished, you can sanity-check your changes by running:
</para>
<programlisting><![CDATA[
% sort -k1,1 /etc/name_to_major | sort -uc -k1,1
% sort -k2n /etc/name_to_major | sort -uc -k2n
]]></programlisting>
<para>
These report the first duplicated device name and the lowest
duplicated major number, respectively.  Either of these
indicates a problem that you must correct before rebooting.
If there is no output, you're all set.  Note that the kernel
will also warn you of such conflicts after you reboot, but by
then it may be too late.
</para>
<para>
<emphasis role='bold'>etc/security/*_attr</emphasis>
</para>
<para>
These files tend to get shuffled around quite a bit by
class-action scripts, so the parent and child versions can
differ wildly. For these, the shortcut described above is
ineffective, but the more general diff of the ancestor with
the parent works well.
</para>
<para>
In general, only NEW conflicts need to be examined.
</para>
</sect3>
</sect2>
<sect2 id='_5_3_3_BFU_and_Zones' xreflabel='5.3.3 BFU and Zones'>
<title>5.3.3 BFU and Zones</title>
<para>
The contents of each zone are copied from the global zone when the zone
is created.  To ensure that all zones remain operational after BFUing,
it is necessary to keep the zone contents consistent with those in the
global zone.  To do this, BFU will update each zone in turn once the
global zone has been updated; however, because each zone may have
configuration files that differ from the global zone's, each zone has
its own BFU conflict management directories.  Unfortunately, it is not
possible to BFU only a single zone.  BFU affects the entire system
including all zones.  If you want to test userspace changes in a zone,
you will need to copy files from your proto area into that zone
manually.
</para>
<para>
It is safest to shut down all zones before BFUing your system.  This
will ensure that dependencies which may be violated by the files being
installed will not break a zone.
</para>
<para>
After BFUing a system with zones other than the global zone, you will
need to first resolve conflicts in the global zone, then resolve
conflicts in each remaining zone before rebooting the system.
Resolving BFU conflicts in a zone works exactly the same way as for
the global zone; however, in many cases it will not be necessary to
manually merge the file contents.  Instead you are likely to find that
the file should be identical to that in the global zone, and you can
simply copy it over.  After resolving conflicts in all zones, you must
reboot your system before rebooting any zone.
</para>
</sect2>
</sect1>
<sect1 id='_5_4_Test_Suites' xreflabel='5.4 Test Suites'>
<title>5.4 Test Suites</title>
<para>
Sun has a number of test suites used with <xref linkend='_ON' />.  Unfortuantely these
aren't yet available; check out the roadmap at
<ulink url='http://opensolaris.org/os/about/roadmap/'>http://opensolaris.org/os/about/roadmap/</ulink>.
</para>
</sect1>
</chapter>
<chapter id='_6_Integration_Procedure' xreflabel='Integration Procedure'>
<title>Integration Procedure</title>
<para>
The integration procedure is documented at
<ulink url='http://opensolaris.org/os/community/onnv/os_dev_process/'>http://opensolaris.org/os/community/onnv/os_dev_process/</ulink>.
</para>
<sect1 id='_6_1_Code_Review_Process' xreflabel='6.1 Code Review Process'>
<title>6.1 Code Review Process</title>
<para>
Code review is the &quot;last defense against brokenness.&quot;  It is a critical
part of the development process: no change can be <xref linkend='_putback' /> by anyone,
no matter how knowledgeable or experienced, without first being
reviewed.  As a version nears release, code review requirements become
more strict; more reviewers may be required.  The code review process
can take anywhere from a few minutes to many hours, depending on the
type, size, and intrusiveness of the changes being made.  Normally,
developers will ask others to review their changes who are familiar with
the code being modified.
</para>
<para>
The purpose of code review is to find subtle and non-obvious problems
with the changes being made, not to absolve the implementor of
responsibility for his or her changes.  Specifically, developers must
conduct their own self-review and testing before requesting a formal
code review.
</para>
</sect1>
<sect1 id='_6_2_Licensing_Requirements' xreflabel='6.2 Licensing Requirements'>
<title>6.2 Licensing Requirements</title>
<para>
All code integrated into OpenSolaris by a Sun employee must contain the
usual Sun copyright notice (see <xref linkend='_7_2_3_Non_Formatting_Considera' />).
The code will then be licensed by Sun Microsystems both as part of the
OpenSolaris project and to other customers via various Solaris and other
licenses.  Thus, licensing is not a concern for Sun employees.
</para>
<para>
In order to contribute code to OpenSolaris, developers who are not Sun
employees or contractors will need to enter into a contributor
agreement.  A contributor agreement assures the community that
contributors have sufficient rights to the code being contributed, and
that any third party intellectual property issues are disclosed.  It
also allows defense of OpenSolaris should there be a legal dispute
regarding the software at some time in the future.
</para>
<para>
Contributors who add significant changes to an existing file or add new
files may include a brief copyright notice similar to the standard Sun
copyright notice.  See <xref linkend='_7_2_3_Non_Formatting_Considera' /> and the
contributor agreement for more information.
</para>
</sect1>
</chapter>
<chapter id='_7_Best_Practices_and_Requireme' xreflabel='Best Practices and Requirements'>
<title>Best Practices and Requirements</title>
<para>
This chapter provides information on standards and procedures which must
be followed by all developers.  These rules are the same ones which Sun
engineers have been required to follow when developing Solaris, and are
the primary reason Solaris, and now OpenSolaris, is among the world's
best available software.  These standards generally apply to all
consolidations.
</para>
<sect1 id='_7_1_Compatibility_and_Visibili' xreflabel='7.1 Compatibility and Visibility Constraints'>
<title>7.1 Compatibility and Visibility Constraints</title>
<para>
OpenSolaris has a comprehensive set of rules governing interfaces.  An
interface is any aspect of the system that a user or developer can
observe or use.  Examples include functions and variables in libraries,
the location of a particular executable program, the output content,
format, and argument semantics of an executable program, and the
location in the filesystem of a header file.  There are thousands of
interfaces provided by OpenSolaris, and each of them has certain
visibility, documentation, and compatibility constraints.
</para>
<sect2 id='_7_1_1_Interface_Stability_Taxo' xreflabel='7.1.1 Interface Stability Taxonomy'>
<title>7.1.1 Interface Stability Taxonomy</title>
<para>
One of the attributes included in many Solaris man pages is &quot;Interface
Stability.&quot;  The value of this attribute defines who may depend on the
interface, and what expectations they may have for its future
maintenance.  The possible values and their explanations are described
here; note that the Private levels will not appear in man pages shipped
to customers.
</para>
<para>
In the absence of any evidence about an interface's stability level,
certain assumptions must be made.  Following the general rule &quot;be strict
in what you produce, and liberal in what you accept&quot; would lead one to
conclude that any documented interface is Stable, and undocumented
interfaces are probably being used by others, but could be changed at
any time without your knowledge (i.e.  they are at once both Project
Private and Unstable); as a consequence you should neither change the
interface nor depend on its current implementation.  If you need to
depend on or change an undocumented interface whose stability level
cannot be determined, you need to find that interface's owner, if any,
and have the action approved by the relevant ARC.  If the owner of the
interface can be found, you will most likely want to promote the
interface either to Open (public) status, or use one of the Contracted
Private stability levels.
</para>
<para>
Following is a list of stability levels and their respective meanings.
Additional information is available in the attributes(5) man page,
including the precise public definitions of major, minor, and micro
releases and additional information about Open interfaces.
</para>
<para>
<emphasis role='bold'>Stability Level: Standard</emphasis>
</para>
<programlisting><![CDATA[
----------------------------------------------------------------
Specification		Open
----------------------------------------------------------------
Incompatible Change	major release (X.0)
----------------------------------------------------------------
Compatible Change	minor release (x.Y)
----------------------------------------------------------------
ARC review of Specs	A precise reference is normally recorded
----------------------------------------------------------------
Examples	POSIX, ANSI-C, ABI, SCD, SVID, XPG, X11, DKI, VMEbus,
		Ethernet, NFS protocol, DPS
----------------------------------------------------------------
]]></programlisting>
<para>
Most of these interfaces are defined by a formal standard, and
controlled by a standards organization.  Incompatible changes to these
interfaces are rare.
</para>
<para>
This stability classification can also apply to interfaces that have
been adopted (without a formal standard) by an &quot;industry convention&quot;
(X/Open, MIT X-Consortium, OMG), or even by a single-source (Adobe's
Display PostScript, Novell's NetWare Protocols, Legato's network backup
protocols, Berkeley's sendmail) if we expect that the de facto standard
is unlikely to change incompatibly.
</para>
<para>
If possible, there should still be a reference to a standard
specification or reference system, although there may be cases where no
such citation is possible.  Customers are normally pointed to the same
specification.
</para>
<para>
Support is only provided for specific version(s) of a standard, and
support for a particular version does not guarantee that support will be
provided for other versions.  Sometimes bugs are corrected or
interpretation is clarified in a standard; we may make incompatible
changes to react to these, but will evaluate the impact of doing so and
will announce a compatibility and migration strategy. (PSARC/1995/224's
Advisory Information section provides guidelines for implementing a
preliminary draft of a new standard.)
</para>
<para>
Some standards lack bindings to a specific programming language; if the
project team chose names, numbers, extensions, or other
implementation-specific details, they should be called out for
architectural review.
</para>
<para>
<emphasis role='bold'>Stability Level: Stable</emphasis>
</para>
<programlisting><![CDATA[
----------------------------------------------------------------
Specification		Open
----------------------------------------------------------------
Incompatible Change	major release (X.0)
----------------------------------------------------------------
Compatible Change	minor release (x.Y)
----------------------------------------------------------------
ARC review of Specs	Yes
----------------------------------------------------------------
Examples		cc options, Sbus, XGL API; most bundled
			commands
----------------------------------------------------------------
]]></programlisting>
<para>
We publish the specification of these interfaces, typically as manual
pages or other product documentation.  We also tell customers we will
remain compatible with them.
</para>
<para>
The intention of a Stable interface is to enable arbitrary third parties
to develop applications to these interfaces, release them, and have
confidence that they will run on all minor releases of the product
(after the one in which the interface was introduced, and within the
same major release), without having to change or recompile the
applications.  Even at a major release, incompatible changes are
expected to be rare, and to have strong justifications.  Stable
interfaces are sometimes proposed to be industry Standards, as was the
case with ToolTalk (now an X/Open standard).
</para>
<para>
An ARC should review and archive the specification, and adequate
customer documentation must also exist.
</para>
<para>
These are interfaces whose specification is generally controlled within
OpenSolaris, and does not rely on externally delivered projects.
</para>
<para>
<emphasis role='bold'>Stability Level: Evolving</emphasis>
</para>
<programlisting><![CDATA[
----------------------------------------------------------------
Specification		Open
----------------------------------------------------------------
Incompatible Change	minor release (x.Y), with impact
			assessment
----------------------------------------------------------------
Compatible Change	minor release (x.Y)
----------------------------------------------------------------
ARC review of Specs	Yes
----------------------------------------------------------------
Examples		core and .il file formats, Solaris DDI &
			DGA; many GUIs, admin utils, config
			files, daemons; most of PAM
----------------------------------------------------------------
]]></programlisting>
<para>
An Evolving interface is subject to incompatible change at a major or
minor release, but we should expect to change an Evolving interface only
carefully, and probably slowly.  As the interface evolves, we will make
reasonable efforts to ensure that all changes are source and binary
compatible.
</para>
<para>
An ARC should review the interface specification (especially with
respect to ability to absorb expected evolution compatibly).  Adequate
customer documentation should also exist.  The intention of an Evolving
interface is to enable ISV's to exploit new technology, and it should be
expected that they will ship products that depend on these interfaces.
As a result, any incompatible change to an Evolving interface requires
an assessment of potential customer impact, and a notification and
migration plan.  Elements of such a plan might include:
</para>
<para>
* clearly setting customer expectations about the circumstances
under which the interfaces might change.
</para>
<para>
* ensuring that all such changes are described in the release notes
for the affected release.
</para>
<para>
* providing migration aids for binary compatibility and/or continued
source development.
</para>
<para>
A project's intention to accept the risk of depending on an Evolving
interface must be evaluated and explicitly approved by an ARC.
</para>
<para>
NOTE: It will often be the case that interfaces declared to be Evolving
will later be reclassified as Stable or Standard.  Nonetheless, foreseen
promotion is not a necessary attribute of the Evolving taxonomy level.
An interface could be classified Evolving and remain as such
indefinitely.
</para>
<para>
<emphasis role='bold'>Stability Level: Unstable</emphasis>
</para>
<programlisting><![CDATA[
----------------------------------------------------------------
Specification		Open
----------------------------------------------------------------
Incompatible Change	minor release (x.Y)
----------------------------------------------------------------
Compatible Change	micro release (x.y.Z)
----------------------------------------------------------------
ARC review of Specs	Yes
----------------------------------------------------------------
Examples		SUNW* package abbreviations,
			some config utils
----------------------------------------------------------------
]]></programlisting>
<para>
Unstable interfaces are experimental or transitional.  They are
typically used to give developers early access to new or rapidly
changing technology, or to provide an interim solution to a problem
where a more general solution is anticipated.  No claims are made about
either source or binary compatibility from one minor release to the
next.
</para>
<para>
The intention of an Unstable interface is that they be imported only by
prototypes and by products on the same CD (or whatever release medium)
as the interface implementation.  A project's intention to import an
Unstable interface should be discussed with the ARC early.  The
stability classification of the interface -- or a replacement interface
-- might be raised.  The opinion allowing any project to import an
Unstable interface should explain why it is acceptable.
</para>
<para>
Any documentation for an Unstable interface must contain warnings that
these interfaces are subject to change without warning and should not be
used in unbundled products.  In some situations, it may be appropriate
to document Unstable interfaces in White Papers rather than in standard
product documentation.
</para>
<para>
Given such caveats, customer impact need not be a factor when
considering incompatible changes to an Unstable interface in a major or
minor release.  Nonetheless, when such changes are introduced, the
changes should still be mentioned in the release notes for the affected
release.
</para>
<para>
An ARC should review and archive the specification.  Any proposed change
to the interface must be ARC approved.
</para>
<para>
NOTE: If we choose to offer a draft standard implementation but state
our intention to track the standard (or the portions we find technically
sound or likely to be standardized), we set customer expectations for
incompatible changes by classifying the interface Unstable.  The
interface should be reclassified Standard when standard is final.  Such
an intention could be encoded &quot;Unstable-&gt;Standard&quot;.)
</para>
<para>
<emphasis role='bold'>Stability Level: External</emphasis>
</para>
<programlisting><![CDATA[
----------------------------------------------------------------
Specification		Open
----------------------------------------------------------------
Incompatible Change	micro release (x.y.z)
----------------------------------------------------------------
Compatible Change	micro release (x.y.z)
----------------------------------------------------------------
Arc review of Specs	A precise reference is normally recorded
----------------------------------------------------------------
Examples		OpenSSL
----------------------------------------------------------------
]]></programlisting>
<para>
These interfaces are controlled by a body outside of OpenSolaris, but
unlike Standard, it can not be asserted that an incompatible change to
the interface would be exceedingly rare.  In some cases it may not even
be possible to clearly identify the controlling body.  This
classification is typically used for third-party open source components
integrated wholesale into an OpenSolaris consolidation.
</para>
<para>
Use of the External interface stability level allows freeware interfaces
provided by Sun to quickly track the fluid, external specification.  In
many cases, this is preferred to providing additional stability to the
interface, as it tends to track the expectations of the community.
However, External interfaces should adhere to OpenSolaris standards in
at least the following areas:
</para>
<para>
* Security, Authentication
* Manual Page Section Numbering
* File System Semantics (/usr may be read-only, /var is where all
significant run-time growth occurs, ...)
</para>
<para>
All External interfaces should be labeled as such in all associated
documentation and the consequence of using such interfaces should be
explained either as part of that documentation or by reference.  Default
search paths should not lead to External interfaces - the user should be
required to take some simple, explicit action to access them.
</para>
<para>
Shipping incompatible change in a patch should be strongly avoided.  It
is not strictly prohibited for the following two reasons:
</para>
<para>
* Since we are not in explicit control of the changes, we can not
guarantee with reasonable assurance that an unidentified
incompatibility isn't present.
</para>
<para>
* A strong business case may exist for shipping a newer version as a
patch if that newer version closes significant escalations.
</para>
<para>
In general, the intent of allowing change in a patch is to allow for
change in Update Releases.
</para>
<para>
It should be noted that in some cases it will be preferable to apply a
less fluid interface classification to an interface even if the
controlling body is external to OpenSolaris.  Use of the Unstable
classification extends the stability commitment over micro/patch
releases, allowing use of additional support models for software that
depends upon these interfaces, at the potential cost of less frequent
updates.  However, care should be exercised because it will be difficult
to differentiate External and Unstable as a classification for seemingly
identical software.  It is suggested to use External and behave (through
contracts) as Unstable.  Use of the Evolving classification promotes
these interfaces to first class OpenSolaris interfaces, at the potential
cost of diverging from the external specification.  By using Evolving,
we are essentially taking control of the interface, although it may
liberally import from the external reference.  Use of the Stable
classification is not recommended.
</para>
<para>
<emphasis role='bold'>Stability Level: Contracted External</emphasis>
</para>
<para>
This stability level is the same as External, except that a contract has
been put in place between the provider and consumer of the interface.
The contract describes special arrangements made for the stability of
the interface.  This can be used, for example, to place restrictions on
how and when an interface may change if the normal rules for External do
not satisfy the requirements of the consumer.
</para>
<para>
An ARC should review, approve, and archive a contract between the
provider and consumer of the interface.  Any change to the contract, the
interface, or the specification requires reapproval.
</para>
<para>
<emphasis role='bold'>Stability Level: Obsolete</emphasis>
</para>
<programlisting><![CDATA[
----------------------------------------------------------------
Specification		Open, along with warning of obsolescence
----------------------------------------------------------------
Incompatible Change	minor release (x.Y)
----------------------------------------------------------------
Compatible Change	By former classification, but unlikely
----------------------------------------------------------------
ARC review of Specs	Normally downgraded from a higher
			stability; ARC approval of interface or
			feature removal is also required.
----------------------------------------------------------------
Examples		RFS, System-V LP protocol
----------------------------------------------------------------
]]></programlisting>
<para>
An interface that is &quot;deprecated&quot; and/or no longer in general use.  An
existing interface may be downgraded from some other status (such as
Stable or Standard) to Obsolete to encourage customers to migrate from
that interface before it will be removed (or incompatibly changed).
</para>
<para>
In addition to reclassifying the interface Obsolete and documenting the
new classification in customer documentation, a pro-active program to
communicate to customers the change in commitment must precede the
incompatible change or removal in a minor release.  For some interfaces,
the ARC may find such a communication program appropriate before
removing an interface, even at a major release.
</para>
<para>
The standard program to communicate a change in commitment requires:
</para>
<para>
1. Demonstration of support by the Steering Committee responsible for
the deliverable(s) containing the interface. Such support can be
demonstrated by a change to strategy document or resolutions taken in
meetings and documented in the minutes.
</para>
<para>
2. One year's notice to the customer base and the Sun product
development community of the intended obsolescence of the interface.
This requirement ensures that no further commitments against the
interface are created and gives those affected by future removal of the
facility a chance to make alternative arrangements.
</para>
<para>
The year must elapse after the notice and prior to the delivery of
a product that contains a change incompatible with the present status of
the interface.
</para>
<para>
Acceptable means of customer notice includes letters to customers
on support contracts, release notes or product documentation, or
announcements to customer forums appropriate for the interface in
question.
</para>
<para>
The notice of obsolescence is considered to be &quot;public&quot;
information in that it is available freely to the customers.  It is not
intended that this require specific actions to &quot;publish&quot; the
information, such as press releases or similar forms of publicity.
</para>
<para>
3. Where technically feasible, inclusion in the release where the
interface is declared Obsolete of a warning mechanism if the interface
is used.  The mechanism should produce a message of the form &quot;The
application uses interface which has been declared obsolete and may not
be present in versions of released after [event].  Please notify your
support person.  See in [reference] for more information.&quot;  One
suggested method is to use syslog(3), with a level of &quot;LOG_WARNING&quot;.  A
method for turning off the warning message should also be provided.
Common sense should apply in determining how often the warning should
appear.
</para>
<para>
4. Information in the User Documentation that contains the following:
</para>
<para>
* An explanation of the meaning of Obsolete.
</para>
<para>
* An indication of the kinds of warning messages that may appear.
</para>
<para>
* A suggesting that the customer ask their support person to
contact the vendor of any application that causes such a
warning to appear.
</para>
<para>
* General instructions for turning off the warning messages.
</para>
<para>
* A list of the Obsolete interfaces contained in this release,
the earliest that they may disappear, the kind of warning
that might appear, and the method for disabling the warning.
</para>
<para>
Proposals to downgrade an interface through this mechanism must be
approved by an ARC before &quot;core&quot; documentation may be altered to
identify the interface as Obsolete.  Release notes may warn of the
possibility of removal with either ARC or Steering Committee approval.
A warning that the interface *may* be removed in a future release could
be included without ARC approval, but the ARC may not deem such notice
alone as sufficient notification to customers to &quot;start the 1-year
clock&quot;.
</para>
<para>
A follow-on project to perform the actual feature removal in a
forthcoming minor or major release after the timeout period expires,
requires architectural approval to ensure that the requirements of the
obsolescence policy have been met.  Provided they have been met,
approval will be straightforward.
</para>
<para>
<emphasis role='bold'>Stability Level: Committed Private</emphasis>
</para>
<programlisting><![CDATA[
----------------------------------------------------------------
Specification		Closed
----------------------------------------------------------------
Incompatible Change	major release (X.0)
----------------------------------------------------------------
Compatible Change	micro release (x.y.Z)
----------------------------------------------------------------
ARC review of Specs	Yes
----------------------------------------------------------------
Example			UFS media format,
			Calendar Manager RPC protocol
----------------------------------------------------------------
]]></programlisting>
<para>
For some otherwise-private interfaces, we must maintain compatibility
from release to release, in order to meet the customer's expectations
for compatibility of the programs using these interfaces.  However, we
don't want customers to depend on these interfaces directly, and we
don't want to directly expose these interfaces to customers.  These
interfaces are classified as Committed Private.
</para>
<para>
Our commitment is that a customer's &quot;normal&quot; use of system facilities
should not allow them to see any incompatible changes to these
interfaces.  Since these interfaces typically span machines by being
embodied in media or protocols (and since customers cannot upgrade all
their machines simultaneously), these interfaces can't be changed with
the freedom of a private interface.  Yet, changes to the details of the
interface can be dramatic, provided the commitment to the customer is
maintained.  In general, Committed Private interfaces should be
versioned.
</para>
<para>
An ARC should review and archive the specification, and will at least
assure that the interface can satisfy its purpose and support the
evolution described in the previous paragraph.  Any proposed change to
or new dependency on the interface must be ARC approved.
</para>
<para>
<emphasis role='bold'>Stability Level: Contracted Committed Private</emphasis>
</para>
<para>
This stability level is the same as Committed Private, except that a
contract has been put in place between the provider and consumer of the
interface.  The contract describes special arrangements made for the
stability of the interface.  This can be used, for example, to allow
exposure of the interface to a Sun Partner.
</para>
<para>
An ARC should review, approve, and archive a contract between the
provider and consumer of the interface.  Any change to the contract, the
interface, or the specification requires reapproval.
</para>
<para>
<emphasis role='bold'>Stability Level: Sun Private</emphasis>
</para>
<programlisting><![CDATA[
----------------------------------------------------------------
Specification		Closed
----------------------------------------------------------------
Incompatible Change	minor release (x.Y)
----------------------------------------------------------------
Compatible Change	micro release (x.y.Z)
----------------------------------------------------------------
ARC review of Specs	Yes
----------------------------------------------------------------
Example		trap 40 (gethrtime)
----------------------------------------------------------------
]]></programlisting>
<para>
These are interfaces which one <xref linkend='_consolidation' /> depends on and another
consolidation provides.  Changes to these interfaces must be coordinated
among all providers and users of the interface.  Some internal kernel
interfaces are Sun Private interfaces.
</para>
<para>
Interfaces are occasionally made Sun Private in order to gain some
experience with them before opening them up to wider use as Unstable or
Stable interfaces.  Making such interfaces Consolidation Private would
be preferable, however, as evolution is then far easier.
</para>
<para>
Sun Private interfaces are strongly discouraged.  Coordinating changes
to these interfaces within a consolidation is usually feasible, but
coordinating changes among different consolidations released
asynchronously is extremely difficult.  Interface versioning is advised
for Sun Private interfaces.
</para>
<para>
An ARC will review and archive these interfaces, with special attention
to how the interface could evolve, if necessary.  Any proposed change to
the interface must be ARC approved.
</para>
<para>
<emphasis role='bold'>Stability Level: Contracted Sun Private</emphasis>
</para>
<para>
This stability level is the same as Sun Private, except that a contract
has been put in place between the provider and consumer of the
interface.  The contract describes special arrangements made for the
stability of the interface.  This can be used, for example, to allow
exposure of the interface to a partner.
</para>
<para>
An ARC should review, approve, and archive a contract between the
provider and consumer of the interface.  Any change to the contract, the
interface, or the specification requires reapproval.
</para>
<para>
<emphasis role='bold'>Stability Level: Consolidation Private</emphasis>
</para>
<programlisting><![CDATA[
----------------------------------------------------------------
Specification		Closed
----------------------------------------------------------------
Incompatible Change	micro release (x.y.Z) or "jumbo patch"
----------------------------------------------------------------
Compatible Change	micro release (x.y.Z) or "jumbo patch"
----------------------------------------------------------------
ARC review of Specs	Not necessary
----------------------------------------------------------------
Examples		libdeskset, kernel nameslists
----------------------------------------------------------------
]]></programlisting>
<para>
These are interfaces internal to the consolidation that one piece of a
consolidation depends on and another piece of the same consolidation
provides.  Changes to these interfaces must be coordinated among all
providers and users of the interface.  Many internal kernel interfaces
are Consolidation Private interfaces.
</para>
<para>
Generally these are interfaces that have proven convenient for building
the consolidation, but which change often enough that we're not willing
to document them for external use nor to commit to their stability.
libdeskset is an example of such an interface.  Though the libkvm API is
Public, the undocumented names that can be accessed through that
interface are Consolidation or Project Private.
</para>
<para>
An ARC may review and archive these interfaces, or may leave the
consolidation to monitor their own internal commitments.  If a
Consolidation Private interface is reviewed by the ARC, ask that ARC if
they want to review later changes to that interface.
</para>
<para>
Importing the interface by any project outside the Consolidation would
require negotiating a &quot;contract&quot; with the interface providers.  An ARC
must review and approve the classification change to Contracted
Consolidation Private and the terms of the contract.
</para>
<para>
<emphasis role='bold'>Stability Level: Contracted Consolidation Private</emphasis>
</para>
<para>
This stability level is the same as Consolidation Private, except that a
contract has been put in place between the provider and consumer of the
interface.  The contract describes special arrangements made for the
stability of the interface.  This can be used, for example, to allow
exposure of the interface to a specific consumer in a different
consolidation.
</para>
<para>
An ARC should review, approve, and archive a contract between the
provider and consumer of the interface.  Any change to the contract, the
interface, or the specification requires reapproval.
</para>
<para>
<emphasis role='bold'>Stability Level: Project Private</emphasis>
</para>
<programlisting><![CDATA[
----------------------------------------------------------------
Specification		Closed
----------------------------------------------------------------
Incompatible Change	micro release (x.y.Z)
----------------------------------------------------------------
Compatible Change	micro release (x.y.Z) or patch
----------------------------------------------------------------
ARC review of Specs	No
----------------------------------------------------------------
Examples		Metamucil ioctls, nfssys system call,
			uadmin cpu control functions
----------------------------------------------------------------
]]></programlisting>
<para>
Project Private interfaces usually occur when a project must communicate
between its components across a boundary in the system.  For instance,
Metamucil includes several new ioctls to perform operations on UFS
filesystems.  The Metamucil ufsdump program uses these ioctls.  The
ioctls are private interfaces since they are intended to be used only by
the Metamucil product.  If the Metamucil product needs to change these
ioctls in the future, they can do so without coordinating with any other
projects, since no other projects may use these ioctls.  Likewise, the
nfssys system call is used to communicate between the kernel- and
user-level portions of NFS.
</para>
<para>
Project Private interfaces also occur in libraries where one module
needs to call a private routine in another module in the same library.
</para>
<para>
Also, Project Private interfaces may be provisional or in transition.
The uadmin cpu control functions are Project Private because they will
change form before appearing as Standard interfaces, and in the meantime
we don't want anyone depending on them.
</para>
<para>
Sadly, many kernel procedures are Project Private interfaces (instead of
Internal interfaces) because they are visible to dynamically loaded
kernel modules.
</para>
<para>
Once an interface is classified Project Private by an ARC, changes to
that interface need not be ARC approved.
</para>
<para>
Any use of the interface from outside the project would involve
negotiating a &quot;contract&quot; with the interface providers; an ARC must
review and approve the classification change to Contracted Project
Private and the terms of the contract.
</para>
<para>
<emphasis role='bold'>Stability Level: Contracted Project Private</emphasis>
</para>
<para>
This stability level is the same as Project Private, except that a
contract has been put in place between the provider and consumer of the
interface.  The contract describes special arrangements made for the
stability of the interface.  This can be used, for example, to allow
exposure of the interface to a specific consumer in a different
consolidation.
</para>
<para>
An ARC should review, approve, and archive a contract between the
provider and consumer of the interface.  Any change to the contract, the
interface, or the specification requires reapproval.
</para>
</sect2>
<sect2 id='_7_1_2_Library_Considerations' xreflabel='7.1.2 Library Considerations'>
<title>7.1.2 Library Considerations</title>
<para>
Libraries delivered by ON contain symbol versioning information that
limits the exposure of private interfaces and provides tracking of
changes to public interfaces.  This versioning information is embodied
in the specfiles and mapfiles found under <code>usr/src/lib/*/spec</code>.
</para>
</sect2>
</sect1>
<sect1 id='_7_2_Style_Guide' xreflabel='7.2 Style Guide'>
<title>7.2 Style Guide</title>
<para>
Like many engineering efforts, OpenSolaris enforces a coding style on
contributed code, regardless of its source.  This coding style is very
similar to that used by the Linux kernel, BSD systems, and many other
non-GNU projects (the GNU project uses its own unique coding style).
This style is described in detail at
<ulink url='http://opensolaris.org/os/community/onnv/'>http://opensolaris.org/os/community/onnv/</ulink>, although some elements
in the style guide are rather dated, especially as they relate to K&amp;R C
versus ANSI (now ISO) C.  You also should examine the files in
<code>usr/src/prototypes</code>; these provide examples of the correct general
layout and style for most types of source files.
</para>
<sect2 id='_7_2_1_Automated_Style_Tools' xreflabel='7.2.1 Automated Style Tools'>
<title>7.2.1 Automated Style Tools</title>
<para>
Two tools for checking many elements of the coding style are available
as part of the ON tools.  These tools are cstyle(1) for verifying
compliance of C code with most style guidelines, and hdrchk(1) for
checking the style of C and C++ headers.  Note that these tools are not
perfect; there are style mistakes that cannot be caught by any
reasonable tool, and others that cannot be caught by the particular
implementations.  Improving the accuracy and completeness of these tools
is an ongoing task and enhancements of all kinds are welcome.
</para>
<para>
All headers are expected to pass 'hdrchk'.  All C files and headers 
are expected to pass 'cstyle -P -p'.  These tools produce no output 
and exit with status code 0 if the file(s) checked meet the style 
requirements.
</para>
<para>
7.2.2 =head3 Style Examples
</para>
<para>
A few common examples of bad style which are not currently caught by the
tools include:
</para>
<para>
* Mixing declaration of initialized and uninitialized variables on the
same line; for example:
</para>
<programlisting><![CDATA[
int a, b = 16, c = -4, d;
]]></programlisting>
<para>
Instead, uninitialized variables may be declared one or more per line,
and each initialized variable should be declared on its own line:
</para>
<programlisting><![CDATA[
int a, d;
int b = 16;
int c = -4;
]]></programlisting>
<para>
or
</para>
<programlisting><![CDATA[
int a;
int b = 16;
int c = -4;
int d;
]]></programlisting>
<para>
* Inconsistent use of acceptable styles.  In the above
example, two acceptable ways to declare variables are presented.
Good style dictates that whichever is used by used everywhere within
a file; however, the tools do not check for such consistency.
</para>
<para>
* Incorrect placement and use of braces around if/else constructs.  The
heuristic test for this is not run by default, and is not completely
reliable.  For simplicity's sake, here is the correct format for
if/else in which both alternatives are compound statements:
</para>
<programlisting><![CDATA[
if (x != SOME_CONSTANT) {
	do_stuff();
	return (x);
} else {
	do_other_stuff();
	x = OTHER_CONSTANT;
}
]]></programlisting>
<para>
If neither alternative is a compound statement, use:
</para>
<programlisting><![CDATA[
if (x != SOME_CONSTANT)
	do_stuff();
else
	do_other_stuff();
]]></programlisting>
<para>
Finally, if only one alternative is a compound statement, both
alternatives should have braces, formatted as shown:
</para>
<programlisting><![CDATA[
if (x != SOME_CONSTANT) {
	do_stuff();
	return (x);
} else {
	do_other_stuff();
}
]]></programlisting>
<para>
Note the placement of braces; they should surround an &quot;else&quot; and only
the closing brace should be on a line by itself.
</para>
<para>
* Use of comments associated with conditional compilation directives.
It is good style to include trailing comments after #else and #endif
directives describing the condition it references; for example:
</para>
<programlisting><![CDATA[
#ifdef __FOO
...
#else	/* !__FOO */
...
#endif	/* !__FOO */
]]></programlisting>
<para>
The style tools do not check for the presence, usefulness, or
correctness of these trailing comments, but you should normally
include them, especially if the intervening code blocks are lengthy
or the tests are part of a complicated set of nested preprocessor
conditionals.
</para>
<para>
* Incorrect guards in header files.  Guard names should be derived
from the header name, but hdrchk does not check this.  For example, a
header installed in &lt;sys/scsi/foo_impl.h&gt; should have a guard as
follows:
</para>
<programlisting><![CDATA[
#ifndef _SYS_SCSI_FOO_IMPL_H
#define _SYS_SCSI_FOO_IMPL_H
...
#endif /* _SYS_SCSI_FOO_IMPL_H */
]]></programlisting>
<para>
However, hdrchk verifies neither the actual guard token name nor the
comment following #endif.
</para>
<para>
* Comment style is only partially checked.  For example, the correct
style for block comments is:
</para>
<programlisting><![CDATA[
/*
 * Some comment here.
 * More here.
 */
]]></programlisting>
<para>
cstyle(1) can detect some common errors, such as enclosing the entire
block comment in a box of asterisks or other characters.  However, it
cannot detect all such errors; for example:
</para>
<programlisting><![CDATA[
/*
   Some comment here.
   We conserve asterisks even though it's harder to read.
   Our comment is nonconforming.
 */
]]></programlisting>
<para>
Correct indentation of comments is also unchecked; block and
single-line comments within functions should be indented at the same
level as the code they document.  Trailing comments should be aligned
with other trailing comments in related code.  None of these style
guidelines is checked by the tools.
</para>
<para>
It probably goes without saying that the contents of comments aren't
checked in any way.  Please, be sure to follow the comment content
guidelines in the style guide.
</para>
</sect2>
<sect2 id='_7_2_3_Non_Formatting_Considera' xreflabel='7.2.3 Non-Formatting Considerations'>
<title>7.2.3 Non-Formatting Considerations</title>
<para>
cstyle(1) and hdrchk(1) will, in addition to several code-formatting
guidelines, verify compliance with SCCS keyword and copyright
requirements.  All files must be under SCCS control, and each must have
a set of keywords near the top (see the prototypes for the exact order
of file contents).  In general, the keywords should have the following
format in C files and headers:
</para>
<programlisting><![CDATA[
@PRAGMA_IDENT_EXP@
]]></programlisting>
<para>
Note that this string actually contains several embedded tabs; showing
these tabs as \t, the keywords look like:
</para>
<programlisting><![CDATA[
@PRAGMA_IDENT@
]]></programlisting>
<para>
Files which are not C (or C++) implementations or headers should
dispense with the &quot;pragma&quot; portion and just use #ident as follows:
</para>
<programlisting><![CDATA[
@IDENT@
]]></programlisting>
<para>
In addition, each file must contain a statement of copyright at the very
top.  The acceptable text and formats for these copyrights are shown in
the example files in usr/src/prototypes.  When a source file is
significantly updated, the year or range of years in the copyright
should be replaced with just the current year at the time of
modification.  Significant updates do not include formatting changes.
However, if you prefer not to think about whether your change
constitutes a significant update or if you don't trust your judgment,
erring on the side of always updating the year is acceptable.  Since the
prototypes assume that Sun is always the sole copyright holder, you will
need to change the copyright statement slightly; for example, if a file
initially contains:
</para>
<programlisting><![CDATA[
/*
 * Copyright (c) 1992-1998 by Sun Microsystems, Inc.
 * All rights reserved.
 */
]]></programlisting>
<para>
you should replace this notice with:
</para>
<programlisting><![CDATA[
/*
 * Copyright 2005 Sun Microsystems, Inc.
 * All rights reserved.  Use is subject to license terms.
 */
]]></programlisting>
<para>
and, if you are a contributor not employed by Sun, you should also add:
</para>
<programlisting><![CDATA[
/*
 * Copyright 2005 J. Random Hacker
 * All rights reserved.  Use is subject to license terms.
 */
]]></programlisting>
<para>
or a similar statement of your copyright.  Do not combine copyright
notices, and do not remove the existing copyright notices unless
specifically instructed to do so.
</para>
</sect2>
<sect2 id='_7_2_4_Integration_Requirements' xreflabel='7.2.4 Integration Requirements'>
<title>7.2.4 Integration Requirements</title>
<para>
Before submitting any changes for code review prior to inclusion in
OpenSolaris, you should self-review your code for stylistic correctness
(as well as semantic correctness!).  Running the cstyle(1) and/or
hdrchk(1) tools is part of this process, but you should also be familiar
with the entire style guide so that you will be able to use correct
style even in elements that the tools do not check.  All new code must
be cstyle- and, if applicable, hdrchk-clean.  If you are modifying
existing code which does not conform to the style guide, your changes
should be conformant, and at worst your changes should not increase the
number of cstyle or hdrchk warnings.
</para>
</sect2>
</sect1>
<sect1 id='_7_3_Testing_Guidelines' xreflabel='7.3 Testing Guidelines'>
<title>7.3 Testing Guidelines</title>
<para>
Changes must be adequately tested.  Because of the complexity of testing
some changes and the lack of test suite availability, sponsors will
provide guidance on appropriate testing.
</para>
</sect1>
<sect1 id='_7_4_Using_Lint' xreflabel='7.4 Using Lint'>
<title>7.4 Using Lint</title>
<para>
The entire Solaris kernel and many libraries and commands are completely
lint clean, both pass1 and pass2.  It is important that we maintain this
cleanliness as yet another tool to insure a high quality release.
Although not all non-kernel code is lint-clean, new code should be, and
all new commands and libraries should be entirely lint-clean.
Lint-clean code should indicate to the build system that it should be
linted.  For an example of code in transition to lint-cleanliness, see
usr/src/cmd/cmd-inet/usr.sbin/Makefile and the associated code.
</para>
<para>
Before checking in your changes use the following steps (on both SPARC
and x86!) to check for any new errors:
</para>
<programlisting><![CDATA[
% cd $SRC/uts
% ( make && make lint ) > ERRS 2>&1
% grep "warning:" ERRS
]]></programlisting>
<para>
*ANY* warning messages must be fixed!
</para>
<para>
Note that you can also use nightly(1) to generate lint output.  If you
instruct nightly(1) to run lint, which you should always do by adding
'l' to your NIGHTLY_OPTIONS or explicitly using the '-l' command line
option, it will produce a listing of any &quot;lint noise&quot; as part of its
final output if your changes have introduced lint warnings; it should be
empty.  This can be much easier than looking through a log file as
described above, and includes any lint warnings from both kernel and
non-kernel code which is intended to be lint-clean.
</para>
<para>
In the build system, linting is fairly similar to a &quot;normal&quot; build, but
it has an additional complication.  In order to get meaningful output
from lint pass2, all the modules must be linted together. This is
accomplished by each module being responsible to produce its own pass1
output (file.ln, one per .c/.s file). It is also responsible for placing
the lint-library (llib-lMODULE) in the uts/MACHINE/lint-libs directory.
The final full lint is accomplished by the makefile in the uts/MACHINE
directory by linting all the lint-libraries against each other.
</para>
<para>
Note that, to keep lint happy about functions defined in assembly
only, there are also C prototypes in the .s files.  For example:
</para>
<programlisting><![CDATA[
#if defined(lint)
int
blort(int, int)
{ return 0 }
#else	/* lint */
]]></programlisting>
<programlisting><![CDATA[
ENTRY(blort)
ld	[%i0],....
....
SET_SIZE(blort)
]]></programlisting>
<programlisting><![CDATA[
#endif	/* lint */
]]></programlisting>
<para>
Here are some additional rules for keeping code lint-clean and avoiding
lint problems:
</para>
<para>
* *NEVER* *EVER* use /* LINTLIBRARY */ in OpenSolaris kernel source!
</para>
<para>
* Modification of header files, either directly or as a result of
a merge, does not always cause the lint libraries to be rebuilt.  This
may result in seemingly impossible errors of a function having two
different declarations. Be sure to run &quot;make clean.lint&quot; after any merge
or modification of a header file.
</para>
<para>
* When calling a function with a return value but not using it, place
a (void) cast in front.  Common functions are sprintf and strcpy.
Many times ignoring a function return value can hide error
conditions.  Functions that always have the values ignored might need
to consider having their specification redeclared void, although of
course this normally does not apply to public interfaces.
</para>
<para>
* Format strings for long integers use one of &quot;%ld&quot;, %lx&quot;, or &quot;%lu&quot;
</para>
<para>
* Format strings for unsigned integers use one of &quot;%u&quot; or &quot;%x&quot;
</para>
<para>
* Format strings for long long integers use &quot;%lld&quot; or &quot;%llx&quot;
</para>
<para>
* Format strings for pointers should use &quot;%p&quot;, with the pointer cast
to (void *).  Using %d or %x and casting to an (int) will break in a
64-bit kernel.
</para>
<para>
* For code that is supposed to work for either ILP32 or LP64, there
are some macros that you can use in the format string, so that you
don't need to #ifdef longs versus ints.  See &lt;sys/int_fmtio.h&gt;.
</para>
<para>
* Use full ANSI/ISO prototypes in function declarations, as the kernel is
always compiled with __STDC__ defined.  New code should not use
K&amp;R-style declarations.
</para>
<para>
* Make sure machine dependent function declarations are consistent
across platforms.
</para>
<para>
* Be sure you are linting against the headers in your proto area and not
the installed headers on your build machine.
</para>
</sect1>
<sect1 id='_7_5_Tips_and_Suggestions' xreflabel='7.5 Tips and Suggestions'>
<title>7.5 Tips and Suggestions</title>
<para>
Contribute your feedback and suggestions!
</para>
</sect1>
</chapter>
<appendix id='_Appendix_A__Glossary' xreflabel='Glossary'>
<title>Glossary</title>
<para>
This glossary lists terms which are in common use within Sun but may be
unfamiliar to other Open Source and Free Software developers.  While we
expect OpenSolaris will in time develop its own unique nomenclature, you
may see other community members, especially Sun engineers, using these
terms.
</para>
<sect1>
<sect2>
<sect3 id='_ACR' xreflabel='ACR'>
<title>ACR</title>
<para>
Automatic Conflict Resolver.  A tool to aid in the resolution of
conflicts imposed by a BFU prior to completing the upgrade.  Without
ACR all conflicts must be resolved manually, this simply automates
the proccess and as such reduces the chances of missed conflicts that
could <xref linkend='_brickify' /> your system.
</para>
</sect3>
<sect3 id='_ARC' xreflabel='ARC'>
<title>ARC</title>
<para>
Architecture Review Committee.  A committee of engineers assembled to
review and approve (or not) software architecture.  Architectural issues
generally include interface dependencies and user interface
presentation.
</para>
</sect3>
<sect3 id='_archives' xreflabel='archives'>
<title>archives</title>
<para>
CPIO-format files used by <xref linkend='_BFU' />.  These contain all the ON binaries
that are installed during the BFU.
</para>
</sect3>
<sect3 id='_BFU' xreflabel='BFU'>
<title>BFU</title>
<para>
Blindingly Fast Upgrade a.k.a. Bonwick/Faulkner Upgrade.  This is a way
to upgrade the subset of a system's binaries that are delivered by the
<xref linkend='_ON' /> <xref linkend='_consolidation' /> that uses cpio(1) archives instead of
packages to improve speed.  This requires manual resolution of
configuration file conflicts and can be hazardous; therefore it is
recommended only for developers who have read and understand <xref linkend='_5_3_Using_BFU_to_Install_ON' />.  BFU is implemented by 'mkbfu', 'makebfu',
'cpiotranslate', and bfu(1).
</para>
</sect3>
<sect3 id='_binary_patch' xreflabel='binary patch'>
<title>binary patch</title>
<para>
Collection of updated binary objects distributed to customers other than
when official releases are made.  Binary patches may correct an urgent
security problem or address a specific bug specific to a major customer.
Binary patches will not be issued for OpenSolaris, since the sources
will include all such fixes.  Distributions may elect to issue binary
patches.
</para>
</sect3>
<sect3 id='_brickify' xreflabel='brickify'>
<title>brickify</title>
<para>
To render a system unbootable or otherwise unusable (a brick).  Causes
can be hardware or software, but in this document it usually means
improper installation or installation of broken bits; in these cases the
term &quot;warmbrick&quot; is also used.  Recovering from this condition usually
entails booting from alternate media.
</para>
</sect3>
<sect3 id='_CTF' xreflabel='CTF'>
<title>CTF</title>
<para>
Compact ANSI-C Type Format.  CTF is a debugging information format
similar to a subset of DWARF or STABS, but more efficient.  The
information is used by mdb, dtrace, and other facilities within Solaris.
</para>
</sect3>
<sect3 id='_consolidation' xreflabel='consolidation'>
<title>consolidation</title>
<para>
A set of related software components developed and delivered together.
An example is the <xref linkend='_ON' /> consolidation, which consists of the kernel,
libraries, and basic utility and server programs in OpenSolaris.  Other
consolidations deliver the windowing system, development tools,
application servers, and so on.
</para>
</sect3>
<sect3 id='_gate' xreflabel='gate'>
<title>gate</title>
<para>
The main or official <xref linkend='_workspace' /> for a <xref linkend='_project' /> or
<xref linkend='_consolidation' />.  This workspace is managed by the gatekeeper for the
project or consolidation, who performs regular builds, backs out
incorrect or nonconforming changes, and is responsible for either
integrating the sources into a parent gate or delivering regular builds
to the <xref linkend='_WOS' />, as appropriate.  After completing implementation and
review, a developer will <xref linkend='_putback' /> his or her changes to an
appropriate gate.  A gate is &quot;golden source,&quot; a shared resource expected
to be usable at all times.
</para>
</sect3>
<sect3 id='_lint' xreflabel='lint'>
<title>lint</title>
<para>
lint(1) is a utility used to perform various checks on source code.  All
new code in OpenSolaris must be &quot;lint-clean,&quot; meaning that lint's checks
on the code do not result in any warnings.  This process of checking
with lint(1) is known as linting.
</para>
</sect3>
<sect3 id='_Nevada' xreflabel='Nevada'>
<title>Nevada</title>
<para>
Nevada is the current (as of 2005) development version of Solaris
following Solaris 10.  OpenSolaris is based on the Solaris Nevada
sources.  The name Nevada was used instead of 10.1 or 11 because it was
not yet known whether this will be a micro or minor release; the initial
assumption was that it will be a micro release; therefore the RELEASE
was 5.10.1.  However, as of build 14, Nevada is now a Minor Release.
See attributes(5) and <xref linkend='_7_1_1_Interface_Stability_Taxo' /> for more
information about the difference between release types.
</para>
</sect3>
<sect3 id='_ON' xreflabel='ON'>
<title>ON</title>
<para>
The consolidation which delivers the OpenSolaris kernel, filesystems,
some drivers and other modules, basic commands, daemons and servers,
libraries, and system headers.  Also known as OS/Net or OS/Networking.
</para>
</sect3>
<sect3 id='_Platinum_Beta' xreflabel='Platinum Beta'>
<title>Platinum Beta</title>
<para>
A Sun beta program for customers that are willing and able to run beta
releases in production. These customers see features like ZFS months
or years before anyone else.
</para>
</sect3>
<sect3 id='_project' xreflabel='project'>
<title>project</title>
<para>
A collection of features and/or bug fixes which is extensive enough to
require its own implementation team, gate, and plans.  Examples of
projects are dtrace, Janus, and a port to a new hardware platform.
Normal individual enhancements and bug fixes are self-contained and
worked on by no more than one or two developers; these do not require
the infrastructure associated with projects.
</para>
</sect3>
<sect3 id='_putback' xreflabel='putback'>
<title>putback</title>
<para>
After all changes are checked in, tested, reviewed, and approved, a
developer integrates his or her changes into an appropriate gate.  The
word putback is used to refer to the set of changes itself and the act
of integrating it into the gate.
</para>
</sect3>
<sect3 id='_RFE' xreflabel='RFE'>
<title>RFE</title>
<para>
Request for Enhancement.  (Feature request.)
</para>
</sect3>
<sect3 id='_Solaris_Next' xreflabel='Solaris Next'>
<title>Solaris Next</title>
<para>
The generic term occasionally used to refer to a new development version
of Solaris, before it is known what type of release it will be.  As of
early 2005, Solaris Next would refer to <xref linkend='_Nevada' /> (Solaris 11).
</para>
</sect3>
<sect3 id='_source_patch' xreflabel='source patch'>
<title>source patch</title>
<para>
A set of diffs which describes a source code change.  Many Open Source
development efforts refer to this simply as a patch; however, see also
<xref linkend='_binary_patch' /> above.
</para>
</sect3>
<sect3 id='_suninstall' xreflabel='suninstall'>
<title>suninstall</title>
<para>
The standard Solaris installer.  A suninstall installation includes the
full <xref linkend='_WOS' /> and is done from CD or network.
</para>
</sect3>
<sect3 id='_SWAN' xreflabel='SWAN'>
<title>SWAN</title>
<para>
The Sun Wide Area Network, Sun's internal network.
</para>
</sect3>
<sect3 id='_TeamWare' xreflabel='TeamWare'>
<title>TeamWare</title>
<para>
The Source Code Management (SCM) software used internally at Sun for
Solaris development, abbreviated as &quot;TW&quot;.
</para>
</sect3>
<sect3 id='_Tonic' xreflabel='Tonic'>
<title>Tonic</title>
<para>
Internal code name for the OpenSolaris program.
</para>
</sect3>
<sect3 id='_UTS' xreflabel='UTS'>
<title>UTS</title>
<para>
UNIX Time Sharing.  The Solaris kernel codebase.
</para>
</sect3>
<sect3 id='_workspace' xreflabel='workspace'>
<title>workspace</title>
<para>
A workspace includes a full source tree as well as metadata such as log
files and version control information.
</para>
</sect3>
<sect3 id='_WOS' xreflabel='WOS'>
<title>WOS</title>
<para>
&quot;Wad Of Stuff,&quot; referring to the integration of all consolidations that
make up the Solaris binary distribution shipped to customers.
</para>
</sect3>
</sect2>
</sect1>
</appendix>
</book>
