Files
mercury/compiler/write_deps_file.m
Julien Fischer 0bd4a05717 Don't use -o when creating executables with MSVC.
Branches: main, 11.07

Don't use -o when creating executables with MSVC.  (For some silly
reason its been deprecated and we have to use -Fe instead.)
Note that mmc --make already uses -Fe with MSVC, this change only
affects mmake.

configure.in:
scripts/Mmake.vars.in:
	Define a new variable, EXEFILE_OPT, whose variable gives the option
	used to name executables.

compiler/write_deps_file.m:
	Use the above variable instead of hardcoding the option to be
	"-o".
2011-10-08 08:16:57 +00:00

2529 lines
103 KiB
Mathematica

%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%-----------------------------------------------------------------------------%
% Copyright (C) 2008-2011 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: write_deps_file.m.
%
%-----------------------------------------------------------------------------%
:- module parse_tree.write_deps_file.
:- interface.
:- import_module libs.file_util.
:- import_module libs.globals.
:- import_module mdbcomp.prim_data.
:- import_module parse_tree.deps_map.
:- import_module parse_tree.module_imports.
:- import_module bool.
:- import_module io.
:- import_module list.
:- import_module maybe.
:- import_module set.
% write_dependency_file(Globals, Module, AllDeps, MaybeTransOptDeps):
%
% Write out the per-module makefile dependencies (`.d') file for the
% specified module. AllDeps is the set of all module names which the
% generated code for this module might depend on, i.e. all that have been
% used or imported, directly or indirectly, into this module, including
% via .opt or .trans_opt files, and including parent modules of nested
% modules. MaybeTransOptDeps is a list of module names which the
% `.trans_opt' file may depend on. This is set to `no' if the
% dependency list is not available.
%
:- 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.
% Write out the `.dv' file, using the information collected in the
% deps_map data structure.
%
:- pred generate_dependencies_write_dv_file(globals::in, file_name::in,
module_name::in, deps_map::in, io::di, io::uo) is det.
% Write out the `.dep' file, using the information collected in the
% deps_map data structure.
%
:- pred generate_dependencies_write_dep_file(globals::in, file_name::in,
module_name::in, deps_map::in, io::di, io::uo) is det.
%-----------------------------------------------------------------------------%
% Generate the list of .NET DLLs which could be referred to by this module
% (including the module itself).
%
% If we are compiling a module within the standard library we should
% reference the runtime DLLs and all other library DLLs. If we are
% outside the library we should just reference mercury.dll (which will
% contain all the DLLs).
%
:- func referenced_dlls(module_name, list(module_name)) = list(module_name).
%-----------------------------------------------------------------------------%
% For each dependency, search intermod_directories for a .Suffix
% file or a .m file, filtering out those for which the search fails.
% If --use-opt-files is set, only look for `.opt' files,
% not `.m' files.
% XXX This won't find nested sub-modules.
% XXX Use `mmc --make' if that matters.
%
:- pred get_opt_deps(globals::in, bool::in, list(module_name)::in,
list(string)::in, string::in, list(module_name)::out, io::di, io::uo)
is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module libs.options.
:- import_module make. % undesirable dependency
:- import_module parse_tree.file_names.
:- import_module parse_tree.module_cmds.
:- import_module parse_tree.prog_data.
:- import_module parse_tree.prog_foreign.
:- import_module parse_tree.prog_io. % undesirable dependency
:- import_module parse_tree.prog_item.
:- import_module parse_tree.source_file_map.
:- import_module assoc_list.
:- import_module cord.
:- import_module dir.
:- import_module library.
:- import_module map.
:- import_module pair.
:- import_module require.
:- import_module string.
%-----------------------------------------------------------------------------%
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, _ContainsForeignExport,
Items, _Specs, _Error, _Timestamps, _HasMain, _Dir),
globals.lookup_bool_option(Globals, verbose, Verbose),
module_name_to_make_var_name(ModuleName, MakeVarName),
module_name_to_file_name(Globals, ModuleName, ".d",
do_create_dirs, DependencyFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".trans_opt_date",
do_not_create_dirs, TransOptDateFileName, !IO),
% To avoid problems with concurrent updates of `.d' files during
% parallel makes, we first create the file with a temporary name,
% and then rename it to the desired name when we've finished.
io.make_temp(dir.dirname(DependencyFileName), "tmp_d",
TmpDependencyFileName, !IO),
maybe_write_string(Verbose, "% Writing auto-dependency file `", !IO),
maybe_write_string(Verbose, DependencyFileName, !IO),
maybe_write_string(Verbose, "'...", !IO),
maybe_flush_output(Verbose, !IO),
io.open_output(TmpDependencyFileName, Result, !IO),
(
Result = error(IOError),
maybe_write_string(Verbose, " failed.\n", !IO),
maybe_flush_output(Verbose, !IO),
io.error_message(IOError, IOErrorMessage),
string.append_list(["error opening temporary file `",
TmpDependencyFileName, "' for output: ",
IOErrorMessage], Message),
report_error(Message, !IO)
;
Result = ok(DepStream),
list.append(IntDeps, ImplDeps, LongDeps0),
ShortDeps0 = IndirectDeps,
set.list_to_set(LongDeps0, LongDepsSet0),
set.delete(ModuleName, LongDepsSet0, LongDepsSet),
set.list_to_set(ShortDeps0, ShortDepsSet0),
set.difference(ShortDepsSet0, LongDepsSet, ShortDepsSet1),
set.delete(ModuleName, ShortDepsSet1, ShortDepsSet),
set.to_sorted_list(LongDepsSet, LongDeps),
set.to_sorted_list(ShortDepsSet, ShortDeps),
set.to_sorted_list(AllDepsSet, AllDeps),
list.sort_and_remove_dups(FactDeps0, FactDeps),
(
MaybeTransOptDeps = yes(TransOptDeps0),
set.list_to_set(TransOptDeps0, TransOptDepsSet0),
set.intersect(TransOptDepsSet0, LongDepsSet, TransOptDepsSet),
set.to_sorted_list(TransOptDepsSet, TransOptDateDeps),
% Note that maybe_read_dependency_file searches for
% this exact pattern.
io.write_strings(DepStream, [TransOptDateFileName, " :"], !IO),
write_dependencies_list(Globals, TransOptDateDeps, ".trans_opt",
DepStream, !IO)
;
MaybeTransOptDeps = no
),
(
FactDeps = [_ | _],
io.write_strings(DepStream,
["\n\n", MakeVarName, ".fact_tables ="], !IO),
write_file_dependencies_list(FactDeps, "", DepStream, !IO),
io.nl(DepStream, !IO),
globals.lookup_bool_option(Globals, assume_gmake, AssumeGmake),
(
AssumeGmake = yes,
io.write_strings(DepStream, [
"\n\n", MakeVarName,
".fact_tables.os = $(", MakeVarName,
".fact_tables:%=$(os_subdir)%.$O)\n\n",
MakeVarName,
".fact_tables.cs = $(", MakeVarName,
".fact_tables:%=$(cs_subdir)%.c)\n\n"
], !IO)
;
AssumeGmake = no,
io.write_strings(DepStream,
[MakeVarName, ".fact_tables.cs ="], !IO),
write_fact_table_dependencies_list(Globals, ModuleName,
FactDeps, ".c", DepStream, !IO),
io.write_strings(DepStream, ["\n\n", MakeVarName,
".fact_tables.os ="], !IO),
write_fact_table_dependencies_list(Globals, ModuleName,
FactDeps, ".$O", DepStream, !IO),
io.nl(DepStream, !IO)
)
;
FactDeps = []
),
( string.remove_suffix(SourceFileName, ".m", SourceFileBase) ->
ErrFileName = SourceFileBase ++ ".err"
;
unexpected($module, $pred, "source file doesn't end in `.m'")
),
module_name_to_file_name(Globals, ModuleName, ".optdate",
do_not_create_dirs, OptDateFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".c_date",
do_not_create_dirs, CDateFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".s_date",
do_not_create_dirs, AsmDateFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".pic_s_date",
do_not_create_dirs, PicAsmDateFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".$O",
do_not_create_dirs, ObjFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".il_date",
do_not_create_dirs, ILDateFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".java_date",
do_not_create_dirs, JavaDateFileName, !IO),
% XXX Why is the extension hardcoded to .pic_o here? That looks
% wrong. It should probably be .$(EXT_FOR_PIC_OBJECT) - juliensf.
module_name_to_file_name(Globals, ModuleName, ".pic_o",
do_not_create_dirs, PicObjFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".int0",
do_not_create_dirs, Int0FileName, !IO),
io.write_strings(DepStream, ["\n\n",
OptDateFileName, " ",
TransOptDateFileName, " ",
ErrFileName, " ",
CDateFileName, " ",
AsmDateFileName, " ",
PicAsmDateFileName, " ",
ILDateFileName, " ",
JavaDateFileName
], !IO),
io.write_strings(DepStream, [" : ", SourceFileName], !IO),
% If the module contains nested sub-modules then the `.int0' file
% must first be built.
(
InclDeps = [_ | _],
io.write_strings(DepStream, [" ", Int0FileName], !IO)
;
InclDeps = []
),
write_dependencies_list(Globals, ParentDeps, ".int0", DepStream, !IO),
write_dependencies_list(Globals, LongDeps, ".int", DepStream, !IO),
write_dependencies_list(Globals, ShortDeps, ".int2", DepStream, !IO),
NestedExts = [
".optdate",
".trans_opt_date",
".c_date",
".s_date",
".pic_s_date",
".dir/*.$O",
".il_date",
".java_date"],
% If a module contains nested-submodules then we need to build
% the nested children before attempting to build the parent module.
(
NestedDeps = []
;
NestedDeps = [_ | _],
Write = (pred(Ext::in, !.LIO::di, !:LIO::uo) is det :-
module_name_to_file_name(Globals, ModuleName, Ext,
do_not_create_dirs, ExtName, !LIO),
io.write_strings(DepStream, ["\n\n", ExtName, " : "], !LIO),
write_dependencies_list(Globals, NestedDeps, Ext, DepStream,
!LIO)
),
list.foldl(Write, NestedExts, !IO)
),
(
FactDeps = [_ | _],
io.write_strings(DepStream, [
" \\\n\t$(", MakeVarName, ".fact_tables)\n\n",
"$(", MakeVarName, ".fact_tables.os) : $(",
MakeVarName, ".fact_tables) ",
SourceFileName, "\n\n",
"$(", MakeVarName, ".fact_tables.cs) : ",
ObjFileName, "\n"
], !IO)
;
FactDeps = []
),
globals.lookup_bool_option(Globals, use_opt_files, UseOptFiles),
globals.lookup_bool_option(Globals, intermodule_optimization,
Intermod),
globals.lookup_accumulating_option(Globals, intermod_directories,
IntermodDirs),
% If intermodule_optimization is enabled then all the .mh files
% must exist because it is possible that the .c file imports them
% directly or indirectly.
(
Intermod = yes,
io.write_strings(DepStream, ["\n\n", ObjFileName, " : "], !IO),
write_dependencies_list(Globals, AllDeps, ".mh", DepStream, !IO)
;
Intermod = no
),
(
( Intermod = yes
; UseOptFiles = yes
)
->
io.write_strings(DepStream, [
"\n\n",
TransOptDateFileName, " ",
ErrFileName, " ",
CDateFileName, " ",
AsmDateFileName, " ",
PicAsmDateFileName, " ",
ILDateFileName, " ",
JavaDateFileName, " : "
], !IO),
% The target (e.g. C) file only depends on the .opt files
% from the current directory, so that inter-module optimization
% works when the .opt files for the library are unavailable.
% This is only necessary because make doesn't allow conditional
% dependencies. The dependency on the current module's .opt file
% is to make sure the module gets type-checked without having
% the definitions of abstract types from other modules.
%
% XXX The code here doesn't correctly handle dependencies
% on `.int' and `.int2' files needed by the `.opt' files.
globals.lookup_bool_option(Globals, transitive_optimization,
TransOpt),
globals.lookup_bool_option(Globals, use_trans_opt_files,
UseTransOpt),
(
( TransOpt = yes
; UseTransOpt = yes
)
->
bool.not(UseTransOpt, BuildOptFiles),
get_both_opt_deps(Globals, BuildOptFiles,
[ModuleName | LongDeps], IntermodDirs,
OptDeps, TransOptDeps, !IO),
OptInt0Deps = sort_and_remove_dups(
condense(list.map(get_ancestors, OptDeps))),
write_dependencies_list(Globals, OptDeps,
".opt", DepStream, !IO),
write_dependencies_list(Globals, OptInt0Deps,
".int0", DepStream, !IO),
io.write_strings(DepStream, [
"\n\n",
ErrFileName, " ",
CDateFileName, " ",
AsmDateFileName, " ",
PicAsmDateFileName, " ",
ILDateFileName, " ",
JavaDateFileName, " : "
], !IO),
write_dependencies_list(Globals, TransOptDeps,
".trans_opt", DepStream, !IO)
;
bool.not(UseOptFiles, BuildOptFiles),
get_opt_deps(Globals, BuildOptFiles, [ModuleName | LongDeps],
IntermodDirs, ".opt", OptDeps, !IO),
OptInt0Deps = sort_and_remove_dups(
condense(list.map(get_ancestors, OptDeps))),
write_dependencies_list(Globals, OptDeps,
".opt", DepStream, !IO),
write_dependencies_list(Globals, OptInt0Deps,
".int0", DepStream, !IO)
)
;
true
),
globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
globals.get_target(Globals, CompilationTarget),
(
HighLevelCode = yes,
CompilationTarget = target_c
->
% For --high-level-code with --target c, we need to make sure that
% we generate the header files for imported modules before
% compiling the C files, since the generated C files
% #include those header files.
io.write_strings(DepStream, [
"\n\n",
PicObjFileName, " ",
ObjFileName, " :"
], !IO),
write_dependencies_list(Globals, AllDeps, ".mih", DepStream, !IO)
;
true
),
% We need to tell make how to make the header files. The header files
% are actually built by the same command that creates the .c or .s
% file, so we just make them depend on the .c or .s files.
% This is needed for the --high-level-code rule above, and for
% the rules introduced for `:- pragma foreign_import_module'
% declarations. In some grades the header file won't actually be built
% (e.g. LLDS grades for modules not containing `:- pragma export'
% declarations), but this rule won't do any harm.
module_name_to_file_name(Globals, ModuleName, ".c",
do_not_create_dirs, CFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".s",
do_not_create_dirs, AsmFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".mh",
do_not_create_dirs, HeaderFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".mih",
do_not_create_dirs, HeaderFileName2, !IO),
io.write_strings(DepStream, [
"\n\n",
"ifeq ($(TARGET_ASM),yes)\n",
HeaderFileName, " ", HeaderFileName2, " : ", AsmFileName, "\n",
"else\n",
HeaderFileName, " ", HeaderFileName2, " : ", CFileName, "\n",
"endif"
], !IO),
% The `.module_dep' file is made as a side effect of
% creating the `.c', `.s', `.il', or `.java'.
module_name_to_file_name(Globals, ModuleName, ".il",
do_not_create_dirs, ILFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".java",
do_not_create_dirs, JavaFileName, !IO),
module_name_to_file_name(Globals, ModuleName,
make_module_dep_file_extension, do_not_create_dirs,
ModuleDepFileName, !IO),
io.write_strings(DepStream, [
"\n\n",
"ifeq ($(TARGET_ASM),yes)\n",
ModuleDepFileName, " : ", AsmFileName, "\n",
"else\n",
" ifeq ($(findstring il,$(GRADE)),il)\n",
ModuleDepFileName, " : ", ILFileName, "\n",
" else\n",
" ifeq ($(findstring java,$(GRADE)),java)\n",
ModuleDepFileName, " : ", JavaFileName, "\n",
" else\n",
ModuleDepFileName, " : ", CFileName, "\n",
" endif\n",
" endif\n",
"endif"
], !IO),
% The .date and .date0 files depend on the .int0 files for the parent
% modules, and the .int3 files for the directly and indirectly imported
% modules.
%
% For nested sub-modules, the `.date' files for the parent modules
% also depend on the same things as the `.date' files for this module,
% since all the `.date' files will get produced by a single mmc
% command. Similarly for `.date0' files, except these don't depend
% on the `.int0' files, because when doing the
% `--make-private-interface' for nested modules, mmc will process
% the modules in outermost to innermost order so as to produce each
% `.int0' file before it is needed.
module_name_to_file_name(Globals, ModuleName, ".date",
do_not_create_dirs, DateFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".date0",
do_not_create_dirs, Date0FileName, !IO),
io.write_strings(DepStream, [
"\n\n", DateFileName, " ", Date0FileName
], !IO),
write_dependencies_list(Globals, ParentDeps, ".date", DepStream, !IO),
io.write_strings(DepStream, [" : ", SourceFileName], !IO),
write_dependencies_list(Globals, ParentDeps, ".int0", DepStream, !IO),
write_dependencies_list(Globals, LongDeps, ".int3", DepStream, !IO),
write_dependencies_list(Globals, ShortDeps, ".int3", DepStream, !IO),
io.write_strings(DepStream, ["\n\n", Date0FileName], !IO),
write_dependencies_list(Globals, ParentDeps, ".date0", DepStream, !IO),
io.write_strings(DepStream, [" : ", SourceFileName], !IO),
write_dependencies_list(Globals, LongDeps, ".int3", DepStream, !IO),
write_dependencies_list(Globals, ShortDeps, ".int3", DepStream, !IO),
io.write_string(DepStream, "\n\n", !IO),
% If we can pass the module name rather than the file name, then do so.
% `--smart-recompilation' doesn't work if the file name is passed
% and the module name doesn't match the file name.
have_source_file_map(HaveMap, !IO),
(
HaveMap = yes,
module_name_to_file_name_stem(SourceFileModuleName, ModuleArg)
;
HaveMap = no,
ModuleArg = SourceFileName
),
globals.get_target(Globals, Target),
globals.lookup_bool_option(Globals, sign_assembly, SignAssembly),
% If we are on the IL backend, add the dependency that the
% top level dll of a nested module hierachy depends on all
% of it sub-modules dlls, as they are referenced from
% inside the top level dll.
% XXX Do we need to do the same for Java?
module_name_to_file_name(Globals, ModuleName, ".dll",
do_not_create_dirs, DllFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".class",
do_not_create_dirs, ClassFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".beam",
do_not_create_dirs, BeamFileName, !IO),
SubModules = submodules(ModuleName, AllDeps),
(
Target = target_il,
SubModules = [_ | _]
->
io.write_strings(DepStream, [DllFileName, " : "], !IO),
write_dll_dependencies_list(Globals, SubModules, "", DepStream,
!IO),
io.nl(DepStream, !IO)
;
true
),
(
ContainsForeignCode = contains_foreign_code(LangSet),
ForeignImports = ForeignImports0
;
ContainsForeignCode = contains_foreign_code_unknown,
get_item_list_foreign_code(Globals, cord.list(Items), LangSet,
ForeignImports1, _),
% If we're generating the `.dep' file, ForeignImports0 will contain
% a conservative approximation to the set of foreign imports
% needed which will include imports required by imported modules.
(
ForeignImports0 = [],
ForeignImports = ForeignImports1
;
ForeignImports0 = [_ | _],
ForeignImports = ForeignImports0
)
;
ContainsForeignCode = contains_no_foreign_code,
set.init(LangSet),
ForeignImports = ForeignImports0
),
% Handle dependencies introduced by
% `:- pragma foreign_import_module' declarations.
list.filter_map(
(pred(ForeignImportMod::in, Import::out) is semidet :-
Import = foreign_import_module_name_from_module(
ForeignImportMod, SourceFileModuleName),
% XXX We can't include mercury.dll as mmake can't find it,
% but we know that it exists.
Import \= unqualified("mercury")
), ForeignImports, ForeignImportedModules),
(
ForeignImportedModules = []
;
ForeignImportedModules = [_ | _],
(
Target = target_il,
ForeignImportTargets = [DllFileName],
ForeignImportExt = ".dll"
;
Target = target_csharp,
% XXX don't know enough about C# yet
ForeignImportTargets = [],
ForeignImportExt = ".cs"
;
Target = target_java,
ForeignImportTargets = [ClassFileName],
ForeignImportExt = ".java"
;
Target = target_erlang,
ForeignImportTargets = [BeamFileName],
ForeignImportExt = ".hrl"
;
Target = target_c,
% NOTE: for C (and asm) the possible targets might be a .o
% file _or_ a .pic_o file. We need to include dependencies
% for the latter otherwise invoking mmake with a <module>.pic_o
% target will break.
ForeignImportTargets = [ObjFileName, PicObjFileName],
ForeignImportExt = ".mh"
;
Target = target_asm,
ForeignImportTargets = [ObjFileName, PicObjFileName],
ForeignImportExt = ".mh"
;
% XXX These are just the C ones at the moment.
Target = target_x86_64,
ForeignImportTargets = [ObjFileName, PicObjFileName],
ForeignImportExt = ".mh"
),
WriteForeignImportTarget = (pred(ForeignImportTarget::in,
!.IO::di, !:IO::uo) is det :-
io.write_string(DepStream, "\n\n", !IO),
io.write_string(DepStream, ForeignImportTarget, !IO),
io.write_string(DepStream, " : ", !IO),
write_dependencies_list(Globals, ForeignImportedModules,
ForeignImportExt, DepStream, !IO),
io.write_string(DepStream, "\n\n", !IO)
),
list.foldl(WriteForeignImportTarget, ForeignImportTargets, !IO)
),
(
Target = target_il,
not set.empty(LangSet)
->
Langs = set.to_sorted_list(LangSet),
list.foldl(write_foreign_dependency_for_il(Globals, DepStream,
ModuleName, AllDeps, ForeignImports), Langs, !IO)
;
true
),
% If we are signing the assembly, then we will need the strong key
% to sign the il file with so add a dependency that the il file
% requires the strong name file `mercury.sn'. Also add the variable
% ILASM_KEYFLAG-<module> which is used to build the command line
% for ilasm.
(
Target = target_il,
SignAssembly = yes
->
module_name_to_make_var_name(ModuleName, ModuleNameString),
module_name_to_file_name(Globals, ModuleName, ".il",
do_not_create_dirs, IlFileName, !IO),
io.write_strings(DepStream, [
"ILASM_KEYFLAG-", ModuleNameString,
" = /keyf=mercury.sn\n",
IlFileName, " : mercury.sn\n"], !IO)
;
true
),
module_name_to_file_name(Globals, ModuleName, ".int",
do_not_create_dirs, IntFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".int2",
do_not_create_dirs, Int2FileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".int3",
do_not_create_dirs, Int3FileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".opt",
do_not_create_dirs, OptFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".trans_opt",
do_not_create_dirs, TransOptFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".date3",
do_not_create_dirs, Date3FileName, !IO),
% We add some extra dependencies to the generated `.d' files, so that
% local `.int', `.opt', etc. files shadow the installed versions
% properly (e.g. for when you're trying to build a new version
% of an installed library). This saves the user from having to add
% these explicitly if they have multiple libraries installed
% in the same installation hierarchy which aren't independent (e.g.
% one uses another). These extra dependencies are necessary due to
% the way the combination of search paths and pattern rules
% works in Make.
%
% Be very careful about changing the following rules. The `@:' is a
% silent do-nothing command. It is used to force GNU Make to recheck
% the timestamp on the target file. (It is a pity that GNU Make
% doesn't have a way of handling these sorts of rules in a
% nicer manner.)
io.write_strings(DepStream, [
"\n",
Int0FileName, " : ", Date0FileName, "\n",
"\t@:\n",
IntFileName, " : ", DateFileName, "\n",
"\t@:\n",
Int2FileName, " : ", DateFileName, "\n",
"\t@:\n",
Int3FileName, " : ", Date3FileName, "\n",
"\t@:\n",
OptFileName, " : ", OptDateFileName, "\n",
"\t@:\n",
TransOptFileName, " : ", TransOptDateFileName, "\n",
"\t@:\n"
], !IO),
globals.lookup_bool_option(Globals, use_subdirs, UseSubdirs),
(
UseSubdirs = yes,
io.nl(DepStream, !IO),
list.foldl(
write_subdirs_shorthand_rule(Globals, DepStream, ModuleName),
[".c", ".$O", ".pic_o", ".s", ".pic_s",
".java", ".class", ".il", ".dll"], !IO)
;
UseSubdirs = no
),
( SourceFileName \= default_source_file(ModuleName) ->
% The pattern rules in Mmake.rules won't work, since the source
% file name doesn't match the expected source file name for this
% module name. This can occur due to just the use of different
% source file names, or it can be due to the use of nested modules.
% So we need to output hard-coded rules in this case.
%
% The rules output below won't work in the case of nested modules
% with parallel makes, because it will end up invoking the same
% command twice (since it produces two output files) at the same
% time.
%
% Any changes here will require corresponding changes to
% scripts/Mmake.rules. See that file for documentation
% on these rules.
io.write_strings(DepStream, [
"\n",
Date0FileName, " : ", SourceFileName, "\n",
"\t$(MCPI) $(ALL_GRADEFLAGS) ",
"$(ALL_MCPIFLAGS) ", ModuleArg, "\n",
DateFileName, " : ", SourceFileName, "\n",
"\t$(MCI) $(ALL_GRADEFLAGS) $(ALL_MCIFLAGS) ",
ModuleArg, "\n",
Date3FileName, " : ", SourceFileName, "\n",
"\t$(MCSI) $(ALL_GRADEFLAGS) $(ALL_MCSIFLAGS) ",
ModuleArg, "\n",
OptDateFileName, " : ", SourceFileName, "\n",
"\t$(MCOI) $(ALL_GRADEFLAGS) $(ALL_MCOIFLAGS) ",
ModuleArg, "\n",
TransOptDateFileName, " : ", SourceFileName,
"\n",
"\t$(MCTOI) $(ALL_GRADEFLAGS) ",
"$(ALL_MCTOIFLAGS) ", ModuleArg, "\n",
CDateFileName, " : ", SourceFileName, "\n",
"\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
ModuleArg, " $(ERR_REDIRECT)\n",
"ifeq ($(TARGET_ASM),yes)\n",
AsmDateFileName, " : ", SourceFileName, "\n",
"\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
"--target-code-only ", ModuleArg,
" $(ERR_REDIRECT)\n",
PicAsmDateFileName, " : ", SourceFileName, "\n",
"\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
"--target-code-only --pic ",
"\\\n",
"\t\t--cflags ""$(GCCFLAGS_FOR_PIC)"" ",
ModuleArg, " $(ERR_REDIRECT)\n",
"endif # TARGET_ASM\n",
ILDateFileName, " : ", SourceFileName, "\n",
"\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
"--il-only ", ModuleArg,
" $(ERR_REDIRECT)\n",
JavaDateFileName, " : ", SourceFileName, "\n",
"\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
"--java-only ", ModuleArg,
" $(ERR_REDIRECT)\n"
], !IO)
;
true
),
io.close_output(DepStream, !IO),
io.rename_file(TmpDependencyFileName, DependencyFileName, Result3,
!IO),
(
Result3 = error(_),
% On some systems, we need to remove the existing file
% first, if any. So try again that way.
io.remove_file(DependencyFileName, Result4, !IO),
(
Result4 = error(Error4),
maybe_write_string(Verbose, " failed.\n", !IO),
maybe_flush_output(Verbose, !IO),
io.error_message(Error4, ErrorMsg),
string.append_list(["can't remove file `", DependencyFileName,
"': ", ErrorMsg], Message),
report_error(Message, !IO)
;
Result4 = ok,
io.rename_file(TmpDependencyFileName, DependencyFileName,
Result5, !IO),
(
Result5 = error(Error5),
maybe_write_string(Verbose, " failed.\n", !IO),
maybe_flush_output(Verbose, !IO),
io.error_message(Error5, ErrorMsg),
string.append_list(["can't rename file `",
TmpDependencyFileName, "' as `", DependencyFileName,
"': ", ErrorMsg], Message),
report_error(Message, !IO)
;
Result5 = ok,
maybe_write_string(Verbose, " done.\n", !IO)
)
)
;
Result3 = ok,
maybe_write_string(Verbose, " done.\n", !IO)
)
).
% submodules(Module, Imports):
%
% Returns the list of submodules from Imports which are sub-modules of
% Module, if Module is a top level module and not in the std library.
% Otherwise it returns the empty list.
%
:- func submodules(module_name, list(module_name)) = list(module_name).
submodules(Module, Modules0) = Modules :-
(
Module = unqualified(Str),
\+ mercury_std_library_module_name(Module)
->
P = (pred(M::in) is semidet :-
Str = outermost_qualifier(M),
M \= Module
),
list.filter(P, Modules0, Modules)
;
Modules = []
).
%-----------------------------------------------------------------------------%
:- pred write_dependencies_list(globals::in, list(module_name)::in, string::in,
io.output_stream::in, io::di, io::uo) is det.
write_dependencies_list(_, [], _, _, !IO).
write_dependencies_list(Globals, [Module | Modules], Suffix, DepStream, !IO) :-
module_name_to_file_name(Globals, Module, Suffix, do_not_create_dirs,
FileName, !IO),
io.write_string(DepStream, " \\\n\t", !IO),
io.write_string(DepStream, FileName, !IO),
write_dependencies_list(Globals, Modules, Suffix, DepStream, !IO).
:- pred write_compact_dependencies_list(globals::in, list(module_name)::in,
string::in, string::in, maybe(pair(string))::in, io.output_stream::in,
io::di, io::uo) is det.
write_compact_dependencies_list(Globals, Modules, Prefix, Suffix, Basis,
DepStream, !IO) :-
(
Basis = yes(VarName - OldSuffix),
io.write_string(DepStream, "$(", !IO),
io.write_string(DepStream, VarName, !IO),
io.write_string(DepStream, ":%", !IO),
io.write_string(DepStream, OldSuffix, !IO),
io.write_string(DepStream, "=", !IO),
io.write_string(DepStream, Prefix, !IO),
io.write_string(DepStream, "%", !IO),
io.write_string(DepStream, Suffix, !IO),
io.write_string(DepStream, ")", !IO)
;
Basis = no,
write_dependencies_list(Globals, Modules, Suffix, DepStream, !IO)
).
:- pred write_compact_dependencies_separator(maybe(pair(string))::in,
io.output_stream::in, io::di, io::uo) is det.
write_compact_dependencies_separator(no, _DepStream, !IO).
write_compact_dependencies_separator(yes(_), DepStream, !IO) :-
io.write_string(DepStream, " ", !IO).
:- pred write_dll_dependencies_list(globals::in, list(module_name)::in,
string::in, io.output_stream::in, io::di, io::uo) is det.
write_dll_dependencies_list(_Globals, [], _Prefix, _DepStream, !IO).
write_dll_dependencies_list(Globals, [Module | Modules], Prefix, DepStream,
!IO) :-
write_dll_dependency(Globals, Module, Prefix, DepStream, !IO),
write_dll_dependencies_list(Globals, Modules, Prefix, DepStream, !IO).
:- pred write_dll_dependency(globals::in, module_name::in, string::in,
io.output_stream::in, io::di, io::uo) is det.
write_dll_dependency(Globals, Module, Prefix, DepStream, !IO) :-
module_name_to_file_name(Globals, Module, ".dll", do_not_create_dirs,
FileName, !IO),
io.write_string(DepStream, " \\\n\t", !IO),
io.write_string(DepStream, Prefix, !IO),
io.write_string(DepStream, FileName, !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.
write_fact_table_dependencies_list(_, _, [], _, _, !IO).
write_fact_table_dependencies_list(Globals, Module, [FactTable | FactTables],
Suffix, DepStream, !IO) :-
fact_table_file_name(Globals, Module, FactTable, Suffix,
do_not_create_dirs, FileName, !IO),
io.write_string(DepStream, " \\\n\t", !IO),
io.write_string(DepStream, FileName, !IO),
write_fact_table_dependencies_list(Globals, Module, FactTables, Suffix,
DepStream, !IO).
:- pred write_extra_link_dependencies_list(globals::in,
assoc_list(file_name, module_name)::in, string::in,
io.output_stream::in, io::di, io::uo) is det.
write_extra_link_dependencies_list(_, [], _, _, !IO).
write_extra_link_dependencies_list(Globals, [ExtraLink - Module | ExtraLinks],
Suffix, DepStream, !IO) :-
extra_link_obj_file_name(Globals, Module, ExtraLink, Suffix,
do_not_create_dirs, FileName, !IO),
io.write_string(DepStream, " \\\n\t", !IO),
io.write_string(DepStream, FileName, !IO),
write_extra_link_dependencies_list(Globals, ExtraLinks, Suffix, DepStream,
!IO).
:- pred write_file_dependencies_list(list(string)::in, string::in,
io.output_stream::in, io::di, io::uo) is det.
write_file_dependencies_list([], _, _, !IO).
write_file_dependencies_list([FileName | FileNames], Suffix, DepStream, !IO) :-
io.write_string(DepStream, " \\\n\t", !IO),
io.write_string(DepStream, FileName, !IO),
io.write_string(DepStream, Suffix, !IO),
write_file_dependencies_list(FileNames, Suffix, DepStream, !IO).
% Generate the following dependency. This dependency is
% needed because module__cpp_code.dll might refer to
% high level data in any of the mercury modules it
% imports plus itself.
% We also generate a dependency on the .il file, so that mmake
% knows we need to generate the .il file to get the foreign language
% source file (e.g. .cpp file).
%
% For example, for MC++ we generate:
%
% <module>__cpp_code.dll : <module>.dll <imports>.dll
% <module>__cpp_code.cpp : <module>.il
%
% (the rule to generate .dll from .cpp is a pattern rule in
% scripts/Mmake.rules).
%
:- pred write_foreign_dependency_for_il(globals::in, io.output_stream::in,
sym_name::in, list(module_name)::in, foreign_import_module_info_list::in,
foreign_language::in, io::di, io::uo) is det.
write_foreign_dependency_for_il(Globals, DepStream, ModuleName, AllDeps,
ForeignImports, ForeignLang, !IO) :-
(
ForeignModuleName = foreign_language_module_name(ModuleName,
ForeignLang),
ForeignExt = foreign_language_file_extension(ForeignLang)
->
module_name_to_make_var_name(ForeignModuleName,
ForeignModuleNameString),
module_name_to_file_name(Globals, ForeignModuleName, ForeignExt,
do_not_create_dirs, ForeignFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".il",
do_not_create_dirs, IlFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".dll",
do_not_create_dirs, DllFileName, !IO),
module_name_to_file_name(Globals, ForeignModuleName, ".dll",
do_not_create_dirs, ForeignDllFileName, !IO),
io.write_strings(DepStream,
[ForeignDllFileName, " : ", DllFileName], !IO),
% XXX This change doesn't work correctly because mmake can't find
% the dlls which don't reside in the current directory.
% write_dll_dependencies_list(ModuleName, AllDeps, DepStream, !IO),
io.nl(DepStream, !IO),
io.write_strings(DepStream,
[ForeignFileName, " : ", IlFileName, "\n\n"], !IO),
(
ForeignLang = lang_csharp,
% Store in the variable CSHARP_ASSEMBLY_REFS-foreign_code_name
% the command line argument to reference all the dlls the
% foreign code module references.
io.write_strings(DepStream,
["CSHARP_ASSEMBLY_REFS-", ForeignModuleNameString, "="], !IO),
( mercury_std_library_module_name(ModuleName) ->
Prefix = "/addmodule:"
;
Prefix = "/r:"
),
ForeignDeps = list.map(
(func(M) = foreign_import_module_name_from_module(M,
ModuleName)),
ForeignImports),
Deps = AllDeps ++ ForeignDeps,
write_dll_dependencies_list(Globals,
referenced_dlls(ModuleName, Deps), Prefix, DepStream, !IO),
io.nl(DepStream, !IO)
;
( ForeignLang = lang_c
; ForeignLang = lang_java
; ForeignLang = lang_il
; ForeignLang = lang_erlang
)
)
;
% This foreign language doesn't generate an external file
% so there are no dependencies to generate.
true
).
% With `--use-subdirs', allow users to type `mmake module.c'
% rather than `mmake Mercury/cs/module.c'.
%
:- pred write_subdirs_shorthand_rule(globals::in, io.output_stream::in,
module_name::in, string::in, io::di, io::uo) is det.
write_subdirs_shorthand_rule(Globals, DepStream, ModuleName, Ext, !IO) :-
module_name_to_file_name_stem(ModuleName, ModuleStr),
module_name_to_file_name(Globals, ModuleName, Ext, do_not_create_dirs,
Target, !IO),
ShorthandTarget = ModuleStr ++ Ext,
io.write_string(DepStream, ".PHONY: ", !IO),
io.write_string(DepStream, ShorthandTarget, !IO),
io.nl(DepStream, !IO),
io.write_string(DepStream, ShorthandTarget, !IO),
io.write_string(DepStream, ": ", !IO),
io.write_string(DepStream, Target, !IO),
io.nl(DepStream, !IO).
%-----------------------------------------------------------------------------%
generate_dependencies_write_dv_file(Globals, SourceFileName, ModuleName,
DepsMap, !IO) :-
globals.lookup_bool_option(Globals, verbose, Verbose),
module_name_to_file_name(Globals, ModuleName, ".dv", do_create_dirs,
DvFileName, !IO),
maybe_write_string(Verbose, "% Creating auto-dependency file `", !IO),
maybe_write_string(Verbose, DvFileName, !IO),
maybe_write_string(Verbose, "'...\n", !IO),
io.open_output(DvFileName, DvResult, !IO),
(
DvResult = ok(DvStream),
generate_dv_file(Globals, SourceFileName, ModuleName, DepsMap,
DvStream, !IO),
io.close_output(DvStream, !IO),
maybe_write_string(Verbose, "% done.\n", !IO)
;
DvResult = error(IOError),
maybe_write_string(Verbose, " failed.\n", !IO),
maybe_flush_output(Verbose, !IO),
io.error_message(IOError, IOErrorMessage),
string.append_list(["error opening file `", DvFileName,
"' for output: ", IOErrorMessage], DvMessage),
report_error(DvMessage, !IO)
).
%-----------------------------------------------------------------------------%
generate_dependencies_write_dep_file(Globals, SourceFileName, ModuleName,
DepsMap, !IO) :-
globals.lookup_bool_option(Globals, verbose, Verbose),
module_name_to_file_name(Globals, ModuleName, ".dep", do_create_dirs,
DepFileName, !IO),
maybe_write_string(Verbose, "% Creating auto-dependency file `", !IO),
maybe_write_string(Verbose, DepFileName, !IO),
maybe_write_string(Verbose, "'...\n", !IO),
io.open_output(DepFileName, DepResult, !IO),
(
DepResult = ok(DepStream),
generate_dep_file(Globals, SourceFileName, ModuleName, DepsMap,
DepStream, !IO),
io.close_output(DepStream, !IO),
maybe_write_string(Verbose, "% done.\n", !IO)
;
DepResult = error(IOError),
maybe_write_string(Verbose, " failed.\n", !IO),
maybe_flush_output(Verbose, !IO),
io.error_message(IOError, IOErrorMessage),
string.append_list(["error opening file `", DepFileName,
"' for output: ", IOErrorMessage], DepMessage),
report_error(DepMessage, !IO)
).
%-----------------------------------------------------------------------------%
:- pred generate_dv_file(globals::in, file_name::in, module_name::in,
deps_map::in, io.output_stream::in, io::di, io::uo) is det.
generate_dv_file(Globals, SourceFileName, ModuleName, DepsMap, DepStream,
!IO) :-
io.write_string(DepStream,
"# Automatically generated dependency variables for module `", !IO),
ModuleNameString = sym_name_to_string(ModuleName),
io.write_string(DepStream, ModuleNameString, !IO),
io.write_string(DepStream, "'\n", !IO),
io.write_string(DepStream, "# generated from source file `", !IO),
io.write_string(DepStream, SourceFileName, !IO),
io.write_string(DepStream, "'\n", !IO),
library.version(Version),
io.write_string(DepStream,
"# Generated by the Mercury compiler, version ", !IO),
io.write_string(DepStream, Version, !IO),
io.write_string(DepStream, ".\n\n", !IO),
map.keys(DepsMap, Modules0),
select_ok_modules(Modules0, DepsMap, Modules1),
list.sort(compare_module_names, Modules1, Modules),
module_name_to_make_var_name(ModuleName, MakeVarName),
list.map(get_source_file(DepsMap), Modules, SourceFiles0),
list.sort_and_remove_dups(SourceFiles0, SourceFiles),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".ms =", !IO),
write_file_dependencies_list(SourceFiles, ".m", DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".errs =", !IO),
write_file_dependencies_list(SourceFiles, ".err", DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".mods =", !IO),
write_dependencies_list(Globals, Modules, "", DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
% The modules for which we need to generate .int0 files.
ModulesWithSubModules = list.filter(
(pred(Module::in) is semidet :-
map.lookup(DepsMap, Module, deps(_, ModuleImports)),
ModuleImports ^ mai_children = [_ | _]
), Modules),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".parent_mods =", !IO),
write_dependencies_list(Globals, ModulesWithSubModules, "", DepStream,
!IO),
io.write_string(DepStream, "\n", !IO),
globals.get_target(Globals, Target),
(
Target = target_il,
ForeignModulesAndExts = foreign_modules(Modules, DepsMap)
;
( Target = target_c
; Target = target_csharp
; Target = target_java
; Target = target_asm
; Target = target_x86_64
; Target = target_erlang
),
ForeignModulesAndExts = []
),
ForeignModules = assoc_list.keys(ForeignModulesAndExts),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".foreign =", !IO),
write_dependencies_list(Globals, ForeignModules, "", DepStream, !IO),
io.write_string(DepStream, "\n\n", !IO),
globals.lookup_bool_option(Globals, assume_gmake, Gmake),
(
Gmake = yes,
string.append(MakeVarName, ".mods", ModsVarName),
Basis = yes(ModsVarName - ""),
string.append(MakeVarName, ".foreign", ForeignVarName),
ForeignBasis = yes(ForeignVarName - ""),
string.append(MakeVarName, ".parent_mods", ParentModsVarName),
ParentBasis = yes(ParentModsVarName - "")
;
Gmake = no,
Basis = no,
ForeignBasis = no,
ParentBasis = no
),
get_extra_link_objects(Modules, DepsMap, Target, ExtraLinkObjs),
MakeFileName = (pred(M - E::in, F::out, IO0::di, IO::uo) is det :-
module_name_to_file_name(Globals, M, E, do_create_dirs, F0, IO0, IO),
F = "$(os_subdir)" ++ F0
),
list.map_foldl(MakeFileName, ForeignModulesAndExts, ForeignFileNames, !IO),
% .foreign_cs are the source files which have had foreign code placed
% in them.
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".foreign_cs = ", !IO),
write_file_dependencies_list(ForeignFileNames, "", DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
% The dlls that contain the foreign_code.
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".foreign_dlls = ", !IO),
write_compact_dependencies_list(Globals, ForeignModules,
"$(dlls_subdir)", ".dll", ForeignBasis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".init_cs = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(cs_subdir)", ".c", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".cs = $(", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".init_cs) ", !IO),
write_extra_link_dependencies_list(Globals, ExtraLinkObjs,
".c", DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".dlls = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(dlls_subdir)", ".dll", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_ss = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(ss_subdir)", ".s", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_pic_ss = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(pic_ss_subdir)", ".pic_s", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_s_dates = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(s_dates_subdir)", ".s_date", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_pic_s_dates = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(pic_s_dates_subdir)", ".pic_s_date", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_os = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(os_subdir)", ".$O", Basis, DepStream, !IO),
write_extra_link_dependencies_list(Globals, ExtraLinkObjs,
".$O", DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_pic_os = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(os_subdir)", ".$(EXT_FOR_PIC_OBJECTS)", Basis, DepStream, !IO),
write_extra_link_dependencies_list(Globals, ExtraLinkObjs,
".$(EXT_FOR_PIC_OBJECTS)", DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
IsNested = (pred(Mod::in) is semidet :-
get_submodule_kind(Mod, DepsMap) = nested_submodule
),
(
% For --target asm, we only generate separate object files
% for top-level modules and separate sub-modules, not for
% nested sub-modules.
Target = target_asm,
list.filter(IsNested, Modules, NestedModules, MainModules),
NestedModules = [_ | _]
->
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".ss = ", !IO),
write_dependencies_list(Globals, MainModules, ".s", DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".pic_ss = ", !IO),
write_dependencies_list(Globals, MainModules,
".pic_s", DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".s_dates = ", !IO),
write_dependencies_list(Globals, MainModules,
".s_date", DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".pic_s_dates = ", !IO),
write_dependencies_list(Globals, MainModules,
".pic_s_date", DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".os = ", !IO),
write_dependencies_list(Globals, MainModules, ".$O", DepStream, !IO),
write_extra_link_dependencies_list(Globals, ExtraLinkObjs,
".$O", DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".pic_os = ", !IO),
write_dependencies_list(Globals, MainModules,
".$(EXT_FOR_PIC_OBJECTS)", DepStream, !IO),
write_extra_link_dependencies_list(Globals, ExtraLinkObjs,
".$(EXT_FOR_PIC_OBJECTS)", DepStream, !IO),
io.write_string(DepStream, "\n", !IO)
;
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".ss = $(", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_ss)\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".pic_ss = $(", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_pic_ss)\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".s_dates = $(", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_s_dates)\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".pic_s_dates = $(", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_pic_s_dates)\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".os = $(", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_os)\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".pic_os = $(", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_pic_os)\n", !IO)
),
% $(foo.cs_or_ss) contains the names of the generated intermediate
% files between `.m' and `.o' files. This is used in foo.dep
% to make sure the intermediate files are generated before the
% object files, so that errors are reported as soon as possible.
%
% If TARGET_ASM=yes, we define $(foo.cs_or_ss) to be $(foo.ss),
% otherwise it is defined to be $(foo.cs).
io.write_strings(DepStream, [
"ifeq ($(TARGET_ASM),yes)\n",
MakeVarName, ".cs_or_ss =$(", MakeVarName, ".ss)\n",
"else\n",
MakeVarName, ".cs_or_ss =$(", MakeVarName, ".cs)\n",
"endif\n\n"
], !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".useds = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(useds_subdir)", ".used", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".ils = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(ils_subdir)", ".il", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".javas = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(javas_subdir)", ".java", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".classes = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(classes_subdir)", ".class", Basis, DepStream, !IO),
io.write_string(DepStream, " ", !IO),
% The Java compiler creates a .class file for each class
% within the original .java file. The filenames of all
% these can be matched with `module\$*.class', hence the
% "\\$$*.class" below.
% If no such files exist, Make will use the pattern verbatim,
% so we enclose the pattern in a `wildcard' function to prevent this.
% XXX This relies on GNU Make.
io.write_string(DepStream, "$(wildcard ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(classes_subdir)", "\\$$*.class", Basis, DepStream, !IO),
io.write_string(DepStream, ")\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".dirs = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(dirs_subdir)", ".dir", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".dir_os = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(dirs_subdir)", ".dir/*.$O", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".dates = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(dates_subdir)", ".date", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".date0s = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(date0s_subdir)", ".date0", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".date3s = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(date3s_subdir)", ".date3", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".optdates = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(optdates_subdir)", ".optdate", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".trans_opt_dates = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(trans_opt_dates_subdir)", ".trans_opt_date", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".c_dates = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(c_dates_subdir)", ".c_date", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".il_dates = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(il_dates_subdir)", ".il_date", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".java_dates = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(java_dates_subdir)", ".java_date", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".ds = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(ds_subdir)", ".d", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".module_deps = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(module_deps_subdir)", make_module_dep_file_extension,
Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".mihs = ", !IO),
globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
(
HighLevelCode = yes,
(
( Target = target_c
; Target = target_asm
),
% For the `--target c' MLDS back-end, we generate `.mih' files
% for every module. Likewise for the `--target asm' back-end.
% (For the `--target asm' back-end, we previously used to do
% that only for modules that contain C code, but this caused
% trouble when trying to interoperate between compiled with
% `--target c' and code compiled with `--target asm', so now we
% generate them unconditionally.)
write_compact_dependencies_list(Globals, Modules,
"$(mihs_subdir)", ".mih", Basis, DepStream, !IO)
;
% For the IL and Java targets, currently we don't generate
% `.mih' files at all; although perhaps we should...
( Target = target_il
; Target = target_csharp
; Target = target_java
; Target = target_erlang
)
;
Target = target_x86_64,
unexpected($module, $pred, "--highlevel-code with --target x86_64")
)
;
% For the LLDS back-end, we don't use `.mih' files at all
HighLevelCode = no
),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".mhs = ", !IO),
(
( Target = target_c
; Target = target_asm
; Target = target_x86_64
),
write_compact_dependencies_list(Globals, Modules, "", ".mh", Basis,
DepStream, !IO)
;
( Target = target_il
; Target = target_csharp
; Target = target_java
; Target = target_erlang
)
),
io.write_string(DepStream, "\n", !IO),
% The `<module>.all_mihs' variable is like `<module>.mihs' except
% that it contains header files for all the modules, regardless
% of the grade or --target option. It is used by the rule for
% `mmake realclean', which should remove anything that could have
% been automatically generated, even if the grade or --target option
% has changed.
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_mihs = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(mihs_subdir)", ".mih", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
% The `<module>.all_mhs' variable is like `<module>.mhs' except
% that it contains header files for all the modules, as for
% `<module>.all_mihs' above.
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_mhs = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"", ".mh", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".ints = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(ints_subdir)", ".int", Basis, DepStream, !IO),
write_compact_dependencies_separator(Basis, DepStream, !IO),
write_compact_dependencies_list(Globals, Modules,
"$(int2s_subdir)", ".int2", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
% `.int0' files are only generated for modules with sub-modules.
% XXX ... or at least they should be. Currently we end up generating
% .int0 files for nested submodules that don't have any children.
% (We do the correct thing for separate sub-modules.)
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".int0s = ", !IO),
write_compact_dependencies_list(Globals, ModulesWithSubModules,
"$(int0s_subdir)", ".int0", ParentBasis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
% XXX The `<module>.all_int0s' variables is like `<module>.int0s' except
% that it contains .int0 files for all modules, regardless of whether
% they should have been created or not. It is used by the rule for
% `mmake realclean' to ensure that we clean up all the .int0 files,
% including the ones that were accidently created by the bug described
% above.
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".all_int0s = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(int0s_subdir)", ".int0", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".int3s = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(int3s_subdir)", ".int3", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".opts = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(opts_subdir)", ".opt", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".trans_opts = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(trans_opts_subdir)", ".trans_opt", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".analysiss = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(analysiss_subdir)", ".analysis", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".requests = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(requests_subdir)", ".request", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".imdgs = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"$(imdgs_subdir)", ".imdg", Basis, DepStream, !IO),
io.write_string(DepStream, "\n", !IO),
io.write_string(DepStream, MakeVarName, !IO),
io.write_string(DepStream, ".profs = ", !IO),
write_compact_dependencies_list(Globals, Modules,
"", ".prof", Basis, DepStream, !IO),
io.write_string(DepStream, "\n\n", !IO).
%-----------------------------------------------------------------------------%
:- pred select_ok_modules(list(module_name)::in, deps_map::in,
list(module_name)::out) is det.
select_ok_modules([], _, []).
select_ok_modules([Module | Modules0], DepsMap, Modules) :-
select_ok_modules(Modules0, DepsMap, ModulesTail),
map.lookup(DepsMap, Module, deps(_, ModuleImports)),
module_and_imports_get_results(ModuleImports, _Items, _Specs, Error),
(
Error = fatal_module_errors,
Modules = ModulesTail
;
( Error = no_module_errors
; Error = some_module_errors
),
Modules = [Module | ModulesTail]
).
%-----------------------------------------------------------------------------%
% Find out which modules will generate as external foreign language files.
% We return the module names and file extensions.
%
:- func foreign_modules(list(module_name), deps_map)
= assoc_list(module_name, string).
foreign_modules(Modules, DepsMap) = ForeignModules :-
P = (pred(M::in, FMs::out) is semidet :-
module_has_foreign(DepsMap, M, LangList),
FMs = list.filter_map((func(L) = (NewM - Ext) is semidet :-
NewM = foreign_language_module_name(M, L),
Ext = foreign_language_file_extension(L)
), LangList
)
),
list.filter_map(P, Modules, ForeignModulesList),
ForeignModules = list.condense(ForeignModulesList).
% Succeed iff we need to generate a foreign language output file
% for the specified module.
%
:- pred module_has_foreign(deps_map::in, module_name::in,
list(foreign_language)::out) is semidet.
module_has_foreign(DepsMap, Module, LangList) :-
map.lookup(DepsMap, Module, deps(_, ModuleImports)),
ModuleImports ^ mai_has_foreign_code = contains_foreign_code(Langs),
LangList = set.to_sorted_list(Langs).
%-----------------------------------------------------------------------------%
% get_extra_link_objects(Modules, DepsMap, Target, ExtraLinkObjs):
%
% Find any extra .$O files that should be linked into the executable.
% These include fact table object files and object files for foreign
% code that can't be generated inline for this target.
%
:- pred get_extra_link_objects(list(module_name)::in, deps_map::in,
compilation_target::in, assoc_list(file_name, module_name)::out) is det.
get_extra_link_objects(Modules, DepsMap, Target, ExtraLinkObjs) :-
get_extra_link_objects_2(Modules, DepsMap, Target, [], ExtraLinkObjs0),
list.reverse(ExtraLinkObjs0, ExtraLinkObjs).
:- pred get_extra_link_objects_2(list(module_name)::in, deps_map::in,
compilation_target::in,
assoc_list(file_name, module_name)::in,
assoc_list(file_name, module_name)::out) is det.
get_extra_link_objects_2([], _DepsMap, _Target, !ExtraLinkObjs).
get_extra_link_objects_2([Module | Modules], DepsMap, Target,
!ExtraLinkObjs) :-
map.lookup(DepsMap, Module, deps(_, ModuleImports)),
% Handle object files for fact tables.
FactDeps = ModuleImports ^ mai_fact_table_deps,
list.length(FactDeps, NumFactDeps),
list.duplicate(NumFactDeps, Module, ModuleList),
assoc_list.from_corresponding_lists(FactDeps, ModuleList, FactTableObjs),
% Handle object files for foreign code.
% XXX Currently we only support `C' foreign code.
(
Target = target_asm,
ModuleImports ^ mai_has_foreign_code = contains_foreign_code(Langs),
set.member(lang_c, Langs)
->
FileName = sym_name_to_string(Module),
NewLinkObjs = [(FileName ++ "__c_code") - Module | FactTableObjs]
;
NewLinkObjs = FactTableObjs
),
list.append(NewLinkObjs, !ExtraLinkObjs),
get_extra_link_objects_2(Modules, DepsMap, Target, !ExtraLinkObjs).
%-----------------------------------------------------------------------------%
:- pred generate_dep_file(globals::in, file_name::in, module_name::in,
deps_map::in, io.output_stream::in, io::di, io::uo) is det.
generate_dep_file(Globals, SourceFileName, ModuleName, DepsMap, DepStream,
!IO) :-
io.write_string(DepStream,
"# Automatically generated dependencies for module `", !IO),
ModuleNameString = sym_name_to_string(ModuleName),
io.write_string(DepStream, ModuleNameString, !IO),
io.write_string(DepStream, "'\n", !IO),
io.write_string(DepStream,
"# generated from source file `", !IO),
io.write_string(DepStream, SourceFileName, !IO),
io.write_string(DepStream, "'\n", !IO),
library.version(Version),
io.write_string(DepStream,
"# Generated by the Mercury compiler, version ", !IO),
io.write_string(DepStream, Version, !IO),
io.write_string(DepStream, ".\n\n", !IO),
module_name_to_make_var_name(ModuleName, MakeVarName),
module_name_to_file_name(Globals, ModuleName, ".init",
do_create_dirs, InitFileName, !IO),
module_name_to_file_name(Globals, ModuleName, "_init.c",
do_create_dirs, InitCFileName, !IO),
module_name_to_file_name(Globals, ModuleName, "_init.s",
do_not_create_dirs, InitAsmFileName, !IO),
module_name_to_file_name(Globals, ModuleName, "_init.$O",
do_create_dirs, InitObjFileName, !IO),
module_name_to_file_name(Globals, ModuleName, "_init.pic_o",
do_create_dirs, InitPicObjFileName, !IO),
globals.lookup_bool_option(Globals, intermodule_optimization, Intermod),
globals.lookup_bool_option(Globals, transitive_optimization, TransOpt),
globals.lookup_bool_option(Globals, generate_mmc_make_module_dependencies,
MmcMakeDeps),
generate_dep_file_exec_library_targets(Globals, DepStream, ModuleName,
MakeVarName, InitFileName, InitObjFileName,
Intermod, TransOpt, MmcMakeDeps,
MaybeOptsVar, MaybeTransOptsVar, MaybeModuleDepsVar,
ExeFileName, JarFileName, LibFileName, SharedLibFileName, !IO),
generate_dep_file_init_targets(Globals, DepStream, ModuleName,
MakeVarName, InitCFileName, InitFileName, DepFileName, DvFileName,
!IO),
generate_dep_file_install_targets(Globals, DepStream, ModuleName, DepsMap,
MakeVarName, MmcMakeDeps, Intermod, TransOpt,
MaybeModuleDepsVar, MaybeOptsVar, MaybeTransOptsVar, !IO),
generate_dep_file_collective_targets(Globals, DepStream, ModuleName,
MakeVarName, !IO),
generate_dep_file_clean_targets(Globals, DepStream, ModuleName,
MakeVarName, ExeFileName, InitCFileName, InitAsmFileName,
InitObjFileName, InitPicObjFileName, InitFileName,
LibFileName, SharedLibFileName, JarFileName, DepFileName, DvFileName,
!IO).
:- pred generate_dep_file_exec_library_targets(globals::in,
io.output_stream::in, module_name::in, string::in, string::in, string::in,
bool::in, bool::in, bool::in, string::out, string::out, string::out,
string::out, string::out, string::out, string::out, io::di, io::uo) is det.
generate_dep_file_exec_library_targets(Globals, DepStream, ModuleName,
MakeVarName, InitFileName, InitObjFileName,
Intermod, TransOpt, MmcMakeDeps,
MaybeOptsVar, MaybeTransOptsVar, MaybeModuleDepsVar,
ExeFileName, JarFileName, LibFileName, SharedLibFileName, !IO) :-
% Note we have to do some ``interesting'' hacks to get
% `$(ALL_MLLIBS_DEP)' to work in the dependency list
% (and not complain about undefined variables).
% These hacks rely on features of GNU Make, so should not be used
% if we cannot assume we are using GNU Make.
globals.lookup_bool_option(Globals, assume_gmake, Gmake),
(
Gmake = yes,
append_list(["\\\n\t\t$(foreach @,", MakeVarName,
",$(ALL_MLLIBS_DEP))"],
All_MLLibsDepString),
append_list(["\\\n\t\t$(foreach @,", MakeVarName,
",$(ALL_MLOBJS))"],
All_MLObjsString),
append_list([
"\\\n\t\t$(patsubst %.o,%.$(EXT_FOR_PIC_OBJECTS),$(foreach @,",
MakeVarName, ",$(ALL_MLOBJS)))"],
All_MLPicObjsString)
;
Gmake = no,
All_MLLibsDepString = "$(ALL_MLLIBS_DEP)",
All_MLObjsString = "$(ALL_MLOBJS)",
All_MLPicObjsString = "$(ALL_MLPICOBJS)"
),
% When compiling to C, we want to include $(foo.cs) first in
% the dependency list, before $(foo.os).
% This is not strictly necessary, since the .$O files themselves depend
% on the .c files, but want to do it to ensure that Make will try to
% create all the C files first, thus detecting errors early,
% rather than first spending time compiling C files to .$O,
% which could be a waste of time if the program contains errors.
%
% When compiling to assembler, we want to do the same kind of thing,
% for the same reason, but with the `.s' files rather than the `.c' files.
module_name_to_file_name(Globals, ModuleName, "",
do_not_create_dirs, ExeFileName, !IO),
IfIL = ["ifeq ($(findstring il,$(GRADE)),il)\n"],
ILMainRule = [ExeFileName, " : ", ExeFileName, ".exe\n",
ExeFileName, ".exe : ", "$(", MakeVarName, ".dlls) ",
"$(", MakeVarName, ".foreign_dlls)\n"],
IfJava2 = [" ifeq ($(findstring java,$(GRADE)),java)\n"],
JavaMainRule = [ExeFileName, " : $(", MakeVarName, ".classes)\n"],
Else = ["else\n"],
Else2 = [" else\n"],
EndIf = ["endif\n"],
EndIf2 = [" endif\n"],
% XXX The output here is GNU Make-specific.
io.write_strings(DepStream, [
"ifneq ($(EXT_FOR_EXE),)\n",
".PHONY : ", ExeFileName, "\n",
ExeFileName, " : ", ExeFileName, "$(EXT_FOR_EXE)\n",
"endif\n"
], !IO),
MainRule =
[ExeFileName, "$(EXT_FOR_EXE) : $(", MakeVarName, ".cs_or_ss) ",
"$(", MakeVarName, ".os) ", InitObjFileName, " ",
All_MLObjsString, " ", All_MLLibsDepString, "\n",
"\t$(ML) $(ALL_GRADEFLAGS) $(ALL_MLFLAGS) -- $(ALL_LDFLAGS) ",
"$(EXEFILE_OPT)", ExeFileName, "$(EXT_FOR_EXE) ", InitObjFileName, " \\\n",
"\t\t$(", MakeVarName, ".os) ", All_MLObjsString, " $(ALL_MLLIBS)\n"],
globals.get_target(Globals, Target),
(
Gmake = yes,
Rules = IfIL ++ ILMainRule ++ Else ++
IfJava2 ++ JavaMainRule ++ Else2 ++
MainRule ++ EndIf2 ++ EndIf
;
Gmake = no,
(
Target = target_il,
Rules = ILMainRule
;
Target = target_csharp,
% XXX not yet
Rules = []
;
Target = target_java,
Rules = JavaMainRule
;
Target = target_erlang,
% XXX not yet
Rules = []
;
( Target = target_c
; Target = target_asm
; Target = target_x86_64 % XXX this is only provisional.
),
Rules = MainRule
)
),
io.write_strings(DepStream, Rules, !IO),
(
Intermod = yes,
MaybeOptsVar = "$(" ++ MakeVarName ++ ".opts) "
;
Intermod = no,
MaybeOptsVar = ""
),
(
TransOpt = yes,
MaybeTransOptsVar = "$(" ++ MakeVarName ++ ".trans_opts) "
;
TransOpt = no,
MaybeTransOptsVar = ""
),
(
MmcMakeDeps = yes,
MaybeModuleDepsVar = "$(" ++ MakeVarName ++ ".module_deps) "
;
MmcMakeDeps = no,
MaybeModuleDepsVar = ""
),
module_name_to_lib_file_name(Globals, "lib", ModuleName, "",
do_not_create_dirs, LibTargetName, !IO),
module_name_to_lib_file_name(Globals, "lib", ModuleName, ".$A",
do_create_dirs, LibFileName, !IO),
module_name_to_lib_file_name(Globals, "lib", ModuleName,
".$(EXT_FOR_SHARED_LIB)", do_create_dirs, SharedLibFileName, !IO),
module_name_to_lib_file_name(Globals, "lib", ModuleName,
".$(EXT_FOR_SHARED_LIB)", do_not_create_dirs, MaybeSharedLibFileName,
!IO),
module_name_to_file_name(Globals, ModuleName, ".jar",
do_not_create_dirs, JarFileName, !IO),
% Set up the installed name for shared libraries.
globals.lookup_bool_option(Globals, shlib_linker_use_install_name,
UseInstallName),
(
UseInstallName = yes,
get_install_name_option(Globals, SharedLibFileName, InstallNameOpt)
;
UseInstallName = no,
InstallNameOpt = ""
),
AllInts = [
"$(", MakeVarName, ".ints) ",
"$(", MakeVarName, ".int3s) ",
MaybeOptsVar, MaybeTransOptsVar,
InitFileName, "\n\n"
],
ILLibRule = [
LibTargetName, " : ", "$(", MakeVarName, ".dlls) ",
"$(", MakeVarName, ".foreign_dlls) \\\n\t\t"
| AllInts
],
JavaLibRule = [
LibTargetName, " : ", JarFileName, " \\\n\t\t"
| AllInts
],
LibRule = [
LibTargetName, " : ", LibFileName, " ",
MaybeSharedLibFileName, " \\\n\t\t"
| AllInts
],
(
Gmake = yes,
LibRules = IfIL ++ ILLibRule ++ Else ++
IfJava2 ++ JavaLibRule ++ Else2 ++
LibRule ++ EndIf2 ++ EndIf
;
Gmake = no,
(
Target = target_il,
LibRules = ILLibRule
;
Target = target_csharp,
% XXX not done yet
LibRules = []
;
Target = target_java,
LibRules = JavaLibRule
;
Target = target_erlang,
% XXX not done yet
LibRules = []
;
( Target = target_c
; Target = target_asm
; Target = target_x86_64 % XXX This is only provisional.
),
LibRules = LibRule
)
),
io.write_strings(DepStream, [
".PHONY : ", LibTargetName, "\n" |
LibRules
], !IO),
io.write_strings(DepStream, [
"ifneq ($(EXT_FOR_SHARED_LIB),$A)\n",
SharedLibFileName, " : $(", MakeVarName, ".cs_or_ss) ",
"$(", MakeVarName, ".pic_os) ",
All_MLPicObjsString, " ", All_MLLibsDepString, "\n",
"\t$(ML) --make-shared-lib $(ALL_GRADEFLAGS) $(ALL_MLFLAGS) ",
"-- ", InstallNameOpt, " $(ALL_LD_LIBFLAGS) -o ",
SharedLibFileName, " \\\n",
"\t\t$(", MakeVarName, ".pic_os) ", All_MLPicObjsString,
" $(ALL_MLLIBS)\n",
"endif\n\n"
], !IO),
io.write_strings(DepStream, [
LibFileName, " : $(", MakeVarName, ".cs_or_ss) ",
"$(", MakeVarName, ".os) ", All_MLObjsString, "\n",
"\trm -f ", LibFileName, "\n",
"\t$(AR) $(ALL_ARFLAGS) $(AR_LIBFILE_OPT)", LibFileName, " ",
"$(", MakeVarName, ".os) ", All_MLObjsString, "\n",
"\t$(RANLIB) $(ALL_RANLIBFLAGS) ", LibFileName, "\n\n"
], !IO),
ClassFiles = "$(" ++ MakeVarName ++ ".classes)",
list_class_files_for_jar_mmake(Globals, ClassFiles, ListClassFiles),
io.write_strings(DepStream, [
JarFileName, " : ", "$(", MakeVarName, ".classes)\n",
"\t$(JAR) $(JAR_CREATE_FLAGS) ", JarFileName, " ",
ListClassFiles, "\n\n"
], !IO).
:- pred generate_dep_file_init_targets(globals::in, io.output_stream::in,
module_name::in, string::in, string::in, string::in,
string::out, string::out, io::di, io::uo) is det.
generate_dep_file_init_targets(Globals, DepStream, ModuleName,
MakeVarName, InitCFileName, InitFileName, DepFileName, DvFileName,
!IO) :-
module_name_to_file_name(Globals, ModuleName, ".dep",
do_not_create_dirs, DepFileName, !IO),
module_name_to_file_name(Globals, ModuleName, ".dv",
do_not_create_dirs, DvFileName, !IO),
io.write_strings(DepStream, [
InitFileName, " : ", DepFileName, " $(", MakeVarName, ".cs)\n",
"\techo > ", InitFileName, "\n"
], !IO),
io.write_strings(DepStream, [
"\t$(MKLIBINIT) ", "$(", MakeVarName, ".cs)", " >> ",
InitFileName, "\n"
], !IO),
% $(EXTRA_INIT_COMMAND) should expand to a command to
% generate extra entries in the `.init' file for a library.
% It may expand to the empty string.
io.write_string(DepStream, "\t$(EXTRA_INIT_COMMAND) >> ", !IO),
io.write_string(DepStream, InitFileName, !IO),
io.write_string(DepStream, "\n", !IO),
% The `force-module_init' dependency forces the commands for
% the `module_init.c' rule to be run every time the rule
% is considered.
ModuleFileName = sym_name_to_string(ModuleName),
ForceC2InitTarget = "force-" ++ ModuleFileName ++ "_init",
TmpInitCFileName = InitCFileName ++ ".tmp",
io.write_strings(DepStream, [
ForceC2InitTarget, " :\n\n",
InitCFileName, " : ", ForceC2InitTarget, " $(", MakeVarName, ".cs)\n",
"\t@$(C2INIT) $(ALL_GRADEFLAGS) $(ALL_C2INITFLAGS) ",
"--init-c-file ", TmpInitCFileName,
" $(", MakeVarName, ".init_cs) $(ALL_C2INITARGS)\n",
"\t@mercury_update_interface ", InitCFileName, "\n\n"
], !IO).
:- pred generate_dep_file_install_targets(globals::in, io.output_stream::in,
module_name::in, deps_map::in, string::in, bool::in, bool::in, bool::in,
string::in, string::in, string::in, io::di, io::uo) is det.
generate_dep_file_install_targets(Globals, DepStream, ModuleName, DepsMap,
MakeVarName, MmcMakeDeps, Intermod, TransOpt,
MaybeModuleDepsVar, MaybeOptsVar, MaybeTransOptsVar, !IO) :-
% XXX Note that we install the `.opt' and `.trans_opt' files
% in two places: in the `lib/$(GRADE)/opts' directory, so
% that mmc will find them, and also in the `ints' directory,
% so that Mmake will find them. That's not ideal, but it works.
module_name_to_lib_file_name(Globals, "lib", ModuleName, ".install_ints",
do_not_create_dirs, LibInstallIntsTargetName, !IO),
(
Intermod = yes,
OptStr = " opt"
;
Intermod = no,
OptStr = ""
),
(
Intermod = yes,
map.member(DepsMap, _, deps(_, Imports)),
Imports ^ mai_children = [_ | _]
->
% The `.int0' files only need to be installed with
% `--intermodule-optimization'.
Int0Str = " int0",
MaybeInt0sVar = "$(" ++ MakeVarName ++ ".int0s) "
;
Int0Str = "",
MaybeInt0sVar = ""
),
(
TransOpt = yes,
TransOptStr = " trans_opt"
;
TransOpt = no,
TransOptStr = ""
),
(
MmcMakeDeps = yes,
DepStr = " module_dep"
;
MmcMakeDeps = no,
DepStr = ""
),
io.write_strings(DepStream, [
".PHONY : ", LibInstallIntsTargetName, "\n",
LibInstallIntsTargetName, " : $(", MakeVarName, ".ints) $(",
MakeVarName, ".int3s) ", MaybeInt0sVar, MaybeOptsVar,
MaybeTransOptsVar, MaybeModuleDepsVar,
" install_lib_dirs\n",
"\tfiles=""$(", MakeVarName, ".ints) $(", MakeVarName,
".int3s) ", MaybeInt0sVar, MaybeOptsVar,
MaybeTransOptsVar, MaybeModuleDepsVar, """; \\\n",
"\tfor file in $$files; do \\\n",
"\t\ttarget=""$(INSTALL_INT_DIR)/`basename $$file`""; \\\n",
"\t\tif cmp -s ""$$file"" ""$$target""; then \\\n",
"\t\t\techo \"$$target unchanged\"; \\\n",
"\t\telse \\\n",
"\t\t\techo \"installing $$target\"; \\\n",
"\t\t\t$(INSTALL) ""$$file"" ""$$target""; \\\n",
"\t\tfi; \\\n",
"\tdone\n",
"\t# The following is needed to support the `--use-subdirs' option\n",
"\t# We try using `$(LN_S)', but if that fails, then we just use\n",
"\t# `$(INSTALL)'.\n",
"\tfor ext in int int2 int3",
Int0Str, OptStr, TransOptStr, DepStr,
"; do \\\n",
"\t\tdir=""$(INSTALL_INT_DIR)/Mercury/$${ext}s""; \\\n",
"\t\trm -rf ""$$dir""; \\\n",
"\t\t$(LN_S) .. ""$$dir"" || { \\\n",
"\t\t\t{ [ -d ""$$dir"" ] || \\\n",
"\t\t\t$(INSTALL_MKDIR) ""$$dir""; } && \\\n",
"\t\t\t$(INSTALL) ""$(INSTALL_INT_DIR)""/*.$$ext ""$$dir""; \\\n",
"\t\t} || exit 1; \\\n",
"\tdone\n\n"
], !IO),
module_name_to_lib_file_name(Globals, "lib", ModuleName, ".install_opts",
do_not_create_dirs, LibInstallOptsTargetName, !IO),
io.write_strings(DepStream,
[".PHONY : ", LibInstallOptsTargetName, "\n",
LibInstallOptsTargetName, " : "], !IO),
(
Intermod = no,
TransOpt = no
->
io.write_string(DepStream, "\n\t@:\n\n", !IO)
;
io.write_strings(DepStream, [
MaybeOptsVar, MaybeTransOptsVar, "install_grade_dirs\n",
"\tfiles=""", MaybeOptsVar, MaybeTransOptsVar, """; \\\n",
"\tfor file in $$files; do \\\n",
"\t\ttarget=""$(INSTALL_GRADE_INT_DIR)/`basename $$file`"";\\\n",
"\t\tif cmp -s ""$$file"" ""$$target""; then \\\n",
"\t\t\techo \"$$target unchanged\"; \\\n",
"\t\telse \\\n",
"\t\t\techo \"installing $$target\"; \\\n",
"\t\t\t$(INSTALL) ""$$file"" ""$$target""; \\\n",
"\t\tfi; \\\n",
"\tdone\n",
"\t# The following is needed to support the",
" `--use-subdirs' option\n",
"\t# We try using `$(LN_S)', but if that fails,",
" then we just use\n",
"\t# `$(INSTALL)'.\n",
"\tfor ext in ", OptStr, TransOptStr, "; do \\\n",
"\t\tdir=""$(INSTALL_GRADE_INT_DIR)/Mercury/$${ext}s""; \\\n",
"\t\trm -rf ""$$dir""; \\\n",
"\t\t$(LN_S) .. ""$$dir"" || { \\\n",
"\t\t\t{ [ -d ""$$dir"" ] || \\\n",
"\t\t\t\t$(INSTALL_MKDIR) ""$$dir""; } && \\\n",
"\t\t\t$(INSTALL) ""$(INSTALL_GRADE_INT_DIR)""/*.$$ext \\\n",
"\t\t\t\t""$$dir""; \\\n",
"\t\t} || exit 1; \\\n",
"\tdone\n\n"
], !IO)
),
% XXX Note that we install the header files in two places:
% in the `lib/inc' or `lib/$(GRADE)/$(FULLARCH)/inc' directory,
% so that the C compiler will find them, and also in the `ints' directory,
% so that Mmake will find them. That's not ideal, but it works.
%
% (A better fix would be to change the VPATH setting in
% scripts/Mmake.vars.in so that Mmake also searches the
% `lib/$(GRADE)/$(FULLARCH)/inc' directory, but doing that properly
% is non-trivial.)
module_name_to_lib_file_name(Globals, "lib", ModuleName, ".install_hdrs",
do_not_create_dirs, LibInstallHdrsTargetName, !IO),
io.write_strings(DepStream, [
".PHONY : ", LibInstallHdrsTargetName, "\n",
LibInstallHdrsTargetName, " : ",
"$(", MakeVarName, ".mhs) ",
"install_lib_dirs\n",
"ifeq ($(", MakeVarName, ".mhs),)\n",
"\t@:\n",
"else\n",
"\tfor hdr in $(", MakeVarName, ".mhs); do \\\n",
"\t\t$(INSTALL) $$hdr $(INSTALL_INT_DIR); \\\n",
"\t\t$(INSTALL) $$hdr $(INSTALL_INC_DIR); \\\n",
"\tdone\n",
"endif\n\n"], !IO),
module_name_to_lib_file_name(Globals, "lib", ModuleName,
".install_grade_hdrs", do_not_create_dirs,
LibInstallGradeHdrsTargetName, !IO),
io.write_strings(DepStream, [
".PHONY : ", LibInstallGradeHdrsTargetName, "\n",
LibInstallGradeHdrsTargetName, " : ",
"$(", MakeVarName, ".mihs) ",
"install_grade_dirs\n",
"ifeq ($(", MakeVarName, ".mihs),)\n",
"\t@:\n",
"else\n",
"\tfor hdr in $(", MakeVarName, ".mihs); do \\\n",
"\t\t$(INSTALL) $$hdr $(INSTALL_INT_DIR); \\\n",
"\t\t$(INSTALL) $$hdr $(INSTALL_GRADE_INC_DIR); \\\n",
"\tdone\n",
"\t# The following is needed to support the `--use-subdirs' option\n",
"\t# We try using `$(LN_S)', but if that fails, then we just use\n",
"\t# `$(INSTALL)'.\n",
"\trm -rf $(INSTALL_GRADE_INC_SUBDIR)\n",
"\t$(LN_S) .. $(INSTALL_GRADE_INC_SUBDIR) || { \\\n",
"\t\t{ [ -d $(INSTALL_GRADE_INC_SUBDIR) ] || \\\n",
"\t\t\t$(INSTALL_MKDIR) $(INSTALL_GRADE_INC_SUBDIR); \\\n",
"\t\t} && \\\n",
"\t\t$(INSTALL) $(INSTALL_GRADE_INC_DIR)/*.mih \\\n",
"\t\t\t$(INSTALL_GRADE_INC_SUBDIR); \\\n",
"\t} || exit 1\n",
"\trm -rf $(INSTALL_INT_DIR)/Mercury/mihs\n",
"\t$(LN_S) .. $(INSTALL_INT_DIR)/Mercury/mihs || { \\\n",
"\t\t{ [ -d $(INSTALL_INT_DIR)/Mercury/mihs ] || \\\n",
"\t\t\t$(INSTALL_MKDIR) \\\n",
"\t\t\t$(INSTALL_INT_DIR)/Mercury/mihs; \\\n",
"\t\t} && \\\n",
"\t\t$(INSTALL) $(INSTALL_GRADE_INC_DIR)/*.mih \\\n",
"\t\t\t$(INSTALL_INT_DIR); \\\n",
"\t} || exit 1\n",
"endif\n\n"], !IO).
:- pred generate_dep_file_collective_targets(globals::in, io.output_stream::in,
module_name::in, string::in, io::di, io::uo) is det.
generate_dep_file_collective_targets(Globals, DepStream, ModuleName,
MakeVarName, !IO) :-
% We need to explicitly mention $(foo.pic_ss) somewhere in the Mmakefile,
% otherwise it won't build properly with --target asm: GNU Make's pattern
% rule algorithm will try to use the .m -> .c_date -> .c -> .pic_o rule
% chain rather than the .m -> .pic_s_date -> .pic_s -> .pic_o chain.
% So don't remove the pic_ss target here.
list.foldl(
generate_dep_file_collective_target(Globals, DepStream, ModuleName,
MakeVarName),
[
".check" - ".errs",
".ints" - ".dates",
".int3s" - ".date3s",
".opts" - ".optdates",
".trans_opts" - ".trans_opt_dates",
".ss" - ".ss",
".pic_ss" - ".pic_ss",
".ils" - ".ils",
".javas" - ".javas",
".classes" - ".classes",
".all_ints" - ".dates",
".all_int3s" - ".date3s",
".all_opts" - ".optdates",
".all_trans_opts" - ".trans_opt_dates",
".all_ss" - ".ss",
".all_pic_ss" - ".pic_ss"
], !IO).
:- pred generate_dep_file_collective_target(globals::in, io.output_stream::in,
module_name::in, string::in, pair(string, string)::in,
io::di, io::uo) is det.
generate_dep_file_collective_target(Globals, DepStream, ModuleName,
MakeVarName, Extension - VarExtension, !IO) :-
module_name_to_file_name(Globals, ModuleName, Extension,
do_not_create_dirs, TargetName, !IO),
io.write_strings(DepStream, [
".PHONY : ", TargetName, "\n",
TargetName, " : $(", MakeVarName, VarExtension, ")\n\n"
], !IO).
:- pred generate_dep_file_clean_targets(globals::in, io.output_stream::in,
module_name::in, string::in, string::in, string::in, string::in,
string::in, string::in, string::in, string::in, string::in, string::in,
string::in, string::in, io::di, io::uo) is det.
generate_dep_file_clean_targets(Globals, DepStream, ModuleName, MakeVarName,
ExeFileName, InitCFileName, InitAsmFileName,
InitObjFileName, InitPicObjFileName, InitFileName, LibFileName,
SharedLibFileName, JarFileName, DepFileName, DvFileName, !IO) :-
% If you change the clean targets below, please also update the
% documentation in doc/user_guide.texi.
%
% XXX The use of xargs in the clean targets doesn't handle special
% characters in the file names correctly. This is currently not a problem
% in practice as we never generate names containing special characters,
% any fix for this problem will also require a fix in `mmake.in'.
module_name_to_file_name(Globals, ModuleName, ".clean",
do_not_create_dirs, CleanTargetName, !IO),
io.write_strings(DepStream, [
"clean_local : ", CleanTargetName, "\n"
], !IO),
io.write_strings(DepStream, [
".PHONY : ", CleanTargetName, "\n",
CleanTargetName, " :\n",
"\t-echo $(", MakeVarName, ".dirs) | xargs rm -rf \n",
"\t-echo $(", MakeVarName, ".cs) ", InitCFileName,
" | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".mihs) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".all_ss) ", InitAsmFileName,
" | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".all_pic_ss) ",
InitAsmFileName, " | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".all_os) ", InitObjFileName,
" | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".all_pic_os) ",
InitPicObjFileName, " | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".c_dates) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".il_dates) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".java_dates) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".all_s_dates) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".all_pic_s_dates) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".useds) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".ils) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".javas) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".profs) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".errs) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".foreign_cs) | xargs rm -f\n",
"\n"
], !IO),
module_name_to_file_name(Globals, ModuleName, ".realclean",
do_not_create_dirs, RealCleanTargetName, !IO),
io.write_strings(DepStream, [
"realclean_local : ", RealCleanTargetName, "\n"
], !IO),
io.write_strings(DepStream, [
".PHONY : ", RealCleanTargetName, "\n",
RealCleanTargetName, " : ", CleanTargetName, "\n",
"\t-echo $(", MakeVarName, ".dates) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".date0s) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".date3s) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".optdates) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".trans_opt_dates) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".ints) | xargs rm -f\n",
% XXX This should acutally be .int0s but we need to make sure that
% we delete any spurious .int0 files created for nested sub-modules.
% For further details see the XXX comments above.
"\t-echo $(", MakeVarName, ".all_int0s) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".int3s) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".opts) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".trans_opts) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".analysiss) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".requests) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".imdgs) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".ds) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".module_deps) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".all_mhs) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".all_mihs) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".dlls) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".foreign_dlls) | xargs rm -f\n",
"\t-echo $(", MakeVarName, ".classes) | xargs rm -f\n"
], !IO),
io.write_strings(DepStream, [
"\t-rm -f ",
ExeFileName, "$(EXT_FOR_EXE) ",
InitFileName, " ",
LibFileName, " ",
SharedLibFileName, " ",
JarFileName, " ",
DepFileName, " ",
DvFileName, "\n\n"
], !IO).
%-----------------------------------------------------------------------------%
:- pred get_source_file(deps_map::in, module_name::in, file_name::out) is det.
get_source_file(DepsMap, ModuleName, FileName) :-
map.lookup(DepsMap, ModuleName, Deps),
Deps = deps(_, ModuleImports),
module_and_imports_get_source_file_name(ModuleImports, SourceFileName),
( string.remove_suffix(SourceFileName, ".m", SourceFileBase) ->
FileName = SourceFileBase
;
unexpected($module, $pred, "source file name doesn't end in `.m'")
).
%-----------------------------------------------------------------------------%
referenced_dlls(Module, DepModules0) = Modules :-
DepModules = [Module | DepModules0],
% If we are not compiling a module in the mercury std library then
% replace all the std library dlls with one reference to mercury.dll.
( mercury_std_library_module_name(Module) ->
% In the standard library we need to add the runtime dlls.
Modules = list.remove_dups(
[unqualified("mercury_dotnet"), unqualified("mercury_il")
| DepModules])
;
F = (func(M) =
( mercury_std_library_module_name(M) ->
unqualified("mercury")
;
% A sub module is located in the top level assembly.
unqualified(outermost_qualifier(M))
)
),
Modules = list.remove_dups(list.map(F, DepModules))
).
%-----------------------------------------------------------------------------%
% get_both_opt_deps(Globals, BuildOptFiles, Deps, IntermodDirs,
% OptDeps, TransOptDeps, !IO):
%
% For each dependency, search intermod_directories for a .m file.
% If it exists, add it to both output lists. Otherwise, if a .opt
% file exists, add it to the OptDeps list, and if a .trans_opt
% file exists, add it to the TransOptDeps list.
% If --use-opt-files is set, don't look for `.m' files, since we are
% not building `.opt' files, only using those which are available.
% XXX This won't find nested sub-modules.
% XXX Use `mmc --make' if that matters.
%
:- pred get_both_opt_deps(globals::in, bool::in, list(module_name)::in,
list(string)::in, list(module_name)::out, list(module_name)::out,
io::di, io::uo) is det.
get_both_opt_deps(_, _, [], _, [], [], !IO).
get_both_opt_deps(Globals, BuildOptFiles, [Dep | Deps], IntermodDirs,
!:OptDeps, !:TransOptDeps, !IO) :-
get_both_opt_deps(Globals, BuildOptFiles, Deps, IntermodDirs,
!:OptDeps, !:TransOptDeps, !IO),
(
BuildOptFiles = yes,
search_for_module_source(Globals, IntermodDirs, IntermodDirs,
Dep, Result1, !IO),
(
Result1 = ok(_),
!:OptDeps = [Dep | !.OptDeps],
!:TransOptDeps = [Dep | !.TransOptDeps],
io.seen(!IO),
Found = yes
;
Result1 = error(_),
Found = no
)
;
BuildOptFiles = no,
Found = no
),
(
Found = no,
module_name_to_file_name(Globals, Dep, ".opt",
do_not_create_dirs, OptName, !IO),
search_for_file_returning_dir(do_not_open_file, IntermodDirs,
OptName, Result2, !IO),
(
Result2 = ok(_),
!:OptDeps = [Dep | !.OptDeps]
;
Result2 = error(_)
),
module_name_to_file_name(Globals, Dep, ".trans_opt",
do_not_create_dirs, TransOptName, !IO),
search_for_file_returning_dir(do_not_open_file, IntermodDirs,
TransOptName, Result3, !IO),
(
Result3 = ok(_),
!:TransOptDeps = [Dep | !.TransOptDeps]
;
Result3 = error(_)
)
;
Found = yes
).
get_opt_deps(_, _, [], _, _, [], !IO).
get_opt_deps(Globals, BuildOptFiles, [Dep | Deps], IntermodDirs, Suffix,
!:OptDeps, !IO) :-
get_opt_deps(Globals, BuildOptFiles, Deps, IntermodDirs, Suffix,
!:OptDeps, !IO),
(
BuildOptFiles = yes,
search_for_module_source(Globals, IntermodDirs, IntermodDirs,
Dep, Result1, !IO),
(
Result1 = ok(_),
!:OptDeps = [Dep | !.OptDeps],
Found = yes,
io.seen(!IO)
;
Result1 = error(_),
Found = no
)
;
BuildOptFiles = no,
Found = no
),
(
Found = no,
module_name_to_search_file_name(Globals, Dep, Suffix, OptName, !IO),
search_for_file(do_not_open_file, IntermodDirs, OptName, Result2, !IO),
(
Result2 = ok(_),
!:OptDeps = [Dep | !.OptDeps]
;
Result2 = error(_)
)
;
Found = yes
).
%-----------------------------------------------------------------------------%
:- pred compare_module_names(module_name::in, module_name::in,
comparison_result::out) is det.
compare_module_names(Sym1, Sym2, Result) :-
Str1 = sym_name_to_string(Sym1),
Str2 = sym_name_to_string(Sym2),
compare(Result, Str1, Str2).
%-----------------------------------------------------------------------------%
:- end_module parse_tree.write_deps_file.
%-----------------------------------------------------------------------------%