[Python-Dev] [C++-sig] GCC version compatibility

Christoph Ludwig cludwig at cdc.informatik.tu-darmstadt.de
Sun Jul 10 14:54:59 CEST 2005


On Sun, Jul 10, 2005 at 09:45:25AM +0200, "Martin v. Löwis" wrote:
> Christoph Ludwig wrote:
> >>I'll describe it once more: *If* a program is compiled with the C++
> >>compiler, is it *then* possible to still link it with the C compiler?
> >>This is the question this test tries to answer.
> > 
> > 
> > The keyword here is "tries"
> 
> Any such test would only "try": to really determine whether this is
> necessary for all possible programs, one would have to test all possible
> programs. Since there is an infinite number of programs, this test could
> take a while.

Sure. You cannot write a test that gives the correct result for all platforms
you can think of, covering every compiler / linker quirk. I never claimed that
is possible.

My point is: The test implemented in the 2.4.1 configure script gives a wrong
result if your platform happens to be x86 Linux with ELF binaries and 
g++ 4.0. 

> The original test, on the original system, would cause __main to be
> undefined, and then decide to use C++. For a long time, on systems
> that don't use collect2, the test *correctly* determined that linking
> with g++ was not necessary.
> 
> It is only recent changes to g++ that break the test, namely the
> introduction of this __gxx_personality_v0 thing.

The test broke due to a change in GCC 4.0, but the "__gxx_personality_v0
thing" was introduced long before. It is merely a symptom. I ran the tests
with GCC 3.3.1, 3.4.2, and 4.0.0. Here are the results:

  GCC version       1 TU        2 TUs
    3.3.1            g++         g++
    3.4.2            g++         g++
    4.0.0            gcc         g++

(1 TU: test with one translation unit, as in Python 2.4.1.
 2 TUs: test with two translation units, as in my last posting.
 g++ / gcc: test indicates linking the executable requires g++ / gcc,
 respectively.)

With GCC 3.3.1 and 3.4.2, linking of the executable conftest in the 1 TU test
fails because of an unresolved symbol __gxx_personality_v0. Therefore, python
is linked with g++.

The change that makes GCC 4.0.0 break the 1 TU test is that the compiler
apparently does a better job eliminating unreachable code. In the 1 TU test,
it recognizes __gxx_personality_v0 (or the code that refers to this symbol) is
unreachable and removes it. It seems there are no other symbols left that
depend on libstdc++ so suddenly conftest can be linked with gcc.

> > - my bug report #1189330 exihibts that the test
> > fails to do its job. And looking at the test that's certainly no surprise:
> 
> However, it *is* a surprise that your modified test fixes the problem.
> 
> > Note that there is *no* reference to any symbol in another TU. The compiler
> > can detect that foo() won't throw any exceptions, that there is no need for RTTI
> > and whatever else the C++ runtime provides. Consequently, the object file
> > produced by g++ does not contain any reference to symbols in libstdc++.
> 
> You are assuming implementation details here. I have seen
> implementations of C++ (eg. g++ with collect2) where the test determines
> that linking with C++ is necessary (because __main was undefined), as
> well as systems where the test decides *correctly* that linking with
> C++ is not necessary (e.g. gcc 2.x on an ELF system). That some C++
> compiler introduces the C++ runtime if some C function may throw an
> exception is a very specific detail of this C++ compiler.

I am not aware of any rule that makes the following program ill-formed:

  // in a.cc:
  extern "C" void foo();

  int main() {
    foo();
  }

  // in b.cc
  extern "C" void foo() {
    throw 1;
  }

Provided the compiler does not do optimizations across translation units, it
has no way to determine in a.cc whether foo() is really a C function (i.e.,
compiled by a C compiler) or a C++ function with "C" linkage. I think a
conforming C++ compiler has to provide for the case that foo() might throw. It
was a very specific detail of gcc 2.x if it failed to do so. (A venial
omission, I admit.)


But I digress. It's not that important for our discussion whether a C++
compiler must / should / is allowed to add exception handling code to the
call of an extern "C" function. The point is that some do *unless* they see
the function definition. I contend the test involving two TUs matches more
closely the situation with ccpython.cc than the current test.

I do not claim the 2 TUs test will cover all possible scenarios. I am not even
sure this decision should be left to an automated test. Because if the test
breaks for some reason then the user is left with a linker error that is
time-consuming to track down.

> > Of course, if you insist on this "dependency optimization" then you can try to
> > fix Python's configure.in by using the second test above. But I would still
> > not trust it to cover all configurations on all platforms supported by
> > Python. 
> 
> Of couse not. This is just autoconf: it does not allow magical porting
> to all possible future operating systems. Instead, from time to time,
> explicit porting activity is necessary. This is not just about this
> specific detail, but about many other details. Each new operation
> system, library, or compiler version might break the build process.

Instead of having yet another test in configure.in that may break on a new
platform and that needs maintenance wouldn't it be better to assume that
--with-cxx implies linking with the C++ compiler and telling users how to
override this assumption? Would it cause so much inconvenience to users
provided the explanation of --with-cxx in the README would be modified?

I think of an explanation along the lines of:

--with-cxx=<compiler>: If you plan to use C++ extension modules, then on some
        platform you need to compile python's main() function with the C++
        compiler. With this option, make will use <compiler> to compile main()
        *and* to link the python executable. It is likely that the resulting
        executable depends on the C++ runtime library of <compiler>.

        Note there are platforms that do not require you to build Python with
        a C++ compiler in order to use C++ extension modules. E.g., x86 Linux
        with ELF shared binaries and GCC 3.x, 4.x is such a platform. We
        recommend that you configure Python --without-cxx on those platforms
        to avoid unnecessary dependencies.

        If you need to compile main() with <compiler>, but your platform does
        not require that you also link the python executable with <compiler> 
        (e.g., <example platform>), then set LINKCC='$(PURIFY) $(CC)' prior to
        calling make. Then the python executable will not depend on the C++
        runtime library of <compiler>.


BTW, I'd also change the short explanation output by `configure --help'.
Something like:

  AC_HELP_STRING(--with-cxx=<compiler>, 
                 use <compiler> to compile and link main())

In Python 2.4.1, the help message says "enable C++ support". That made me use
this option even though it turned out it is not necessary on my platform.

Regards

Christoph
-- 
http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/cludwig.html
LiDIA: http://www.informatik.tu-darmstadt.de/TI/LiDIA/Welcome.html



More information about the Python-Dev mailing list