Boost logo

Boost :

From: Jens Seidel (jensseidel_at_[hidden])
Date: 2008-01-14 03:31:03


On Mon, Jan 14, 2008 at 01:16:51AM -0500, Gennadiy Rozental wrote:
> "Benoit Sigoure" <tsuna_at_[hidden]> wrote in message
> news:805924BB-31B0-44E8-88CE-9538D89B082C_at_lrde.epita.fr...
> > On Jan 12, 2008, at 3:26 AM, Gennadiy Rozental wrote:
> >
> >> Benoit Sigoure <tsuna <at> lrde.epita.fr> writes:
> >>> Thanks for your code. It grieves me that Boost.Test is the *only*
> >>> library for which I have to write "special cases" only because it's
> >>> not "well-behaved".
> >>
> >> In what sence? How do you define well behaved?
> >
> > What is this whole thread about? Boost.Test is non standard because
> > it messes up your `main'
>
> Why do you care? how does it make Boost.Test behave badly?

Normally one is able to test for the existence of a library by just
calling a function inside main() or by creating an instance of a special
type:

#include <required_lib_header.h>

int main(int argc, char* argv[])
{
  double a = function_from_lib();
  type_in_lib object;
}

If this links successfully (using current compiler flags maybe after
extented with -l <libname>) one can be sure that the library is
properly installed. This is a very common task. That's why Autoconf
provides a macro AC_TRY_LINK which expects the arguments "#include
<required_lib_header.h>" and the body of main.

A example of one of my configure.ac files (the last two arguments
specify the code used if the linkage works or not, resp., I nested it):
AC_TRY_LINK([#include <math.h>],
            [double f=3.14; return isnan(f);],,
            [AC_TRY_LINK([#include <math.h>
                          int __isnand(double x) { return x != x; }],
                         [double f=3.14; return isnan(f);],
                          AC_DEFINE(NEED___ISNAND, 1, [Use own
implementation of __isnand (cygwin)]))])
 
Beeing forced to also write

int main(int argc, char* argv[])
{

}

is just not required for nearly all library tests and error prone. This
is probably the argument of Benoit. He also wrapped AC_TRY_LINK to
simplify his tests (it is necessary to test all library variants
(multithreaded or not, ...) so a own macro makes sense) and expects a
single header file name only. See e.g. the following excerpt of
boost.m4:

# BOOST_WAVE([PREFERRED-RT-OPT])
# ------------------------------
# Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the
# documentation of BOOST_FIND_LIB above.
AC_DEFUN([BOOST_WAVE],
[BOOST_FIND_LIB([wave], [$1],
                [boost/wave.hpp],
                [boost::wave::token_id id; get_token_name(id);])])

There is in general no guarantee that a single header file is sufficent
for a test but it worked for all other Boost libraries as well. That's
why he was looking for the most simple test.

> > and must be used differently whether you're
> > linking with it as a shared library or a static archive.
>
> As you have seen in my example, it is exactly the same for both usage
> variants. The only difference is additional macro in makefile. But, than,
> link command is going to be different anyway.

No, you're wrong. There is no need to specify different link commands
for shared or static libraries in general.

I tried to compile your proposed test:

#define BOOST_TEST_MODULE boost.m4
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE( MyCase )
{
  BOOST_ERROR( "expected" );
}

Normally (for at least 95% of all libraries) one just adds -l <libname>
to get it compile:

$ g++ test.cpp -lboost_unit_test_framework
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: ld returned 1 exit status

It works indeed well with
$ g++ -DBOOST_TEST_DYN_LINK test.cpp -lboost_unit_test_framework

Once I remove /usr/lib/libboost_unit_test_framework.so so that only
the static library /usr/lib/libboost_unit_test_framework.a (which is a
symbolic (filesystem) link to
libboost_unit_test_framework-gcc41-1_34_1.a in Debian testing) exists
one can also (normally) just specify -l <libname>. But I get:

$ g++ -DBOOST_TEST_DYN_LINK test.cpp -lboost_unit_test_framework
/tmp/ccKcB2Ps.o: In function `main':
test.cpp:(.text+0x3d4): undefined reference to `boost::unit_test::unit_test_main(bool (*)(), int, char**)'
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/libboost_unit_test_framework.a(framework.o): In function `boost::unit_test::framework::init(int, char**)':
(.text+0x6fa): undefined reference to `init_unit_test_suite(int, char**)'
collect2: ld returned 1 exit status

Without -DBOOST_TEST_DYN_LINK
$ g++ test.cpp -lboost_unit_test_framework
it works.

You're right that it is also possible to enforce using the static
library (even if the shared one exists) by using different arguments:
$ g++ test.cpp /usr/lib/libboost_unit_test_framework.a

But in general everyone probably just uses -l <libname> and let's the
compiler decide (which defaults to shared library variant if available).
This normally works even if only one variant of a library is installed
except with Boost.Test.

Jens


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk