[m-rev.] for review: improve `mmc --make' shared library support

Simon Taylor stayl at cs.mu.OZ.AU
Fri Nov 29 18:20:29 AEDT 2002


Estimated hours taken: 15
Branches: main

Make it easier to use shared libraries on Linux/x86 and FreeBSD.
Fix the defaults on Solaris so linking with Mercury
libraries and debugging both work with the default options.

These problems were solved by adding a third kind
of object file, `.lpic_o'. These files are compiled
with `--pic-reg' but not with CFLAGS_FOR_PIC, so
they can be linked with shared Mercury libraries.

On x86, executables which are linked with shared Mercury
libraries now depend on $(main_module.lpic_os), not
$(main_module.os).

This does not work with Mmake because ml doesn't have
knowledge about which libraries are Mercury libraries,
so it doesn't know to link with the static versions of
those libraries if MERCURY_LINKAGE is set to "static".

configure.in:
bindist/bindist.configure.in:
bindist/bindist.build_vars.in:
	Work out whether `.lpic_o' files are needed.

compiler/modules.m:
	Add `.lpic_o' to the list of grade or architecture
	dependent files.

NEWS:
README.Linux:
compiler/options.m:
doc/user_guide.texi:
	Document MERCURY_LINKAGE, LINKAGE, --linkage,
	--mercury-linkage and -R.

compiler/options_file.m:
compiler/make.program_target.m:
	Handle LINKAGE and MERCURY_LINKAGE variables.

	Allow LIBGRADES, LINKAGE and MERCURY_LINKAGE to be target-specific.

scripts/mmc.in:
	Set up the default linkage using the MERCURY_LINKAGE
	variable.
	
compiler/compile_target_code.m:
	Build `.lpic_o' files.

	Work out which type of object files to link with.

	When linking statically with Mercury libraries,
	find the absolute pathname for the `.a' file
	for each Mercury library, and pass that to ml,
	rather than just using `-lname'.

	Pass `-R' options to ml for each link library
	directory.

compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/mercury_compile.m:
	Specify which type of object files to build.

compiler/make.program_target.m:
compiler/make.module_target.m:
	Make sure all generated object files are cleaned up.

compiler/prog_io.m:
	Add a better message for files which can't be found.

compiler/make.util.m:
	Add `.lpic_o' to the list of extensions.

compiler/Mmakefile:
profiler/Mmakefile:
deep_profiler/Mmakefile:
	Pass `--linkage shared' to mmc (`--shared' is in MLFLAGS).


Index: NEWS
===================================================================
RCS file: /home/mercury1/repository/mercury/NEWS,v
retrieving revision 1.282
diff -u -u -r1.282 NEWS
--- NEWS	25 Nov 2002 11:53:15 -0000	1.282
+++ NEWS	29 Nov 2002 05:52:54 -0000
@@ -1,3 +1,11 @@
+NEWS since Mercury release 0.11:
+------------------------------
+
+* It's now easier to use shared libraries on Linux/x86 systems with
+  `mmc --make'.  See the documentation for the `--mercury-linkage'
+  and `--linkage' options and the MERCURY_LINKAGE Mmake
+  variable in the Mercury User's Guide.
+
 NEWS for Mercury release 0.11:
 ------------------------------
 
Index: README.Linux
===================================================================
RCS file: /home/mercury1/repository/mercury/README.Linux,v
retrieving revision 1.14
diff -u -u -r1.14 README.Linux
--- README.Linux	19 Dec 1999 15:54:17 -0000	1.14
+++ README.Linux	29 Nov 2002 05:13:46 -0000
@@ -27,6 +27,8 @@
 To use the shared libraries, you must compile your program with
 `mmc --pic-reg' and link with `ml --shared' or add 
 `MGNUCFLAGS=--pic-reg' and `MLFLAGS=--shared' to your Mmake file.
+If you are using `mmc --make' you can set the MERCURY_LINKAGE environment
+variable to "shared" or use `mmc --make --linkage shared'.
 
 Mercury code compiled with `--pic-reg' or with gcc's `-fpic' option has
 what we shall call "PIC linkage", whereas Mercury code compiled without
Index: configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/configure.in,v
retrieving revision 1.341
diff -u -u -r1.341 configure.in
--- configure.in	25 Nov 2002 11:53:16 -0000	1.341
+++ configure.in	29 Nov 2002 05:45:07 -0000
@@ -2537,12 +2537,18 @@
 SHLIB_RPATH_SEP=" -Wl,-rpath,"
 CFLAGS_FOR_PIC="-fpic -DMR_PIC"
 EXT_FOR_PIC_OBJECTS=pic_o
+# Object files with extension $EXT_FOR_LINK_WITH_PIC_OBJECTS are used
+# in executables which are linked with shared Mercury libraries.
+# EXT_FOR_LINK_WITH_PIC_OBJECTS should be `lpic_o' if `-DMR_PIC_REG'
+# has any effect (currently only on x86), or `o' otherwise.
+EXT_FOR_LINK_WITH_PIC_OBJECTS=lpic_o
 EXT_FOR_SHARED_LIB=$LIB_SUFFIX
 USE_DLLS=no
 # The following variables specify options to $LINK_SHARED_OBJ to
 # allow/disallow unresolved symbols when building shared libraries.
 ALLOW_UNDEFINED=""
 ERROR_UNDEFINED=""
+DEFAULT_LINKAGE="shared"
 
 case "$host" in
 	i*86-*-linux|i*86-*-linux-gnu)
@@ -2582,10 +2588,12 @@
 			AC_MSG_RESULT(no)
 			;;
 		esac
+		DEFAULT_LINKAGE=static
 		;;
 	m68*-linux|m68*-linux-gnu)
 		AC_MSG_RESULT(yes)
 		EXT_FOR_SHARED_LIB=so
+		EXT_FOR_LINK_WITH_PIC_OBJECTS=o
 		;;
 	i*86-*-freebsd*)
 		# From Cornelis van der Laan <nils at ims.uni-stuttgart.de>
@@ -2598,6 +2606,7 @@
 		EXE_RPATH_SEP=" -R"
 		SHLIB_RPATH_OPT="-R"
 		SHLIB_RPATH_SEP=" -R"
+		DEFAULT_LINKAGE=static
 		;;
 	i*86-*-solaris2.*)
 		AC_MSG_RESULT(yes)
@@ -2625,6 +2634,7 @@
 		SHLIB_RPATH_OPT="-R"
 		SHLIB_RPATH_SEP=" -R"
 		EXT_FOR_SHARED_LIB=so
+		DEFAULT_LINKAGE=static
 		;;
 	sparc-sun-solaris2.*)
 		AC_MSG_RESULT(yes)
@@ -2639,6 +2649,7 @@
 		SHLIB_RPATH_SEP=" -R"
 		CFLAGS_FOR_PIC="-fpic -DMR_PIC"	# used only for libgc.{a,so}
 		EXT_FOR_PIC_OBJECTS=o
+		EXT_FOR_LINK_WITH_PIC_OBJECTS=o
 		#
 		# Note that despite the above definition of CFLAGS_FOR_PIC,
 		# we don't use `-fpic' for shared libraries on Solaris
@@ -2670,6 +2681,7 @@
 		# in runtime/machdeps/i386_regs.h).
 
 		EXT_FOR_SHARED_LIB=so
+		DEFAULT_LINKAGE=static
 		;;
 	alpha*-dec-osf*)
 		AC_MSG_RESULT(yes)
@@ -2698,6 +2710,7 @@
 		# -fpic not needed on Alpha/OSF, since it is the default
 		CFLAGS_FOR_PIC=
 		EXT_FOR_PIC_OBJECTS=o
+		EXT_FOR_LINK_WITH_PIC_OBJECTS=o
 		;;
 	mips-sgi-irix5.*)
 		LINK_SHARED_OBJ="ld -shared \
@@ -2714,6 +2727,7 @@
 		# -fpic not needed on IRIX, since it is the default
 		CFLAGS_FOR_PIC=
 		EXT_FOR_PIC_OBJECTS=o
+		EXT_FOR_LINK_WITH_PIC_OBJECTS=o
 		# shared libraries are incompatible with gcc non-local gotos,
 		case "$GRADE" in
 		reg.gc | none.gc | hlc.gc)
@@ -2735,12 +2749,15 @@
 		AC_MSG_RESULT(disabled for now because it is untested)
 
 		CFLAGS_FOR_PIC=
+		DEFAULT_LINKAGE=static
 		;;
 	*)
 		# CFLAGS_FOR_PIC is used by boehm_gc/Makefile when creating
 		# libgc.a.  If the system doesn't support shared libraries,
 		# then we should set it to empty, not `-fpic'.
 		CFLAGS_FOR_PIC=
+		EXT_FOR_LINK_WITH_PIC_OBJECTS=o
+		DEFAULT_LINKAGE=static
 		AC_MSG_RESULT(no)
 		;;
 esac
@@ -2768,11 +2785,13 @@
 AC_SUBST(SHLIB_RPATH_SEP)
 AC_SUBST(CFLAGS_FOR_PIC)
 AC_SUBST(EXT_FOR_PIC_OBJECTS)
+AC_SUBST(EXT_FOR_LINK_WITH_PIC_OBJECTS)
 AC_SUBST(EXT_FOR_SHARED_LIB)
 AC_SUBST(EXT_FOR_EXE)
 AC_SUBST(USE_DLLS)
 AC_SUBST(SHARED_LIBS)
 AC_SUBST(SHARED_LIBS_SH)
+AC_SUBST(DEFAULT_LINKAGE)
 if test $USE_DLLS = "yes"; then
 	AC_DEFINE(MR_USE_DLLS)
 fi
Index: bindist/bindist.build_vars.in
===================================================================
RCS file: /home/mercury1/repository/mercury/bindist/bindist.build_vars.in,v
retrieving revision 1.21
diff -u -u -r1.21 bindist.build_vars.in
--- bindist/bindist.build_vars.in	24 Oct 2002 09:16:09 -0000	1.21
+++ bindist/bindist.build_vars.in	19 Nov 2002 06:32:40 -0000
@@ -29,6 +29,7 @@
 SHLIB_RPATH_SEP="@SHLIB_RPATH_SEP@"
 EXT_FOR_EXE="@EXT_FOR_EXE@"
 EXT_FOR_PIC_OBJECTS="@EXT_FOR_PIC_OBJECTS@"
+EXT_FOR_LINK_WITH_PIC_OBJECTS="@EXT_FOR_LINK_WITH_PIC_OBJECTS@"
 EXT_FOR_SHARED_LIB="@EXT_FOR_SHARED_LIB@"
 CFLAGS_FOR_PIC="@CFLAGS_FOR_PIC@"
 SHARED_LIBS='@SHARED_LIBS@'
@@ -51,6 +52,7 @@
 LIB_LIBPATH="@LIB_LIBPATH@"
 LINK_LIB="@LINK_LIB@"
 LINK_OPT_SEP="@LINK_OPT_SEP@"
+DEFAULT_LINKAGE="@DEFAULT_LINKAGE@"
 FIX_PATH_FOR_CC="@FIX_PATH_FOR_CC@"
 MATH_LIB="@MATH_LIB@"
 CGIDIR="@CGIDIR@"
Index: bindist/bindist.configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/bindist/bindist.configure.in,v
retrieving revision 1.45
diff -u -u -r1.45 bindist.configure.in
--- bindist/bindist.configure.in	4 Nov 2002 06:30:39 -0000	1.45
+++ bindist/bindist.configure.in	19 Nov 2002 01:19:57 -0000
@@ -62,6 +62,7 @@
 AC_SUBST(SHLIB_RPATH_SEP)
 AC_SUBST(EXT_FOR_EXE)
 AC_SUBST(EXT_FOR_PIC_OBJECTS)
+AC_SUBST(EXT_FOR_LINK_WITH_PIC_OBJECTS)
 AC_SUBST(EXT_FOR_SHARED_LIB)
 AC_SUBST(SHARED_LIBS)
 AC_SUBST(HAVE_DELAY_SLOT)
@@ -83,6 +84,7 @@
 AC_SUBST(LIB_LIBPATH)
 AC_SUBST(LINK_LIB)
 AC_SUBST(LINK_OPT_SEP)
+AC_SUBST(DEFAULT_LINKAGE)
 AC_SUBST(FIX_PATH_FOR_CC)
 AC_SUBST(CYGPATH)
 AC_SUBST(MATH_LIB)
Index: compiler/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/Mmakefile,v
retrieving revision 1.62
diff -u -u -r1.62 Mmakefile
--- compiler/Mmakefile	25 Sep 2002 16:36:39 -0000	1.62
+++ compiler/Mmakefile	29 Nov 2002 02:26:31 -0000
@@ -51,6 +51,7 @@
 MLOBJS :=	../main.$O $(MLOBJS)
 ALL_MLLIBS =	$(MLLIBS) $(EXTRA_MLLIBS) $(GCC_BACKEND_LIBS)
 MLFLAGS +=	--no-main --shared
+MCFLAGS +=	--no-main --linkage shared
 
 #
 # Work-around for a fixed limit: on alpha-dec-osf3.2, if we compile with
@@ -64,6 +65,7 @@
 #
 ifeq ($(FULLARCH),alpha-dec-osf3.2)
 MLFLAGS += --static
+MCFLAGS += --linkage static
 endif
 
 #-----------------------------------------------------------------------------#
Index: compiler/compile_target_code.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/compile_target_code.m,v
retrieving revision 1.28
diff -u -u -r1.28 compile_target_code.m
--- compiler/compile_target_code.m	20 Nov 2002 12:32:58 -0000	1.28
+++ compiler/compile_target_code.m	29 Nov 2002 06:08:13 -0000
@@ -25,6 +25,7 @@
 	% files.
 :- type pic
 	--->    pic
+	;	link_with_pic
 	;       non_pic
 	.
 
@@ -101,6 +102,14 @@
 :- pred link_module_list(list(string), bool, io__state, io__state).
 :- mode link_module_list(in, out, di, uo) is det.
 
+	% get_linkage_info(TargetType, PIC, ObjExt)
+	%
+	% Work out whether we should be using position independent
+	% code, and what object extension should be used.
+:- pred get_linkage_info(linked_target_type, pic, string,
+		io__state, io__state).
+:- mode get_linkage_info(in, out, out, di, uo) is det.
+
 %-----------------------------------------------------------------------------%
 	% Code to deal with `--split-c-files'.
 
@@ -144,7 +153,7 @@
 :- implementation.
 
 :- import_module libs__globals, libs__options, libs__handle_options.
-:- import_module hlds__passes_aux, libs__trace_params.
+:- import_module hlds__error_util, hlds__passes_aux, libs__trace_params.
 :- import_module parse_tree__prog_out.
 
 :- import_module ll_backend__llds_out.	% for llds_out__make_init_name and
@@ -310,6 +319,10 @@
 		globals__io_lookup_string_option(pic_object_file_extension,
 			ObjExt)
 	;
+		{ PIC = link_with_pic },
+		globals__io_lookup_string_option(
+			link_with_pic_object_file_extension, ObjExt)
+	;
 		{ PIC = non_pic },
 		globals__io_lookup_string_option(object_file_extension, ObjExt)
 	),
@@ -337,15 +350,6 @@
 		CompilerType = unknown
 	},
 
-	(
-		{ PIC = pic },
-		globals__io_lookup_string_option(cflags_for_pic,
-			CFLAGS_FOR_PIC)
-	;
-		{ PIC = non_pic },
-		{ CFLAGS_FOR_PIC = "" }
-	),
-
 	globals__io_lookup_bool_option(use_subdirs, UseSubdirs),
 	globals__io_lookup_bool_option(split_c_files, SplitCFiles),
 	{ (UseSubdirs = yes ; SplitCFiles = yes) ->
@@ -456,12 +460,30 @@
 	;
 		ProfileDeepOpt = ""
 	},
-	globals__io_lookup_bool_option(pic_reg, PIC_Reg),
+
+	(
+		{ PIC = pic },
+		globals__io_lookup_string_option(cflags_for_pic,
+			CFLAGS_FOR_PIC),
+		{ 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)
+	),
 	{ 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_Opt = ""
 	},
+
 	globals__io_get_tags_method(Tags_Method),
 	{ Tags_Method = high ->
 		TagsOpt = "-DMR_HIGHTAGS "
@@ -739,7 +761,12 @@
 
 	{ file_name_to_module_name(OutputFileName, MainModuleName) },
 
-	globals__io_lookup_string_option(object_file_extension, Obj),
+	globals__io_lookup_bool_option(compile_to_shared_lib,
+		CompileToSharedLib),
+	{ TargetType =
+		(CompileToSharedLib = yes -> shared_library ; executable) },
+	get_linkage_info(TargetType, _, Obj),
+
 	globals__io_get_target(Target),
 	globals__io_lookup_bool_option(split_c_files, SplitFiles),
 	io__output_stream(OutputStream),
@@ -767,10 +794,6 @@
 	( { MakeLibCmdOK = no } ->
     	    { Succeeded = no }
 	;
-	    globals__io_lookup_bool_option(compile_to_shared_lib,
-			CompileToSharedLib),
-	    { TargetType =
-		(CompileToSharedLib = yes -> shared_library ; executable) },
     	    ( { TargetType = executable } ->
 		{ list__map(
 		    (pred(ModuleStr::in, ModuleName::out) is det :-
@@ -831,8 +854,10 @@
 	{ compute_grade(Globals, Grade) },
 
 	standard_library_directory_option(StdLibOpt),
-	globals__io_lookup_string_option(object_file_extension, Obj),
-	{ string__append("_init", Obj, InitObj) },
+
+	get_linkage_info(executable, PIC, ObjExt),
+	{ InitObj = "_init" ++ ObjExt },
+		
 	module_name_to_file_name(ModuleName, "_init.c", yes, InitCFileName),
 	module_name_to_file_name(ModuleName, InitObj, yes, InitObjFileName),
 
@@ -900,7 +925,7 @@
 		    maybe_write_string(Verbose,
 			"% Compiling initialization file...\n"),
 
-		    compile_c_file(ErrorStream, non_pic, InitCFileName,
+		    compile_c_file(ErrorStream, PIC, InitCFileName,
 		    	InitObjFileName, CompileOK),
 		    maybe_report_stats(Stats),
 		    ( { CompileOK = no } ->
@@ -980,22 +1005,66 @@
 				LinkLibraryDirectoriesList),
 		{ join_quoted_string_list(LinkLibraryDirectoriesList, "-L", "",
 				" ", LinkLibraryDirectories) },
+		globals__io_lookup_accumulating_option(
+				runtime_link_library_directories,
+				RuntimeLinkLibraryDirectoriesList),
+		{ join_quoted_string_list(RuntimeLinkLibraryDirectoriesList,
+				"-R", "", " ",
+				RuntimeLinkLibraryDirectories) },
+
+		%
+		% Pass either `-llib' or `PREFIX/lib/GRADE/FULLARCH/liblib.a',
+		% depending on whether we are linking with static or shared
+		% Mercury libraries.
+		%
+		globals__io_lookup_accumulating_option(
+				mercury_library_directories,
+				MercuryLibDirs0),
+		globals__io_lookup_string_option(fullarch, FullArch),
+		{ MercuryLibDirs = list__map(
+				(func(LibDir) = LibDir/"lib"/Grade/FullArch),
+				MercuryLibDirs0) },
 		globals__io_lookup_accumulating_option(link_libraries,
-				LinkLibrariesList),
-		{ join_quoted_string_list(LinkLibrariesList, "-l", "", " ",
-				LinkLibraries) },
-
-		% Note that LDFlags may contain `-l' options
-		% so it should come after Objects.
-		{ string__append_list(
-			["ml --grade ", Grade, " ", SharedLibOpt,
-			Target_Debug_Opt, TraceOpt, StdLibOpt,
-			LinkFlags, " ", LinkLibraryDirectories,
-			" -- -o ", OutputFileName, " ", Objects, " ",
-			LDFlags, " ", LinkLibraries],
-			LinkCmd) },
-		invoke_shell_command(ErrorStream, verbose_commands,
-			LinkCmd, LinkSucceeded),
+				LinkLibrariesList0),
+		list__map_foldl2(process_link_library(MercuryLibDirs),
+				LinkLibrariesList0, LinkLibrariesList,
+				yes, LibrariesSucceeded),	
+		(
+			{ LibrariesSucceeded = yes },
+			{ join_quoted_string_list(LinkLibrariesList,
+				"", "", " ", LinkLibraries) },
+
+			globals__io_lookup_string_option(linkage, Linkage),
+			{ LinkageOpt = "--" ++ Linkage },
+			globals__io_lookup_maybe_string_option(
+				mercury_standard_library_directory,
+				MaybeStdLibDir),
+			globals__io_lookup_string_option(mercury_linkage,
+				MercuryLinkage),
+			{ MaybeStdLibDir = yes(_),
+				MercuryLinkageOpt =
+					"--mercury-libs " ++ MercuryLinkage
+			; MaybeStdLibDir = no,
+				MercuryLinkageOpt = ""
+			},
+
+			% Note that LDFlags may contain `-l' options
+			% so it should come after Objects.
+			{ string__append_list(
+				["ml --grade ", Grade, " ", SharedLibOpt,
+				Target_Debug_Opt, TraceOpt, StdLibOpt,
+				LinkageOpt, " ", MercuryLinkageOpt, " ",
+				LinkFlags, " ", LinkLibraryDirectories, " ",
+				RuntimeLinkLibraryDirectories,
+				" -- -o ", OutputFileName, " ", Objects, " ",
+				LDFlags, " ", LinkLibraries],
+				LinkCmd) },
+			invoke_shell_command(ErrorStream, verbose_commands,
+				LinkCmd, LinkSucceeded)
+		;
+			{ LibrariesSucceeded = no },
+			{ LinkSucceeded = no }
+		),
 		maybe_report_stats(Stats),
 		globals__io_lookup_bool_option(use_grade_subdirs,
 			UseGradeSubdirs),
@@ -1020,6 +1089,47 @@
 		)
 	).
 
+:- pred process_link_library(list(dir_name), string, string, bool, bool,
+		io__state, io__state).
+:- mode process_link_library(in, in, out, in, out, di, uo) is det.
+
+process_link_library(MercuryLibDirs, LibName, LinkerOpt, !Succeeded) -->
+	globals__io_lookup_string_option(mercury_linkage, MercuryLinkage),
+	globals__io_lookup_accumulating_option(mercury_libraries, MercuryLibs),
+	( { 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),
+		globals__io_set_option(use_grade_subdirs, bool(no)),
+		globals__io_set_option(use_grade_subdirs,
+			bool(UseGradeSubdirs)),
+
+		{ file_name_to_module_name(LibName, LibModuleName) },
+		globals__io_lookup_string_option(library_extension, LibExt),
+		module_name_to_lib_file_name("lib", LibModuleName, LibExt,
+			no, LibFileName),
+
+		io__input_stream(InputStream),
+		search_for_file_returning_dir(MercuryLibDirs, LibFileName,
+			SearchResult),
+		(
+			{ SearchResult = ok(DirName) },
+			{ LinkerOpt = DirName/LibFileName },
+			io__seen,
+			io__set_input_stream(InputStream, _)
+		;
+			{ SearchResult = error(Error) },
+			{ LinkerOpt = "" },
+			write_error_pieces_maybe_with_context(no,
+				0, [words(Error)]),
+			{ !:Succeeded = no }
+		)	
+	;
+		{ LinkerOpt = "-l" ++ LibName }
+	).
+
 :- pred create_archive(io__output_stream, file_name, list(file_name),
 		bool, io__state, io__state).
 :- mode create_archive(in, in, in, out, di, uo) is det.
@@ -1039,6 +1149,70 @@
 		" && ", RanLib, " ", LibFileName]) },
 	invoke_system_command(ErrorStream, verbose_commands,
 		MakeLibCmd, MakeLibCmdOK).
+
+get_linkage_info(FileType, ObjectCodeType, ObjExtToUse) -->
+	globals__io_lookup_string_option(pic_object_file_extension, PicObjExt),
+	globals__io_lookup_string_option(link_with_pic_object_file_extension,
+		LinkWithPicObjExt),
+	globals__io_lookup_string_option(object_file_extension, ObjExt),
+	globals__io_lookup_string_option(mercury_linkage, MercuryLinkage),
+	globals__io_lookup_bool_option(gcc_global_registers, GCCGlobals),
+	globals__io_lookup_bool_option(pic, PIC),
+	(
+	    { PIC = yes },
+		% We've been explicitly told to use position independent code.
+	    { PicObjExt = ObjExt ->
+		ObjectCodeType = non_pic,
+		ObjExtToUse = ObjExt
+	    ;
+		ObjectCodeType = pic,
+		ObjExtToUse = PicObjExt
+	    }
+	;
+    	    { PIC = no },
+	    {
+		FileType = static_library,
+		ObjectCodeType = non_pic,
+		ObjExtToUse = ObjExt
+	    ;
+		FileType = shared_library,
+		( PicObjExt = ObjExt ->
+			ObjectCodeType = non_pic,
+			ObjExtToUse = ObjExt
+		;
+			ObjectCodeType = pic,
+			ObjExtToUse = PicObjExt
+		)
+	    ;
+		FileType = executable,
+		( MercuryLinkage = "shared" ->
+			ObjExtToUse = LinkWithPicObjExt,
+			(
+				PicObjExt = ObjExt
+			->
+				ObjectCodeType = non_pic
+			;
+				% 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.
+				( LinkWithPicObjExt = PicObjExt
+				; GCCGlobals = no
+				)
+			->
+				ObjectCodeType = pic
+			;
+				ObjectCodeType = link_with_pic
+			)
+		; MercuryLinkage = "static" ->
+			ObjectCodeType = non_pic,
+			ObjExtToUse = ObjExt
+		;
+			error("unknown linkage " ++ MercuryLinkage)
+		)
+	    }
+	).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.160
diff -u -u -r1.160 handle_options.m
--- compiler/handle_options.m	13 Nov 2002 06:14:58 -0000	1.160
+++ compiler/handle_options.m	29 Nov 2002 06:31:48 -0000
@@ -464,6 +464,12 @@
 		[]
 	),
 
+	option_implies(compile_to_shared_lib, pic, bool(yes)),
+	option_implies(pic, pic_reg, bool(yes)),
+	option_implies(compile_to_shared_lib, linkage, string("shared")),
+	option_implies(compile_to_shared_lib, mercury_linkage,
+		string("shared")),
+
 	% --high-level-code disables the use of low-level gcc extensions
 	option_implies(highlevel_code, gcc_non_local_gotos, bool(no)),
 	option_implies(highlevel_code, gcc_global_registers, bool(no)),
@@ -964,6 +970,11 @@
 			link_library_directories, LinkLibDirs),
 		globals__io_set_option(link_library_directories,
 			accumulating(LinkLibDirs ++ ExtraLinkLibDirs)),
+
+		globals__io_lookup_accumulating_option(
+			runtime_link_library_directories, Rpath),
+		globals__io_set_option(runtime_link_library_directories,
+			accumulating(Rpath ++ ExtraLinkLibDirs)),
 
 		{ ExtraCIncludeDirs = list__map(
 			(func(MercuryLibDir) =
Index: compiler/make.module_target.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.module_target.m,v
retrieving revision 1.17
diff -u -u -r1.17 make.module_target.m
--- compiler/make.module_target.m	30 Oct 2002 13:31:48 -0000	1.17
+++ compiler/make.module_target.m	19 Nov 2002 16:16:01 -0000
@@ -43,7 +43,8 @@
 		).
 
 	% Find the foreign code files generated when a module is processed.
-:- pred external_foreign_code_files(module_imports::in,
+	% The `pic' field is only used for C foreign code.
+:- pred external_foreign_code_files(pic::in, module_imports::in,
 	list(foreign_code_file)::out, io__state::di, io__state::uo) is det.
 
 %-----------------------------------------------------------------------------%
@@ -314,7 +315,7 @@
 build_target_2(ModuleName, target_code_to_object_code(PIC),
 		Imports, _, ErrorStream, Succeeded, Info0, Info) -->
 	get_target_code_to_object_code_foreign_files(ModuleName,
-		ForeignCodeFiles, Info0, Info),
+		PIC, ForeignCodeFiles, Info0, Info),
 	globals__io_get_target(CompilationTarget),
 
 	{ CompileTargetCode =
@@ -479,13 +480,14 @@
 compilation_task(_, asm_code(PIC)) =
 		process_module(compile_to_target_code) - 
 			( PIC = pic -> ["--pic"] ; [] ).
-compilation_task(Globals, object_code(PIC)) =
+compilation_task(_, object_code(PIC)) =
 			target_code_to_object_code(PIC) - Flags :-
-		globals__get_target(Globals, Target),
-		( PIC = pic ->
-			Flags = ( Target = asm -> ["--pic"] ; ["--pic-reg"] )
-		;
-			Flags = []
+		% `--pic-reg' is harmless for architectures and grades where
+		% it is not needed (it's only needed for grades using
+		% GCC global register variables on x86).
+		( PIC = pic, Flags = ["--pic", "--pic-reg"]
+		; PIC = link_with_pic, Flags = ["--pic-reg"]
+		; PIC = non_pic, Flags = []
 		).
 
 	% Find the files which could be touched by a compilation task.
@@ -543,8 +545,9 @@
 	(
 	    { Task = compile_to_target_code }
 	->
-	    list__map_foldl(external_foreign_code_files, ModuleImportsList,
-			ForeignCodeFileList),
+	    list__map_foldl(
+		    external_foreign_code_files(target_type_to_pic(FileType)),
+	    	    ModuleImportsList, ForeignCodeFileList),
 	    { ForeignCodeFiles = list__map(
 	    		(func(ForeignFile) = ForeignFile ^ target_file),
 			list__condense(ForeignCodeFileList)) },
@@ -632,18 +635,19 @@
 
 touched_files(TargetFile, target_code_to_object_code(_),
 		[TargetFile], ForeignObjectFiles, Info0, Info) -->
-	{ TargetFile = ModuleName - _ },
+	{ TargetFile = ModuleName - FileType },
 	get_target_code_to_object_code_foreign_files(ModuleName,
+		target_type_to_pic(FileType),
 		ForeignCodeFileList, Info0, Info),
 	{ ForeignObjectFiles = list__map(
 			(func(ForeignFile) = ForeignFile ^ object_file),
 			ForeignCodeFileList) }.
 
-:- pred get_target_code_to_object_code_foreign_files(module_name::in, 
+:- pred get_target_code_to_object_code_foreign_files(module_name::in, pic::in,
 		list(foreign_code_file)::out, make_info::in, make_info::out,
 		io__state::di, io__state::uo) is det.
 
-get_target_code_to_object_code_foreign_files(ModuleName, ForeignCodeFiles,
+get_target_code_to_object_code_foreign_files(ModuleName, PIC, ForeignCodeFiles,
 		Info0, Info) -->
 	get_module_dependencies(ModuleName, MaybeImports, Info0, Info1),
 	{ MaybeImports = yes(Imports0) ->
@@ -658,8 +662,8 @@
 	},
 
 	%
-	% For `--target asm' there is only one `.s' file per module
-	% so we should compile the foreign code for 
+	% For `--target asm' there is only one `.s' file per source file
+	% so we should compile the foreign code for all nested sub-modules.
 	%
 	globals__io_get_target(CompilationTarget),
 	( { CompilationTarget = asm } ->
@@ -686,17 +690,18 @@
 		{ Info = Info1 },
 		{ ModuleImportsList = [Imports] }
 	),
-	list__map_foldl(external_foreign_code_files,
+	list__map_foldl(external_foreign_code_files(PIC),
 		ModuleImportsList, ForeignCodeFileLists),
 	{ ForeignCodeFiles = list__condense(ForeignCodeFileLists) }.
 
-external_foreign_code_files(Imports, ForeignFiles) -->
+external_foreign_code_files(PIC, Imports, ForeignFiles) -->
 	%
 	% Find externally compiled foreign code files for
 	% `:- pragma foreign_proc' declarations.
 	%
+	globals__io_get_globals(Globals),
+	{ ObjExt = target_extension(Globals, object_code(PIC)) },
 	globals__io_get_target(CompilationTarget),
-	globals__io_lookup_string_option(object_file_extension, ObjExt),
 	{ ModuleName = Imports ^ module_name },
 	(
 		{ CompilationTarget = asm },
@@ -762,5 +767,16 @@
 		% No external file is generated for this foreign language.
 		{ ForeignFiles = [] }
 	).
+
+:- func target_type_to_pic(module_target_type) = pic.
+
+target_type_to_pic(TargetType) =
+		( TargetType = asm_code(PIC) ->
+			PIC
+		; TargetType = object_code(PIC) ->
+			PIC
+		;
+			non_pic
+		).
 
 %-----------------------------------------------------------------------------%
Index: compiler/make.program_target.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.program_target.m,v
retrieving revision 1.15
diff -u -u -r1.15 make.program_target.m
--- compiler/make.program_target.m	31 Oct 2002 14:47:01 -0000	1.15
+++ compiler/make.program_target.m	29 Nov 2002 06:59:49 -0000
@@ -34,6 +34,15 @@
 :- import_module hlds__passes_aux.
 
 make_linked_target(MainModuleName - FileType, Succeeded, Info0, Info) -->
+	build_with_module_options(MainModuleName, [],
+		make_linked_target_2(MainModuleName - FileType),
+		Succeeded, Info0, Info).
+
+:- pred make_linked_target_2(linked_target_file::in, list(string)::in,
+		bool::out, make_info::in, make_info::out,
+		io__state::di, io__state::uo) is det.
+
+make_linked_target_2(MainModuleName - FileType, _, Succeeded, Info0, Info) -->
     find_reachable_local_modules(MainModuleName, DepsSuccess,
 		AllModules, Info0, Info1),
     globals__io_lookup_bool_option(keep_going, KeepGoing),
@@ -41,15 +50,7 @@
 	{ Succeeded = no },
 	{ Info = Info1 }
     ;
-	globals__io_lookup_string_option(pic_object_file_extension, PicObjExt),
-	globals__io_lookup_string_option(object_file_extension, ObjExt),
-	{ FileType = shared_library, PicObjExt \= ObjExt ->
-		ObjectCodeType = pic,
-		ObjExtToUse = PicObjExt
-	;
-		ObjectCodeType = non_pic,
-		ObjExtToUse = ObjExt
-	},
+	get_linkage_info(FileType, PIC, ObjExtToUse),
 
 	%
 	% Build the `.c' files first so that errors are
@@ -59,11 +60,11 @@
 	{
 		CompilationTarget = c,
 		IntermediateTargetType = c_code,
-		ObjectTargetType = object_code(ObjectCodeType)
+		ObjectTargetType = object_code(PIC)
 	;
 		CompilationTarget = asm,
-		IntermediateTargetType = asm_code(ObjectCodeType),
-		ObjectTargetType = object_code(ObjectCodeType)
+		IntermediateTargetType = asm_code(PIC),
+		ObjectTargetType = object_code(PIC)
 	;
 		CompilationTarget = il,
 		IntermediateTargetType = il_code,
@@ -97,12 +98,11 @@
 	    { BuildDepsResult \= error }
 	->
 	    build_with_check_for_interrupt(
-		build_with_module_options_and_output_redirect(
-			MainModuleName, [],
+		build_with_output_redirect(MainModuleName, 
 			build_linked_target(MainModuleName, FileType,
 				OutputFileName, MaybeTimestamp, AllModules,
 				ObjModules, CompilationTarget, ObjExtToUse,
-				DepsSuccess, BuildDepsResult)),
+				PIC, DepsSuccess, BuildDepsResult)),
 		linked_target_cleanup(MainModuleName, FileType, OutputFileName,
 			CompilationTarget),
 		Succeeded, Info7, Info)
@@ -152,14 +152,14 @@
 
 :- pred build_linked_target(module_name::in, linked_target_type::in,
 	file_name::in, maybe_error(timestamp)::in, set(module_name)::in,
-	list(module_name)::in, compilation_target::in, string::in, bool::in,
-	dependencies_result::in, list(string)::in, io__output_stream::in,
+	list(module_name)::in, compilation_target::in, string::in, pic::in,
+	bool::in, dependencies_result::in, io__output_stream::in,
 	bool::out, make_info::in, make_info::out,
 	io__state::di, io__state::uo) is det.
 
 build_linked_target(MainModuleName, FileType, OutputFileName, MaybeTimestamp,
-		AllModules, ObjModules, CompilationTarget, ObjExtToUse,
-		DepsSuccess, BuildDepsResult, _, ErrorStream, Succeeded,
+		AllModules, ObjModules, CompilationTarget, ObjExtToUse, PIC,
+		DepsSuccess, BuildDepsResult, ErrorStream, Succeeded,
 		Info0, Info) -->
 	globals__io_lookup_maybe_string_option(pre_link_command,
 		MaybePreLinkCommand),
@@ -175,7 +175,7 @@
 	( { PreLinkSucceeded = yes } ->
 		build_linked_target_2(MainModuleName, FileType, OutputFileName,
 			MaybeTimestamp, AllModules, ObjModules,
-			CompilationTarget, ObjExtToUse, DepsSuccess,
+			CompilationTarget, ObjExtToUse, PIC, DepsSuccess,
 			BuildDepsResult, ErrorStream, Succeeded,
 			Info0, Info)
 	;
@@ -185,12 +185,12 @@
 
 :- pred build_linked_target_2(module_name::in, linked_target_type::in,
 	file_name::in, maybe_error(timestamp)::in, set(module_name)::in,
-	list(module_name)::in, compilation_target::in, string::in, bool::in,
-	dependencies_result::in, io__output_stream::in, bool::out,
+	list(module_name)::in, compilation_target::in, string::in, pic::in,
+	bool::in, dependencies_result::in, io__output_stream::in, bool::out,
 	make_info::in, make_info::out, io__state::di, io__state::uo) is det.
 
 build_linked_target_2(MainModuleName, FileType, OutputFileName, MaybeTimestamp,
-		AllModules, ObjModules, CompilationTarget, ObjExtToUse,
+		AllModules, ObjModules, CompilationTarget, ObjExtToUse, PIC,
 		DepsSuccess, BuildDepsResult, ErrorStream, Succeeded,
 		Info0, Info) -->
 	globals__io_lookup_accumulating_option(link_objects, LinkObjects),
@@ -284,7 +284,8 @@
 				MakeInfo0, MakeInfo),
 			(
 			    { MaybeImports = yes(Imports) },
-			    external_foreign_code_files(Imports, ForeignFiles)
+			    external_foreign_code_files(PIC,
+			    	Imports, ForeignFiles)
 			;
 			    { MaybeImports = no },
 			    % This error should have been detected earlier.
@@ -360,10 +361,7 @@
 		; CompilationTarget = asm
 		}
 	->
-		globals__io_lookup_string_option(object_file_extension,
-			ObjExt),
-		remove_file(MainModuleName, "_init.c", Info1, Info2),
-		remove_file(MainModuleName, "_init" ++ ObjExt, Info2, Info)
+		remove_init_files(MainModuleName, Info1, Info)
 	;
 		{ Info = Info1 }
 	).
@@ -371,6 +369,15 @@
 %-----------------------------------------------------------------------------%
 
 make_misc_target(MainModuleName - TargetType, Succeeded, Info0, Info) -->
+	build_with_module_options(MainModuleName, [],
+		make_misc_target(MainModuleName - TargetType), 
+		Succeeded, Info0, Info).
+
+:- pred make_misc_target(pair(module_name, misc_target_type)::in,
+		list(string)::in, bool::out, make_info::in, make_info::out,
+		io__state::di, io__state::uo) is det.
+
+make_misc_target(MainModuleName - TargetType, _, Succeeded, Info0, Info) -->
 	% Don't rebuild dependencies when cleaning up.
 	{ RebuildDeps = Info0 ^ rebuild_dependencies },
 	{ ( TargetType = clean ; TargetType = realclean ) ->
@@ -879,41 +886,82 @@
 
 remove_init_files(ModuleName, Info0, Info) -->
 	globals__io_lookup_string_option(object_file_extension, ObjExt),
-	list__foldl2(remove_file(ModuleName), ["_init.c", "_init" ++ ObjExt],
+	globals__io_lookup_string_option(pic_object_file_extension, PicObjExt),
+	globals__io_lookup_string_option(link_with_pic_object_file_extension,
+		LinkWithPicObjExt),
+	list__foldl2(remove_file(ModuleName), ["_init.c", "_init" ++ ObjExt,
+		"_init" ++ PicObjExt, "_init" ++ LinkWithPicObjExt],
 		Info0, Info).
 
 :- pred make_module_clean(module_name::in, make_info::in, make_info::out,
 		io__state::di, io__state::uo) is det.
 
-make_module_clean(ModuleName, Info0, Info) -->
+make_module_clean(ModuleName, !Info) -->
 	list__foldl2(remove_target_file(ModuleName),
-		[errors, c_code, c_header(mih),
-		object_code(pic), object_code(non_pic),
-		asm_code(pic), asm_code(non_pic),
-		il_code, java_code
-		],
-		Info0, Info1),
+		[errors, c_code, c_header(mih), il_code, java_code],
+		!Info),
 
 	list__foldl2(remove_file(ModuleName),
 		[".used", ".prof", ".derived_schema", ".base_schema"],
-		Info1, Info2),
+		!Info),
 
-	get_module_dependencies(ModuleName, MaybeImports, Info2, Info3),
-	(
-		{ MaybeImports = yes(Imports) },
-		external_foreign_code_files(Imports, ForeignCodeFiles),
-		list__foldl2(
-		    (pred(ForeignCodeFile::in, MakeInfo0::in, MakeInfo::out,
-		    		di, uo) is det -->
-			{ ForeignCodeFile = foreign_code_file(_,
-				TargetFile, ObjectFile) },
-			remove_file(TargetFile, MakeInfo0, MakeInfo1),
-			remove_file(ObjectFile, MakeInfo1, MakeInfo)
-		    ), ForeignCodeFiles, Info3, Info)
+	get_module_dependencies(ModuleName, MaybeImports,
+		!Info),
+	{
+		MaybeImports = yes(Imports),
+		FactTableFiles = Imports ^ fact_table_deps
 	;
-		{ MaybeImports = no },
-		{ Info = Info3 }
-	).
+		MaybeImports = no,
+		FactTableFiles = []
+	},
+
+	list__foldl2(
+		(pred(FactTableFile::in, !.Info::in, !:Info::out,
+				di, uo) is det -->
+			fact_table_file_name(ModuleName, FactTableFile,
+				".c", FactTableCFile),
+			remove_file(FactTableCFile, !Info)
+		), FactTableFiles, !Info),
+
+	{ CCodeModule = foreign_language_module_name(ModuleName, c) },
+	remove_file(CCodeModule, ".c", !Info),
+
+	%
+	% Remove object and  assembler files.
+	%
+	list__foldl2(
+	    (pred(PIC::in, !.Info::in, !:Info::out, di, uo) is det -->
+		globals__io_get_globals(Globals),
+		{ ObjExt = target_extension(Globals, object_code(PIC)) },
+		{ AsmExt = target_extension(Globals, asm_code(PIC)) },
+		remove_target_file(ModuleName, object_code(PIC), !Info),
+		remove_target_file(ModuleName, asm_code(PIC), !Info),
+		remove_file(CCodeModule, ObjExt, !Info),
+		remove_file(CCodeModule, AsmExt, !Info),
+		list__foldl2(
+		    (pred(FactTableFile::in, !.Info::in, !:Info::out,
+				di, uo) is det -->
+			fact_table_file_name(ModuleName, FactTableFile,
+				ObjExt, FactTableObjFile),
+			remove_file(FactTableObjFile, !Info)
+		    ), FactTableFiles, !Info)
+	    ),
+	    [pic, link_with_pic, non_pic], !Info),
+
+	%
+	% Remove IL foreign code files.
+	%
+	{ CSharpModule = foreign_language_module_name(ModuleName, csharp) },
+	remove_file(CSharpModule, foreign_language_file_extension(csharp),
+		!Info),
+	remove_file(CSharpModule, ".dll", !Info),
+	
+	{ McppModule = foreign_language_module_name(ModuleName,
+				managed_cplusplus) },
+	remove_file(McppModule,
+		foreign_language_file_extension(managed_cplusplus),
+		!Info),
+	remove_file(McppModule, ".dll", !Info).
 
 :- pred make_module_realclean(module_name::in, make_info::in, make_info::out,
 		io__state::di, io__state::uo) is det.
Index: compiler/make.util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.util.m,v
retrieving revision 1.10
diff -u -u -r1.10 make.util.m
--- compiler/make.util.m	30 Oct 2002 13:31:49 -0000	1.10
+++ compiler/make.util.m	19 Nov 2002 02:11:45 -0000
@@ -620,11 +620,15 @@
 target_extension(_, il_asm) = ".dll". % XXX ".exe" if the module contains main.
 target_extension(_, java_code) = ".java".
 target_extension(_, asm_code(non_pic)) = ".s".
+target_extension(_, asm_code(link_with_pic)) = ".s".
 target_extension(_, asm_code(pic)) = ".pic_s".
 target_extension(Globals, object_code(non_pic)) = Ext :-
 	globals__lookup_string_option(Globals, object_file_extension, Ext).
 target_extension(Globals, object_code(pic)) = Ext :-
 	globals__lookup_string_option(Globals, pic_object_file_extension, Ext).
+target_extension(Globals, object_code(link_with_pic)) = Ext :-
+	globals__lookup_string_option(Globals,
+		link_with_pic_object_file_extension, Ext).
 
 linked_target_file_name(ModuleName, executable, FileName) -->
 	globals__io_lookup_string_option(executable_file_extension, Ext),
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.268
diff -u -u -r1.268 mercury_compile.m
--- compiler/mercury_compile.m	22 Nov 2002 13:41:50 -0000	1.268
+++ compiler/mercury_compile.m	26 Nov 2002 01:45:32 -0000
@@ -387,8 +387,10 @@
 				TargetCodeOnly),
 		( { Result = ok, TargetCodeOnly = no } ->
 			io__output_stream(OutputStream),
+			get_linked_target_type(TargetType),
+			get_linkage_info(TargetType, PIC, _),
 			compile_target_code__assemble(OutputStream,
-				non_pic, ModuleName, AssembleOK),
+				PIC, ModuleName, AssembleOK),
 			maybe_set_exit_status(AssembleOK)
 		;
 			[]
@@ -1186,10 +1188,11 @@
 				% C compiler on that.
 				%
 				( { ContainsCCode = yes } ->
+					get_linked_target_type(TargetType),
+					compile_target_code__get_linkage_info(
+						TargetType, PIC, Obj),
 					module_name_to_file_name(ModuleName,
 						".c", no, CCode_C_File),
-					globals__io_lookup_string_option(
-						object_file_extension, Obj),
 					{ ForeignModuleName =
 						foreign_language_module_name(
 							ModuleName, c) },
@@ -1198,7 +1201,7 @@
 						yes, CCode_O_File),
 					io__output_stream(OutputStream),
 					compile_target_code__compile_c_file(
-						OutputStream, non_pic,
+						OutputStream, PIC,
 						CCode_C_File, CCode_O_File,
 						CompileOK),
 					maybe_set_exit_status(CompileOK),
@@ -1222,13 +1225,13 @@
 			;
 				module_name_to_file_name(ModuleName, ".c", no,
 					C_File),
-				globals__io_lookup_string_option(
-					object_file_extension, Obj),
+				get_linked_target_type(TargetType),
+				get_linkage_info(TargetType, PIC, Obj),
 				module_name_to_file_name(ModuleName, Obj, yes,
 					O_File),
 				io__output_stream(OutputStream),
 				compile_target_code__compile_c_file(
-					OutputStream, non_pic, C_File, O_File,
+					OutputStream, PIC, C_File, O_File,
 					CompileOK),
 				maybe_set_exit_status(CompileOK)
 			)
@@ -1270,6 +1273,14 @@
 		no_main
 	).
 
+:- pred get_linked_target_type(linked_target_type, io__state, io__state).
+:- mode get_linked_target_type(out, di, uo) is det.
+
+get_linked_target_type(LinkedTargetType) -->
+	globals__io_lookup_bool_option(compile_to_shared_lib, MakeSharedLib),
+	{ LinkedTargetType =
+		( MakeSharedLib = yes -> shared_library ; executable ) }.
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -3450,10 +3461,11 @@
 		compile_target_code__split_c_to_obj(ErrorStream, ModuleName,
 			NumChunks, Succeeded)
 	;
-		globals__io_lookup_string_option(object_file_extension, Obj),
+		get_linked_target_type(LinkedTargetType),
+		get_linkage_info(LinkedTargetType, PIC, Obj),
 		module_name_to_file_name(ModuleName, ".c", no, C_File),
 		module_name_to_file_name(ModuleName, Obj, yes, O_File),
-		compile_target_code__compile_c_file(ErrorStream, non_pic,
+		compile_target_code__compile_c_file(ErrorStream, PIC,
 			C_File, O_File, Succeeded)
 	).
 
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.253
diff -u -u -r1.253 modules.m
--- compiler/modules.m	15 Nov 2002 04:50:25 -0000	1.253
+++ compiler/modules.m	29 Nov 2002 05:22:22 -0000
@@ -989,15 +989,17 @@
 		->
 			SubDirName = "dirs"
 		;
-			% .$O and .pic_o files need to go in the
+			% .$O, .pic_o and .lpic_o files need to go in the
 			% same directory, so that using
 			% .$(EXT_FOR_PIC_OBJECTS) will work.
 			( Ext = ".o"
 			; Ext = ".$O"
+			; Ext = ".lpic_o"
 			; Ext = ".pic_o"
 			; Ext = "$(EXT_FOR_PIC_OBJECTS)"
 			; Ext = "_init.o"
 			; Ext = "_init.$O"
+			; Ext = "_init.lpic_o"
 			; Ext = "_init.pic_o"
 			; Ext = "_init.$(EXT_FOR_PIC_OBJECTS)"
 			)
@@ -1188,12 +1190,19 @@
 file_is_arch_or_grade_dependent(Globals, Ext) :-
 	globals__lookup_string_option(Globals, executable_file_extension, Ext).
 file_is_arch_or_grade_dependent(Globals, Ext) :-
-	globals__lookup_string_option(Globals, object_file_extension, ObjExt),
+	(
+		globals__lookup_string_option(Globals,
+			object_file_extension, ObjExt)
+	;
+		globals__lookup_string_option(Globals,
+			pic_object_file_extension, ObjExt)
+	;
+		globals__lookup_string_option(Globals,
+			link_with_pic_object_file_extension, ObjExt)
+	),
 	( Ext = ObjExt
 	; Ext = "_init" ++ ObjExt
 	).
-file_is_arch_or_grade_dependent(Globals, Ext) :-
-	globals__lookup_string_option(Globals, pic_object_file_extension, Ext).
 file_is_arch_or_grade_dependent(Globals, Ext) :-
 	globals__lookup_string_option(Globals, library_extension, LibExt),
 	( Ext = LibExt
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.397
diff -u -u -r1.397 options.m
--- compiler/options.m	27 Nov 2002 00:49:10 -0000	1.397
+++ compiler/options.m	29 Nov 2002 06:32:20 -0000
@@ -576,7 +576,9 @@
 		;	init_files
 		;	trace_init_files
 		;	linkage
+		;	linkage_special
 		;	mercury_linkage
+		;	mercury_linkage_special
 		;	strip
 		;	demangle
 		;	main
@@ -1168,8 +1170,10 @@
 	init_file_directories -		accumulating([]),
 	init_files -			accumulating([]),
 	trace_init_files -		accumulating([]),
-	linkage -			string("default"),
-	mercury_linkage -		string("default"),
+	linkage -			string("shared"),
+	linkage_special -		string_special,
+	mercury_linkage -		string("shared"),
+	mercury_linkage_special -	string_special,
 	demangle -			bool(yes),
 	strip -				bool(yes),
 	main -				bool(yes),
@@ -1815,8 +1819,8 @@
 long_option("init-file-directory",	init_file_directories).
 long_option("init-file",		init_files).
 long_option("trace-init-file",		trace_init_files).
-long_option("linkage",			linkage).
-long_option("mercury-linkage",		mercury_linkage).
+long_option("linkage",			linkage_special).
+long_option("mercury-linkage",		mercury_linkage_special).
 long_option("demangle",			demangle).
 long_option("strip",			strip).
 long_option("main",			main).
@@ -2042,6 +2046,24 @@
 special_handler(quoted_ld_libflag, string(Flag),
 			OptionTable0, ok(OptionTable)) :-
 	handle_quoted_flag(ld_libflags, Flag, OptionTable0, OptionTable).
+special_handler(linkage_special, string(Flag), OptionTable0, Result) :-
+	( ( Flag = "shared" ; Flag = "static" ) ->
+		Result = ok(
+			(OptionTable0 ^ elem(mercury_linkage) := string(Flag))
+					^ elem(linkage) := string(Flag))
+	;
+		Result = error(
+	"argument of `--linkage' should be either ""shared"" or ""static"".")
+	).
+special_handler(mercury_linkage_special, string(Flag),
+			OptionTable0, Result) :-
+	( ( Flag = "shared" ; Flag = "static" ) ->
+		Result = ok(
+			OptionTable0 ^ elem(mercury_linkage) := string(Flag))
+	;
+		Result = error(
+"argument of `--mercury-linkage' should be either ""shared"" or ""static"".")
+	).
 
 %-----------------------------------------------------------------------------%
 
@@ -3726,13 +3748,9 @@
 		"-L <directory>, --library-directory <directory>",
 		"\tAppend <directory> to the list of directories in which",
 		"\tto search for libraries.",
-
-		/* NYI
 		"-R <directory>, --runtime-library-directory <directory>",
 		"\tAppend <directory> to the list of directories in which",
 		"\tto search for shared libraries at runtime.",
-		*/
-
 		"-l <library>, --library <library>",
 		"\tLink with the specified library.",
 		"--link-object <object-file>",
@@ -3752,14 +3770,12 @@
 		"--ml <library>, --mercury-library <library>",
 		"\tLink with the specified Mercury library.",
 
-		/* NYI
 		"--linkage {shared|static}",
 		"\tSpecify whether to use shared or static linking for",
 		"\texecutables.",
 		"--mercury-linkage {shared|static}",
 		"\tSpecify whether to use shared or static linking when",
-		"\tlinking with Mercury libraries."
-		*/
+		"\tlinking with Mercury libraries.",
 
 		"--init-file-directory <directory>",
 		"\tAppend <directory> to the list of directories to",
Index: compiler/options_file.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options_file.m,v
retrieving revision 1.13
diff -u -u -r1.13 options_file.m
--- compiler/options_file.m	15 Nov 2002 15:32:16 -0000	1.13
+++ compiler/options_file.m	28 Nov 2002 13:29:46 -0000
@@ -776,6 +776,8 @@
 	;	lib_dirs
 	;	lib_grades
 	;	install_prefix
+	;	linkage
+	;	mercury_linkage
 	.
 
 :- func options_variable_types = list(options_variable_type).
@@ -788,7 +790,7 @@
 	ilasm_flags, csharp_flags, mcpp_flags,
 	ml_objs, lib_dirs, ml_flags, ld_flags,
 	libraries, ml_libs, c2init_args,
-	lib_grades, install_prefix].
+	lib_grades, install_prefix, linkage, mercury_linkage].
 
 :- func options_variable_name(options_variable_type) = string.
 
@@ -809,6 +811,8 @@
 options_variable_name(lib_dirs) = "LIB_DIRS".
 options_variable_name(lib_grades) = "LIBGRADES".
 options_variable_name(install_prefix) = "INSTALL_PREFIX".
+options_variable_name(linkage) = "LINKAGE".
+options_variable_name(mercury_linkage) = "MERCURY_LINKAGE".
 
 :- func options_variable_type_is_target_specific(options_variable_type) = bool.
 
@@ -827,9 +831,10 @@
 options_variable_type_is_target_specific(c2init_args) = yes.
 options_variable_type_is_target_specific(libraries) = yes.
 options_variable_type_is_target_specific(lib_dirs) = no.
-	% XXX With Mmake, LIBGRADES is target specific.
-options_variable_type_is_target_specific(lib_grades) = no.
 options_variable_type_is_target_specific(install_prefix) = no.
+options_variable_type_is_target_specific(lib_grades) = yes.
+options_variable_type_is_target_specific(linkage) = yes.
+options_variable_type_is_target_specific(mercury_linkage) = yes.
 
 :- func convert_to_mmc_options(
 		pair(options_variable_type, maybe(list(string)))) =
@@ -884,6 +889,8 @@
 mmc_option_type(lib_dirs) = option([], "--mercury-library-directory").
 mmc_option_type(lib_grades) = option(["--no-libgrade"], "--libgrade").
 mmc_option_type(install_prefix) = option([], "--install-prefix").
+mmc_option_type(linkage) = option([], "--linkage").
+mmc_option_type(mercury_linkage) = option([], "--mercury-linkage").
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/prog_io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io.m,v
retrieving revision 1.210
diff -u -u -r1.210 prog_io.m
--- compiler/prog_io.m	1 Aug 2002 00:41:37 -0000	1.210
+++ compiler/prog_io.m	26 Nov 2002 02:17:30 -0000
@@ -398,10 +398,17 @@
 		Result = error(Message)
 	}.	
 
-search_for_file_returning_dir([], FileName,
-		error("cannot open `" ++ FileName ++ "'")) -->
-	[].
-search_for_file_returning_dir([Dir | Dirs], FileName, R) -->
+search_for_file_returning_dir(Dirs, FileName, R) -->
+	search_for_file_returning_dir(Dirs, Dirs, FileName, R).
+
+:- pred search_for_file_returning_dir(list(dir_name), list(dir_name),
+		file_name, maybe_error(dir_name), io__state, io__state).
+:- mode search_for_file_returning_dir(in, in, in, out, di, uo) is det.
+
+search_for_file_returning_dir([], AllDirs, FileName, error(Msg)) -->
+	{ Msg = append_list(["cannot find `", FileName, "' in directories ",
+			string__join_list(", ", AllDirs), "."]) }.
+search_for_file_returning_dir([Dir | Dirs], AllDirs, FileName, R) -->
 	{ dir__this_directory(Dir) ->
 		ThisFileName = FileName
 	;
@@ -411,7 +418,7 @@
 	( { R0 = ok } ->
 		{ R = ok(Dir) }
 	;
-		search_for_file_returning_dir(Dirs, FileName, R)
+		search_for_file_returning_dir(Dirs, AllDirs, FileName, R)
 	).
 
 search_for_module_source(Dirs, ModuleName, MaybeFileName) -->
Index: deep_profiler/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/deep_profiler/Mmakefile,v
retrieving revision 1.5
diff -u -u -r1.5 Mmakefile
--- deep_profiler/Mmakefile	22 Jun 2002 19:16:01 -0000	1.5
+++ deep_profiler/Mmakefile	29 Nov 2002 07:12:24 -0000
@@ -34,6 +34,7 @@
 #-----------------------------------------------------------------------------#
 
 MLFLAGS += --shared
+MCFLAGS += --linkage shared
 
 #-----------------------------------------------------------------------------#
 
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.344
diff -u -u -r1.344 user_guide.texi
--- doc/user_guide.texi	21 Nov 2002 15:58:54 -0000	1.344
+++ doc/user_guide.texi	29 Nov 2002 06:09:02 -0000
@@ -698,6 +698,19 @@
 @vindex ML
 The executable that invokes the linker.
 
+ at item LINKAGE
+ at vindex LINKAGE
+Can be set to either @samp{shared} to link with shared libraries,
+or @samp{static} to always link statically.  The default is @samp{shared}.
+This variable only has an effect with @samp{mmc --make}.
+
+ at item MERCURY_LINKAGE
+ at vindex MERCURY_LINKAGE
+Can be set to either @samp{shared} to link with shared Mercury libraries,
+or @samp{static} to always link with the static versions of Mercury libraries.
+The default is system dependent.
+This variable only has an effect with @samp{mmc --make}.
+
 @item MLFLAGS and EXTRA_MLFLAGS
 @vindex MLFLAGS
 @vindex EXTRA_MLFLAGS
@@ -842,7 +855,7 @@
 Parallel builds are not yet supported.
 
 Note that @samp{--use-subdirs} is automatically enabled if you specify
- at samp{--mmake}.
+ at samp{mmc --make}.
 
 The Mmake variables above can be used by @samp{mmc --make} if they
 are set in a file called @file{Mercury.options}. The @file{Mercury.options}
@@ -6479,6 +6492,14 @@
 Append @var{directory} to the list of directories in which
 to search for libraries.
 
+ at sp 1
+ at item -R @var{directory}
+ at itemx --runtime-library-directory @var{directory}
+ at findex -R
+ at findex --runtime-library-directory
+Append @var{directory} to the list of directories in which
+to search for shared libraries at runtime.
+
 @item -l @var{library}
 @itemx --library @var{library}
 @findex -l
@@ -6537,6 +6558,17 @@
 Append @var{file} to the list of @samp{.init} files
 to be passed to @samp{c2init} when tracing is enabled.
 
+ at sp 1
+ at item --linkage @{shared,static@}
+ at findex --linkage
+Specify whether to use shared or static linking for executables.
+
+ at sp 1
+ at item --mercury-linkage @{shared,static@}
+ at findex --mercury-linkage
+Specify whether to link with the shared or static versions of
+the Mercury standard library and runtime.
+
 @end table
 
 @c ----------------------------------------------------------------------------
@@ -6558,6 +6590,7 @@
 @vindex MERCURY_DEFAULT_GRADE
 The default grade to use if no @samp{--grade} option is specified.
 
+ at sp 1
 @item MERCURY_STDLIB_DIR
 @vindex MERCURY_STDLIB_DIR
 The directory containing the installed Mercury standard library.
Index: profiler/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/profiler/Mmakefile,v
retrieving revision 1.21
diff -u -u -r1.21 Mmakefile
--- profiler/Mmakefile	22 Jun 2002 19:16:06 -0000	1.21
+++ profiler/Mmakefile	29 Nov 2002 07:12:13 -0000
@@ -20,6 +20,7 @@
 #-----------------------------------------------------------------------------#
 
 MLFLAGS += --shared
+MCFLAGS += --linkage shared
 
 #-----------------------------------------------------------------------------#
 
Index: scripts/Mmake.vars.in
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/Mmake.vars.in,v
retrieving revision 1.83
diff -u -u -r1.83 Mmake.vars.in
--- scripts/Mmake.vars.in	4 Nov 2002 01:49:10 -0000	1.83
+++ scripts/Mmake.vars.in	29 Nov 2002 05:54:29 -0000
@@ -129,9 +129,11 @@
 	echo EXTRA_LIB_DIRS += '$(EXTRA_LIB_DIRS)'; \
 	echo LIBGRADES = '$(ALL_LIBGRADES)'; \
 	echo INSTALL_PREFIX = '$(INSTALL_PREFIX)'; \
+	echo LINKAGE = '$(LINKAGE)'; \
+	echo MERCURY_LINKAGE = '$(MERCURY_LINKAGE)'; \
 	}
 
-MC_MAKE_FLAGS	=
+MC_MAKE_FLAGS =
 EXTRA_MC_MAKE_FLAGS =
 
 MCS		= $(MC) --split-c-files --compile-only
@@ -339,6 +341,10 @@
 MLLIBS		=
 EXTRA_MLLIBS	=
 LIB_MLLIBS	= $(patsubst %,-l%,$(ALL_EXTRA_LIBRARIES))
+
+# These only have an effect with `mmc --make'.
+LINKAGE = shared
+MERCURY_LINKAGE = @DEFAULT_LINKAGE@
 
 #-----------------------------------------------------------------------------#
 #
Index: scripts/mmc.in
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/mmc.in,v
retrieving revision 1.27
diff -u -u -r1.27 mmc.in
--- scripts/mmc.in	8 Aug 2002 06:22:00 -0000	1.27
+++ scripts/mmc.in	28 Nov 2002 14:07:15 -0000
@@ -27,6 +27,9 @@
 	;;
 esac
 
+DEFAULT_MERCURY_LINKAGE=${MERCURY_LINKAGE=@DEFAULT_LINKAGE@}
+export DEFAULT_MERCURY_LINKAGE
+
 # The default options settings are passed in the DEFAULT_MCFLAGS enviroment
 # variable, rather than on the command line, so that they can be overridden
 # by the value of MCFLAGS in the Mercury.options file. 
@@ -44,6 +47,7 @@
 		--c-flag-to-name-object-file \"@OBJFILE_OPT@\" \
 		--object-file-extension \". at OBJ_SUFFIX@\" \
 		--pic-object-file-extension \". at EXT_FOR_PIC_OBJECTS@\" \
+		--link-with-pic-object-file-extension \". at EXT_FOR_LINK_WITH_PIC_OBJECTS@\" \
 		--create-archive-command \"@AR@\" \
 		--create-archive-command-output-flag \"@AR_LIBFILE_OPT@\" \
 		--create-archive-command-flags \"@ARFLAGS@\" \
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list