mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-17 06:47:17 +00:00
Estimated hours taken: 10 Branches: main Library installation with `mmc --make'. compiler/make.m: compiler/make.program_target.m: Handle `mmc --make lib<module>.install'. compiler/options.m: Add an option `--use-grade-subdirs', which causes all grade-dependenent files to be placed in `Mercury/<grade>/<ext>s' subdirectories, even those files that are intended for use by the user. `--use-grade-subdirs' is not documented because it is only intended for use in library installation with `mmc --make' (it doesn't work at all with Mmake). Documenting it would require documenting (and setting in stone) the layout of the `Mercury' directory, which is probably a bad idea. Mmake.workspace: compiler/handle_options.m: scripts/Mmake.rules: Header files are now always searched for using the plain file name (not Mercury/mihs/module.mih), so add a `--c-include-directory' option to search Mercury/mihs in the current directory. compiler/modules.m: compiler/intermod.m: compiler/make.module_dep_file.m: compiler/mercury_compile.m: compiler/mlds_to_c.m: compiler/trans_opt.m: Handle `--use-grade-subdirs' in module_name_to_file_name. Add module_name_to_search_file_name, which should be used to generate the names of files that might be part of an installed library. This is needed because installation and local directory hierarchies have a different layout, A better long-term fix would be to change things so that the installation and local directory layouts are the same. compiler/make.util.m: compiler/make.dependencies.m: compiler/make.module_target.m: Add an extra argument to get_target_timestamp and get_file_name to specify whether the file should be searched for. compiler/options_file.m: scripts/Mmake.vars.in: Handle the LIBGRADES and INSTALL_PREFIX make variables. doc/user_guide.texi: Remove the statement that library installation is not supported with `mmc --make'.
621 lines
21 KiB
Mathematica
621 lines
21 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.
|
|
%-----------------------------------------------------------------------------%
|
|
% File: make.module_dep_file.m
|
|
% Author: stayl
|
|
%
|
|
% Code to read and write the `<module>.module_dep' files, which contain
|
|
% information about inter-module dependencies.
|
|
%-----------------------------------------------------------------------------%
|
|
:- module make__module_dep_file.
|
|
|
|
:- interface.
|
|
|
|
:- import_module parse_tree__modules.
|
|
:- import_module std_util, io.
|
|
|
|
% Get the dependencies for a given module.
|
|
% Dependencies are generated on demand, not by a `mmc --make depend'
|
|
% command, so this predicate may need to read the source for
|
|
% the module.
|
|
:- pred get_module_dependencies(module_name::in, maybe(module_imports)::out,
|
|
make_info::in, make_info::out, io__state::di, io__state::uo) is det.
|
|
|
|
:- pred write_module_dep_file(module_imports::in,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- implementation.
|
|
|
|
get_module_dependencies(ModuleName, MaybeImports, Info0, Info) -->
|
|
{ RebuildDeps = Info0 ^ rebuild_dependencies },
|
|
(
|
|
{ ModuleName = unqualified(_) }
|
|
->
|
|
get_module_dependencies_2(RebuildDeps, ModuleName, MaybeImports,
|
|
Info0, Info)
|
|
;
|
|
{ map__search(Info0 ^ module_dependencies,
|
|
ModuleName, MaybeImports0) }
|
|
->
|
|
{ MaybeImports = MaybeImports0 },
|
|
{ Info = Info0 }
|
|
;
|
|
%
|
|
% For sub-modules, we need to generate the dependencies
|
|
% for the parent modules first (make_module_dependencies
|
|
% expects to be given the top-level module in a source file).
|
|
% If the module is a nested module, its dependencies will be
|
|
% generated as a side effect of generating the parent's
|
|
% dependencies.
|
|
%
|
|
{ Ancestors = get_ancestors(ModuleName) },
|
|
list__foldl3(
|
|
generate_ancestor_dependencies(RebuildDeps),
|
|
Ancestors, no, Error, Info0, Info1),
|
|
(
|
|
{ Error = yes },
|
|
{ MaybeImports = no },
|
|
{ Info = Info1 ^ module_dependencies
|
|
^ elem(ModuleName) := MaybeImports }
|
|
;
|
|
{ Error = no },
|
|
get_module_dependencies_2(RebuildDeps,
|
|
ModuleName, MaybeImports, Info1, Info)
|
|
)
|
|
).
|
|
|
|
:- pred generate_ancestor_dependencies(bool::in, module_name::in,
|
|
bool::in, bool::out, make_info::in, make_info::out,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
generate_ancestor_dependencies(_, ModuleName, yes, yes, Info,
|
|
Info ^ module_dependencies ^ elem(ModuleName) := no) --> [].
|
|
generate_ancestor_dependencies(RebuildDeps, ModuleName,
|
|
no, Error, Info0, Info) -->
|
|
get_module_dependencies_2(RebuildDeps,
|
|
ModuleName, MaybeImports, Info0, Info),
|
|
{ MaybeImports = yes(_), Error = no
|
|
; MaybeImports = no, Error = yes
|
|
}.
|
|
|
|
:- pred get_module_dependencies_2(bool::in, module_name::in,
|
|
maybe(module_imports)::out, make_info::in, make_info::out,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
get_module_dependencies_2(RebuildDeps, ModuleName,
|
|
MaybeImports, Info0, Info) -->
|
|
(
|
|
{ map__search(Info0 ^ module_dependencies, ModuleName, MaybeImports0) }
|
|
->
|
|
{ MaybeImports = MaybeImports0 },
|
|
{ Info = Info0 }
|
|
;
|
|
% We can't just use
|
|
% `get_target_timestamp(ModuleName - source, ..)'
|
|
% because that could recursively call get_module_dependencies,
|
|
% leading to an infinite loop. Just using module_name_to_file_name
|
|
% will fail if the module name doesn't match the file name, but
|
|
% that case is handled below.
|
|
module_name_to_file_name(ModuleName, ".m", no, SourceFileName),
|
|
get_file_timestamp([dir__this_directory], SourceFileName,
|
|
MaybeSourceFileTimestamp, Info0, Info2),
|
|
|
|
module_name_to_file_name(ModuleName, module_dep_file_extension,
|
|
no, DepFileName),
|
|
globals__io_lookup_accumulating_option(search_directories, SearchDirs),
|
|
get_file_timestamp(SearchDirs, DepFileName,
|
|
MaybeDepFileTimestamp, Info2, Info3),
|
|
|
|
(
|
|
{ MaybeSourceFileTimestamp = ok(SourceFileTimestamp) },
|
|
{ MaybeDepFileTimestamp = ok(DepFileTimestamp) },
|
|
(
|
|
{ RebuildDeps = no
|
|
; compare((>), DepFileTimestamp, SourceFileTimestamp)
|
|
}
|
|
->
|
|
read_module_dependencies(RebuildDeps,
|
|
ModuleName, Info3, Info6)
|
|
;
|
|
make_module_dependencies(ModuleName, Info3, Info6)
|
|
)
|
|
;
|
|
{ MaybeSourceFileTimestamp = error(_) },
|
|
{ MaybeDepFileTimestamp = ok(DepFileTimestamp) },
|
|
read_module_dependencies(RebuildDeps,
|
|
ModuleName, Info3, Info4),
|
|
|
|
%
|
|
% Check for the case where the module name doesn't match
|
|
% the source file name (e.g. parse.m contains module
|
|
% mdb.parse). Get the correct source file name from
|
|
% the module dependency file, then check whether the
|
|
% module dependency file is up to date.
|
|
%
|
|
{ map__lookup(Info4 ^ module_dependencies,
|
|
ModuleName, MaybeImports0) },
|
|
(
|
|
{ MaybeImports0 = yes(Imports0) },
|
|
{ Imports0 ^ module_dir = dir__this_directory }
|
|
->
|
|
{ SourceFileName1 = Imports0 ^ source_file_name },
|
|
get_file_timestamp([dir__this_directory], SourceFileName1,
|
|
MaybeSourceFileTimestamp1, Info4, Info5),
|
|
(
|
|
{ MaybeSourceFileTimestamp1 =
|
|
ok(SourceFileTimestamp1) },
|
|
(
|
|
{ RebuildDeps = no
|
|
; compare((>), DepFileTimestamp,
|
|
SourceFileTimestamp1)
|
|
}
|
|
->
|
|
{ Info6 = Info5 }
|
|
;
|
|
make_module_dependencies(ModuleName, Info5, Info6)
|
|
)
|
|
;
|
|
{ MaybeSourceFileTimestamp1 = error(Message) },
|
|
io__write_string("** Error reading file `"),
|
|
io__write_string(SourceFileName1),
|
|
io__write_string("' to generate dependencies: "),
|
|
io__write_string(Message),
|
|
io__write_string(".\n"),
|
|
maybe_write_importing_module(ModuleName,
|
|
Info5 ^ importing_module),
|
|
{ Info6 = Info5 }
|
|
)
|
|
;
|
|
{ Info6 = Info4 }
|
|
)
|
|
;
|
|
{ MaybeDepFileTimestamp = error(_)},
|
|
|
|
%
|
|
% Try to make the dependencies. This will succeed
|
|
% when the module name doesn't match the file name
|
|
% and the dependencies for this module haven't been
|
|
% built before. It will fail if the source file is
|
|
% in another directory.
|
|
%
|
|
( { RebuildDeps = yes } ->
|
|
make_module_dependencies(ModuleName, Info3, Info6)
|
|
;
|
|
{ Info6 = Info3 ^ module_dependencies
|
|
^ elem(ModuleName) := no }
|
|
)
|
|
),
|
|
|
|
{ MaybeImports1 = Info6 ^ module_dependencies ^ elem(ModuleName) ->
|
|
Info = Info6,
|
|
MaybeImports = MaybeImports1
|
|
;
|
|
MaybeImports = no,
|
|
Info = Info6 ^ module_dependencies ^ elem(ModuleName) := no
|
|
}
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- func module_dependencies_version_number = int.
|
|
|
|
module_dependencies_version_number = 1.
|
|
|
|
write_module_dep_file(Imports0) -->
|
|
% Make sure all the required fields are filled in.
|
|
globals__io_get_globals(Globals),
|
|
{ strip_imported_items(Imports0 ^ items, Items) },
|
|
{ init_dependencies(Imports0 ^ source_file_name,
|
|
Imports0 ^ source_file_module_name,
|
|
Imports0 ^ nested_children, no_module_errors, Globals,
|
|
Imports0 ^ module_name - Items, Imports) },
|
|
do_write_module_dep_file(Imports).
|
|
|
|
:- pred do_write_module_dep_file(module_imports::in,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
do_write_module_dep_file(Imports) -->
|
|
{ ModuleName = Imports ^ module_name },
|
|
module_name_to_file_name(ModuleName, module_dep_file_extension,
|
|
yes, ProgDepFile),
|
|
io__open_output(ProgDepFile, ProgDepResult),
|
|
(
|
|
{ ProgDepResult = ok(ProgDepStream) },
|
|
io__set_output_stream(ProgDepStream, OldOutputStream),
|
|
io__write_string("module("),
|
|
io__write_int(module_dependencies_version_number),
|
|
io__write_string(", """),
|
|
io__write_string(Imports ^ source_file_name),
|
|
io__write_string(""",\n\t"),
|
|
mercury_output_bracketed_sym_name(
|
|
Imports ^ source_file_module_name),
|
|
io__write_string(",\n\t{"),
|
|
io__write_list(Imports ^ parent_deps,
|
|
", ", mercury_output_bracketed_sym_name),
|
|
io__write_string("},\n\t{"),
|
|
io__write_list(Imports ^ int_deps,
|
|
", ", mercury_output_bracketed_sym_name),
|
|
io__write_string("},\n\t{"),
|
|
io__write_list(Imports ^ impl_deps,
|
|
", ", mercury_output_bracketed_sym_name),
|
|
io__write_string("},\n\t{"),
|
|
io__write_list(Imports ^ children,
|
|
", ", mercury_output_bracketed_sym_name),
|
|
io__write_string("},\n\t{"),
|
|
io__write_list(Imports ^ nested_children,
|
|
", ", mercury_output_bracketed_sym_name),
|
|
io__write_string("},\n\t{"),
|
|
io__write_list(Imports ^ fact_table_deps,
|
|
", ", io__write),
|
|
io__write_string("},\n\t{"),
|
|
{
|
|
Imports ^ foreign_code =
|
|
contains_foreign_code(ForeignLanguages0)
|
|
->
|
|
ForeignLanguages = set__to_sorted_list(
|
|
ForeignLanguages0)
|
|
;
|
|
ForeignLanguages = []
|
|
},
|
|
io__write_list(ForeignLanguages, ", ",
|
|
mercury_output_foreign_language_string),
|
|
io__write_string("},\n\t{"),
|
|
io__write_list(Imports ^ foreign_import_module_info, ", ",
|
|
(pred(ForeignImportModule::in, di, uo) is det -->
|
|
{ ForeignImportModule = foreign_import_module(
|
|
Lang, ForeignImport, _) },
|
|
mercury_output_foreign_language_string(Lang),
|
|
io__write_string(" - "),
|
|
mercury_output_bracketed_sym_name(ForeignImport)
|
|
)),
|
|
io__write_string("},\n\t"),
|
|
io__write(Imports ^ contains_foreign_export),
|
|
io__write_string(",\n\t"),
|
|
io__write(Imports ^ has_main),
|
|
io__write_string("\n).\n"),
|
|
io__set_output_stream(OldOutputStream, _),
|
|
io__close_output(ProgDepStream)
|
|
;
|
|
{ ProgDepResult = error(Error) },
|
|
{ io__error_message(Error, Msg) },
|
|
io__write_strings(["Error opening ", ProgDepFile,
|
|
"for output: ", Msg, "\n"]),
|
|
io__set_exit_status(1)
|
|
).
|
|
|
|
:- pred read_module_dependencies(bool::in, module_name::in,
|
|
make_info::in, make_info::out, io__state::di, io__state::uo) is det.
|
|
|
|
read_module_dependencies(RebuildDeps, ModuleName, Info0, Info) -->
|
|
module_name_to_search_file_name(ModuleName, module_dep_file_extension,
|
|
ModuleDepFile),
|
|
globals__io_lookup_accumulating_option(search_directories, SearchDirs),
|
|
io__input_stream(OldInputStream),
|
|
search_for_file_returning_dir(SearchDirs, ModuleDepFile, SearchResult),
|
|
( { SearchResult = ok(ModuleDir) } ->
|
|
parser__read_term(ImportsTermResult),
|
|
io__set_input_stream(OldInputStream, ModuleDepStream),
|
|
io__close_input(ModuleDepStream),
|
|
(
|
|
{ ImportsTermResult = term(_, ImportsTerm) },
|
|
{ ImportsTerm = term__functor(term__atom("module"),
|
|
ModuleArgs, _) },
|
|
{ ModuleArgs = [
|
|
VersionNumberTerm,
|
|
SourceFileTerm,
|
|
SourceFileModuleNameTerm,
|
|
ParentsTerm,
|
|
IntDepsTerm,
|
|
ImplDepsTerm,
|
|
ChildrenTerm,
|
|
NestedChildrenTerm,
|
|
FactDepsTerm,
|
|
ForeignLanguagesTerm,
|
|
ForeignImportsTerm,
|
|
ContainsForeignExportTerm,
|
|
HasMainTerm
|
|
] },
|
|
{ VersionNumberTerm = term__functor(
|
|
term__integer(module_dependencies_version_number),
|
|
[], _) },
|
|
{ SourceFileTerm = term__functor(
|
|
term__string(SourceFileName), [], _) },
|
|
{ sym_name_and_args(SourceFileModuleNameTerm,
|
|
SourceFileModuleName, []) },
|
|
{ parse_sym_name_list(ParentsTerm, Parents) },
|
|
{ parse_sym_name_list(IntDepsTerm, IntDeps) },
|
|
{ parse_sym_name_list(ImplDepsTerm, ImplDeps) },
|
|
{ parse_sym_name_list(ChildrenTerm, Children) },
|
|
{ parse_sym_name_list(NestedChildrenTerm, NestedChildren) },
|
|
{ FactDepsTerm = term__functor(term__atom("{}"),
|
|
FactDepsStrings, _) },
|
|
{ list__map(
|
|
(pred(StringTerm::in, String::out) is semidet :-
|
|
StringTerm = term__functor(
|
|
term__string(String), [], _)
|
|
), FactDepsStrings, FactDeps) },
|
|
{ ForeignLanguagesTerm = term__functor(
|
|
term__atom("{}"), ForeignLanguagesTerms, _) },
|
|
{ list__map(
|
|
(pred(LanguageTerm::in,
|
|
Language::out) is semidet :-
|
|
LanguageTerm = term__functor(
|
|
term__string(LanguageString), [], _),
|
|
globals__convert_foreign_language(
|
|
LanguageString, Language)
|
|
), ForeignLanguagesTerms, ForeignLanguages) },
|
|
{ ForeignImportsTerm = term__functor(term__atom("{}"),
|
|
ForeignImportTerms, _) },
|
|
{ list__map(
|
|
(pred(ForeignImportTerm::in,
|
|
ForeignImportModule::out) is semidet :-
|
|
ForeignImportTerm = term__functor(term__atom("-"),
|
|
[LanguageTerm, ImportedModuleTerm], _),
|
|
LanguageTerm = term__functor(
|
|
term__string(LanguageString), [], _),
|
|
globals__convert_foreign_language(LanguageString,
|
|
Language),
|
|
sym_name_and_args(ImportedModuleTerm,
|
|
ImportedModuleName, []),
|
|
ForeignImportModule = foreign_import_module(
|
|
Language, ImportedModuleName,
|
|
term__context_init)
|
|
), ForeignImportTerms, ForeignImports) },
|
|
|
|
{ ContainsForeignExportTerm =
|
|
term__functor(term__atom(ContainsForeignExportStr),
|
|
[], _) },
|
|
{ ContainsForeignExportStr = "contains_foreign_export",
|
|
ContainsForeignExport = contains_foreign_export
|
|
; ContainsForeignExportStr = "no_foreign_export",
|
|
ContainsForeignExport = no_foreign_export
|
|
},
|
|
|
|
{ HasMainTerm = term__functor(term__atom(HasMainStr),
|
|
[], _) },
|
|
{ HasMainStr = "has_main", HasMain = has_main
|
|
; HasMainStr = "no_main", HasMain = no_main
|
|
}
|
|
->
|
|
{ ForeignLanguages = [] ->
|
|
ContainsForeignCode = no_foreign_code
|
|
;
|
|
ContainsForeignCode = contains_foreign_code(
|
|
set__list_to_set(ForeignLanguages))
|
|
},
|
|
|
|
% { Imports = module_imports(^...) },
|
|
{ Imports ^ source_file_name = SourceFileName },
|
|
{ Imports ^ source_file_module_name = SourceFileModuleName },
|
|
{ Imports ^ module_name = ModuleName },
|
|
{ Imports ^ parent_deps = Parents },
|
|
{ Imports ^ int_deps = IntDeps },
|
|
{ Imports ^ impl_deps = ImplDeps },
|
|
{ Imports ^ indirect_deps = [] }, % not used.
|
|
{ Imports ^ children = Children },
|
|
{ Imports ^ public_children = [] }, % not used.
|
|
{ Imports ^ nested_children = NestedChildren },
|
|
{ Imports ^ fact_table_deps = FactDeps },
|
|
{ Imports ^ foreign_code = ContainsForeignCode },
|
|
{ Imports ^ foreign_import_module_info = ForeignImports },
|
|
{ Imports ^ contains_foreign_export = ContainsForeignExport },
|
|
{ Imports ^ items = [] }, % not used.
|
|
{ Imports ^ error = no_module_errors }, % not used.
|
|
{ Imports ^ maybe_timestamps = no }, % not used.
|
|
{ Imports ^ has_main = HasMain },
|
|
{ Imports ^ module_dir = ModuleDir },
|
|
|
|
{ Info1 = Info0 ^ module_dependencies
|
|
^ elem(ModuleName) := yes(Imports) },
|
|
|
|
%
|
|
% Read the dependencies for the nested children.
|
|
% If something goes wrong (for example one of the
|
|
% files was removed), the dependencies for all
|
|
% modules in the source file will be remade
|
|
% (make_module_dependencies expects to be given
|
|
% the top-level module in the source file).
|
|
%
|
|
{ SubRebuildDeps = no },
|
|
list__foldl2(read_module_dependencies(SubRebuildDeps),
|
|
NestedChildren, Info1, Info2),
|
|
(
|
|
{ list__member(NestedChild, NestedChildren) },
|
|
{
|
|
map__search(Info2 ^ module_dependencies,
|
|
NestedChild, ChildImports)
|
|
->
|
|
ChildImports = no
|
|
;
|
|
true
|
|
}
|
|
->
|
|
read_module_dependencies_remake(RebuildDeps,
|
|
ModuleName, "error in nested sub-modules",
|
|
Info2, Info)
|
|
;
|
|
{ Info = Info2 }
|
|
)
|
|
;
|
|
read_module_dependencies_remake(RebuildDeps,
|
|
ModuleName, "parse error", Info0, Info)
|
|
)
|
|
;
|
|
read_module_dependencies_remake(RebuildDeps, ModuleName,
|
|
"couldn't find `.module_dep' file", Info0, Info)
|
|
).
|
|
|
|
% Something went wrong reading the dependencies, so just rebuild them.
|
|
:- pred read_module_dependencies_remake(bool::in, module_name::in, string::in,
|
|
make_info::in, make_info::out, io__state::di, io__state::uo) is det.
|
|
|
|
read_module_dependencies_remake(RebuildDeps, ModuleName, Msg, Info0, Info) -->
|
|
( { RebuildDeps = yes } ->
|
|
debug_msg(
|
|
(pred(di, uo) is det -->
|
|
module_name_to_file_name(ModuleName,
|
|
module_dep_file_extension, no, ModuleDepsFile),
|
|
io__write_string("Error reading file `"),
|
|
io__write_string(ModuleDepsFile),
|
|
io__write_string("rebuilding: "),
|
|
io__write_string(Msg),
|
|
io__nl
|
|
)),
|
|
make_module_dependencies(ModuleName, Info0, Info)
|
|
;
|
|
{ Info = Info0 }
|
|
).
|
|
|
|
:- pred parse_sym_name_list(term::in, list(sym_name)::out) is semidet.
|
|
|
|
parse_sym_name_list(term__functor(term__atom("{}"), Args, _), SymNames) :-
|
|
list__map(
|
|
(pred(Arg::in, SymName::out) is semidet :-
|
|
sym_name_and_args(Arg, SymName, [])
|
|
), Args, SymNames).
|
|
|
|
% The module_name given must be the top level module in
|
|
% the source file. get_module_dependencies ensures this by
|
|
% making the dependencies for all parent modules of the
|
|
% requested module first.
|
|
:- pred make_module_dependencies(module_name::in, make_info::in,
|
|
make_info::out, io__state::di, io__state::uo) is det.
|
|
|
|
make_module_dependencies(ModuleName, Info0, Info) -->
|
|
{ Search = no },
|
|
{ ReturnTimestamp = yes },
|
|
|
|
redirect_output(ModuleName, MaybeErrorStream, Info0, Info1),
|
|
(
|
|
{ MaybeErrorStream = yes(ErrorStream) },
|
|
io__set_output_stream(ErrorStream, OldOutputStream),
|
|
read_mod(ModuleName, ".m",
|
|
"Getting dependencies for module", Search, ReturnTimestamp,
|
|
Items, Error, SourceFileName, _),
|
|
( { Error = fatal_module_errors } ->
|
|
io__set_output_stream(OldOutputStream, _),
|
|
io__write_string("** Error: error reading file `"),
|
|
io__write_string(SourceFileName),
|
|
io__write_string("' to generate dependencies.\n"),
|
|
maybe_write_importing_module(ModuleName, Info0 ^ importing_module),
|
|
|
|
% Display the contents of the `.err' file, then remove it
|
|
% so we don't leave `.err' files lying around for nonexistent
|
|
% modules.
|
|
globals__io_lookup_int_option(output_compile_error_lines, Lines),
|
|
globals__io_set_option(output_compile_error_lines, int(10000)),
|
|
unredirect_output(ModuleName, ErrorStream, Info1, Info2),
|
|
globals__io_set_option(output_compile_error_lines, int(Lines)),
|
|
module_name_to_file_name(ModuleName, ".err", no, ErrFileName),
|
|
io__remove_file(ErrFileName, _),
|
|
{ Info = Info2 ^ module_dependencies ^ elem(ModuleName) := no }
|
|
;
|
|
io__set_exit_status(0),
|
|
io__set_output_stream(ErrorStream, _),
|
|
split_into_submodules(ModuleName, Items, SubModuleList),
|
|
io__set_output_stream(OldOutputStream, _),
|
|
|
|
globals__io_get_globals(Globals),
|
|
{ assoc_list__keys(SubModuleList, SubModuleNames) },
|
|
{ list__map(
|
|
init_dependencies(SourceFileName, ModuleName,
|
|
SubModuleNames, Error, Globals),
|
|
SubModuleList, ModuleImportList) },
|
|
{ list__foldl(
|
|
(pred(ModuleImports::in, in, out) is det -->
|
|
{ SubModuleName = ModuleImports ^ module_name },
|
|
^ module_dependencies ^ elem(SubModuleName)
|
|
:= yes(ModuleImports)
|
|
), ModuleImportList, Info1, Info2) },
|
|
|
|
%
|
|
% If there were no errors, write out the `.int3' file
|
|
% while we have the contents of the module. The `int3'
|
|
% file doesn't depend on anything else.
|
|
%
|
|
( { Error = no_module_errors } ->
|
|
{ Target = ModuleName - unqualified_short_interface },
|
|
maybe_make_target_message(OldOutputStream, Target),
|
|
build_with_check_for_interrupt(
|
|
build_with_module_options(ModuleName,
|
|
["--make-short-interface"],
|
|
make_short_interfaces(ErrorStream,
|
|
SourceFileName, SubModuleList)),
|
|
cleanup_short_interfaces(SubModuleNames),
|
|
Succeeded, Info2, Info3)
|
|
;
|
|
{ Info3 = Info2 },
|
|
{ Succeeded = no }
|
|
),
|
|
|
|
build_with_check_for_interrupt(
|
|
(pred(yes::out, MakeInfo::in, MakeInfo::out, di, uo) is det -->
|
|
list__foldl(do_write_module_dep_file,
|
|
ModuleImportList)
|
|
), cleanup_module_dep_files(SubModuleNames),
|
|
_, Info3, Info5),
|
|
|
|
record_made_target(ModuleName - unqualified_short_interface,
|
|
process_module(make_short_interface), Succeeded, Info5, Info6),
|
|
|
|
unredirect_output(ModuleName, ErrorStream,
|
|
Info6, Info)
|
|
)
|
|
;
|
|
{ MaybeErrorStream = no },
|
|
{ Info = Info1 }
|
|
).
|
|
|
|
:- pred make_short_interfaces(io__output_stream::in, file_name::in,
|
|
assoc_list(module_name, item_list)::in, list(string)::in, bool::out,
|
|
make_info::in, make_info::out, io__state::di, io__state::uo) is det.
|
|
|
|
make_short_interfaces(ErrorStream, SourceFileName, SubModuleList,
|
|
_, Succeeded, Info, Info) -->
|
|
io__set_output_stream(ErrorStream, OutputStream),
|
|
list__foldl(
|
|
(pred(SubModule::in, di, uo) is det -->
|
|
{ SubModule = SubModuleName - SubModuleItems },
|
|
modules__make_short_interface(SourceFileName,
|
|
SubModuleName, SubModuleItems)
|
|
), SubModuleList),
|
|
io__set_output_stream(OutputStream, _),
|
|
io__get_exit_status(ExitStatus),
|
|
{ Succeeded = ( ExitStatus = 0 -> yes ; no ) }.
|
|
|
|
:- pred cleanup_short_interfaces(list(module_name)::in,
|
|
make_info::in, make_info::out, io__state::di, io__state::uo) is det.
|
|
|
|
cleanup_short_interfaces(SubModuleNames, Info0, Info) -->
|
|
list__foldl2(
|
|
(pred(SubModuleName::in, Info1::in, Info2::out, di, uo) is det -->
|
|
remove_target_file(SubModuleName, unqualified_short_interface,
|
|
Info1, Info2)
|
|
), SubModuleNames, Info0, Info).
|
|
|
|
:- pred cleanup_module_dep_files(list(module_name)::in,
|
|
make_info::in, make_info::out, io__state::di, io__state::uo) is det.
|
|
|
|
cleanup_module_dep_files(SubModuleNames, Info0, Info) -->
|
|
list__foldl2(
|
|
(pred(SubModuleName::in, Info1::in, Info2::out, di, uo) is det -->
|
|
remove_file(SubModuleName, module_dep_file_extension,
|
|
Info1, Info2)
|
|
), SubModuleNames, Info0, Info).
|
|
|
|
:- pred maybe_write_importing_module(module_name::in, maybe(module_name)::in,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
maybe_write_importing_module(_, no) --> [].
|
|
maybe_write_importing_module(ModuleName, yes(ImportingModuleName)) -->
|
|
io__write_string("** Module `") ,
|
|
prog_out__write_sym_name(ModuleName),
|
|
io__write_string("' is imported or included by module `"),
|
|
prog_out__write_sym_name(ImportingModuleName),
|
|
io__write_string("'.\n").
|
|
|
|
%-----------------------------------------------------------------------------%
|