[m-rev.] for review: call javac only once per linked target (mmc --make)
Peter Wang
novalazy at gmail.com
Tue May 5 12:11:02 AEST 2009
Branches: main
With mmc --make, invoke `javac' once only for a linked target, passing it all
the .java files which need compiling. This is how the Java compiler is meant
to be used, and is much quicker.
compiler/make.program_target.m:
As above.
Clear cached timestamps of all `.class' files afterwards.
compiler/compile_target_code.m:
Change `compile_java_file' to accept multiple Java files.
compiler/make.dependencies.m:
Fix a bug. `.class' files should depend on the `.java' file only.
compiler/make.module_target.m:
compiler/mercury_compile.m:
Conform to changes.
diff --git a/compiler/compile_target_code.m b/compiler/compile_target_code.m
index c07670a..f298c87 100644
--- a/compiler/compile_target_code.m
+++ b/compiler/compile_target_code.m
@@ -56,9 +56,9 @@
:- pred assemble(io.output_stream::in, pic::in, module_name::in,
bool::out, io::di, io::uo) is det.
- % compile_java_file(ErrorStream, JavaFile, Succeeded)
+ % compile_java_files(ErrorStream, JavaFiles, Succeeded)
%
-:- pred compile_java_file(io.output_stream::in, string::in, bool::out,
+:- pred compile_java_files(io.output_stream::in, list(string)::in, bool::out,
io::di, io::uo) is det.
% il_assemble(ErrorStream, ModuleName, HasMain, Succeeded)
@@ -865,11 +865,29 @@ gather_c_compiler_flags(PIC, AllCFlags, !IO) :-
%-----------------------------------------------------------------------------%
-compile_java_file(ErrorStream, JavaFile, Succeeded, !IO) :-
+compile_java_files(ErrorStream, JavaFiles, Succeeded, !IO) :-
globals.io_lookup_bool_option(verbose, Verbose, !IO),
- maybe_write_string(Verbose, "% Compiling `", !IO),
- maybe_write_string(Verbose, JavaFile, !IO),
- maybe_write_string(Verbose, "':\n", !IO),
+ (
+ JavaFiles = [JavaFile | MoreFiles],
+ (
+ Verbose = yes,
+ io.write_string("% Compiling `", !IO),
+ io.write_string(JavaFile, !IO),
+ (
+ MoreFiles = [],
+ io.write_string("':\n", !IO)
+ ;
+ MoreFiles = [_ | _],
+ io.write_string("', etc.:\n", !IO)
+ )
+ ;
+ Verbose = no
+ )
+ ;
+ JavaFiles = [],
+ unexpected(this_file, "compile_java_files: empty list")
+ ),
+
globals.io_lookup_string_option(java_compiler, JavaCompiler, !IO),
globals.io_lookup_accumulating_option(java_flags, JavaFlagsList, !IO),
join_string_list(JavaFlagsList, "", "", " ", JAVAFLAGS),
@@ -930,8 +948,9 @@ compile_java_file(ErrorStream, JavaFile, Succeeded, !IO) :-
% Be careful with the order here! Some options may override others.
% Also be careful that each option is separated by spaces.
+ JoinedJavaFiles = string.join_list(" ", JavaFiles),
string.append_list([JavaCompiler, " ", InclOpt, DirOpts,
- Target_DebugOpt, JAVAFLAGS, " ", JavaFile], Command),
+ Target_DebugOpt, JAVAFLAGS, " ", JoinedJavaFiles], Command),
invoke_system_command(ErrorStream, cmd_verbose_commands, Command,
Succeeded, !IO).
diff --git a/compiler/make.dependencies.m b/compiler/make.dependencies.m
index 8e37b9f..6191138 100644
--- a/compiler/make.dependencies.m
+++ b/compiler/make.dependencies.m
@@ -391,8 +391,8 @@ target_dependencies(_, module_target_il_asm) =
]).
target_dependencies(Globals, module_target_java_code) =
compiled_code_dependencies(Globals).
-target_dependencies(Globals, module_target_java_class_code) =
- compiled_code_dependencies(Globals).
+target_dependencies(_, module_target_java_class_code) =
+ module_target_java_code `of` self.
target_dependencies(Globals, module_target_erlang_header) =
target_dependencies(Globals, module_target_erlang_code).
target_dependencies(Globals, module_target_erlang_code) =
diff --git a/compiler/make.module_target.m b/compiler/make.module_target.m
index 042d20f..3437a2a 100644
--- a/compiler/make.module_target.m
+++ b/compiler/make.module_target.m
@@ -509,7 +509,7 @@ build_object_code(ModuleName, target_java, _,
ErrorStream, _Imports, Succeeded,
!IO) :-
module_name_to_file_name(ModuleName, ".java", do_create_dirs, JavaFile,
!IO),
- compile_target_code.compile_java_file(ErrorStream, JavaFile,
+ compile_target_code.compile_java_files(ErrorStream, [JavaFile],
Succeeded, !IO).
build_object_code(ModuleName, target_il, _, ErrorStream, Imports, Succeeded,
!IO) :-
@@ -539,7 +539,7 @@ compile_foreign_code_file(ErrorStream, _, _Imports,
no_main, Succeeded, !IO).
compile_foreign_code_file(ErrorStream, _, _Imports,
foreign_code_file(lang_java, JavaFile, _ClassFile), Succeeded, !IO) :-
- compile_target_code.compile_java_file(ErrorStream, JavaFile,
+ compile_target_code.compile_java_files(ErrorStream, [JavaFile],
Succeeded, !IO).
compile_foreign_code_file(ErrorStream, _, Imports,
foreign_code_file(lang_csharp, CSharpFile, DLLFile),
diff --git a/compiler/make.program_target.m b/compiler/make.program_target.m
index 13842e3..7bf69cf 100644
--- a/compiler/make.program_target.m
+++ b/compiler/make.program_target.m
@@ -56,6 +56,7 @@
:- import_module digraph.
:- import_module dir.
:- import_module getopt_io.
+:- import_module svmap.
%-----------------------------------------------------------------------------%
@@ -204,20 +205,29 @@ make_linked_target_2(LinkedTargetFile, _,
Succeeded, !Info, !IO) :-
BuildDepsSucceeded0, !Info, !IO),
(
BuildDepsSucceeded0 = yes,
- foldl2_maybe_stop_at_error_maybe_parallel(KeepGoing,
- make_module_target, ObjTargets,
- BuildDepsSucceeded1, !Info, !IO)
+ maybe_make_java_files(MainModuleName,
+ ObjectTargetType, ObjModules, BuildDepsSucceeded1,
+ !Info, !IO)
;
BuildDepsSucceeded0 = no,
BuildDepsSucceeded1 = no
),
(
BuildDepsSucceeded1 = yes,
+ foldl2_maybe_stop_at_error_maybe_parallel(KeepGoing,
+ make_module_target, ObjTargets, BuildDepsSucceeded2,
+ !Info, !IO)
+ ;
+ BuildDepsSucceeded1 = no,
+ BuildDepsSucceeded2 = no
+ ),
+ (
+ BuildDepsSucceeded2 = yes,
foldl2_maybe_stop_at_error(KeepGoing, make_module_target,
ForeignObjTargets,
BuildDepsSucceeded, !Info, !IO)
;
- BuildDepsSucceeded1 = no,
+ BuildDepsSucceeded2 = no,
BuildDepsSucceeded = no
)
),
@@ -626,6 +636,99 @@ linked_target_cleanup(MainModuleName, FileType,
OutputFileName,
%-----------------------------------------------------------------------------%
+ % When compiling to Java we want to invoke `javac' just once, passing it a
+ % list of all out-of-date `.java' files. This is a lot quicker than
+ % compiling each Java file individually.
+ %
+:- pred maybe_make_java_files(module_name::in, module_target_type::in,
+ list(module_name)::in, bool::out, make_info::in, make_info::out,
+ io::di, io::uo) is det.
+
+maybe_make_java_files(MainModuleName, ObjectTargetType, ObjModules, Succeeded,
+ !Info, !IO) :-
+ ( ObjectTargetType = module_target_java_class_code ->
+ out_of_date_java_modules(ObjModules, OutOfDateModules, !Info, !IO),
+ (
+ OutOfDateModules = [],
+ Succeeded = yes
+ ;
+ OutOfDateModules = [_ | _],
+ build_java_files(MainModuleName, OutOfDateModules, Succeeded,
+ !Info, !IO),
+ % javac might write more `.class' files than we anticipated (though
+ % it probably won't) so clear out all the timestamps which might be
+ % affected.
+ Timestamps0 = !.Info ^ file_timestamps,
+ map.foldl(delete_java_class_timestamps, Timestamps0,
+ map.init, Timestamps),
+ !Info ^ file_timestamps := Timestamps
+ )
+ ;
+ Succeeded = yes
+ ).
+
+:- pred out_of_date_java_modules(list(module_name)::in, list(module_name)::out,
+ make_info::in, make_info::out, io::di, io::uo) is det.
+
+out_of_date_java_modules(ObjModules, OutOfDateModules, !Info, !IO) :-
+ (
+ ObjModules = [],
+ OutOfDateModules = []
+ ;
+ ObjModules = [ModuleName | Rest],
+ out_of_date_java_modules(Rest, OutOfDateModules0, !Info, !IO),
+ JavaTarget = target_file(ModuleName, module_target_java_code),
+ ClassTarget = target_file(ModuleName, module_target_java_class_code),
+ get_target_timestamp(do_not_search, JavaTarget, MaybeJavaTimestamp,
+ !Info, !IO),
+ get_target_timestamp(do_not_search, ClassTarget, MaybeClassTimestamp,
+ !Info, !IO),
+ (
+ MaybeJavaTimestamp = ok(JavaTimestamp),
+ MaybeClassTimestamp = ok(ClassTimestamp),
+ ClassTimestamp @>= JavaTimestamp
+ ->
+ OutOfDateModules = OutOfDateModules0
+ ;
+ OutOfDateModules = [ModuleName | OutOfDateModules0]
+ )
+ ).
+
+:- pred build_java_files(module_name::in, list(module_name)::in, bool::out,
+ make_info::in, make_info::out, io::di, io::uo) is det.
+
+build_java_files(MainModuleName, ModuleNames, Succeeded, !Info, !IO) :-
+ verbose_msg(io.write_string("Making Java class files\n"), !IO),
+ ToJavaFile =
+ (pred(ModuleName::in, JavaFile::out, !.IO::di, !:IO::uo) is det :-
+ module_name_to_file_name(ModuleName, ".java", do_create_dirs,
+ JavaFile, !IO)
+ ),
+ list.map_foldl(ToJavaFile, ModuleNames, JavaFiles, !IO),
+ % We redirect errors to a file named after the main module.
+ build_with_output_redirect(MainModuleName,
+ build_java_files_2(JavaFiles), Succeeded, !Info, !IO).
+
+:- pred build_java_files_2(list(string)::in, io.output_stream::in, bool::out,
+ make_info::in, make_info::out, io::di, io::uo) is det.
+
+build_java_files_2(JavaFiles, ErrorStream, Succeeded, !Info, !IO) :-
+ call_in_forked_process(
+ compile_target_code.compile_java_files(ErrorStream, JavaFiles),
+ Succeeded, !IO).
+
+:- pred delete_java_class_timestamps(string::in, maybe_error(timestamp)::in,
+ file_timestamps::in, file_timestamps::out) is det.
+
+delete_java_class_timestamps(FileName, MaybeTimestamp, !Timestamps) :-
+ ( string.suffix(FileName, ".class") ->
+ true
+ ;
+ svmap.det_insert(FileName, MaybeTimestamp, !Timestamps)
+ ).
+
+%-----------------------------------------------------------------------------%
+
make_misc_target(MainModuleName - TargetType, Succeeded, !Info, !IO) :-
build_with_module_options(MainModuleName, [],
make_misc_target_builder(MainModuleName - TargetType),
diff --git a/compiler/mercury_compile.m b/compiler/mercury_compile.m
index 489c454..8e1c736 100644
--- a/compiler/mercury_compile.m
+++ b/compiler/mercury_compile.m
@@ -1687,7 +1687,7 @@
mercury_compile_after_front_end(NestedSubModules, FindTimestampFiles,
io.output_stream(OutputStream, !IO),
module_name_to_file_name(ModuleName, ".java",
do_not_create_dirs, JavaFile, !IO),
- compile_target_code.compile_java_file(OutputStream, JavaFile,
+ compile_target_code.compile_java_files(OutputStream,
[JavaFile],
Succeeded, !IO),
maybe_set_exit_status(Succeeded, !IO)
),
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list