mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-18 07:15:19 +00:00
Estimated hours taken: 60
Branches: main
Provide a mechanism for collecting statistics about tabling operations,
and provide a much more convenient mechanism for resetting tables.
Since it would too complex to do this while preserving the capability
of setting --tabling-via-extra-args to no, eliminate that capability
and the option. That option was useful only for measurements of the
performance boost from setting --tabling-via-extra-args to yes in any case,
so users lose no functionality.
Previously, the only way to debug the low level details of the tabling
mechanism was to build a runtime with a specific C macro (MR_TABLE_DEBUG)
and link with that runtime; this was cumbersome. Change that so that
every one of the debuggable tabling macros has a bool argument that says
whether debugging is enabled or not. The compiler can then set this to
MR_TRUE if the new option --table-debug is given, and to MR_FALSE otherwise.
If set to MR_FALSE, the C compiler should optimize away the debug code,
with zero impact on program size or speed.
Since these changes to macros require nontrivial bootstrapping, which we don't
want to do unnecessarily, modify the interface of the tabling macros as
required to support size limits on tables. This diff also implements the
parsing of size limit specifications on tables, but does not implement them
yet; that is for a future change.
To make the syntax simpler, this diff deletes the free-standing fast_loose_memo
pragma. The same functionality is now available with a fast_loose annotation
on an ordinary memo pragma.
Make a bunch of changes to improve readability and maintainability
in the process. These mostly take the form of renaming ambiguous and/or
not sufficiently expressive function symbols.
runtime/mercury_stack_layout.h:
runtime/mercury_tabling.h:
Move the description of structure of tables from mercury_stack_layout.h
to mercury_tabling.h, since we now need it for statistics even if
execution tracing is not enabled.
Modify those data structures to have room for the statistics.
Don't distinguish "strict", "fast_loose" and "specified" memoing
as separate eval methods; treat them as just different kinds
of the same eval method: "memo".
Remove underscores from the names of some types that the style guide
says shouldn't be there.
runtime/mercury_tabling_preds.h:
runtime/mercury_tabling_macros.h:
Modify the approach we use for macros that implement the predicates
of library/table_builtin.m. Instead of selecting between debug and
nondebug based on whether MR_TABLE_DEBUG is defined or not, add
an explicit argument controlling this to each debuggable macro.
The advantage of the new arrangement is that it scales. Another
argument controls whether we are computing statistics (and if yes,
where do we put it), and a third argument controls whether we maintain
back links in the tries and hash tables (this last argument is present
but is ignored for now).
Since the values of the arguments will be known when the .c files
containing calls to these macros are compiled, we pay the space and
time cost of debugging, statistics gathering and the maintenance of
back links if and only we need the revelant functionality.
Provide macros for limited backward compatibility with the old set
of macros; these allow workspaces created by old compilers to work
with the new macros in the runtime. The old macros followed the
naming scheme MR_table_*, the new ones are named MR_tbl_*.
runtime/mercury_table_int_fix_index_body.h:
runtime/mercury_table_int_start_index_body.h:
runtime/mercury_table_type_body.h:
New files containing parts of the old mercury_tabling.c. Each of these
files contains the body of the functions that used to be in
mercury_tabling.c. The new mercury_tabling.c #includes each of these
files more than once, to provide more than one variant of the old
function. These variants differ in aspects such as whether debugging
is enabled or statistics is being collected. Each variant therefore
incurs only the time costs it needs to. (We pay the space cost of
having all these variants all the time of course, but this cost
is negligible.)
runtime/mercury_tabling_stats_defs.h:
runtime/mercury_tabling_stats_nodefs.h:
runtime/mercury_tabling_stats_undefs.h:
New files that serve as wrappers around the newly #included files,
controlling how they handle statistics.
runtime/mercury_tabling.c:
Delete functions now in the new files, and #include them instead.
Delete the data structures that used to contain summary statistics;
the new approach keeps statistics in compiler-generated,
procedure-specific data structures.
runtime/mercury_trace_base.c:
Use the new versions of the tabling macros to access the I/O table.
runtime/mercury_type_info.h:
Update some documentation for the movement of code out of
mercury_tabling.c.
runtime/mercury_types.h:
Provide forward declarations of the identifiers denoting the new types
in mercury_tabling.h.
runtime/mercury_grade.h:
Increment the exec trace version number, since we have changed
a part of the exec trace structure.
runtime/mercury_bootstrap.h:
Fix some temporary issues that arise from some renames above.
runtime/mercury_hash_lookup_or_add_body.h:
Fix comment.
runtime/Mmakefile:
Mention the new files and the dependencies that involve them.
library/table_builtin.m:
Provide a type for representing statistics and a predicate for
printing statistics.
Use the updated versions of the macros in
runtime/mercury_tabling_preds.h.
compiler/prog_item.m:
Change representation of tabling pragmas to allow room for the new
attributes.
Allow an item to be marked as being generated by the compiler
as a result of a pragma memo attribute. We use this for the reset
and statistics predicates.
compiler/mercury_to_mercury.m:
Write out the new attributes of the tabling pragma.
compiler/prog_data.m:
compiler/hlds_data.m:
Change the cons_id that used to refer to a procedure's call table root
to refer to the entirety of the new data structure now containing it.
The compiler now needs a way to refer to the other components of this
new data structure, since it contains the statistics.
As in the runtime, don't distinguish "strict", "fast_loose" and
"specified" memoing as separate eval methods; treat them as just
different kinds of the same eval method: "memo".
Rename some of the uses of the function symbols "c", "java", "il".
compiler/hlds_pred.m:
Add an extra field in proc_infos for storing any tabling attributes.
Change the existing proc_info field that records information about
the kinds of arguments of tabled procedures to record the information
needed by the debugger too. This was needed to allow us to shift all
the RTTI for procedure-specific tables (as opposed to the RTTI for
the global I/O table) from mercury_stack_layout.h to mercury_tabling.h
without duplicating the data (which would be a maintenance problem).
Reformat some comments to make them easier to read.
compiler/layout.m:
compiler/layout_out.m:
Delete the part of the exec trace information that used to record
RTTI for tables, since this information is not generated only as
part of the debugger data structures anymore.
compiler/prog_io_pragma.m:
Recognize the updated syntax for tabling pragmas.
compiler/add_pragma.m:
When processing tabling pragmas for inclusion in the HLDS, create
any reset and statistics predicates they ask for.
compiler/make_hlds_passes.m:
Export a predicate now needed by add_pragma.m.
Handle the new attributes on tabling pragmas
compiler/globals.m:
Change the function symbols of the types describing backends and
foreign languages to say what they are. Previously, both types (as well
as several others) included the function symbol "c"; now, they are
target_c and lang_c respectively.
compiler/table_gen.m:
Implement the changes described at the top.
When passing around varsets and vartypes, pass the arguments in the
standard order.
compiler/goal_util.m:
compiler/hlds_goal.m:
When passing around varsets and vartypes, pass the arguments in the
standard order.
compiler/rtti.m:
Provide types for representing the runtime's data structures for
tabling (which are now significantly more complex than a single word)
and predicates for manipulating them, for use by both the ml and ll
backends.
compiler/llds.m:
Replace the comp_gen_c_var type with the tabling_info_struct type,
which contains the information needed to create the per-procedure
tabling data structures.
Replace references to call tables with references to the various
components of the new tabling data structures.
compiler/llds_out.m:
Add code to write out tabling_info_structs.
Delete the code required for the old, hacky way of resetting tables.
Reorder some code more logically.
compiler/proc_gen.m:
Generate tabling_info_structs.
compiler/stack_layout.m:
Don't generate the information now generated in proc_gen.m.
compiler/mlds.m:
Give mlds_proc_labels their own function symbols, instead of using
a pair. Rename some other function symbols to avoid ambiguity and add
expressiveness.
Provide for the representation of references to the various components
of the new tabling data structures, and for the representation of their
types.
compiler/ml_code_gen.m:
When generating code for a tabled procedure, generate also the data
structures required for its table.
compiler/rtti_to_mlds.m:
compiler/ml_util.m:
Move some predicates from rtti_to_mlds.m to ml_util.m, since we
now also want to call them from ml_code_gen.m.
compiler/name_mangle.m:
Add some utility predicates.
compiler/options.m:
Delete the old --allow-table-reset option.
Add the new --table-debug option.
Comment out an implementor-only option.
compiler/add_pred.m:
compiler/add_solver.m:
compiler/add_trail_ops.m:
compiler/add_type.m:
compiler/bytecode_gen.m:
compiler/code_gen.m:
compiler/compile_target_code.m:
compiler/complexity.m:
compiler/dependency_graph.m:
compiler/det_report.m:
compiler/export.m:
compiler/fact_table.m:
compiler/foreign.m:
compiler/global_data.m:
compiler/globals.m:
compiler/handle_options.m:
compiler/higher_order.m:
compiler/hlds_code_util.m:
compiler/hlds_data.m:
compiler/hlds_goal.m:
compiler/hlds_out.m:
compiler/inlining.m:
compiler/intermod.m:
compiler/make.dependencies.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make.util.m:
compiler/make_hlds_passes.m:
compiler/mercury_compile.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_optimize.m:
compiler/ml_switch_gen.m:
compiler/ml_tailcall.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen.m:
compiler/mlds_to_c.m:
compiler/mlds_to_gcc.m:
compiler/mlds_to_il.m:
compiler/mlds_to_ilasm.m:
compiler/mlds_to_java.m:
compiler/mlds_to_managed.m:
compiler/modes.m:
compiler/module_qual.m:
compiler/modules.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/polymorphism.m:
compiler/pragma_c_gen.m:
compiler/proc_label.m:
compiler/prog_data.m:
compiler/prog_foreign.m:
compiler/prog_item.m:
compiler/prog_mutable.m:
compiler/prog_out.m:
compiler/prog_rep.m:
compiler/prog_util.m:
compiler/recompilation.version.m:
compiler/size_prof.m:
compiler/special_pred.m:
compiler/switch_util.m:
compiler/transform_llds.m:
compiler/tupling.m:
compiler/type_ctor_info.m:
compiler/unify_gen.m:
Conform to the changes above, and/or improve some comments.
mdbcomp/prim_data.m:
Make the names of the function symbols of the proc_label type more
expressive and less ambiguous.
mdbcomp/prim_data.m:
mdbcomp/mdbcomp.m:
mdbcomp/program_representation.m:
mdbcomp/rtti_access.m:
mdbcomp/slice_and_dice.m:
mdbcomp/trace_counts.m:
Use . instead of __ as module qualifier.
Conform to the change to prim_data.m.
browser/declarative_execution.m:
browser/declarative_oracle.m:
browser/declarative_tree.m:
Conform the change to mdbcomp/prim_data.m.
tests/debugger/Mercury.options:
Don't specify --allow-table-reset for fib.m, since that option
doesn't exist anymore.
tests/debugger/fib.m:
Use the new mechanism for resetting the table.
tests/debugger/print_table.m:
Use the new syntax for pragma memo attributes.
tests/invalid/specified.{m,err_exp}:
Use to the new syntax and reset method for pragma memo attributes.
Test the handling of errors in the new attribute syntax.
tests/tabling/Mercury.options:
Don't specify --allow-table-reset for specified.m, since that option
doesn't exist anymore.
tests/tabling/specified.m:
Use the new syntax for pragma memo attributes, and use the new
mechanism for resetting tables. We could also use this test case
for testing the printing of statistics, but the format of that
output is still not final.
tests/tabling/fast_loose.m:
Use the new syntax for pragma memo attributes, and use the new
mechanism for resetting tables.
trace/mercury_trace.c:
trace/mercury_trace_cmd_developer.c:
Conform to the changes in the RTTI data structures regarding tabling.
Remove underscores from the names of some types that the style guide
says shouldn't be there.
library/robdd.m:
Comment out the tabling pragma until this change is bootstrapped.
Without this, the conflict between the old calls to macros generated
by the existing compiler and the new definition of those macros
in the runtime would cause errors from the C compiler.
1918 lines
68 KiB
Mathematica
1918 lines
68 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2002-2006 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: compile_target_code.m.
|
|
% Main authors: fjh, stayl.
|
|
%
|
|
% Code to compile the generated `.c', `.s', `.o', etc, files.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module backend_libs.compile_target_code.
|
|
:- interface.
|
|
|
|
:- import_module parse_tree.prog_io.
|
|
:- import_module parse_tree.modules.
|
|
:- import_module libs.globals.
|
|
:- import_module mdbcomp.prim_data.
|
|
|
|
:- import_module bool.
|
|
:- import_module io.
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Are we generating position independent code (for use in a shared
|
|
% library)? On some architectures, pic and non-pic code are incompatible,
|
|
% so we need to generate `.o' and `.pic_o' files.
|
|
%
|
|
:- type pic
|
|
---> pic
|
|
; link_with_pic
|
|
; non_pic.
|
|
|
|
% compile_c_file(ErrorStream, PIC, CFile, ObjFile, Succeeded)
|
|
%
|
|
:- pred compile_c_file(io.output_stream::in, pic::in, string::in, string::in,
|
|
bool::out, io::di, io::uo) is det.
|
|
|
|
% compile_c_file(ErrorStream, PIC, ModuleName, Succeeded)
|
|
%
|
|
:- pred compile_c_file(io.output_stream::in, pic::in, module_name::in,
|
|
bool::out, io::di, io::uo) is det.
|
|
|
|
% assemble(ErrorStream, PIC, ModuleName, Succeeded)
|
|
%
|
|
:- pred assemble(io.output_stream::in, pic::in, module_name::in,
|
|
bool::out, io::di, io::uo) is det.
|
|
|
|
% compile_java_file(ErrorStream, JavaFile, Succeeded)
|
|
%
|
|
:- pred compile_java_file(io.output_stream::in, string::in, bool::out,
|
|
io::di, io::uo) is det.
|
|
|
|
% il_assemble(ErrorStream, ModuleName, HasMain, Succeeded)
|
|
%
|
|
:- pred il_assemble(io.output_stream::in, module_name::in, has_main::in,
|
|
bool::out, io::di, io::uo) is det.
|
|
|
|
% il_assemble(ErrorStream, ILFile, DLLFile, HasMain, Succeeded)
|
|
%
|
|
:- pred il_assemble(io.output_stream::in, file_name::in, file_name::in,
|
|
has_main::in, bool::out, io::di, io::uo) is det.
|
|
|
|
% compile_managed_cplusplus_file(ErrorStream, MCPPFile, DLLFile, Succeeded)
|
|
%
|
|
:- pred compile_managed_cplusplus_file(io.output_stream::in,
|
|
file_name::in, file_name::in, bool::out, io::di, io::uo) is det.
|
|
|
|
% compile_csharp_file(ErrorStream, C#File, DLLFile, Succeeded)
|
|
%
|
|
:- pred compile_csharp_file(io.output_stream::in, module_imports::in,
|
|
file_name::in, file_name::in, bool::out, io::di, io::uo) is det.
|
|
|
|
% make_init_file(ErrorStream, MainModuleName, ModuleNames, Succeeded):
|
|
%
|
|
% Make the `.init' file for a library containing the given modules.
|
|
%
|
|
:- pred make_init_file(io.output_stream::in, module_name::in,
|
|
list(module_name)::in, bool::out, io::di, io::uo) is det.
|
|
|
|
% make_init_obj_file(ErrorStream, MainModuleName, AllModuleNames,
|
|
% MaybeInitObjFileName)
|
|
%
|
|
:- pred make_init_obj_file(io.output_stream::in, module_name::in,
|
|
list(module_name)::in, maybe(file_name)::out, io::di, io::uo) is det.
|
|
|
|
:- type linked_target_type
|
|
---> executable
|
|
; static_library
|
|
; shared_library
|
|
; java_archive.
|
|
|
|
% link(TargetType, MainModuleName, ObjectFileNames, Succeeded)
|
|
%
|
|
:- pred link(io.output_stream::in, linked_target_type::in, module_name::in,
|
|
list(string)::in, bool::out, io::di, io::uo) is det.
|
|
|
|
% post_link_make_symlink_or_copy(TargetType, MainModuleName, Succeeded)
|
|
%
|
|
% If `--use-grade-subdirs' is enabled, link or copy the executable or
|
|
% library into the user's directory after having successfully built it.
|
|
%
|
|
:- pred post_link_make_symlink_or_copy(io.output_stream::in,
|
|
linked_target_type::in, module_name::in, bool::out, io::di, io::uo) is det.
|
|
|
|
% link_module_list(ModulesToLink, FactTableObjFiles, Succeeded):
|
|
%
|
|
% The elements of ModulesToLink are the output of
|
|
% `module_name_to_filename(ModuleName, "", no, ModuleToLink)'
|
|
% for each module in the program.
|
|
%
|
|
:- pred link_module_list(list(string)::in, list(string)::in, bool::out,
|
|
io::di, io::uo) is det.
|
|
|
|
% shared_libraries_supported(SharedLibsSupported, !IO)
|
|
%
|
|
% Return whether or not shared libraries are supported on the current
|
|
% platform.
|
|
%
|
|
:- pred shared_libraries_supported(bool::out, io::di, io::uo) is det.
|
|
|
|
% get_object_code_type(TargetType, PIC):
|
|
%
|
|
% Work out whether we should be generating position-independent
|
|
% object code.
|
|
%
|
|
:- pred get_object_code_type(linked_target_type::in, pic::out, io::di, io::uo)
|
|
is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% make_all_module_command(CommandName, MainModule, AllModuleNames,
|
|
% CommandString):
|
|
%
|
|
% Create a command string which passes the source file names
|
|
% for AllModuleNames to CommandName, with MainModule given first.
|
|
%
|
|
:- pred make_all_module_command(string::in, module_name::in,
|
|
list(module_name)::in, string::out, io::di, io::uo) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% maybe_pic_object_file_extension(Globals, PIC, Ext) is true iff
|
|
% Ext is the extension which should be used on object files according to
|
|
% the value of PIC. The value of PIC should be obtained from a call to
|
|
% `get_object_code_type'. In particular, on architectures for which
|
|
% no special handling for PIC is necessary, only a value of `non_pic'
|
|
% should be used. The `(in, out, in)' mode guarantees that the returned
|
|
% value of PIC meets this requirement.
|
|
%
|
|
:- pred maybe_pic_object_file_extension(globals, pic, string).
|
|
:- mode maybe_pic_object_file_extension(in, in, out) is det.
|
|
:- mode maybe_pic_object_file_extension(in, out, in) is semidet.
|
|
|
|
% Same as above except the globals are obtained from the io.state.
|
|
%
|
|
:- pred maybe_pic_object_file_extension(pic::in, string::out, io::di, io::uo)
|
|
is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module backend_libs.foreign.
|
|
:- import_module backend_libs.name_mangle.
|
|
:- import_module hlds.passes_aux.
|
|
:- import_module libs.compiler_util.
|
|
:- import_module libs.globals.
|
|
:- import_module libs.handle_options.
|
|
:- import_module libs.options.
|
|
:- import_module libs.trace_params.
|
|
:- import_module parse_tree.error_util.
|
|
:- import_module parse_tree.prog_foreign.
|
|
:- import_module parse_tree.prog_out.
|
|
|
|
:- import_module char.
|
|
:- import_module dir.
|
|
:- import_module getopt_io.
|
|
:- import_module int.
|
|
:- import_module string.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
il_assemble(ErrorStream, ModuleName, HasMain, Succeeded, !IO) :-
|
|
module_name_to_file_name(ModuleName, ".il", no, IL_File, !IO),
|
|
module_name_to_file_name(ModuleName, ".dll", yes, DllFile, !IO),
|
|
|
|
% If the module contains main/2 then we it should be built as an
|
|
% executable. Unfortunately MC++ or C# code may refer to the dll
|
|
% so we always need to build the dll.
|
|
%
|
|
il_assemble(ErrorStream, IL_File, DllFile, no_main, DllSucceeded, !IO),
|
|
(
|
|
HasMain = has_main,
|
|
module_name_to_file_name(ModuleName, ".exe", yes, ExeFile, !IO),
|
|
il_assemble(ErrorStream, IL_File, ExeFile, HasMain, ExeSucceeded, !IO),
|
|
Succeeded = DllSucceeded `and` ExeSucceeded
|
|
;
|
|
HasMain = no_main,
|
|
Succeeded = DllSucceeded
|
|
).
|
|
|
|
il_assemble(ErrorStream, IL_File, TargetFile, HasMain, Succeeded, !IO) :-
|
|
globals.io_lookup_bool_option(verbose, Verbose, !IO),
|
|
globals.io_lookup_bool_option(sign_assembly, SignAssembly, !IO),
|
|
maybe_write_string(Verbose, "% Assembling `", !IO),
|
|
maybe_write_string(Verbose, IL_File, !IO),
|
|
maybe_write_string(Verbose, "':\n", !IO),
|
|
globals.io_lookup_string_option(il_assembler, ILASM, !IO),
|
|
globals.io_lookup_accumulating_option(ilasm_flags, ILASMFlagsList, !IO),
|
|
join_string_list(ILASMFlagsList, "", "", " ", ILASMFlags),
|
|
(
|
|
SignAssembly = yes,
|
|
SignOpt = "/keyf=mercury.sn "
|
|
;
|
|
SignAssembly = no,
|
|
SignOpt = ""
|
|
),
|
|
(
|
|
Verbose = yes,
|
|
VerboseOpt = ""
|
|
;
|
|
Verbose = no,
|
|
VerboseOpt = "/quiet "
|
|
),
|
|
globals.io_lookup_bool_option(target_debug, Debug, !IO),
|
|
(
|
|
Debug = yes,
|
|
DebugOpt = "/debug "
|
|
;
|
|
Debug = no,
|
|
DebugOpt = ""
|
|
),
|
|
(
|
|
HasMain = has_main,
|
|
TargetOpt = ""
|
|
;
|
|
HasMain = no_main,
|
|
TargetOpt = "/dll "
|
|
),
|
|
string.append_list([ILASM, " ", SignOpt, VerboseOpt, DebugOpt,
|
|
TargetOpt, ILASMFlags, " /out=", TargetFile, " ", IL_File], Command),
|
|
invoke_system_command(ErrorStream, verbose_commands, Command, Succeeded,
|
|
!IO).
|
|
|
|
compile_managed_cplusplus_file(ErrorStream, MCPPFileName, DLLFileName,
|
|
Succeeded, !IO) :-
|
|
globals.io_lookup_bool_option(verbose, Verbose, !IO),
|
|
maybe_write_string(Verbose, "% Compiling `", !IO),
|
|
maybe_write_string(Verbose, MCPPFileName, !IO),
|
|
maybe_write_string(Verbose, "':\n", !IO),
|
|
globals.io_lookup_string_option(mcpp_compiler, MCPP, !IO),
|
|
globals.io_lookup_accumulating_option(mcpp_flags, MCPPFlagsList, !IO),
|
|
join_string_list(MCPPFlagsList, "", "", " ", MCPPFlags),
|
|
globals.io_lookup_bool_option(target_debug, Debug, !IO),
|
|
(
|
|
Debug = yes,
|
|
DebugOpt = "/Zi "
|
|
;
|
|
Debug = no,
|
|
DebugOpt = ""
|
|
),
|
|
|
|
% XXX Should we introduce a `--mcpp-include-directory' option?
|
|
globals.io_lookup_accumulating_option(c_include_directory,
|
|
C_Incl_Dirs, !IO),
|
|
InclOpts = string.append_list(list.condense(list.map(
|
|
(func(C_INCL) = ["-I", C_INCL, " "]), C_Incl_Dirs))),
|
|
|
|
% XXX Should we use a separate dll_directories options?
|
|
globals.io_lookup_accumulating_option(link_library_directories,
|
|
DLLDirs, !IO),
|
|
DLLDirOpts = "-AIMercury/dlls " ++
|
|
string.append_list(list.condense(list.map(
|
|
(func(DLLDir) = ["-AI", DLLDir, " "]), DLLDirs))),
|
|
|
|
string.append_list([MCPP, " -CLR ", DebugOpt, InclOpts, DLLDirOpts,
|
|
MCPPFlags, " ", MCPPFileName, " -LD -o ", DLLFileName], Command),
|
|
invoke_system_command(ErrorStream, verbose_commands, Command,
|
|
Succeeded, !IO).
|
|
|
|
compile_csharp_file(ErrorStream, Imports, CSharpFileName0, DLLFileName,
|
|
Succeeded, !IO) :-
|
|
globals.io_lookup_bool_option(verbose, Verbose, !IO),
|
|
maybe_write_string(Verbose, "% Compiling `", !IO),
|
|
maybe_write_string(Verbose, CSharpFileName, !IO),
|
|
maybe_write_string(Verbose, "':\n", !IO),
|
|
globals.io_lookup_string_option(csharp_compiler, CSC, !IO),
|
|
globals.io_lookup_accumulating_option(csharp_flags, CSCFlagsList, !IO),
|
|
join_string_list(CSCFlagsList, "", "", " ", CSCFlags),
|
|
|
|
% XXX This is because the MS C# compiler doesn't understand
|
|
% / as a directory separator.
|
|
CSharpFileName = string.replace_all(CSharpFileName0, "/", "\\\\"),
|
|
|
|
globals.io_lookup_bool_option(target_debug, Debug, !IO),
|
|
(
|
|
Debug = yes,
|
|
% XXX This needs testing before it can be enabled (see the comments
|
|
% for install_debug_library in library/Mmakefile).
|
|
|
|
% DebugOpt = "/debug+ /debug:full "
|
|
DebugOpt = ""
|
|
;
|
|
Debug = no,
|
|
DebugOpt = ""
|
|
),
|
|
|
|
% XXX Should we use a separate dll_directories options?
|
|
globals.io_lookup_accumulating_option(link_library_directories, DLLDirs,
|
|
!IO),
|
|
DLLDirOpts = "/lib:Mercury/dlls " ++
|
|
string.append_list(list.condense(list.map(
|
|
(func(DLLDir) = ["/lib:", DLLDir, " "]), DLLDirs))),
|
|
|
|
( mercury_std_library_module_name(Imports ^ module_name) ->
|
|
Prefix = "/addmodule:"
|
|
;
|
|
Prefix = "/r:"
|
|
),
|
|
ForeignDeps = list.map(
|
|
(func(M) = foreign_import_module_name(M, Imports ^ module_name)),
|
|
Imports ^ foreign_import_module_info ),
|
|
ReferencedDlls = referenced_dlls(Imports ^ module_name,
|
|
Imports ^ int_deps ++ Imports ^ impl_deps ++ ForeignDeps),
|
|
list.map_foldl(
|
|
(pred(Mod::in, Result::out, IO0::di, IO::uo) is det :-
|
|
module_name_to_file_name(Mod, ".dll", no, FileName, IO0, IO),
|
|
Result = [Prefix, FileName, " "]
|
|
), ReferencedDlls, ReferencedDllsList, !IO),
|
|
ReferencedDllsStr = string.append_list(
|
|
list.condense(ReferencedDllsList)),
|
|
|
|
string.append_list([CSC, DebugOpt,
|
|
" /t:library ", DLLDirOpts, CSCFlags, ReferencedDllsStr,
|
|
" /out:", DLLFileName, " ", CSharpFileName], Command),
|
|
invoke_system_command(ErrorStream, verbose_commands, Command,
|
|
Succeeded, !IO).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% WARNING: The code here duplicates the functionality of scripts/mgnuc.in.
|
|
% Any changes there may also require changes here, and vice versa.
|
|
|
|
:- type compiler_type
|
|
---> gcc
|
|
; lcc
|
|
; cl
|
|
; unknown.
|
|
|
|
compile_c_file(ErrorStream, PIC, ModuleName, Succeeded, !IO) :-
|
|
module_name_to_file_name(ModuleName, ".c", yes, C_File, !IO),
|
|
maybe_pic_object_file_extension(PIC, ObjExt, !IO),
|
|
module_name_to_file_name(ModuleName, ObjExt, yes, O_File, !IO),
|
|
compile_c_file(ErrorStream, PIC, C_File, O_File, Succeeded, !IO).
|
|
|
|
compile_c_file(ErrorStream, PIC, C_File, O_File, Succeeded, !IO) :-
|
|
globals.io_lookup_bool_option(verbose, Verbose, !IO),
|
|
globals.io_lookup_string_option(c_flag_to_name_object_file,
|
|
NameObjectFile, !IO),
|
|
maybe_write_string(Verbose, "% Compiling `", !IO),
|
|
maybe_write_string(Verbose, C_File, !IO),
|
|
maybe_write_string(Verbose, "':\n", !IO),
|
|
globals.io_lookup_string_option(cc, CC, !IO),
|
|
globals.io_lookup_accumulating_option(cflags, C_Flags_List, !IO),
|
|
join_string_list(C_Flags_List, "", "", " ", CFLAGS),
|
|
|
|
globals.io_lookup_bool_option(use_subdirs, UseSubdirs, !IO),
|
|
(
|
|
UseSubdirs = yes,
|
|
% The source file (foo.c) will be compiled in a subdirectory
|
|
% (either Mercury/cs, foo.dir, or Mercury/dirs/foo.dir, depending
|
|
% on which of these two options is set) so we need to add `-I.'
|
|
% so it can include header files in the source directory.
|
|
SubDirInclOpt = "-I. "
|
|
;
|
|
UseSubdirs = no,
|
|
SubDirInclOpt = ""
|
|
),
|
|
globals.io_lookup_accumulating_option(c_include_directory,
|
|
C_Incl_Dirs, !IO),
|
|
InclOpt = string.append_list(list.condense(list.map(
|
|
(func(C_INCL) = ["-I", quote_arg(C_INCL), " "] ), C_Incl_Dirs))),
|
|
globals.io_lookup_bool_option(highlevel_code, HighLevelCode, !IO),
|
|
(
|
|
HighLevelCode = yes,
|
|
HighLevelCodeOpt = "-DMR_HIGHLEVEL_CODE "
|
|
;
|
|
HighLevelCode = no,
|
|
HighLevelCodeOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(gcc_nested_functions,
|
|
GCC_NestedFunctions, !IO),
|
|
(
|
|
GCC_NestedFunctions = yes,
|
|
NestedFunctionsOpt = "-DMR_USE_GCC_NESTED_FUNCTIONS "
|
|
;
|
|
GCC_NestedFunctions = no,
|
|
NestedFunctionsOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(highlevel_data, HighLevelData, !IO),
|
|
(
|
|
HighLevelData = yes,
|
|
HighLevelDataOpt = "-DMR_HIGHLEVEL_DATA "
|
|
;
|
|
HighLevelData = no,
|
|
HighLevelDataOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(gcc_global_registers, GCC_Regs, !IO),
|
|
(
|
|
GCC_Regs = yes,
|
|
globals.io_lookup_string_option(cflags_for_regs, CFLAGS_FOR_REGS,
|
|
!IO),
|
|
RegOpt = "-DMR_USE_GCC_GLOBAL_REGISTERS "
|
|
;
|
|
GCC_Regs = no,
|
|
CFLAGS_FOR_REGS = "",
|
|
RegOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(gcc_non_local_gotos, GCC_Gotos, !IO),
|
|
(
|
|
GCC_Gotos = yes,
|
|
GotoOpt = "-DMR_USE_GCC_NONLOCAL_GOTOS ",
|
|
globals.io_lookup_string_option(cflags_for_gotos,
|
|
CFLAGS_FOR_GOTOS, !IO)
|
|
;
|
|
GCC_Gotos = no,
|
|
GotoOpt = "",
|
|
CFLAGS_FOR_GOTOS = ""
|
|
),
|
|
globals.io_lookup_bool_option(asm_labels, ASM_Labels, !IO),
|
|
(
|
|
ASM_Labels = yes,
|
|
AsmOpt = "-DMR_USE_ASM_LABELS "
|
|
;
|
|
ASM_Labels = no,
|
|
AsmOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(parallel, Parallel, !IO),
|
|
(
|
|
Parallel = yes,
|
|
globals.io_lookup_string_option(cflags_for_threads,
|
|
CFLAGS_FOR_THREADS, !IO)
|
|
;
|
|
Parallel = no,
|
|
CFLAGS_FOR_THREADS = ""
|
|
),
|
|
globals.io_get_gc_method(GC_Method, !IO),
|
|
(
|
|
GC_Method = automatic,
|
|
GC_Opt = ""
|
|
;
|
|
GC_Method = none,
|
|
GC_Opt = ""
|
|
;
|
|
GC_Method = boehm,
|
|
GC_Opt = "-DMR_CONSERVATIVE_GC -DMR_BOEHM_GC "
|
|
;
|
|
GC_Method = mps,
|
|
GC_Opt = "-DMR_CONSERVATIVE_GC -DMR_MPS_GC "
|
|
;
|
|
GC_Method = accurate,
|
|
GC_Opt = "-DMR_NATIVE_GC "
|
|
),
|
|
globals.io_lookup_bool_option(profile_calls, ProfileCalls, !IO),
|
|
(
|
|
ProfileCalls = yes,
|
|
ProfileCallsOpt = "-DMR_MPROF_PROFILE_CALLS "
|
|
;
|
|
ProfileCalls = no,
|
|
ProfileCallsOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(profile_time, ProfileTime, !IO),
|
|
(
|
|
ProfileTime = yes,
|
|
ProfileTimeOpt = "-DMR_MPROF_PROFILE_TIME "
|
|
;
|
|
ProfileTime = no,
|
|
ProfileTimeOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(profile_memory, ProfileMemory, !IO),
|
|
(
|
|
ProfileMemory = yes,
|
|
ProfileMemoryOpt = "-DMR_MPROF_PROFILE_MEMORY "
|
|
;
|
|
ProfileMemory = no,
|
|
ProfileMemoryOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(profile_deep, ProfileDeep, !IO),
|
|
(
|
|
ProfileDeep = yes,
|
|
ProfileDeepOpt = "-DMR_DEEP_PROFILING "
|
|
;
|
|
ProfileDeep = no,
|
|
ProfileDeepOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(record_term_sizes_as_words,
|
|
RecordTermSizesAsWords, !IO),
|
|
globals.io_lookup_bool_option(record_term_sizes_as_cells,
|
|
RecordTermSizesAsCells, !IO),
|
|
(
|
|
RecordTermSizesAsWords = yes,
|
|
RecordTermSizesAsCells = yes,
|
|
% this should have been caught in handle_options
|
|
unexpected(this_file,
|
|
"compile_c_file: inconsistent record term size options")
|
|
;
|
|
RecordTermSizesAsWords = yes,
|
|
RecordTermSizesAsCells = no,
|
|
RecordTermSizesOpt = "-DMR_RECORD_TERM_SIZES "
|
|
;
|
|
RecordTermSizesAsWords = no,
|
|
RecordTermSizesAsCells = yes,
|
|
RecordTermSizesOpt = "-DMR_RECORD_TERM_SIZES " ++
|
|
"-DMR_RECORD_TERM_SIZES_AS_CELLS "
|
|
;
|
|
RecordTermSizesAsWords = no,
|
|
RecordTermSizesAsCells = no,
|
|
RecordTermSizesOpt = ""
|
|
),
|
|
(
|
|
PIC = pic,
|
|
globals.io_lookup_string_option(cflags_for_pic, CFLAGS_FOR_PIC, !IO),
|
|
PIC_Reg = yes
|
|
;
|
|
PIC = link_with_pic,
|
|
CFLAGS_FOR_PIC = "",
|
|
PIC_Reg = yes
|
|
;
|
|
PIC = non_pic,
|
|
CFLAGS_FOR_PIC = "",
|
|
globals.io_lookup_bool_option(pic_reg, PIC_Reg, !IO)
|
|
),
|
|
(
|
|
PIC_Reg = yes,
|
|
% This will be ignored for architectures/grades where use of position
|
|
% independent code does not reserve a register.
|
|
PIC_Reg_Opt = "-DMR_PIC_REG "
|
|
;
|
|
PIC_Reg = no,
|
|
PIC_Reg_Opt = ""
|
|
),
|
|
|
|
globals.io_get_tags_method(Tags_Method, !IO),
|
|
( Tags_Method = high ->
|
|
TagsOpt = "-DMR_HIGHTAGS "
|
|
;
|
|
TagsOpt = ""
|
|
),
|
|
globals.io_lookup_int_option(num_tag_bits, NumTagBits, !IO),
|
|
string.int_to_string(NumTagBits, NumTagBitsString),
|
|
string.append_list(["-DMR_TAGBITS=", NumTagBitsString, " "],
|
|
NumTagBitsOpt),
|
|
globals.io_lookup_bool_option(decl_debug, DeclDebug, !IO),
|
|
(
|
|
DeclDebug = yes,
|
|
DeclDebugOpt = "-DMR_DECL_DEBUG "
|
|
;
|
|
DeclDebug = no,
|
|
DeclDebugOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(exec_trace, ExecTrace, !IO),
|
|
(
|
|
ExecTrace = yes,
|
|
ExecTraceOpt = "-DMR_EXEC_TRACE "
|
|
;
|
|
ExecTrace = no,
|
|
ExecTraceOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(extend_stacks_when_needed, Extend, !IO),
|
|
(
|
|
Extend = yes,
|
|
ExtendOpt = "-DMR_EXTEND_STACKS_WHEN_NEEDED "
|
|
;
|
|
Extend = no,
|
|
ExtendOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(target_debug, Target_Debug, !IO),
|
|
(
|
|
Target_Debug = yes,
|
|
globals.io_lookup_string_option(cflags_for_debug, Target_DebugOpt0,
|
|
!IO),
|
|
string.append(Target_DebugOpt0, " ", Target_DebugOpt)
|
|
;
|
|
Target_Debug = no,
|
|
Target_DebugOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(low_level_debug, LL_Debug, !IO),
|
|
(
|
|
LL_Debug = yes,
|
|
LL_DebugOpt = "-DMR_LOW_LEVEL_DEBUG "
|
|
;
|
|
LL_Debug = no,
|
|
LL_DebugOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(use_trail, UseTrail, !IO),
|
|
(
|
|
UseTrail = yes,
|
|
UseTrailOpt = "-DMR_USE_TRAIL "
|
|
;
|
|
UseTrail = no,
|
|
UseTrailOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(reserve_tag, ReserveTag, !IO),
|
|
(
|
|
ReserveTag = yes,
|
|
ReserveTagOpt = "-DMR_RESERVE_TAG "
|
|
;
|
|
ReserveTag = no,
|
|
ReserveTagOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(use_minimal_model_stack_copy,
|
|
MinimalModelStackCopy, !IO),
|
|
globals.io_lookup_bool_option(use_minimal_model_own_stacks,
|
|
MinimalModelOwnStacks, !IO),
|
|
(
|
|
MinimalModelStackCopy = yes,
|
|
MinimalModelOwnStacks = yes,
|
|
% this should have been caught in handle_options
|
|
unexpected(this_file,
|
|
"compile_c_file: inconsistent minimal model options")
|
|
;
|
|
MinimalModelStackCopy = yes,
|
|
MinimalModelOwnStacks = no,
|
|
MinimalModelBaseOpt = "-DMR_USE_MINIMAL_MODEL_STACK_COPY "
|
|
;
|
|
MinimalModelStackCopy = no,
|
|
MinimalModelOwnStacks = yes,
|
|
MinimalModelBaseOpt = "-DMR_USE_MINIMAL_MODEL_OWN_STACKS "
|
|
;
|
|
MinimalModelStackCopy = no,
|
|
MinimalModelOwnStacks = no,
|
|
MinimalModelBaseOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(minimal_model_debug, MinimalModelDebug,
|
|
!IO),
|
|
(
|
|
MinimalModelDebug = yes,
|
|
( MinimalModelBaseOpt = "" ->
|
|
% We ignore the debug flag unless one of the base flags is set.
|
|
MinimalModelOpt = MinimalModelBaseOpt
|
|
;
|
|
MinimalModelOpt = MinimalModelBaseOpt ++ "-DMR_MINIMAL_MODEL_DEBUG"
|
|
)
|
|
;
|
|
MinimalModelDebug = no,
|
|
MinimalModelOpt = MinimalModelBaseOpt
|
|
),
|
|
globals.io_lookup_bool_option(type_layout, TypeLayoutOption, !IO),
|
|
(
|
|
TypeLayoutOption = no,
|
|
TypeLayoutOpt = "-DMR_NO_TYPE_LAYOUT "
|
|
;
|
|
TypeLayoutOption = yes,
|
|
TypeLayoutOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(c_optimize, C_optimize, !IO),
|
|
(
|
|
C_optimize = yes,
|
|
globals.io_lookup_string_option(cflags_for_optimization, OptimizeOpt,
|
|
!IO)
|
|
;
|
|
C_optimize = no,
|
|
OptimizeOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(ansi_c, Ansi, !IO),
|
|
(
|
|
Ansi = yes,
|
|
globals.io_lookup_string_option(cflags_for_ansi, AnsiOpt, !IO)
|
|
;
|
|
Ansi = no,
|
|
AnsiOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(inline_alloc, InlineAlloc, !IO),
|
|
(
|
|
InlineAlloc = yes,
|
|
InlineAllocOpt = "-DMR_INLINE_ALLOC -DSILENT "
|
|
;
|
|
InlineAlloc = no,
|
|
InlineAllocOpt = ""
|
|
),
|
|
globals.io_lookup_bool_option(warn_target_code, Warn, !IO),
|
|
(
|
|
Warn = yes,
|
|
globals.io_lookup_string_option(cflags_for_warnings,
|
|
WarningOpt, !IO)
|
|
;
|
|
Warn = no,
|
|
WarningOpt = ""
|
|
),
|
|
|
|
% The -floop-optimize option is incompatible with the global
|
|
% register code we generate on Darwin PowerPC.
|
|
% See the hard_coded/ppc_bug test case for an example
|
|
% program which fails with this optimization.
|
|
|
|
globals.io_lookup_string_option(fullarch, FullArch, !IO),
|
|
(
|
|
HighLevelCode = no,
|
|
GCC_Regs = yes,
|
|
string.prefix(FullArch, "powerpc-apple-darwin")
|
|
->
|
|
AppleGCCRegWorkaroundOpt = "-fno-loop-optimize"
|
|
;
|
|
AppleGCCRegWorkaroundOpt = ""
|
|
),
|
|
|
|
% Be careful with the order here! Some options override others,
|
|
% e.g. CFLAGS_FOR_REGS must come after OptimizeOpt so that
|
|
% it can override -fomit-frame-pointer with -fno-omit-frame-pointer.
|
|
% Also be careful that each option is separated by spaces.
|
|
string.append_list([
|
|
CC, " ",
|
|
SubDirInclOpt, InclOpt,
|
|
OptimizeOpt, " ",
|
|
HighLevelCodeOpt,
|
|
NestedFunctionsOpt,
|
|
HighLevelDataOpt,
|
|
RegOpt, GotoOpt, AsmOpt,
|
|
CFLAGS_FOR_REGS, " ", CFLAGS_FOR_GOTOS, " ",
|
|
CFLAGS_FOR_THREADS, " ", CFLAGS_FOR_PIC, " ",
|
|
GC_Opt,
|
|
ProfileCallsOpt, ProfileTimeOpt,
|
|
ProfileMemoryOpt, ProfileDeepOpt,
|
|
RecordTermSizesOpt,
|
|
PIC_Reg_Opt,
|
|
TagsOpt, NumTagBitsOpt,
|
|
ExtendOpt,
|
|
Target_DebugOpt, LL_DebugOpt, DeclDebugOpt, ExecTraceOpt,
|
|
UseTrailOpt,
|
|
ReserveTagOpt,
|
|
MinimalModelOpt,
|
|
TypeLayoutOpt,
|
|
InlineAllocOpt, " ",
|
|
AnsiOpt, " ",
|
|
AppleGCCRegWorkaroundOpt, " ",
|
|
WarningOpt, " ",
|
|
CFLAGS,
|
|
" -c ", C_File, " ",
|
|
NameObjectFile, O_File], Command),
|
|
invoke_system_command(ErrorStream, verbose_commands,
|
|
Command, Succeeded, !IO).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
compile_java_file(ErrorStream, JavaFile, Succeeded, !IO) :-
|
|
globals.io_lookup_bool_option(verbose, Verbose, !IO),
|
|
maybe_write_string(Verbose, "% Compiling `", !IO),
|
|
maybe_write_string(Verbose, JavaFile, !IO),
|
|
maybe_write_string(Verbose, "':\n", !IO),
|
|
globals.io_lookup_string_option(java_compiler, JavaCompiler, !IO),
|
|
globals.io_lookup_accumulating_option(java_flags, JavaFlagsList, !IO),
|
|
join_string_list(JavaFlagsList, "", "", " ", JAVAFLAGS),
|
|
|
|
globals.io_lookup_accumulating_option(java_classpath, Java_Incl_Dirs,
|
|
!IO),
|
|
% XXX PathSeparator should be ";" on Windows
|
|
PathSeparator = ":",
|
|
% We prepend the current CLASSPATH to preserve the accumulating
|
|
% nature of this variable.
|
|
get_env_classpath(EnvClasspath, !IO),
|
|
join_string_list([EnvClasspath|Java_Incl_Dirs], "", "",
|
|
PathSeparator, ClassPath),
|
|
( ClassPath = "" ->
|
|
InclOpt = ""
|
|
;
|
|
InclOpt = string.append_list([
|
|
"-classpath ", quote_arg(ClassPath), " "])
|
|
),
|
|
|
|
globals.io_lookup_bool_option(target_debug, Target_Debug, !IO),
|
|
(
|
|
Target_Debug = yes,
|
|
Target_DebugOpt = "-g "
|
|
;
|
|
Target_Debug = no,
|
|
Target_DebugOpt = ""
|
|
),
|
|
|
|
globals.io_lookup_bool_option(use_subdirs, UseSubdirs, !IO),
|
|
globals.io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs, !IO),
|
|
globals.io_lookup_string_option(fullarch, FullArch, !IO),
|
|
globals.io_get_globals(Globals, !IO),
|
|
(
|
|
UseSubdirs = yes,
|
|
(
|
|
UseGradeSubdirs = yes,
|
|
grade_directory_component(Globals, Grade),
|
|
DirName = "Mercury"/Grade/FullArch/"Mercury"/"classs"
|
|
;
|
|
UseGradeSubdirs = no,
|
|
DirName = "Mercury"/"classs"
|
|
),
|
|
% Javac won't create the destination directory for class files,
|
|
% so we need to do it.
|
|
dir.make_directory(DirName, _, !IO),
|
|
% Set destination directory for class files.
|
|
DestDir = "-d " ++ DirName ++ " "
|
|
;
|
|
UseSubdirs = no,
|
|
DestDir = ""
|
|
),
|
|
|
|
% Be careful with the order here! Some options may override others.
|
|
% Also be careful that each option is separated by spaces.
|
|
string.append_list([JavaCompiler, " ", InclOpt, DestDir,
|
|
Target_DebugOpt, JAVAFLAGS, " ", JavaFile], Command),
|
|
invoke_system_command(ErrorStream, verbose_commands, Command, Succeeded,
|
|
!IO).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
assemble(ErrorStream, PIC, ModuleName, Succeeded, !IO) :-
|
|
(
|
|
PIC = pic,
|
|
AsmExt = ".pic_s",
|
|
GCCFLAGS_FOR_ASM = "-x assembler ",
|
|
GCCFLAGS_FOR_PIC = "-fpic "
|
|
;
|
|
PIC = link_with_pic,
|
|
% `--target asm' doesn't support any grades for
|
|
% which `.lpic_o' files are needed.
|
|
unexpected(this_file, "assemble: link_with_pic")
|
|
;
|
|
PIC = non_pic,
|
|
AsmExt = ".s",
|
|
GCCFLAGS_FOR_ASM = "",
|
|
GCCFLAGS_FOR_PIC = ""
|
|
),
|
|
module_name_to_file_name(ModuleName, AsmExt, no, AsmFile, !IO),
|
|
maybe_pic_object_file_extension(PIC, ObjExt, !IO),
|
|
module_name_to_file_name(ModuleName, ObjExt, yes, ObjFile, !IO),
|
|
|
|
globals.io_lookup_bool_option(verbose, Verbose, !IO),
|
|
maybe_write_string(Verbose, "% Assembling `", !IO),
|
|
maybe_write_string(Verbose, AsmFile, !IO),
|
|
maybe_write_string(Verbose, "':\n", !IO),
|
|
% XXX should we use new asm_* options rather than
|
|
% reusing cc, cflags, c_flag_to_name_object_file?
|
|
globals.io_lookup_string_option(cc, CC, !IO),
|
|
globals.io_lookup_string_option(c_flag_to_name_object_file,
|
|
NameObjectFile, !IO),
|
|
globals.io_lookup_accumulating_option(cflags, C_Flags_List, !IO),
|
|
join_string_list(C_Flags_List, "", "", " ", CFLAGS),
|
|
% Be careful with the order here.
|
|
% Also be careful that each option is separated by spaces.
|
|
string.append_list([CC, " ", CFLAGS, " ", GCCFLAGS_FOR_PIC,
|
|
GCCFLAGS_FOR_ASM, "-c ", AsmFile, " ", NameObjectFile, ObjFile],
|
|
Command),
|
|
invoke_system_command(ErrorStream, verbose_commands, Command, Succeeded,
|
|
!IO).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
make_init_file(ErrorStream, MainModuleName, AllModules, Succeeded, !IO) :-
|
|
module_name_to_file_name(MainModuleName, ".init.tmp", yes, TmpInitFileName,
|
|
!IO),
|
|
io.open_output(TmpInitFileName, InitFileRes, !IO),
|
|
(
|
|
InitFileRes = ok(InitFileStream),
|
|
ModuleNameToCFileName =
|
|
(pred(ThisModule::in, CFileName::out, !.IO::di, !:IO::uo) is det :-
|
|
module_name_to_file_name(ThisModule, ".c", no, CFileName, !IO)
|
|
),
|
|
list.map_foldl(ModuleNameToCFileName, AllModules, AllCFilesList, !IO),
|
|
join_quoted_string_list(AllCFilesList, "", "", " ", CFileNames),
|
|
|
|
globals.io_lookup_string_option(mkinit_command, MkInit, !IO),
|
|
MkInitCmd = string.append_list(
|
|
[ MkInit,
|
|
" -k ",
|
|
" ", CFileNames
|
|
]),
|
|
invoke_system_command(InitFileStream, verbose, MkInitCmd, MkInitOK,
|
|
!IO),
|
|
|
|
(
|
|
MkInitOK = yes,
|
|
globals.io_lookup_maybe_string_option(extra_init_command,
|
|
MaybeInitFileCommand, !IO),
|
|
(
|
|
MaybeInitFileCommand = yes(InitFileCommand),
|
|
make_all_module_command(InitFileCommand, MainModuleName,
|
|
AllModules, CommandString, !IO),
|
|
invoke_system_command(InitFileStream, verbose_commands,
|
|
CommandString, Succeeded0, !IO)
|
|
;
|
|
MaybeInitFileCommand = no,
|
|
Succeeded0 = yes
|
|
)
|
|
;
|
|
MkInitOK = no,
|
|
Succeeded0 = no
|
|
),
|
|
|
|
io.close_output(InitFileStream, !IO),
|
|
module_name_to_file_name(MainModuleName, ".init", yes, InitFileName,
|
|
!IO),
|
|
update_interface_return_succeeded(InitFileName, Succeeded1, !IO),
|
|
Succeeded = Succeeded0 `and` Succeeded1
|
|
;
|
|
InitFileRes = error(Error),
|
|
io.progname_base("mercury_compile", ProgName, !IO),
|
|
io.write_string(ErrorStream, ProgName, !IO),
|
|
io.write_string(ErrorStream, ": can't open `", !IO),
|
|
io.write_string(ErrorStream, TmpInitFileName, !IO),
|
|
io.write_string(ErrorStream, "' for output:\n", !IO),
|
|
io.nl(ErrorStream, !IO),
|
|
io.write_string(ErrorStream, io.error_message(Error), !IO),
|
|
io.nl(ErrorStream, !IO),
|
|
Succeeded = no
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
link_module_list(Modules, FactTableObjFiles, Succeeded, !IO) :-
|
|
globals.io_lookup_string_option(output_file_name, OutputFileName0, !IO),
|
|
( OutputFileName0 = "" ->
|
|
(
|
|
Modules = [Module | _],
|
|
OutputFileName = Module
|
|
;
|
|
Modules = [],
|
|
unexpected(this_file, "link_module_list: no modules")
|
|
)
|
|
;
|
|
OutputFileName = OutputFileName0
|
|
),
|
|
|
|
file_name_to_module_name(OutputFileName, MainModuleName),
|
|
|
|
globals.io_lookup_bool_option(compile_to_shared_lib, CompileToSharedLib,
|
|
!IO),
|
|
TargetType = (CompileToSharedLib = yes -> shared_library ; executable),
|
|
get_object_code_type(TargetType, PIC, !IO),
|
|
maybe_pic_object_file_extension(PIC, Obj, !IO),
|
|
|
|
globals.io_get_target(Target, !IO),
|
|
io.output_stream(OutputStream, !IO),
|
|
( Target = target_asm ->
|
|
% For --target asm, we generate everything into a single object file.
|
|
(
|
|
Modules = [FirstModule | _],
|
|
join_module_list([FirstModule], Obj, ObjectsList, !IO)
|
|
;
|
|
Modules = [],
|
|
unexpected(this_file, "link_module_list: no modules")
|
|
)
|
|
;
|
|
join_module_list(Modules, Obj, ObjectsList, !IO)
|
|
),
|
|
( TargetType = executable ->
|
|
list.map(
|
|
(pred(ModuleStr::in, ModuleName::out) is det :-
|
|
file_name_to_module_name(dir.basename_det(ModuleStr),
|
|
ModuleName)
|
|
), Modules, ModuleNames),
|
|
MustCompile = yes,
|
|
make_init_obj_file(OutputStream, MustCompile, MainModuleName,
|
|
ModuleNames, InitObjResult, !IO)
|
|
;
|
|
InitObjResult = yes("")
|
|
),
|
|
(
|
|
InitObjResult = yes(InitObjFileName),
|
|
globals.io_lookup_accumulating_option(link_objects,
|
|
ExtraLinkObjectsList, !IO),
|
|
AllObjects0 = ObjectsList ++ ExtraLinkObjectsList
|
|
++ FactTableObjFiles,
|
|
AllObjects =
|
|
( InitObjFileName = "" ->
|
|
AllObjects0
|
|
;
|
|
[InitObjFileName | AllObjects0]
|
|
),
|
|
link(OutputStream, TargetType, MainModuleName, AllObjects,
|
|
Succeeded, !IO)
|
|
;
|
|
InitObjResult = no,
|
|
Succeeded = no
|
|
).
|
|
|
|
make_init_obj_file(ErrorStream, ModuleName, ModuleNames, Result, !IO) :-
|
|
globals.io_lookup_bool_option(rebuild, MustCompile, !IO),
|
|
make_init_obj_file(ErrorStream, MustCompile, ModuleName, ModuleNames,
|
|
Result, !IO).
|
|
|
|
% WARNING: The code here duplicates the functionality of scripts/c2init.in.
|
|
% Any changes there may also require changes here, and vice versa.
|
|
|
|
:- pred make_init_obj_file(io.output_stream::in, bool::in,
|
|
module_name::in, list(module_name)::in, maybe(file_name)::out,
|
|
io::di, io::uo) is det.
|
|
|
|
make_init_obj_file(ErrorStream, MustCompile, ModuleName, ModuleNames, Result,
|
|
!IO) :-
|
|
globals.io_lookup_bool_option(verbose, Verbose, !IO),
|
|
globals.io_lookup_bool_option(statistics, Stats, !IO),
|
|
maybe_write_string(Verbose, "% Creating initialization file...\n", !IO),
|
|
|
|
globals.io_get_globals(Globals, !IO),
|
|
compute_grade(Globals, Grade),
|
|
|
|
get_object_code_type(executable, PIC, !IO),
|
|
maybe_pic_object_file_extension(PIC, ObjExt, !IO),
|
|
InitObj = "_init" ++ ObjExt,
|
|
|
|
module_name_to_file_name(ModuleName, "_init.c", yes, InitCFileName, !IO),
|
|
module_name_to_file_name(ModuleName, InitObj, yes, InitObjFileName, !IO),
|
|
|
|
list.map_foldl(
|
|
(pred(ThisModule::in, CFileName::out, IO0::di, IO::uo) is det :-
|
|
module_name_to_file_name(ThisModule, ".c", no, CFileName, IO0, IO)
|
|
), ModuleNames, CFileNameList, !IO),
|
|
join_quoted_string_list(CFileNameList, "", "", " ", CFileNames),
|
|
|
|
globals.io_lookup_accumulating_option(init_file_directories,
|
|
InitFileDirsList, !IO),
|
|
join_quoted_string_list(InitFileDirsList, "-I ", "", " ", InitFileDirs),
|
|
|
|
globals.io_lookup_accumulating_option(init_files, InitFileNamesList0,
|
|
!IO),
|
|
globals.io_lookup_accumulating_option(trace_init_files,
|
|
TraceInitFileNamesList0, !IO),
|
|
globals.io_lookup_maybe_string_option(
|
|
mercury_standard_library_directory, MaybeStdLibDir, !IO),
|
|
(
|
|
MaybeStdLibDir = yes(StdLibDir),
|
|
InitFileNamesList1 = [StdLibDir/"modules"/"mer_rt.init",
|
|
StdLibDir/"modules"/"mer_std.init" |
|
|
InitFileNamesList0],
|
|
TraceInitFileNamesList =
|
|
[StdLibDir/"modules"/"mer_browser.init",
|
|
StdLibDir/"modules"/"mer_mdbcomp.init" |
|
|
TraceInitFileNamesList0]
|
|
;
|
|
MaybeStdLibDir = no,
|
|
InitFileNamesList1 = InitFileNamesList0,
|
|
TraceInitFileNamesList = TraceInitFileNamesList0
|
|
),
|
|
|
|
globals.io_get_trace_level(TraceLevel, !IO),
|
|
( given_trace_level_is_none(TraceLevel) = no ->
|
|
TraceOpt = "-t",
|
|
InitFileNamesList = InitFileNamesList1 ++ TraceInitFileNamesList
|
|
;
|
|
TraceOpt = "",
|
|
InitFileNamesList = InitFileNamesList1
|
|
),
|
|
join_quoted_string_list(InitFileNamesList, "", "", " ", InitFileNames),
|
|
|
|
globals.io_lookup_accumulating_option(runtime_flags, RuntimeFlagsList,
|
|
!IO),
|
|
join_quoted_string_list(RuntimeFlagsList, "-r ", "", " ", RuntimeFlags),
|
|
|
|
globals.io_lookup_bool_option(extra_initialization_functions, ExtraInits,
|
|
!IO),
|
|
ExtraInitsOpt = ( ExtraInits = yes -> "-x" ; "" ),
|
|
|
|
globals.io_lookup_bool_option(main, Main, !IO),
|
|
NoMainOpt = ( Main = no -> "-l" ; "" ),
|
|
|
|
globals.io_lookup_string_option(experimental_complexity,
|
|
ExperimentalComplexity, !IO),
|
|
( ExperimentalComplexity = "" ->
|
|
ExperimentalComplexityOpt = ""
|
|
;
|
|
ExperimentalComplexityOpt = "-X " ++ ExperimentalComplexity
|
|
),
|
|
|
|
globals.io_lookup_string_option(mkinit_command, Mkinit, !IO),
|
|
TmpInitCFileName = InitCFileName ++ ".tmp",
|
|
MkInitCmd = string.append_list(
|
|
[ Mkinit,
|
|
" -g ", Grade,
|
|
" ", TraceOpt,
|
|
" ", ExtraInitsOpt,
|
|
" ", NoMainOpt,
|
|
" ", ExperimentalComplexityOpt,
|
|
" ", RuntimeFlags,
|
|
" -o ", quote_arg(TmpInitCFileName),
|
|
" ", InitFileDirs,
|
|
" ", InitFileNames,
|
|
" ", CFileNames
|
|
]),
|
|
invoke_system_command(ErrorStream, verbose, MkInitCmd, MkInitOK0, !IO),
|
|
maybe_report_stats(Stats, !IO),
|
|
(
|
|
MkInitOK0 = yes,
|
|
update_interface_return_succeeded(InitCFileName, MkInitOK1, !IO),
|
|
(
|
|
MkInitOK1 = yes,
|
|
(
|
|
MustCompile = yes,
|
|
Compile = yes
|
|
;
|
|
MustCompile = no,
|
|
io.file_modification_time(InitCFileName,
|
|
InitCModTimeResult, !IO),
|
|
io.file_modification_time(InitObjFileName,
|
|
InitObjModTimeResult, !IO),
|
|
(
|
|
InitObjModTimeResult = ok(InitObjModTime),
|
|
InitCModTimeResult = ok(InitCModTime),
|
|
compare(TimeCompare, InitObjModTime, InitCModTime),
|
|
( TimeCompare = (=)
|
|
; TimeCompare = (>)
|
|
)
|
|
->
|
|
Compile = no
|
|
;
|
|
Compile = yes
|
|
)
|
|
),
|
|
(
|
|
Compile = yes,
|
|
maybe_write_string(Verbose,
|
|
"% Compiling initialization file...\n", !IO),
|
|
|
|
compile_c_file(ErrorStream, PIC, InitCFileName,
|
|
InitObjFileName, CompileOK, !IO),
|
|
maybe_report_stats(Stats, !IO),
|
|
(
|
|
CompileOK = no,
|
|
Result = no
|
|
;
|
|
CompileOK = yes,
|
|
Result = yes(InitObjFileName)
|
|
)
|
|
;
|
|
Compile = no,
|
|
Result = yes(InitObjFileName)
|
|
)
|
|
;
|
|
MkInitOK1 = no,
|
|
Result = no
|
|
)
|
|
;
|
|
MkInitOK0 = no,
|
|
Result = no
|
|
).
|
|
|
|
% WARNING: The code here duplicates the functionality of scripts/ml.in.
|
|
% Any changes there may also require changes here, and vice versa.
|
|
|
|
link(ErrorStream, LinkTargetType, ModuleName, ObjectsList, Succeeded, !IO) :-
|
|
globals.io_lookup_bool_option(verbose, Verbose, !IO),
|
|
globals.io_lookup_bool_option(statistics, Stats, !IO),
|
|
|
|
maybe_write_string(Verbose, "% Linking...\n", !IO),
|
|
link_output_filename(LinkTargetType, ModuleName, _Ext, OutputFileName, !IO),
|
|
( LinkTargetType = static_library ->
|
|
create_archive(ErrorStream, OutputFileName, yes, ObjectsList,
|
|
LinkSucceeded, !IO)
|
|
; LinkTargetType = java_archive ->
|
|
create_java_archive(ErrorStream, ModuleName, OutputFileName,
|
|
ObjectsList, LinkSucceeded, !IO)
|
|
;
|
|
(
|
|
LinkTargetType = shared_library,
|
|
CommandOpt = link_shared_lib_command,
|
|
RpathFlagOpt = shlib_linker_rpath_flag,
|
|
RpathSepOpt = shlib_linker_rpath_separator,
|
|
LDFlagsOpt = ld_libflags,
|
|
ThreadFlagsOpt = shlib_linker_thread_flags,
|
|
DebugFlagsOpt = shlib_linker_debug_flags,
|
|
TraceFlagsOpt = shlib_linker_trace_flags,
|
|
globals.io_lookup_bool_option(allow_undefined, AllowUndef, !IO),
|
|
(
|
|
AllowUndef = yes,
|
|
globals.io_lookup_string_option(
|
|
linker_allow_undefined_flag, UndefOpt, !IO)
|
|
;
|
|
AllowUndef = no,
|
|
globals.io_lookup_string_option(
|
|
linker_error_undefined_flag, UndefOpt, !IO)
|
|
)
|
|
;
|
|
LinkTargetType = executable,
|
|
CommandOpt = link_executable_command,
|
|
RpathFlagOpt = linker_rpath_flag,
|
|
RpathSepOpt = linker_rpath_separator,
|
|
LDFlagsOpt = ld_flags,
|
|
ThreadFlagsOpt = linker_thread_flags,
|
|
DebugFlagsOpt = linker_debug_flags,
|
|
TraceFlagsOpt = linker_trace_flags,
|
|
UndefOpt = ""
|
|
;
|
|
LinkTargetType = static_library,
|
|
unexpected(this_file, "compile_target_code.link")
|
|
;
|
|
LinkTargetType = java_archive,
|
|
unexpected(this_file, "compile_target_code.link")
|
|
),
|
|
|
|
% Should the executable be stripped?
|
|
globals.io_lookup_bool_option(strip, Strip, !IO),
|
|
(
|
|
LinkTargetType = executable,
|
|
Strip = yes
|
|
->
|
|
globals.io_lookup_string_option(linker_strip_flag, StripOpt, !IO)
|
|
;
|
|
StripOpt = ""
|
|
),
|
|
|
|
globals.io_lookup_bool_option(target_debug, TargetDebug, !IO),
|
|
(
|
|
TargetDebug = yes,
|
|
globals.io_lookup_string_option(DebugFlagsOpt, DebugOpts, !IO)
|
|
;
|
|
TargetDebug = no,
|
|
DebugOpts = ""
|
|
),
|
|
|
|
% Should the executable be statically linked?
|
|
globals.io_lookup_string_option(linkage, Linkage, !IO),
|
|
(
|
|
LinkTargetType = executable,
|
|
Linkage = "static"
|
|
->
|
|
globals.io_lookup_string_option(linker_static_flags, StaticOpts,
|
|
!IO)
|
|
;
|
|
StaticOpts = ""
|
|
),
|
|
|
|
% Are the thread libraries needed?
|
|
use_thread_libs(UseThreadLibs, !IO),
|
|
(
|
|
UseThreadLibs = yes,
|
|
globals.io_lookup_string_option(ThreadFlagsOpt, ThreadOpts, !IO)
|
|
;
|
|
UseThreadLibs = no,
|
|
ThreadOpts = ""
|
|
),
|
|
|
|
% Find the Mercury standard libraries.
|
|
globals.io_lookup_maybe_string_option(
|
|
mercury_standard_library_directory, MaybeStdLibDir, !IO),
|
|
(
|
|
MaybeStdLibDir = yes(StdLibDir),
|
|
get_mercury_std_libs(LinkTargetType, StdLibDir, MercuryStdLibs,
|
|
!IO)
|
|
;
|
|
MaybeStdLibDir = no,
|
|
MercuryStdLibs = ""
|
|
),
|
|
|
|
% Find which system libraries are needed.
|
|
get_system_libs(LinkTargetType, SystemLibs, !IO),
|
|
|
|
join_quoted_string_list(ObjectsList, "", "", " ", Objects),
|
|
globals.io_lookup_accumulating_option(LDFlagsOpt, LDFlagsList, !IO),
|
|
join_string_list(LDFlagsList, "", "", " ", LDFlags),
|
|
globals.io_lookup_accumulating_option(link_library_directories,
|
|
LinkLibraryDirectoriesList, !IO),
|
|
globals.io_lookup_string_option(linker_path_flag, LinkerPathFlag,
|
|
!IO),
|
|
join_quoted_string_list(LinkLibraryDirectoriesList, LinkerPathFlag, "",
|
|
" ", LinkLibraryDirectories),
|
|
|
|
% Set up the runtime library path.
|
|
globals.io_lookup_bool_option(shlib_linker_use_install_name,
|
|
UseInstallName, !IO),
|
|
shared_libraries_supported(SharedLibsSupported, !IO),
|
|
(
|
|
UseInstallName = no,
|
|
SharedLibsSupported = yes,
|
|
( Linkage = "shared"
|
|
; LinkTargetType = shared_library
|
|
)
|
|
->
|
|
globals.io_lookup_accumulating_option(
|
|
runtime_link_library_directories, RpathDirs, !IO),
|
|
(
|
|
RpathDirs = [],
|
|
RpathOpts = ""
|
|
;
|
|
RpathDirs = [_|_],
|
|
globals.io_lookup_string_option(RpathSepOpt, RpathSep, !IO),
|
|
globals.io_lookup_string_option(RpathFlagOpt, RpathFlag, !IO),
|
|
RpathOpts0 = string.join_list(RpathSep, RpathDirs),
|
|
RpathOpts = RpathFlag ++ RpathOpts0
|
|
)
|
|
;
|
|
RpathOpts = ""
|
|
),
|
|
|
|
% Set up the install name for shared libraries.
|
|
(
|
|
UseInstallName = yes,
|
|
LinkTargetType = shared_library
|
|
->
|
|
% NOTE: `ShLibFileName' must *not* be prefixed with a directory.
|
|
% get_install_name_option will prefix it with the correct
|
|
% directory which is the one where the library is going to
|
|
% be installed, *not* where it is going to be built.
|
|
%
|
|
sym_name_to_string(ModuleName, BaseFileName),
|
|
globals.io_lookup_string_option(shared_library_extension,
|
|
SharedLibExt, !IO),
|
|
ShLibFileName = "lib" ++ BaseFileName ++ SharedLibExt,
|
|
get_install_name_option(ShLibFileName, InstallNameOpt, !IO)
|
|
;
|
|
InstallNameOpt = ""
|
|
),
|
|
|
|
globals.io_get_trace_level(TraceLevel, !IO),
|
|
( given_trace_level_is_none(TraceLevel) = yes ->
|
|
TraceOpts = ""
|
|
;
|
|
globals.io_lookup_string_option(TraceFlagsOpt, TraceOpts, !IO)
|
|
),
|
|
|
|
% Pass either `-llib' or `PREFIX/lib/GRADE/liblib.a',
|
|
% depending on whether we are linking with static or shared
|
|
% Mercury libraries.
|
|
|
|
globals.io_lookup_accumulating_option(
|
|
mercury_library_directories, MercuryLibDirs0, !IO),
|
|
globals.io_get_globals(Globals, !IO),
|
|
grade_directory_component(Globals, GradeDir),
|
|
MercuryLibDirs = list.map(
|
|
(func(LibDir) = LibDir/"lib"/GradeDir),
|
|
MercuryLibDirs0),
|
|
globals.io_lookup_accumulating_option(link_libraries,
|
|
LinkLibrariesList0, !IO),
|
|
list.map_foldl2(process_link_library(MercuryLibDirs),
|
|
LinkLibrariesList0, LinkLibrariesList, yes,
|
|
LibrariesSucceeded, !IO),
|
|
|
|
globals.io_lookup_string_option(linker_opt_separator,
|
|
LinkOptSep, !IO),
|
|
(
|
|
LibrariesSucceeded = yes,
|
|
join_quoted_string_list(LinkLibrariesList, "", "", " ",
|
|
LinkLibraries),
|
|
|
|
% Note that LDFlags may contain `-l' options so it should come
|
|
% after Objects.
|
|
globals.io_lookup_string_option(CommandOpt, Command, !IO),
|
|
string.append_list(
|
|
[Command, " ",
|
|
StaticOpts, " ", StripOpt, " ", UndefOpt, " ",
|
|
ThreadOpts, " ", TraceOpts, " ",
|
|
" -o ", OutputFileName, " ", Objects, " ",
|
|
LinkOptSep, " ", LinkLibraryDirectories, " ",
|
|
RpathOpts, " ", InstallNameOpt, " ", DebugOpts,
|
|
" ", LDFlags, " ", LinkLibraries, " ",
|
|
MercuryStdLibs, " ", SystemLibs],
|
|
LinkCmd),
|
|
|
|
globals.io_lookup_bool_option(demangle, Demangle, !IO),
|
|
(
|
|
Demangle = yes,
|
|
globals.io_lookup_string_option(demangle_command,
|
|
DemamngleCmd, !IO),
|
|
MaybeDemangleCmd = yes(DemamngleCmd)
|
|
;
|
|
Demangle = no,
|
|
MaybeDemangleCmd = no
|
|
),
|
|
|
|
invoke_system_command(ErrorStream, verbose_commands, LinkCmd,
|
|
MaybeDemangleCmd, LinkSucceeded, !IO)
|
|
;
|
|
LibrariesSucceeded = no,
|
|
LinkSucceeded = no
|
|
)
|
|
),
|
|
maybe_report_stats(Stats, !IO),
|
|
(
|
|
LinkSucceeded = yes,
|
|
post_link_make_symlink_or_copy(ErrorStream, LinkTargetType,
|
|
ModuleName, Succeeded, !IO)
|
|
;
|
|
LinkSucceeded = no,
|
|
Succeeded = no
|
|
).
|
|
|
|
:- pred link_output_filename(linked_target_type::in, module_name::in,
|
|
string::out, string::out, io::di, io::uo) is det.
|
|
|
|
link_output_filename(LinkTargetType, ModuleName, Ext, OutputFileName, !IO) :-
|
|
(
|
|
LinkTargetType = static_library,
|
|
globals.io_lookup_string_option(library_extension, Ext, !IO),
|
|
module_name_to_lib_file_name("lib", ModuleName, Ext, yes,
|
|
OutputFileName, !IO)
|
|
;
|
|
LinkTargetType = shared_library,
|
|
globals.io_lookup_string_option(shared_library_extension, Ext, !IO),
|
|
module_name_to_lib_file_name("lib", ModuleName, Ext, yes,
|
|
OutputFileName, !IO)
|
|
;
|
|
LinkTargetType = java_archive,
|
|
Ext = ".jar",
|
|
module_name_to_file_name(ModuleName, Ext, yes, OutputFileName, !IO)
|
|
;
|
|
LinkTargetType = executable,
|
|
globals.io_lookup_string_option(executable_file_extension, Ext, !IO),
|
|
module_name_to_file_name(ModuleName, Ext, yes, OutputFileName, !IO)
|
|
).
|
|
|
|
% Find the standard Mercury libraries, and the system
|
|
% libraries needed by them.
|
|
%
|
|
:- pred get_mercury_std_libs(linked_target_type::in, dir_name::in, string::out,
|
|
io::di, io::uo) is det.
|
|
|
|
get_mercury_std_libs(TargetType, StdLibDir, StdLibs, !IO) :-
|
|
globals.io_get_gc_method(GCMethod, !IO),
|
|
globals.io_lookup_string_option(library_extension, LibExt, !IO),
|
|
globals.io_get_globals(Globals, !IO),
|
|
grade_directory_component(Globals, GradeDir),
|
|
|
|
% GC libraries.
|
|
(
|
|
GCMethod = automatic,
|
|
StaticGCLibs = "",
|
|
SharedGCLibs = ""
|
|
;
|
|
GCMethod = none,
|
|
StaticGCLibs = "",
|
|
SharedGCLibs = ""
|
|
;
|
|
GCMethod = boehm,
|
|
globals.io_lookup_bool_option(profile_time, ProfTime, !IO),
|
|
globals.io_lookup_bool_option(profile_deep, ProfDeep, !IO),
|
|
(
|
|
( ProfTime = yes
|
|
; ProfDeep = yes
|
|
)
|
|
->
|
|
GCGrade0 = "gc_prof"
|
|
;
|
|
GCGrade0 = "gc"
|
|
),
|
|
globals.io_lookup_bool_option(parallel, Parallel, !IO),
|
|
(
|
|
Parallel = yes,
|
|
GCGrade = "par_" ++ GCGrade0
|
|
;
|
|
Parallel = no,
|
|
GCGrade = GCGrade0
|
|
),
|
|
make_link_lib(TargetType, GCGrade, SharedGCLibs, !IO),
|
|
StaticGCLibs = quote_arg(StdLibDir/"lib"/
|
|
("lib" ++ GCGrade ++ LibExt))
|
|
;
|
|
GCMethod = mps,
|
|
make_link_lib(TargetType, "mps", SharedGCLibs, !IO),
|
|
StaticGCLibs = quote_arg(StdLibDir/"lib"/
|
|
("libmps" ++ LibExt) )
|
|
;
|
|
GCMethod = accurate,
|
|
StaticGCLibs = "",
|
|
SharedGCLibs = ""
|
|
),
|
|
|
|
% Trace libraries.
|
|
globals.io_get_trace_level(TraceLevel, !IO),
|
|
( given_trace_level_is_none(TraceLevel) = yes ->
|
|
StaticTraceLibs = "",
|
|
SharedTraceLibs = ""
|
|
;
|
|
StaticTraceLibs =
|
|
quote_arg(StdLibDir/"lib"/GradeDir/
|
|
("libmer_trace" ++ LibExt)) ++
|
|
" " ++
|
|
quote_arg(StdLibDir/"lib"/GradeDir/
|
|
("libmer_browser" ++ LibExt)) ++
|
|
" " ++
|
|
quote_arg(StdLibDir/"lib"/GradeDir/
|
|
("libmer_mdbcomp" ++ LibExt)),
|
|
make_link_lib(TargetType, "mer_trace", TraceLib, !IO),
|
|
make_link_lib(TargetType, "mer_browser", BrowserLib, !IO),
|
|
make_link_lib(TargetType, "mer_mdbcomp", MdbCompLib, !IO),
|
|
SharedTraceLibs = string.join_list(" ",
|
|
[TraceLib, BrowserLib, MdbCompLib])
|
|
),
|
|
|
|
globals.io_lookup_string_option(mercury_linkage, MercuryLinkage, !IO),
|
|
( MercuryLinkage = "static" ->
|
|
StdLibs = string.join_list(" ",
|
|
[StaticTraceLibs,
|
|
quote_arg(StdLibDir/"lib"/GradeDir/
|
|
("libmer_std" ++ LibExt)),
|
|
quote_arg(StdLibDir/"lib"/GradeDir/
|
|
("libmer_rt" ++ LibExt)),
|
|
StaticGCLibs])
|
|
; MercuryLinkage = "shared" ->
|
|
make_link_lib(TargetType, "mer_std", StdLib, !IO),
|
|
make_link_lib(TargetType, "mer_rt", RuntimeLib, !IO),
|
|
StdLibs = string.join_list(" ",
|
|
[SharedTraceLibs, StdLib, RuntimeLib, SharedGCLibs])
|
|
;
|
|
unexpected(this_file, "unknown linkage " ++ MercuryLinkage)
|
|
).
|
|
|
|
:- pred make_link_lib(linked_target_type::in, string::in, string::out,
|
|
io::di, io::uo) is det.
|
|
|
|
make_link_lib(TargetType, LibName, LinkOpt, !IO) :-
|
|
(
|
|
TargetType = executable,
|
|
LinkLibFlag = linker_link_lib_flag,
|
|
LinkLibSuffix = linker_link_lib_suffix
|
|
;
|
|
TargetType = shared_library,
|
|
LinkLibFlag = shlib_linker_link_lib_flag,
|
|
LinkLibSuffix = shlib_linker_link_lib_suffix
|
|
;
|
|
TargetType = java_archive,
|
|
unexpected(this_file, "make_link_lib: java_archive")
|
|
;
|
|
TargetType = static_library,
|
|
unexpected(this_file, "make_link_lib: static_library")
|
|
),
|
|
globals.io_lookup_string_option(LinkLibFlag, LinkLibOpt, !IO),
|
|
globals.io_lookup_string_option(LinkLibSuffix, Suffix, !IO),
|
|
LinkOpt = quote_arg(LinkLibOpt ++ LibName ++ Suffix).
|
|
|
|
:- pred get_system_libs(linked_target_type::in, string::out, io::di, io::uo)
|
|
is det.
|
|
|
|
get_system_libs(TargetType, SystemLibs, !IO) :-
|
|
% System libraries used when tracing.
|
|
globals.io_get_trace_level(TraceLevel, !IO),
|
|
( given_trace_level_is_none(TraceLevel) = yes ->
|
|
SystemTraceLibs = ""
|
|
;
|
|
globals.io_lookup_string_option(trace_libs, SystemTraceLibs0, !IO),
|
|
globals.io_lookup_bool_option(use_readline, UseReadline, !IO),
|
|
(
|
|
UseReadline = yes,
|
|
globals.io_lookup_string_option(readline_libs, ReadlineLibs, !IO),
|
|
SystemTraceLibs = SystemTraceLibs0 ++ " " ++ ReadlineLibs
|
|
;
|
|
UseReadline = no,
|
|
SystemTraceLibs = SystemTraceLibs0
|
|
)
|
|
),
|
|
|
|
% Thread libraries
|
|
use_thread_libs(UseThreadLibs, !IO),
|
|
(
|
|
UseThreadLibs = yes,
|
|
globals.io_lookup_string_option(thread_libs, ThreadLibs, !IO)
|
|
;
|
|
UseThreadLibs = no,
|
|
ThreadLibs = ""
|
|
),
|
|
|
|
% Other system libraries.
|
|
(
|
|
TargetType = shared_library,
|
|
globals.io_lookup_string_option(shared_libs, OtherSystemLibs, !IO)
|
|
;
|
|
TargetType = static_library,
|
|
unexpected(this_file, "get_std_libs: static library")
|
|
;
|
|
TargetType = java_archive,
|
|
unexpected(this_file, "get_std_libs: java archive")
|
|
;
|
|
TargetType = executable,
|
|
globals.io_lookup_string_option(math_lib, OtherSystemLibs, !IO)
|
|
),
|
|
|
|
SystemLibs = string.join_list(" ",
|
|
[SystemTraceLibs, OtherSystemLibs, ThreadLibs]).
|
|
|
|
:- pred use_thread_libs(bool::out, io::di, io::uo) is det.
|
|
|
|
use_thread_libs(UseThreadLibs, !IO) :-
|
|
globals.io_lookup_bool_option(parallel, Parallel, !IO),
|
|
globals.io_get_gc_method(GCMethod, !IO),
|
|
UseThreadLibs = ( ( Parallel = yes ; GCMethod = mps ) -> yes ; no ).
|
|
|
|
post_link_make_symlink_or_copy(ErrorStream, LinkTargetType, ModuleName,
|
|
Succeeded, !IO) :-
|
|
globals.io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs, !IO),
|
|
(
|
|
UseGradeSubdirs = yes,
|
|
link_output_filename(LinkTargetType, ModuleName,
|
|
Ext, OutputFileName, !IO),
|
|
% Link/copy the executable into the user's directory.
|
|
globals.io_set_option(use_subdirs, bool(no), !IO),
|
|
globals.io_set_option(use_grade_subdirs, bool(no), !IO),
|
|
( LinkTargetType = executable ->
|
|
module_name_to_file_name(ModuleName, Ext, no, UserDirFileName, !IO)
|
|
;
|
|
module_name_to_lib_file_name("lib", ModuleName, Ext, no,
|
|
UserDirFileName, !IO)
|
|
),
|
|
globals.io_set_option(use_subdirs, bool(yes), !IO),
|
|
globals.io_set_option(use_grade_subdirs, bool(yes), !IO),
|
|
|
|
io.set_output_stream(ErrorStream, OutputStream, !IO),
|
|
% Remove the target of the symlink/copy in case it already exists.
|
|
io.remove_file(UserDirFileName, _, !IO),
|
|
make_symlink_or_copy_file(OutputFileName, UserDirFileName, Succeeded,
|
|
!IO),
|
|
io.set_output_stream(OutputStream, _, !IO)
|
|
;
|
|
UseGradeSubdirs = no,
|
|
Succeeded = yes
|
|
).
|
|
|
|
shared_libraries_supported(Supported, !IO) :-
|
|
% XXX This seems to be the standard way to check whether shared libraries
|
|
% are supported but it's not very nice.
|
|
globals.io_lookup_string_option(library_extension, LibExt, !IO),
|
|
globals.io_lookup_string_option(shared_library_extension, SharedLibExt,
|
|
!IO),
|
|
Supported = (if LibExt \= SharedLibExt then yes else no).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred process_link_library(list(dir_name)::in, string::in, string::out,
|
|
bool::in, bool::out, io::di, io::uo) is det.
|
|
|
|
process_link_library(MercuryLibDirs, LibName, LinkerOpt, !Succeeded, !IO) :-
|
|
globals.io_lookup_string_option(mercury_linkage, MercuryLinkage, !IO),
|
|
globals.io_lookup_accumulating_option(mercury_libraries, MercuryLibs,
|
|
!IO),
|
|
(
|
|
MercuryLinkage = "static",
|
|
list.member(LibName, MercuryLibs)
|
|
->
|
|
% If we are linking statically with Mercury libraries, pass the
|
|
% absolute pathname of the `.a' file for the library.
|
|
globals.io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs, !IO),
|
|
|
|
file_name_to_module_name(LibName, LibModuleName),
|
|
globals.io_lookup_string_option(library_extension, LibExt, !IO),
|
|
|
|
globals.io_set_option(use_grade_subdirs, bool(no), !IO),
|
|
module_name_to_lib_file_name("lib", LibModuleName, LibExt, no,
|
|
LibFileName, !IO),
|
|
globals.io_set_option(use_grade_subdirs, bool(UseGradeSubdirs), !IO),
|
|
|
|
io.input_stream(InputStream, !IO),
|
|
search_for_file_returning_dir(MercuryLibDirs, LibFileName,
|
|
SearchResult, !IO),
|
|
(
|
|
SearchResult = ok(DirName),
|
|
LinkerOpt = DirName/LibFileName,
|
|
io.set_input_stream(InputStream, LibInputStream, !IO),
|
|
io.close_input(LibInputStream, !IO)
|
|
;
|
|
SearchResult = error(Error),
|
|
LinkerOpt = "",
|
|
write_error_pieces_maybe_with_context(no, 0, [words(Error)], !IO),
|
|
!:Succeeded = no
|
|
)
|
|
;
|
|
LinkerOpt = "-l" ++ LibName
|
|
).
|
|
|
|
:- pred create_archive(io.output_stream::in, file_name::in, bool::in,
|
|
list(file_name)::in, bool::out, io::di, io::uo) is det.
|
|
|
|
create_archive(ErrorStream, LibFileName, Quote, ObjectList, Succeeded, !IO) :-
|
|
globals.io_lookup_string_option(create_archive_command, ArCmd, !IO),
|
|
globals.io_lookup_accumulating_option(create_archive_command_flags,
|
|
ArFlagsList, !IO),
|
|
join_string_list(ArFlagsList, "", "", " ", ArFlags),
|
|
globals.io_lookup_string_option(create_archive_command_output_flag,
|
|
ArOutputFlag, !IO),
|
|
globals.io_lookup_string_option(ranlib_command, RanLib, !IO),
|
|
(
|
|
Quote = yes,
|
|
join_quoted_string_list(ObjectList, "", "", " ", Objects)
|
|
;
|
|
Quote = no,
|
|
% Elements of ObjectList may contain shell wildcards, which
|
|
% are intended to cause the element to expand to several words.
|
|
% Quoting would prevent that.
|
|
join_string_list(ObjectList, "", "", " ", Objects)
|
|
),
|
|
MakeLibCmd = string.append_list([
|
|
ArCmd, " ", ArFlags, " ", ArOutputFlag, " ",
|
|
LibFileName, " ", Objects]),
|
|
invoke_system_command(ErrorStream, verbose_commands,
|
|
MakeLibCmd, MakeLibCmdSucceeded, !IO),
|
|
(
|
|
( RanLib = ""
|
|
; MakeLibCmdSucceeded = no
|
|
)
|
|
->
|
|
Succeeded = MakeLibCmdSucceeded
|
|
;
|
|
RanLibCmd = string.append_list([RanLib, " ", LibFileName]),
|
|
invoke_system_command(ErrorStream, verbose_commands, RanLibCmd,
|
|
Succeeded, !IO)
|
|
).
|
|
|
|
:- pred create_java_archive(io.output_stream::in, module_name::in,
|
|
file_name::in, list(file_name)::in, bool::out, io::di, io::uo) is det.
|
|
|
|
create_java_archive(ErrorStream, ModuleName, JarFileName, ObjectList,
|
|
Succeeded, !IO) :-
|
|
% XXX Maybe these should be set up as options:
|
|
Jar = "jar",
|
|
JarCreateFlags = "cf",
|
|
|
|
join_quoted_string_list(ObjectList, "", "", " ", Objects),
|
|
list_class_files_for_jar(ModuleName, Objects, ListClassFiles, !IO),
|
|
Cmd = string.append_list([
|
|
Jar, " ", JarCreateFlags, " ", JarFileName, " ", ListClassFiles ]),
|
|
|
|
invoke_system_command(ErrorStream, verbose_commands, Cmd, Succeeded, !IO).
|
|
|
|
get_object_code_type(FileType, ObjectCodeType, !IO) :-
|
|
globals.io_lookup_string_option(pic_object_file_extension, PicObjExt, !IO),
|
|
globals.io_lookup_string_option(link_with_pic_object_file_extension,
|
|
LinkWithPicObjExt, !IO),
|
|
globals.io_lookup_string_option(object_file_extension, ObjExt, !IO),
|
|
globals.io_lookup_string_option(mercury_linkage, MercuryLinkage, !IO),
|
|
globals.io_lookup_bool_option(gcc_global_registers, GCCGlobals, !IO),
|
|
globals.io_lookup_bool_option(highlevel_code, HighLevelCode, !IO),
|
|
globals.io_lookup_bool_option(pic, PIC, !IO),
|
|
globals.io_get_target(Target, !IO),
|
|
(
|
|
PIC = yes,
|
|
% We've been explicitly told to use position independent code.
|
|
ObjectCodeType = ( if PicObjExt = ObjExt then non_pic else pic )
|
|
;
|
|
PIC = no,
|
|
(
|
|
FileType = static_library,
|
|
ObjectCodeType = non_pic
|
|
;
|
|
FileType = shared_library,
|
|
ObjectCodeType = ( if PicObjExt = ObjExt then non_pic else pic )
|
|
;
|
|
FileType = java_archive,
|
|
ObjectCodeType = non_pic
|
|
;
|
|
FileType = executable,
|
|
( MercuryLinkage = "shared" ->
|
|
(
|
|
% We only need to create `.lpic' files if `-DMR_PIC_REG'
|
|
% has an effect, which currently is only with grades using
|
|
% GCC global registers on x86 Unix.
|
|
( LinkWithPicObjExt = ObjExt
|
|
; HighLevelCode = yes
|
|
; GCCGlobals = no
|
|
; Target \= target_c
|
|
)
|
|
->
|
|
ObjectCodeType = non_pic
|
|
;
|
|
LinkWithPicObjExt = PicObjExt
|
|
->
|
|
ObjectCodeType = pic
|
|
;
|
|
ObjectCodeType = link_with_pic
|
|
)
|
|
; MercuryLinkage = "static" ->
|
|
ObjectCodeType = non_pic
|
|
;
|
|
% The linkage string is checked by options.m.
|
|
unexpected(this_file, "unknown linkage " ++ MercuryLinkage)
|
|
)
|
|
)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred standard_library_directory_option(string::out, io::di, io::uo) is det.
|
|
|
|
standard_library_directory_option(Opt, !IO) :-
|
|
globals.io_lookup_maybe_string_option(mercury_standard_library_directory,
|
|
MaybeStdLibDir, !IO),
|
|
globals.io_lookup_maybe_string_option(mercury_configuration_directory,
|
|
MaybeConfDir, !IO),
|
|
(
|
|
MaybeStdLibDir = yes(StdLibDir),
|
|
Opt0 = "--mercury-standard-library-directory " ++ StdLibDir ++ " ",
|
|
(
|
|
MaybeConfDir = yes(ConfDir),
|
|
ConfDir \= StdLibDir
|
|
->
|
|
Opt = Opt0 ++
|
|
"--mercury-configuration-directory " ++ ConfDir ++ " "
|
|
;
|
|
Opt = Opt0
|
|
)
|
|
;
|
|
MaybeStdLibDir = no,
|
|
Opt = "--no-mercury-standard-library-directory "
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% join_string_list(Strings, Prefix, Suffix, Serarator, Result):
|
|
%
|
|
% Appends the strings in the list `Strings' together into the string
|
|
% Result. Each string is prefixed by Prefix, suffixed by Suffix and
|
|
% separated by Separator.
|
|
%
|
|
:- pred join_string_list(list(string)::in, string::in, string::in, string::in,
|
|
string::out) is det.
|
|
|
|
join_string_list([], _Prefix, _Suffix, _Separator, "").
|
|
join_string_list([String | Strings], Prefix, Suffix, Separator, Result) :-
|
|
(
|
|
Strings = [],
|
|
string.append_list([Prefix, String, Suffix], Result)
|
|
;
|
|
Strings = [_ | _],
|
|
join_string_list(Strings, Prefix, Suffix, Separator, Result0),
|
|
string.append_list([Prefix, String, Suffix, Separator, Result0],
|
|
Result)
|
|
).
|
|
|
|
% As above, but quote the strings first. Note that the strings in values
|
|
% of the *flags options are already quoted.
|
|
%
|
|
:- pred join_quoted_string_list(list(string)::in, string::in, string::in,
|
|
string::in, string::out) is det.
|
|
|
|
join_quoted_string_list(Strings, Prefix, Suffix, Separator, Result) :-
|
|
join_string_list(map(quote_arg, Strings), Prefix, Suffix, Separator,
|
|
Result).
|
|
|
|
% join_module_list(ModuleNames, Extension, Result):
|
|
%
|
|
% The list of strings `Result' is computed from the list of strings
|
|
% `ModuleNames', by removing any directory paths, and converting the
|
|
% strings to file names and then back, adding the specified Extension.
|
|
% (This conversion ensures that we follow the usual file naming
|
|
% conventions.)
|
|
|
|
:- pred join_module_list(list(string)::in, string::in, list(string)::out,
|
|
io::di, io::uo) is det.
|
|
|
|
join_module_list([], _Extension, [], !IO).
|
|
join_module_list([Module | Modules], Extension, [FileName | Rest], !IO) :-
|
|
file_name_to_module_name(dir.basename_det(Module), ModuleName),
|
|
module_name_to_file_name(ModuleName, Extension, no, FileName, !IO),
|
|
join_module_list(Modules, Extension, Rest, !IO).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
make_all_module_command(Command0, MainModule, AllModules, Command, !IO) :-
|
|
% Pass the main module first.
|
|
list.map_foldl(
|
|
(pred(Module::in, FileName::out, IO0::di, IO::uo) is det :-
|
|
module_name_to_file_name(Module, ".m", no, FileName, IO0, IO)
|
|
),
|
|
[MainModule | list.delete_all(AllModules, MainModule)],
|
|
ModuleNameStrings, !IO),
|
|
Command = string.join_list(" ",
|
|
list.map(quote_arg, [Command0 | ModuleNameStrings])).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pragma promise_pure(maybe_pic_object_file_extension/3).
|
|
|
|
maybe_pic_object_file_extension(Globals::in, PIC::in, Ext::out) :-
|
|
(
|
|
PIC = non_pic,
|
|
globals.lookup_string_option(Globals, object_file_extension, Ext)
|
|
;
|
|
PIC = pic,
|
|
globals.lookup_string_option(Globals, pic_object_file_extension, Ext)
|
|
;
|
|
PIC = link_with_pic,
|
|
globals.lookup_string_option(Globals,
|
|
link_with_pic_object_file_extension, Ext)
|
|
).
|
|
maybe_pic_object_file_extension(Globals::in, PIC::out, Ext::in) :-
|
|
(
|
|
% This test must come first -- if the architecture doesn't
|
|
% need special treatment for PIC, we should always return
|
|
% `non_pic'. `mmc --make' depends on this.
|
|
globals.lookup_string_option(Globals, object_file_extension, Ext)
|
|
->
|
|
PIC = non_pic
|
|
;
|
|
globals.lookup_string_option(Globals, pic_object_file_extension, Ext)
|
|
->
|
|
PIC = pic
|
|
;
|
|
globals.lookup_string_option(Globals,
|
|
link_with_pic_object_file_extension, Ext)
|
|
->
|
|
PIC = link_with_pic
|
|
;
|
|
fail
|
|
).
|
|
|
|
maybe_pic_object_file_extension(PIC, ObjExt, !IO) :-
|
|
globals.io_get_globals(Globals, !IO),
|
|
maybe_pic_object_file_extension(Globals, PIC, ObjExt).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- func this_file = string.
|
|
|
|
this_file = "compile_target_code.m".
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module compile_target_code.
|
|
%-----------------------------------------------------------------------------%
|