mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 01:13:30 +00:00
compiler/make.make_info.m:
... and give the type a non-misleading name.
compiler/make.prereqs.m:
Conform to the change above.
compiler/make.program_target.m:
Fix too-long line.
1449 lines
63 KiB
Mathematica
1449 lines
63 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2002-2011 The University of Melbourne.
|
|
% Copyright (C) 2013-2017, 2019-2025 The Mercury team.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: make.prereqs.m.
|
|
% Original author: stayl.
|
|
% Author of current version: zs.
|
|
%
|
|
% This job of this module to find, for a given file T (a target file),
|
|
% which *other* Pi (prerequisite files) you need in order to build T.
|
|
% Effectively, given a file name T, it finds all the prerequisites
|
|
% that occur on the right hand sides of the (implicit) make rules
|
|
% whose left hand side contains T:
|
|
%
|
|
% T: P1 P2 ...
|
|
%
|
|
% Note that we find only the *direct* prereqs of T. This means that
|
|
% we return e.g. P1, but not the files needed to build P1 itself.
|
|
% (Unless by some unlikely chance, the files needed to build P1
|
|
% are also direct prereqs of T itself.)
|
|
%
|
|
% We should consider returning effectively a tree, whose nodes are file names,
|
|
% where the children of a node are the direct prereqs of the file represented
|
|
% by that node, but which have their own prereqs as their children, all the way
|
|
% down to the files that have *no* prerequisites. We could construct such
|
|
% a tree for every target named on the "mmc --make" command line, yielding
|
|
% effectively a forest.
|
|
%
|
|
% Having the full forest available before we start building the first target
|
|
% should allow us to increase parallelism by exploiting our knowledge of
|
|
% the structure of Mercury dependencies. We could follow a strategy of
|
|
% building files in a bottom up order, like a layercake:
|
|
%
|
|
% - building all needed .int3 files
|
|
% - building all needed .int0 files
|
|
% - building all needed .int and .int2 files
|
|
% - building all needed .opt files (if enabled)
|
|
% - building all needed .trans_opt files (if enabled)
|
|
% - building all needed .c/.java/.cs files, depending on the target language
|
|
% - building all needed .o/.jar/.dll files, depending on the target language
|
|
% - building all needed executables or their equivalents
|
|
%
|
|
% In most of these stages, once all the files of the previous stages have been
|
|
% built, it should be possible to build all files with the given suffix
|
|
% in that stage in parallel. The exceptions are the creation of .int0 files
|
|
% (where the creation of the .int0 files for e.g. module A and module A.B
|
|
% may not be independent), and the creation of .trans_opt files (which must
|
|
% respect the chosen order between those files.)
|
|
%
|
|
% In the absence of this global view, it is possible for e.g. an invocation
|
|
% of "mmc --make -j8 prog" the decide to build A.c, B.c, C.c, D.c, E.c, F.c
|
|
% and G.c at once, but if all of those modules import module H, then all
|
|
% seven build processes may need to stall waiting for the completion of
|
|
% the task that builds H.int. This cannot happen with the layercake approach.
|
|
%
|
|
% The one drawback of the layercake approach is that computing the full
|
|
% prereq tree before building the first file may feel like a slow startup
|
|
% to the user. This is definitely a much smaller concern now (the 2020s)
|
|
% than it was in the 1980s, but whether the startup delay it causes
|
|
% is below the perceptibility threshold for typical size projects,
|
|
% is something that can be answered only by empirical testing.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module make.prereqs.
|
|
:- interface.
|
|
|
|
:- import_module libs.
|
|
:- import_module libs.globals.
|
|
:- import_module make.make_info.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.module_dep_info.
|
|
|
|
:- import_module io.
|
|
:- import_module set.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type find_prereqs_result
|
|
---> could_not_find_some_prereqs(set(target_id))
|
|
% There were some prerequisites that we could not find.
|
|
% The set specifies the prerequisites we *could* find.
|
|
; found_all_prereqs(set(target_id)).
|
|
% We found all prerequisites, and here they are.
|
|
|
|
% find_direct_prereqs_of_target_file(ProgressStream, Globals,
|
|
% CompilationTaskType, ModuleDepInfo, TargetFile,
|
|
% PrereqsResult, !Info, !IO):
|
|
%
|
|
% The TargetType and ModuleIndexes arguments define a set of make targets.
|
|
% Return in PrereqsResult the target_id_indexes of all the files
|
|
% that these make targets depend on, and which therefore have to be built
|
|
% before we can build those make targets.
|
|
%
|
|
:- pred find_direct_prereqs_of_target_file(io.text_output_stream::in,
|
|
globals::in, compilation_task_type::in, module_dep_info::in,
|
|
target_file::in, find_prereqs_result::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module backend_libs.
|
|
:- import_module backend_libs.compile_target_code.
|
|
:- import_module libs.file_util.
|
|
:- import_module libs.maybe_util.
|
|
:- import_module libs.options.
|
|
:- import_module make.file_names.
|
|
:- import_module make.find_local_modules.
|
|
:- import_module make.get_module_dep_info.
|
|
:- import_module make.index_set.
|
|
:- import_module make.prereqs_cache.
|
|
:- import_module make.util.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.file_names.
|
|
:- import_module parse_tree.module_baggage.
|
|
:- import_module parse_tree.prog_data_foreign.
|
|
|
|
:- import_module bool.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module sparse_bitset.
|
|
:- import_module string.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% XXX MDNEW add loop on top to find indirect prereqs
|
|
% That way, complexity is given by
|
|
% #layers in dependency hierarchy * avg width of each layer
|
|
% instead of by #paths through the layers,
|
|
% but ONLY if we don't repeat this work later, in submakes.
|
|
%
|
|
% XXX MDNEW Sort the final, overall set of prereqs
|
|
% - first on target type (.int3, .int0, .int/.int2, .opt etc)
|
|
% - then on the list of module name components
|
|
%
|
|
% Sorting on target type should put prereqs before the things they are prereqs
|
|
% *for* in all cases where the target types differ.
|
|
%
|
|
% Sorting on the list of module name components should put prereqs before
|
|
% the things they are prereqs *for* in all cases where the target types match.
|
|
%
|
|
% For parallel makes, we would also need to return, for each element of the
|
|
% list, the set of earlier elements that are its prereqs.
|
|
%
|
|
% XXX MDNEW We should never put any targets involving nested submodules into
|
|
% sets of depenendency_file_indexes. Those targets will be made as a side
|
|
% effect of making the same target type for the top module in the source file.
|
|
% However, the prereqs of a nested submodule, such as any fact table files
|
|
% it may need, must become the prereqs of the top-level module of their
|
|
% source file.
|
|
|
|
find_direct_prereqs_of_target_file(ProgressStream, Globals,
|
|
CompilationTaskType, ModuleDepInfo, TargetFile, PrereqsResult,
|
|
!Info, !IO) :-
|
|
TargetFile = target_file(ModuleName, TargetType),
|
|
(
|
|
CompilationTaskType = process_module(_),
|
|
module_dep_info_get_maybe_top_module(ModuleDepInfo, MaybeTopModule),
|
|
NestedSubModulesToCheck =
|
|
get_nested_children_list_of_top_module(MaybeTopModule)
|
|
;
|
|
( CompilationTaskType = target_code_to_object_code(_)
|
|
; CompilationTaskType = fact_table_code_to_object_code(_, _)
|
|
),
|
|
NestedSubModulesToCheck = []
|
|
),
|
|
KeepGoing = make_info_get_keep_going(!.Info),
|
|
(
|
|
NestedSubModulesToCheck = [],
|
|
ModulesToCheck = [ModuleName],
|
|
module_name_to_index(ModuleName, ModuleIndex, !Info),
|
|
find_direct_prereqs_of_module_target(ProgressStream, KeepGoing,
|
|
Globals, TargetType, ModuleIndex, Succeeded, PrereqIndexes0,
|
|
!Info, !IO)
|
|
;
|
|
NestedSubModulesToCheck = [_ | _],
|
|
ModulesToCheck = [ModuleName | NestedSubModulesToCheck],
|
|
module_names_to_index_set(ModulesToCheck, ModuleIndexesToCheckSet,
|
|
!Info),
|
|
ModuleIndexesToCheck =
|
|
index_set_to_sorted_list(ModuleIndexesToCheckSet),
|
|
find_direct_prereqs_of_nested_module_targets(ProgressStream, KeepGoing,
|
|
Globals, TargetType, ModuleIndexesToCheck,
|
|
succeeded, Succeeded, index_set_init, PrereqIndexes0, !Info, !IO)
|
|
),
|
|
( if TargetType = module_target_int0 then
|
|
% XXX Simon Taylor's comment, added originally to make.module_target.m
|
|
% on 2002 Apr 23, says:
|
|
%
|
|
% Avoid circular dependencies (the `.int0' files for the
|
|
% nested sub-modules depend on this module's `.int0' file).
|
|
%
|
|
% The log message of the commit says:
|
|
%
|
|
% The `.int0' file for a module depends on the `.int0' file for the
|
|
% parent module, which caused circular dependencies with nested
|
|
% submodules, resulting in a compiler abort. The circular
|
|
% dependencies are now removed from the list of dependencies to make.
|
|
% Test case: tests/valid/foreign_type_spec.m.
|
|
%
|
|
% That test case, after being moved to valid_seq, was deleted together
|
|
% with the IL backend. It seems to have consisted of a main module
|
|
% and a separate submodule, so the NestedSubModules part of
|
|
% ModulesToCheck would have been irrelevant. And the ModuleName part
|
|
% of ModulesToCheck seems to be redundant: if the *target* is
|
|
% ModuleName.int0, then surely ModuleName.int0 cannot be a prereq?
|
|
%
|
|
% For these reasons, the code here seems to me (zs) to be too crude:
|
|
% it seems to delete far more prereqs than just the ones that may
|
|
% cause the problem that it was added to address.
|
|
ToDelete = make_target_id_list(ModulesToCheck, module_target_int0),
|
|
target_ids_to_index_set(ToDelete, ToDeleteIndexes, !Info),
|
|
PrereqIndexes = index_set_difference(PrereqIndexes0, ToDeleteIndexes)
|
|
else
|
|
ToDelete = [],
|
|
PrereqIndexes = PrereqIndexes0
|
|
),
|
|
target_id_index_set_to_plain_set(!.Info, PrereqIndexes, Prereqs),
|
|
(
|
|
Succeeded = did_not_succeed,
|
|
PrereqsResult = could_not_find_some_prereqs(Prereqs)
|
|
;
|
|
Succeeded = succeeded,
|
|
PrereqsResult = found_all_prereqs(Prereqs)
|
|
),
|
|
|
|
globals.lookup_bool_option(Globals, debug_make, DebugMake),
|
|
(
|
|
DebugMake = no
|
|
;
|
|
DebugMake = yes,
|
|
% XXX LEGACY
|
|
set.map2_fold(target_id_to_file_name(Globals), Prereqs,
|
|
PrereqFileNames, _PrereqFileNamesProposed, !IO),
|
|
WriteFileName =
|
|
( pred(FN::in, SIO0::di, SIO::uo) is det :-
|
|
io.format(ProgressStream, "\t%s\n", [s(FN)], SIO0, SIO)
|
|
),
|
|
io.format(ProgressStream, "direct prereqs of %s %s:\n",
|
|
[s(sym_name_to_string(ModuleName)),
|
|
s(string.string(TargetType))], !IO),
|
|
set.foldl(WriteFileName, PrereqFileNames, !IO),
|
|
(
|
|
ToDelete = []
|
|
;
|
|
ToDelete = [_ | _],
|
|
% XXX LEGACY
|
|
list.map2_foldl(target_id_to_file_name(Globals), ToDelete,
|
|
ToDeleteFileNames, _ToDeleteFileNamesProposed, !IO),
|
|
io.write_string(ProgressStream, "after deleting:\n", !IO),
|
|
list.foldl(WriteFileName, ToDeleteFileNames, !IO)
|
|
),
|
|
io.write_string(ProgressStream, "end direct prereqs\n", !IO)
|
|
).
|
|
|
|
:- pred find_direct_prereqs_of_nested_module_targets(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in, module_target_type::in,
|
|
list(module_index)::in, maybe_succeeded::in, maybe_succeeded::out,
|
|
target_id_index_set::in, target_id_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
find_direct_prereqs_of_nested_module_targets(_, _, _, _, [],
|
|
!Succeeded, !Prereqs, !Info, !IO).
|
|
find_direct_prereqs_of_nested_module_targets(ProgressStream, KeepGoing,
|
|
Globals, TargetType, [ModuleIndex | ModuleIndexes],
|
|
!Succeeded, !Prereqs, !Info, !IO) :-
|
|
find_direct_prereqs_of_module_target(ProgressStream, KeepGoing,
|
|
Globals, TargetType, ModuleIndex, HeadSucceeded, HeadPrereqs,
|
|
!Info, !IO),
|
|
index_set_union(HeadPrereqs, !Prereqs),
|
|
should_we_stop_or_continue(KeepGoing, HeadSucceeded, StopOrContinue,
|
|
!Succeeded),
|
|
(
|
|
StopOrContinue = soc_stop
|
|
;
|
|
StopOrContinue = soc_continue,
|
|
find_direct_prereqs_of_nested_module_targets(ProgressStream, KeepGoing,
|
|
Globals, TargetType, ModuleIndexes, !Succeeded, !Prereqs,
|
|
!Info, !IO)
|
|
).
|
|
|
|
:- pred find_direct_prereqs_of_module_target(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in,
|
|
module_target_type::in, module_index::in,
|
|
maybe_succeeded::out, target_id_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
find_direct_prereqs_of_module_target(ProgressStream, KeepGoing, Globals,
|
|
TargetType, ModuleIndex, Succeeded, Prereqs, !Info, !IO) :-
|
|
(
|
|
( TargetType = module_target_source
|
|
; TargetType = module_target_track_flags
|
|
),
|
|
Succeeded = succeeded,
|
|
Prereqs = index_set_init
|
|
;
|
|
TargetType = module_target_int3,
|
|
PrereqSpecs = [self(module_target_source)],
|
|
find_prereqs_from_specs(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, PrereqSpecs, Prereqs, succeeded, Succeeded,
|
|
!Info, !IO)
|
|
;
|
|
( TargetType = module_target_int0
|
|
; TargetType = module_target_int1
|
|
; TargetType = module_target_int2
|
|
),
|
|
PrereqSpecs = [
|
|
self(module_target_source),
|
|
ancestors(module_target_int0),
|
|
direct_imports_intermod(module_target_int3),
|
|
indirect_imports_intermod(module_target_int3)
|
|
],
|
|
find_prereqs_from_specs(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, PrereqSpecs, Prereqs, succeeded, Succeeded,
|
|
!Info, !IO)
|
|
;
|
|
( TargetType = module_target_c_code
|
|
; TargetType = module_target_c_header(_)
|
|
; TargetType = module_target_csharp_code
|
|
; TargetType = module_target_java_code
|
|
; TargetType = module_target_errors
|
|
),
|
|
compiled_code_dependencies(Globals, PrereqSpecs),
|
|
% XXX MDNEW Get intermod, pass as extra arg in the returned deps.
|
|
% XXX MDNEW Same for direct and indirect deps, and ancestors.
|
|
find_prereqs_from_specs(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, PrereqSpecs, Prereqs, succeeded, Succeeded,
|
|
!Info, !IO)
|
|
;
|
|
TargetType = module_target_java_class_code,
|
|
% Generating the .class file of a module obviously requires
|
|
% its .java file. However, it also seems to need the .java files
|
|
% of the modules it imports, directly or indirectly.
|
|
%
|
|
% For modules in other directories, such as standard library modules,
|
|
% we don't need to make them now, since they have been made by
|
|
% mmc --make invocations in those other directories.
|
|
% For the modules in the current directory, we want to make them now.
|
|
% This extra set of prerequisites fixes a whole bunch of test case
|
|
% failures in tests/{valid,valid_seq} in the java grade.
|
|
%
|
|
% XXX I (zs) don't know whether doing s/non_intermod/intermod/ on
|
|
% the specifications below would prevent any more test case failures.
|
|
% This is because for me the difference is moot, due to java bootchecks
|
|
% being slow enough that I don't usually do them with intermodule
|
|
% optimization enabled.
|
|
%
|
|
% NOTE When making executables or libraries in a java grade,
|
|
% make.program_target.m does NOT make the program's .class files
|
|
% one-by-one using this target. Instead, it gives all the .java files
|
|
% that do not have an up-to-date corresponding .class file to the
|
|
% Java compiler all in one invocation. The reason for this is that
|
|
% the Java compiler will generate .class code not just for the
|
|
% .java files on its command line, but also for any other reachable
|
|
% .java files that define classes that the command-line files refer to
|
|
% but do not define. This means that compiling the .java files
|
|
% of the program separately, one-by-one, could, about probably would,
|
|
% recompile many .java files many times.
|
|
PrereqSpecs = [
|
|
self(module_target_java_code),
|
|
direct_imports_non_intermod_local(module_target_java_code),
|
|
indirect_imports_non_intermod_local(module_target_java_code)
|
|
],
|
|
find_prereqs_from_specs(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, PrereqSpecs, Prereqs, succeeded, Succeeded,
|
|
!Info, !IO)
|
|
;
|
|
TargetType = module_target_fact_table_object(PIC, _),
|
|
globals.get_target(Globals, CompilationTarget),
|
|
TargetCodeType = target_to_module_target_code(CompilationTarget, PIC),
|
|
PrereqSpec = self(TargetCodeType),
|
|
find_prereqs_from_spec(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, PrereqSpec, Succeeded, Prereqs, !Info, !IO)
|
|
;
|
|
TargetType = module_target_object_code(PIC),
|
|
globals.get_target(Globals, CompilationTarget),
|
|
TargetCodeType = target_to_module_target_code(CompilationTarget, PIC),
|
|
globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
|
|
|
|
MhHeader = module_target_c_header(header_mh),
|
|
MihHeader = module_target_c_header(header_mih),
|
|
PrereqSpecSelf = self(TargetCodeType),
|
|
PrereqSpecMh = foreign_imports_intermod_trans(MhHeader),
|
|
( if
|
|
CompilationTarget = target_c,
|
|
HighLevelCode = yes
|
|
then
|
|
PrereqSpecs = [PrereqSpecSelf, PrereqSpecMh,
|
|
direct_imports_intermod(MihHeader),
|
|
indirect_imports_intermod(MihHeader),
|
|
ancestors(MihHeader),
|
|
intermod_imports(MihHeader)
|
|
]
|
|
else
|
|
PrereqSpecs = [PrereqSpecSelf, PrereqSpecMh]
|
|
),
|
|
find_prereqs_from_specs(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, PrereqSpecs, Prereqs, succeeded, Succeeded,
|
|
!Info, !IO)
|
|
;
|
|
( TargetType = module_target_opt
|
|
; TargetType = module_target_xml_doc
|
|
),
|
|
PrereqSpecs = [
|
|
self(module_target_source),
|
|
anc0_dir1_indir2_non_intermod
|
|
],
|
|
find_prereqs_from_specs(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, PrereqSpecs, Prereqs, succeeded, Succeeded,
|
|
!Info, !IO)
|
|
;
|
|
TargetType = module_target_analysis_registry,
|
|
PrereqSpecs = [
|
|
self(module_target_source),
|
|
anc0_dir1_indir2_non_intermod,
|
|
direct_imports_intermod(module_target_opt),
|
|
indirect_imports_intermod(module_target_opt),
|
|
intermod_imports(module_target_opt)
|
|
],
|
|
find_prereqs_from_specs(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, PrereqSpecs, Prereqs, succeeded, Succeeded,
|
|
!Info, !IO)
|
|
).
|
|
|
|
:- func target_to_module_target_code(compilation_target, pic)
|
|
= module_target_type.
|
|
|
|
target_to_module_target_code(_CompilationTarget, _PIC) = TargetCode :-
|
|
% XXX it looks wrong to be returning module_target_c_code for
|
|
% all compilation targets.
|
|
TargetCode = module_target_c_code.
|
|
|
|
:- pred compiled_code_dependencies(globals::in, list(prereq_spec)::out) is det.
|
|
|
|
compiled_code_dependencies(Globals, PrereqSpecs) :-
|
|
% We build up PrereqSpecs in stages.
|
|
|
|
% Stage 0: dependencies on flags.
|
|
globals.lookup_bool_option(Globals, make_track_flags, TrackFlags),
|
|
(
|
|
TrackFlags = yes,
|
|
PrereqSpecsTracks = [self(module_target_track_flags)]
|
|
;
|
|
TrackFlags = no,
|
|
PrereqSpecsTracks = []
|
|
),
|
|
|
|
% Stage 1: dependencies on the source file, and on the fact table files,
|
|
% foreign language files and Mercury interface files it imports.
|
|
PrereqSpecsSrcInts = [
|
|
self(module_target_source),
|
|
self_foreign_incl_fact_table_files,
|
|
self(module_target_int1),
|
|
% XXX MDNEW The next two prereq_specs should be a single
|
|
% combined prereq_spec, anc01_dir1_indir2_intermod.
|
|
ancestors(module_target_int1),
|
|
anc0_dir1_indir2_intermod
|
|
],
|
|
|
|
globals.lookup_bool_option(Globals, intermodule_optimization, IntermodOpt),
|
|
globals.lookup_bool_option(Globals, intermodule_analysis,
|
|
IntermodAnalysis),
|
|
AnyIntermod = bool.or(IntermodOpt, IntermodAnalysis),
|
|
|
|
% Stage 2: dependencies on optimization files.
|
|
(
|
|
AnyIntermod = yes,
|
|
PrereqSpecsOpts = [
|
|
self(module_target_opt),
|
|
% XXX MDNEW Given that we compute the set of intermod imports
|
|
% for this prereq_spec ...
|
|
intermod_imports(module_target_opt),
|
|
% ... why do we have to compute it AGAIN, as part of this
|
|
% prereq_spec as well?
|
|
%
|
|
% We should replace both of these prereq_specs with one that
|
|
% does the job of both but computes the set of intermod_imports
|
|
% modules set just once. This would save even the cost of a
|
|
% cache hit.
|
|
anc0_dir1_indir2_intermod_of_ancestors_of_intermod_imports
|
|
]
|
|
;
|
|
AnyIntermod = no,
|
|
PrereqSpecsOpts = []
|
|
),
|
|
|
|
% Stage 3: dependencies on analysis result files.
|
|
(
|
|
IntermodAnalysis = yes,
|
|
PrereqSpecsRegistries = [
|
|
self(module_target_analysis_registry),
|
|
direct_imports_intermod(module_target_analysis_registry)
|
|
]
|
|
;
|
|
IntermodAnalysis = no,
|
|
PrereqSpecsRegistries = []
|
|
),
|
|
|
|
PrereqSpecs = PrereqSpecsTracks ++ PrereqSpecsSrcInts ++
|
|
PrereqSpecsOpts ++ PrereqSpecsRegistries.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% The prerequisite specification type.
|
|
%
|
|
% Values of this type indirectly represent the specification of
|
|
% a set of target_ids (actually, target_id_indexes).
|
|
% The "indirect" part is there because they actually represent
|
|
% a specification of a task for find_prereqs_from_spec, which will compute
|
|
% that set of target_id_indexes when given a prereq_spec.
|
|
%
|
|
% NOTE I (zs) considered using a local_modules_only wrapper around
|
|
% a prereq_spec to replace {direct,indirect}_imports_non_intermod_local,
|
|
% but this turns out to be a bad idea for two reasons.
|
|
%
|
|
% - First, the local-modules-only filter must be applied *between*
|
|
% determining a set of maybe-local-or-maybe-not modules, and
|
|
% converting the local module names' indexes to target_ids by adding
|
|
% a target_type, which means that applying the filter *after* having
|
|
% find_prereqs_from_spec return a target_id_index_set requires
|
|
% first effectively converting each target_id_index back to
|
|
% a module_index.
|
|
%
|
|
% - Second, one of the prereq_specs, self_foreign_incl_fact_table_files,
|
|
% specifies target_ids that do not *have* a module name component,
|
|
% and such targets therefore cannot reasonably be considered as
|
|
% either having, or not having, a local Mercury source module.
|
|
%
|
|
:- type prereq_spec
|
|
---> self(module_target_type)
|
|
; ancestors(module_target_type)
|
|
; direct_imports_non_intermod_local(module_target_type)
|
|
; direct_imports_non_intermod(module_target_type)
|
|
; direct_imports_intermod(module_target_type)
|
|
; indirect_imports_non_intermod_local(module_target_type)
|
|
; indirect_imports_non_intermod(module_target_type)
|
|
; indirect_imports_intermod(module_target_type)
|
|
; intermod_imports(module_target_type)
|
|
; foreign_imports_intermod_trans(module_target_type)
|
|
|
|
; anc0_dir1_indir2_non_intermod
|
|
; anc0_dir1_indir2_intermod
|
|
% Get the .int0 files of ancestors, the .int files of direct
|
|
% imports, and the .int2 files of indirect imports.
|
|
|
|
; anc0_dir1_indir2_intermod_of_ancestors_of_intermod_imports
|
|
% Get the .int0 files of ancestors, the .int files of direct
|
|
% imports, and the .int2 files of indirect imports, but not
|
|
% of the specified module, but of the ancestors of its intermod
|
|
% imports.
|
|
|
|
; self_foreign_incl_fact_table_files.
|
|
% Files named in foreign include module and fact table pragmas.
|
|
|
|
:- pred find_prereqs_from_specs(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in, module_index::in, list(prereq_spec)::in,
|
|
target_id_index_set::out,
|
|
maybe_succeeded::in, maybe_succeeded::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
find_prereqs_from_specs(_, _, _, _, [], index_set_init,
|
|
!Succeeded, !Info, !IO).
|
|
find_prereqs_from_specs(ProgressStream, KeepGoing, Globals, ModuleIndex,
|
|
[HeadPrereqSpec | TailPrereqSpecs], TargetIdIndexSet,
|
|
!Succeeded, !Info, !IO) :-
|
|
find_prereqs_from_spec(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, HeadPrereqSpec, HeadSucceeded, HeadTargetIdIndexSet,
|
|
!Info, !IO),
|
|
should_we_stop_or_continue(KeepGoing, HeadSucceeded, StopOrContinue,
|
|
!Succeeded),
|
|
(
|
|
StopOrContinue = soc_stop,
|
|
TargetIdIndexSet = HeadTargetIdIndexSet
|
|
;
|
|
StopOrContinue = soc_continue,
|
|
find_prereqs_from_specs(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, TailPrereqSpecs, TailTargetIdIndexSet,
|
|
!Succeeded, !Info, !IO),
|
|
index_set_union(HeadTargetIdIndexSet, TailTargetIdIndexSet,
|
|
TargetIdIndexSet)
|
|
).
|
|
|
|
:- pred find_prereqs_from_spec(io.text_output_stream::in, maybe_keep_going::in,
|
|
globals::in, module_index::in, prereq_spec::in,
|
|
maybe_succeeded::out, target_id_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
find_prereqs_from_spec(ProgressStream, KeepGoing, Globals, ModuleIndex,
|
|
PrereqSpec, Succeeded, TargetIdIndexSet, !Info, !IO) :-
|
|
trace [
|
|
compile_time(flag("find_prereqs_from_spec")),
|
|
run_time(env("FIND_PREREQS_FROM_SPEC")),
|
|
io(!TIO)
|
|
] (
|
|
module_index_to_name(!.Info, ModuleIndex, IndexModuleName),
|
|
IndexModuleNameStr = sym_name_to_string(IndexModuleName),
|
|
io.format(ProgressStream, "starting prereq_spec %s for %s\n",
|
|
[s(string.string(PrereqSpec)), s(IndexModuleNameStr)], !TIO)
|
|
),
|
|
% XXX Some of these alternatives don't need I/O.
|
|
% We can wrap caching code around the code of any set of switch arms.
|
|
%
|
|
% XXX Are there are any prereq_spec kinds for which we may return
|
|
% did_not_succeed AND a nonempty TargetIdIndexSet? If not, then
|
|
% those two parameters are effectively a single value of a maybe type.
|
|
(
|
|
PrereqSpec = self(TargetType),
|
|
Succeeded = succeeded,
|
|
timi_target(ModuleIndex, TargetType, TargetIdIndexSet, !Info)
|
|
;
|
|
PrereqSpec = ancestors(TargetType),
|
|
Succeeded = succeeded,
|
|
module_index_to_name(!.Info, ModuleIndex, ModuleName),
|
|
Ancestors = get_ancestors(ModuleName),
|
|
module_names_to_index_set(Ancestors, ModuleIndexSet, !Info),
|
|
timi_targets(ModuleIndexSet, TargetType, TargetIdIndexSet, !Info)
|
|
;
|
|
PrereqSpec = direct_imports_non_intermod_local(TargetType),
|
|
get_direct_imports_non_intermod(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, ModuleIndexSet0, !Info, !IO),
|
|
ModuleIndexes0 = index_set_to_sorted_list(ModuleIndexSet0),
|
|
find_local_modules(ProgressStream, ModuleIndexes0,
|
|
index_set_init, ModuleIndexSet, !Info, !IO),
|
|
timi_targets(ModuleIndexSet, TargetType, TargetIdIndexSet, !Info)
|
|
;
|
|
PrereqSpec = direct_imports_non_intermod(TargetType),
|
|
get_direct_imports_non_intermod(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, ModuleIndexSet, !Info, !IO),
|
|
timi_targets(ModuleIndexSet, TargetType, TargetIdIndexSet, !Info)
|
|
;
|
|
PrereqSpec = direct_imports_intermod(TargetType),
|
|
get_direct_imports_intermod(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, ModuleIndexSet, !Info, !IO),
|
|
timi_targets(ModuleIndexSet, TargetType, TargetIdIndexSet, !Info)
|
|
;
|
|
PrereqSpec = indirect_imports_non_intermod_local(TargetType),
|
|
get_indirect_imports_non_intermod(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, ModuleIndexSet0, !Info, !IO),
|
|
ModuleIndexes0 = index_set_to_sorted_list(ModuleIndexSet0),
|
|
find_local_modules(ProgressStream, ModuleIndexes0,
|
|
index_set_init, ModuleIndexSet, !Info, !IO),
|
|
timi_targets(ModuleIndexSet, TargetType, TargetIdIndexSet, !Info)
|
|
;
|
|
PrereqSpec = indirect_imports_non_intermod(TargetType),
|
|
get_indirect_imports_non_intermod(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, ModuleIndexSet, !Info, !IO),
|
|
timi_targets(ModuleIndexSet, TargetType, TargetIdIndexSet, !Info)
|
|
;
|
|
PrereqSpec = indirect_imports_intermod(TargetType),
|
|
get_indirect_imports_intermod(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, ModuleIndexSet, !Info, !IO),
|
|
timi_targets(ModuleIndexSet, TargetType, TargetIdIndexSet, !Info)
|
|
;
|
|
PrereqSpec = intermod_imports(TargetType),
|
|
get_intermod_imports(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, ModuleIndexSet, !Info, !IO),
|
|
timi_targets(ModuleIndexSet, TargetType, TargetIdIndexSet, !Info)
|
|
;
|
|
PrereqSpec = foreign_imports_intermod_trans(TargetType),
|
|
get_foreign_imports_intermod_trans(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, ModuleIndexSet, !Info, !IO),
|
|
timi_targets(ModuleIndexSet, TargetType, TargetIdIndexSet, !Info)
|
|
;
|
|
PrereqSpec = anc0_dir1_indir2_non_intermod,
|
|
SubPrereqSpecs = [
|
|
ancestors(module_target_int0),
|
|
direct_imports_non_intermod(module_target_int1),
|
|
indirect_imports_non_intermod(module_target_int2)
|
|
],
|
|
trace [
|
|
compile_time(flag("find_prereqs_from_spec")),
|
|
run_time(env("FIND_PREREQS_FROM_SPEC")),
|
|
io(!TIO)
|
|
] (
|
|
module_index_to_name(!.Info, ModuleIndex, IndexModuleName),
|
|
IndexModuleNameStr = sym_name_to_string(IndexModuleName),
|
|
io.format(ProgressStream, "prereq_spec %s for %s starts\n\n",
|
|
[s(string.string(PrereqSpec)), s(IndexModuleNameStr)], !TIO)
|
|
),
|
|
|
|
% This cache is disabled, because it is ineffective.
|
|
% ( if
|
|
% search_anc0_dir1_indir2_non_intermod_cache(!.Info, ModuleIndex,
|
|
% Result0)
|
|
% then
|
|
% Result0 = deps_result(Succeeded, TargetIdIndexSet)
|
|
% else
|
|
find_prereqs_from_specs(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, SubPrereqSpecs, TargetIdIndexSet,
|
|
succeeded, Succeeded, !Info, !IO),
|
|
% Result = deps_result(Succeeded, TargetIdIndexSet),
|
|
% add_to_anc0_dir1_indir2_non_intermod_cache(ModuleIndex, Result,
|
|
% !Info)
|
|
% ),
|
|
|
|
trace [
|
|
compile_time(flag("find_prereqs_from_spec")),
|
|
run_time(env("FIND_PREREQS_FROM_SPEC")),
|
|
io(!TIO)
|
|
] (
|
|
module_index_to_name(!.Info, ModuleIndex, IndexModuleName),
|
|
IndexModuleNameStr = sym_name_to_string(IndexModuleName),
|
|
io.format(ProgressStream, "prereq_spec %s for %s ends\n",
|
|
[s(string.string(PrereqSpec)), s(IndexModuleNameStr)], !TIO)
|
|
)
|
|
;
|
|
PrereqSpec = anc0_dir1_indir2_intermod,
|
|
SubPrereqSpecs = [
|
|
ancestors(module_target_int0),
|
|
direct_imports_intermod(module_target_int1),
|
|
indirect_imports_intermod(module_target_int2)
|
|
],
|
|
trace [
|
|
compile_time(flag("find_prereqs_from_spec")),
|
|
run_time(env("FIND_PREREQS_FROM_SPEC")),
|
|
io(!TIO)
|
|
] (
|
|
module_index_to_name(!.Info, ModuleIndex, IndexModuleName),
|
|
IndexModuleNameStr = sym_name_to_string(IndexModuleName),
|
|
io.format(ProgressStream, "prereq_spec %s for %s starts\n\n",
|
|
[s(string.string(PrereqSpec)), s(IndexModuleNameStr)], !TIO)
|
|
),
|
|
|
|
( if
|
|
search_anc0_dir1_indir2_intermod_cache(!.Info, ModuleIndex,
|
|
Result0)
|
|
then
|
|
Result0 = prereqs_result(Succeeded, TargetIdIndexSet)
|
|
else
|
|
find_prereqs_from_specs(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, SubPrereqSpecs, TargetIdIndexSet,
|
|
succeeded, Succeeded, !Info, !IO),
|
|
Result = prereqs_result(Succeeded, TargetIdIndexSet),
|
|
add_to_anc0_dir1_indir2_intermod_cache(ModuleIndex, Result, !Info)
|
|
),
|
|
|
|
trace [
|
|
compile_time(flag("find_prereqs_from_spec")),
|
|
run_time(env("FIND_PREREQS_FROM_SPEC")),
|
|
io(!TIO)
|
|
] (
|
|
module_index_to_name(!.Info, ModuleIndex, IndexModuleName),
|
|
IndexModuleNameStr = sym_name_to_string(IndexModuleName),
|
|
io.format(ProgressStream, "prereq_spec %s for %s ends\n",
|
|
[s(string.string(PrereqSpec)), s(IndexModuleNameStr)], !TIO)
|
|
)
|
|
;
|
|
PrereqSpec =
|
|
anc0_dir1_indir2_intermod_of_ancestors_of_intermod_imports,
|
|
trace [
|
|
compile_time(flag("find_prereqs_from_spec")),
|
|
run_time(env("FIND_PREREQS_FROM_SPEC")),
|
|
io(!TIO)
|
|
] (
|
|
module_index_to_name(!.Info, ModuleIndex, IndexModuleName),
|
|
IndexModuleNameStr = sym_name_to_string(IndexModuleName),
|
|
io.format(ProgressStream, "prereq_spec %s for %s starts\n\n",
|
|
[s(string.string(PrereqSpec)), s(IndexModuleNameStr)], !TIO)
|
|
),
|
|
|
|
get_anc0_dir1_indir2_intermod_of_ancestors_of_intermod_imports(
|
|
ProgressStream, KeepGoing, Globals, ModuleIndex,
|
|
Succeeded, TargetIdIndexSet, !Info, !IO),
|
|
|
|
trace [
|
|
compile_time(flag("find_prereqs_from_spec")),
|
|
run_time(env("FIND_PREREQS_FROM_SPEC")),
|
|
io(!TIO)
|
|
] (
|
|
module_index_to_name(!.Info, ModuleIndex, IndexModuleName),
|
|
IndexModuleNameStr = sym_name_to_string(IndexModuleName),
|
|
io.format(ProgressStream, "prereq_spec %s for %s ends\n",
|
|
[s(string.string(PrereqSpec)), s(IndexModuleNameStr)], !TIO)
|
|
)
|
|
;
|
|
PrereqSpec = self_foreign_incl_fact_table_files,
|
|
get_foreign_incl_fact_table_files(ProgressStream, Globals,
|
|
ModuleIndex, Succeeded, TargetIdIndexSet, !Info, !IO)
|
|
),
|
|
trace [
|
|
compile_time(flag("find_prereqs_from_spec")),
|
|
run_time(env("FIND_PREREQS_FROM_SPEC")),
|
|
io(!TIO)
|
|
] (
|
|
module_index_to_name(!.Info, ModuleIndex, IndexModuleName),
|
|
IndexModuleNameStr = sym_name_to_string(IndexModuleName),
|
|
target_id_index_set_to_plain_set(!.Info, TargetIdIndexSet,
|
|
TargetIdSet),
|
|
TargetIds = set.to_sorted_list(TargetIdSet),
|
|
(
|
|
TargetIds = [],
|
|
io.format(ProgressStream,
|
|
"prereq_spec %s for %s yields no prereqs\n\n",
|
|
[s(string.string(PrereqSpec)), s(IndexModuleNameStr)], !TIO)
|
|
;
|
|
TargetIds = [_ | _],
|
|
TargetIdNlStrs = list.map(
|
|
target_id_to_debug_string(" ", "\n"), TargetIds),
|
|
io.format(ProgressStream,
|
|
"prereq_spec %s for %s yields these prereqs:\n",
|
|
[s(string.string(PrereqSpec)), s(IndexModuleNameStr)], !TIO),
|
|
list.foldl(io.write_string(ProgressStream), TargetIdNlStrs, !TIO),
|
|
io.write_string(ProgressStream, "prereq list ends\n\n", !TIO)
|
|
)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred timi_target(module_index::in, module_target_type::in,
|
|
target_id_index_set::out, make_info::in, make_info::out) is det.
|
|
:- pragma inline(pred(timi_target/5)).
|
|
|
|
timi_target(ModuleIndex, TargetType, TargetIdIndexSet, !Info) :-
|
|
acc_rev_timi_target(TargetType, ModuleIndex,
|
|
index_set_init, TargetIdIndexSet, !Info).
|
|
|
|
:- pred timi_targets(module_index_set::in, module_target_type::in,
|
|
target_id_index_set::out, make_info::in, make_info::out) is det.
|
|
:- pragma inline(pred(timi_targets/5)).
|
|
|
|
timi_targets(ModuleIndexSet, TargetType, TargetIdIndexSet, !Info) :-
|
|
index_set_foldl2(acc_rev_timi_target(TargetType), ModuleIndexSet,
|
|
index_set_init, TargetIdIndexSet, !Info).
|
|
|
|
:- pred acc_rev_timi_target(module_target_type::in, module_index::in,
|
|
target_id_index_set::in, target_id_index_set::out,
|
|
make_info::in, make_info::out) is det.
|
|
:- pragma inline(pred(acc_rev_timi_target/6)).
|
|
|
|
acc_rev_timi_target(TargetType, ModuleIndex, !TargetIdIndexSet, !Info) :-
|
|
TargetId = timi_merc(ModuleIndex, TargetType),
|
|
target_id_to_index(TargetId, TargetIdIndex, !Info),
|
|
index_set_insert(TargetIdIndex, !TargetIdIndexSet).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Return the modules for which `.int' files are read in a compilation
|
|
% which does not use `--intermodule-optimization'.
|
|
%
|
|
:- pred get_direct_imports_non_intermod(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in, module_index::in,
|
|
maybe_succeeded::out, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_direct_imports_non_intermod(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, Modules, !Info, !IO) :-
|
|
( if
|
|
search_direct_imports_non_intermod_cache(!.Info, ModuleIndex, Result0)
|
|
then
|
|
Result0 = prereqs_result(Succeeded, Modules)
|
|
else
|
|
get_direct_imports_non_intermod_uncached(ProgressStream, KeepGoing,
|
|
Globals, ModuleIndex, Succeeded, Modules, !Info, !IO),
|
|
Result = prereqs_result(Succeeded, Modules),
|
|
add_to_direct_imports_non_intermod_cache(ModuleIndex, Result, !Info)
|
|
).
|
|
|
|
:- pred get_direct_imports_non_intermod_uncached(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in, module_index::in,
|
|
maybe_succeeded::out, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_direct_imports_non_intermod_uncached(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, Modules, !Info, !IO) :-
|
|
module_index_to_name(!.Info, ModuleIndex, ModuleName),
|
|
get_maybe_module_dep_info(ProgressStream, Globals,
|
|
ModuleName, MaybeModuleDepInfo, !Info, !IO),
|
|
(
|
|
MaybeModuleDepInfo = some_module_dep_info(ModuleDepInfo),
|
|
% Find the direct imports of this module, i.e. the modules
|
|
% for which we will read the `.int' files.
|
|
%
|
|
% Note that we need to do this both for the imports of this module,
|
|
% and for the imports of its ancestors. This is because if this module
|
|
% is a submodule, then it may depend on things imported only by its
|
|
% ancestors.
|
|
%
|
|
module_dep_info_get_int_deps(ModuleDepInfo, IntModuleNames),
|
|
module_dep_info_get_imp_deps(ModuleDepInfo, ImpModuleNames),
|
|
module_names_to_index_set(set.to_sorted_list(IntModuleNames),
|
|
IntModules, !Info),
|
|
module_names_to_index_set(set.to_sorted_list(ImpModuleNames),
|
|
ImpModules, !Info),
|
|
index_set_union(IntModules, ImpModules, Modules0),
|
|
(
|
|
ModuleName = qualified(ParentModule, _),
|
|
module_name_to_index(ParentModule, ParentIndex, !Info),
|
|
get_direct_imports_non_intermod(ProgressStream, KeepGoing,
|
|
Globals, ParentIndex, Succeeded, ParentImports, !Info, !IO),
|
|
index_set_union(ParentImports, Modules0, Modules)
|
|
;
|
|
ModuleName = unqualified(_),
|
|
Succeeded = succeeded,
|
|
Modules = Modules0
|
|
)
|
|
;
|
|
MaybeModuleDepInfo = no_module_dep_info,
|
|
Succeeded = did_not_succeed,
|
|
Modules = index_set_init
|
|
).
|
|
|
|
:- pred get_direct_imports_intermod(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in, module_index::in,
|
|
maybe_succeeded::out, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_direct_imports_intermod(ProgressStream, KeepGoing, Globals, ModuleIndex,
|
|
Succeeded, Modules, !Info, !IO) :-
|
|
( if
|
|
search_direct_imports_intermod_cache(!.Info, ModuleIndex, Result0)
|
|
then
|
|
Result0 = prereqs_result(Succeeded, Modules)
|
|
else
|
|
get_direct_imports_non_intermod(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded0, Modules0, !Info, !IO),
|
|
( if
|
|
Succeeded0 = did_not_succeed,
|
|
KeepGoing = do_not_keep_going
|
|
then
|
|
Succeeded = did_not_succeed,
|
|
Modules = index_set_init
|
|
else
|
|
% We also read `.int' files for the modules for which we read
|
|
% `.opt' files, and for the modules imported by those modules.
|
|
get_intermod_imports(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded1, IntermodModules, !Info, !IO),
|
|
( if
|
|
Succeeded1 = did_not_succeed,
|
|
KeepGoing = do_not_keep_going
|
|
then
|
|
Succeeded = did_not_succeed,
|
|
Modules = index_set_init
|
|
else
|
|
index_set_union(IntermodModules, Modules0, Modules1),
|
|
fold_find_modules_over_modules(ProgressStream, KeepGoing,
|
|
Globals, get_direct_imports_non_intermod,
|
|
index_set_to_sorted_list(IntermodModules),
|
|
succeeded, Succeeded2, Modules1, Modules2, !Info, !IO),
|
|
Succeeded = Succeeded0 `and` Succeeded1 `and` Succeeded2,
|
|
index_set_delete(ModuleIndex, Modules2, Modules)
|
|
)
|
|
),
|
|
Result = prereqs_result(Succeeded, Modules),
|
|
add_to_direct_imports_intermod_cache(ModuleIndex, Result, !Info)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Return the list of modules for which we should read `.int2' files,
|
|
% ignoring those which need to be read as a result of importing modules
|
|
% imported by a `.opt' file.
|
|
%
|
|
:- pred get_indirect_imports_non_intermod(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in, module_index::in,
|
|
maybe_succeeded::out, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_indirect_imports_non_intermod(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, IndirectNonIntermodImportModules,
|
|
!Info, !IO) :-
|
|
% This cache is disabled, because it is ineffective.
|
|
% ( if
|
|
% search_indirect_imports_non_intermod_cache(!.Info, ModuleIndex,
|
|
% Result0)
|
|
% then
|
|
% Result0 = deps_result(Succeeded, IndirectNonIntermodImportModules)
|
|
% else
|
|
get_direct_imports_non_intermod(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, DirectSucceeded, DirectImportModules, !Info, !IO),
|
|
get_indirect_imports_uncached(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, DirectSucceeded, DirectImportModules,
|
|
Succeeded, IndirectNonIntermodImportModules, !Info, !IO).
|
|
% Result = deps_result(Succeeded, IndirectNonIntermodImportModules),
|
|
% add_to_indirect_imports_non_intermod_cache(ModuleIndex, Result, !Info)
|
|
% ).
|
|
|
|
% Return the list of modules for which we should read `.int2' files.
|
|
%
|
|
:- pred get_indirect_imports_intermod(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in, module_index::in,
|
|
maybe_succeeded::out, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_indirect_imports_intermod(ProgressStream, KeepGoing, Globals, ModuleIndex,
|
|
Succeeded, IndirectIntermodImportModules, !Info, !IO) :-
|
|
( if
|
|
search_indirect_imports_intermod_cache(!.Info, ModuleIndex, Result0)
|
|
then
|
|
Result0 = prereqs_result(Succeeded, IndirectIntermodImportModules)
|
|
else
|
|
get_direct_imports_intermod(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, DirectSucceeded, DirectImportModules, !Info, !IO),
|
|
get_indirect_imports_uncached(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, DirectSucceeded, DirectImportModules,
|
|
Succeeded, IndirectIntermodImportModules, !Info, !IO),
|
|
Result = prereqs_result(Succeeded, IndirectIntermodImportModules),
|
|
add_to_indirect_imports_intermod_cache(ModuleIndex, Result, !Info)
|
|
).
|
|
|
|
:- pred get_indirect_imports_uncached(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in, module_index::in,
|
|
maybe_succeeded::in, module_index_set::in,
|
|
maybe_succeeded::out, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_indirect_imports_uncached(ProgressStream, KeepGoing, Globals, ModuleIndex,
|
|
DirectSucceeded, DirectImports, Succeeded, IndirectImports,
|
|
!Info, !IO) :-
|
|
( if
|
|
DirectSucceeded = did_not_succeed,
|
|
KeepGoing = do_not_keep_going
|
|
then
|
|
Succeeded = did_not_succeed,
|
|
IndirectImports = index_set_init
|
|
else
|
|
fold_find_modules_over_modules(ProgressStream, KeepGoing, Globals,
|
|
find_transitive_implementation_imports,
|
|
index_set_to_sorted_list(DirectImports),
|
|
succeeded, IndirectSucceeded, index_set_init, IndirectImports0,
|
|
!Info, !IO),
|
|
index_set_delete(ModuleIndex, IndirectImports0, IndirectImports1),
|
|
IndirectImports =
|
|
index_set_difference(IndirectImports1, DirectImports),
|
|
Succeeded = DirectSucceeded `and` IndirectSucceeded
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Return the list of modules for which we should read `.opt' files.
|
|
%
|
|
:- pred get_intermod_imports(io.text_output_stream::in, maybe_keep_going::in,
|
|
globals::in, module_index::in,
|
|
maybe_succeeded::out, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_intermod_imports(ProgressStream, KeepGoing, Globals, ModuleIndex,
|
|
Succeeded, Modules, !Info, !IO) :-
|
|
globals.get_any_intermod(Globals, AnyIntermod),
|
|
(
|
|
AnyIntermod = yes,
|
|
globals.lookup_bool_option(Globals, read_opt_files_transitively,
|
|
Transitive),
|
|
(
|
|
Transitive = yes,
|
|
find_transitive_implementation_imports(ProgressStream, KeepGoing,
|
|
Globals, ModuleIndex, Succeeded, Modules, !Info, !IO)
|
|
;
|
|
Transitive = no,
|
|
get_direct_imports_non_intermod(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, Modules, !Info, !IO)
|
|
)
|
|
;
|
|
AnyIntermod = no,
|
|
Succeeded = succeeded,
|
|
Modules = index_set_init
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred get_foreign_imports_intermod_trans(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in, module_index::in,
|
|
maybe_succeeded::out, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_foreign_imports_intermod_trans(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, Modules, !Info, !IO) :-
|
|
% The object file depends on the header files for the modules
|
|
% mentioned in `:- pragma foreign_import_module' declarations
|
|
% in the current module and the `.opt' files it imports.
|
|
globals.get_backend_foreign_languages(Globals, Languages),
|
|
LanguagesSet = set.list_to_set(Languages),
|
|
get_intermod_imports(ProgressStream, KeepGoing, Globals, ModuleIndex,
|
|
IntermodSucceeded, IntermodModules, !Info, !IO),
|
|
index_set_insert(ModuleIndex, IntermodModules, IntermodSelfModules),
|
|
fold_find_modules_over_modules(ProgressStream, KeepGoing, Globals,
|
|
get_foreign_imports_non_intermod_trans(LanguagesSet),
|
|
to_sorted_list(IntermodSelfModules),
|
|
succeeded, ForeignSucceeded, index_set_init, Modules, !Info, !IO),
|
|
Succeeded = IntermodSucceeded `and` ForeignSucceeded.
|
|
|
|
:- pred get_foreign_imports_non_intermod_trans(set(foreign_language)::in,
|
|
io.text_output_stream::in, maybe_keep_going::in, globals::in,
|
|
module_index::in, maybe_succeeded::out, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_foreign_imports_non_intermod_trans(LangSet, ProgressStream, KeepGoing,
|
|
Globals, ModuleIndex, Succeeded, ForeignModules, !Info, !IO) :-
|
|
% LangSet should be constant for the duration of the process,
|
|
% which means that it is unnecessary to include it in the cache key.
|
|
( if
|
|
search_foreign_imports_non_intermod_trans_cache(!.Info, ModuleIndex,
|
|
Result0)
|
|
then
|
|
Result0 = prereqs_result(Succeeded, ForeignModules)
|
|
else
|
|
find_transitive_implementation_imports(ProgressStream, KeepGoing,
|
|
Globals, ModuleIndex, Succeeded0, ImportedModules, !Info, !IO),
|
|
(
|
|
Succeeded0 = succeeded,
|
|
fold_find_modules_over_modules(ProgressStream, KeepGoing, Globals,
|
|
get_foreign_imports_non_intermod_uncached(LangSet),
|
|
to_sorted_list(insert(ImportedModules, ModuleIndex)),
|
|
succeeded, Succeeded, index_set_init, ForeignModules,
|
|
!Info, !IO),
|
|
Result = prereqs_result(Succeeded, ForeignModules),
|
|
add_to_foreign_imports_non_intermod_trans_cache(ModuleIndex,
|
|
Result, !Info)
|
|
;
|
|
Succeeded0 = did_not_succeed,
|
|
Succeeded = did_not_succeed,
|
|
ForeignModules = index_set_init
|
|
)
|
|
).
|
|
|
|
:- pred get_foreign_imports_non_intermod_uncached(set(foreign_language)::in,
|
|
io.text_output_stream::in, maybe_keep_going::in, globals::in,
|
|
module_index::in, maybe_succeeded::out, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_foreign_imports_non_intermod_uncached(LangSet, ProgressStream, _KeepGoing,
|
|
Globals, ModuleIndex, Succeeded, ForeignModules, !Info, !IO) :-
|
|
module_index_to_name(!.Info, ModuleIndex, ModuleName),
|
|
get_maybe_module_dep_info(ProgressStream, Globals,
|
|
ModuleName, MaybeModuleDepInfo, !Info, !IO),
|
|
(
|
|
MaybeModuleDepInfo = some_module_dep_info(ModuleDepInfo),
|
|
module_dep_info_get_fims(ModuleDepInfo, FIMSpecs),
|
|
set.foldl2(acc_module_index_if_for_lang_in_set(LangSet), FIMSpecs,
|
|
index_set_init, ForeignModules, !Info),
|
|
Succeeded = succeeded
|
|
;
|
|
MaybeModuleDepInfo = no_module_dep_info,
|
|
ForeignModules = index_set_init,
|
|
Succeeded = did_not_succeed
|
|
).
|
|
|
|
:- pred acc_module_index_if_for_lang_in_set(set(foreign_language)::in,
|
|
fim_spec::in, module_index_set::in, module_index_set::out,
|
|
make_info::in, make_info::out) is det.
|
|
|
|
acc_module_index_if_for_lang_in_set(LangSet, FIMSpec,
|
|
!ModuleIndexSet, !Info) :-
|
|
FIMSpec = fim_spec(Lang, ModuleName),
|
|
( if set.contains(LangSet, Lang) then
|
|
module_name_to_index(ModuleName, ModuleIndex, !Info),
|
|
index_set_insert(ModuleIndex, !ModuleIndexSet)
|
|
else
|
|
true
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred get_anc0_dir1_indir2_intermod_of_ancestors_of_intermod_imports(
|
|
io.text_output_stream::in, maybe_keep_going::in,
|
|
globals::in, module_index::in,
|
|
maybe_succeeded::out, target_id_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_anc0_dir1_indir2_intermod_of_ancestors_of_intermod_imports(ProgressStream,
|
|
KeepGoing, Globals, ModuleIndex, !:Succeeded, TargetIdIndexSet,
|
|
!Info, !IO) :-
|
|
get_ancestors_of_intermod_imports(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded1, Modules1, !Info, !IO),
|
|
should_we_stop_or_continue(KeepGoing, Succeeded1, StopOrContinue,
|
|
succeeded, !:Succeeded),
|
|
(
|
|
StopOrContinue = soc_stop,
|
|
TargetIdIndexSet = index_set_init
|
|
;
|
|
StopOrContinue = soc_continue,
|
|
ModuleList1 = index_set_to_sorted_list(Modules1),
|
|
fold_prereq_spec_over_modules(ProgressStream, KeepGoing, Globals,
|
|
anc0_dir1_indir2_intermod, ModuleList1,
|
|
!Succeeded, index_set_init, TargetIdIndexSet, !Info, !IO)
|
|
).
|
|
|
|
:- pred get_ancestors_of_intermod_imports(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in, module_index::in,
|
|
maybe_succeeded::out, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_ancestors_of_intermod_imports(ProgressStream, KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, ModuleIndexSet, !Info, !IO) :-
|
|
get_intermod_imports(ProgressStream, KeepGoing, Globals, ModuleIndex,
|
|
Succeeded1, Modules1, !Info, !IO),
|
|
should_we_stop_or_continue(KeepGoing, Succeeded1, StopOrContinue,
|
|
succeeded, Succeeded),
|
|
(
|
|
StopOrContinue = soc_stop,
|
|
ModuleIndexSet = index_set_init
|
|
;
|
|
StopOrContinue = soc_continue,
|
|
ModuleList1 = index_set_to_sorted_list(Modules1),
|
|
list.map_foldl(index_get_ancestors,
|
|
ModuleList1, AncestorModuleIndexSets, !Info),
|
|
ModuleIndexSet = index_set_union_list(AncestorModuleIndexSets)
|
|
).
|
|
|
|
:- pred index_get_ancestors(module_index::in, module_index_set::out,
|
|
make_info::in, make_info::out) is det.
|
|
|
|
index_get_ancestors(ModuleIndex, AncestorModuleIndexSet, !Info) :-
|
|
module_index_to_name(!.Info, ModuleIndex, ModuleName),
|
|
AncestorModuleNames = get_ancestors(ModuleName),
|
|
module_names_to_index_set(AncestorModuleNames, AncestorModuleIndexSet,
|
|
!Info).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred get_foreign_incl_fact_table_files(io.text_output_stream::in,
|
|
globals::in, module_index::in,
|
|
maybe_succeeded::out, target_id_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
get_foreign_incl_fact_table_files(ProgressStream, Globals, ModuleIndex,
|
|
Succeeded, TargetIdIndexSet, !Info, !IO) :-
|
|
module_index_to_name(!.Info, ModuleIndex, ModuleName),
|
|
get_maybe_module_dep_info(ProgressStream, Globals,
|
|
ModuleName, MaybeModuleDepInfo, !Info, !IO),
|
|
(
|
|
MaybeModuleDepInfo = some_module_dep_info(ModuleDepInfo),
|
|
Succeeded = succeeded,
|
|
module_dep_info_get_fact_tables(ModuleDepInfo, FactTableFileNames),
|
|
file_names_to_index_set(set.to_sorted_list(FactTableFileNames),
|
|
FactTargetIdIndexSet, !Info),
|
|
|
|
module_dep_info_get_source_file_name(ModuleDepInfo, SourceFileName),
|
|
module_dep_info_get_foreign_include_files(ModuleDepInfo,
|
|
ForeignIncludeFiles),
|
|
globals.get_backend_foreign_languages(Globals, Languages),
|
|
LangSet = set.list_to_set(Languages),
|
|
set.foldl2(
|
|
acc_dep_file_index_for_foreign_include_if_in_langset(LangSet,
|
|
SourceFileName),
|
|
ForeignIncludeFiles, FactTargetIdIndexSet, TargetIdIndexSet, !Info)
|
|
;
|
|
MaybeModuleDepInfo = no_module_dep_info,
|
|
Succeeded = did_not_succeed,
|
|
TargetIdIndexSet = index_set_init
|
|
).
|
|
|
|
:- pred acc_dep_file_index_for_foreign_include_if_in_langset(
|
|
set(foreign_language)::in, file_name::in, foreign_include_file_info::in,
|
|
target_id_index_set::in, target_id_index_set::out,
|
|
make_info::in, make_info::out) is det.
|
|
|
|
acc_dep_file_index_for_foreign_include_if_in_langset(LangSet, SourceFileName,
|
|
ForeignInclude, !TargetIdIndexSet, !Info) :-
|
|
ForeignInclude = foreign_include_file_info(Lang, IncludeFileName),
|
|
( if set.contains(LangSet, Lang) then
|
|
make_include_file_path(SourceFileName, IncludeFileName, IncludePath),
|
|
TargetId = timi_non_merc(IncludePath),
|
|
target_id_to_index(TargetId, TargetIdIndex, !Info),
|
|
index_set_insert(TargetIdIndex, !TargetIdIndexSet)
|
|
else
|
|
true
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred find_transitive_implementation_imports(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in, module_index::in,
|
|
maybe_succeeded::out, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
find_transitive_implementation_imports(ProgressStream, _KeepGoing, Globals,
|
|
ModuleIndex, Succeeded, Modules, !Info, !IO) :-
|
|
% XXX MDNEW process_modules_anywhere allows a .module_dep file
|
|
% from a directory far down a search path to create a reference
|
|
% to a module that exists in the *current* directory, if its name
|
|
% duplicates the name of a module in the .module_dep file's directory.
|
|
% This caused the failure of e.g. the warnings/bug311 test case,
|
|
% with the module in the current directory being time.m (until
|
|
% that module was renamed specially in order to avoid such failures).
|
|
find_transitive_module_dependencies(ProgressStream, Globals, all_imports,
|
|
process_modules_anywhere, ModuleIndex, Succeeded, Modules0,
|
|
!Info, !IO),
|
|
index_set_insert(ModuleIndex, Modules0, Modules),
|
|
trace [
|
|
compile_time(flag("find_trans_impl_imports")),
|
|
run_time(env("FIND_TRANS_IMPL_IMPORTS")),
|
|
io(!TIO)
|
|
] (
|
|
module_index_to_name(!.Info, ModuleIndex, IndexModuleName),
|
|
IndexModuleNameStr = sym_name_to_string(IndexModuleName),
|
|
module_index_set_to_plain_set(!.Info, Modules, ModuleSet),
|
|
ModuleList = set.to_sorted_list(ModuleSet),
|
|
ModuleNlStrs = list.map(
|
|
(func(M) = " " ++ sym_name_to_string(M) ++ "\n"),
|
|
ModuleList),
|
|
io.format(ProgressStream, "trans impl imports for %s:\n",
|
|
[s(IndexModuleNameStr)], !TIO),
|
|
list.foldl(io.write_string(ProgressStream), ModuleNlStrs, !TIO),
|
|
io.write_string(ProgressStream,
|
|
"trans impl imports list ends\n\n", !TIO)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred find_local_modules(io.text_output_stream::in, list(module_index)::in,
|
|
module_index_set::in, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
find_local_modules(_ProgressStream, [], !LocalModuleIndexSet, !Info, !IO).
|
|
find_local_modules(ProgressStream, [ModuleIndex | ModuleIndexes],
|
|
!LocalModuleIndexSet, !Info, !IO) :-
|
|
SrcIsLocalMap0 = make_info_get_module_src_is_local_map(!.Info),
|
|
( if map.search(SrcIsLocalMap0, ModuleIndex, IsLocal0) then
|
|
(
|
|
IsLocal0 = src_is_local,
|
|
index_set_insert(ModuleIndex, !LocalModuleIndexSet)
|
|
;
|
|
IsLocal0 = src_is_not_local
|
|
)
|
|
else
|
|
module_index_to_name(!.Info, ModuleIndex, ModuleName),
|
|
module_name_to_source_file_name(ModuleName, FileName, !IO),
|
|
io.open_input(FileName, OpenResult, !IO),
|
|
(
|
|
OpenResult = ok(InputStream),
|
|
io.close_input(InputStream, !IO),
|
|
index_set_insert(ModuleIndex, !LocalModuleIndexSet),
|
|
IsLocal = src_is_local
|
|
;
|
|
OpenResult = error(_),
|
|
IsLocal = src_is_not_local
|
|
),
|
|
map.det_insert(ModuleIndex, IsLocal, SrcIsLocalMap0, SrcIsLocalMap),
|
|
make_info_set_module_src_is_local_map(SrcIsLocalMap, !Info)
|
|
),
|
|
find_local_modules(ProgressStream, ModuleIndexes,
|
|
!LocalModuleIndexSet, !Info, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% find_module_deps(Globals, ModuleIndex, Succeeded, ModuleIndexSet,
|
|
% !Info, !IO).
|
|
%
|
|
% The reason we don't return maybe(ModuleIndexSet) is that
|
|
% with `--keep-going', we want to do as much work as possible.
|
|
%
|
|
:- type find_module_deps(T) ==
|
|
pred(io.text_output_stream, maybe_keep_going, globals, module_index,
|
|
maybe_succeeded, index_set(T), make_info, make_info, io, io).
|
|
:- inst find_module_deps ==
|
|
(pred(in, in, in, in, out, out, in, out, di, uo) is det).
|
|
|
|
% fold_find_modules_over_modules(KeepGoing, Globals, FindModules,
|
|
% ModuleIndexes, !Succeeded, !ModuleIndexSet, !Info, !IO):
|
|
%
|
|
% Invoke FindModules on each element of ModuleIndexes, adding
|
|
% the union of the returned module index sets to !ModuleIndexSet.
|
|
%
|
|
% Stop only if an invocation of FindModules returns did_not_succeed
|
|
% *and* KeepGoing is do_not_keep_going.
|
|
%
|
|
:- pred fold_find_modules_over_modules(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in,
|
|
find_module_deps(module_index)::in(find_module_deps),
|
|
list(module_index)::in, maybe_succeeded::in, maybe_succeeded::out,
|
|
module_index_set::in, module_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
fold_find_modules_over_modules(_, _, _, _,
|
|
[], !Succeeded, !ModuleIndexSet, !Info, !IO).
|
|
fold_find_modules_over_modules(ProgressStream, KeepGoing, Globals, FindModules,
|
|
[MI | MIs], !Succeeded, !ModuleIndexSet, !Info, !IO) :-
|
|
FindModules(ProgressStream, KeepGoing, Globals, MI,
|
|
HeadSucceeded, HeadModuleIndexSet, !Info, !IO),
|
|
index_set_union(HeadModuleIndexSet, !ModuleIndexSet),
|
|
should_we_stop_or_continue(KeepGoing, HeadSucceeded, StopOrContinue,
|
|
!Succeeded),
|
|
(
|
|
StopOrContinue = soc_stop
|
|
;
|
|
StopOrContinue = soc_continue,
|
|
fold_find_modules_over_modules(ProgressStream, KeepGoing, Globals,
|
|
FindModules, MIs, !Succeeded, !ModuleIndexSet, !Info, !IO)
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
% fold_prereq_spec_over_modules(ProgressStream, KeepGoing, Globals,
|
|
% PrereqSpec, ModuleIndexes, !Succeeded, !TargetIdIndexSet, !Info, !IO):
|
|
%
|
|
% Invoke find_prereqs_from_spec with PrereqSpec on each element of
|
|
% ModuleIndexes, adding the union of the resulting dependency file
|
|
% index sets to !TargetIdIndexSet.
|
|
%
|
|
% Stop only if an invocation of find_prereqs_from_spec returns
|
|
% did_not_succeed *and* KeepGoing is do_not_keep_going.
|
|
%
|
|
:- pred fold_prereq_spec_over_modules(io.text_output_stream::in,
|
|
maybe_keep_going::in, globals::in, prereq_spec::in, list(module_index)::in,
|
|
maybe_succeeded::in, maybe_succeeded::out,
|
|
target_id_index_set::in, target_id_index_set::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
fold_prereq_spec_over_modules(_, _, _, _,
|
|
[], !Succeeded, !TargetIdIndexSet, !Info, !IO).
|
|
fold_prereq_spec_over_modules(ProgressStream, KeepGoing, Globals, PrereqSpec,
|
|
[MI | MIs], !Succeeded, !TargetIdIndexSet, !Info, !IO) :-
|
|
find_prereqs_from_spec(ProgressStream, KeepGoing, Globals, MI, PrereqSpec,
|
|
HeadSucceeded, HeadTargetIdIndexSet, !Info, !IO),
|
|
index_set_union(HeadTargetIdIndexSet, !TargetIdIndexSet),
|
|
should_we_stop_or_continue(KeepGoing, HeadSucceeded, StopOrContinue,
|
|
!Succeeded),
|
|
(
|
|
StopOrContinue = soc_stop
|
|
;
|
|
StopOrContinue = soc_continue,
|
|
fold_prereq_spec_over_modules(ProgressStream, KeepGoing, Globals,
|
|
PrereqSpec, MIs, !Succeeded, !TargetIdIndexSet, !Info, !IO)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- func target_id_to_debug_string(string, string, target_id) = string.
|
|
|
|
target_id_to_debug_string(Prefix, Suffix, TargetId) = Str :-
|
|
(
|
|
TargetId = merc_target(TargetFile),
|
|
TargetFile = target_file(ModuleName, TargetType),
|
|
ModuleNameStr = sym_name_to_string(ModuleName),
|
|
TargetTypeStr = string.string(TargetType),
|
|
string.format("merc_target %s of %s",
|
|
[s(TargetTypeStr), s(ModuleNameStr)], Str0)
|
|
;
|
|
TargetId = non_merc_target(FileName),
|
|
string.format("non_term_target %s", [s(FileName)], Str0)
|
|
),
|
|
Str = Prefix ++ Str0 ++ Suffix.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module make.prereqs.
|
|
%---------------------------------------------------------------------------%
|