Files
mercury/compiler/make.module_target.m
Fergus Henderson 7597790760 Use sub-modules to structure the modules in the Mercury compiler directory.
The main aim of this change is to make the overall, high-level structure
of the compiler clearer, and to encourage better encapsulation of the
major components.

compiler/libs.m:
compiler/backend_libs.m:
compiler/parse_tree.m:
compiler/hlds.m:
compiler/check_hlds.m:
compiler/transform_hlds.m:
compiler/bytecode_backend.m:
compiler/aditi_backend.m:
compiler/ml_backend.m:
compiler/ll_backend.m:
compiler/top_level.m:
	New files.  One module for each of the major components of the
	Mercury compiler.  These modules contain (as separate sub-modules)
	all the other modules in the Mercury compiler, except gcc.m and
	mlds_to_gcc.m.

Mmakefile:
compiler/Mmakefile:
	Handle the fact that the top-level module is now `top_level',
	not `mercury_compile' (since `mercury_compile' is a sub-module
	of `top_level').

compiler/Mmakefile:
	Update settings of *FLAGS-<modulename> to use the appropriate
	nested module names.

compiler/recompilation_check.m:
compiler/recompilation_version.m:
compiler/recompilation_usage.m:
compiler/recompilation.check.m:
compiler/recompilation.version.m:
compiler/recompilation.version.m:
	Convert the `recompilation_*' modules into sub-modules of the
	`recompilation' module.

compiler/*.m:
compiler/*.pp:
	Module-qualify the module names in `:- module', `:- import_module',
	and `:- use_module' declarations.

compiler/base_type_info.m:
compiler/base_type_layout.m:
	Deleted these unused empty modules.

compiler/prog_data.m:
compiler/globals.m:
	Move the `foreign_language' type from prog_data to globals.

compiler/mlds.m:
compiler/ml_util.m:
compiler/mlds_to_il.m:
	Import `globals', for `foreign_language'.

Mmake.common.in:
trace/Mmakefile:
runtime/Mmakefile:
	Rename the %.check.c targets as %.check_hdr.c,
	to avoid conflicts with compiler/recompilation.check.c.
2002-03-20 12:37:56 +00:00

702 lines
24 KiB
Mathematica

%-----------------------------------------------------------------------------%
% Copyright (C) 2002 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
:- module make__module_target.
:- interface.
:- pred make_module_target(dependency_file::in, bool::out,
make_info::in, make_info::out, io__state::di, io__state::uo) is det.
% For make__module_dep_file__write_module_dep_file.
:- pred record_made_target(target_file::in, compilation_task_type::in,
bool::in, make_info::in, make_info::out,
io__state::di, io__state::uo) is det.
:- type foreign_code_file
---> foreign_code_file(
foreign_language :: foreign_language,
target_file :: file_name,
object_file :: file_name
).
% Find the foreign code files generated when a module is processed.
:- pred external_foreign_code_files(module_imports::in,
list(foreign_code_file)::out, io__state::di, io__state::uo) is det.
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module hlds__passes_aux.
:- pred make_module_target(dependency_file::in, bool::in, bool::out,
make_info::in, make_info::out, io__state::di, io__state::uo) is det.
make_module_target(TargetFile, Succeeded1, Succeeded1 `and` Succeeded2,
Info0, Info) -->
make_module_target(TargetFile, Succeeded2, Info0, Info).
make_module_target(file(_, _) @ Dep, Succeeded, Info0, Info) -->
dependency_status(Dep, Status, Info0, Info),
{ Succeeded = ( Status = error -> no ; yes ) }.
make_module_target(target(TargetFile) @ Dep, Succeeded, Info0, Info) -->
dependency_status(Dep, Status, Info0, Info1),
(
{ Status = not_considered },
{ TargetFile = ModuleName - FileType },
get_module_dependencies(ModuleName, MaybeImports, Info1, Info2),
(
{ MaybeImports = no },
{ Succeeded = no },
{ Info = Info2 ^ dependency_status ^ elem(Dep) := error }
;
{ MaybeImports = yes(Imports) },
globals__io_get_globals(Globals),
{ CompilationTask = compilation_task(Globals, FileType) },
(
% For a target built by processing a Mercury source file,
% the target for a nested sub-module is produced as a side
% effect of making the target for the top-level module in
% the file.
{ CompilationTask = process_module(_) - _ },
{ Imports ^ source_file_module_name \= ModuleName }
->
make_module_target(
target(Imports ^ source_file_module_name - FileType),
Succeeded, Info2, Info)
;
{ CompilationTask = CompilationTaskType - _ },
touched_files(TargetFile, CompilationTaskType,
TouchedTargetFiles, TouchedFiles, Info2, Info3),
{ list__foldl(update_target_status(being_built),
TouchedTargetFiles, Info3, Info4) },
debug_file_msg(TargetFile, "checking dependencies"),
{ CompilationTask = process_module(_) - _ ->
ModulesToCheck = [ModuleName | Imports ^ nested_children]
;
ModulesToCheck = [ModuleName]
},
foldl3_maybe_stop_at_error(Info4 ^ keep_going,
union_deps(target_dependencies(Globals, FileType)),
ModulesToCheck, DepsSuccess, set__init,
DepFiles0, Info4, Info5),
{ DepFiles = set__to_sorted_list(DepFiles0) },
debug_msg(
(pred(di, uo) is det -->
write_target_file(TargetFile),
io__write_string(": dependencies:\n"),
io__write_list(DepFiles, ", ", write_dependency_file),
io__nl
)),
%
% For comparison, find the oldest of the touched
% timestamp files.
%
list__map_foldl2(
get_timestamp_file_timestamp, TouchedTargetFiles,
TouchedTargetFileTimestamps, Info5, Info6),
list__map_foldl2(get_file_timestamp([dir__this_directory]),
TouchedFiles, TouchedFileTimestamps, Info6, Info8),
{ MaybeOldestTimestamp0 = list__foldl(find_oldest_timestamp,
TouchedTargetFileTimestamps, ok(newest_timestamp)) },
{ MaybeOldestTimestamp = list__foldl(find_oldest_timestamp,
TouchedFileTimestamps, MaybeOldestTimestamp0) },
module_name_to_file_name(ModuleName,
target_extension(Globals, FileType),
no, TargetFileName),
globals__io_lookup_bool_option(keep_going, KeepGoing),
( { DepsSuccess = no, KeepGoing = no } ->
{ Info10 = Info8 },
{ DepsResult = error }
;
foldl2_maybe_stop_at_error(KeepGoing,
make_module_target, DepFiles,
_, Info8, Info9),
check_dependencies(TargetFileName,
MaybeOldestTimestamp, DepFiles,
DepsResult0, Info9, Info10),
{ DepsResult =
( DepsSuccess = yes -> DepsResult0 ; error ) }
),
(
{ DepsResult = error },
{ Succeeded = no },
{ list__foldl(update_target_status(error),
TouchedTargetFiles, Info10, Info) }
;
{ DepsResult = out_of_date },
build_target(CompilationTask, TargetFile, Imports,
TouchedTargetFiles, TouchedFiles, Succeeded,
Info10, Info)
;
{ DepsResult = up_to_date },
debug_file_msg(TargetFile, "up to date"),
{ Succeeded = yes },
{ list__foldl(update_target_status(up_to_date),
[TargetFile | TouchedTargetFiles],
Info10, Info) }
)
)
)
;
{ Status = up_to_date },
{ Succeeded = yes },
{ Info = Info1 }
;
{ Status = being_built },
{ error(
"make_module_target: target being built, circular dependencies?") },
{ Succeeded = no },
{ Info = Info1 }
;
{ Status = error },
{ Succeeded = no },
{ Info = Info1 }
).
:- func find_oldest_timestamp(maybe_error(timestamp),
maybe_error(timestamp)) = maybe_error(timestamp).
find_oldest_timestamp(error(_) @ Timestamp, _) = Timestamp.
find_oldest_timestamp(ok(_), error(_) @ Timestamp) = Timestamp.
find_oldest_timestamp(ok(Timestamp1), ok(Timestamp2)) =
ok( ( compare((<), Timestamp1, Timestamp2) -> Timestamp1 ; Timestamp2 ) ).
%-----------------------------------------------------------------------------%
:- pred build_target(compilation_task_result::in, target_file::in,
module_imports::in, list(target_file)::in, list(file_name)::in,
bool::out, make_info::in, make_info::out,
io__state::di, io__state::uo) is det.
build_target(CompilationTask, TargetFile, Imports, TouchedTargetFiles,
TouchedFiles, Succeeded, Info0, Info) -->
maybe_make_target_message(TargetFile),
{ TargetFile = ModuleName - _FileType },
{ CompilationTask = Task - TaskOptions },
{ Cleanup =
(pred(MakeInfo0::in, MakeInfo::out, di, uo) is det -->
% XXX Remove `.int.tmp' files.
list__foldl2(remove_target_file, TouchedTargetFiles,
MakeInfo0, MakeInfo1),
list__foldl2(remove_file, TouchedFiles,
MakeInfo1, MakeInfo)
) },
build_with_check_for_interrupt(
build_with_module_options_and_output_redirect(ModuleName,
TaskOptions, build_target_2(ModuleName, Task, Imports)),
Cleanup, Succeeded, Info0, Info1),
record_made_target_2(Succeeded, TargetFile, TouchedTargetFiles,
TouchedFiles, Info1, Info).
:- pred build_target_2(module_name::in, compilation_task_type::in,
module_imports::in, list(string)::in, io__output_stream::in,
bool::out, make_info::in, make_info::out,
io__state::di, io__state::uo) is det.
build_target_2(ModuleName, process_module(ModuleTask), _Imports,
AllOptionArgs, ErrorStream, Succeeded, Info, Info) -->
{ prog_out__sym_name_to_string(ModuleName, ".", ModuleArg) },
globals__io_lookup_bool_option(verbose_commands, Verbose),
( { Verbose = yes } ->
{ AllArgs = list__append(AllOptionArgs, [ModuleArg]) },
io__write_string("Invoking command `mmc "),
% XXX Don't write the default options.
io__write_list(quote_args(AllArgs), " ",
io__write_string),
io__write_string("'"),
io__nl
;
[]
),
%
% Run compilations to target code in a separate process.
% This is necessary for `--target asm' because the GCC
% backend can only be invoked once per process. It's a good
% idea for other the backends because it avoids problems with
% the Boehm GC retaining memory by scanning too much of the
% Mercury stacks. If the compilation is run in a separate
% process, it is also easier to kill if an interrupt arrives.
%
io__set_output_stream(ErrorStream, OldOutputStream),
( { ModuleTask = compile_to_target_code } ->
call_in_forked_process(call_mercury_compile_main([ModuleArg]),
invoke_mmc(ErrorStream, AllOptionArgs), Succeeded)
;
call_mercury_compile_main([ModuleArg], Succeeded)
),
io__set_output_stream(OldOutputStream, _),
(
{ ModuleTask = compile_to_target_code
; ModuleTask = errorcheck
}
->
% The `.err_date' file is needed because the `.err'
% file is touched by all phases of compilation, including
% writing interfaces.
touch_interface_datestamp(ModuleName, ".err_date")
;
[]
).
build_target_2(ModuleName, target_code_to_object_code,
Imports, _, ErrorStream, Succeeded, Info0, Info) -->
get_target_code_to_object_code_foreign_files(ModuleName,
ForeignCodeFiles, Info0, Info),
globals__io_get_target(CompilationTarget),
{ CompileTargetCode =
(pred(Succeeded1::out, di, uo) is det -->
build_object_code(ModuleName, CompilationTarget,
ErrorStream, Imports, Succeeded0),
list__map_foldl(compile_foreign_code_file(ErrorStream),
ForeignCodeFiles, ForeignCodeSucceeded),
{
Succeeded0 = yes,
\+ list__member(no, ForeignCodeSucceeded)
->
Succeeded1 = yes
;
Succeeded1 = no
}
) },
% Run the compilation in a child process so it can
% be killed if an interrupt arrives.
call_in_forked_process(CompileTargetCode,
CompileTargetCode, Succeeded).
:- pred build_object_code(module_name::in, compilation_target::in,
io__output_stream::in, module_imports::in, bool::out,
io__state::di, io__state::uo) is det.
build_object_code(ModuleName, c, ErrorStream, _Imports, Succeeded) -->
compile_target_code__compile_c_file(ErrorStream, ModuleName, Succeeded).
build_object_code(ModuleName, asm, ErrorStream, _Imports, Succeeded) -->
compile_target_code__assemble(ErrorStream, ModuleName, Succeeded).
build_object_code(ModuleName, java, ErrorStream, _Imports, Succeeded) -->
compile_target_code__compile_java_file(ErrorStream, ModuleName, Succeeded).
build_object_code(ModuleName, il, ErrorStream, Imports, Succeeded) -->
compile_target_code__il_assemble(ErrorStream, ModuleName,
Imports ^ has_main, Succeeded).
:- pred compile_foreign_code_file(io__output_stream::in, foreign_code_file::in,
bool::out, io__state::di, io__state::uo) is det.
compile_foreign_code_file(ErrorStream, foreign_code_file(c, CFile, ObjFile),
Succeeded) -->
compile_target_code__compile_c_file(ErrorStream,
CFile, ObjFile, Succeeded).
compile_foreign_code_file(ErrorStream, foreign_code_file(il, ILFile, DLLFile),
Succeeded) -->
compile_target_code__il_assemble(ErrorStream, ILFile, DLLFile,
no_main, Succeeded).
compile_foreign_code_file(ErrorStream,
foreign_code_file(managed_cplusplus, MCPPFile, DLLFile),
Succeeded) -->
compile_target_code__compile_managed_cplusplus_file(ErrorStream,
MCPPFile, DLLFile, Succeeded).
compile_foreign_code_file(ErrorStream,
foreign_code_file(csharp, CSharpFile, DLLFile),
Succeeded) -->
compile_target_code__compile_csharp_file(ErrorStream,
CSharpFile, DLLFile, Succeeded).
%-----------------------------------------------------------------------------%
:- pred call_mercury_compile_main(list(string)::in, bool::out,
io__state::di, io__state::uo) is det.
call_mercury_compile_main(Args, Succeeded) -->
io__get_exit_status(Status0),
io__set_exit_status(0),
mercury_compile__main(Args),
io__get_exit_status(Status),
{ Succeeded = ( Status = 0 -> yes ; no ) },
io__set_exit_status(Status0).
:- pred invoke_mmc(io__output_stream::in, list(string)::in, bool::out,
io__state::di, io__state::uo) is det.
invoke_mmc(ErrorStream, Args, Succeeded) -->
{ CommandVerbosity = verbose }, % We've already written the command.
{ Command = string__join_list(" ", ["mmc" | quote_args(Args)]) },
invoke_shell_command(ErrorStream, CommandVerbosity,
Command, Succeeded).
%-----------------------------------------------------------------------------%
record_made_target(TargetFile, CompilationTask, Succeeded, Info0, Info) -->
touched_files(TargetFile, CompilationTask, TouchedTargetFiles,
TouchedFiles, Info0, Info1),
record_made_target_2(Succeeded, TargetFile, TouchedTargetFiles,
TouchedFiles, Info1, Info).
:- pred record_made_target_2(bool::in, target_file::in, list(target_file)::in,
list(file_name)::in, make_info::in, make_info::out,
io__state::di, io__state::uo) is det.
record_made_target_2(Succeeded, TargetFile, TouchedTargetFiles,
OtherTouchedFiles, Info0, Info) -->
( { Succeeded = yes } ->
{ TargetStatus = up_to_date },
{ Info1 = Info0 }
;
{ TargetStatus = error },
{ Info1 = Info0 },
target_file_error(TargetFile)
),
{ list__foldl(update_target_status(TargetStatus),
TouchedTargetFiles, Info1, Info2) },
{ DeleteTimestamp =
(pred(TouchedFile::in, MakeInfo0::in, MakeInfo::out) is det :-
MakeInfo = MakeInfo0 ^ file_timestamps :=
map__delete(MakeInfo0 ^ file_timestamps, TouchedFile)
) },
list__map_foldl2(get_file_name, TouchedTargetFiles,
TouchedTargetFileNames, Info2, Info3),
{ list__foldl(DeleteTimestamp, TouchedTargetFileNames, Info3, Info4) },
{ list__foldl(DeleteTimestamp, OtherTouchedFiles, Info4, Info) }.
:- pred update_target_status(dependency_status::in, target_file::in,
make_info::in, make_info::out) is det.
update_target_status(TargetStatus, TargetFile, Info,
Info ^ dependency_status ^ elem(target(TargetFile)) := TargetStatus).
%-----------------------------------------------------------------------------%
:- type compilation_task_result == pair(compilation_task_type, list(string)).
:- func compilation_task(globals, module_target_type) =
compilation_task_result.
compilation_task(_, source) = _ :- error("compilation_task").
compilation_task(_, errors) =
process_module(errorcheck) - ["--errorcheck_only"].
compilation_task(_, unqualified_short_interface) =
process_module(make_short_interface) -
["--make-short-interface"].
compilation_task(Globals, short_interface) =
compilation_task(Globals, long_interface).
compilation_task(_, long_interface) =
process_module(make_interface) - ["--make-interface"].
compilation_task(_, private_interface) =
process_module(make_private_interface) -
["--make-private-interface"].
compilation_task(_, intermodule_interface) =
process_module(make_optimization_interface) -
["--make-optimization-interface"].
compilation_task(_, aditi_code) =
process_module(compile_to_target_code) - ["--aditi-only"].
compilation_task(Globals, c_header) = compilation_task(Globals, c_code).
compilation_task(_, c_code) = process_module(compile_to_target_code) -
["--compile-to-c"].
compilation_task(_, il_code) = process_module(compile_to_target_code) -
["--il-only"].
compilation_task(_, il_asm) = target_code_to_object_code - [].
compilation_task(_, java_code) = process_module(compile_to_target_code) -
["--java-only"].
compilation_task(_, asm_code(PIC)) =
process_module(compile_to_target_code) -
( PIC = pic -> ["--pic"] ; [] ).
compilation_task(Globals, object_code(PIC)) =
target_code_to_object_code - Flags :-
globals__get_target(Globals, Target),
( PIC = pic ->
Flags = ( Target = asm -> ["--pic"] ; ["--pic-reg"] )
;
Flags = []
).
% Find the files which could be touched by a compilation task.
:- pred touched_files(target_file::in, compilation_task_type::in,
list(target_file)::out, list(file_name)::out,
make_info::in, make_info::out, io__state::di, io__state::uo) is det.
touched_files(TargetFile, process_module(Task), TouchedTargetFiles,
TouchedFileNames, Info0, Info) -->
{ TargetFile = ModuleName - FileType },
get_module_dependencies(ModuleName, MaybeImports, Info0, Info1),
{ MaybeImports = yes(Imports0) ->
Imports = Imports0
;
% This error should have been caught earlier.
% We shouldn't be attempting to build a target
% if we couldn't find the dependencies for the
% module.
error("touched_files: no module dependencies")
},
{ NestedChildren = Imports ^ nested_children },
{ SourceFileModuleNames = [ModuleName | NestedChildren] },
list__map_foldl2(get_module_dependencies, NestedChildren,
MaybeNestedImportsList, Info1, Info),
{
list__map(
(pred(yes(NestedModuleImports)::in,
NestedModuleImports::out) is semidet),
MaybeNestedImportsList, NestedImportsList)
->
ModuleImportsList = [Imports | NestedImportsList]
;
% This error should have been caught earlier.
% We shouldn't be attempting to build a target
% if we couldn't find the dependencies for the
% module or its nested sub-modules.
error("touched_files: no nested module dependencies")
},
globals__io_get_target(CompilationTarget),
{ Task = compile_to_target_code, CompilationTarget = asm ->
% For `--target asm' the code for the nested children
% is placed in the `.s' file for the top-level module
% in the source file.
TargetModuleNames = [ModuleName]
;
TargetModuleNames = SourceFileModuleNames
},
%
% Find out what header files are generated.
%
(
{ Task = compile_to_target_code }
->
list__map_foldl(external_foreign_code_files, ModuleImportsList,
ForeignCodeFileList),
{ ForeignCodeFiles = list__map(
(func(ForeignFile) = ForeignFile ^ target_file),
list__condense(ForeignCodeFileList)) },
(
{ CompilationTarget = c },
globals__io_lookup_bool_option(highlevel_code, HighLevelCode),
( { HighLevelCode = yes } ->
%
% When compiling to high-level C, we always generate
% a header file.
%
{ HeaderModuleNames = SourceFileModuleNames }
;
%
% When compiling to low-level C, we only generate a
% header file if the module contains `:- pragma export'
% declarations.
%
{ HeaderModuleNames =
list__filter_map(
(func(MImports) =
MImports ^ module_name is semidet :-
contains_foreign_export =
MImports ^ contains_foreign_export
), ModuleImportsList) }
),
{ HeaderTargets = make_target_list(HeaderModuleNames,
c_header) }
;
{ CompilationTarget = asm },
%
% When compiling to assembler, we only generate
% a header file if the module contains foreign code.
%
{ HeaderModuleNames =
list__filter_map(
(func(MImports) = MImports ^ module_name is semidet :-
contains_foreign_code(_) = MImports ^ foreign_code
), ModuleImportsList) },
{ HeaderTargets = make_target_list(HeaderModuleNames,
c_header) }
;
{ CompilationTarget = il },
{ HeaderTargets = [] }
;
{ CompilationTarget = java },
{ HeaderTargets = [] }
),
{ TouchedTargetFiles0 =
make_target_list(TargetModuleNames, FileType) },
{ TouchedTargetFiles = TouchedTargetFiles0 ++ HeaderTargets }
;
{ Task = make_interface }
->
% Both long and short interface files are produced
% when making the interface.
{ ForeignCodeFiles = [] },
{ TouchedTargetFiles =
make_target_list(TargetModuleNames, long_interface)
++ make_target_list(TargetModuleNames, short_interface) }
;
{ ForeignCodeFiles = [] },
{ TouchedTargetFiles =
make_target_list(TargetModuleNames, FileType) }
),
list__foldl2(
(pred((TargetModuleName - TargetFileType)::in, TimestampFiles0::in,
TimestampFiles1::out, di, uo) is det -->
( { TimestampExt = timestamp_extension(TargetFileType) } ->
module_name_to_file_name(TargetModuleName,
TimestampExt, no, TimestampFile),
{ TimestampFiles1 =
[TimestampFile | TimestampFiles0] }
;
{ TimestampFiles1 = TimestampFiles0 }
)
), TouchedTargetFiles, [], TimestampFileNames),
{ TouchedFileNames = list__condense([ForeignCodeFiles,
TimestampFileNames]) }.
touched_files(TargetFile, target_code_to_object_code,
[TargetFile], ForeignObjectFiles, Info0, Info) -->
{ TargetFile = ModuleName - _ },
get_target_code_to_object_code_foreign_files(ModuleName,
ForeignCodeFileList, Info0, Info),
{ ForeignObjectFiles = list__map(
(func(ForeignFile) = ForeignFile ^ object_file),
ForeignCodeFileList) }.
:- pred get_target_code_to_object_code_foreign_files(module_name::in,
list(foreign_code_file)::out, make_info::in, make_info::out,
io__state::di, io__state::uo) is det.
get_target_code_to_object_code_foreign_files(ModuleName, ForeignCodeFiles,
Info0, Info) -->
get_module_dependencies(ModuleName, MaybeImports, Info0, Info1),
{ MaybeImports = yes(Imports0) ->
Imports = Imports0
;
% This error should have been caught earlier.
% We shouldn't be attempting to build a target
% if we couldn't find the dependencies for the
% module.
error(
"get_target_code_to_object_code_foreign_files: no module dependencies")
},
%
% For `--target asm' there is only one `.s' file per module
% so we should compile the foreign code for
%
globals__io_get_target(CompilationTarget),
( { CompilationTarget = asm } ->
{ NestedChildren = Imports ^ nested_children },
list__map_foldl2(get_module_dependencies, NestedChildren,
MaybeNestedImportsList, Info1, Info),
{
list__map(
(pred(yes(NestedModuleImports)::in,
NestedModuleImports::out) is semidet),
MaybeNestedImportsList, NestedImportsList)
->
ModuleImportsList = [Imports | NestedImportsList]
;
% This error should have been caught earlier.
% We shouldn't be attempting to build a target
% if we couldn't find the dependencies for the
% module or its nested sub-modules.
error(
"get_target_code_to_object_code_foreign_files: no nested module dependencies")
}
;
{ Info = Info1 },
{ ModuleImportsList = [Imports] }
),
list__map_foldl(external_foreign_code_files,
ModuleImportsList, ForeignCodeFileLists),
{ ForeignCodeFiles = list__condense(ForeignCodeFileLists) }.
external_foreign_code_files(Imports, ForeignFiles) -->
%
% Find externally compiled foreign code files for
% `:- pragma foreign_proc' declarations.
%
globals__io_get_target(CompilationTarget),
{ ModuleName = Imports ^ module_name },
(
{ CompilationTarget = asm },
{ Imports ^ foreign_code = contains_foreign_code(Langs) },
{ set__member(c, Langs) }
->
module_name_to_file_name(
foreign_language_module_name(ModuleName, c), ".c",
no, CCodeFileName),
module_name_to_file_name(
foreign_language_module_name(ModuleName, c), ".o",
no, ObjFileName),
{ ForeignFiles0 =
[foreign_code_file(c, CCodeFileName, ObjFileName) ] }
;
{ CompilationTarget = il },
{ Imports ^ foreign_code = contains_foreign_code(Langs) }
->
list__map_foldl(external_foreign_code_files_for_il(ModuleName),
set__to_sorted_list(Langs), ForeignFilesList),
{ list__condense(ForeignFilesList, ForeignFiles0) }
;
{ ForeignFiles0 = [] }
),
%
% Find externally compiled foreign code files for fact tables.
%
( { CompilationTarget = c ; CompilationTarget = asm } ->
list__map_foldl(
(pred(FactTableFile::in, FactTableForeignFile::out,
di, uo) is det -->
fact_table_file_name(ModuleName, FactTableFile,
".c", FactTableCFile),
globals__io_lookup_string_option(
object_file_extension, ObjExt),
fact_table_file_name(ModuleName, FactTableFile,
ObjExt, FactTableObjFile),
{ FactTableForeignFile = foreign_code_file(c,
FactTableCFile, FactTableObjFile) }
), Imports ^ fact_table_deps, FactTableForeignFiles),
{ ForeignFiles = ForeignFiles0 ++ FactTableForeignFiles }
;
{ ForeignFiles = ForeignFiles0 }
).
:- pred external_foreign_code_files_for_il(module_name::in,
foreign_language::in, list(foreign_code_file)::out,
io__state::di, io__state::uo) is det.
external_foreign_code_files_for_il(ModuleName, Language,
ForeignFiles) -->
(
{ ForeignModuleName = foreign_language_module_name(ModuleName,
Language) },
{ ForeignExt = foreign_language_file_extension(Language) }
->
module_name_to_file_name(ForeignModuleName, ForeignExt, no,
ForeignFileName),
module_name_to_file_name(ForeignModuleName, ".dll", no,
ForeignDLLFileName),
{ ForeignFiles = [foreign_code_file(Language, ForeignFileName,
ForeignDLLFileName)] }
;
% No external file is generated for this foreign language.
{ ForeignFiles = [] }
).
%-----------------------------------------------------------------------------%