mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-21 12:23:44 +00:00
329 lines
12 KiB
Mathematica
329 lines
12 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2023 The Mercury team.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: make.file_names.m.
|
|
% Authors: stayl, wangp.
|
|
%
|
|
% Predicates dealing with file names, used to implement `mmc --make'.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module make.file_names.
|
|
:- interface.
|
|
|
|
:- import_module libs.
|
|
:- import_module libs.file_util.
|
|
:- import_module libs.globals.
|
|
:- import_module make.make_info.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.file_names.
|
|
|
|
:- import_module io.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File names.
|
|
%
|
|
|
|
% get_file_name_for_target_file(Globals, From, Search, TargetFile,
|
|
% FileName, !IO):
|
|
%
|
|
% Compute a file name for the given target file.
|
|
% `Search' should be `for_search' if the file could be part of an
|
|
% installed library.
|
|
%
|
|
:- pred get_file_name_for_target_file(io.text_output_stream::in, globals::in,
|
|
string::in, maybe_for_search::in, target_file::in, file_name::out,
|
|
make_info::in, make_info::out, io::di, io::uo) is det.
|
|
|
|
:- pred dependency_file_to_file_name(globals::in, dependency_file::in,
|
|
string::out, io::di, io::uo) is det.
|
|
|
|
% Return the file name for the given target_file. The I/O state pair
|
|
% may be needed to find this file name.
|
|
%
|
|
:- pred get_make_target_file_name(globals::in, string::in,
|
|
target_file::in, string::out, io::di, io::uo) is det.
|
|
|
|
:- pred module_target_to_file_name(globals::in, string::in,
|
|
module_target_type::in, module_name::in, file_name::out,
|
|
io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Extensions on file names.
|
|
%
|
|
|
|
% Find the extension for the timestamp file for the given target type,
|
|
% if one exists.
|
|
%
|
|
:- pred timestamp_extension(module_target_type::in, ext::out) is semidet.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module backend_libs.
|
|
:- import_module backend_libs.compile_target_code.
|
|
:- import_module make.get_module_dep_info.
|
|
:- import_module parse_tree.module_dep_info.
|
|
:- import_module parse_tree.prog_foreign.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
get_file_name_for_target_file(ProgressStream, Globals, From, Search,
|
|
TargetFile, FileName, !Info, !IO) :-
|
|
TargetFile = target_file(ModuleName, TargetType),
|
|
( if TargetType = module_target_source then
|
|
% In some cases the module name won't match the file name
|
|
% (module mdb.parse might be in parse.m or mdb.m), so we need to
|
|
% look up the file name here.
|
|
get_maybe_module_dep_info(ProgressStream, Globals,
|
|
ModuleName, MaybeModuleDepInfo, !Info, !IO),
|
|
(
|
|
MaybeModuleDepInfo = some_module_dep_info(ModuleDepInfo),
|
|
module_dep_info_get_source_file_name(ModuleDepInfo, FileName)
|
|
;
|
|
MaybeModuleDepInfo = no_module_dep_info,
|
|
% Something has gone wrong generating the dependencies,
|
|
% so just take a punt (which probably won't work).
|
|
module_name_to_source_file_name(ModuleName, FileName, !IO)
|
|
)
|
|
else
|
|
target_type_to_target_extension(TargetType, TargetExt),
|
|
(
|
|
TargetExt = source,
|
|
module_name_to_source_file_name(ModuleName, FileName, !IO)
|
|
;
|
|
TargetExt = extension(Ext),
|
|
(
|
|
Search = not_for_search,
|
|
module_name_to_file_name(Globals, From, Ext,
|
|
ModuleName, FileName)
|
|
;
|
|
Search = for_search,
|
|
module_name_to_search_file_name(Globals, From, Ext,
|
|
ModuleName, FileName)
|
|
)
|
|
;
|
|
( TargetExt = foreign_obj(_, _)
|
|
; TargetExt = fact_table_obj(_, _)
|
|
),
|
|
(
|
|
Search = not_for_search,
|
|
module_target_to_file_name(Globals, From, TargetType,
|
|
ModuleName, FileName, !IO)
|
|
;
|
|
Search = for_search,
|
|
module_target_to_search_file_name(Globals, From, TargetType,
|
|
ModuleName, FileName, !IO)
|
|
)
|
|
)
|
|
).
|
|
|
|
dependency_file_to_file_name(Globals, DepFile, FileName, !IO) :-
|
|
(
|
|
DepFile = dep_target(TargetFile),
|
|
get_make_target_file_name(Globals, $pred, TargetFile, FileName, !IO)
|
|
;
|
|
DepFile = dep_file(FileName)
|
|
).
|
|
|
|
get_make_target_file_name(Globals, From, TargetFile, FileName, !IO) :-
|
|
TargetFile = target_file(ModuleName, TargetType),
|
|
module_target_to_file_name(Globals, From, TargetType, ModuleName,
|
|
FileName, !IO).
|
|
|
|
module_target_to_file_name(Globals, From, TargetType, ModuleName,
|
|
FileName, !IO) :-
|
|
target_type_to_target_extension(TargetType, TargetExt),
|
|
(
|
|
TargetExt = source,
|
|
module_name_to_source_file_name(ModuleName, FileName, !IO)
|
|
;
|
|
TargetExt = extension(Ext),
|
|
module_name_to_file_name(Globals, From, Ext,
|
|
ModuleName, FileName)
|
|
;
|
|
TargetExt = foreign_obj(PIC, Lang),
|
|
foreign_language_module_name(ModuleName, Lang, ForeignModuleName),
|
|
module_target_to_file_name(Globals, From,
|
|
module_target_object_code(PIC),
|
|
ForeignModuleName, FileName, !IO)
|
|
;
|
|
TargetExt = fact_table_obj(PIC, FactFile),
|
|
maybe_pic_object_file_extension(PIC, ObjExt, _),
|
|
fact_table_file_name(Globals, $pred, ext_cur_ngs_gs(ObjExt),
|
|
FactFile, FileName)
|
|
).
|
|
|
|
:- pred module_target_to_search_file_name(globals::in, string::in,
|
|
module_target_type::in,
|
|
module_name::in, file_name::out, io::di, io::uo) is det.
|
|
|
|
module_target_to_search_file_name(Globals, From, TargetType, ModuleName,
|
|
FileName, !IO) :-
|
|
target_type_to_target_extension(TargetType, TargetExt),
|
|
(
|
|
TargetExt = source,
|
|
% XXX This call ignores the implicit for_search setting.
|
|
module_name_to_source_file_name(ModuleName, FileName, !IO)
|
|
;
|
|
TargetExt = extension(Ext),
|
|
module_name_to_search_file_name(Globals, From, Ext,
|
|
ModuleName, FileName)
|
|
;
|
|
TargetExt = foreign_obj(PIC, Lang),
|
|
foreign_language_module_name(ModuleName, Lang, ForeignModuleName),
|
|
module_target_to_search_file_name(Globals, From,
|
|
module_target_object_code(PIC), ForeignModuleName, FileName, !IO)
|
|
;
|
|
TargetExt = fact_table_obj(PIC, FactFile),
|
|
maybe_pic_object_file_extension(PIC, ObjExt, _),
|
|
% XXX This call ignores the implicit for_search setting.
|
|
fact_table_file_name(Globals, $pred, ext_cur_ngs_gs(ObjExt),
|
|
FactFile, FileName)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type target_extension
|
|
---> source
|
|
; extension(ext)
|
|
; foreign_obj(pic, foreign_language)
|
|
; fact_table_obj(pic, string).
|
|
|
|
:- pred target_type_to_target_extension(module_target_type::in,
|
|
target_extension::out) is det.
|
|
|
|
target_type_to_target_extension(Target, TargetExt) :-
|
|
% target_type_to_extension and part of the implementation of
|
|
% classify_target_2 in make.top_level.m represent the same relationship
|
|
% between targets and suffixes, but in different directions, and for
|
|
% slightly different sets of targets. (For example, there is no extension
|
|
% that generates module_target_fact_table_object as a target.)
|
|
% Where they talk about the same targets, their codes should be
|
|
% kept in sync.
|
|
require_complete_switch [Target]
|
|
(
|
|
Target = module_target_source,
|
|
TargetExt = source
|
|
;
|
|
Target = module_target_errors,
|
|
TargetExt = extension(ext_cur(ext_cur_user_err))
|
|
;
|
|
Target = module_target_int0,
|
|
TargetExt = extension(ext_cur_ngs(ext_cur_ngs_int_int0))
|
|
;
|
|
Target = module_target_int1,
|
|
TargetExt = extension(ext_cur_ngs(ext_cur_ngs_int_int1))
|
|
;
|
|
Target = module_target_int2,
|
|
TargetExt = extension(ext_cur_ngs(ext_cur_ngs_int_int2))
|
|
;
|
|
Target = module_target_int3,
|
|
TargetExt = extension(ext_cur_ngs(ext_cur_ngs_int_int3))
|
|
;
|
|
Target = module_target_opt,
|
|
TargetExt = extension(
|
|
ext_cur_ngs_gs_max_ngs(ext_cur_ngs_gs_max_ngs_opt_plain))
|
|
;
|
|
Target = module_target_analysis_registry,
|
|
TargetExt = extension(
|
|
ext_cur_ngs_gs_max_ngs(ext_cur_ngs_gs_max_ngs_an_analysis))
|
|
;
|
|
Target = module_target_track_flags,
|
|
TargetExt = extension(ext_cur_ngs_gs(ext_cur_ngs_gs_misc_track_flags))
|
|
;
|
|
Target = module_target_c_header(header_mih),
|
|
TargetExt = extension(
|
|
ext_cur_ngs_gs_max_cur(ext_cur_ngs_gs_max_cur_mih))
|
|
;
|
|
Target = module_target_c_header(header_mh),
|
|
TargetExt = extension(ext_cur(ext_cur_mh))
|
|
;
|
|
Target = module_target_c_code,
|
|
TargetExt = extension(ext_cur_ngs_gs(ext_cur_ngs_gs_target_c))
|
|
;
|
|
Target = module_target_csharp_code,
|
|
% XXX ".exe" if the module contains main.
|
|
TargetExt = extension(ext_cur_ngs_gs(ext_cur_ngs_gs_target_cs))
|
|
;
|
|
Target = module_target_java_code,
|
|
TargetExt = extension(ext_cur_ngs_gs_java(ext_cur_ngs_gs_java_java))
|
|
;
|
|
Target = module_target_java_class_code,
|
|
TargetExt = extension(ext_cur_ngs_gs_java(ext_cur_ngs_gs_java_class))
|
|
;
|
|
Target = module_target_object_code(PIC),
|
|
maybe_pic_object_file_extension(PIC, ObjExt, _),
|
|
TargetExt = extension(ext_cur_ngs_gs(ObjExt))
|
|
;
|
|
Target = module_target_xml_doc,
|
|
TargetExt = extension(ext_cur(ext_cur_user_xml))
|
|
;
|
|
Target = module_target_foreign_object(PIC, Lang),
|
|
TargetExt = foreign_obj(PIC, Lang)
|
|
;
|
|
Target = module_target_fact_table_object(PIC, FactFile),
|
|
TargetExt = fact_table_obj(PIC, FactFile)
|
|
).
|
|
|
|
timestamp_extension(ModuleTargetType, Ext) :-
|
|
% XXX EXT The absence of code handling .trans_opt_date files
|
|
% would seem to me (zs) to be a bug.
|
|
(
|
|
ModuleTargetType = module_target_errors,
|
|
% We need a timestamp file for `.err' files because errors are written
|
|
% to the `.err' file even when writing interfaces. The timestamp
|
|
% is only updated when compiling to target code.
|
|
Ext = ext_cur_ngs(ext_cur_ngs_misc_err_date)
|
|
;
|
|
ModuleTargetType = module_target_int0,
|
|
Ext = ext_cur_ngs(ext_cur_ngs_int_date_int0)
|
|
;
|
|
ModuleTargetType = module_target_int1,
|
|
Ext = ext_cur_ngs(ext_cur_ngs_int_date_int12)
|
|
;
|
|
ModuleTargetType = module_target_int2,
|
|
Ext = ext_cur_ngs(ext_cur_ngs_int_date_int12)
|
|
;
|
|
ModuleTargetType = module_target_int3,
|
|
Ext = ext_cur_ngs(ext_cur_ngs_int_date_int3)
|
|
;
|
|
ModuleTargetType = module_target_opt,
|
|
Ext = ext_cur_ngs_gs(ext_cur_ngs_gs_opt_date_plain)
|
|
;
|
|
ModuleTargetType = module_target_analysis_registry,
|
|
% We need a timestamp file for `.analysis' files because they
|
|
% can be modified in the process of analysing _another_ module.
|
|
% The timestamp is only updated after actually analysing the module
|
|
% that the `.analysis' file corresponds to.
|
|
Ext = ext_cur_ngs_gs(ext_cur_ngs_gs_an_ds_date)
|
|
;
|
|
% Header files share a timestamp file with their corresponding
|
|
% target code files.
|
|
( ModuleTargetType = module_target_c_code
|
|
; ModuleTargetType = module_target_c_header(_)
|
|
),
|
|
Ext = ext_cur_ngs_gs(ext_cur_ngs_gs_target_date_c)
|
|
;
|
|
ModuleTargetType = module_target_csharp_code,
|
|
Ext = ext_cur_ngs_gs(ext_cur_ngs_gs_target_date_cs)
|
|
;
|
|
ModuleTargetType = module_target_java_code,
|
|
Ext = ext_cur_ngs_gs(ext_cur_ngs_gs_target_date_java)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module make.file_names.
|
|
%---------------------------------------------------------------------------%
|