[m-rev.] for review: linking with shared Mercury libraries

Simon Taylor stayl at cs.mu.OZ.AU
Thu Jan 16 11:31:03 AEDT 2003


Estimated hours taken: 15
Branches: main

Make it easier to use shared libraries on x86
with `mmc --make'.

There is now 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 doesn't work with Mmake because ml doesn't know
which libraries are Mercury libraries, so it can't
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 `-R' option to mmc.

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.291
diff -u -u -r1.291 NEWS
--- NEWS	5 Dec 2002 03:52:27 -0000	1.291
+++ NEWS	15 Jan 2003 13:50:02 -0000
@@ -1,5 +1,5 @@
-NEWS for Mercury release 0.12:
-------------------------------
+NEWS since Mercury release 0.11:
+--------------------------------
 
 HIGHLIGHTS
 ==========
@@ -8,7 +8,8 @@
 * Infix `.' is now accepted as a module name separator.
 
 Changes to the Mercury compiler:
-* Nothing yet.
+* It's now easier to use shared libraries on Linux/x86 systems
+  with `mmc --make'.
 
 Portability improvements:
 * Nothing yet.
@@ -56,7 +57,10 @@
 
 Changes to the Mercury compiler:
 
-* Nothing yet.
+* 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.
 
 Portability improvements:
 
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	15 Jan 2003 22:58:23 -0000
@@ -27,6 +27,9 @@
 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 Mmake
+variable to "shared" in the Mercury.options file or the environment,
+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.345
diff -u -u -r1.345 configure.in
--- configure.in	2 Jan 2003 06:53:51 -0000	1.345
+++ configure.in	15 Jan 2003 23:26:46 -0000
@@ -2587,12 +2587,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)
@@ -2632,10 +2638,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>
@@ -2648,6 +2656,7 @@
 		EXE_RPATH_SEP=" -R"
 		SHLIB_RPATH_OPT="-R"
 		SHLIB_RPATH_SEP=" -R"
+		DEFAULT_LINKAGE=static
 		;;
 	i*86-*-solaris2.*)
 		AC_MSG_RESULT(yes)
@@ -2675,6 +2684,7 @@
 		SHLIB_RPATH_OPT="-R"
 		SHLIB_RPATH_SEP=" -R"
 		EXT_FOR_SHARED_LIB=so
+		DEFAULT_LINKAGE=static
 		;;
 	sparc-sun-solaris2.*)
 		AC_MSG_RESULT(yes)
@@ -2689,6 +2699,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
@@ -2748,6 +2759,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 \
@@ -2764,6 +2776,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)
@@ -2785,12 +2798,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
@@ -2818,11 +2834,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.22
diff -u -u -r1.22 bindist.build_vars.in
--- bindist/bindist.build_vars.in	2 Dec 2002 07:59:53 -0000	1.22
+++ bindist/bindist.build_vars.in	2 Dec 2002 08:27:29 -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@"
 CYGPATH="@CYGPATH@"
 MATH_LIB="@MATH_LIB@"
Index: bindist/bindist.configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/bindist/bindist.configure.in,v
retrieving revision 1.47
diff -u -u -r1.47 bindist.configure.in
--- bindist/bindist.configure.in	22 Dec 2002 07:00:00 -0000	1.47
+++ bindist/bindist.configure.in	3 Jan 2003 03:52:57 -0000
@@ -71,6 +71,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)
@@ -92,6 +93,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.63
diff -u -u -r1.63 Mmakefile
--- compiler/Mmakefile	2 Jan 2003 06:53:54 -0000	1.63
+++ compiler/Mmakefile	3 Jan 2003 03:54:04 -0000
@@ -53,6 +53,7 @@
 MLOBJS :=	../main.$O ../analysis/lib$(ANALYSIS_LIB_NAME).$A $(MLOBJS)
 ALL_MLLIBS =	$(MLLIBS) $(EXTRA_MLLIBS) $(GCC_BACKEND_LIBS)
 MLFLAGS +=	--no-main --shared
+MCFLAGS +=	--no-main --linkage shared
 C2INITARGS +=	$(ANALYSIS_DIR)/$(ANALYSIS_LIB_NAME).init
 
 #
@@ -67,6 +68,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.33
diff -u -u -r1.33 compile_target_code.m
--- compiler/compile_target_code.m	23 Dec 2002 12:32:56 -0000	1.33
+++ compiler/compile_target_code.m	16 Jan 2003 00:01:38 -0000
@@ -26,6 +26,7 @@
 	% files.
 :- type pic
 	--->    pic
+	;	link_with_pic
 	;       non_pic
 	.
 
@@ -102,6 +103,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'.
 
@@ -157,8 +166,8 @@
 %-----------------------------------------------------------------------------%
 :- implementation.
 
-:- import_module libs__options, libs__handle_options.
-:- import_module hlds__passes_aux, libs__trace_params.
+:- import_module libs__globals, libs__options, libs__handle_options.
+:- import_module hlds__error_util, hlds__passes_aux, libs__trace_params.
 :- import_module parse_tree__prog_out.
 :- import_module backend_libs__foreign.
 
@@ -380,15 +389,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) ->
@@ -499,12 +499,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 "
@@ -790,7 +808,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),
@@ -818,10 +841,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 :-
@@ -882,8 +901,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),
 
@@ -951,7 +972,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 } ->
@@ -1026,22 +1047,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,
@@ -1071,6 +1136,48 @@
 		{ Succeeded = LinkSucceeded }
 	).
 
+:- 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),
+
+		{ file_name_to_module_name(LibName, LibModuleName) },
+		globals__io_lookup_string_option(library_extension, LibExt),
+
+		globals__io_set_option(use_grade_subdirs, bool(no)),
+		module_name_to_lib_file_name("lib", LibModuleName, LibExt,
+			no, LibFileName),
+		globals__io_set_option(use_grade_subdirs,
+			bool(UseGradeSubdirs)),
+
+		io__input_stream(InputStream),
+		search_for_file_returning_dir(MercuryLibDirs, LibFileName,
+			SearchResult),
+		(
+			{ SearchResult = ok(DirName) },
+			{ LinkerOpt = DirName/LibFileName },
+			io__set_input_stream(InputStream, LibInputStream),
+			io__close_input(LibInputStream)	
+		;
+			{ 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.
@@ -1091,6 +1198,72 @@
 	invoke_system_command(ErrorStream, verbose_commands,
 		MakeLibCmd, MakeLibCmdOK).
 
+get_linkage_info(FileType, ObjectCodeType, ObjExtToUse, !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(pic, PIC, !IO),
+	(
+	    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,
+			(
+				% 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 = ObjExt
+				; GCCGlobals = no
+				)
+			->
+				ObjectCodeType = non_pic
+			;
+				LinkWithPicObjExt = PicObjExt
+			->
+				ObjectCodeType = pic
+			;
+				ObjectCodeType = link_with_pic
+			)
+		; MercuryLinkage = "static" ->
+			ObjectCodeType = non_pic,
+			ObjExtToUse = ObjExt
+		;
+			% The linkage string is checked by options.m.
+			error("unknown linkage " ++ MercuryLinkage)
+		)
+	    )
+	).
+
 %-----------------------------------------------------------------------------%
 
 :- pred standard_library_directory_option(string, io__state, io__state).
@@ -1289,6 +1462,9 @@
 
 maybe_pic_object_file_extension(Globals, pic, Ext) :-
 	globals__lookup_string_option(Globals, pic_object_file_extension, Ext).
+maybe_pic_object_file_extension(Globals, link_with_pic, ObjExt) :-
+	globals__lookup_string_option(Globals,
+		link_with_pic_object_file_extension, ObjExt).
 maybe_pic_object_file_extension(Globals, non_pic, Ext) :-
 	globals__lookup_string_option(Globals, object_file_extension, Ext).
 
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.161
diff -u -u -r1.161 handle_options.m
--- compiler/handle_options.m	20 Dec 2002 09:46:18 -0000	1.161
+++ compiler/handle_options.m	3 Jan 2003 03:53:00 -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.20
diff -u -u -r1.20 make.module_target.m
--- compiler/make.module_target.m	23 Dec 2002 12:32:57 -0000	1.20
+++ compiler/make.module_target.m	16 Jan 2003 00:12:07 -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.
 
 %-----------------------------------------------------------------------------%
@@ -555,24 +556,23 @@
 compilation_task(_, asm_code(PIC)) =
 		process_module(compile_to_target_code) - 
 			( PIC = pic -> ["--pic"] ; [] ).
-compilation_task(Globals, object_code(PIC)) =
-	target_code_to_object_code(PIC) - get_pic_flags(Globals, PIC).
+compilation_task(_, object_code(PIC)) =
+	target_code_to_object_code(PIC) - get_pic_flags(PIC).
 compilation_task(_, foreign_il_asm(Lang)) =
 	foreign_code_to_object_code(non_pic, Lang) - [].
-compilation_task(Globals, foreign_object(PIC, Lang)) =
-	foreign_code_to_object_code(PIC, Lang) - get_pic_flags(Globals, PIC).
-compilation_task(Globals, factt_object(PIC)) =
-	fact_table_code_to_object_code(PIC) - get_pic_flags(Globals, PIC).
-
-:- func get_pic_flags(globals, pic) = list(string).
-
-get_pic_flags(Globals, PIC) = Flags :-
-	globals__get_target(Globals, Target),
-	( PIC = pic ->
-		Flags = ( Target = asm -> ["--pic"] ; ["--pic-reg"] )
-	;
-		Flags = []
-	).
+compilation_task(_, foreign_object(PIC, Lang)) =
+	foreign_code_to_object_code(PIC, Lang) - get_pic_flags(PIC).
+compilation_task(_, factt_object(PIC)) =
+	fact_table_code_to_object_code(PIC) - get_pic_flags(PIC).
+
+:- func get_pic_flags(pic) = list(string).
+
+% `--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).
+get_pic_flags(pic) = ["--pic", "--pic-reg"].
+get_pic_flags(link_with_pic) = ["--pic-reg"].
+get_pic_flags(non_pic) = [].
 
 	% Find the files which could be touched by a compilation task.
 :- pred touched_files(target_file::in, compilation_task_type::in,
@@ -629,8 +629,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)) },
@@ -743,64 +744,14 @@
 	{ ForeignObjectFiles = list__map((func(F) = F ^ object_file),
 			FactTableForeignCodes) }.
 
-:- pred get_target_code_to_object_code_foreign_files(module_name::in, 
-		list(foreign_code_file)::out, make_info::in, make_info::out,
-		io__state::di, io__state::uo) is det.
-
-get_target_code_to_object_code_foreign_files(ModuleName, ForeignCodeFiles,
-		Info0, Info) -->
-	get_module_dependencies(ModuleName, MaybeImports, Info0, Info1),
-	{ MaybeImports = yes(Imports0) ->
-		Imports = Imports0
-	;
-		% This error should have been caught earlier.
-		% We shouldn't be attempting to build a target
-		% if we couldn't find the dependencies for the
-		% module.
-		error(
-"get_target_code_to_object_code_foreign_files: no module dependencies")
-	},
-
-	%
-	% For `--target asm' there is only one `.s' file per module
-	% so we should compile the foreign code for 
-	%
-	globals__io_get_target(CompilationTarget),
-	( { CompilationTarget = asm } ->
-		{ NestedChildren = Imports ^ nested_children },
-
-		list__map_foldl2(get_module_dependencies, NestedChildren,
-			MaybeNestedImportsList, Info1, Info),
-		{
-		    list__map(
-			(pred(yes(NestedModuleImports)::in,
-					NestedModuleImports::out) is semidet),
-			MaybeNestedImportsList, NestedImportsList)
-		->
-		    ModuleImportsList = [Imports | NestedImportsList]
-		;
-			% This error should have been caught earlier.
-			% We shouldn't be attempting to build a target
-			% if we couldn't find the dependencies for the
-			% module or its nested sub-modules.
-		    error(
-"get_target_code_to_object_code_foreign_files: no nested module dependencies")
-		}
-	;
-		{ Info = Info1 },
-		{ ModuleImportsList = [Imports] }
-	),
-	list__map_foldl(external_foreign_code_files,
-		ModuleImportsList, ForeignCodeFileLists),
-	{ ForeignCodeFiles = list__condense(ForeignCodeFileLists) }.
-
-external_foreign_code_files(Imports, ForeignFiles) -->
+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 },
@@ -866,6 +817,17 @@
 		% 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.16
diff -u -u -r1.16 make.program_target.m
--- compiler/make.program_target.m	20 Dec 2002 09:46:18 -0000	1.16
+++ compiler/make.program_target.m	16 Jan 2003 00:12:51 -0000
@@ -33,22 +33,23 @@
 
 :- import_module hlds__passes_aux.
 
-make_linked_target(MainModuleName - FileType, Succeeded, !Info) -->
+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, !Info) -->
     find_reachable_local_modules(MainModuleName, DepsSuccess,
 		AllModules, !Info),
     globals__io_lookup_bool_option(keep_going, KeepGoing),
     ( { DepsSuccess = no, KeepGoing = no } ->
 	{ Succeeded = no }
     ;
-	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
@@ -58,11 +59,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,
@@ -80,7 +81,7 @@
 					IntermediateTargetType) },
 	{ ObjTargets = make_dependency_list(ObjModules, ObjectTargetType) },
 
-	list__map_foldl2(get_foreign_object_targets(ObjectCodeType),
+	list__map_foldl2(get_foreign_object_targets(PIC),
 			ObjModules, ForeignObjTargetsList, !Info),
 	{ ForeignObjTargets = list__condense(ForeignObjTargetsList) },
 
@@ -100,12 +101,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, !Info)
@@ -204,14 +204,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),
@@ -227,7 +227,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)
 	;
@@ -237,12 +237,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),
@@ -336,7 +336,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.
@@ -412,10 +413,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 }
 	).
@@ -423,6 +421,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 ) ->
@@ -931,41 +938,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", no, 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, no, 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.11
diff -u -u -r1.11 make.util.m
--- compiler/make.util.m	20 Dec 2002 09:46:18 -0000	1.11
+++ compiler/make.util.m	3 Jan 2003 05:38:42 -0000
@@ -620,6 +620,7 @@
 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(PIC)) = Ext :-
 	maybe_pic_object_file_extension(Globals, PIC, Ext).
@@ -630,16 +631,19 @@
 		% the reverse mode of this function remains nondet.
 target_extension(_, foreign_object(PIC, csharp)) = "bogus ext" :-
 	( PIC = pic
+	; PIC = link_with_pic
 	; PIC = non_pic
 	),
 	unexpected(this_file, "C# foreign_object").
 target_extension(_, foreign_object(PIC, managed_cplusplus)) = "bogus ext" :-
 	( PIC = pic
+	; PIC = link_with_pic
 	; PIC = non_pic
 	),
 	unexpected(this_file, "MC++ foreign_object").
 target_extension(_, foreign_object(PIC, il)) = "bogus ext" :-
 	( PIC = pic
+	; PIC = link_with_pic
 	; PIC = non_pic
 	),
 	unexpected(this_file, "il foreign_object").
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.269
diff -u -u -r1.269 mercury_compile.m
--- compiler/mercury_compile.m	2 Jan 2003 06:53:54 -0000	1.269
+++ compiler/mercury_compile.m	3 Jan 2003 03:53:01 -0000
@@ -391,8 +391,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)
 		;
 			[]
@@ -1202,10 +1204,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) },
@@ -1214,7 +1217,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),
@@ -1238,13 +1241,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)
 			)
@@ -1286,6 +1289,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 ) }.
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -3466,10 +3477,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.259
diff -u -u -r1.259 modules.m
--- compiler/modules.m	14 Jan 2003 16:42:28 -0000	1.259
+++ compiler/modules.m	15 Jan 2003 06:19:12 -0000
@@ -1002,15 +1002,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)"
 			)
@@ -1201,12 +1203,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.398
diff -u -u -r1.398 options.m
--- compiler/options.m	2 Jan 2003 06:53:55 -0000	1.398
+++ compiler/options.m	3 Jan 2003 03:53:03 -0000
@@ -577,7 +577,9 @@
 		;	init_files
 		;	trace_init_files
 		;	linkage
+		;	linkage_special
 		;	mercury_linkage
+		;	mercury_linkage_special
 		;	strip
 		;	demangle
 		;	main
@@ -1170,8 +1172,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),
@@ -1818,8 +1822,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).
@@ -2045,6 +2049,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"".")
+	).
 
 %-----------------------------------------------------------------------------%
 
@@ -3733,13 +3755,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>",
@@ -3759,14 +3777,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.213
diff -u -u -r1.213 prog_io.m
--- compiler/prog_io.m	5 Dec 2002 03:52:28 -0000	1.213
+++ compiler/prog_io.m	19 Dec 2002 04:20:53 -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.7
diff -u -u -r1.7 Mmakefile
--- deep_profiler/Mmakefile	2 Dec 2002 11:51:34 -0000	1.7
+++ deep_profiler/Mmakefile	19 Dec 2002 04:20:54 -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.347
diff -u -u -r1.347 user_guide.texi
--- doc/user_guide.texi	10 Jan 2003 05:36:33 -0000	1.347
+++ doc/user_guide.texi	15 Jan 2003 06:19:14 -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}
@@ -6485,6 +6498,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
@@ -6543,6 +6564,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 ----------------------------------------------------------------------------
@@ -6564,6 +6596,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.84
diff -u -u -r1.84 Mmake.vars.in
--- scripts/Mmake.vars.in	2 Jan 2003 06:54:00 -0000	1.84
+++ scripts/Mmake.vars.in	3 Jan 2003 03:53:15 -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