Boost logo

Boost Users :

From: Matt England (mengland_at_[hidden])
Date: 2006-04-02 16:54:30


Summary:

I'm managing a newly-open-sourced project, and I'm looking to accomplish
these goals:

1) Ensure the source packages can build on all systems
2) Ensure the application (binary) packages run on all supported systems
3) Ensure libraries we deliver integrate properly with other software projects

Any feedback or guidance from this community would be greatly
appreciated. I provide further details, as well as more-specific
questions, below.

Details:

I manage a significant, C++ based software project that is on the verge of
presenting an open-source format. Up until now, my group had tight control
on the systems/environments (mostly Windows-MinGW, RHEL, Fedora, and Debian
to this point) for which we built and tested our software. No longer; we
now believe we have to support most of the worlds' systems, representing a
set of very heterogeneous environments, and that's not trivial.

I'm looking for feedback and guidance on what tools and paradigms are
available to my C++ based, open-source project to best ensure consistent
cross-platform build and execution capability. I provide my research
findings and general understanding of the issues below. Thanks in advance
for any help.

(I plan on posting this note in a couple different email lists, forums, and
newsgroups. Please forgive me if my post is not appropriate for your
community. For what it's worth, I have found it difficult reaching a
conclusion for this cross-platform-software-distribution issue, and I think
it best to query several different communities involved with this stuff and
get their combined take on the matter.)

I break this issue down into these goals:

1) Ensure the source packages can build on all systems
2) Ensure the application (binary) packages run on all supported systems
3) Ensure libraries we deliver integrate properly with other software projects

I write more details, including associated questions, for each one of these
goals in 3 different sections of my note below.

I'm looking for the best and/or most-accepted ways to solve these
problems. I've done a little research (coupled with my many years of
user/developer experience with similar systems facing the same problems),
and the following notes reflect what I've come up with thus far.

For what it's worth: our project has taken extreme care to create portable
and modular C++ code and to use only the most-common and highly-portable
libraries. We feel that our problem lies not in making our code more
portable, but rather making our build process and our binary-distribution
systems more portable.

------------------------------------------------------------------
---- 1) Ensure the source packages can build on all systems ------
------------------------------------------------------------------

The target stakeholder for this problem seems to be one of:

a) user looking to build binaries from source, or
b) a developer looking to modify the source for some reason, or
c) some combination thereof.

While this stakeholder set may be more knowledgeable and experienced then a
general "binary-only" user, I still believe an automated system needs to
check the build environment to make sure it's suitable to build my software
package.

This task appears to be centered on 2 basic issues:

* Check that a proper compiler-and-linker system exists with all the
appropriate system headers and libraries
* Check availability and compatibility of "external" libraries and their
headers

Am I missing anything here?

For what it's worth: the external libraries (besides "standard" system
libraries) that we currently use include but may not be limited to the
following: various Boost-C++ libraries, OpenSSL, BZip2, libpqxx, Xerces-c,
and optionally ACE (<http://www.cs.wustl.edu/~schmidt/ACE.html>), libcurl,
and xmlrpc-c.

Up until now, we were including each library (and its associated header
files) from the above toolset in a Subversion-controlled "external"
directory for each platform (eg, one for MinGW, Fedora, RHEL, Debian,
etc). However, we're finding that some boost libs don't work for all
debian3.1 systems, etc. I suspect we are going to run into this problem
more and more over time, and as such we need to let system in question
provide the library that's compatible with said system (in the
aforementioned case: let Debian's apt download/build the right boost
library). Is my understanding correct?

My project also uses an extensive and modular GNU-make Makefile system
based on a core Makefile we authored that builds rules dynamically (by
heavily leveraging the $(eval) function in make) based up on
per-application "input" Makefiles. Further, we do not hard-code lists of
source files in our Makefiles, for we auto-find the source files in each
application or library subdirectory on the fly; therefore, when one adds or
removes source-code files to our repos (we use Subversion, although it may
not matter that much), we require no changes to the Makefiles. This system
has served us well, and we're not inclined to move away from this system
unless absolutely necessary. (And if we want to support single-source
control of all build processes, even with non-MinGW Windows systems, we
might have to move away from this to something like bakefile or CMake...but
more on this in a minute.)

However, I doubt the Makefile system will be robust enough to handle the
nuances of truly cross-platform builds; maybe that's an
understatement. The tried-and-true tool to address this seems to be
autoconf, and I'm currently gearing myself up to author some autoconf-based
control files. However, autoconf does not appear to address non-MinGW
Windows environments. For that reason, my project is currently supporting
only MinGW in Windows environments. However, I'd like to be able to
"single-source control" the build process for non-autoconf-supported
systems like VisualStudio systems (and to a lesser extent CodeBlocks,
Dev-C++, etc...although they are a safer bet to read GNUmake Makefiles) in
the future. bakefile is the only thing that I've seen that yet supports
this approach. CMake (CMake?) might, but I'm not sure about VStudio;
further, CMake requires that all my developer-users change their usage
patterns (from './configure && make && make install') and to build and use
CMake...and I'm not yet inclined to change this paradigm.

A note about autoconf: I'm hoping it provides a *supplement* to my
existing Makefile system, instead of replacing such system with new,
auto-generated makefiles, etc. (For this and possibly other reasons I'm
steering clear of using automake, as per experiences like these:
<http://subversion.tigris.org/hacking.html#configury>). I'm a control
freak about my build-control process, and I don't want some automated tool
specifying what my build rules and dependencies are. Rather, I want
autoconf (or some tool that replaces it) to simply make sure that the build
environment (on said machine) is sufficient and then set the make variables
accordingly as inputs to my existing make/Makefile process. Is this the
way it works...or at least can work...with autoconf? Another way to ask
this: can autoconf essentially be made a "slave" to the Makefile.in file?

------------------------------------------------------------------
------ 2) Ensure the app packages run on all supported systems ---
------------------------------------------------------------------

The target stakeholder here seems to be: A "binary-only" user that simply
needs to install the package and have it run, no fuss, no muss.

This seems to boil down address this problem (or set of problems): making
sure that all the shared-object/DLL library and other binary dependencies
(like having a PostgreSQL or MySQL system installed if the system stores
data in a database like ours does) are satisfied for the target operating
system (and can be referenced in the appropriate binary/library "lookup"
paths). And if said libraries/binaries/software can not be found,
auto-downloading and installing them if necessary.

Mechanisms like Fedora's yum, RHEL's up2date (hopefully I didn't get those
mixed up), Debian's apt, *BSD's pkg, Solaris' pkg, etc, all seem to handle
this with more or less sufficient capability. (Eg, an .rpm ".spec" file
will map out the necessary rpm dependencies on a fedora/reel system.)
Assuming they do, a couple questions:

* Is there ever a time when I should package the binary libraries or
binaries for external products (eg, OpenSSL, PostgreSQL) for my project's
binary distribution?
* Do tools exist where I can write one "control spec" for all the above
auto-package toolsets instead of having to write a different spec for each
of .rpm, .deb, BSD-pkg, etc?

Separately: what does one do about Windows? What about other "non-Unix"
operating systems like VMS?

Do .msi-like installation packages do the work that of Debian's apt in that
said system will automatically download missing library dependencies? I
highly doubt it. Must my project include all the binary packages for my
external libs/bins (eg, OpenSSL, PostgreSQL) in these distributions? (For
what it's worth, our project currently supports MinGW-based Windows
distributions of our stuff.)

An additional note/question about "common" Linux binaries:

For Linux flavors of my binary distribution, I'd like to be able to support
a "build once, support many" paradigm. ie, if I could make one binary to
support many different Linux distributions (Fedora, Debian, RHEL, SuSE,
Mandiva/Mandrake, etc) and many different versions of each distribution (FC
1, 2, 3, 4, 5), I feel like I could save myself a lot of headache running
different builds on all these platforms. At the very least, I'd like to
not have to make a different build for every single Fedora flavor.

Alas, I suspect this boils down to which "native, Linux-system" libraries
does my app/apps/libraries depend on? Is there implicit kernel-level
dependence in this scenario? Is it more then libc/libc++/etc? Where can I
read more about this? This is the area for which I'm least experienced and
knowledgeable.

To be clear: I still want to make separate, "native," .rpm and .deb
packages (and any other packages I need to support for Linux distros), but
if they could all use the same underlying binary...and we could do this
reliably and consistently with no problems...it would seem to make our life
a lot easier. I see mature projects (like CMake) use one binary tarball
(again, I'm not saying I'm going to distribute in a tarball-only fashion)
for all Linux distros, so I'm hopeful this can be done.

------------------------------------------------------------------
-- 3) Ensure our libraries integrate w/ other software projects --
------------------------------------------------------------------

We want to provide the core functionality of our project's technology as an
"embed-able" library (either in static or dynamic-shared-object/dll fashion).

The libtool section of the autoconf manual
(<http://www.gnu.org/software/autoconf/manual/index.html>), quoted below,
appears to sum up the issues surrounding this...I guess. I have to take
libtool's word for it, for I have to experience the library distribution
problems in our project that libtool says will happen. But if this helps,
then we'll do it. Do any alternatives exist?

But what do we do in non-MinGW Windows environments (assuming libtool works
with MinGW-based systems at all)? Is there where the Windows' dlltool and
similar tools come in? Can anyone point me to good reading for this on the
web or elsewhere?

The libtool quote as promised:

"2.2 Libtool

Very often, one wants to build not only programs, but libraries, so that
other programs can benefit from the fruits of your labor. Ideally, one
would like to produce shared (dynamically linked) libraries, which can be
used by multiple programs without duplication on disk or in memory and can
be updated independently of the linked programs. Producing shared libraries
portably, however, is the stuff of nightmares; each system has its own
incompatible tools, compiler flags, and magic incantations. Fortunately,
gnu provides a solution: Libtool.

Libtool handles all the requirements of building shared libraries for you,
and at this time seems to be the only way to do so with any portability. It
also handles many other headaches, such as: the interaction of Makefile
rules with the variable suffixes of shared libraries, linking reliably with
shared libraries before they are installed by the superuser, and supplying
a consistent versioning system (so that different versions of a library can
be installed or upgraded without breaking binary compatibility)."

-Matt

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe_at_[hidden]
For additional commands, e-mail: users-help_at_[hidden]


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net