Build environment used
======================
OS: Oracle Solaris 11 Update 1 (S11.1)
Compilers:
cc: Sun C 5.10 SunOS_i386 Patch 142363-07 2010/12/09
CC: Sun C++ 5.10 SunOS_i386 128229-12 2011/01/19
lint: Sun C 5.10 SunOS_i386 Patch 142363-07 2010/12/09
java full version "1.6.0_33-b03"
as: Sun Compiler Common 12 SunOS_i386 s11u1_19 06/12/2012
dmake: Sun Distributed Make 7.9 SunOS_i386 2009/06/03
cc: Sun C 5.10 SunOS_sparc Patch 141861-07 2010/12/09
CC: Sun C++ 5.10 SunOS_sparc 128228-12 2011/01/19
lint: Sun C 5.10 SunOS_sparc Patch 141861-07 2010/12/09
java full version "1.6.0_33-b03"
as: Sun Compiler Common 12 SunOS_sparc s11u1_19 06/12/2012
dmake: Sun Distributed Make 7.9 SunOS_sparc 2009/06/03
from <http://hub.opensolaris.org/bin/view/Community+Group+on/devref_4>
======================================================================
1 Environment Variables
-----------------------
This section describes a few of the environment variables that affect all ON builds, regardless of the build method. See Section 2 "Using nightly and bldenv" for information on environment variables and files that affect nightly(1) and bldenv(1).
CODEMGR_WS
This variable 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.
Originally, CODEMGR_WS was defined by TeamWare. Over time, ON's build tools have come to depend on it, so we continue to use it with Mercurial.
SRC
This variable must be set to the root of the 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.
MACH
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:
Good:
MACH=`/usr/bin/uname -p`
Bad:
MACH=sparc
ROOT
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.1 for more information on the proto area. If bldenv(1) is used, this variable will be set to ${CODEMGR_WS}/proto/root_${MACH}.
PARENT_ROOT
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.
MAKEFLAGS
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 "e". 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.
SPRO_ROOT
This points to the top of the installed compiler tree. People outside Oracle will normally set this to /opt/SUNWspro. You can see how this works by looking at usr/src/Makefile.master. But if you need to override the default, you should do so via the environment variable. Note that opensolaris.sh already sets SPRO_ROOT to /opt/SUNWspro.
SPRO_VROOT
The 'V' stands for version. At Oracle, multiple versions of the compilers are installed under ${SPRO_ROOT}
to support building older sources. The compiler itself is expected to be in ${SPRO_VROOT}/bin/cc
, so you will most likely need to set this variable to /opt/SUNWspro. Note that opensolaris.sh has this variable already set to this value.
GNU_ROOT
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 /usr/sfw. Although it is not recommended, you can use a different gcc by setting this variable to the gcc install root. See usr/src/Makefile.master for more information.
__GNUC, __GNUC64
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 enables the use of gcc to build the corresponding binaries. Setting them to '#' 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).
CLOSED_IS_PRESENT
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).
ON_CLOSED_BINS
If the closed source tree is not present, this variable points to the tree of unpacked closed binaries.
2 Using nightly and bldenv
--------------------------
There are many steps in building any consolidation; ON's build process entails creation of the proto area, compiling and linking binaries, generating 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.
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.
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.
After each run, nightly(1) will leave a detailed log of the commands it ran and their output. This log is normally located in $CODEMGR_WS/log/log.YYYY-MM-DD.HH:MM/nightly.log, where YYYY-MM-DD.HH:MM is a timestamp, but can be changed as desired. If such a log already exists, nightly(1) will rename it for you.
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 effects your changes, if any, have 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:
< 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'
Note the '<' - this means this output was for the previous build. If the output is prefaced with '>', 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.
2.1 Options
-----------
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.
2.2 Using Environment Files
---------------------------
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 below in Section 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.
2.3 Variables
-------------
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).
* NIGHTLY_OPTIONS
* CODEMGR_WS
* CLONE_WS
* STAFFER
* MAILTO
* ON_CRYPTO_BINS
* MAKEFLAGS
2.4 DEBUG and Non-DEBUG Builds
------------------------------
The ON sources contain additional debugging support and self-checks (assertions) that can be enabled by doing a DEBUG build. This makes the binaries larger and slower, but unless you are running on older hardware, you are unlikely to notice the difference. Benchmarking should only be done with non-DEBUG builds.
Non-DEBUG binary deliverables (e.g., closed binaries) are usually tagged with "-nd" in the file name. If you are unsure as to which you have, the kernel will say when it boots if it is a DEBUG kernel. Non-DEBUG closed binaries unpack into closed/root_$MACH-nd; DEBUG closed binaries unpack into closed/root_$MACH. In the source tree, non-DEBUG kernel objects live in "objNN" (e.g., "obj64" or "obj32") directories, while DEBUG kernel objects live in "debugNN" directories.
When building with nightly(1), you can specify a DEBUG build, a non-DEBUG build, or both, by setting the appropriate flags in NIGHTLY_OPTIONS. Note that "D" turns on the DEBUG build, while "F" turns off the non-DEBUG build.
By default, nightly(1) will reuse the proto area (described in Section 4.1 Proto Area) for both the DEBUG and non-DEBUG builds. (This is done to save space.) You can tell nightly(1) to put the non-DEBUG build in a separate proto area by setting the MULTI_PROTO environment variable to "yes". In that case, the (default) DEBUG proto area will be ${CODEMGR_WS}/proto/root_${MACH}, and the (default) non-DEBUG proto area will be ${CODEMGR_WS}/proto/root_${MACH}-nd. Be careful about extracting binaries--especially kernel modules--by hand from the proto area. It doesn't always work to mix DEBUG and non-DEBUG kernel modules.
When building with bldenv(1), you can build either DEBUG binaries or non-DEBUG binaries, but not both at the same time. bldenv(1) is not smart enough to look at NIGHTLY_OPTIONS to determine the build type; see CR 6414851 for details. Instead, bldenv(1) defaults to a non-DEBUG build. Use "bldenv -d" to get a DEBUG build.
3 Using Make
------------
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 workspace, it is advantageous to build and install only the kernel during intermediate testing.
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 ection 4.2 "Using nightly and bldenv" for more information on this command.
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 Solaris 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.
The entire uts directory allows you to run make commands in a particular build subdirectory 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 should generally work without any problems.
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.
Here are the generic targets:
all
Build all derived objects in the object directory.
install
Install derived objects into the proto area defined by ${ROOT}.
install_h
Install header files into the proto area defined by ${ROOT}.
clean
Remove intermediate object files, but do not remove "complete" derived files such as executable programs, libraries, or kernel modules.
clobber
Remove all derived files.
check
Perform source-specific checks such as source and header style conformance.
lint
Generate lint libraries and run all appropriate lint passes against all code which would be used to build objects in the current directory.
4 Build Products
----------------
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 can be used to construct a kernel installation archive directly from a fully-built usr/src/uts.
Section 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.2 describes the construction of the package tree for ON deliverables.
4.1 Proto Area
--------------
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. Normally nightly(1) and bldenv(1) will set ROOT for you. The usual value for ROOT is ${CODEMGR_WS}/proto/root_${MACH}, though it may be different for non-DEBUG builds.
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.
If you're checking a current ON workspace, then you can simply build the protocmp make target in usr/src/pkg:
$ bldenv solaris.sh
$ cd $SRC/pkg
$ dmake protocmp
Otherwise, you may invoke protocmp directly.
protocmp does not include a man page. Its invocation is as follows:
protocmp [-gupGUPlmsLv] [-e <exception-list> ...] -d <protolist|pkg dir>
[-d <protolist|pkg dir> ...] [<protolist|pkg dir>...]|<root>]
Where:
-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 SVr4 packaging directory to check
-e <file>: exceptions file
-L : list filtered exceptions
-v : verbose output
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.
A protolist is a text file with information about each file in a proto area or package manifest, 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.
For a current ON workspace, you can generate a protolist corresponding to the package manifests by building the protolist make target in usr/src/pkg:
$ bldenv opensolaris.sh
$ cd $SRC/pkg
$ dmake protolist
This will generate the file $SRC/pkg/protolist_`uname -p`.
You can generate protolists from a proto area with the protolist command, which also does not include a man page. Its invocation is as follows:
$ protolist <protoroot>
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.
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.
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.
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 2 for more information on automating proto comparison as part of your automatic build.
In addition to the protolist and protocmp build targets described above, as a shortcut to using protolist and protocmp, you can use the 'checkproto' command found in the developer/opensolaris/onbld package. This utility does not include a man page, but has a simple invocation syntax:
$ checkproto [-X] <workspace>
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.
You can find the sources for protolist, protocmp, and checkproto in usr/src/tools. The resulting binaries are included in the developer/opensolaris/onbld package.
4.2 Packages
------------
The -p option to nightly will package the files that were installed into your proto area. If your workspace contains the directory usr/src/pkgdefs, this will result in SVr4 packages. If instead it contains usr/src/pkg, it will produce an IPS package repository. In either case, this is done automatically by the main makefile's all and pkg_all targets (see usr/src/Makefile) as part of a successful build. SVr4 packages or IPS package repositories are placed in ${CODEMGR_WS}/packages. See nightly(1) and section 2 for more information on automating package construction as part of your automatic build.