diff --git a/compiler/link_target_code.m b/compiler/link_target_code.m index 06197797c..3db123856 100644 --- a/compiler/link_target_code.m +++ b/compiler/link_target_code.m @@ -442,8 +442,6 @@ construct_cli_shell_script_for_csharp(Globals, ExeFileName, ContentStr) :- create_exe_or_lib_for_java(ProgressStream, Globals, LinkedTargetType, MainModuleName, FullJarFileName, ObjectList, Succeeded, !IO) :- - globals.lookup_string_option(Globals, java_archive_command, Jar), - list_class_files_for_jar(Globals, ObjectList, ClassSubDir, ListClassFiles, !IO), ( @@ -454,10 +452,13 @@ create_exe_or_lib_for_java(ProgressStream, Globals, LinkedTargetType, ), % Write the list of class files to a temporary file and pass the name of - % the temporary file to jar using @syntax. The list of class files can be - % extremely long. We create the temporary file in the current directory to - % avoid problems under Cygwin, where absolute paths will be interpreted - % incorrectly when passed to a non-Cygwin jar program. + % the temporary file to jar using @syntax. We do this because the list + % of class files can be extremely long, and can cause problems with + % limited argument vector lengths. + % + % We create the temporary file in the current directory to avoid problems + % under Cygwin, where absolute paths will be interpreted incorrectly + % when passed to a non-Cygwin jar program. open_temp_output_with_naming_scheme(".", "mtmp", "", TempFileResult, !IO), ( TempFileResult = ok({TempFileName, Stream}), @@ -465,8 +466,9 @@ create_exe_or_lib_for_java(ProgressStream, Globals, LinkedTargetType, ListClassFiles, !IO), io.close_output(Stream, !IO), + globals.lookup_string_option(Globals, java_archive_command, JarCmd), Cmd = string.append_list( - [Jar, " cf ", FullJarFileName, " @", TempFileName]), + [JarCmd, " cf ", FullJarFileName, " @", TempFileName]), invoke_system_command(Globals, ProgressStream, ProgressStream, cmd_verbose_commands, Cmd, Succeeded0, !IO), io.file.remove_file(TempFileName, _, !IO), diff --git a/compiler/make.program_target.m b/compiler/make.program_target.m index a30cc3b7b..1fe7892a2 100644 --- a/compiler/make.program_target.m +++ b/compiler/make.program_target.m @@ -736,10 +736,10 @@ build_linked_target(ProgressStream, NoLinkObjsGlobals, CompilationTarget, PIC, % timestamp checking above -- they will have been checked when the % module's object file was built. list.map_foldl2( - get_module_foreign_object_files(ProgressStream, NoLinkObjsGlobals, + get_module_fact_table_object_files(ProgressStream, NoLinkObjsGlobals, PIC), - AllModulesList, ForeignObjectFileNameLists, !Info, !IO), - ForeignObjectFileNames = list.condense(ForeignObjectFileNameLists), + AllModulesList, FactTableObjFileNameLists, !Info, !IO), + FactTableObjFileNames = list.condense(FactTableObjFileNameLists), ( CompilationTarget = target_c, @@ -757,10 +757,19 @@ build_linked_target(ProgressStream, NoLinkObjsGlobals, CompilationTarget, PIC, list.map2(module_name_to_file_name(NoLinkObjsGlobals, $pred, Ext), ProgModules, ProgModuleObjFileNames, _ProgModuleObjFileNamesProposed), - % LinkObjectFileNames may contain `.a' files which must come - % after all the object files on the linker command line. + % InitObjectFileNames, passed from maybe_build_linked_target: + % Contains the _init.o object file. Makes sense only for C. + % ProgModuleObjFileNames: + % Contains the "object" files of the modules of the program itself. + % FactTableObjFileNames: + % Contains the set of object files implementing fact tables. + % Makes sense only for C. + % LinkObjectFileNames, passed from maybe_build_linked_targets: + % Contains the value of the link_objects option. This consists of + % .a files (that make sense only for C) that must come after + % all the object files on the linker command line. AllObjects = InitObjectFileNames ++ ProgModuleObjFileNames ++ - ForeignObjectFileNames ++ LinkObjectFileNames, + FactTableObjFileNames ++ LinkObjectFileNames, ( ( CompilationTarget = target_c ; CompilationTarget = target_java @@ -793,21 +802,21 @@ build_linked_target(ProgressStream, NoLinkObjsGlobals, CompilationTarget, PIC, maybe_write_msg_locked(ProgressStream, !.Info, ErrorMsg, !IO) ). -:- pred get_module_foreign_object_files(io.text_output_stream::in, globals::in, - pic::in, module_name::in, list(file_name)::out, +:- pred get_module_fact_table_object_files(io.text_output_stream::in, + globals::in, pic::in, module_name::in, list(file_name)::out, make_info::in, make_info::out, io::di, io::uo) is det. -get_module_foreign_object_files(ProgressStream, Globals, PIC, - ModuleName, ForeignObjectFiles, !MakeInfo, !IO) :- +get_module_fact_table_object_files(ProgressStream, Globals, PIC, + ModuleName, FactTableObjFiles, !MakeInfo, !IO) :- get_maybe_module_dep_info(ProgressStream, Globals, ModuleName, MaybeModuleDepInfo, !MakeInfo, !IO), ( MaybeModuleDepInfo = some_module_dep_info(ModuleDepInfo), get_any_fact_table_object_code_files(Globals, PIC, ModuleDepInfo, - ForeignFiles, !IO), - ForeignObjectFiles = list.map( + FactTableFiles, !IO), + FactTableObjFiles = list.map( (func(foreign_code_file(_, _, ObjFile)) = ObjFile), - ForeignFiles) + FactTableFiles) ; MaybeModuleDepInfo = no_module_dep_info, % This error should have been detected earlier. diff --git a/compiler/mercury_compile_main.m b/compiler/mercury_compile_main.m index 3865d54a7..754f5a472 100644 --- a/compiler/mercury_compile_main.m +++ b/compiler/mercury_compile_main.m @@ -42,7 +42,9 @@ :- import_module backend_libs. :- import_module backend_libs.compile_target_code. :- import_module backend_libs.create_launchers. +:- import_module backend_libs.link_target_code. :- import_module backend_libs.link_target_code_c. +:- import_module backend_libs.link_target_util. :- import_module check_hlds. :- import_module check_hlds.switch_detection. :- import_module hlds. @@ -441,22 +443,26 @@ do_op_mode_args(ProgressStream, ErrorStream, Globals, OpModeArgs, % Print all remaining module-specific error_specs, % as well as the ones generated just above. + % + % Note that the call to generate_executable below CAN generate + % new error_specs, which it also writes out. It is ok for any such + % diagnostics to come out after the ones we print here. write_not_yet_written_specs(ErrorStream, Globals, !MaybeWrittenSpecs, !IO), - io.get_exit_status(ExitStatus, !IO), ( if OpModeArgs = opma_augment(opmau_front_and_middle( opfam_target_object_and_executable)), ModulesToLink = cord.list(ModulesToLinkCord), - ModulesToLink = [FirstModule | _] + ModulesToLink = [FirstModuleName | _] then + io.get_exit_status(ExitStatus, !IO), ( if ExitStatus = 0 then ExtraObjFiles = cord.list(ExtraObjFilesCord), generate_executable(ProgressStream, ErrorStream, Globals, InvokedByMmcMake, Params, - FirstModule, ModulesToLink, ExtraObjFiles, !IO) + FirstModuleName, ModulesToLink, ExtraObjFiles, !IO) else if all_args_end_in_dot_m(Args) = yes, AllSpecsSoFar = @@ -561,27 +567,28 @@ could_not_read_some_int_file([Spec | Specs]) = CouldNotRead :- list(module_name)::in, list(string)::in, io::di, io::uo) is det. generate_executable(ProgressStream, ErrorStream, Globals, InvokedByMmcMake, - Params, FirstModule, ModulesToLink, ExtraObjFiles, !IO) :- + Params, FirstModuleName, ModulesToLink, ExtraObjFiles, !IO) :- globals.get_target(Globals, Target), ( Target = target_java, % For Java, at the "link" step we just generate a shell script; % the actual linking will be done at runtime by the Java interpreter. - create_java_shell_script(ProgressStream, Globals, FirstModule, + create_java_shell_script(ProgressStream, Globals, FirstModuleName, Succeeded, !IO) ; - ( Target = target_c - ; Target = target_csharp - ), - % XXX The code below is appropriate for creating real, actual - % executable files, as used by the C backend. Why are we executing - % the same code for C#, whose backend uses a launcher script, - % not a real executable? This totally does the wrong thing - % for e.g. "mmc --grade csharp a.m b.m c.m". - % - % XXX STREAM - % Should we go from non-main-module-specific - % progress and error streams to main-module-specific streams? + Target = target_csharp, + Ext = ext_cur_ngs_gs(ext_cur_ngs_gs_target_cs), + % The next two lines duplicate the relevant parts of the + % build_linked_target predicate in make.program_target.m. + % XXX LEGACY + list.map2(module_name_to_file_name(Globals, $pred, Ext), + ModulesToLink, CssFilesToLink, _CssFilesToLinkProposed), + link_files_into_executable_or_library_for_c_cs_java(ProgressStream, + Globals, csharp_executable, FirstModuleName, CssFilesToLink, + Specs, Succeeded, !IO), + write_error_specs(ErrorStream, Globals, Specs, !IO) + ; + Target = target_c, ( InvokedByMmcMake = op_mode_invoked_by_mmc_make, % `mmc --make' has already set up the options. @@ -594,7 +601,7 @@ generate_executable(ProgressStream, ErrorStream, Globals, InvokedByMmcMake, globals.get_maybe_stdlib_grades(Globals, MaybeStdLibGrades), setup_for_build_with_module_options(ProgressStream, DefaultOptionTable, MaybeStdLibGrades, not_invoked_by_mmc_make, - FirstModule, Params, [], MayBuild, !IO), + FirstModuleName, Params, [], MayBuild, !IO), ( MayBuild = may_not_build(Specs), Succeeded = did_not_succeed