[m-rev.] for review: auto detection of library grades

Peter Wang novalazy at gmail.com
Tue Sep 3 16:27:02 AEST 2013


On Wed, 28 Aug 2013 17:47:00 +1000 (EST), Julien Fischer <jfischer at opturion.com> wrote:
> 
> For review by anyone.
> 
> This change has also revealed a bug in the existing library grade check in
> mmc --make; I will fix that separately since that fix also needs to go on
> to the 13.05 branch.
> 
> --------------------
> 
> 
> Auto detection of standard library grades.
> 
> Currently, the set of installed standard library grades is hardcoded in
> Mercury's configuration file (and some other spots, but they are not relevant
> here).  This change modifies the compiler so it can scan the standard library
> directory at runtime in order to determine what library grades are installed.
> This removes the need for the set of library grades to be specified in the
> configuration file at all.  Adding or removing grades from an existing
> installation should now not require changes to any configuration files
> (provided you don't use mmake -- see below).
> 
> In the case where the library grades are specified in the Mercury.config file
> and auto detection is also enabled, the auto detected grades will override any
> --libgrade settings from the Mercury.config file.
> 
> Automatic detection of library grades is not supported with mmake and I don't
> have any plans to support it.  mmake will just use the set of grades with
> which the installation was configured.
> 
> compiler/options.m:
>  	Add a new option `--auto-detect-libgrades' that can be used to control
>  	the new feature.  For now, this is a developer-only option and is
>  	disabled by default -- I will document it properly when it is enabled
>  	by default.

I assume it's intended to be enabled for mmc --make in future.

Minor thing, but I think the "auto"- and "Auto"- prefixes don't add
anything.

> 
> compiler/mercury_compile.m:
>  	Scan the standard library directory to see what grades are installed
>  	and set the options necessary to make the set of library grades those
>  	that were detected.
> 
> compiler/options_file.m:
>  	Add a predicate for looking up the value of the MERCURY_STDLIB_DIR
>  	variable.
> 
> Julien.
> 
> diff --git a/compiler/mercury_compile.m b/compiler/mercury_compile.m
> index 9e690bb..8623595 100644
> --- a/compiler/mercury_compile.m
> +++ b/compiler/mercury_compile.m
> @@ -89,6 +89,7 @@
>   :- import_module assoc_list.
>   :- import_module bool.
>   :- import_module cord.
> +:- import_module dir.
>   :- import_module gc.
>   :- import_module getopt_io.
>   :- import_module list.
> @@ -235,6 +236,7 @@ real_main_after_expansion(CmdLineArgs, !IO) :-
>               OptionArgs = [],
>               NonOptionArgs = []
>           ),
> +        AutoDetectedGradeFlags = [],
>           Variables = options_variables_init,
>           MaybeMCFlags = yes([])
>       ;
> @@ -258,6 +260,7 @@ real_main_after_expansion(CmdLineArgs, !IO) :-
>                   (
>                       FlagsErrors = [_ | _],
>                       usage_errors(FlagsErrors, !IO),
> +                    AutoDetectedGradeFlags = [],
>                       Variables = options_variables_init,
>                       MaybeMCFlags = no
>                   ;
> @@ -271,14 +274,20 @@ real_main_after_expansion(CmdLineArgs, !IO) :-
>                           (
>                               MaybeVariables = yes(Variables),
>                               lookup_mmc_options(FlagsArgsGlobals, Variables,
> -                                MaybeMCFlags, !IO)
> +                                MaybeMCFlags, !IO),
> +                            lookup_mercury_stdlib_dir(FlagsArgsGlobals, Variables,
> +                                MaybeMerStdLibDir, !IO),
> +                            auto_detect_libgrades(FlagsArgsGlobals, MaybeMerStdLibDir,
> +                                AutoDetectedGradeFlags, !IO)
>                           ;
>                               MaybeVariables = no,
>                               MaybeMCFlags = no,
> +                            AutoDetectedGradeFlags = [],
>                               Variables = options_variables_init
>                           )
>                       ;
>                           MaybeConfigFile = no,
> +                        AutoDetectedGradeFlags = [],
>                           Variables = options_variables_init,
>                           lookup_mmc_options(FlagsArgsGlobals, Variables,
>                               MaybeMCFlags, !IO)
> @@ -287,18 +296,20 @@ real_main_after_expansion(CmdLineArgs, !IO) :-
>               ;
>                   MaybeMCFlags0 = no,
>                   Variables = options_variables_init,
> +                AutoDetectedGradeFlags = [],
>                   MaybeMCFlags = no
>               )
>           ;
>               MaybeVariables0 = no,
>               Variables = options_variables_init,
> +            AutoDetectedGradeFlags = [],
>               MaybeMCFlags = no
>           )
>       ),
>       (
>           MaybeMCFlags = yes(MCFlags),
> -        handle_given_options(MCFlags ++ OptionArgs, _, _, _,
> -            Errors, ActualGlobals, !IO),
> +        AllFlags = MCFlags ++ AutoDetectedGradeFlags ++ OptionArgs,
> +        handle_given_options(AllFlags, _, _, _, Errors, ActualGlobals, !IO),
> 
>           % When computing the option arguments to pass to `--make', only include
>           % the command-line arguments, not the contents of DEFAULT_MCFLAGS.
> @@ -2025,6 +2036,107 @@ maybe_output_prof_call_graph(Verbose, Stats, !HLDS, !IO) :-
>       ).
> 
>   %-----------------------------------------------------------------------------%
> +%
> +% Library grade detection.
> +%
> +
> +:- pred auto_detect_libgrades(globals::in, maybe(list(string))::in,
> +    list(string)::out, io::di, io::uo) is det.
> +
> +auto_detect_libgrades(Globals, MaybeConfigMerStdLibDir, GradeOpts, !IO) :-
> +    globals.lookup_bool_option(Globals, auto_detect_libgrades, AutoDetect),
> +    (
> +        AutoDetect = yes,
> +        ( if
> +            % Was the standard library directory set on the command line?
> +            % 
> +            globals.lookup_maybe_string_option(Globals,
> +                mercury_standard_library_directory, MaybeStdLibDir),
> +            MaybeStdLibDir = yes(MerStdLibDir)
> +        then
> +            do_auto_detect_libgrades(MerStdLibDir, GradeOpts, !IO)
> +        else if
> +            % Was the standard library directory set using the
> +            % MERCURY_STDLIB_DIR variable?
> +            MaybeConfigMerStdLibDir = yes([MerStdLibDir])
> +        then
> +            do_auto_detect_libgrades(MerStdLibDir, GradeOpts, !IO)
> +        else
> +            GradeOpts = [] 
> +        )

Maybe lookup_maybe_string_option followed by switch on MaybeStdLibDir.

> +    ;
> +        AutoDetect = no,
> +        GradeOpts = []
> +    ).
> +
> +:- pred do_auto_detect_libgrades(string::in, list(string)::out,
> +    io::di, io::uo) is det.
> +
> +do_auto_detect_libgrades(StdLibDir, GradeOpts, !IO) :-
> +    ModulesDir = StdLibDir / "modules",
> +    dir.foldl2(do_auto_detect_libgrade, ModulesDir, [], MaybeGradeOpts, !IO),
> +    (
> +        MaybeGradeOpts = ok(GradeOpts0),
> +        (
> +            GradeOpts0 = [],
> +            GradeOpts = GradeOpts0
> +        ;
> +            GradeOpts0 = [_ | _],
> +            % Override any --libgrades settings from Mercury.config.
> +            GradeOpts = ["--no-libgrade" | GradeOpts0]
> +        )
> +    ;
> +        MaybeGradeOpts = error(_, _),
> +        GradeOpts = []
> +    ).
> +

> +:- pred do_auto_detect_libgrade(string::in, string::in, io.file_type::in,
> +    bool::out, list(string)::in, list(string)::out, io::di, io::uo) is det.
> +
> +do_auto_detect_libgrade(DirName, FileName, FileType, Continue, !GradeOpts, !IO) :-
> +    (
> +        FileType = directory,
> +        (
> +            % We do not generate .init files for the non-C grades so just check
> +            % for directories in StdLibDir / "modules" containing the name of
> +            % their base grade.
> +            %
> +            ( string.prefix(FileName, "csharp")
> +            ; string.prefix(FileName, "erlang")
> +            ; string.prefix(FileName, "java")
> +            )
> +        ->
> +            !:GradeOpts = ["--libgrade", FileName | !.GradeOpts]
> +        ;
> +            % For C grades, we check for the presence of the .init file for
> +            % mer_std to test whether the grade is present or not.
> +            %
> +            InitFile = DirName / FileName / "mer_std.init",
> +            io.check_file_accessibility(InitFile, [read], Result, !IO),
> +            (
> +                Result = ok,
> +                !:GradeOpts = ["--libgrade", FileName | !.GradeOpts]
> +            ;
> +                Result = error(_)
> +            )
> +        ),
> +        Continue = yes

Is the test for the .init file really necessary?
The list of non-C grade prefixes is another thing to maintain.

Peter



More information about the reviews mailing list