Sun Java Solaris Communities My SDN Account Join SDN
 
Article

Building Software on the Solaris OS

 
By Rich Teer, October 2006  
Introduction

Since the availability of the Solaris 10 Operating System in January 2005, its popularity (using the number of registered users as a yardstick) has exploded: As of August 2006, in excess of 5 million copies were registered, more than all of the previous versions of the Solaris OS combined. Further fueling this frenzy was the release of OpenSolaris in June 2005. Given this surge in the number of users, more developers (commercial and open-source alike) are seeing the Solaris platform as a viable target for their software. This article explains why developers should make Solaris their primary development and deployment platform, and also explains how to develop software on the Solaris OS.

This article assumes that C will be used as the programming language of choice, although much of the information is relevant to other high-level languages. The discussion is aimed at two kinds of people:

  • Non-developers who just want to build their favorite (perhaps open-source) software on the Solaris platform
  • Developers (commercial and otherwise) who are porting their code to the Solaris OS (or are considering doing so)

The article also assumes the use of the Solaris 10 (or newer) release, although most of it is relevant to previous versions.

Why Develop on the Solaris Platform?

One of the reasons the Solaris OS enjoyed a huge popularity boost was its price: $0 for everyone, for any use (commercial and non-commercial), on any machine (using both SPARC and x86 platforms). Another reason was Sun's promise (and delivering on that promise) of making the Solaris source code available under an OSI-approved open-source license, the CDDL.

However, the most important reason for the popularity of the Solaris OS is arguably the vast wealth of features it offers. In no particular order, these include Solaris Zones (the ability to partition a machine into numerous virtual machines, each of which is isolated from the others), DTrace (a comprehensive dynamic tracing tool for investigating system behavior, safely on production machines), a new IP stack with vastly increased performance, and most recently, ZFS (a 128-bit, state-of-the-art file system, with end-to-end error checking and correction, a simple command-line interface, and virtually limitless storage capacity).

All these features build on what long-time Solaris OS users have come to expect: rock-solid stability, huge scalability, high performance, and guaranteed backwards compatibility. The last of these is especially important to commercial software developers, because maintenance is usually the largest expense associated with a piece of software. With its backwards compatibility guarantee, software vendors know that (provided they stick to published APIs) software built for Solaris N will run correctly on Solaris N+1 and subsequent versions. (Contrast this with some other operating systems, where incompatible changes to system components -- for example, libraries -- are made without regard to the effect on applications. The net effect is application breakage, resulting in increased maintenance costs and frustration for application vendors and users.)

The preceding paragraphs give some reasons why we should develop for the Solaris OS, but there are additional reasons to develop on the Solaris platform. One is that Solaris is a multiplatform OS, supporting both SPARC and x86 architectures (a community-driven port to Power is in the works, too). Although there was a hiccup a few years ago with the Solaris OS for x86 platforms, the fact that Sun has introduced a range of AMD-based servers and workstations demonstrates the company's commitment to x86 technology.

From the developer's perspective, the Solaris versions for SPARC and x86 platforms have the same feature set and APIs. This means that developers can concentrate on the other issues endemic to cross-platform development, like CPU endianness. The SPARC platform is big-endian and x86 is little-endian, so an application that is developed and tested on the Solaris platform has a high probability of being free from endian-related problems. The Solaris OS also supports both 32-bit and 64-bit applications on both platforms, thus helping to eliminate bugs due to assumptions about word size and so on.

Perhaps the most compelling reason to develop software on the Solaris OS is the wealth of professional-grade development tools available for it.

Development Tools on the Solaris Platform

Market-size issues aside, one of the most important features of an OS from a developer's point of view is the variety and quality of the development tools available. Compilers and debuggers are the most obvious examples of these tools, but other examples include code checkers (to ensure that our code is free from subtle errors the compiler might not catch), cross-reference generators (to see which functions reference other functions and variables), performance analyzers, and so on.

The Sun Studio 11 suite is the product of choice for Solaris OS developers. Available as a free download from the developers.sun.com, Studio 11 software is a collection of professional-grade compilers and tools. It includes C, C++, and FORTRAN compilers, code analysis tools, an integrated development environment (IDE), the dbx source-level debugger, editors, and so on.

Other tools included with Studio 11 software are cscope (an interactive source browser), ctrace (a tool to generate a self-tracing version of our programs), cxref (a C program cross-referencer), dmake (for distributed parallel makes), and lint (the C program checker -- historically also known as a C program defluffer!).

The Solaris OS ships with the GNU C compiler, gcc, and its companion source-level debugger, gdb. The Solaris OS also ships with the very powerful modular debugger, mdb. However, mdb is not a source-level debugger. It is most useful when we are debugging kernel code, or performing post-mortem analysis on programs for which the source is not available. See Solaris Modular Debugger Guide and Solaris Performance and Tools by McDougall, Mauro, and Gregg (in Bibliography) for more information about mdb.

In the author's experience, most (if not all) of the time, the Sun Studio compiler produces better (that is, faster) code than that generated by gcc, so the Sun Studio compiler should be used if at all possible. To ensure our code is portable between compilers, we should test that it compiles cleanly at the maximum warning level with both gcc and Sun's compiler (the Sun Studio C compiler, cc), before using the latter for the final production build. (The author finds it disheartening that many supposedly portable open-source projects rely on "gccisms" and cannot be compiled with Sun's compiler without a fair amount of work. It is the author's opinion that the fact that gcc is available on many platforms is no excuse for such poor engineering.)

Now that we've explored the reasons why we would choose Solaris as our primary development platform, let's explore how to actually go about doing so.

Building Software on the Solaris Platform

To successfully build software using the Solaris OS, we must first ensure that all the tools we need are installed on our development machine. This means that when we install the Solaris OS, we must select at least the "Developer" metacluster. (The "Full" or "Full + OEM" metaclusters, being supersets of the Developer metacluster, will also work and are probably the best option for people new to the Solaris OS.) An optional (but highly recommended) step is to install the Sun Studio 11 compilers and tools.

The next step is to make sure that our PATH is correctly set: /usr/ccs/bin is required for various tools (including the linker, ld, sccs, and make), and /usr/sfw/bin is required for gcc and its companion tools (this directory also contains numerous programs that are not directly related to development). If the Sun Studio tools are installed, their directory must also be in our PATH. By default, the Sun Studio tools are installed in /opt/SUNWspro/bin, so this directory (or wherever the Sun Studio tools were installed) must also be added to our PATH.

One problem that people new to the Solaris OS sometimes come across is the inclusion of /usr/ucb in their PATH. This directory contains programs that are used to provide compatibility for legacy SunOS 4.x applications and scripts. SunOS shipped with a C compiler, so /usr/ucb contains cc, which is a script that invokes the C compiler with command-line options suitable for generating programs that rely on BSD semantics and behavior. For modern applications, this is most likely not what we want, so it is important to make sure that /usr/ucb is after /usr/ccs/bin and /opt/SUNWspro/bin in our PATH (or perhaps even better, not in our PATH at all).

With the right software installed, and our PATH appropriately set, we're ready to start building programs. A program called make is used to build programs. It uses the concept of dependencies to determine which steps are required to produce the required results. For example, suppose our program consists of several C files, which we compile. All the files will be compiled and the resulting object files will be linked together. If we subsequently modify one of the source files, make will determine that only the modified file needs to be compiled, and will link the newly created object file with those from the previous build.

The rules and dependencies used to build our program are described in a file called Makefile, which the make program uses to determine its actions. However, make is pretty smart and has a number of built-in rules which it uses, even if there is no Makefile. One of these built-in rules describes how to create an executable program from a C source file, a fact we take advantage of in the following examples.

The file /usr/share/lib/make/make.rules contains the standard rules and definitions used by make, and contains entries for programs written in C, C++, FORTRAN, and Java, as well as some other languages. Some of the standard rules for programs written in C include:

  • Retrieving the source code from the SCCS source code control system
  • Using lint to inspect the source code for errors
  • Creating archive libraries (.a files)
  • Preprocessing the source code, leaving the output in files with a .i suffix

Let's look at a few examples, using the simple counter program shown in the following:

1 #include <stdio.h>
       
2 int main ()
3 {
4     int i;
       
5     for (i = 0; i < 10; i++)
6         printf ("i = %d\n", i);
       
7     return (0);
8 }

Example: Building With Sun's Compiler and make

Our first example runs Sun's make using the defaults:

rich@marrakesh4098# make counter
cc    -o counter counter.c 

Example: Building With Sun's Compiler and gmake

The next example runs GNU's version of make, gmake, using the defaults:

rich@marrakesh4100# gmake counter
cc     counter.c   -o counter

Notice that even though the arguments to cc are reversed, the end result is the same.

A detailed look at make is beyond the scope of this article, but we should note that the default rules for make (and gmake) use the CC environment variable to determine the name of the compiler. If CC is unset, cc is used by default. (Interested readers are referred to the respective manual pages for more details about make, gmake, and Makefiles.)

Example: Building With gcc and make

Our final example sets the CC variable before calling make:

rich@marrakesh4103# CC=gcc make counter
gcc    -o counter counter.c

Notice that this time, gcc is used to compile counter.c rather than cc (we can use a similar invocation with gmake if that is the build tool we want to use).

Linking With Libraries

Many programs, especially those that are more than moderate in size and complexity, link with libraries other than the default C library. These libraries either come with the Solaris OS, or are third-party libraries installed by the system administrator (be they commercially supplied, downloaded from places like Blastwave.org or Sunfreeware.com, or compiled locally).

We link with these libraries, which are also called shared objects, by passing the name of the library to the compiler with the -l flag. For example, to link with libfoo.so, we would use -lfoo. This works fine for system libraries that are installed under /usr/lib, but what about other libraries?

The correct place for these libraries to be installed is a library-specific location under /opt, although many sites still adhere to the deprecated practice of storing them under /usr/local (see the filesystem(5) man page for more about this). However, "somewhere under /opt" leaves a lot of room for interpretation, so we need to tell the linker where to find the libraries we want our program to use. We do this by passing the -L flag to the linker. For example, -L/opt/local/lib would tell the linker to look for libraries in /opt/local/lib in addition to the default locations.

The problem with -L is that it is only used when the program is linked. The loader needs to be able to find the libraries at runtime. The correct way to do this is to set the library run path, by passing the -R flag to the linker, using the same syntax as the -L flag. The incorrect way to do this is to set the LD_LIBRARY_PATH environment variable to the appropriate location. Unfortunately, a lot of software relies on this method of locating libraries. This problem is easily remedied for programs for which we have the source. We can simply edit the Makefile and rebuild it. For commercial applications, we must petition the vendor to build future versions of their programs correctly.

We should point out that there is one legitimate use of LD_LIBRARY_PATH: when we are developing a new version of a library. We can then use the environment variable to override the compiled-in run path. We can run our (correctly linked) programs with LD_LIBRARY_PATH unset, which will use the current version of the library, and then set it to our development area when we are ready to test the new version of the library. For the sake of emphasis, it is worth repeating that we should not set LD_LIBRARY_PATH in our session start-up scripts (for example, .profile or .login). If a program to which we do not have the source relies on LD_LIBRARY_PATH, we should write a wrapper script that sets it before invoking the desired program.

Summary

This article has described why developers (both commercial and open-source) should choose Solaris as their platform of choice, for both development and deployment. The reasons include:

  • The large number of people using the Solaris OS
  • The availability of Solaris as an open-source operating system, the source code for which is available under the OSI-approved CDDL
  • The wealth of advanced technological features the Solaris platform has, including DTrace, Solaris Zones, improved IP stack, and ZFS
  • The fact that Solaris is a multiplatform OS (SPARC and x86 currently, with others in the works)
  • Sun's commitment to long-term backwards compatibility for the Solaris OS, which protects the end users' investment in their software
  • The professional-quality development tools, some of which are available for no charge

We also described how to build software on the Solaris platform, using both Sun Studio compilers and gcc. We described how to install the Solaris OS in a manner suitable for software development, and how to ensure that our PATH is set correctly. We briefly discussed make and gmake. And we ended with a discussion about shared objects (dynamically linked libraries), and how to avoid runtime problems by not using LD_LIBRARY_PATH (unless we are developing a new version of a library).

Recommended Reading

The author's book, Solaris Systems Programming, published 2005, is considered essential for readers developing Solaris applications. Many books in the Solaris 10 Software Developer Collection are also worth reading or at least being aware of.

Bibliography

McDougall, Richard; Mauro, Jim; and Gregg, Brendan. Solaris Performance and Tools, ISBN 0-13-156819-1. Prentice Hall PTR, 2007.

Oram, Andrew, and Talbott, Steve. Managing Projects with make, ISBN 0-937175-90-0. Sebastopol, Calif.: O'Reilly and Associates, 1991.

Solaris Modular Debugger Guide. Sun Microsystems, 2002.

Teer, Rich. Solaris Systems Programming, ISBN 0-201-75039-2. Prentice Hall PTR, 2005.

About the Author

Rich Teer is an independent Solaris consultant who has been an active member of the Solaris community for more than 10 years. He is the author of the best-selling Sun Microsystems Press book, Solaris Systems Programming, and numerous Solaris OS-related articles. He was a member of the OpenSolaris pilot program and currently serves on the OpenSolaris Community Advisory Board (CAB). Rich lives in Kelowna, British Columbia, with his wife, Jenny. His web site can be found at http://www.rite-group.com/rich.

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.