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