PATCH: Parallel compilation of class files

Mark Mitchell mark@codesourcery.com
Wed May 8 12:27:00 GMT 2002


Here's the much-discussed patch to allow parallel make in libjava (and in
user programs as well).

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2002-05-08  Mark Mitchell  <mark@codesourcery.com>

	* java/jcf-write.c (write_classfile): Write the file to a
	temporary file and then rename it.

2002-05-08  Mark Mitchell  <mark@codesourcery.com>

	* libjava/Makefile.am (all_java_source_files): New variable.
	(all_java_class_files): Likewise.
	.java.class: New rule.
	(CLEANFILES): Remove tmp-list.
	* libjava/Makefile.in: Regenerated.

Index: gcc/java/jcf-write.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-write.c,v
retrieving revision 1.102
diff -c -p -r1.102 jcf-write.c
*** gcc/java/jcf-write.c	22 Apr 2002 16:55:39 -0000	1.102
--- gcc/java/jcf-write.c	8 May 2002 18:51:46 -0000
*************** write_classfile (clas)
*** 3374,3389 ****

    if (class_file_name != NULL)
      {
!       FILE *stream = fopen (class_file_name, "wb");
        if (stream == NULL)
! 	fatal_io_error ("can't open %s for writing", class_file_name);

        jcf_dependency_add_target (class_file_name);
        init_jcf_state (state, work);
        chunks = generate_classfile (clas, state);
        write_chunks (stream, chunks);
        if (fclose (stream))
! 	fatal_io_error ("error closing %s", class_file_name);
        free (class_file_name);
      }
    release_jcf_state (state);
--- 3374,3401 ----

    if (class_file_name != NULL)
      {
!       FILE *stream;
!       char *temporary_file_name;
!
!       /* The .class file is initially written to a ".tmp" file so that
! 	 if multiple instances of the compiler are running at once
! 	 they do not see partially formed class files. */
!       temporary_file_name = xmalloc (strlen (class_file_name)
! 				     + strlen (".tmp") + 1);
!       sprintf (temporary_file_name, "%s.tmp", class_file_name);
!       stream = fopen (temporary_file_name, "wb");
        if (stream == NULL)
! 	fatal_io_error ("can't open %s for writing", temporary_file_name);

        jcf_dependency_add_target (class_file_name);
        init_jcf_state (state, work);
        chunks = generate_classfile (clas, state);
        write_chunks (stream, chunks);
        if (fclose (stream))
! 	fatal_io_error ("error closing %s", temporary_file_name);
!       if (rename (temporary_file_name, class_file_name) == -1)
! 	fatal_io_error ("can't create %s", class_file_name);
!       free (temporary_file_name);
        free (class_file_name);
      }
    release_jcf_state (state);
Index: libjava/Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.215
diff -c -p -r1.215 Makefile.am
*** libjava/Makefile.am	26 Apr 2002 22:39:28 -0000	1.215
--- libjava/Makefile.am	8 May 2002 18:51:48 -0000
*************** install-exec-hook:
*** 165,209 ****
  	  $(LN_S) libgcjx.la gnu-awt-xlib.la; \
  	fi

! ## Make the .class files depend on the .zip file.  This seems
! ## backwards, but is right.  This doesn't catch all the .class files,
! ## but that is ok, because the ones it fails to pick up are defined in
! ## a .java file with some other class which is caught.  Note that we
! ## only want to create headers for those files which do not have
! ## hand-maintained headers.
! $(built_java_source_files:.java=.class): libgcj-@gcc_version@.jar
! $(java_source_files:.java=.class): libgcj-@gcc_version@.jar

! ## The .class files for X will not be included in libgcj.jar, but the
! ## rule for libgcj.jar will cause all out-of-date .class files to be
! ## built. We need this to generate headers for the nat-files.
! $(x_java_source_files:.java=.class): libgcj-@gcc_version@.jar

! ## We have the zip file depend on the java sources and not the class
! ## files, because we don't know the names of all the class files.
! ## FIXME: this method fails in a peculiar case: if libgcj.jar is
! ## up-to-date, and foo.class is removed, and bar.java is touched, then
! ## `make libgcj.jar' will not rebuilt foo.class.  That's because
! ## libgcj.jar is not out-of-date with respect to foo.java.
! libgcj-@gcc_version@.jar: $(built_java_source_files) $(java_source_files) 
$(x_java_source_files)
! ## Create a list of all Java sources, without exceeding any shell limits.
! 	@: $(shell echo Creating list of files to compile...) $(shell rm -f 
tmp-list || :) $(shell touch tmp-list) $(foreach source,$?,$(shell echo 
$(source) >> tmp-list))
! 	@set fnord $(MAKEFLAGS); amf=$$2; fail=no; \
! 	javac="$(JAVAC)"; \
! 	cat tmp-list | (while read f; do \
! 	  echo $$javac $(JCFLAGS) -classpath \'\' -bootclasspath 
$(here):$(srcdir) -d $(here) $$f; \
! 	  $$javac $(JCFLAGS) -classpath '' -bootclasspath $(here):$(srcdir) -d 
$(here) $$f \
! 	    || case "$$amf" in *=*) exit 1;; *k*) fail=yes ;; *) exit 1;; esac; \
! 	done; \
! 	test "$$fail" = no)
! 	-@rm -f tmp-list libgcj-@gcc_version@.jar
  ## Note that we explicitly want to include directory information.
  	find java gnu javax org -type d -o -type f -name '*.class' | \
  	  sed -e '/\/\./d' -e '/\/xlib/d' | \
  	  $(ZIP) cfM0E@ $@

  MOSTLYCLEANFILES = $(javao_files) $(nat_files) $(nat_headers) $(c_files) 
$(x_javao_files) $(x_nat_files) $(x_nat_headers)
! CLEANFILES = tmp-list libgcj-@gcc_version@.jar

  clean-local:
  ## We just remove every .class file that was created.
--- 165,190 ----
  	  $(LN_S) libgcjx.la gnu-awt-xlib.la; \
  	fi

! all_java_source_files = \
!     $(java_source_files) \
!     $(built_java_source_files) \
!     $(x_java_source_files)

! all_java_class_files = $(all_java_source_files:.java=.class)

! .java.class:
! 	$(JAVAC) $(JCFLAGS) -classpath '' -bootclasspath $(here):$(srcdir) \
!              -d $(here) $<
!
! libgcj-@gcc_version@.jar: $(all_java_class_files)
! 	-@rm -f libgcj-@gcc_version@.jar
  ## Note that we explicitly want to include directory information.
  	find java gnu javax org -type d -o -type f -name '*.class' | \
  	  sed -e '/\/\./d' -e '/\/xlib/d' | \
  	  $(ZIP) cfM0E@ $@

  MOSTLYCLEANFILES = $(javao_files) $(nat_files) $(nat_headers) $(c_files) 
$(x_javao_files) $(x_nat_files) $(x_nat_headers)
! CLEANFILES = libgcj-@gcc_version@.jar

  clean-local:
  ## We just remove every .class file that was created.



More information about the Java mailing list