From faa18a15bd332b51ec6d6fdae4d999ec2bf3fa82 Mon Sep 17 00:00:00 2001 From: Julien Fischer Date: Sun, 21 May 2006 06:22:59 +0000 Subject: [PATCH] Fix the bug with initialisers/finalisers in libraries not being called ( and Estimated hours taken: 7 Branches: main, release Fix the bug with initialisers/finalisers in libraries not being called ( and as consequence also fixes the bug with mutables not being given their correct initial value). The problem was that the directives necessary to call them were not being included in the libraries' .init file. The fix is to add a new mode of operation to mkinit that given a list of .c files that make up some Mercury library, constructs the .init file for that library. In particular, it now constructs the .init file so that it contains any REQUIRED_{INIT,FINAL} directives needed by the library. The new mode of operation is invoked when mkinit is given the `-k' option. Modify the build systems (i.e. mmake and mmc --make) to conform to the above change. compiler/modules.m: Change the rule mmake uses to build .init files so that it calls mkinit -k on all the .c files generated for the library. scripts/Mmake.vars.in: Add a new mmake variable MKLIBINIT. This is the program used to create .init files. (It will nearly always be mkinit.) compiler/compile_target_code.m: Change how .init files are built. We now have to call mkinit -k to scan all of the .c files to write out the correct set of INIT, REQUIRED_INIT and REQUIRED_FINAL directives. The code here is that used by mmc --make for creating the .init files. compiler/make.program_target.m: Build the .init file after building the .c files, since building it before will no longer work. --- compiler/compile_target_code.m | 53 ++++++++++++++++++++-------------- compiler/make.program_target.m | 50 +++++++++++++++++--------------- compiler/modules.m | 16 +++++----- scripts/Mmake.vars.in | 4 +++ 4 files changed, 71 insertions(+), 52 deletions(-) diff --git a/compiler/compile_target_code.m b/compiler/compile_target_code.m index bb4875503..88178ee84 100644 --- a/compiler/compile_target_code.m +++ b/compiler/compile_target_code.m @@ -866,18 +866,39 @@ make_init_file(ErrorStream, MainModuleName, AllModules, Succeeded, !IO) :- io.open_output(TmpInitFileName, InitFileRes, !IO), ( InitFileRes = ok(InitFileStream), - list.foldl(make_init_file(InitFileStream), AllModules, !IO), - globals.io_lookup_maybe_string_option(extra_init_command, - MaybeInitFileCommand, !IO), - ( - MaybeInitFileCommand = yes(InitFileCommand), - make_all_module_command(InitFileCommand, MainModuleName, - AllModules, CommandString, !IO), - invoke_system_command(InitFileStream, verbose_commands, - CommandString, Succeeded0, !IO) + ModuleNameToCFileName = + (pred(ThisModule::in, CFileName::out, !.IO::di, !:IO::uo) is det :- + module_name_to_file_name(ThisModule, ".c", no, CFileName, !IO) + ), + list.map_foldl(ModuleNameToCFileName, AllModules, AllCFilesList, !IO), + join_quoted_string_list(AllCFilesList, "", "", " ", CFileNames), + + globals.io_lookup_string_option(mkinit_command, MkInit, !IO), + MkInitCmd = string.append_list( + [ MkInit, + " -k ", + " ", CFileNames + ]), + invoke_system_command(InitFileStream, verbose, MkInitCmd, MkInitOK, + !IO), + + ( + MkInitOK = yes, + globals.io_lookup_maybe_string_option(extra_init_command, + MaybeInitFileCommand, !IO), + ( + MaybeInitFileCommand = yes(InitFileCommand), + make_all_module_command(InitFileCommand, MainModuleName, + AllModules, CommandString, !IO), + invoke_system_command(InitFileStream, verbose_commands, + CommandString, Succeeded0, !IO) + ; + MaybeInitFileCommand = no, + Succeeded0 = yes + ) ; - MaybeInitFileCommand = no, - Succeeded0 = yes + MkInitOK = no, + Succeeded0 = no ), io.close_output(InitFileStream, !IO), @@ -898,16 +919,6 @@ make_init_file(ErrorStream, MainModuleName, AllModules, Succeeded, !IO) :- Succeeded = no ). -:- pred make_init_file(io.output_stream::in, module_name::in, - io::di, io::uo) is det. - -make_init_file(InitFileStream, ModuleName, !IO) :- - InitFuncName0 = make_init_name(ModuleName), - InitFuncName = InitFuncName0 ++ "init", - io.write_string(InitFileStream, "INIT ", !IO), - io.write_string(InitFileStream, InitFuncName, !IO), - io.nl(InitFileStream, !IO). - %-----------------------------------------------------------------------------% link_module_list(Modules, FactTableObjFiles, Succeeded, !IO) :- diff --git a/compiler/make.program_target.m b/compiler/make.program_target.m index 7a1b6e03c..9ec522ad2 100644 --- a/compiler/make.program_target.m +++ b/compiler/make.program_target.m @@ -5,12 +5,13 @@ % This file may only be copied under the terms of the GNU General % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% - +% % File: make.program_target.m. % Main author: stayl. - +% % Build targets which relate to whole programs or libraries. - +% +%-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% :- module make.program_target. @@ -560,32 +561,33 @@ make_misc_target(MainModuleName - TargetType, _, Succeeded, !Info, !IO) :- IntSucceeded, !Info, !IO), ( IntSucceeded = yes, - % Errors while making the `.init' file should be very rare. - io.output_stream(ErrorStream, !IO), - compile_target_code.make_init_file(ErrorStream, MainModuleName, - AllModules, InitSucceeded, !IO), + make_linked_target(MainModuleName - static_library, + StaticSucceeded, !Info, !IO), + shared_libraries_supported(SharedLibsSupported, !IO), ( - InitSucceeded = yes, - make_linked_target(MainModuleName - static_library, - StaticSucceeded, !Info, !IO), - compile_target_code.shared_libraries_supported( - SharedLibsSupported, !IO), + StaticSucceeded = yes, ( - StaticSucceeded = yes, - ( - SharedLibsSupported = yes, - make_linked_target(MainModuleName - shared_library, - Succeeded, !Info, !IO) - ; - SharedLibsSupported = no, - Succeeded = yes - ) + SharedLibsSupported = yes, + make_linked_target(MainModuleName - shared_library, + SharedLibsSucceeded, !Info, !IO) ; - StaticSucceeded = no, - Succeeded = no + SharedLibsSupported = no, + SharedLibsSucceeded = yes + ), + % We can only build the .init file if we have succesfully + % built the .c files. + ( + SharedLibsSucceeded = yes, + % Errors while making the .init file should be very rare. + io.output_stream(ErrorStream, !IO), + make_init_file(ErrorStream, MainModuleName, + AllModules, Succeeded, !IO) + ; + SharedLibsSucceeded = no, + Succeeded = no ) ; - InitSucceeded = no, + StaticSucceeded = no, Succeeded = no ) ; diff --git a/compiler/modules.m b/compiler/modules.m index 1cee5f3d8..5ee0b2cbe 100644 --- a/compiler/modules.m +++ b/compiler/modules.m @@ -5,10 +5,10 @@ % This file may only be copied under the terms of the GNU General % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% - +% % File: modules.m. % Main author: fjh. - +% % This module contains all the code for handling module imports and exports, % for computing module dependencies, and for generating makefile fragments to % record those dependencies. @@ -37,6 +37,7 @@ % file gives the last time the .int0 file was checked. % %-----------------------------------------------------------------------------% +%-----------------------------------------------------------------------------% :- module parse_tree.modules. :- interface. @@ -5048,9 +5049,6 @@ generate_dep_file(SourceFileName, ModuleName, DepsMap, DepStream, !IO) :- io.write_string(DepStream, Version, !IO), io.write_string(DepStream, ".\n\n", !IO), - map.keys(DepsMap, Modules0), - select_ok_modules(Modules0, DepsMap, Modules), - module_name_to_make_var_name(ModuleName, MakeVarName), module_name_to_file_name(ModuleName, ".init", yes, InitFileName, !IO), @@ -5270,12 +5268,16 @@ generate_dep_file(SourceFileName, ModuleName, DepsMap, DepStream, !IO) :- module_name_to_file_name(ModuleName, ".dep", no, DepFileName, !IO), module_name_to_file_name(ModuleName, ".dv", no, DvFileName, !IO), + io.write_strings(DepStream, [ InitFileName, " : ", DepFileName, "\n", "\techo > ", InitFileName, "\n" ], !IO), - list.foldl(append_to_init_list(DepStream, InitFileName), Modules, !IO), - + io.write_strings(DepStream, [ + "\t$(MKLIBINIT) ", "$(", MakeVarName, ".cs)", " >> ", + InitFileName, "\n" + ], !IO), + % $(EXTRA_INIT_COMMAND) should expand to a command to % generate extra entries in the `.init' file for a library. % It may expand to the empty string. diff --git a/scripts/Mmake.vars.in b/scripts/Mmake.vars.in index f4946b4db..9ab872fa5 100644 --- a/scripts/Mmake.vars.in +++ b/scripts/Mmake.vars.in @@ -358,6 +358,10 @@ MLLIBS = EXTRA_MLLIBS = LIB_MLLIBS = $(patsubst %,-l%,$(ALL_EXTRA_LIBRARIES)) +# Program used to create the .init file for a library. +# This is usually just mkinit invoked with the `-k' option. +MKLIBINIT = mkinit -k + # These only have an effect with `mmc --make'. LINKAGE = shared MERCURY_LINKAGE = @DEFAULT_LINKAGE@