Skip to content

Latest commit

 

History

History
584 lines (360 loc) · 20.4 KB

NQP-Config.md

File metadata and controls

584 lines (360 loc) · 20.4 KB

NAME

NQP::Config

SYNOPSIS

use NQP::Config;
use NQP::Config::Rakudo; # The language we're building

my $cfg = NQP::Config::Rakudo->new;

my $config = $cfg->config( no_ctx => 1 );

$config->{a_variable} = "a value"; # This can be later expanded as @a_variable@ by macros in a template.

$cfg->configure_paths;
$cfg->configure_from_options;

...

$cfg->expand_template;

...

DESCRIPTION

This is a helper module for build a language from NQP/Raku family. It provides basic utility methods, configure_-family methods for presetting environment-dependent values, and methods to manipulate this data.

NQP::Config is a base (abstract) class which has to be inherited and completed by a language-specific class. See NQP::Config::NQP and NQP::Config::Rakudo classes from nqp and rakudo implementations.

Concepts

Configuration

A hash of configuration variables as keys with their values.

Configuration Context

Usually referred as just context.

A NQP::Config object manages a collection of configurations stored as a stack-like list. Whenever a configuration variable is requested its being searched in the list from top to bottom. The bottommost configuration does not belong to the list and is stored in config key on the object itself. Each entry in the list is called context because it might be created by some configuration subsystems for a limited period of time and be destroyed when no long needed. So, we can say that a configuration variable has a value in a context.

However, contexts are a little more than chunks of configuration. A context is a hash where configuration is defined by configs key. Other key names are not reserved by now and can be used for holding any useful information. They're called properties and can be requested with method prop. From this point of view attribute keys on the configuration object itself are the bottom-level properties, similar to config key been the bottom-level configuration.

Note that configuration keys is using plural form of its name configs. This is because it is a list too, a list of configuration hashes in this case. Though it seems somewhat overcomplicated but there is a good explanation for this: sometimes a context config chunk is being assembled from several pieces; while merging of hashrefs in Perl is terrible...

Another tricky part is that chunks in the context list are searched for a variable in start-to-end order. This is because the first chunk in the context is considered the base to which other chunks can only append missing variables.

Backends

Options

They should be called 'command line options', but a short form is a short form! It's too attractive for lazy ones...

Note that options can only be set from the command line and their alteration is better be avoided at any cost. This is our initial status which is to be used as the ground for all decisions we make. If an option or its default value is needed to be reconsidered during configuration process then it's value must be cloned and either stored on the configuration object itself; or used as a configuration variable. The latter is preferable. If the value is a boolean and the option of setting a configuration variable is chosen then it is recommended to use some user-readable values. For example, marking a relocatable build variable relocatable is set to reloc; and to nonreloc otherwise. Though this might complicate some code a bit it provides a better way to use these variable in templates when necessary:

@template(nqp-m-@relocatable@)@

Nobody would object that having nqp-m-reloc and nqp-m-nonreloc template files is preferable over nqp-m-1 and nqp-m-0.

Scoping Object

An instance of NQP::Config::_Scoping class which would execute a callback when destroyed. Usually used to auto-delete a context when code is leaving a scope.

ATTRIBUTES

Because NQP::Class is build using barebones Perl OO implementation, there're no attributes as such. We're listing here keys on a NQP::Class instance.

Some irrelevant and internally used keys would miss a description. They're only listed here to avoid being accidentally used by a child class.

  • config the main (bottommost) hash of configuration variables

  • quiet is a boolean; true if minimal output is requested by a user

  • backend_prefix - mapping of full backend names into short aliases

  • abbr_to_backend – reverse mapping of backend_prefix

  • backend_order - default order (kinda priority) of backends

  • active_backends_order

  • options - a hash of parsed command line options (see Getopt::Long). Must be set by a Configure script:

    GetOptions( $cfg->options, ... );
    

    Note that as it was already stated Options section, values in this hash are not to be changed unless absolutely, unavoidably necessary.

  • contexts - list of contexts

  • repo_maps

  • impls contains data structures related to backend implementations

  • backend_errors

  • expand_as_is - boolean; true if template must be expanded as-is, without adding informational comments

  • out_header

  • template is a file which is being expanded

  • out is a file where expanded output is send to

Use of the keys directly should be avoided as much as possible by external scripts and reduced to reasonable levels by child classes. Methods are always preferable.

METHODS

Class Level

new(%params)

Constructor

init(%params)

Initializer. Called by new. Can be overriden by a child class but must not be called manually.

Utility Methods

msg(@message)

Outputs a message to the console unless quiet attribute is true. Usually recommended over say or print unless note or sorry methods apply.

mute($on)

Sets quiet attribute-flag to $on or to a true value if used without an argument.

note($type, @message)

For cases where a notice must be output which is not a subject for quietness and requires user attention. $type is a short message explaining what type of notice we're printing. It's a free-form, but words like ATTENTION or 'WARNING' are recommended. A typical output would look like:

===ATTENTION===
  The information we want the user to see
  goes here and it is indented for clearer look.

sorry(@messages)

This method outputs a ===SORRY!=== message. For historical reasons it treats it's parameters differently. Where note considers them a single message, sorry expects a list of messages. Each will be output on a new lines with on common ===SORRY!=== prefix.

Usually, calling sorry causes a script to die unless ignore-errors option is set.

shell_cmd

Return current platform's shell. Basically, cmd for Win* and sh for others.

batch_file($file)

Takes a single parameter and forms a valid script name depending on the current platform. I.e. will append .bat on Win* if needed.

make_cmd

Determines what command is to be used as make depending on the current platform. Would mostly result in make, nmake on Win*, and may return gmake on BSD family.

options

Return options hash.

option($opt)

Returns a option $opt or undef if its doesn't exists.

has_option($opt)

Returns true if option $opt exists. It may not necessarily be defined though.

validate_backend($backend, $method)

Dies if $backend is not supported. Error message would inform method name if $method is defined.

Returns $backend

known_backends

Return a list of supported backends.

known_backend($backend)

Returns true if $backend is supported.

known_abbrs

Returns a list of short names of supported backends.

abbr_to_backend($backend_abbreviation)

Maps short backend name to its full form. Like "j" -> "jvm".

backend_abbr($backend)

Returns $backend short name.

backend_config($backend [, %config])

If supplied with key => value pairs (%config) then this method will store them in a backend-specific configuration hash. If a key already exists it will be overwritten.

Returns backend-specific configuration hash.

use_backend($backend)

Activates a $backend for build. This includes:

  • appending of the backend to the list of active ones. It means active_backends_order content depends in what order the backends were activated.
  • if no other backends were activated yet, the default_backend configuration variable is set to $backend

If the method is called for the second time with the same parameters it returns without any actions taken.

active_backends

Returns a list of activated backends.

active_backend($backend)

Returns true if $backend is activate.

active_abbrs

Returns a list of short names of active backends.

base_path($relative_path)

Takes a relative path and prepends it with base_dir. If the parameter happens to be an absolute path it is returned as is then.

configure_platform

The only method of configure_* family which is used by NQP::Config itself. It presets configuration values specific to the current platform.

configure_*

Methods from this family are to be used by a Configure.pl script to actually perform configuration tasks. Of those

  • configure_backends
  • configure_misc

are abstract and have to be implemented by child classes.

parse_backends($cli_backends)

Parses what is passed with --backends.

backend_error($backend, @msgs)

Stores error messages related to a $backend.

backend_errors($backend)

Returns a list or arrayref (context dependant) of stored errors for a $backend.

expand_template

Expands the default template (see attribute template). The result of expansion goes into file specified by out attribute. If out_header attribute is defined it's prepended to the expanded text.

See more details in macro expansion docs.

save_config_status

Creates config.status file in base_dir using content of @lclang@_config_status configuration variable.

opts_for_configure(@opts)

Generate command line options for subsequent Configure.pl calls based on the information collected so far; mostly on based upon user-specified command line options.

Returns list of options or space-concatenated string made of the list depending on the call context.

NOTE: Subsequent calls are the calls made after the main run which creates Makefile. They're made by the Makefile receipts and currently their sole purpose is to expand other templates the way they would be expanded by the main run but at the time of the build process.

make_option($opt[, no_quote => 1])

Generates a command line option for a subsequent call to a Configure.pl based on options provided by the user. The option value is shell-quoted unless no_quote parameter is true.

ignorable_opts

Returns a list of options to be ignored when building a command line for subsequent calls to Configure.pl.

A language-specific child class can override this method.

is_win, is_solaris, is_bsd, isa_unix

Shortcuts for checking what our platform is.

is_executable($file)

Returns true if $file is an executable.

github_url($protocol, $user, $repo)

Builds URL for a github repository based on requested protocol. The protocol could be either "git" or "https". $user is github's user account which owns the repository $repo.

repo_url($repo_alias[, %params])

Higher level github URL builder. $repo_alias is a key from repo_maps attribute: one of moar, nqp, rakudo, or roast values. The following keys can be used in %params:

  • actiongit action we're requesting the URL for. For now only push and pull are supported.
  • protocolgit protocol. See github_url

Note that for push action only git protocol is valid.

find_file_path($short_name, %params)

Finds a file defined $short_name in specified subdirectories. Returns file name with path if found or empty string otherwise.

%params can have the following keys:

  • where - which base directory we're lookin in. Currently it could be either templates or build. But any other word can be used as long as there is a configuration variable ${where}_dir.
  • subdir – single directory name to look in. Appended to $where directory.
  • subdirs - a list of directories.
  • subdirs_only – boolean. If true then file isn't searched in $where dir itself, only in subdirectories of it. For example, one can limit the search of a Makefile template by platform of backend directories avoiding the universal Makefile template.
  • suffix - suffix to be appended to $short_name.
  • suffixes - list of suffix'es. To look for a file without a suffix too this list must contain an empty string.
  • required - if its true then the method dies when no file is found.

Implicitly the routine is also using ctx_subdir configuration variable as a subdir. It can be set by iterators which create contexts to look in a context-specific location. For example, an iterator over active backends can set this variable on a per-context basis and execute a callback where a template is requested. The callback doesn't need to worry about where to look for its templates as this would be done automatically.

template_file_path($template, %params)

A shortcut to call:

$cfg->find_file_path(
    $template,
    where    => 'templates',
    suffixes => [ ".$platform", ".in", "" ],
    %params
);

build_file_path($file_name, %params)

A shortcut to call:

$cfg->find_file_path(
    $file_name,
    where    => 'build',
    suffixes => [ qw<.pl .nqp .p6>, "" ],
    %params
);

fill_template_file($infile, $outfile, %params)

Expand $infile into $outfile. $outfile could be a file name or an opened file handle. $infile could be a single template name or an arrayref of templates. If $infile is a list then all templates are expanded into a single $outfile.

For each template being expanded the method creates a context with template_file property and a configuration variable of the same name. Both are holding the template file path.

In the output result of each template file expansion is wrapped into a pair of:

# Generated from <template>_
<actual expanded text>
# (end of section generated from <template>)

commetns unless as_is key in %params is true.

The actual expansion is done by fill_template_text method.

fill_template_text($text, %params)

Expands $text by creating an instance of NQP::Macros class and calling its expand method on the text. Passes $self as the configuration object for the NQP::Macros instance.

If the expanded text contains "nqp::makefile" string then additionally passes it through fixup_makefile method.

Returns the expanded text.

fixup_makefile($text)

This method tries to prepend commands in Makefile receipts with time utility if makefile_timing configuration variable is true. Must be replaced with a dedicated macro.

git_checkout($repo, $dir, $branch)

Checkouts a repository specified by its short name $repo (see repo_maps attribute) into a directory $dir. By checkout we mean either clone or fetch, depending on the existence of $dir.

$branch defined what specific branch is requested if defined.

Method dies if git command fails.

contexts

Returns a list of context hashes. For the simplicity of searching, the list is returned in reverse order so that when searching for a property or a configuration variable iteration could be done in strait direction.

cur_ctx

Returns currently active context.

push_ctx($ctx)

Pushes a context hash to the list. Returns a scoping object which upon destruction will delete the context from the list. So, normally adding a context is:

foreach my $backend ( $self->active_backends ) {
    my $scoping = $self->push_ctx(
            {
                configs => [ { backend => $backend } ],
            }
    );

    ... # Do our work
}

As soon as a single loop iteration ends $scoping will go out of scope and will be destroyed effectively deactivating the context.

NOTE that strictly saying contexts are not a stack because it is possible for the scoping object to either be preserved and used outside of a scope or be deleted any time, even if other contexts were pushed later. So, the only reason to consider the list as a stack-like structure is the way we look for data in it.

pop_ctx

Deletes last pushed context. Usually is not needed.

push_config({ $config | %config })

Shortcut for pushing just a single configuration hash onto the context list. Parameters could be either a hashref or list of key => value pairs.

Returns a scoping object.

config(%params)

Returns a configuration hash. Depending on a parameter the hash could be:

  • the config attribute itself, no contexts added, no_ctx parameter is true.
  • otherwise it's a result of summing up the base configuration hash with all currently active contexts.

cfg($variable, %params)

Fetches a configuration variable. The variable is looked through contexts first then in the config attribute. If parameter strict is true and no variable is found then method dies.

Returns the value of the variable or undef if not found and strict is not set. In array context if with_ctx parameter is set will return a list of the value and the context hash where the variable was located.

set($variable, $value[, in_ctx => 1])

Set a configuration variable. If in_ctx parameter is set the variable will be set in the topmost context. Otherwise the value in the config attribute is changed.

prop($property[, strict => 1])

Looks for a $property in the contexts. If not found then tries the configuration object itself. If property is not found but strict is set then dies.

in_ctx($property, $value)

Locates the context where $property is defined and has value $value.

Returns the context hash.

shell_quote_filename($filename)

Quotes/escapes $filename in accordance to the current platform's rules.

nfp($filename)

The name stands for Normalize File Path. Takes a file path in Unix-like format and converts it to match the current platform rules. For example, for Windows it means replacing / directory seprators with \.

Returns normalized file name.

c_escape_string($string)

Escapes a string for use in C source code.

sq_escape_string($string)

Escapes a string for use in single quoted delimiters. E.g. a Perl '' string.

ROUTINES

slash

Returns platform-specific path separator.

slurp($file)

Returns $file content as a single line.

os2platform([$os])

Maps operation system to a family of platforms. For example, Windows and OS/2 would map into family windows.

See %os_platforms hash in the beginning of the module source.

rm_l

Similar to ExtUtils::Command rm_* exports. Deletes symlinks.

system_or_die(@cmd)

Tries to execute @cmd with system routine. Dies if exit code is not 0.

run_or_die($cmd, %params)

Intended as a replacement for qx{command}. Returns command output or dies if exit code is not 0.

If %params has an output_timeout key then the routine attempts to use IPC::Cmd run_forked if available and monitors the subcommand for produced output. If none is produced in more that output_timeout seconds the process gets terminated and die is invoked with an explanation. Additional parameters are used then:

  • description – a description for the command invoked
  • heartbeat – report description every hearbeat seconds to keep the user entertained
  • verbose – if true then command output is not hidden; heartbeat is ignored then

The rest of %params keys are passed through into run or run_forked as is.

parse_revision($rev)

Parses standard revisions of MoarVM, NQP, Rakudo.

Returns a list of revision components.

cmp_rev($rev_a, $rev_b)

Compares two revisions.

read_config(@sources)

Iterates over @sources, treats them as executables capable of --show-config command line option. Reads their output, parses and combines the result into a configuration hash which is then returned.

SEE ALSO