Files
mercury/compiler/make.program_target.m
Simon Taylor a719e74ee9 Rearrange some code after the `--make' change.
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.
2002-03-18 04:44:16 +00:00

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).
%-----------------------------------------------------------------------------%