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