[m-rev.] for review: Add foreign include files to makefile dependencies files.
Peter Wang
novalazy at gmail.com
Fri Mar 14 17:05:32 AEDT 2014
List files included by pragma foreign_decl and pragma foreign_code
declarations in the makefile dependencies file (`.d') generated for
a module.
The written dependencies are more conservative than necessary
(e.g. C target files should not depend on Java include files),
but I don't think any more effort is warranted.
compiler/module_imports.m:
Add get_foreign_include_files to return a list of include files
from a list of items.
compiler/modules.m:
Add foreign include files when initialising the module_imports
structure in grab_imported_modules. Otherwise it will be empty
when the `.d' file is automatically generated as a side-effect
of generating target code.
compiler/write_deps_file.m:
Write include files from the module_imports structure into the
`.d' file.
doc/reference_manual.texi:
Update manual.
tests/invalid/Mmakefile:
Make `missing_file' a phony target. This change makes `make'
aware of the dependency and report the error, instead of
running the test case that checks the compiler's reaction
to the missing file.
---
diff --git a/compiler/module_imports.m b/compiler/module_imports.m
index ed292c1..7e83fb7 100644
--- a/compiler/module_imports.m
+++ b/compiler/module_imports.m
@@ -250,6 +250,12 @@
%
:- pred get_fact_table_dependencies(list(item)::in, list(string)::out) is det.
+ % Get foreign include_file dependencies for a module.
+ % This replicates part of get_item_list_foreign_code.
+ %
+:- pred get_foreign_include_files(list(item)::in,
+ foreign_include_file_info_list::out) is det.
+
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -804,5 +810,37 @@ get_fact_table_dependencies_2([Item | Items], !Deps) :-
get_fact_table_dependencies_2(Items, !Deps).
%-----------------------------------------------------------------------------%
+
+get_foreign_include_files(Items, IncludeFiles) :-
+ list.foldl(get_foreign_include_file, Items, [], IncludeFiles).
+
+:- pred get_foreign_include_file(item::in,
+ foreign_include_file_info_list::in, foreign_include_file_info_list::out)
+ is det.
+
+get_foreign_include_file(Item, !IncludeFiles) :-
+ (
+ Item = item_pragma(ItemPragma),
+ ItemPragma = item_pragma_info(_, Pragma, _, _),
+ (
+ Pragma = pragma_foreign_decl(FDInfo),
+ FDInfo = pragma_info_foreign_decl(Lang, _IsLocal, LiteralOrInclude)
+ ;
+ Pragma = pragma_foreign_code(FCInfo),
+ FCInfo = pragma_info_foreign_code(Lang, LiteralOrInclude)
+ )
+ ->
+ (
+ LiteralOrInclude = literal(_)
+ ;
+ LiteralOrInclude = include_file(FileName),
+ IncludeFile = foreign_include_file_info(Lang, FileName),
+ !:IncludeFiles = [IncludeFile | !.IncludeFiles]
+ )
+ ;
+ true
+ ).
+
+%-----------------------------------------------------------------------------%
:- end_module parse_tree.module_imports.
%-----------------------------------------------------------------------------%
diff --git a/compiler/modules.m b/compiler/modules.m
index e2f6560..7bcf077 100644
--- a/compiler/modules.m
+++ b/compiler/modules.m
@@ -161,8 +161,8 @@
% Similar to grab_imported_modules, but only reads in the unqualified
% short interfaces (.int3s), and the .int0 files for parent modules,
% instead of reading the long interfaces and qualified short interfaces
- % (.int and int2s). Does not set the `PublicChildren' or `FactDeps'
- % fields of the module_and_imports structure.
+ % (.int and int2s). Does not set the `PublicChildren', `FactDeps'
+ % `ForeignIncludeFiles' fields of the module_and_imports structure.
%
:- pred grab_unqual_imported_modules(globals::in, file_name::in,
module_name::in, module_name::in, list(item)::in, module_and_imports::out,
@@ -1876,10 +1876,11 @@ grab_imported_modules(Globals, SourceFileName, SourceFileModuleName,
ImpImportedModules0, ImpImportedModules,
ImpUsedModules0, ImpUsedModules, !Specs),
- get_fact_table_dependencies(Items0, FactDeps),
get_interface_and_implementation(ModuleName, no, Items0,
InterfaceItems, ImplItems),
get_children(InterfaceItems, PublicChildren),
+ get_fact_table_dependencies(Items0, FactDeps),
+ get_foreign_include_files(Items0, ForeignIncludeFiles),
(
MaybeTimestamp = yes(Timestamp),
MaybeTimestamps = yes(map.singleton(ModuleName,
@@ -1887,11 +1888,10 @@ grab_imported_modules(Globals, SourceFileName, SourceFileModuleName,
;
MaybeTimestamp = no,
MaybeTimestamps = no
-
),
init_module_and_imports(SourceFileName, SourceFileModuleName,
ModuleName, Items0, !.Specs, PublicChildren, NestedChildren,
- FactDeps, MaybeTimestamps, !:Module),
+ FactDeps, ForeignIncludeFiles, MaybeTimestamps, !:Module),
% If this module has any separately-compiled sub-modules, then
% we need to make everything in the implementation of this module
@@ -2021,7 +2021,7 @@ grab_unqual_imported_modules(Globals, SourceFileName, SourceFileModuleName,
% Construct the initial module import structure.
init_module_and_imports(SourceFileName, SourceFileModuleName, ModuleName,
- Items0, [], [], [], [], no, !:Module),
+ Items0, [], [], [], [], [], no, !:Module),
% Add `builtin' and `private_builtin' to the imported modules.
add_implicit_imports(Items0, Globals,
@@ -3602,11 +3602,12 @@ get_interface_and_implementation(ModuleName, IncludeImplTypes,
:- pred init_module_and_imports(file_name::in,
module_name::in, module_name::in, list(item)::in, list(error_spec)::in,
list(module_name)::in, list(module_name)::in, list(string)::in,
+ foreign_include_file_info_list::in,
maybe(module_timestamps)::in, module_and_imports::out) is det.
init_module_and_imports(SourceFileName, SourceFileModuleName, ModuleName,
Items0, Specs, PublicChildren, NestedChildren, FactDeps,
- MaybeTimestamps, Module) :-
+ ForeignIncludeFiles, MaybeTimestamps, Module) :-
% XXX The reason why init_module_and_imports is here and not in
% module_imports.m is this call. This should be fixed, preferably
% by changing the module_and_imports structure.
@@ -3614,9 +3615,9 @@ init_module_and_imports(SourceFileName, SourceFileModuleName, ModuleName,
ItemsCord = cord.from_list(Items),
Module = module_and_imports(SourceFileName, SourceFileModuleName,
ModuleName, [], [], [], [], [], PublicChildren,
- NestedChildren, FactDeps, contains_foreign_code_unknown, [], [],
- contains_no_foreign_export, ItemsCord, Specs, no_module_errors,
- MaybeTimestamps, no_main, dir.this_directory).
+ NestedChildren, FactDeps, contains_foreign_code_unknown, [],
+ ForeignIncludeFiles, contains_no_foreign_export, ItemsCord, Specs,
+ no_module_errors, MaybeTimestamps, no_main, dir.this_directory).
:- pred maybe_add_foreign_import_module(module_name::in,
list(item)::in, list(item)::out) is det.
diff --git a/compiler/write_deps_file.m b/compiler/write_deps_file.m
index 33b6e77..85d5cd9 100644
--- a/compiler/write_deps_file.m
+++ b/compiler/write_deps_file.m
@@ -36,9 +36,6 @@
% `.trans_opt' file may depend on. This is set to `no' if the
% dependency list is not available.
%
- % XXX we do not yet write dependencies on files referenced by pragma
- % foreign_decl or pragma foreign_code
- %
:- pred write_dependency_file(globals::in, module_and_imports::in,
set(module_name)::in, maybe(list(module_name))::in, io::di, io::uo) is det.
@@ -109,7 +106,7 @@ write_dependency_file(Globals, Module, AllDepsSet, MaybeTransOptDeps, !IO) :-
Module = module_and_imports(SourceFileName, SourceFileModuleName,
ModuleName, ParentDeps, IntDeps, ImplDeps, IndirectDeps,
_Children, InclDeps, NestedDeps, FactDeps0,
- ContainsForeignCode, ForeignImports0, _ForeignIncludeFiles,
+ ContainsForeignCode, ForeignImports0, ForeignIncludeFiles,
_ContainsForeignExport,
Items, _Specs, _Error, _Timestamps, _HasMain, _Dir),
@@ -275,6 +272,12 @@ write_dependency_file(Globals, Module, AllDepsSet, MaybeTransOptDeps, !IO) :-
),
list.foldl(Write, NestedExts, !IO)
),
+
+ % This is conservative: a target file for foreign language A does not
+ % does not truly depend on a file included for foreign language B.
+ write_foreign_include_file_dependencies_list(DepStream,
+ SourceFileName, ForeignIncludeFiles, !IO),
+
(
FactDeps = [_ | _],
io.write_strings(DepStream, [
@@ -860,6 +863,25 @@ write_dll_dependency(Globals, Module, Prefix, DepStream, !IO) :-
io.write_string(DepStream, Prefix, !IO),
io.write_string(DepStream, FileName, !IO).
+:- pred write_foreign_include_file_dependencies_list(io.output_stream::in,
+ file_name::in, foreign_include_file_info_list::in, io::di, io::uo) is det.
+
+write_foreign_include_file_dependencies_list(DepStream, SourceFileName,
+ IncludeFiles, !IO) :-
+ list.foldl(
+ write_foreign_include_file_dependency(DepStream, SourceFileName),
+ IncludeFiles, !IO).
+
+:- pred write_foreign_include_file_dependency(io.output_stream::in,
+ file_name::in, foreign_include_file_info::in, io::di, io::uo) is det.
+
+write_foreign_include_file_dependency(DepStream, SourceFileName,
+ IncludeFile, !IO) :-
+ IncludeFile = foreign_include_file_info(_Lang, IncludeFileName),
+ make_include_file_path(SourceFileName, IncludeFileName, IncludePath),
+ io.write_string(DepStream, " \\\n\t", !IO),
+ io.write_string(DepStream, IncludePath, !IO).
+
:- pred write_fact_table_dependencies_list(globals::in, module_name::in,
list(file_name)::in, string::in, io.output_stream::in,
io::di, io::uo) is det.
diff --git a/doc/reference_manual.texi b/doc/reference_manual.texi
index 525aa26..382e64fa 100644
--- a/doc/reference_manual.texi
+++ b/doc/reference_manual.texi
@@ -9566,8 +9566,8 @@ the string literal in the last argument, without further interpretation.
directory that contains the source file of the module containing the
declaration. The interpretation of the path is platform-dependent.
-The @samp{mmc --make} tool takes @samp{include_file} references into
-account when computing dependencies.
+ at samp{mmc --make} and @samp{mmake} treat included files as dependencies
+of the module.
@node Fact tables
@section Fact tables
diff --git a/tests/invalid/Mmakefile b/tests/invalid/Mmakefile
index b27ca64..c81d474 100644
--- a/tests/invalid/Mmakefile
+++ b/tests/invalid/Mmakefile
@@ -455,6 +455,7 @@ illtyped_compare.err: illtyped_compare.m
# For foreign_include_file_missing, the error is only caught when generating
# target code.
+.PHONY: missing_file
foreign_include_file_missing.err: foreign_include_file_missing.m
if $(MC) --target-code-only $(ALL_GRADEFLAGS) $(ALL_MCFLAGS) \
$* > $*.err 2>&1; \
More information about the reviews
mailing list