mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-16 22:35:41 +00:00
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".
2529 lines
103 KiB
Mathematica
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.
|
|
%-----------------------------------------------------------------------------%
|