| /** | |
| * Configuration options for druntime | |
| * | |
| * Copyright: Copyright Digital Mars 2014. | |
| * License: Distributed under the | |
| * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). | |
| * (See accompanying file LICENSE) | |
| * Authors: Rainer Schuetze | |
| * Source: $(DRUNTIMESRC src/rt/_config.d) | |
| */ | |
| module rt.config; | |
| // The default way to configure the runtime is by passing command line arguments | |
| // starting with "--DRT-" and followed by the option name, e.g. "--DRT-gcopt" to | |
| // configure the GC. | |
| // Command line options starting with "--DRT-" are filtered out before calling main, | |
| // so the program will not see them. They are still available via rt_args(). | |
| // | |
| // Configuration via the command line can be disabled by declaring a variable for the | |
| // linker to pick up before using it's default from the runtime: | |
| // | |
| // extern(C) __gshared bool rt_cmdline_enabled = false; | |
| // | |
| // Likewise, declare a boolean rt_envvars_enabled to enable configuration via the | |
| // environment variable "DRT_" followed by the option name, e.g. "DRT_GCOPT": | |
| // | |
| // extern(C) __gshared bool rt_envvars_enabled = true; | |
| // | |
| // Setting default configuration properties in the executable can be done by specifying an | |
| // array of options named rt_options: | |
| // | |
| // extern(C) __gshared string[] rt_options = [ "gcopt=precise:1 profile:1"]; | |
| // | |
| // Evaluation order of options is rt_options, then environment variables, then command | |
| // line arguments, i.e. if command line arguments are not disabled, they can override | |
| // options specified through the environment or embedded in the executable. | |
| import core.demangle : cPrefix; | |
| // put each variable in its own COMDAT by making them template instances | |
| template rt_envvars_enabled() | |
| { | |
| pragma(mangle, cPrefix ~ "rt_envvars_enabled") __gshared bool rt_envvars_enabled = false; | |
| } | |
| template rt_cmdline_enabled() | |
| { | |
| pragma(mangle, cPrefix ~ "rt_cmdline_enabled") __gshared bool rt_cmdline_enabled = true; | |
| } | |
| template rt_options() | |
| { | |
| pragma(mangle, cPrefix ~ "rt_options") __gshared string[] rt_options = []; | |
| } | |
| import core.stdc.ctype : toupper; | |
| import core.stdc.stdlib : getenv; | |
| import core.stdc.string : strlen; | |
| extern extern(C) string[] rt_args() @nogc nothrow; | |
| alias rt_configCallBack = string delegate(string) @nogc nothrow; | |
| /** | |
| * get a druntime config option using standard configuration options | |
| * opt name of the option to retreive | |
| * dg if non-null, passes the option through this | |
| * delegate and only returns its return value if non-null | |
| * reverse reverse the default processing order cmdline/envvar/rt_options | |
| * to allow overwriting settings in the delegate with values | |
| * from higher priority | |
| * | |
| * returns the options' value if | |
| * - set on the command line as "--DRT-<opt>=value" (rt_cmdline_enabled enabled) | |
| * - the environment variable "DRT_<OPT>" is set (rt_envvars_enabled enabled) | |
| * - rt_options[] contains an entry "<opt>=value" | |
| * - null otherwise | |
| */ | |
| string rt_configOption(string opt, scope rt_configCallBack dg = null, bool reverse = false) @nogc nothrow | |
| { | |
| if (!dg) | |
| dg = (string s) => s; | |
| string s = (reverse ? rt_linkOption(opt, dg) : rt_cmdlineOption(opt, dg)); | |
| if (s != null) | |
| return s; | |
| s = rt_envvarsOption(opt, dg); | |
| if (s != null) | |
| return s; | |
| s = (reverse ? rt_cmdlineOption(opt, dg) : rt_linkOption(opt, dg)); | |
| return s; | |
| } | |
| string rt_cmdlineOption(string opt, scope rt_configCallBack dg) @nogc nothrow | |
| { | |
| if (rt_cmdline_enabled!()) | |
| { | |
| foreach (a; rt_args) | |
| { | |
| if (a.length >= opt.length + 7 && a[0..6] == "--DRT-" && | |
| a[6 .. 6 + opt.length] == opt && a[6 + opt.length] == '=') | |
| { | |
| string s = dg(a[7 + opt.length .. $]); | |
| if (s != null) | |
| return s; | |
| } | |
| } | |
| } | |
| return null; | |
| } | |
| string rt_envvarsOption(string opt, scope rt_configCallBack dg) @nogc nothrow | |
| { | |
| if (rt_envvars_enabled!()) | |
| { | |
| if (opt.length >= 32) | |
| assert(0); | |
| char[40] var = void; | |
| var[0 .. 4] = "DRT_"; | |
| foreach (i, c; opt) | |
| var[4 + i] = cast(char) toupper(c); | |
| var[4 + opt.length] = 0; | |
| auto p = getenv(var.ptr); | |
| if (p) | |
| { | |
| string s = dg(cast(string) p[0 .. strlen(p)]); | |
| if (s != null) | |
| return s; | |
| } | |
| } | |
| return null; | |
| } | |
| string rt_linkOption(string opt, scope rt_configCallBack dg) @nogc nothrow | |
| { | |
| foreach (a; rt_options!()) | |
| { | |
| if (a.length > opt.length && a[0..opt.length] == opt && a[opt.length] == '=') | |
| { | |
| string s = dg(a[opt.length + 1 .. $]); | |
| if (s != null) | |
| return s; | |
| } | |
| } | |
| return null; | |
| } |