[m-rev.] for review: library installation with `mmc --make'

Simon Taylor stayl at cs.mu.OZ.AU
Sun Jul 7 22:12:59 AEST 2002


Estimated hours taken: 10
Branches: main

Library installation with `mmc --make'.

compiler/make.m:
compiler/make.program_target.m:
	Handle `mmc --make lib<module>.install'.

compiler/options.m:
compiler/handle_options.m:
	Add an option `--use-grade-subdirs', which causes
	all grade-dependenent files to be placed in
	`Mercury/<grade>/<ext>s' subdirectories, even
	those files that are intended for use by the user.

	`--use-grade-subdirs' is not documented because it
	is only intended for use in library installation
	with `mmc --make' (it doesn't work at all with Mmake).
	Documenting it would require documenting (and setting
	in stone) the layout of the `Mercury' directory, which
	is probably a bad idea.

compiler/modules.m:
compiler/intermod.m:
compiler/make.module_dep_file.m:
compiler/mercury_compile.m:
compiler/mlds_to_c.m:
compiler/trans_opt.m:
	Handle `--use-grade-subdirs' in module_name_to_file_name.

	Add module_name_to_search_file_name, which should be
	used to generate the names of files that might be part
	of an installed library. This is needed because installation
	and local directory hierarchies have a different layout,
	A better long-term fix would be to change things so that
	the installation and local directory layouts are the same.

compiler/make.util.m:
compiler/make.dependencies.m:
compiler/make.module_target.m:
	Add an extra argument to get_target_timestamp and
	get_file_name to specify whether the file should
	be searched for.

compiler/options_file.m:
scripts/Mmake.vars.in:
	Handle the LIBGRADES and INSTALL_PREFIX make variables.

doc/user_guide.texi:
	Remove the statement that library installation is
	not supported with `mmc --make'.

Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.142
diff -u -u -r1.142 handle_options.m
--- compiler/handle_options.m	1 Jul 2002 09:03:54 -0000	1.142
+++ compiler/handle_options.m	6 Jul 2002 16:48:28 -0000
@@ -61,6 +61,10 @@
 :- pred convert_grade_option(string::in, option_table::in, option_table::out)
 	is semidet.
 
+	% Produce the grade component of grade-specific
+	% installation directories.
+:- pred grade_directory_component(globals::in, string::out) is det.
+
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -447,6 +451,11 @@
 	option_implies(make, compile_only, bool(yes)),
 	option_implies(make, target_code_only, bool(yes)),
 
+	% This is needed for library installation (the library grades
+	% are built using `--use-grade-subdirs', and assume that
+	% the interface files were built using `--use-subdirs').
+	option_implies(make, use_subdirs, bool(yes)),
+
 	option_implies(verbose_check_termination, check_termination,bool(yes)),
 	option_implies(check_termination, termination, bool(yes)),
 	option_implies(check_termination, warn_missing_trans_opt_files,
@@ -537,6 +546,8 @@
 	% without checking timestamps.
 	option_implies(rebuild, make, bool(yes)),
 
+	option_implies(use_grade_subdirs, use_subdirs, bool(yes)),
+
 	% --make handles creation of the module dependencies itself,
 	% and they don't need to be recreated when compiling to C.
 	option_implies(invoked_by_mmc_make,
@@ -897,31 +908,24 @@
 	%
 	globals__io_lookup_accumulating_option(mercury_library_directories,
 		MercuryLibDirs),
+	globals__io_lookup_string_option(fullarch, FullArch),
+	globals__io_get_globals(Globals),
+	{ grade_directory_component(Globals, GradeString) },
 	(
 		{ MercuryLibDirs = [_|_] },
-		globals__io_lookup_string_option(fullarch, FullArch),
-		globals__io_get_globals(Globals),
-		{ compute_grade(Globals, GradeString) },
 		{ ExtraLinkLibDirs = list__map(
-				(func(MercuryLibDir) =
-					dir__make_path_name(MercuryLibDir,
-					dir__make_path_name("lib",
-					dir__make_path_name(GradeString,
-					FullArch)))
-				), MercuryLibDirs) },
+			(func(MercuryLibDir) =
+				MercuryLibDir/"lib"/GradeString/FullArch
+			), MercuryLibDirs) },
 		globals__io_lookup_accumulating_option(
 			link_library_directories, LinkLibDirs),
 		globals__io_set_option(link_library_directories,
 			accumulating(LinkLibDirs ++ ExtraLinkLibDirs)),
 
 		{ ExtraCIncludeDirs = list__map(
-				(func(MercuryLibDir) =
-					dir__make_path_name(MercuryLibDir,
-					dir__make_path_name("lib",
-					dir__make_path_name(GradeString,
-					dir__make_path_name(FullArch,
-					"inc"))))
-				), MercuryLibDirs) },
+			(func(MercuryLibDir) =
+				MercuryLibDir/"lib"/GradeString/FullArch/"inc"
+			), MercuryLibDirs) },
 		globals__io_lookup_accumulating_option(c_include_directory,
 			CIncludeDirs),
 		globals__io_set_option(c_include_directory,
@@ -947,6 +951,40 @@
 		[]
 	),
 
+	globals__io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs),
+	( { UseGradeSubdirs = yes } ->
+		%
+		% With `--use-grade-subdirs', `.opt', `.mih' and `.mh' files
+		% are placed in a directory named
+		% `Mercury/<grade>/<fullarch>/Mercury/<ext>s'.
+		% When searching for a file, module_name_to_file_name
+		% produces `Mercury/<ext>/<module>.ext' so that searches
+		% for installed files work, so we need to add
+		% `--intermod-directory Mercury/<grade>/<fullarch>'
+		% to find the `.opt' files in the current directory.
+		%
+		globals__io_lookup_accumulating_option(intermod_directories,
+			IntermodDirs1),
+		{ GradeSubdirIntermodDirs =
+			["Mercury"/GradeString/FullArch |
+			list__filter(isnt(unify(dir__this_directory)),
+				IntermodDirs1)] },
+		globals__io_set_option(intermod_directories,
+			accumulating(GradeSubdirIntermodDirs)),
+
+		globals__io_lookup_accumulating_option(c_include_directory,
+			CIncludeDirs1),
+		{ GradeSubdirCIncludeDirs = 
+			["Mercury"/GradeString/FullArch/"Mercury"/"mhs",
+			"Mercury"/GradeString/FullArch |
+			list__filter(isnt(unify(dir__this_directory)),
+				CIncludeDirs1)] },
+		globals__io_set_option(c_include_directory,
+			accumulating(GradeSubdirCIncludeDirs))
+	;
+		[]
+	),
+
 	% --use-opt-files implies --no-warn-missing-opt-files since
 	% we are expecting some to be missing.
 	option_implies(use_opt_files, warn_missing_opt_files, bool(no)),
@@ -1231,6 +1269,25 @@
 		Opt = Option - Data,
 		map__set(Opts1, Option, Data, Opts2)
 	)), CompOpts, Opts0, Opts).
+
+grade_directory_component(Globals, Grade) :-
+	compute_grade(Globals, Grade0),
+
+	%
+	% Strip out the `.picreg' part of the grade -- `.picreg' is
+	% implied by the file names (.pic_o vs .o, `.a' vs `.so').
+	%
+	(
+		string__sub_string_search(Grade0,
+			".picreg", PicRegIndex),
+		string__split(Grade0, PicRegIndex,
+			LeftPart, RightPart0),
+		string__append(".picreg", RightPart, RightPart0)
+	->
+		Grade = LeftPart ++ RightPart
+	;
+		Grade = Grade0
+	).
 
 compute_grade(Globals, Grade) :-
 	globals__get_options(Globals, Options),
Index: compiler/intermod.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/intermod.m,v
retrieving revision 1.122
diff -u -u -r1.122 intermod.m
--- compiler/intermod.m	30 Jun 2002 17:06:18 -0000	1.122
+++ compiler/intermod.m	5 Jul 2002 07:21:41 -0000
@@ -2184,7 +2184,7 @@
 	maybe_write_string(VeryVerbose, "'...\n"),
 	maybe_flush_output(VeryVerbose),
 
-	module_name_to_file_name(ModuleToRead, ".opt", no, FileName),
+	module_name_to_search_file_name(ModuleToRead, ".opt", FileName),
 	prog_io__read_opt_file(FileName, ModuleToRead,
 			ModuleError, Messages, OptItems),
 	update_error_status(opt, FileName, ModuleError, Messages,
Index: compiler/make.dependencies.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.dependencies.m,v
retrieving revision 1.6
diff -u -u -r1.6 make.dependencies.m
--- compiler/make.dependencies.m	21 Jun 2002 16:52:46 -0000	1.6
+++ compiler/make.dependencies.m	5 Jul 2002 10:10:03 -0000
@@ -881,7 +881,8 @@
 		% considered to be up-to-date if they
 		% exist.
 		%
-		get_target_timestamp(Target, MaybeTimestamp, Info1, Info2),
+		get_target_timestamp(yes, Target,
+			MaybeTimestamp, Info1, Info2),
 		(
 		    { MaybeTimestamp = ok(_) },
 		    { Status = up_to_date }
Index: compiler/make.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.m,v
retrieving revision 1.8
diff -u -u -r1.8 make.m
--- compiler/make.m	22 Jun 2002 19:15:54 -0000	1.8
+++ compiler/make.m	4 Jul 2002 09:26:23 -0000
@@ -369,9 +369,10 @@
 			ModuleNameStr = ModuleNameStr0,
 			TargetType0 = misc_target(realclean)
 		;
-			Suffix = ".install"
+			Suffix = ".install",
+			string__append("lib", ModuleNameStr1, ModuleNameStr0)
 		->
-			ModuleNameStr = ModuleNameStr0,
+			ModuleNameStr = ModuleNameStr1,
 			TargetType0 = misc_target(install_library)
 		;
 			fail
Index: compiler/make.module_dep_file.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.module_dep_file.m,v
retrieving revision 1.4
diff -u -u -r1.4 make.module_dep_file.m
--- compiler/make.module_dep_file.m	21 May 2002 19:04:26 -0000	1.4
+++ compiler/make.module_dep_file.m	5 Jul 2002 07:08:27 -0000
@@ -288,8 +288,8 @@
 	make_info::in, make_info::out, io__state::di, io__state::uo) is det.
 
 read_module_dependencies(RebuildDeps, ModuleName, Info0, Info) -->
-    module_name_to_file_name(ModuleName, module_dep_file_extension,
-    	no, ModuleDepFile),
+    module_name_to_search_file_name(ModuleName, module_dep_file_extension,
+		ModuleDepFile),
     globals__io_lookup_accumulating_option(search_directories, SearchDirs),
     io__input_stream(OldInputStream),
     search_for_file_returning_dir(SearchDirs, ModuleDepFile, SearchResult),
@@ -452,10 +452,10 @@
 
 read_module_dependencies_remake(RebuildDeps, ModuleName, Msg, Info0, Info) -->
 	( { RebuildDeps = yes } ->
-		module_name_to_file_name(ModuleName,
-			module_dep_file_extension, no, ModuleDepsFile),
 		debug_msg(
 		    (pred(di, uo) is det -->
+			module_name_to_file_name(ModuleName,
+				module_dep_file_extension, no, ModuleDepsFile),
 			io__write_string("Error reading file `"),
 			io__write_string(ModuleDepsFile),
 			io__write_string("rebuilding: "),
Index: compiler/make.module_target.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.module_target.m,v
retrieving revision 1.10
diff -u -u -r1.10 make.module_target.m
--- compiler/make.module_target.m	4 Jul 2002 14:18:07 -0000	1.10
+++ compiler/make.module_target.m	5 Jul 2002 10:10:37 -0000
@@ -169,7 +169,7 @@
 	%
 	% Check that the target files exist.
 	%
-	list__map_foldl2(get_target_timestamp, TouchedTargetFiles,
+	list__map_foldl2(get_target_timestamp(no), TouchedTargetFiles,
 			TargetTimestamps, Info1, Info2),
 	( { list__member(error(_), TargetTimestamps) } ->
 		debug_file_msg(TargetFile, "target file does not exist"),
@@ -190,7 +190,7 @@
 		{ MaybeOldestTimestamp = list__foldl(find_oldest_timestamp, 
 			TouchedFileTimestamps, MaybeOldestTimestamp0) },
 
-		get_file_name(TargetFile, TargetFileName, Info4, Info5),
+		get_file_name(no, TargetFile, TargetFileName, Info4, Info5),
 		check_dependencies(TargetFileName,
 			MaybeOldestTimestamp, DepFilesToMake,
 			DepsResult, Info5, Info)
@@ -396,7 +396,7 @@
 		MakeInfo = MakeInfo0 ^ file_timestamps :=
 			map__delete(MakeInfo0 ^ file_timestamps, TouchedFile)
 	    ) },
-	list__map_foldl2(get_file_name, TouchedTargetFiles,
+	list__map_foldl2(get_file_name(no), TouchedTargetFiles,
 		TouchedTargetFileNames, Info2, Info3),
 	{ list__foldl(DeleteTimestamp, TouchedTargetFileNames, Info3, Info4) },
 	{ list__foldl(DeleteTimestamp, OtherTouchedFiles, Info4, Info) }.
@@ -679,10 +679,10 @@
 	->
 		module_name_to_file_name(
 			foreign_language_module_name(ModuleName, c), ".c",
-			no, CCodeFileName),
+			yes, CCodeFileName),
 		module_name_to_file_name(
 			foreign_language_module_name(ModuleName, c), ObjExt,
-			no, ObjFileName),
+			yes, ObjFileName),
 		{ ForeignFiles0 =
 			[foreign_code_file(c, CCodeFileName, ObjFileName) ] }
 	;
@@ -726,9 +726,9 @@
 					Language) },
 		{ ForeignExt = foreign_language_file_extension(Language) }
 	->
-		module_name_to_file_name(ForeignModuleName, ForeignExt, no, 
+		module_name_to_file_name(ForeignModuleName, ForeignExt, yes, 
 			ForeignFileName),
-		module_name_to_file_name(ForeignModuleName, ".dll", no, 
+		module_name_to_file_name(ForeignModuleName, ".dll", yes, 
 			ForeignDLLFileName),
 		{ ForeignFiles = [foreign_code_file(Language, ForeignFileName,
 					ForeignDLLFileName)] }
Index: compiler/make.program_target.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.program_target.m,v
retrieving revision 1.7
diff -u -u -r1.7 make.program_target.m
--- compiler/make.program_target.m	22 Jun 2002 19:15:54 -0000	1.7
+++ compiler/make.program_target.m	7 Jul 2002 10:22:38 -0000
@@ -359,20 +359,13 @@
 	(
 		{ TargetType = clean },
 		{ Succeeded = yes },
-		list__foldl2(make_clean, AllModules, Info3, Info)
+		list__foldl2(make_module_clean, AllModules, Info3, Info4),
+		remove_init_files(MainModuleName, Info4, Info)
 	;
 		{ TargetType = realclean },	
 		{ Succeeded = yes },
-		list__foldl2(make_realclean, AllModules, Info3, Info4),
-		globals__io_lookup_string_option(executable_file_extension,
-			ExeExt),
-		globals__io_lookup_string_option(library_extension, LibExt),
-		globals__io_lookup_string_option(shared_library_extension,
-			SharedLibExt),
-
-		list__foldl2(remove_file(MainModuleName),
-			[ExeExt, LibExt, SharedLibExt, "_init.c", "_init.o"],
-			Info4, Info)
+		make_main_module_realclean(MainModuleName, Info3, Info4),
+		list__foldl2(make_module_realclean, AllModules, Info4, Info)
 	;
 		{ TargetType = build_all(ModuleTargetType) },
 		get_target_modules(ModuleTargetType, AllModules,
@@ -399,7 +392,7 @@
 			Intermod),
 		{ Intermod = yes ->
 			OptFiles = make_dependency_list(AllModules,
-					long_interface)
+					intermodule_interface)
 		;
 			OptFiles = []
 		},
@@ -435,14 +428,432 @@
 		)
 	;
 		{ TargetType = install_library },
-		{ Succeeded = no },
-		{ error("sorry, not implemented: mmc --make module.install") }
+		make_misc_target(MainModuleName - build_library,
+			LibSucceeded, Info3, Info4),
+		( { LibSucceeded = yes } ->
+			install_library(MainModuleName, Succeeded, Info4, Info)
+		;
+		    { Info = Info4 },
+		    { Succeeded = no }
+		)
+	).
+
+%-----------------------------------------------------------------------------%
+
+:- pred install_library(module_name::in, bool::out,
+	make_info::in, make_info::out, io__state::di, io__state::uo) is det.
+
+install_library(MainModuleName, Succeeded, Info0, Info) -->
+    find_reachable_local_modules(MainModuleName, DepsSuccess,
+		AllModules0, Info0, Info1),
+    { AllModules = set__to_sorted_list(AllModules0) },
+    make_install_dirs(DirSucceeded, LinkSucceeded),
+    ( { DepsSuccess = yes, DirSucceeded = yes } ->
+	globals__io_lookup_string_option(install_prefix, Prefix),
+
+	{ ModulesDir = Prefix/"lib"/"mercury"/"modules" },
+	module_name_to_file_name(MainModuleName, ".init", no, InitFileName),
+	install_file(InitFileName, ModulesDir, InitSucceded),
+
+        list__map_foldl2(install_ints_and_headers(LinkSucceeded), AllModules,
+		IntsSucceeded, Info1, Info2),
+
+	globals__io_get_globals(Globals),
+	{ compute_grade(Globals, Grade) },
+        install_library_grade_files(LinkSucceeded, Grade, MainModuleName,
+		AllModules, GradeSucceeded, Info2, Info3),
+	(
+		{ InitSucceded = yes },
+		{ bool__and_list(IntsSucceeded) = yes },
+		{ GradeSucceeded = yes }
+	->
+		% XXX With Mmake, LIBGRADES is target-specific.
+        	globals__io_lookup_accumulating_option(libgrades, LibGrades),
+		globals__io_lookup_bool_option(keep_going, KeepGoing),
+        	foldl2_maybe_stop_at_error(KeepGoing,
+			install_library_grade(LinkSucceeded,
+				MainModuleName, AllModules),
+			LibGrades, Succeeded, Info3, Info)
+    	;
+		{ Info = Info3 },
+		{ Succeeded = no }
+    	)
+    ;
+        { Info = Info1 },
+        { Succeeded = no }
+    ).
+
+:- pred install_ints_and_headers(bool::in, module_name::in, bool::out,
+	make_info::in, make_info::out, io__state::di, io__state::uo) is det.
+
+install_ints_and_headers(SubdirLinkSucceeded, ModuleName,
+		Succeeded, Info0, Info) -->
+    get_module_dependencies(ModuleName, MaybeImports, Info0, Info),
+    (
+	{ MaybeImports = yes(Imports) },
+	globals__io_lookup_bool_option(intermodule_optimization, Intermod),
+	{ Intermod = yes ->
+		% `.int0' files are imported by `.opt' files.
+		Exts =
+		    ( Imports ^ children \= [] -> ["int0", "opt"] ; ["opt"] )
+	;
+		Exts = []
+	},
+
+	globals__io_lookup_string_option(install_prefix, Prefix),
+	{ LibDir = Prefix/"lib"/"mercury" },
+	list__map_foldl(
+		install_subdir_file(SubdirLinkSucceeded,
+			LibDir/"ints", ModuleName),
+		["int", "int2", "int3", "module_dep" | Exts],
+		Results),
+
+	globals__io_get_target(Target),
+	(
+		% `.mh' files are only generated for modules containing
+		% `:- pragma export' declarations.
+		{ Target = c ; Target = asm },
+		{ Imports ^ contains_foreign_export = contains_foreign_export }
+	->
+		install_subdir_file(SubdirLinkSucceeded, LibDir/"inc",
+			ModuleName, "mh", HeaderSucceded1),
+
+		% This is needed so that the file will be
+		% found in Mmake's VPATH.
+		install_subdir_file(SubdirLinkSucceeded, LibDir/"ints",
+			ModuleName, "mh", HeaderSucceded2),
+
+		{ HeaderSucceded = HeaderSucceded1 `and` HeaderSucceded2 }
+	;
+		{ HeaderSucceded = yes }
+	),
+	{ Succeeded = bool__and_list([HeaderSucceded | Results]) }
+    ;
+    	{ MaybeImports = no },
+	{ Succeeded = no }
+    ).
+
+:- pred install_library_grade(bool::in, module_name::in, list(module_name)::in,
+	string::in, bool::out, make_info::in, make_info::out,
+	io__state::di, io__state::uo) is det.
+
+install_library_grade(LinkSucceeded0, ModuleName, AllModules, Grade,
+		Succeeded, Info0, Info) -->
+	%
+	% Building the library in the new grade is done in a separate
+	% process to make it easier to stop and clean up on an interrupt.
+	%
+	{ Cleanup = make_grade_clean(ModuleName, AllModules) },
+	build_with_check_for_interrupt(
+	    (pred(GradeSuccess::out, MInfo::in, MInfo::out, di, uo) is det -->
+		call_in_forked_process(
+		    (pred(GradeSuccess0::out, di, uo) is det -->
+			install_library_grade_2(LinkSucceeded0,
+			    Grade, ModuleName, AllModules,
+			    MInfo, GradeSuccess0)
+		    ), GradeSuccess)
+	    ), Cleanup, Succeeded, Info0, Info).
+
+:- pred install_library_grade_2(bool::in, string::in, module_name::in,
+		list(module_name)::in, make_info::in,
+		bool::out, io__state::di, io__state::uo) is det.
+
+install_library_grade_2(LinkSucceeded0, Grade, ModuleName, AllModules,
+		Info0, Succeeded) -->
+	globals__io_get_globals(Globals),
+
+	%
+	% Set up so that grade-dependent files for the current grade
+	% don't overwrite the files for the default grade.
+	%
+	{ OptionArgs0 = Info0 ^ option_args },
+	{ OptionArgs = OptionArgs0 ++
+			["--grade", Grade, "--use-grade-subdirs"] },
+
+	verbose_msg(
+		(pred(di, uo) is det -->
+			io__write_string("Installing grade "),
+			io__write_string(Grade),
+			io__nl
+		)),
+
+	lookup_mmc_options(Info0 ^ options_variables, MaybeMCFlags),
+	(
+		{ MaybeMCFlags = yes(MCFlags) },
+		handle_options(MCFlags ++ OptionArgs, OptionsError, _, _, _)
+	;
+		{ MaybeMCFlags = no },
+		% Errors should have been caught before.
+		{ error("install_library_grade: bad DEFAULT_MCFLAGS") }
+	),
+
+	( 
+		{ OptionsError = yes(OptionsMessage) },
+		usage_error(OptionsMessage),
+		{ Succeeded = no }
+	;
+		{ OptionsError = no },
+		%
+		% Remove the grade-dependent targets from the status map
+		% (we need to rebuild them in the new grade).
+		%
+		{ StatusMap0 = Info0 ^ dependency_status },
+		{ StatusMap = map__from_assoc_list(list__filter(
+			(pred((File - _)::in) is semidet :-
+			    \+ (
+				File = target(_ - Target),
+				target_is_grade_or_arch_dependent(Target)
+			    )
+			), 
+			map__to_assoc_list(StatusMap0))) },
+		{ Info1 = (Info0 ^ dependency_status := StatusMap)
+				^ option_args := OptionArgs },
+
+		make_misc_target(ModuleName - build_library,
+			LibSucceeded, Info1, Info2),
+		( { LibSucceeded = yes } ->
+			install_library_grade_files(LinkSucceeded0,
+				Grade, ModuleName, AllModules,
+				Succeeded, Info2, Info3),
+
+			make_grade_clean(ModuleName, AllModules,
+				Info3, _)
+		;
+			{ Succeeded = no }
+		)
+	),
+	globals__io_set_globals(unsafe_promise_unique(Globals)).
+
+	% Install the `.a', `.so, `.opt' and `.mih' files
+	% for the current grade.
+:- pred install_library_grade_files(bool::in, string::in, module_name::in,
+	list(module_name)::in, bool::out, make_info::in, make_info::out,
+	io__state::di, io__state::uo) is det.
+
+install_library_grade_files(LinkSucceeded0, Grade, ModuleName, AllModules,
+		Succeeded, Info0, Info) -->
+    make_grade_install_dirs(Grade, DirResult, LinkSucceeded1),
+    { LinkSucceeded = LinkSucceeded0 `and` LinkSucceeded1 },
+    ( { DirResult = yes } ->
+	linked_target_file_name(ModuleName, static_library, LibFileName),
+	linked_target_file_name(ModuleName, shared_library, SharedLibFileName),
+
+	globals__io_lookup_string_option(install_prefix, Prefix),
+	globals__io_lookup_string_option(fullarch, FullArch),
+	{ GradeLibDir = Prefix/"lib"/"mercury"/"lib"/Grade/FullArch },
+
+	install_file(LibFileName, GradeLibDir, LibSucceded),
+	install_file(SharedLibFileName, GradeLibDir, SharedLibSucceded),
+
+	list__map_foldl2(install_grade_ints_and_headers(LinkSucceeded, Grade),
+		AllModules, IntsHeadersSucceded, Info0, Info),
+	{ Succeeded = bool__and_list(
+		[LibSucceded, SharedLibSucceded | IntsHeadersSucceded]) }
+    ;
+	{ Succeeded = no },
+    	{ Info = Info0 }
+    ).
+
+	% Install the `.opt' and `.mih' files for the current grade.
+:- pred install_grade_ints_and_headers(bool::in, string::in, module_name::in,
+		bool::out, make_info::in, make_info::out,
+		io__state::di, io__state::uo) is det.
+
+install_grade_ints_and_headers(LinkSucceeded, Grade, ModuleName,
+		Succeeded, Info0, Info) -->
+    get_module_dependencies(ModuleName, MaybeImports, Info0, Info),
+    (
+	{ MaybeImports = yes(Imports) },
+	globals__io_lookup_string_option(install_prefix, Prefix),
+	globals__io_lookup_string_option(fullarch, FullArch),
+	{ LibDir = Prefix/"lib"/"mercury" },
+
+	globals__io_get_target(Target),
+	globals__io_lookup_bool_option(highlevel_code, HighLevelCode),
+	(
+		{ Target = c, HighLevelCode = yes
+		; Target = asm,
+			Imports ^ foreign_code = contains_foreign_code(_) 
+		}
+	->
+		{ GradeIncDir = LibDir/"lib"/Grade/FullArch/"inc" },
+		install_subdir_file(LinkSucceeded, GradeIncDir,
+			ModuleName, "mih", HeaderSucceded1),
+
+		% This is needed so that the file will be
+		% found in Mmake's VPATH.
+		{ IntDir = LibDir/"int" },
+		install_subdir_file(LinkSucceeded, IntDir,
+			ModuleName, "mih", HeaderSucceded2),
+
+		{ HeaderSucceded = HeaderSucceded1 `and` HeaderSucceded2 }
+	;
+		{ HeaderSucceded = yes }
+	),
+
+	globals__io_lookup_bool_option(intermodule_optimization, Intermod),
+	( { Intermod = yes } ->
+		{ GradeIntDir = LibDir/"ints"/Grade },
+		install_subdir_file(LinkSucceeded, GradeIntDir,
+			ModuleName, "opt", OptSucceded)
+	;
+		{ OptSucceded = yes }
+	),
+	{ Succeeded = HeaderSucceded `and` OptSucceded }
+    ;
+	{ MaybeImports = no },
+	{ Succeeded = no }
+    ).
+
+	% Install a file in the given directory, and in
+	% directory/Mercury/exts if the symlinks for the
+	% subdirectories couldn't be created (e.g. on Windows).
+:- pred install_subdir_file(bool::in, dir_name::in, module_name::in,
+	string::in, bool::out, io__state::di, io__state::uo) is det.
+
+install_subdir_file(SubdirLinkSucceeded, InstallDir,
+		ModuleName, Ext, Succeeded) -->
+	module_name_to_file_name(ModuleName, "." ++ Ext, no, FileName),
+	install_file(FileName, InstallDir, Succeeded1),
+	( { SubdirLinkSucceeded = no } ->
+		install_file(FileName, InstallDir/"Mercury"/(Ext ++ "s"),
+			Succeeded2),
+		{ Succeeded = Succeeded1 `and` Succeeded2 }
+	;
+		{ Succeeded = Succeeded1 }
+	).
+
+:- pred install_file(file_name::in, dir_name::in, bool::out,
+		io__state::di, io__state::uo) is det.
+
+install_file(FileName, InstallDir, Succeeded) -->
+	verbose_msg(
+		(pred(di, uo) is det -->
+			io__write_string("Installing file "),
+			io__write_string(FileName),
+			io__write_string(" in "),
+			io__write_string(InstallDir),
+			io__nl
+		)),
+	globals__io_lookup_string_option(install_command, InstallCommand),
+	{ Command = string__join_list("	",
+		quote_args([InstallCommand, FileName, InstallDir])) },
+	io__output_stream(OutputStream),
+	invoke_shell_command(OutputStream, verbose, Command, Succeeded).
+
+:- pred make_install_dirs(bool::out, bool::out,
+		io__state::di, io__state::uo) is det.
+
+make_install_dirs(Result, LinkResult) -->
+	globals__io_lookup_string_option(install_prefix, Prefix),
+	{ LibDir = Prefix/"lib"/"mercury" },
+	make_directory(LibDir/"inc", Result1),
+	make_directory(LibDir/"modules", Result2),
+
+	{ IntsSubdir = LibDir/"ints"/"Mercury" },
+	make_directory(IntsSubdir, Result3),
+
+	{ Result4 = Result1 `and` Result2 `and` Result3 },
+
+	{ Subdirs = ["int", "int2", "int3",
+			"opt", "trans_opt", "module_dep"] },
+	list__map_foldl(make_install_symlink(IntsSubdir),
+		Subdirs, LinkResults),
+	{ LinkResult = bool__and_list(LinkResults) },
+	( { LinkResult = yes } ->
+		{ Result = Result4 }
+	;
+		list__map_foldl(
+		    (pred(Ext::in, MkDirResult::out, di, uo) is det -->
+		    	make_directory(IntsSubdir/(Ext ++ "s"), MkDirResult)
+		    ), Subdirs, MkDirResults),
+		{ Result = bool__and_list([Result4 | MkDirResults]) }
 	).
 
-:- pred make_clean(module_name::in, make_info::in, make_info::out,
+:- pred make_grade_install_dirs(string::in, bool::out, bool::out,
+		io__state::di, io__state::uo) is det.
+
+make_grade_install_dirs(Grade, Result, LinkResult) -->
+	globals__io_lookup_string_option(install_prefix, Prefix),
+	globals__io_lookup_string_option(fullarch, FullArch),
+	{ LibDir = Prefix/"lib"/"mercury" },
+
+	{ GradeIntsSubdir = LibDir/"ints"/Grade/"Mercury" },
+	make_directory(GradeIntsSubdir, Result1),
+
+	{ GradeIncSubdir = LibDir/"lib"/Grade/FullArch/"inc"/"Mercury" },
+	make_directory(GradeIncSubdir, Result2),
+
+	{ Result3 = Result1 `and` Result2 },
+
+	make_install_symlink(GradeIncSubdir, "mih", LinkResult0),
+	list__map_foldl(make_install_symlink(GradeIntsSubdir),
+		["opt", "trans_opt"], LinkResults),
+	{ LinkResult = bool__and_list([LinkResult0 | LinkResults]) },
+	( { LinkResult = yes } ->
+		{ Result = Result3 }
+	;
+		make_directory(GradeIncSubdir/"mih", Result4),
+		list__map_foldl(
+		    (pred(Ext::in, MkDirResult::out, di, uo) is det -->
+		    	make_directory(GradeIntsSubdir/(Ext ++ "s"),
+				MkDirResult)
+		    ), ["opt", "trans_opt"], MkDirResults),
+		{ Result = bool__and_list([Result3, Result4 | MkDirResults]) }
+	).
+
+:- pred make_install_symlink(string::in, string::in, bool::out,
+		io__state::di, io__state::uo) is det.
+
+make_install_symlink(Subdir, Ext, Result) -->
+	{ LinkName = Subdir/(Ext ++ "s") },
+	make_symlink("..", LinkName, Result).
+
+:- pred make_symlink(string::in, string::in, bool::out,
+		io__state::di, io__state::uo) is det.
+
+make_symlink(LinkTarget, LinkName, Result) -->
+	io__output_stream(ErrorStream),
+	{ string__format("rm -f %s && ln -s %s %s",
+		[s(LinkName), s(LinkTarget), s(LinkName)], Command) },
+	invoke_shell_command(ErrorStream, verbose, Command, Result).
+
+%-----------------------------------------------------------------------------%
+
+	% Clean up grade-dependent files.
+:- pred make_grade_clean(module_name::in, list(module_name)::in,
+	make_info::in, make_info::out, io__state::di, io__state::uo) is det.
+
+make_grade_clean(ModuleName, AllModules, Info0, Info) -->
+	make_main_module_realclean(ModuleName, Info0, Info1),
+	list__foldl2(make_module_clean, AllModules, Info1, Info).
+
+:- pred make_main_module_realclean(module_name::in,
+		make_info::in, make_info::out,
+		io__state::di, io__state::uo) is det.
+
+make_main_module_realclean(ModuleName, Info0, Info) -->
+	linked_target_file_name(ModuleName, executable, ExeFileName),
+	linked_target_file_name(ModuleName, static_library, LibFileName),
+	linked_target_file_name(ModuleName, shared_library, SharedLibFileName),
+	list__foldl2(remove_file,
+		[ExeFileName, LibFileName, SharedLibFileName],
+		Info0, Info1),
+	remove_file(ModuleName, ".init", Info1, Info2),
+	remove_init_files(ModuleName, Info2, Info).
+
+:- pred remove_init_files(module_name::in, make_info::in, make_info::out,
+		io__state::di, io__state::uo) is det.
+
+remove_init_files(ModuleName, Info0, Info) -->
+	globals__io_lookup_string_option(object_file_extension, ObjExt),
+	list__foldl2(remove_file(ModuleName), ["_init.c", "_init" ++ ObjExt],
+		Info0, Info).
+
+:- pred make_module_clean(module_name::in, make_info::in, make_info::out,
 		io__state::di, io__state::uo) is det.
 
-make_clean(ModuleName, Info0, Info) -->
+make_module_clean(ModuleName, Info0, Info) -->
 	list__foldl2(remove_target_file(ModuleName),
 		[errors, c_code, c_header(mih),
 		object_code(pic), object_code(non_pic),
@@ -451,10 +862,8 @@
 		],
 		Info0, Info1),
 
-	globals__io_lookup_string_option(object_file_extension, ObjExt),
 	list__foldl2(remove_file(ModuleName),
-		["_init.c", "_init" ++ ObjExt, ".used", ".prof",
-		".derived_schema", ".base_schema"],
+		[".used", ".prof", ".derived_schema", ".base_schema"],
 		Info1, Info2),
 
 	get_module_dependencies(ModuleName, MaybeImports, Info2, Info3),
@@ -474,23 +883,17 @@
 		{ Info = Info3 }
 	).
 
-:- pred make_realclean(module_name::in, make_info::in, make_info::out,
+:- pred make_module_realclean(module_name::in, make_info::in, make_info::out,
 		io__state::di, io__state::uo) is det.
 
-make_realclean(ModuleName, Info0, Info) -->
-	make_clean(ModuleName, Info0, Info1),
+make_module_realclean(ModuleName, Info0, Info) -->
+	make_module_clean(ModuleName, Info0, Info1),
 	list__foldl2(remove_target_file(ModuleName),
 		[private_interface, long_interface, short_interface,
 		unqualified_short_interface, intermodule_interface,
 		aditi_code, c_header(mh)
 		],
 		Info1, Info2),
-	remove_file(ModuleName, module_dep_file_extension, Info2, Info3),
-	linked_target_file_name(ModuleName, executable, ExeFileName),
-	linked_target_file_name(ModuleName, static_library, LibFileName),
-	linked_target_file_name(ModuleName, shared_library, SharedLibFileName),
-	list__foldl2(remove_file,
-		[ExeFileName, LibFileName, SharedLibFileName],
-		Info3, Info).
+	remove_file(ModuleName, module_dep_file_extension, Info2, Info).
 
 %-----------------------------------------------------------------------------%
Index: compiler/make.util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.util.m,v
retrieving revision 1.8
diff -u -u -r1.8 make.util.m
--- compiler/make.util.m	21 Jun 2002 16:52:46 -0000	1.8
+++ compiler/make.util.m	5 Jul 2002 10:09:13 -0000
@@ -92,12 +92,21 @@
 	maybe_error(timestamp)::out, make_info::in, make_info::out,
 	io__state::di, io__state::uo) is det.
 
+	% get_target_timestamp(Search, TargetFile, Timestamp)
+	%
 	% Find the timestamp for the given target file.
-:- pred get_target_timestamp(target_file::in, maybe_error(timestamp)::out,
-	make_info::in, make_info::out, io__state::di, io__state::uo) is det.
+	% `Search' should be `yes' if the file could be part of an
+	% installed library.
+:- pred get_target_timestamp(bool::in, target_file::in,
+	maybe_error(timestamp)::out, make_info::in, make_info::out,
+	io__state::di, io__state::uo) is det.
 
+	% get_file_name(Search, TargetFile, FileName).
+	%
 	% Compute a file name for the given target file.
-:- pred get_file_name(target_file::in, file_name::out,
+	% `Search' should be `yes' if the file could be part of an
+	% installed library.
+:- pred get_file_name(bool::in, target_file::in, file_name::out,
 	make_info::in, make_info::out, io__state::di, io__state::uo) is det.
 
 	% Find the timestamp of the first file matching the given
@@ -148,6 +157,8 @@
 	% given target type, if one exists.
 :- func timestamp_extension(globals, module_target_type) = string is semidet.
 
+:- pred target_is_grade_or_arch_dependent(module_target_type::in) is semidet.
+
 %-----------------------------------------------------------------------------%
 	% Debugging, verbose and error messages.
 
@@ -279,9 +290,12 @@
 		% --invoked-by-mmc-make disables reading DEFAULT_MCFLAGS
 		% from the environment (DEFAULT_MCFLAGS is included in
 		% OptionArgs) and generation of `.d' files.
+		% --use-subdirs is needed because the code to install
+		% libraries uses `--use-grade-subdirs' and assumes the
+		% interface files were built with `--use-subdirs'.
 		{ AllOptionArgs = list__condense([
 		    ["--invoked-by-mmc-make" | OptionArgs],
-		    Info0 ^ option_args, ExtraOptions]) },
+		    Info0 ^ option_args, ExtraOptions, ["--use-subdirs"]]) },
 		handle_options(AllOptionArgs, OptionsError, _, _, _),
 		(
 			{ OptionsError = yes(OptionsMessage) },
@@ -420,7 +434,7 @@
 	),
 	get_file_timestamp(SearchDirs, FileName, MaybeTimestamp, Info0, Info).
 get_dependency_timestamp(target(Target), MaybeTimestamp, Info0, Info) -->
-	get_target_timestamp(Target, MaybeTimestamp0, Info0, Info),
+	get_target_timestamp(yes, Target, MaybeTimestamp0, Info0, Info),
 	{ Target = _ - c_header(mih), MaybeTimestamp0 = ok(_) ->
 		% Don't rebuild the `.o' file if an irrelevant part of a
 		% `.mih' file has changed. If a relevant part of a `.mih'
@@ -432,9 +446,14 @@
 		MaybeTimestamp = MaybeTimestamp0
 	}.
 
-get_target_timestamp(ModuleName - FileType, MaybeTimestamp, Info0, Info) -->
-	get_file_name(ModuleName - FileType, FileName, Info0, Info1),
-	get_search_directories(FileType, SearchDirs),
+get_target_timestamp(Search, ModuleName - FileType, MaybeTimestamp,
+		Info0, Info) -->
+	get_file_name(Search, ModuleName - FileType, FileName, Info0, Info1),
+	( { Search = yes } ->
+		get_search_directories(FileType, SearchDirs)
+	;
+		{ SearchDirs = [dir__this_directory] }
+	),
 	get_file_timestamp(SearchDirs, FileName, MaybeTimestamp0,
 		Info1, Info2),
 	(
@@ -464,7 +483,7 @@
 		{ Info = Info2 }
 	).
 
-get_file_name(ModuleName - FileType, FileName, Info0, Info) -->
+get_file_name(Search, ModuleName - FileType, FileName, Info0, Info) -->
 	( { FileType = source } -> 
 		%
 		% In some cases the module name won't match the file
@@ -486,8 +505,14 @@
 	;
 		{ Info = Info0 },
 		globals__io_get_globals(Globals),
-		module_name_to_file_name(ModuleName,
-			target_extension(Globals, FileType), no, FileName)
+		{ Ext = target_extension(Globals, FileType) },
+		( { Search = yes } ->
+			module_name_to_search_file_name(ModuleName,
+				Ext, FileName)
+		;
+			module_name_to_file_name(ModuleName,
+				Ext, no, FileName)
+		)
 	).
 
 get_file_timestamp(SearchDirs, FileName, MaybeTimestamp, Info0, Info) -->
@@ -643,6 +668,29 @@
 search_for_file_type(java_code) = no.
 search_for_file_type(asm_code(_)) = no.
 search_for_file_type(object_code(_)) = no.
+
+target_is_grade_or_arch_dependent(Target) :-
+	target_is_grade_or_arch_dependent(Target, yes).
+
+:- pred target_is_grade_or_arch_dependent(module_target_type::in,
+		bool::out) is det.
+
+target_is_grade_or_arch_dependent(source, no).
+target_is_grade_or_arch_dependent(errors, no).
+target_is_grade_or_arch_dependent(private_interface, no).
+target_is_grade_or_arch_dependent(long_interface, no).
+target_is_grade_or_arch_dependent(short_interface, no).
+target_is_grade_or_arch_dependent(unqualified_short_interface, no).
+target_is_grade_or_arch_dependent(intermodule_interface, yes).
+target_is_grade_or_arch_dependent(aditi_code, no).
+target_is_grade_or_arch_dependent(c_header(mh), no).
+target_is_grade_or_arch_dependent(c_header(mih), yes).
+target_is_grade_or_arch_dependent(c_code, yes).
+target_is_grade_or_arch_dependent(il_code, yes).
+target_is_grade_or_arch_dependent(il_asm, yes).
+target_is_grade_or_arch_dependent(java_code, yes).
+target_is_grade_or_arch_dependent(asm_code(_), yes).
+target_is_grade_or_arch_dependent(object_code(_), yes).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.256
diff -u -u -r1.256 mercury_compile.m
--- compiler/mercury_compile.m	26 Jun 2002 08:31:23 -0000	1.256
+++ compiler/mercury_compile.m	6 Jul 2002 15:19:18 -0000
@@ -365,7 +365,7 @@
 		{ file_name_to_module_name(Module, ModuleName) },
 		globals__io_lookup_bool_option(pic, Pic),
 		{ AsmExt = (Pic = yes -> ".pic_s" ; ".s") },
-		module_name_to_file_name(ModuleName, AsmExt, no,
+		module_name_to_file_name(ModuleName, AsmExt, yes,
 			AsmFile),
 		(
 			{ ModuleName \= FirstModuleName }
@@ -919,7 +919,7 @@
 :- mode module_to_link(in, out, di, uo) is det.
 
 module_to_link(ModuleName - _Items, ModuleToLink) -->
-	module_name_to_file_name(ModuleName, "", no, ModuleToLink).
+	{ module_name_to_file_name(ModuleName, ModuleToLink) }.
 
 %-----------------------------------------------------------------------------%
 
@@ -1681,8 +1681,8 @@
 			{ UpdateStatus = yes }
 		; { UseOptFiles = yes } ->
 			{ module_info_name(HLDS0, ModuleName) },
-			module_name_to_file_name(ModuleName,
-				".opt", no, OptName),
+			module_name_to_search_file_name(ModuleName,
+				".opt", OptName),
 			search_for_file(IntermodDirs, OptName, Found),
 			( { Found = ok(_) } ->
 				{ UpdateStatus = yes },
@@ -3320,8 +3320,8 @@
 		Include) -->
 	(
 		{ Lang = c },
-		module_name_to_file_name(ModuleName, ".mh",
-			no, HeaderFileName),
+		module_name_to_search_file_name(ModuleName, ".mh",
+			HeaderFileName),
 		{ string__append_list(
 			["#include """, HeaderFileName, """\n"],
 			IncludeString) },
Index: compiler/mlds_to_c.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_c.m,v
retrieving revision 1.132
diff -u -u -r1.132 mlds_to_c.m
--- compiler/mlds_to_c.m	21 Jun 2002 13:26:42 -0000	1.132
+++ compiler/mlds_to_c.m	5 Jul 2002 07:18:22 -0000
@@ -191,7 +191,7 @@
 		unexpected(this_file, "foreign import in C backend")
 	},
 
-	module_name_to_file_name(ModuleName, HeaderExt, no, HeaderFile),
+	module_name_to_search_file_name(ModuleName, HeaderExt, HeaderFile),
 	io__write_strings(["#include """, HeaderFile, """\n"]).
 
 
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.239
diff -u -u -r1.239 modules.m
--- compiler/modules.m	30 Jun 2002 17:06:33 -0000	1.239
+++ compiler/modules.m	6 Jul 2002 16:42:53 -0000
@@ -61,8 +61,8 @@
 	%
 	%	Currently we use the convention that the module
 	%	`foo:bar:baz' should be named `foo.bar.baz.m',
-	%	but eventually we will also allow other file
-	%	naming conventions.
+	%	and allow other naming conventions with the
+	% 	`-f' option.
 	%
 	%	Note that this predicate is also used to create
 	%	some "phony" Makefile targets that do not have
@@ -72,6 +72,30 @@
 				io__state, io__state).
 :- mode module_name_to_file_name(in, in, in, out, di, uo) is det.
 
+	% module_name_to_search_file_name(Module, Extension, FileName):
+	% 
+	%	As above, but for a file which might be in an installed
+	% 	library, not the current directory.
+	%
+	%	With `--use-grade-subdirs', the current directory's `.mih'
+	%	files are in `Mercury/<grade>/<arch>/Mercury/mihs', and those
+	%	for installed libraries are in
+	%	`<prefix>/lib/mercury/lib/<grade>/<arch>/inc/Mercury/mihs'.
+	%
+	%	handle_options.m sets up the `--c-include-directory' options
+	%	so that the name `Mercury/mihs/<module>.mih' should be used
+	%	in a context which requires searching for the `.mih files,
+	%	for example in a C file.
+	%
+	%	module_name_to_file_name would return
+	%	`Mercury/<grade>/<arch>/Mercury/mihs/<module>.mihs',
+	%	which would be used when writing or removing the
+	%	`.mih' file.
+	%
+:- pred module_name_to_search_file_name(module_name, string, file_name,
+				io__state, io__state).
+:- mode module_name_to_search_file_name(in, in, out, di, uo) is det.
+
 	% module_name_to_lib_file_name(Prefix, Module, Extension, MkDir,
 	%		FileName):
 	%	Like module_name_to_file_name, but also allows a prefix.
@@ -119,6 +143,10 @@
 :- pred file_name_to_module_name(file_name, module_name).
 :- mode file_name_to_module_name(in, out) is det.
 
+	% convert a module name to a file name stem (e.g. foo.bar.baz).
+:- pred module_name_to_file_name(module_name, file_name).
+:- mode module_name_to_file_name(in, out) is det.
+
 	% Convert a module name to something that is suitable
 	% for use as a variable name in makefiles.
 :- pred module_name_to_make_var_name(module_name, string).
@@ -650,9 +678,12 @@
 :- pred update_interface(string, io__state, io__state).
 :- mode update_interface(in, di, uo) is det.
 
-	% make_directory(Dir)
+	% make_directory(Dir, Succeeded)
 	%
 	% Make the directory Dir and all its parents.
+:- pred make_directory(string, bool, io__state, io__state).
+:- mode make_directory(in, out, di, uo) is det.
+
 :- pred make_directory(string, io__state, io__state).
 :- mode make_directory(in, di, uo) is det.
 
@@ -678,7 +709,7 @@
 :- implementation.
 :- import_module ll_backend__llds_out, hlds__passes_aux, parse_tree__prog_out.
 :- import_module parse_tree__prog_util, parse_tree__mercury_to_mercury.
-:- import_module parse_tree__prog_io_util, libs__options.
+:- import_module parse_tree__prog_io_util, libs__options, libs__handle_options.
 :- import_module parse_tree__source_file_map.
 :- import_module parse_tree__module_qual, backend_libs__foreign.
 :- import_module recompilation__version.
@@ -760,7 +791,17 @@
 mercury_std_library_module("type_desc").
 mercury_std_library_module("varset").
 
+module_name_to_search_file_name(ModuleName, Ext, FileName) -->
+	module_name_to_file_name(ModuleName, Ext, yes, no, FileName).
+
 module_name_to_file_name(ModuleName, Ext, MkDir, FileName) -->
+	module_name_to_file_name(ModuleName, Ext, no, MkDir, FileName).
+
+:- pred module_name_to_file_name(module_name, string, bool, bool, file_name,
+				io__state, io__state).
+:- mode module_name_to_file_name(in, in, in, in, out, di, uo) is det.
+
+module_name_to_file_name(ModuleName, Ext, Search, MkDir, FileName) -->
 	( { Ext = ".m" } ->
 		% Look up the module in the module->file mapping.
 		source_file_map__lookup_module_source_file(ModuleName,
@@ -769,13 +810,14 @@
 		{ prog_out__sym_name_to_string(ModuleName,
 			".", BaseFileName) },
 		{ string__append_list([BaseFileName, Ext], BaseName) },
-		choose_file_name(ModuleName, BaseName, Ext, MkDir, FileName)
+		choose_file_name(ModuleName, BaseName, Ext,
+			Search, MkDir, FileName)
 	).
 
 module_name_to_lib_file_name(Prefix, ModuleName, Ext, MkDir, FileName) -->
 	{ prog_out__sym_name_to_string(ModuleName, ".", BaseFileName) },
 	{ string__append_list([Prefix, BaseFileName, Ext], BaseName) },
-	choose_file_name(ModuleName, BaseName, Ext, MkDir, FileName).
+	choose_file_name(ModuleName, BaseName, Ext, no, MkDir, FileName).
 
 fact_table_file_name(ModuleName, FactTableFileName, Ext, FileName) -->
 	extra_link_obj_file_name(ModuleName, FactTableFileName, Ext, FileName).
@@ -789,14 +831,16 @@
 :- mode extra_link_obj_file_name(in, in, in, out, di, uo) is det.
 extra_link_obj_file_name(ModuleName, ExtraLinkObjName, Ext, FileName) -->
 	{ string__append(ExtraLinkObjName, Ext, BaseName) },
-	choose_file_name(ModuleName, BaseName, Ext, no, FileName).
+	choose_file_name(ModuleName, BaseName, Ext, no, no, FileName).
 
-:- pred choose_file_name(module_name, string, string, bool, file_name,
+:- pred choose_file_name(module_name, string, string, bool, bool, file_name,
 			io__state, io__state).
-:- mode choose_file_name(in, in, in, in, out, di, uo) is det.
+:- mode choose_file_name(in, in, in, in, in, out, di, uo) is det.
 
-choose_file_name(_ModuleName, BaseName, Ext, MkDir, FileName) -->
+choose_file_name(_ModuleName, BaseName, Ext, Search, MkDir, FileName) -->
 	globals__io_lookup_bool_option(use_subdirs, UseSubdirs),
+	globals__io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs),
+	globals__io_get_globals(Globals),
 	( { UseSubdirs = no } ->
 		{ FileName = BaseName }
 	;
@@ -806,6 +850,23 @@
 		% output files intended for use by the user,
 		% and phony Mmake targets names go in the current directory
 		%
+		\+ {
+			UseGradeSubdirs = yes,
+			file_is_arch_or_grade_dependent(Globals, Ext),
+
+			%
+			% If we're searching for (rather than writing)
+			% a `.mh' file, use the plain file name. This is
+			% so that searches for files in installed libraries
+			% will work.  `--c-include-directory' is set so
+			% that searches for files in the current directory
+			% will work.
+			%
+			\+ (
+				Search = yes,
+				( Ext = ".mh" ; Ext = ".mh.tmp" )
+			)
+		},
 		{
 			% executable files
 			( Ext = ""
@@ -939,20 +1000,16 @@
 		->
 			string__append(ExtName, "s", SubDirName)
 		;
+			Ext = ""
+		->
+			SubDirName = "bin"
+		;
 			string__append_list(["unknown extension `", Ext, "'"],
 				ErrorMsg),
 			error(ErrorMsg)
 		},
-		{ dir__directory_separator(SlashChar) },
-		{ string__char_to_string(SlashChar, Slash) },
-		{ string__append_list(["Mercury", Slash, SubDirName],
-			DirName) },
-		( { MkDir = yes } ->
-			make_directory(DirName)
-		;
-			[]
-		),
-		{ string__append_list([DirName, Slash, BaseName], FileName) }
+		make_file_name(SubDirName, Search, MkDir,
+			BaseName, Ext, FileName)
 	).
 
 module_name_to_split_c_file_name(ModuleName, Num, Ext, FileName) -->
@@ -973,19 +1030,134 @@
 file_name_to_module_name(FileName, ModuleName) :-
 	string_to_sym_name(FileName, ".", ModuleName).
 
+module_name_to_file_name(ModuleName, FileName) :-
+	prog_out__sym_name_to_string(ModuleName, ".", FileName).
+
 module_name_to_make_var_name(ModuleName, MakeVarName) :-
 	prog_out__sym_name_to_string(ModuleName, ".", MakeVarName).
 
 make_directory(DirName) -->
+	make_directory(DirName, _Result).
+
+make_directory(DirName, Result) -->
 	( { dir__this_directory(DirName) } ->
-		[]
+		{ Result = yes }
 	;
-		{ make_command_string(string__format(
-			"[ -d %s ] || mkdir -p %s",
-			[s(DirName), s(DirName)]), forward, Command) },
-		io__call_system(Command, _Result)
+		{ string__format("[ -d %s ] || mkdir -p %s",
+			[s(DirName), s(DirName)], Command) },
+		io__output_stream(ErrorStream),
+		invoke_shell_command(ErrorStream, verbose, Command, Result)
 	).
 
+:- pred make_file_name(dir_name, bool, bool, file_name, string,
+		file_name, io__state, io__state).
+:- mode make_file_name(in, in, in, in, in, out, di, uo) is det.
+
+make_file_name(SubDirName, Search, MkDir, BaseName, Ext, FileName) -->
+	globals__io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs),
+	globals__io_lookup_string_option(fullarch, FullArch),
+	globals__io_get_globals(Globals),
+	{
+		UseGradeSubdirs = yes,
+		file_is_arch_or_grade_dependent(Globals, Ext),
+
+		%
+		% If we're searching for (rather than writing) the file,
+		% just search in Mercury/<ext>s. This is so that searches
+		% for files in installed libraries work.
+		% `--intermod-directories' and `--c-include-directories'
+		% are set so this will work.
+		%
+		\+ (
+			Search = yes,
+			( Ext = ".opt" ; Ext = ".mih" )
+		)
+	->
+		grade_directory_component(Globals, Grade),
+
+		% The extra "Mercury" is needed so we can use
+		% `--intermod-directory Mercury/<grade>/<fullarch>' and
+		% `--c-include Mercury/<grade>/<fullarch>' to find
+		% the local `.opt' and `.mih' files without messing
+		% up the search for the files for installed libraries.
+		DirName =  "Mercury"/Grade/FullArch/"Mercury"/SubDirName
+	;
+		DirName = "Mercury"/SubDirName
+	},
+	( { MkDir = yes } ->
+		make_directory(DirName)
+	;
+		[]
+	),
+	{ FileName = DirName/BaseName }.
+
+:- pred file_is_arch_or_grade_dependent(globals, string).
+:- mode file_is_arch_or_grade_dependent(in, in) is semidet.
+
+file_is_arch_or_grade_dependent(_, Ext) :-
+	file_is_arch_or_grade_dependent_2(Ext).
+file_is_arch_or_grade_dependent(Globals, Ext0) :-
+	string__append(Ext, ".tmp", Ext0), % for mercury_update_interface.
+	file_is_arch_or_grade_dependent(Globals, Ext).
+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),
+	( 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
+	; Ext = ".split" ++ LibExt
+	).
+file_is_arch_or_grade_dependent(Globals, Ext) :-
+	globals__lookup_string_option(Globals, shared_library_extension, Ext).
+
+:- pred file_is_arch_or_grade_dependent_2(string).
+:- mode file_is_arch_or_grade_dependent_2(in) is semidet.
+
+	% The `.used' file isn't grade dependent itself, but it contains
+	% information collected while compiling a grade-dependent
+	% `.c', `il', etc file.
+file_is_arch_or_grade_dependent_2(".used").
+file_is_arch_or_grade_dependent_2(".opt").
+file_is_arch_or_grade_dependent_2(".optdate").
+file_is_arch_or_grade_dependent_2(".trans_opt").
+file_is_arch_or_grade_dependent_2(".trans_opt_date").
+file_is_arch_or_grade_dependent_2(".mih").
+
+	% This isn't true (.mh files are the same in all grades)
+	% but we need to generate the `.mh' files in a sub-directory
+	% so that we don't need to pass `--c-include-directory .' to mmc,
+	% which would resut in the `.mih' files for the default grade
+	% being found, rather than those for the current grade, when
+	% installing a library.
+file_is_arch_or_grade_dependent_2(".mh").
+file_is_arch_or_grade_dependent_2(".c").
+file_is_arch_or_grade_dependent_2(".c_date").
+file_is_arch_or_grade_dependent_2(".s").
+file_is_arch_or_grade_dependent_2(".s_date").
+file_is_arch_or_grade_dependent_2(".pic_s").
+file_is_arch_or_grade_dependent_2(".pic_s_date").
+file_is_arch_or_grade_dependent_2(".il").
+file_is_arch_or_grade_dependent_2(".il_date").
+file_is_arch_or_grade_dependent_2(".java").
+file_is_arch_or_grade_dependent_2(".java_date").
+file_is_arch_or_grade_dependent_2(".class").
+file_is_arch_or_grade_dependent_2(".dir").
+file_is_arch_or_grade_dependent_2(".num_split").
+file_is_arch_or_grade_dependent_2(".dll").
+file_is_arch_or_grade_dependent_2(".$A").
+file_is_arch_or_grade_dependent_2(".a").
+file_is_arch_or_grade_dependent_2(".split.$A").
+file_is_arch_or_grade_dependent_2(".split.a").
+file_is_arch_or_grade_dependent_2(".split").
+file_is_arch_or_grade_dependent_2("_init.c").
+file_is_arch_or_grade_dependent_2("_init.$O").
+
 %-----------------------------------------------------------------------------%
 
 	% Read in the .int3 files that the current module depends on,
@@ -2258,8 +2430,8 @@
 		%
 		have_source_file_map(HaveMap),
 		{ HaveMap = yes,
-			prog_out__sym_name_to_string(
-				SourceFileModuleName, ".", ModuleArg)
+			module_name_to_file_name(SourceFileModuleName,
+				ModuleArg)
 		; HaveMap = no,
 			ModuleArg = SourceFileName
 		},
@@ -2361,7 +2533,7 @@
 			% Also add the variable ILASM_KEYFLAG-<module> which
 			% is used to build the command line for ilasm.
 		( { Target = il, SignAssembly = yes } ->
-			{ prog_out__sym_name_to_string(ModuleName, ".",
+			{ module_name_to_make_var_name(ModuleName,
 					ModuleNameString) },
 			module_name_to_file_name(ModuleName, ".il",
 					no, IlFileName),
@@ -2572,8 +2744,8 @@
 			ModuleName, ForeignLang) },
 		{ ForeignExt = foreign_language_file_extension(ForeignLang) }
 	->
-		module_name_to_file_name(ForeignModuleName, "", no,
-			ForeignModuleNameString),
+		{ module_name_to_make_var_name(ForeignModuleName,
+			ForeignModuleNameString) },
 		module_name_to_file_name(ForeignModuleName, ForeignExt, no,
 			ForeignFileName),
 		module_name_to_file_name(ModuleName, ".il", no, IlFileName),
@@ -2629,7 +2801,7 @@
 	module_name::in, string::in, io__state::di, io__state::uo) is det.
 
 write_subdirs_shorthand_rule(DepStream, ModuleName, Ext) -->
-	{ prog_out__sym_name_to_string(ModuleName, ".", ModuleStr) },
+	{ module_name_to_file_name(ModuleName, ModuleStr) },
 	module_name_to_file_name(ModuleName, Ext, no, Target),
 	{ ShorthandTarget = ModuleStr ++ Ext },
 	io__write_string(DepStream, ".PHONY: "),
@@ -2824,7 +2996,7 @@
 	),
 	{ is_bool(Found) },
 	( { Found = no } ->
-		module_name_to_file_name(Dep, Suffix, no, OptName),
+		module_name_to_search_file_name(Dep, Suffix, OptName),
 		search_for_file(IntermodDirs, OptName, Result2),
 		( { Result2 = ok(_) } ->
 			{ OptDeps = [Dep | OptDeps1] },
@@ -4928,7 +5100,12 @@
 read_mod_2(IgnoreErrors, ModuleName,
 		Extension, Descr, Search, MaybeOldTimestamp,
 		ReturnTimestamp, Items, Error, FileName, MaybeTimestamp) -->
-	module_name_to_file_name(ModuleName, Extension, no, FileName0),
+	( { Search = yes } ->
+		module_name_to_search_file_name(ModuleName,
+			Extension, FileName0)
+	;
+		module_name_to_file_name(ModuleName, Extension, no, FileName0)
+	),
 	globals__io_lookup_bool_option(very_verbose, VeryVerbose),
 	maybe_write_string(VeryVerbose, "% "),
 	maybe_write_string(VeryVerbose, Descr),
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.376
diff -u -u -r1.376 options.m
--- compiler/options.m	2 Jul 2002 06:19:37 -0000	1.376
+++ compiler/options.m	6 Jul 2002 16:09:34 -0000
@@ -551,6 +551,7 @@
 		;	options_files
 		;	options_search_directories
 		;	use_subdirs
+		;	use_grade_subdirs
 
 	% Miscellaneous Options
 		;	search_directories
@@ -1091,6 +1092,7 @@
 	options_files		-	accumulating(["Mercury.options"]),
 	options_search_directories -	accumulating(["."]),
 	use_subdirs		-	bool(no),
+	use_grade_subdirs	-	bool(no),
 	search_directories 	-	accumulating(["."]),
 	intermod_directories	-	accumulating([]),
 	use_search_directories_for_intermod
@@ -1670,6 +1672,7 @@
 long_option("options-file",		options_files).
 long_option("options-search-directory", options_search_directories).
 long_option("use-subdirs",		use_subdirs).	
+long_option("use-grade-subdirs",	use_grade_subdirs).	
 long_option("search-directory",		search_directories).
 long_option("intermod-directory",	intermod_directories).
 long_option("use-search-directories-for-intermod",
@@ -3462,6 +3465,13 @@
 		"--use-subdirs",
 		"\tGenerate intermediate files in a `Mercury' subdirectory,",
 		"\trather than generating them in the current directory."
+
+		% `--use-grade-subdirs' is not documented because it
+		% is only intended for use in library installation
+		% with `mmc --make' (it doesn't work at all with Mmake).
+		% Documenting it would require documenting (and setting
+		% in stone) the layout of the `Mercury' directory, which
+		% is probably a bad idea.
 	]).
 
 :- pred options_help_misc(io__state::di, io__state::uo) is det.
Index: compiler/options_file.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options_file.m,v
retrieving revision 1.8
diff -u -u -r1.8 options_file.m
--- compiler/options_file.m	25 May 2002 13:25:09 -0000	1.8
+++ compiler/options_file.m	7 Jul 2002 10:00:57 -0000
@@ -762,6 +762,8 @@
 	;	c2init_args
 	;	libraries
 	;	lib_dirs
+	;	lib_grades
+	;	install_prefix
 	.
 
 :- func options_variable_types = list(options_variable_type).
@@ -773,7 +775,8 @@
 	[grade_flags, mmc_flags, c_flags, java_flags,
 	ilasm_flags, csharp_flags, mcpp_flags,
 	ml_objs, lib_dirs, ml_flags, ld_flags,
-	libraries, ml_libs, c2init_args].
+	libraries, ml_libs, c2init_args,
+	lib_grades, install_prefix].
 
 :- func options_variable_name(options_variable_type) = string.
 
@@ -792,6 +795,8 @@
 options_variable_name(c2init_args) = "C2INITARGS".
 options_variable_name(libraries) = "LIBRARIES".
 options_variable_name(lib_dirs) = "LIB_DIRS".
+options_variable_name(lib_grades) = "LIBGRADES".
+options_variable_name(install_prefix) = "INSTALL_PREFIX".
 
 :- func options_variable_type_is_target_specific(options_variable_type) = bool.
 
@@ -810,6 +815,9 @@
 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.
 
 :- func convert_to_mmc_options(pair(options_variable_type, list(string)))
 			= list(string).
@@ -820,22 +828,26 @@
 		MMCOptionType = mmc_flags,
 		OptionsStrings = VariableValue
 	;
-		MMCOptionType = option(not_split, OptionName),
-		OptionsStrings = [OptionName,
+		MMCOptionType = option(not_split, InitialOptions, OptionName),
+		OptionsStrings = InitialOptions ++ [OptionName,
 					string__join_list(" ", VariableValue)]
 	;
-		MMCOptionType = option(split, OptionName),
-		OptionsStrings = list__condense(
+		MMCOptionType = option(split, InitialOptions, OptionName),
+		OptionsStrings = list__condense([InitialOptions |
 				list__map((func(Word) = [OptionName, Word]),
-					VariableValue))
+					VariableValue)])
 	).
 
 :- type mmc_option_type
 	--->	mmc_flags	% The options can be passed directly to mmc.
 
-	;	option(split_into_words, option_name :: string)
-				% The options need to be passed as an
-				% argument of an option to mmc.
+	;	option(split_into_words, initial_options :: list(string),
+				option_name :: string)
+			% The options need to be passed as an
+			% argument of an option to mmc.
+			% The `initial_options' will be passed before
+			% the options generated by the variable.
+			% This is useful for clearing an accumulating option.
 	.
 
 	% The split_into_words type specifies whether there should be
@@ -853,19 +865,21 @@
 
 mmc_option_type(grade_flags) = mmc_flags.
 mmc_option_type(mmc_flags) = mmc_flags.
-mmc_option_type(c_flags) = option(not_split, "--cflags").
-mmc_option_type(java_flags) = option(not_split, "--java-flags").
-mmc_option_type(ilasm_flags) = option(not_split, "--ilasm-flags").
-mmc_option_type(mcpp_flags) = option(not_split, "--mcpp-flags").
-mmc_option_type(csharp_flags) = option(not_split, "--csharp-flags").
-mmc_option_type(ml_flags) = option(not_split, "--link-flags").
-mmc_option_type(ml_objs) = option(split, "--link-object").
+mmc_option_type(c_flags) = option(not_split, [], "--cflags").
+mmc_option_type(java_flags) = option(not_split, [], "--java-flags").
+mmc_option_type(ilasm_flags) = option(not_split, [], "--ilasm-flags").
+mmc_option_type(mcpp_flags) = option(not_split, [], "--mcpp-flags").
+mmc_option_type(csharp_flags) = option(not_split, [], "--csharp-flags").
+mmc_option_type(ml_flags) = option(not_split, [], "--link-flags").
+mmc_option_type(ml_objs) = option(split, [], "--link-object").
 mmc_option_type(ml_libs) = mmc_flags.
-mmc_option_type(ld_flags) = option(not_split, "--ld-flags").
-mmc_option_type(ld_libflags) = option(not_split, "--ld-libflags").
-mmc_option_type(c2init_args) = option(split, "--init-file").
-mmc_option_type(libraries) = option(split, "--mercury-library").
-mmc_option_type(lib_dirs) = option(split, "--mercury-library-directory").
+mmc_option_type(ld_flags) = option(not_split, [], "--ld-flags").
+mmc_option_type(ld_libflags) = option(not_split, [], "--ld-libflags").
+mmc_option_type(c2init_args) = option(split, [], "--init-file").
+mmc_option_type(libraries) = option(split, [], "--mercury-library").
+mmc_option_type(lib_dirs) = option(split, [], "--mercury-library-directory").
+mmc_option_type(lib_grades) = option(split, ["--no-libgrade"], "--libgrade").
+mmc_option_type(install_prefix) = option(not_split, [], "--install-prefix").
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/trans_opt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/trans_opt.m,v
retrieving revision 1.18
diff -u -u -r1.18 trans_opt.m
--- compiler/trans_opt.m	7 Apr 2002 10:22:51 -0000	1.18
+++ compiler/trans_opt.m	5 Jul 2002 07:21:14 -0000
@@ -160,7 +160,7 @@
 	maybe_write_string(VeryVerbose, "'... "),
 	maybe_flush_output(VeryVerbose),
 
-	module_name_to_file_name(Import, ".trans_opt", no, FileName),
+	module_name_to_search_file_name(Import, ".trans_opt", FileName),
 	prog_io__read_opt_file(FileName, Import,
 			ModuleError, Messages, Items1),
 
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.314
diff -u -u -r1.314 user_guide.texi
--- doc/user_guide.texi	12 Jun 2002 14:26:55 -0000	1.314
+++ doc/user_guide.texi	6 Jul 2002 16:47:34 -0000
@@ -838,8 +838,7 @@
 
 The advantages of the @samp{mmc --make} over Mmake are that there
 is no @samp{mmake depend} step and the dependencies are more accurate.
-Library installation (@pxref{Libraries}) and parallel builds are not
-yet supported.
+Parallel builds are not yet supported.
 
 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}
Index: scripts/Mmake.vars.in
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/Mmake.vars.in,v
retrieving revision 1.74
diff -u -u -r1.74 Mmake.vars.in
--- scripts/Mmake.vars.in	24 Jun 2002 16:15:22 -0000	1.74
+++ scripts/Mmake.vars.in	7 Jul 2002 10:53:55 -0000
@@ -126,6 +126,8 @@
 	echo LD_LIBFLAGS += '$(ALL_LD_LIBFLAGS)'; \
 	echo EXTRA_LIBRARIES += '$(EXTRA_LIBRARIES)'; \
 	echo EXTRA_LIB_DIRS += '$(EXTRA_LIB_DIRS)'; \
+	echo LIBGRADES = '$(ALL_LIBGRADES)'; \
+	echo INSTALL_PREFIX = '$(INSTALL_PREFIX)'; \
 	}
 
 MC_MAKE_FLAGS	=
@@ -185,14 +187,14 @@
 
 MGNUC		= mgnuc
 ALL_MGNUCFLAGS	= $(MGNUCFLAGS) $(EXTRA_MGNUCFLAGS) $(TARGET_MGNUCFLAGS) \
-		  $(LIB_MGNUCFLAGS) -- $(ALL_CFLAGS)
+		  -- $(ALL_CFLAGS)
 MGNUCFLAGS	=
 EXTRA_MGNUCFLAGS =
-LIB_MGNUCFLAGS	= $(patsubst %,-I %,$(EXTRA_C_INCL_DIRS))
 
-ALL_CFLAGS	= $(CFLAGS) $(EXTRA_CFLAGS) $(TARGET_CFLAGS)
+ALL_CFLAGS	= $(CFLAGS) $(EXTRA_CFLAGS) $(TARGET_CFLAGS) $(LIB_CFLAGS)
 CFLAGS		=
 EXTRA_CFLAGS	=
+LIB_CFLAGS	= $(patsubst %,-I %,$(EXTRA_C_INCL_DIRS))
 
 #-----------------------------------------------------------------------------#
 #
--------------------------------------------------------------------------
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