[m-rev.] diff: option to query compiler about linker flags

Julien Fischer juliensf at csse.unimelb.edu.au
Mon Jan 19 16:22:12 AEDT 2009


Note: we probably need to do a little more work for this to work
in .par and .debug grades (and probably on Mac OS X).  I will look
into those things separately though.  Once everythings is more less
stable I will update the standalone interface section of the user's
guide.

----

Add a new command line option that causes the compiler to print out the
set of flags that it passes to the linker in order to link against a
selected set of Mercury libraries (the standard libraries plus any others
specified via the --ml option) in the current grade.
This removes the need for using the ml script with standalone interfaces.
(Which is useful on those systems that don't have a proper shell and can't
use that script!)

compiler/compiler_target_code.m:
 	Add a predicate that prints out the above information.

 	Refactor code in order to to avoid duplication between the new
 	functionality and the existing code for invoking the linker.

compiler/mercury_compile.m:
compiler/options.m:
 	Add the new option.

doc/user_guide.texi:
 	Add an entry for the new option.

samples/c_interface/standalone_c/Makefile:
 	Query the compiler directly about what flags to pass to the linker
 	rather than using the ml script.

 	Query the compiler about what flags to pass to the C compiler as
 	well.  (This was implemented a while ago, but this example was
 	never updated.)

 	Extend this example to optionally work with shared libraries.

Julien.

Index: compiler/compile_target_code.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/compile_target_code.m,v
retrieving revision 1.134
diff -u -r1.134 compile_target_code.m
--- compiler/compile_target_code.m	11 Dec 2008 15:12:16 -0000	1.134
+++ compiler/compile_target_code.m	16 Jan 2009 07:30:56 -0000
@@ -188,7 +188,10 @@
      is det.

  %-----------------------------------------------------------------------------%
- 
+%
+% Stuff used for standalone interfaces
+% 
+
      % make_standalone_interface(Basename, !IO):
      %
      % Create a standalone interface in the current directory.
@@ -200,6 +203,14 @@
      %
  :- pred output_c_compiler_flags(io.output_stream::in, io::di, io::uo) is det.

+    % Output the list of flags required to link against the selected set
+    % of Mercury libraries (the standard libraries, plus any other specified
+    % via the --ml option) in the current grade.
+    % This predicate is used to implement the `--output-library-link-flags'
+    % option.
+    %
+:- pred output_library_link_flags(io.output_stream::in, io::di, io::uo) is det.
+
  %-----------------------------------------------------------------------------%
  %-----------------------------------------------------------------------------%

@@ -1710,16 +1721,7 @@
      ),

      % 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 = ""
-    ),
+    get_mercury_std_libs(LinkTargetType, MercuryStdLibs, !IO),

      % Find which system libraries are needed.
      get_system_libs(LinkTargetType, SystemLibs, !IO),
@@ -1734,34 +1736,12 @@
          " ", LinkLibraryDirectories),

      % Set up the runtime library path.
+    get_runtime_library_path_opts(LinkTargetType, RpathFlagOpt, RpathSepOpt,
+        RpathOpts, !IO),
+
+    % Set up the install name for shared libraries.
      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, RpathDirs0, !IO),
-        RpathDirs = list.map(quote_arg, RpathDirs0),
-        ( 
-            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
@@ -1787,27 +1767,11 @@
          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),
-
+    get_link_libraries(MaybeLinkLibraries, !IO),
      globals.io_lookup_string_option(linker_opt_separator,
          LinkOptSep, !IO),
      (
-        LibrariesSucceeded = yes,
+        MaybeLinkLibraries = yes(LinkLibrariesList),
          join_quoted_string_list(LinkLibrariesList, "", "", " ",
              LinkLibraries),

@@ -1884,147 +1848,184 @@
              MaybeDeleteTmpArchive = no
          )
      ;
-        LibrariesSucceeded = no,
+        MaybeLinkLibraries = no,
          LinkSucceeded = no
      ).
-
+
      % Find the standard Mercury libraries, and the system
      % libraries needed by them.
+    % Return the empty string if --mercury-standard-library-directory
+    % is not set.
      %
-:- pred get_mercury_std_libs(linked_target_type::in, dir_name::in, string::out,
+:- pred get_mercury_std_libs(linked_target_type::in, string::out,
      io::di, io::uo) is det.

-get_mercury_std_libs(TargetType, StdLibDir, StdLibs, !IO) :-
-    globals.io_get_gc_method(GCMethod, !IO),
-    (
-        ( TargetType = executable
-        ; TargetType = static_library
-        ; TargetType = shared_library
-        ),
-        globals.io_lookup_string_option(library_extension, LibExt, !IO)
-    ;
-        TargetType = java_archive,
-        unexpected(this_file, "get_mercury_std_libs: java_archive")
-    ;
-        TargetType = erlang_archive,
-        unexpected(this_file, "get_mercury_std_libs: erlang_archive")
-    ),
-    globals.io_get_globals(Globals, !IO),
-    grade_directory_component(Globals, GradeDir),
-
-    % GC libraries.
+get_mercury_std_libs(TargetType, StdLibs, !IO) :-
+    globals.io_lookup_maybe_string_option(
+        mercury_standard_library_directory, MaybeStdlibDir, !IO),
      (
-        GCMethod = gc_automatic,
-        StaticGCLibs = "",
-        SharedGCLibs = ""
-    ;
-        GCMethod = gc_none,
-        StaticGCLibs = "",
-        SharedGCLibs = ""
-    ;
+        MaybeStdlibDir = yes(StdLibDir),
+        globals.io_get_gc_method(GCMethod, !IO),
          (
-            GCMethod = gc_boehm,
-            GCGrade0 = "gc"
+            ( TargetType = executable
+            ; TargetType = static_library
+            ; TargetType = shared_library
+            ),
+            globals.io_lookup_string_option(library_extension, LibExt, !IO)
+        ;
+            TargetType = java_archive,
+            unexpected(this_file, "get_mercury_std_libs: java_archive")
          ;
-            GCMethod = gc_boehm_debug,
-            GCGrade0 = "gc_debug"
+            TargetType = erlang_archive,
+            unexpected(this_file, "get_mercury_std_libs: erlang_archive")
          ),
-        globals.io_lookup_bool_option(profile_time, ProfTime, !IO),
-        globals.io_lookup_bool_option(profile_deep, ProfDeep, !IO),
+        globals.io_get_globals(Globals, !IO),
+        grade_directory_component(Globals, GradeDir),
+
+        % GC libraries.
          (
-            ( ProfTime = yes
-            ; ProfDeep = yes
-            )
-        ->
-            GCGrade1 = GCGrade0 ++ "_prof"
+            GCMethod = gc_automatic,
+            StaticGCLibs = "",
+            SharedGCLibs = ""
+        ;
+            GCMethod = gc_none,
+            StaticGCLibs = "",
+            SharedGCLibs = ""
          ;
-            GCGrade1 = GCGrade0
+            (
+                GCMethod = gc_boehm,
+                GCGrade0 = "gc"
+            ;
+                GCMethod = gc_boehm_debug,
+                GCGrade0 = "gc_debug"
+            ),
+            globals.io_lookup_bool_option(profile_time, ProfTime, !IO),
+            globals.io_lookup_bool_option(profile_deep, ProfDeep, !IO),
+            (
+                ( ProfTime = yes
+                ; ProfDeep = yes
+                )
+            ->
+                GCGrade1 = GCGrade0 ++ "_prof"
+            ;
+                GCGrade1 = GCGrade0
+            ),
+            globals.io_lookup_bool_option(parallel, Parallel, !IO),
+            (
+                Parallel = yes,
+                GCGrade = "par_" ++ GCGrade1
+            ;
+                Parallel = no,
+                GCGrade = GCGrade1
+            ),
+            make_link_lib(TargetType, GCGrade, SharedGCLibs, !IO),
+            StaticGCLibs = quote_arg(StdLibDir/"lib"/
+                ("lib" ++ GCGrade ++ LibExt))
+        ;
+            GCMethod = gc_mps,
+            make_link_lib(TargetType, "mps", SharedGCLibs, !IO),
+            StaticGCLibs = quote_arg(StdLibDir/"lib"/
+                ("libmps" ++ LibExt) )
+        ;
+            GCMethod = gc_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_eventspec" ++ 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_eventspec", EventSpecLib, !IO),
+            make_link_lib(TargetType, "mer_browser", BrowserLib, !IO),
+            make_link_lib(TargetType, "mer_mdbcomp", MdbCompLib, !IO),
+            SharedTraceLibs = string.join_list(" ",
+                [TraceLib, EventSpecLib, BrowserLib, MdbCompLib])
          ),
-        globals.io_lookup_bool_option(parallel, Parallel, !IO),
+
+        % Source-to-source debugging libraries.
+        globals.io_lookup_bool_option(source_to_source_debug, SourceDebug, !IO),
          (
-            Parallel = yes,
-            GCGrade = "par_" ++ GCGrade1
-        ;
-            Parallel = no,
-            GCGrade = GCGrade1
+            SourceDebug = yes,
+            StaticSourceDebugLibs =
+                quote_arg(StdLibDir/"lib"/GradeDir/
+                    ("libmer_ssdb" ++ LibExt)),
+            make_link_lib(TargetType, "mer_mdbcomp", SharedSourceDebugLibs, !IO)
+        ;
+            SourceDebug = no,
+            StaticSourceDebugLibs = "",
+            SharedSourceDebugLibs = ""
          ),
-        make_link_lib(TargetType, GCGrade, SharedGCLibs, !IO),
-        StaticGCLibs = quote_arg(StdLibDir/"lib"/
-            ("lib" ++ GCGrade ++ LibExt))
-    ;
-        GCMethod = gc_mps,
-        make_link_lib(TargetType, "mps", SharedGCLibs, !IO),
-        StaticGCLibs = quote_arg(StdLibDir/"lib"/
-            ("libmps" ++ LibExt) )
-    ;
-        GCMethod = gc_accurate,
-        StaticGCLibs = "",
-        SharedGCLibs = ""
-    ),

-    % Trace libraries.
-    globals.io_get_trace_level(TraceLevel, !IO),
-    ( given_trace_level_is_none(TraceLevel) = yes ->
-        StaticTraceLibs = "",
-        SharedTraceLibs = ""
+        globals.io_lookup_string_option(mercury_linkage, MercuryLinkage, !IO),
+        ( MercuryLinkage = "static" ->
+            StdLibs = string.join_list(" ", [
+                StaticTraceLibs,
+                StaticSourceDebugLibs,
+                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,
+                SharedSourceDebugLibs,
+                StdLib,
+                RuntimeLib,
+                SharedGCLibs
+            ])
+        ;
+            unexpected(this_file, "unknown linkage " ++ MercuryLinkage)
+        )
      ;
-        StaticTraceLibs =
-            quote_arg(StdLibDir/"lib"/GradeDir/
-                ("libmer_trace" ++ LibExt)) ++
-            " " ++
-            quote_arg(StdLibDir/"lib"/GradeDir/
-                ("libmer_eventspec" ++ 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_eventspec", EventSpecLib, !IO),
-        make_link_lib(TargetType, "mer_browser", BrowserLib, !IO),
-        make_link_lib(TargetType, "mer_mdbcomp", MdbCompLib, !IO),
-        SharedTraceLibs = string.join_list(" ",
-            [TraceLib, EventSpecLib, BrowserLib, MdbCompLib])
-    ),
+        MaybeStdlibDir = no,
+        StdLibs = ""
+    ).
+ 
+    % Pass either `-llib' or `PREFIX/lib/GRADE/liblib.a',
+    % depending on whether we are linking with static or shared
+    % Mercury libraries.
+    %
+:- pred get_link_libraries(maybe(list(string))::out, io::di, io::uo) is det.

-    % Source-to-source debugging libraries.
-    globals.io_lookup_bool_option(source_to_source_debug, SourceDebug, !IO),
+get_link_libraries(MaybeLinkLibraries, !IO) :-
+    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),
      (
-        SourceDebug = yes,
-        StaticSourceDebugLibs =
-            quote_arg(StdLibDir/"lib"/GradeDir/
-                ("libmer_ssdb" ++ LibExt)),
-        make_link_lib(TargetType, "mer_mdbcomp", SharedSourceDebugLibs, !IO)
-    ;
-        SourceDebug = no,
-        StaticSourceDebugLibs = "",
-        SharedSourceDebugLibs = ""
-    ),
-
-    globals.io_lookup_string_option(mercury_linkage, MercuryLinkage, !IO),
-    ( MercuryLinkage = "static" ->
-        StdLibs = string.join_list(" ", [
-            StaticTraceLibs,
-            StaticSourceDebugLibs,
-            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,
-            SharedSourceDebugLibs,
-            StdLib,
-            RuntimeLib,
-            SharedGCLibs
-        ])
+        LibrariesSucceeded = yes,
+        MaybeLinkLibraries = yes(LinkLibrariesList)
      ;
-        unexpected(this_file, "unknown linkage " ++ MercuryLinkage)
+        LibrariesSucceeded = no,
+        MaybeLinkLibraries = no
      ).

  :- pred make_link_lib(linked_target_type::in, string::in, string::out,
@@ -2055,6 +2056,40 @@
          unexpected(this_file, "make_link_lib: static_library")
      ).

+:- pred get_runtime_library_path_opts(linked_target_type::in,
+    option::in(bound(shlib_linker_rpath_flag ; linker_rpath_flag)),
+    option::in(bound(shlib_linker_rpath_separator ; linker_rpath_separator)),
+    string::out, io::di, io::uo) is det.
+
+get_runtime_library_path_opts(LinkTargetType, RpathFlagOpt, RpathSepOpt, RpathOpts, !IO) :-
+    globals.io_lookup_bool_option(shlib_linker_use_install_name,
+        UseInstallName, !IO),
+    shared_libraries_supported(SharedLibsSupported, !IO),
+    globals.io_lookup_string_option(linkage, Linkage, !IO),
+    (
+        UseInstallName = no,
+        SharedLibsSupported = yes,
+        ( Linkage = "shared"
+        ; LinkTargetType = shared_library
+        )
+    ->
+        globals.io_lookup_accumulating_option(
+            runtime_link_library_directories, RpathDirs0, !IO),
+        RpathDirs = list.map(quote_arg, RpathDirs0),
+        ( 
+            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 = ""
+    ).
+
  :- pred get_system_libs(linked_target_type::in, string::out, io::di, io::uo)
      is det.

@@ -2113,7 +2148,7 @@
      globals.io_lookup_bool_option(parallel, Parallel, !IO),
      globals.io_get_gc_method(GCMethod, !IO),
      UseThreadLibs = ( ( Parallel = yes ; GCMethod = gc_mps ) -> yes ; no ).
-
+
  post_link_make_symlink_or_copy(ErrorStream, LinkTargetType, ModuleName,
          Succeeded, MadeSymlinkOrCopy, !IO) :-
      globals.io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs, !IO),
@@ -2451,7 +2486,7 @@
      % 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.

@@ -2478,7 +2513,7 @@

  %-----------------------------------------------------------------------------%

-:- pragma promise_pure(maybe_pic_object_file_extension/3).
+:- pragma promise_equivalent_clauses(maybe_pic_object_file_extension/3).

  maybe_pic_object_file_extension(Globals::in, PIC::in, Ext::out) :-
      (
@@ -2765,6 +2800,47 @@
      io.write_string(Stream, CFlags, !IO).

  %-----------------------------------------------------------------------------%
+%
+% Library link flags
+%
+
+output_library_link_flags(Stream, !IO) :-
+ 
+    % We output the library link flags as they are for when we are linking
+    % an executable.
+    LinkTargetType = executable,
+    RpathFlagOpt = linker_rpath_flag,
+    RpathSepOpt = linker_rpath_separator,
+ 
+    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),
+    get_runtime_library_path_opts(LinkTargetType, RpathFlagOpt, RpathSepOpt,
+        RpathOpts, !IO), 
+    get_link_libraries(MaybeLinkLibraries, !IO),
+    ( 
+        MaybeLinkLibraries = yes(LinkLibrariesList),
+        join_quoted_string_list(LinkLibrariesList, "", "", " ",
+            LinkLibraries)
+    ;
+        MaybeLinkLibraries = no,
+        LinkLibraries = ""
+    ),
+    % Find the Mercury standard libraries.
+    get_mercury_std_libs(LinkTargetType, MercuryStdLibs, !IO),
+    get_system_libs(LinkTargetType, SystemLibs, !IO),
+    string.append_list([
+        LinkLibraryDirectories, " ",
+        RpathOpts, " ",
+        LinkLibraries, " ",
+        MercuryStdLibs, " ",
+        SystemLibs], LinkFlags),
+    io.write_string(Stream, LinkFlags, !IO).
+
+%-----------------------------------------------------------------------------%

  :- func this_file = string.

Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.485
diff -u -r1.485 mercury_compile.m
--- compiler/mercury_compile.m	16 Jan 2009 02:31:22 -0000	1.485
+++ compiler/mercury_compile.m	16 Jan 2009 04:33:06 -0000
@@ -401,6 +401,8 @@
          OutputLibGrades),
      globals.lookup_bool_option(Globals, output_cc, OutputCC),
      globals.lookup_bool_option(Globals, output_cflags, OutputCFlags),
+    globals.lookup_bool_option(Globals, output_library_link_flags,
+        OutputLibraryLinkFlags),
      globals.lookup_bool_option(Globals, make, Make),
      globals.lookup_maybe_string_option(Globals, generate_standalone_interface,
          GenerateStandaloneInt),
@@ -445,6 +447,9 @@
      ; OutputCFlags = yes ->
          io.stdout_stream(StdOut, !IO),
          output_c_compiler_flags(StdOut, !IO)
+    ; OutputLibraryLinkFlags = yes ->
+        io.stdout_stream(StdOut, !IO),
+        output_library_link_flags(StdOut, !IO)
      ; GenerateMapping = yes ->
          source_file_map.write_source_file_map(Args, !IO)
      ; GenerateStandaloneInt = yes(StandaloneIntBasename) ->
Index: compiler/options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.641
diff -u -r1.641 options.m
--- compiler/options.m	23 Dec 2008 01:37:38 -0000	1.641
+++ compiler/options.m	19 Jan 2009 05:16:56 -0000
@@ -187,6 +187,7 @@
      ;       output_libgrades
      ;       output_cc
      ;       output_cflags
+    ;       output_library_link_flags

      % Auxiliary output options
      ;       smart_recompilation
@@ -1080,9 +1081,8 @@
      output_shared_lib_link_command      -   bool(no),
      output_libgrades                    -   bool(no),
      output_cc                           -   bool(no),
-    output_cflags                       -   bool(no)
-
-
+    output_cflags                       -   bool(no),
+    output_library_link_flags           -   bool(no)
  ]).
  option_defaults_2(aux_output_option, [
      % Auxiliary Output Options
@@ -1908,6 +1908,7 @@
  long_option("output-libgrades", output_libgrades).
  long_option("output-cc",        output_cc).
  long_option("output-cflags",    output_cflags).
+long_option("output-library-link-flags",  output_library_link_flags).

  % aux output options
  long_option("smart-recompilation",  smart_recompilation).
@@ -3493,7 +3494,13 @@
          "\tPrint the name of the C compiler to the standard output.",
          "--output-cflags",
          "\tPrint the flags with which the C compiler will be invoked",
-        "\tto the standard output."
+        "\tto the standard output.",
+        "--output-library-link-flags",
+        "\tPrint the flags that are passed to linker in order to link",
+        "\tagainst the current set of libraries.  This includes the",
+        "\tstandard library as well as any other libraries specified",
+        "\tvia the --ml option.  The flags are printed to the standard",
+        "\toutput."
      ]).

  :- pred options_help_aux_output(io::di, io::uo) is det.
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.580
diff -u -r1.580 user_guide.texi
--- doc/user_guide.texi	3 Nov 2008 11:56:17 -0000	1.580
+++ doc/user_guide.texi	19 Jan 2009 05:14:58 -0000
@@ -6665,6 +6665,14 @@
  Print the flags with which the C compiler will be invoked
  to the standard output.

+ at sp 1
+ at item --output-library-link-flags
+ at findex --output-library-link-flags
+Print the flags that are passed to the linker in order to link
+against the current set of libraries.  This includes the standard
+library as well as any other libraries specified via the
+ at samp{--ml} option.  The flags are printed to the standard output.
+
  @end table

  @node Auxiliary output options
Index: samples/c_interface/standalone_c/Makefile
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/samples/c_interface/standalone_c/Makefile,v
retrieving revision 1.2
diff -u -r1.2 Makefile
--- samples/c_interface/standalone_c/Makefile	18 Jun 2007 05:25:48 -0000	1.2
+++ samples/c_interface/standalone_c/Makefile	16 Jan 2009 06:42:52 -0000
@@ -32,11 +32,8 @@
  # link them all together.  Specific details concerning each step in the build
  # process are discussed below.  See c_main.c for details of how to invoke the
  # stand-alone interface from C or C++ code.
-#
-# NOTE: the following example is statically linked against the Mercury
-# libraries.  This is in order to make the example as portable as possible.
-# Shared libraries will also work with stand-alone interfaces on systems
-# that support them.
+
+MMC = mmc

  all: c_main

@@ -48,6 +45,40 @@
  #
  GRADEOPT=

+# By default we link our application statically against the Mercury libraries.
+# If you wish to use the shared versions of the Mercury libraries, comment
+# out the next two lines and uncomment the two following them.
+#
+# Note that we specify the example mercury_lib library to the linker separately
+# here.  This is because we have not installed it.
+#
+MERCURY_LINKAGE = --mercury-linkage static
+MERCURY_LIB_LDFLAGS = libmercury_lib.a
+
+# For using shared libraries.  (Remember to comment out the versions
+# above if you use these.)
+# 
+#MERCURY_LINKAGE = --mercury-linkage shared
+#MERCURY_LIB_LDFLAGS = -L. -Wl,-rpath . -lmercury_lib
+
+# Ask the Mercury compiler what C compiler we should use?
+#
+CC = $(shell $(MMC) --output-cc)
+
+# Ask the Mercury compiler what flags it passes to the C compiler?
+#
+CFLAGS=$(shell $(MMC) $(GRADEOPT) --output-cflags)
+
+# Ask the Mercury compiler what command it uses to invoke the linker when
+# creating an executable?
+#
+LD = $(shell $(MMC) --output-link-command)
+
+# Ask the Mercury compiler what flags it passes to the linker in order to link against
+# the selected set of Mercury libraries?
+#
+LIB_LDFLAGS = $(shell $(MMC) $(GRADEOPT) $(MERCURY_LINKAGE) --output-library-link-flags)
+
  # Build the example Mercury library, mercury_lib.
  # The dependency on the .init file is merely a convenience.  It's a good
  # one to choose since it will always be regenerated if one of the .m files
@@ -58,7 +89,7 @@
  # library.
  #
  mercury_lib.init: mercury_lib.m
-	mmc $(GRADEOPT) --make libmercury_lib
+	$(MMC) $(GRADEOPT) --make libmercury_lib

  # The following rule creates the stand-alone interface to the mercury_lib
  # library, Mercury standard library and Mercury runtime.  Since we haven't
@@ -67,7 +98,7 @@
  # `--mld' option to specify its location.
  #
  mercury_lib_int.o: mercury_lib.init
-	mmc $(GRADEOPT) --mercury-linkage static --ml mercury_lib \
+	$(MMC) $(GRADEOPT) --ml mercury_lib \
  		--generate-standalone-interface mercury_lib_int

  # We use the mgnuc script here rather than invoking gcc directly since
@@ -78,16 +109,15 @@
  # the `-I' option.
  #
  c_main.o: c_main.c mercury_lib.init mercury_lib_int.o
-	mgnuc $(GRADEOPT) -c c_main.c
+	$(CC) $(CFLAGS) -c c_main.c

  # For similar reasons we use the ml script rather than invoking ld directly.
  #
  c_main: c_main.o mercury_lib_int.o mercury_lib.init
-	ml $(GRADEOPT) --mercury-libs static -o c_main \
-		c_main.o libmercury_lib.a mercury_lib_int.o 
+	$(LD) -o c_main c_main.o $(MERCURY_LIB_LDFLAGS) mercury_lib_int.o $(LIB_LDFLAGS)

  .PHONY: realclean
  realclean:
-	-mmc --make mercury_lib.realclean
+	-$(MMC) --make mercury_lib.realclean
  	/bin/rm -f mercury_lib_int.[cho] c_main.o c_main Deep.data
  	/bin/rm -rf Mercury

--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list