Patch for Review: libjava Configury Changes for Cross Builds
Mohan Embar
gnustuff@thisiscool.com
Sun Apr 27 08:28:00 GMT 2003
Hi Patch People.
This patch is accompanied by a verbose explanation, so
I'll use section headings.
(Ranjit: this new patch supersedes the previous alpha
patch I sent you off list which was incorrect in several
ways. If you are up to testing this again, have at it.)
INTRODUCTION
At long last, here is the cross-configury patch I've been
promising. It has taken me so long to submit this because
I've been doing intensive testing on it on many (build,host,target)
combinations.
Before I start, I want to credit Ranjit Mathew with his initial
analysis:
http://gcc.gnu.org/ml/java/2002-11/msg00044.html
...and precursor to this patch:
http://gcc.gnu.org/ml/java-patches/2003-q1/msg00126.html
...as well as for getting me on this whole configury kick.
I take full blame for any errors in this patch, however.
CONFIGURY TERMS
The configury terms in this text (like "cross", "crossed-native", etc.)
are defined here:
http://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html
This is required reading to understand this patch.
WHY THIS PATCH IS NEEDED
This patch is needed because the current build rules do not
allow libgcj to be built correctly and successfully for crossed
or crossed-native builds and even for native Win32-hosted builds.
Before I detail my solution, let me first detail what I think is
wrong with the current state of affairs.
--> libltdl Only Built for Native Builds
The current configure.in has this:
Ref. 1:
------------------------- 8< ------------------------------
# Only use libltdl for native builds.
if test -z "${with_cross_host}"; then
<< censored >>
fi
------------------------- 8< ------------------------------
This means that cross compilers can't build a libgcj which
supports native libraries (no JNI, SWT, etc.)
--> Incorrect tests for built gcj
The remaining section in the current configure.in in question
is this:
Ref. 2:
------------------------- 8< ------------------------------
if test -x "${builddotdot}/../../gcc/gcj"; then
dir="`cd ${builddotdot}/../../gcc && ${PWDCMD-pwd}`"
GCJ="$dir/gcj -B`${PWDCMD-pwd}`/ -B$dir/"
else
CANADIAN=yes
NULL_TARGET=yes
GCJ="gcj -B`${PWDCMD-pwd}`/"
fi
------------------------- 8< ------------------------------
This section attempts to detect whether the gcj that was
built during this build is eligible for use in compiling
and linking the libjava libraries.
There are several problems with the above code:
- test -x "${builddotdot}/../../gcc/gcj" doesn't account
for .exe extensions under Windows, for example
- the entire test is in the else clause of the following
containing if test:
if test "x${with_newlib}" = "xyes"; then
...which means that the only assumption we can make about
Ref. 2 is that we are being built without newlib. However,
this could be a non-newlib build where we are nevertheless
being configured with a cross compiler. Think about the
following cases:
- using a (linux,mingw) cross compiler to build a (mingw,mingw)
native compiler: the built native compiler has an .exe extension
so we hit the "else" clause and attempt to use a gcj in
the path which incorrectly omits the target alias prefix
(i.e. gcj instead of mingw32-gcj)
- using a (linux,solaris) cross compiler to build a (solaris,solaris)
native compiler: the built native compiler has no .exe extension
so we actually attempt to invoke the (solaris,solaris) compiler
on Linux. Ouch. (Hmm what would happen with (linux,freebsd), where
FreeBSD claims it can run Linux executables...?)
--> Incorrect gcjh in Makefile.am
Finally, let's look at this code in Makefile.am:
------------------------- 8< ------------------------------
if NULL_TARGET
## In this case, gcj is found outside the build tree. However, zip is
## found in the build tree.
ZIP = $(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar
else
ZIP = jar
endif
GCJH = gcjh
------------------------- 8< ------------------------------
This is also incorrect if we are being built with a cross compiler,
because we need ${target_alias}-gcjh instead of gcjh (i.e. mingw32-gcjh
if a (linux,mingw) cross compiler is building a (mingw,mingw) native
compiler).
PREVIOUS ANALYSES
The problems we're trying to solve aren't new. If you peruse the
following thread:
http://gcc.gnu.org/ml/gcc-bugs/2001-07/msg00181.html
...you'll see that the libstdc++ people agonized about the same
problem. If you look at configure.in in libstdc++v3, starting at
this line:
if test -n "$with_cross_host" || test x"$build" != x"$host"; then
...you'll see that they even refuse to do any compile/link tests
for cross builds, instead hardcoding the functions for each host.
Their comment ("This lets us hard-code the functionality...") explains
their rationale.
For libjava builds, however, I think we can exploit the with_newlib flag
and do compile and link tests for non-newlib builds since we have the
target libraries around. (Was --with-newlib not available or used for libstdc++?)
Tom seems to agree with this approach (cf. last sentence of
http://gcc.gnu.org/ml/java/2002-11/msg00132.html).
THIS PATCH
This patch attempts to remedy the problems listed above. It basically tries
to distinguish between newlib and non-newlib (possibly cross) builds and
do the right thing in all cases.
I've tested this with the following combinations:
(l=i686-pc-linux-gnu, y=i686-pc-cygwin, m=i386-pc-mingw32)
(l,l,l) [native]
(l,l,m) [normal cross]
(l,m,m) [native cross]
(l,y,m) [Canadian cross]
(l,y,l) [crossback]
(m,m,m) [native build on Win32]
(y,y,m) [normal cross on Win32]
(y,m,m) [native cross on Win32]
using the test case I've attached to this message. The test case
tests whether JNI (needs libltdl) and stack traces work correctly,
which wasn't the case for Ranjit's previous incarnation of this
patch.
Here are the ways in which this patch attempts to solve
the problems listed previously:
--> libltdl Only Built for Non-newlib builds
When deciding whether to incorporate libltdl, we use
this test:
if test "x${with_newlib}" = "xno"; then
instead of the current one:
if test -z "${with_cross_host}"; then
This allows non-newlib cross compilers (i.e. (linux,mingw)) to load
native libraries.
--> Move "which gcj?" test outside of newlib test
>From the above discussion ("Incorrect tests for built gcj"), it
is clear that the determination of the correct gcj to use is
more complex than the present test. There are currently two
such tests for the newlib and non-newlib builds. I moved these
outside of the newlib test and consolidated them somewhat.
When reading on, consult the "# Which gcj do we use?" portion
of the patch.
Determination of the correct gcj to use depends on whether this
is a cross build as well as whether the compiler will actually
run on the machine we're building on. The compiler is hosted
on $with_cross_host if this is defined; otherwise, on $host.
We need to factor in the extension of the built compiler to
see if it has been built alongside, but can't use $ac_exeext
in the $with_cross_host case because that is for $host, which
is different from $with_cross_host. We really need the executable
extension of the <i>build</i> machine in this case.
Instead of the hardcoded *mingw* | *cygwin* test, we could have used
another autoconf macro like this one:
http://www.gnu.org/software/ac-archive/htmldoc/ac_prog_cc_for_build.html
...but it seemed overkill for our purposes. (Note that djgpp
is conspicuously absent from this list. The day that someone gets
a working djgpp gcj (cross) compiler working, I'll swoon.)
The remainder of the code is intended to be self-documenting. (Ha!)
--> Choose correct gcjh in Makefile.am
Finally, we choose the correct gcjh in Makefile.am. This is
unchanged from Ranjit's patch.
KNOWN ISSUES WITH THIS PATCH
- For newlib builds for non-embedded targets (such as Cygwin),
we will still get a crippled cross compiler. Solving this
would require the hardcoding approach taken by libstdc++.
This is beyond the scope of this patch. The workaround is
to not build newlib alongside.
- The "FIXME (comment): Why is this needed?" section of this
patch needs to be scrutinized and remedied. In particular, I
am not clear on why the -B flag was omitted in the newlib
case. (This refactored code is equivalent to the code in the
previous newlib section, so I blindly did this without understanding
what I was doing.)
- To correctly handle the case where a previously-built native
compiler is used to build the libraries of a crossback (i.e.
(l,l) builds the libraries for an (l,y,l) build), we should
have the install target of gcc create a $host_alias-gcjh in
the same manner it does $host_alias-gcj. Otherwise, the build
breaks. This is beyond the scope of this patch, but seems to
make sense, doesn't it?
- I'm still not getting the whole CANADIAN, NULL_TARGET thing.
What in the world does NULL_TARGET mean? Here an attempt to
categorize this, but I'm grappling with some sort of semantic
hook for NULL_TARGET:
CANADIAN NULL_TARGET Description
-------- ----------- -----------
yes yes jar in build tree, gcjh not
yes no jar not in build tree, use cross gcjh
no no jar and gcjh in build tree
The patch follows and the test case is attached. Enjoy.
-- Mohan
http://www.thisiscool.com/
http://www.animalsong.org/
ChangeLog
2003-04-27 Mohan Embar <gnustuff@thisiscool.com>
Ranjit Mathew <rmathew@hotmail.com>
* Makefile.am: Use cross-compiling gcjh from the path for
a crossed-native build.
* Makefile.in: Rebuilt.
* configure.in: Include libltdl in non-newlib builds.
Moved determination of gcj used to build libraries to
its own section. Fixed cross-compilation issues for
non-newlib builds.
* configure: Rebuilt.
Index: Makefile.am
===================================================================
RCS file: /cvsroot/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.264.2.12
diff -u -2 -r1.264.2.12 Makefile.am
--- Makefile.am 1 Mar 2003 22:57:52 -0000 1.264.2.12
+++ Makefile.am 27 Apr 2003 06:54:28 -0000
@@ -53,8 +53,9 @@
## found in the build tree.
ZIP = $(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar
+GCJH = gcjh
else
ZIP = jar
+GCJH = $(target_alias)-gcjh
endif
-GCJH = gcjh
else # CANADIAN
GCJH = $(MULTIBUILDTOP)../$(COMPPATH)/gcc/gcjh
Index: configure.in
===================================================================
RCS file: /cvsroot/gcc/gcc/libjava/configure.in,v
retrieving revision 1.142.4.7
diff -u -2 -r1.142.4.7 configure.in
--- configure.in 28 Mar 2003 23:42:56 -0000 1.142.4.7
+++ configure.in 27 Apr 2003 06:54:56 -0000
@@ -24,6 +24,6 @@
AM_CONFIG_HEADER(include/config.h gcj/libgcj-config.h)
-# Only use libltdl for native builds.
-if test -z "${with_cross_host}"; then
+# Only use libltdl for non-newlib builds.
+if test "x${with_newlib}" = "xno"; then
AC_LIBLTDL_CONVENIENCE
AC_LIBTOOL_DLOPEN
@@ -492,14 +492,4 @@
dnl Assume we do not have getuid and friends.
AC_DEFINE(NO_GETUID)
-
- # If Canadian cross, then don't pick up tools from the build
- # directory.
- if test x"$build" != x"$with_cross_host" \
- && test x"$build" != x"$target"; then
- CANADIAN=yes
- GCC_UNWIND_INCLUDE=
- GCJ="${target_alias}-gcj"
- fi
- NATIVE=no
else
AC_CHECK_FUNCS(strerror ioctl select fstat open fsync sleep opendir)
@@ -732,13 +722,67 @@
changequote([,])
fi
- if test -x "${builddotdot}/../../gcc/gcj"; then
- dir="`cd ${builddotdot}/../../gcc && ${PWDCMD-pwd}`"
- GCJ="$dir/gcj -B`${PWDCMD-pwd}`/ -B$dir/"
- else
+fi
+
+# Which gcj do we use?
+which_gcj=default
+built_gcc_dir="`cd ${builddotdot}/../../gcc && ${PWDCMD-pwd}`"
+if test -n "${with_cross_host}"; then
+ # We are being configured with a cross compiler. We can't
+ # use ac_exeext, because that is for the target platform.
+ NATIVE=no
+ cross_host_exeext=
+ case "${with_cross_host}" in
+ *mingw* | *cygwin*)
+ cross_host_exeext=.exe
+ ;;
+ esac
+ if test -x "${built_gcc_dir}/gcj${cross_host_exeext}"; then
+ if test x"$build" = x"$with_cross_host"; then
+ # Ordinary cross (host!=target and host=build)
+ which_gcj=built
+ else
+ # Canadian cross (host!=target and host!=build)
+ which_gcj=cross
+ fi
+ else
+ which_gcj=cross
+ fi
+else
+ # We are being configured with a native or crossed-native compiler
+ if test -x "${built_gcc_dir}/gcj${ac_exeext}"; then
+ if test x"$build" = x"$host"; then
+ # True native build (host=target and host=build)
+ which_gcj=built
+ else
+ # Crossed-native build (host=target and host!=build)
+ which_gcj=cross
+ fi
+ else
+ which_gcj=path
+ fi
+fi
+case "${which_gcj}" in
+ built)
+ GCJ="$built_gcc_dir/gcj -B`${PWDCMD-pwd}`/ -B$built_gcc_dir/"
+ ;;
+ cross)
+ # See the comment in Makefile.am about CANADIAN being a misnomer
+ CANADIAN=yes
+ NULL_TARGET=no
+ if test "x${with_newlib}" = "xyes"; then
+ # FIXME (comment): Why is this needed?
+ GCC_UNWIND_INCLUDE=
+ GCJ="${target_alias}-gcj"
+ else
+ GCJ="${target_alias}-gcj -B`${PWDCMD-pwd}`/"
+ fi
+ ;;
+ path)
+ # See the comment in Makefile.am about CANADIAN being a misnomer
CANADIAN=yes
NULL_TARGET=yes
GCJ="gcj -B`${PWDCMD-pwd}`/"
- fi
-fi
+ ;;
+esac
# Create it, so that compile/link tests don't fail
More information about the Java-patches
mailing list