mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-16 06:14:59 +00:00
Estimated hours taken: 1.5 Branches: main Rearrange some code after the `--make' change. This was not done as part of that change for ease of reviewing. compiler/mercury_compile.m: compiler/compile_target_code.m: compiler/make.m: compiler/make.module_target.m: compiler/make.program_target.m: Move code to compile the generated code into compile_target_code.m. compiler/make.util.m: compiler/passes_aux.m: compiler/process_util.m: Move process and signal handling functionality into process_util.m. compiler/Mmakefile: Compile process_util.c with `--no-ansi' so that the declarations of `struct sigaction' and `kill' are available on Linux. compiler/notes/compiler_design.html: Document compile_target_code.m and process_util.m. Move timestamp.m into the "Miscellaneous" section (it's used by make as well as smart recompilation). Fix the documentation of options_file.m.
399 lines
12 KiB
Mathematica
399 lines
12 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2002 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
:- module make__program_target.
|
|
|
|
:- interface.
|
|
|
|
:- pred make_linked_target(linked_target_file::in, bool::out,
|
|
make_info::in, make_info::out,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
:- pred make_misc_target(pair(module_name, misc_target_type)::in,
|
|
bool::out, make_info::in, make_info::out,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- implementation.
|
|
|
|
make_linked_target(MainModuleName - FileType, Succeeded, Info0, Info) -->
|
|
find_reachable_local_modules(MainModuleName, DepsSuccess,
|
|
AllModules, Info0, Info1),
|
|
globals__io_lookup_bool_option(keep_going, KeepGoing),
|
|
( { DepsSuccess = no, KeepGoing = no } ->
|
|
{ Succeeded = no },
|
|
{ Info = Info1 }
|
|
;
|
|
globals__io_get_target(CompilationTarget),
|
|
( { CompilationTarget = asm } ->
|
|
% An assembler file is only produced for the top-level
|
|
% module in each source file.
|
|
list__foldl3(
|
|
(pred(ModuleName::in, ObjModules0::in, ObjModules1::out,
|
|
MInfo0::in, MInfo::out, di, uo) is det -->
|
|
get_module_dependencies(ModuleName, MaybeImports,
|
|
MInfo0, MInfo),
|
|
{
|
|
MaybeImports = yes(Imports),
|
|
ModuleName = Imports ^ source_file_module_name
|
|
->
|
|
ObjModules1 = [ModuleName | ObjModules0]
|
|
;
|
|
ObjModules1 = ObjModules0
|
|
}
|
|
),
|
|
set__to_sorted_list(AllModules), [],
|
|
ObjModules, Info1, Info4)
|
|
;
|
|
{ Info4 = Info1 },
|
|
{ ObjModules = set__to_sorted_list(AllModules) }
|
|
),
|
|
|
|
globals__io_get_globals(Globals),
|
|
module_name_to_file_name(MainModuleName,
|
|
linked_target_extension(Globals, FileType),
|
|
no, OutputFileName),
|
|
get_file_timestamp([dir__this_directory], OutputFileName,
|
|
MaybeTimestamp, Info4, Info5),
|
|
|
|
globals__io_lookup_string_option(pic_object_file_extension, PicObjExt),
|
|
globals__io_lookup_string_option(object_file_extension, ObjExt),
|
|
{ FileType = shared_library, PicObjExt \= ObjExt ->
|
|
ObjectCodeType = pic,
|
|
ObjExtToUse = PicObjExt
|
|
;
|
|
ObjectCodeType = non_pic,
|
|
ObjExtToUse = ObjExt
|
|
},
|
|
|
|
%
|
|
% Build the `.c' files first so that errors are
|
|
% reported as soon as possible.
|
|
%
|
|
{
|
|
CompilationTarget = c,
|
|
IntermediateTargetType = c_code,
|
|
ObjectTargetType = object_code(ObjectCodeType)
|
|
;
|
|
CompilationTarget = asm,
|
|
IntermediateTargetType = asm_code(ObjectCodeType),
|
|
ObjectTargetType = object_code(ObjectCodeType)
|
|
;
|
|
CompilationTarget = il,
|
|
IntermediateTargetType = il_code,
|
|
ObjectTargetType = il_asm
|
|
;
|
|
CompilationTarget = java,
|
|
IntermediateTargetType = java_code,
|
|
% XXX Whoever finishes the Java backend can fill this in.
|
|
ObjectTargetType = object_code(non_pic)
|
|
},
|
|
|
|
{ IntermediateTargets = make_dependency_list(ObjModules,
|
|
IntermediateTargetType) },
|
|
{ ObjTargets = make_dependency_list(ObjModules, ObjectTargetType) },
|
|
|
|
foldl2_maybe_stop_at_error(KeepGoing,
|
|
foldl2_maybe_stop_at_error(KeepGoing, make_module_target),
|
|
[IntermediateTargets, ObjTargets], _, Info5, Info6),
|
|
check_dependencies(OutputFileName, MaybeTimestamp,
|
|
ObjTargets, BuildDepsResult, Info6, Info7),
|
|
|
|
(
|
|
{ DepsSuccess = yes },
|
|
{ BuildDepsResult \= error }
|
|
->
|
|
build_with_check_for_interrupt(
|
|
build_with_module_options_and_output_redirect(
|
|
MainModuleName, [],
|
|
build_linked_target(MainModuleName, FileType,
|
|
OutputFileName, MaybeTimestamp, AllModules,
|
|
ObjModules, CompilationTarget, ObjExtToUse,
|
|
DepsSuccess, BuildDepsResult)),
|
|
linked_target_cleanup(MainModuleName, FileType, OutputFileName,
|
|
CompilationTarget),
|
|
Succeeded, Info7, Info)
|
|
;
|
|
{ Succeeded = no },
|
|
{ Info = Info7 }
|
|
)
|
|
).
|
|
|
|
:- pred build_linked_target(module_name::in, linked_target_type::in,
|
|
file_name::in, maybe_error(timestamp)::in, set(module_name)::in,
|
|
list(module_name)::in, compilation_target::in, string::in, bool::in,
|
|
dependencies_result::in, list(string)::in, io__output_stream::in,
|
|
bool::out, make_info::in, make_info::out,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
build_linked_target(MainModuleName, FileType, OutputFileName, MaybeTimestamp,
|
|
AllModules, ObjModules, CompilationTarget, ObjExtToUse,
|
|
DepsSuccess, BuildDepsResult, _, ErrorStream, Succeeded,
|
|
Info0, Info) -->
|
|
|
|
globals__io_lookup_accumulating_option(link_objects, ExtraObjects0),
|
|
|
|
% Clear the option -- we'll pass the list of files directly.
|
|
globals__io_set_option(link_objects, accumulating([])),
|
|
|
|
%
|
|
% Remake the `_init.o' file.
|
|
% XXX We should probably make a `_init.o' file for shared
|
|
% libraries linked using dlopen().
|
|
%
|
|
{ AllModulesList = set__to_sorted_list(AllModules) },
|
|
(
|
|
{ FileType = executable },
|
|
{ CompilationTarget = c ; CompilationTarget = asm }
|
|
->
|
|
compile_target_code__make_init_obj_file(ErrorStream,
|
|
MainModuleName, AllModulesList, InitObjectResult),
|
|
(
|
|
{ InitObjectResult = yes(InitObject) },
|
|
|
|
% We may need to update the timestamp
|
|
% of the `_init.o' file.
|
|
{ Info1 = Info0 ^ file_timestamps :=
|
|
map__delete(Info0 ^ file_timestamps,
|
|
InitObject) },
|
|
{ ExtraObjects = [InitObject | ExtraObjects0] },
|
|
{ DepsResult2 = BuildDepsResult }
|
|
;
|
|
{ InitObjectResult = no },
|
|
{ Info1 = Info0 },
|
|
{ DepsResult2 = error },
|
|
{ ExtraObjects = ExtraObjects0 }
|
|
)
|
|
;
|
|
{ DepsResult2 = BuildDepsResult },
|
|
{ Info1 = Info0 },
|
|
{ ExtraObjects = ExtraObjects0 }
|
|
),
|
|
|
|
list__map_foldl2(get_file_timestamp([dir__this_directory]),
|
|
ExtraObjects, ExtraObjectTimestamps, Info1, Info2),
|
|
check_dependency_timestamps(OutputFileName, MaybeTimestamp,
|
|
ExtraObjects, io__write, ExtraObjectTimestamps,
|
|
ExtraObjectDepsResult),
|
|
|
|
{ DepsResult3 = ( DepsSuccess = yes -> DepsResult2 ; error ) },
|
|
{ DepsResult3 = error, DepsResult = DepsResult3
|
|
; DepsResult3 = out_of_date, DepsResult = DepsResult3
|
|
; DepsResult3 = up_to_date, DepsResult = ExtraObjectDepsResult
|
|
},
|
|
(
|
|
{ DepsResult = error },
|
|
file_error(OutputFileName),
|
|
{ Succeeded = no },
|
|
{ Info = Info2 }
|
|
;
|
|
{ DepsResult = up_to_date },
|
|
{ Succeeded = yes },
|
|
{ Info = Info2 }
|
|
;
|
|
{ DepsResult = out_of_date },
|
|
maybe_make_linked_target_message(OutputFileName),
|
|
|
|
%
|
|
% Find the extra object files for externally compiled
|
|
% foreign procedures and fact tables. We don't need
|
|
% to include these in the timestamp checking above --
|
|
% they will have been checked when the module's object
|
|
% file was built.
|
|
%
|
|
list__map_foldl2(
|
|
(pred(ModuleName::in, ForeignFiles::out,
|
|
MakeInfo0::in, MakeInfo::out, di, uo) is det -->
|
|
get_module_dependencies(ModuleName, MaybeImports,
|
|
MakeInfo0, MakeInfo),
|
|
(
|
|
{ MaybeImports = yes(Imports) },
|
|
external_foreign_code_files(Imports, ForeignFiles)
|
|
;
|
|
{ MaybeImports = no },
|
|
% This error should have been detected earlier.
|
|
{ error(
|
|
"build_linked_target: error in dependencies") }
|
|
)
|
|
), AllModulesList, ExtraForeignFiles, Info2, Info3),
|
|
{ ForeignObjects = list__map(
|
|
(func(foreign_code_file(_, _, ObjFile)) = ObjFile),
|
|
list__condense(ExtraForeignFiles)) },
|
|
{ AllExtraObjects = ExtraObjects ++ ForeignObjects },
|
|
|
|
list__map_foldl(
|
|
(pred(ObjModule::in, ObjToLink::out, di, uo) is det -->
|
|
module_name_to_file_name(ObjModule,
|
|
ObjExtToUse, no, ObjToLink)
|
|
), ObjModules, ObjList),
|
|
{ AllObjects = AllExtraObjects ++ ObjList },
|
|
|
|
(
|
|
{ CompilationTarget = c },
|
|
% Run the link in a separate process so it can
|
|
% be killed if an interrupt is received.
|
|
call_in_forked_process(
|
|
compile_target_code__link(ErrorStream,
|
|
FileType, MainModuleName, AllObjects),
|
|
Succeeded)
|
|
;
|
|
{ CompilationTarget = asm },
|
|
% Run the link in a separate process so it can
|
|
% be killed if an interrupt is received.
|
|
call_in_forked_process(
|
|
compile_target_code__link(ErrorStream,
|
|
FileType, MainModuleName, AllObjects),
|
|
Succeeded)
|
|
;
|
|
%
|
|
% IL doesn't need any linking. XXX Is this right?
|
|
%
|
|
{ CompilationTarget = il },
|
|
{ Succeeded = yes }
|
|
;
|
|
{ CompilationTarget = java },
|
|
{ Succeeded = no },
|
|
io__write_string(
|
|
"Sorry, not implemented, linking for `--target java'")
|
|
),
|
|
|
|
( { Succeeded = yes } ->
|
|
{ Info = Info3 ^ file_timestamps :=
|
|
map__delete(Info3 ^ file_timestamps,
|
|
OutputFileName) }
|
|
;
|
|
file_error(OutputFileName),
|
|
{ Info = Info3 }
|
|
)
|
|
).
|
|
|
|
:- pred linked_target_cleanup(module_name::in, linked_target_type::in,
|
|
file_name::in, compilation_target::in, make_info::in, make_info::out,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
linked_target_cleanup(MainModuleName, FileType, OutputFileName,
|
|
CompilationTarget, Info0, Info) -->
|
|
remove_file(OutputFileName, Info0, Info1),
|
|
(
|
|
{ FileType = executable },
|
|
{ CompilationTarget = c
|
|
; CompilationTarget = asm
|
|
}
|
|
->
|
|
globals__io_lookup_string_option(object_file_extension,
|
|
ObjExt),
|
|
remove_file(MainModuleName, "_init.c", Info1, Info2),
|
|
remove_file(MainModuleName, "_init" ++ ObjExt, Info2, Info)
|
|
;
|
|
{ Info = Info1 }
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
make_misc_target(MainModuleName - TargetType, Succeeded, Info0, Info) -->
|
|
% Don't rebuild dependencies when cleaning up.
|
|
{ RebuildDeps = Info0 ^ rebuild_dependencies },
|
|
{ ( TargetType = clean ; TargetType = realclean ) ->
|
|
Info1 = Info0 ^ rebuild_dependencies := no
|
|
;
|
|
Info1 = Info0
|
|
},
|
|
find_reachable_local_modules(MainModuleName, Succeeded0,
|
|
AllModules0, Info1, Info2),
|
|
{ Info3 = Info2 ^ rebuild_dependencies := RebuildDeps },
|
|
|
|
{ AllModules = set__to_sorted_list(AllModules0) },
|
|
(
|
|
{ TargetType = clean },
|
|
{ Succeeded = yes },
|
|
list__foldl2(make_clean, AllModules, Info3, Info)
|
|
;
|
|
{ TargetType = realclean },
|
|
{ Succeeded = yes },
|
|
list__foldl2(make_realclean, AllModules, Info3, Info4),
|
|
globals__io_lookup_string_option(executable_file_extension,
|
|
ExeExt),
|
|
globals__io_lookup_string_option(library_extension, LibExt),
|
|
globals__io_lookup_string_option(shared_library_extension,
|
|
SharedLibExt),
|
|
|
|
list__foldl2(remove_file(MainModuleName),
|
|
[ExeExt, LibExt, SharedLibExt, "_init.c", "_init.o"],
|
|
Info4, Info)
|
|
;
|
|
{ TargetType = check },
|
|
globals__io_lookup_bool_option(keep_going, KeepGoing),
|
|
( { Succeeded0 = no, KeepGoing = no } ->
|
|
{ Info = Info3 },
|
|
{ Succeeded = no }
|
|
;
|
|
foldl2_maybe_stop_at_error(KeepGoing,
|
|
make_module_target,
|
|
make_dependency_list(AllModules, errors),
|
|
Succeeded1, Info3, Info),
|
|
{ Succeeded = Succeeded0 `and` Succeeded1 }
|
|
)
|
|
;
|
|
{ TargetType = install_library },
|
|
{ Succeeded = no },
|
|
{ error("sorry, not implemented: mmc --make module.install") }
|
|
).
|
|
|
|
:- pred make_clean(module_name::in, make_info::in, make_info::out,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
make_clean(ModuleName, Info0, Info) -->
|
|
list__foldl2(remove_target_file(ModuleName),
|
|
[errors, c_code, c_header,
|
|
object_code(pic), object_code(non_pic),
|
|
asm_code(pic), asm_code(non_pic),
|
|
il_code, java_code
|
|
],
|
|
Info0, Info1),
|
|
|
|
globals__io_lookup_string_option(object_file_extension, ObjExt),
|
|
list__foldl2(remove_file(ModuleName),
|
|
["_init.c", "_init" ++ ObjExt, ".used", ".prof",
|
|
".derived_schema", ".base_schema"],
|
|
Info1, Info2),
|
|
|
|
get_module_dependencies(ModuleName, MaybeImports, Info2, Info3),
|
|
(
|
|
{ MaybeImports = yes(Imports) },
|
|
external_foreign_code_files(Imports, ForeignCodeFiles),
|
|
list__foldl2(
|
|
(pred(ForeignCodeFile::in, MakeInfo0::in, MakeInfo::out,
|
|
di, uo) is det -->
|
|
{ ForeignCodeFile = foreign_code_file(_,
|
|
TargetFile, ObjectFile) },
|
|
remove_file(TargetFile, MakeInfo0, MakeInfo1),
|
|
remove_file(ObjectFile, MakeInfo1, MakeInfo)
|
|
), ForeignCodeFiles, Info3, Info)
|
|
;
|
|
{ MaybeImports = no },
|
|
{ Info = Info3 }
|
|
).
|
|
|
|
:- pred make_realclean(module_name::in, make_info::in, make_info::out,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
make_realclean(ModuleName, Info0, Info) -->
|
|
make_clean(ModuleName, Info0, Info1),
|
|
list__foldl2(remove_target_file(ModuleName),
|
|
[private_interface, long_interface, short_interface,
|
|
unqualified_short_interface, intermodule_interface,
|
|
aditi_code, c_header
|
|
],
|
|
Info1, Info2),
|
|
globals__io_lookup_string_option(executable_file_extension, ExeExt),
|
|
globals__io_lookup_string_option(library_extension, LibExt),
|
|
globals__io_lookup_string_option(shared_library_extension,
|
|
SharedLibExt),
|
|
list__foldl2(remove_file(ModuleName),
|
|
[module_dep_file_extension, ExeExt, LibExt, SharedLibExt],
|
|
Info2, Info).
|
|
|
|
%-----------------------------------------------------------------------------%
|