cgal/Documentation/doc/Documentation/Developer_manual/Chapter_portability.txt

395 lines
12 KiB
Plaintext

/*!
\page devman_portability Portability Issues
\author Michael Hoffmann (<TT>hoffmann@inf.ethz.ch</TT>)
\author Stefan Schirra
\author Sylvain Pion
This chapter gives an overview of issues related to the
configuration of \cgal that allow you to answer such questions as:
<UL>
<LI>Is \em LEDA / \gmp there? (Section \ref secleda_gmp_support)
<LI>Which compiler is this? (Section \ref secwhich_compiler )
<LI>Does the compiler support feature X? (Section \ref secworkaround_flags )
</UL>
Also addressed here are issues related to writing code for
non-standard-compliant compilers. Compilers have made a lot of progress toward
the \cpp-standard recently. But still they do not fully implement it. There
are a few features you may assume; others you may not
assume. Especially you may assume that the compiler
<UL>
<LI>supports namespaces
<LI>supports member templates
<LI>support for <TT>std::iterator_traits</TT>.
</UL>
Still, there are many bugs (sometimes known as "features") left in the
compilers. Have a look at the list of (non-obsolete) workarounds in
Section \ref secworkaround_flags to get an idea of which "features" are
still present.
\section secleda_gmp_support Checking for LEDA or GMP support
In the makefiles included for the compilation of every \cgal program
(<I>i.e.</I>, those to which the environment variable <TT>CGAL_MAKEFILE</TT> refers),
we define command line switches that set the flags
\code{.cpp}
CGAL_USE_LEDA, CGAL_USE_GMP
\endcode
iff \cgal is configured with \leda or GMP support, respectively.
\section secboost_support Using Boost
\cgal code can rely on Boost libraries to some extent.
Boost was shipped with \cgal Release 3.1, and is no longer
shipped within \cgal, as it is mainstream, and already distributed
with Linux and Cygwin.
Since portability and backward compatibility are a concern in \cgal,
we have decided that the list of Boost libraries usable in \cgal will be
decided by the \cgal editorial board. The requirements are higher
when it appears in the user visible interface than when Boost code
is used only internally. Requirements are lower for code that
is not released such as the test-suite. Boost libraries already accepted
in the C++ Standard Library Technical Report will be the first easy
candidates (these are marked <TT>[TR1]</TT> in the list below). However,
wrapping the use within \cgal is generally advised (like what is done
in the `cpp11` namespace).
Finally, the policy is that if a better alternative exists in Boost and is
allowed, then \cgal code must use it instead of a \cgal version (which
probably must be deprecated and phased out), trying not to break backward
compatibility too much.
A list of reasonable Boost libraries to use in the \cgal API is
Graph, Optional, Parameter (for packages already using it),
Property Map, Smart Pointers (for packages already using it),
Variant.
Before using a Boost libraries internally, first check whether it is already
used, and if not indicate it while submitting your changes (feature, small-feature
or pull request), or even by sending an email to cgal-develop during the development.
\section secusing_version_macros Using the version-number and configuration macros and flags
Here is a short example on how these macros can be used. Assume you have some
piece of code that depends on whether you have \leda-4.0 or later.
\code{.cpp}
#ifdef CGAL_USE_LEDA
#include <LEDA/basic.h>
#endif
#if defined(CGAL_USE_LEDA) && __LEDA__ >= 400
... put your code for LEDA 4.0 or later ...
#else
... put your code for the other case ...
#endif
\endcode
\section secwhich_compiler Identifying compilers and architectures
Every compiler defines some macros that allow you to identify it; see
the following table.
<TABLE BORDER=2><TR><TD>
<TABLE CELLSPACING=5 >
<TR>
<TD ALIGN=LEFT NOWRAP>
GNU 3.2.1
<TD ALIGN=LEFT NOWRAP>
`__GNUC__`
<TD ALIGN=LEFT NOWRAP>
3
<TR>
<TD ALIGN=LEFT NOWRAP>
GNU 3.2.1
<TD ALIGN=LEFT NOWRAP>
`__GNUC_MINOR__`
<TD ALIGN=LEFT NOWRAP>
2
<TR>
<TD ALIGN=LEFT NOWRAP>
GNU 3.2.1
<TD ALIGN=LEFT NOWRAP>
`__GNUC_PATCHLEVEL__`
<TD ALIGN=LEFT NOWRAP>
1
<TR>
<TD ALIGN=LEFT NOWRAP>
Microsoft VC7.1
<TD ALIGN=LEFT NOWRAP>
`_MSC_VER`
<TD ALIGN=LEFT NOWRAP>
1310
<TR>
<TD ALIGN=LEFT NOWRAP>
Microsoft VC8.0
<TD ALIGN=LEFT NOWRAP>
`_MSC_VER`
<TD ALIGN=LEFT NOWRAP>
1400
<TR>
<TD ALIGN=LEFT NOWRAP>
Intel 11.1
<TD ALIGN=LEFT NOWRAP>
`__INTEL_COMPILER`
<TD ALIGN=LEFT NOWRAP>
1110
<TR>
<TD ALIGN=LEFT NOWRAP>
Clang 2.9
<TD ALIGN=LEFT NOWRAP>
`__clang_major__`
<TD ALIGN=LEFT NOWRAP>
2
<TR>
<TD ALIGN=LEFT NOWRAP>
Clang 2.9
<TD ALIGN=LEFT NOWRAP>
`__clang_minor__`
<TD ALIGN=LEFT NOWRAP>
9
<TR>
<TD ALIGN=LEFT NOWRAP>
SUN 5.3
<TD ALIGN=LEFT NOWRAP>
`__SUNPRO_CC`
<TD ALIGN=LEFT NOWRAP>
0x530
<TR>
<TD ALIGN=LEFT NOWRAP>
SUN 5.10
<TD ALIGN=LEFT NOWRAP>
`__SUNPRO_CC`
<TD ALIGN=LEFT NOWRAP>
0x5100
</TABLE>
</TABLE>
There are also flags to identify the architecture.
<TABLE BORDER=2><TR><TD>
<TABLE CELLSPACING=5 >
<TR>
<TD ALIGN=LEFT NOWRAP>
SGI
<TD ALIGN=LEFT NOWRAP>
`__sgi`
<TR>
<TD ALIGN=LEFT NOWRAP>
SUN
<TD ALIGN=LEFT NOWRAP>
`__sun`
<TR>
<TD ALIGN=LEFT NOWRAP>
Linux
<TD ALIGN=LEFT NOWRAP>
`__linux`
</TABLE>
</TABLE>
\section secproblems_and_workarounds Known problems and workarounds
For (good) reasons that will not be discussed here, it was decided to
use \cpp for the development of \cgal. An international standard for
\cpp has been sanctioned in 1998 \cgalCite{cgal:ansi-is14882-98} and the
level of compliance varies widely between different
compilers, let alone bugs.
\subsection secworkaround_flags Workaround flags
In order to provide a uniform development environment for \cgal that
looks more standard compliant than what the compilers provide, a number
of workaround flags and macros have been created. Some of the
workaround macros are set in `<CGAL/config.h>`.
using the macros
listed in Section \ref secwhich_compiler to identify the compiler.
But most of them are set in the platform-specific configuration files
<CENTER>
<TT><CGAL/config/</TT><I>os-compiler</I><TT>/CGAL/compiler_config.h></TT>
</CENTER>
where <I>os-compiler</I> refers to a string describing your
operating system and compiler that is defined as follows.
<CENTER>
<I>`<arch>_<os>-<os-version>_<comp>-<comp-version>`</I>
</CENTER>
<DL>
<DT><B>`<arch>`</B><DD> is the system architecture as defined by <TT>uname -p</TT> or <TT>uname -m</TT>,
<DT><B>`<os>`</B><DD> is the operating system as defined by <TT>uname
-s</TT>,
<DT><B>`<os-version>`</B><DD> is the operating system version as defined by
<TT>uname -r</TT>,
<DT><B>`<comp>`</B><DD> is the basename of the compiler executable (if it
contains spaces, these are replaced by "-"), and
<DT><B>`<comp-version>`</B><DD> is the compiler's version number (which
unfortunately can not be derived in a uniform manner, since it is
quite compiler specific).
</DL>
Examples are <TT>mips_IRIX64-6.5_CC-n32-7.30</TT> or <TT>sparc_SunOS-5.6_g++-2.95</TT>.
For more information, see the \cgal \link usage usage guide \endlink.
This platform-specific configuration file is created during
installation by the script <TT>install_cgal</TT>. The flags listed below
are set according to the results of test programs that are compiled and run.
These test programs reside in the directory
<CENTER>
<TT>$(CGAL_ROOT)/config/testfiles</TT>
</CENTER>
where <TT>$(CGAL_ROOT)</TT> represents the installation directory for the library.
The names of all testfiles, which correspond to the names of the flags,
start with <TT>CGAL_CFG_</TT> followed by
<UL>
<LI><I>either</I> a description of a bug ending with
<TT>_BUG</TT>
<LI><I>or</I> a description of a feature starting with
<TT>NO_</TT>.
</UL>
For any of these files a corresponding flag is set in the
platform-specific configuration file, iff either compilation or execution
fails. The reasoning behind this sort of negative scheme is that on
standard-compliant platforms there should be no flags at all.
Currently (CGAL-3.4-I-181), we have the following configuration
test files (and flags). The short descriptions that are given in the files are
included here. In some cases, it is probably necessary to have a look at the
actual files to understand what the flag is for. This list is just to
give an overview.
Be sure to have a look at <TT>Installation/config/testfiles/</TT> to have an
up-to-date version of this list.
<DL>
<DT><B><TT>CGAL_CFG_LONGNAME_BUG</TT></B><DD>
This flag is set if a compiler (or assembler or linker) has problems
with long symbol names.
<DT><B><TT>CGAL_CFG_NET2003_MATCHING_BUG</TT></B><DD>
This flag is set, if the compiler does not match a member definition
to an existing declaration. This bug shows up on VC 7.1 Beta
(`cl1310`).
<DT><B><TT>CGAL_CFG_NO_LIMITS</TT></B><DD>
This flag is set if a compiler does not know the limits.
<DT><B><TT>CGAL_CFG_NO_LONG_LONG</TT></B><DD>
The `long long` built-in integral type is not part of the
\iso C++ standard, but many compilers support it
nevertheless, since it is part of the \iso C standard. This
flag is set if it is supported.
<DT><B><TT>CGAL_CFG_NO_TMPL_IN_TMPL_PARAM</TT></B><DD>
Nested templates in template parameter, such as `template <
template <class T> class A>` are not supported by any compiler.
This flag is set if they are not supported.
</DL>
\subsection secworkaround_macros Macros connected to workarounds/compilers
Some macros are defined according to certain workaround flags. This is
done to avoid some `ifdef`s in our actual code.
<DL>
<DT><B><TT>CGAL_LITTLE_ENDIAN</TT></B><DD> set, iff
<TT>CGAL_CFG_NO_BIG_ENDIAN</TT> is set.
<DT><B><TT>CGAL_BIG_ENDIAN</TT></B><DD> set, iff
<TT>CGAL_CFG_NO_BIG_ENDIAN</TT> is not set.
<DT><B><TT>CGAL_DEPRECATED</TT></B><DD>
used to declare a function as deprecated - just add it before the
function declaration. You may also surround deprecated code with
<TT>CGAL_NO_DEPRECATED_CODE</TT>, such that it is easy to test
if a piece of code uses deprecated code or not:
\code{.cpp}
#ifndef CGAL_NO_DEPRECATED_CODE
CGAL_DEPRECATED void foo(int i)
{
...
}
#endif // CGAL_NO_DEPRECATED_CODE
\endcode
</DL>
\subsection secvarious_problems Various other problems and solutions
<DL>
<DT><B><B>min and max</B></B><DD>
Visual \cpp headers (and others) sometimes define `min` and `max` as macros. If you write `max` followed by an opening parenthesis, this can lead to unwanted substitutions. In order to work around it, you should use one of the following tricks:
\code{.cpp}
max BOOST_PREVENT_MACRO_SUBSTITUTION (a, b);
(max) (a, b);
\endcode
<DT><B><B>Templated member functions</B></B><DD>
For SunPRO \cpp member function templates with dependent return type
must be defined in the body of the class.
<DT><B><B>Function parameter matching</B></B><DD>
The function parameter matching capacities of Visual \cpp are rather limited.
Failures occur when your function `bar` is like
\code{.cpp}
bar(std::some_iterator<std::some_container<T>>....) ...
...
bar(std::some_iterator<std::some_other_container<T>>....) ...
\endcode
VC++ fails to distinguish that these parameters have different types.
A workaround is to add some dummy parameters that are defaulted to
certain values, and this affects only the places where the functions
are defined, not the places where they are called.
This may not be true anymore for recent VC++ versions.
<DT><B><B>typedefs of derived classes</B></B><DD>
Microsoft VC++ does not like the following sorts of typedefs that are
standard
\code{.cpp}
class A : public B::C {
typedef B::C C;
};
\endcode
It says that the typedef is "redefinition". So such typedefs should be
enclosed by
\code{.cpp}
#ifndef _MSC_VER
#endif
\endcode
This may not be true anymore for recent VC++ versions.
</DL>
\section secportability_req_and_rec Requirements and recommendations
Recommendations:
<UL>
<LI>Workarounds for a compiler bug or a missing feature should not
be treated on a per-compiler basis. When you detect a deficiency,
you should rather write a short test program that triggers the setting
of a flag for this deficiency during configuration.
</UL>
*/