1 /** 2 * Configuration options for druntime 3 * 4 * Copyright: Copyright Digital Mars 2014. 5 * License: Distributed under the 6 * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). 7 * (See accompanying file LICENSE) 8 * Authors: Rainer Schuetze 9 * Source: $(DRUNTIMESRC src/rt/_config.d) 10 */ 11 12 module rt.config; 13 14 // The default way to configure the runtime is by passing command line arguments 15 // starting with "--DRT-" and followed by the option name, e.g. "--DRT-gcopt" to 16 // configure the GC. 17 // Command line options starting with "--DRT-" are filtered out before calling main, 18 // so the program will not see them. They are still available via rt_args(). 19 // 20 // Configuration via the command line can be disabled by declaring a variable for the 21 // linker to pick up before using it's default from the runtime: 22 // 23 // extern(C) __gshared bool rt_cmdline_enabled = false; 24 // 25 // Likewise, declare a boolean rt_envvars_enabled to enable configuration via the 26 // environment variable "DRT_" followed by the option name, e.g. "DRT_GCOPT": 27 // 28 // extern(C) __gshared bool rt_envvars_enabled = true; 29 // 30 // Setting default configuration properties in the executable can be done by specifying an 31 // array of options named rt_options: 32 // 33 // extern(C) __gshared string[] rt_options = [ "gcopt=precise:1 profile:1"]; 34 // 35 // Evaluation order of options is rt_options, then environment variables, then command 36 // line arguments, i.e. if command line arguments are not disabled, they can override 37 // options specified through the environment or embedded in the executable. 38 39 import core.demangle : cPrefix; 40 41 // put each variable in its own COMDAT by making them template instances 42 template rt_envvars_enabled() 43 { 44 pragma(mangle, cPrefix ~ "rt_envvars_enabled") __gshared bool rt_envvars_enabled = false; 45 } 46 template rt_cmdline_enabled() 47 { 48 pragma(mangle, cPrefix ~ "rt_cmdline_enabled") __gshared bool rt_cmdline_enabled = true; 49 } 50 template rt_options() 51 { 52 pragma(mangle, cPrefix ~ "rt_options") __gshared string[] rt_options = []; 53 } 54 55 import core.stdc.ctype : toupper; 56 import core.stdc.stdlib : getenv; 57 import core.stdc.string : strlen; 58 59 extern extern(C) string[] rt_args() @nogc nothrow; 60 61 alias rt_configCallBack = string delegate(string) @nogc nothrow; 62 63 /** 64 * get a druntime config option using standard configuration options 65 * opt name of the option to retreive 66 * dg if non-null, passes the option through this 67 * delegate and only returns its return value if non-null 68 * reverse reverse the default processing order cmdline/envvar/rt_options 69 * to allow overwriting settings in the delegate with values 70 * from higher priority 71 * 72 * returns the options' value if 73 * - set on the command line as "--DRT-<opt>=value" (rt_cmdline_enabled enabled) 74 * - the environment variable "DRT_<OPT>" is set (rt_envvars_enabled enabled) 75 * - rt_options[] contains an entry "<opt>=value" 76 * - null otherwise 77 */ 78 string rt_configOption(string opt, scope rt_configCallBack dg = null, bool reverse = false) @nogc nothrow 79 { 80 if (!dg) 81 dg = (string s) => s; 82 83 string s = (reverse ? rt_linkOption(opt, dg) : rt_cmdlineOption(opt, dg)); 84 if (s != null) 85 return s; 86 s = rt_envvarsOption(opt, dg); 87 if (s != null) 88 return s; 89 s = (reverse ? rt_cmdlineOption(opt, dg) : rt_linkOption(opt, dg)); 90 return s; 91 } 92 93 string rt_cmdlineOption(string opt, scope rt_configCallBack dg) @nogc nothrow 94 { 95 if (rt_cmdline_enabled!()) 96 { 97 foreach (a; rt_args) 98 { 99 if (a.length >= opt.length + 7 && a[0..6] == "--DRT-" && 100 a[6 .. 6 + opt.length] == opt && a[6 + opt.length] == '=') 101 { 102 string s = dg(a[7 + opt.length .. $]); 103 if (s != null) 104 return s; 105 } 106 } 107 } 108 return null; 109 } 110 111 string rt_envvarsOption(string opt, scope rt_configCallBack dg) @nogc nothrow 112 { 113 if (rt_envvars_enabled!()) 114 { 115 if (opt.length >= 32) 116 assert(0); 117 118 char[40] var = void; 119 var[0 .. 4] = "DRT_"; 120 foreach (i, c; opt) 121 var[4 + i] = cast(char) toupper(c); 122 var[4 + opt.length] = 0; 123 124 auto p = getenv(var.ptr); 125 if (p) 126 { 127 string s = dg(cast(string) p[0 .. strlen(p)]); 128 if (s != null) 129 return s; 130 } 131 } 132 return null; 133 } 134 135 string rt_linkOption(string opt, scope rt_configCallBack dg) @nogc nothrow 136 { 137 foreach (a; rt_options!()) 138 { 139 if (a.length > opt.length && a[0..opt.length] == opt && a[opt.length] == '=') 140 { 141 string s = dg(a[opt.length + 1 .. $]); 142 if (s != null) 143 return s; 144 } 145 } 146 return null; 147 } 148