1 /** 2 Copyright 2018 Mark Fisher 3 4 Permission is hereby granted, free of charge, to any person obtaining a copy of 5 this software and associated documentation files (the "Software"), to deal in 6 the Software without restriction, including without limitation the rights to 7 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 8 of the Software, and to permit persons to whom the Software is furnished to do 9 so, subject to the following conditions: 10 11 The above copyright notice and this permission notice shall be included in all 12 copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 SOFTWARE. 21 **/ 22 module dxx.constants; 23 24 private import core.runtime; 25 private import core.cpuid; 26 private import core.thread : ThreadID; 27 28 private import std.compiler; 29 private import std.file; 30 private import std.path; 31 private import std..string : split,indexOf,strip; 32 private import std.array : appender,join; 33 private import std.algorithm.searching : countUntil; 34 private import std.process : thisProcessID,thisThreadID; 35 36 private import semver; 37 38 private import dxx.packageVersion; 39 40 /** 41 * Constants that represt the platform configuration. 42 * The class Constants constains enums or aliases, 43 * whereas RTConstants contains static strings. 44 **/ 45 class Constants { 46 //enum { 47 // COMPILER_VERSION = std.compiler.name, 48 // PALTFORM = _PLATFORM, 49 // //CPU = core.cpuid.getCpuFeatures.vendorID 50 //} 51 enum compilerName = __VENDOR__; 52 enum compilerVersionMajor = version_major; 53 enum compilerVersionMinor = version_minor; 54 55 enum compileTimestamp = __TIMESTAMP__; 56 57 enum libVersion = packageVersion; 58 enum libVersionRange = "~>"~(packageVersion[1..$].split("-")[0]); 59 enum libTimestamp = packageTimestamp; 60 enum libTimestampISO = packageTimestampISO; 61 62 //enum cpuID = core.cpuid.getCpuFeatures.vendorID; 63 alias cpuCores = core.cpuid.coresPerCPU; 64 alias cpuThreads = core.cpuid.threadsPerCPU; 65 //alias cpuID = core.cpuid.getCpuFeatures.vendorID; 66 67 alias processID = thisProcessID; 68 alias threadID = thisThreadID; 69 70 version (OSX) { enum hostOperatingSystem = "OSX"; } 71 else version(MacOS) { enum hostOperatingSystem = "MacOS"; } 72 else version (linux) { enum hostOperatingSystem = "linux"; } 73 else version(Windows) { enum hostOperatingSystem = "Windows"; } 74 else version (FreeBSD) { enum hostOperatingSystem = "FreeBSD"; } 75 else version (NetBSD) { enum hostOperatingSystem = "NetBSD"; } 76 else version (DragonFlyBSD) { enum hostOperatingSystem = "DragonFlyBSD"; } 77 else version (Solaris) { enum hostOperatingSystem = "Solaris"; } 78 else version(Posix) { enum hostOperatingSystem = "Posix"; } 79 else { enum hostOperatingSystem = "<unknown-OS>"; } 80 81 version(Windows) { 82 enum Windows = true; 83 enum Posix = false; 84 } else version(Posix) { 85 enum Windows = false; 86 enum Posix = true; 87 } else { 88 enum Windows = false; 89 enum Posix = false; 90 } 91 92 version(unittest) { enum unitTest = true; } 93 else { enum unitTest = false; } 94 95 debug { 96 enum buildType = "Debug"; 97 } else version(Release) { 98 enum buildType = "Release"; 99 } else { 100 enum buildType = "<unknown-buildtype>"; 101 } 102 103 version(DXX_Module) { 104 enum dxxModule = true; 105 version(Windows) { 106 import core.sys.windows.windows; 107 template exePath() { 108 auto exePath() { 109 char[512] szModule; 110 GetModuleFileNameA(null, szModule.ptr, szModule.length); 111 return szModule.dup; 112 } 113 alias exePath = szModule; 114 } 115 } else { 116 alias exePath = thisExePath; 117 } 118 } else { 119 enum dxxModule = false; 120 alias exePath = thisExePath; 121 } 122 123 //template libSemVer() { 124 // auto libSemVer = SemVer(packageVersion); 125 //} 126 }; 127 128 alias runtimeConstants = RTConstants.runtimeConstants; 129 130 struct RTConstants { 131 const(string) libVersion = Constants.libVersion; 132 const(string) libTimestamp = Constants.libTimestamp; 133 const(string) libTimestampISO = Constants.libTimestampISO; 134 const(string) libVersionRange = Constants.libVersionRange; 135 136 const(string) compilerName = Constants.compilerName; 137 const(uint) compilerVersionMajor = Constants.compilerVersionMajor; 138 const(uint) compilerVersionMinor = Constants.compilerVersionMinor; 139 140 const(string) compileTimestamp = Constants.compileTimestamp; 141 142 const(string) hostOperatingSystem = Constants.hostOperatingSystem; 143 144 const(bool) unitTest = Constants.unitTest; 145 const(string) buildType = Constants.buildType; 146 147 const(bool) dxxModule = Constants.dxxModule; 148 149 const(string) appFileName; 150 const(string) appDir; 151 const(string) curDir; 152 const(string) appBaseName; 153 const(string) argString; 154 const(string)[] args; 155 const(string)[] argsApp; 156 const(string)[] argsAppPassthrough; 157 const(int) processID; 158 const(ThreadID) threadID; 159 160 shared static this() { 161 runtimeConstants.appFileName = thisExePath; 162 runtimeConstants.appDir = dirName(runtimeConstants.appFileName); 163 runtimeConstants.curDir = getcwd; 164 runtimeConstants.argString = Runtime.args.join(" "); 165 runtimeConstants.args = Runtime.args.dup; 166 auto inx = runtimeConstants.args.countUntil("--"); 167 if(inx!=-1) { 168 //auto argSplit = runtimeConstants.args.split("--"); 169 //runtimeConstants.argsApp = argSplit[0]; 170 //runtimeConstants.argsAppPassthrough = runtimeConstants.argString. 171 //auto i = runtimeConstants.argString.indexOf("--"); 172 //auto a = runtimeConstants.argString[0..i]; 173 //auto b = runtimeConstants.argString[i+2..$].strip; 174 175 runtimeConstants.argsApp = runtimeConstants.args[0..inx]; 176 runtimeConstants.argsAppPassthrough = runtimeConstants.args[inx+1..$]; 177 } else { 178 runtimeConstants.argsApp = runtimeConstants.args; 179 runtimeConstants.argsAppPassthrough = []; 180 } 181 182 version(Windows) { 183 version(DXX_Module) { 184 runtimeConstants.appBaseName = baseName(runtimeConstants.appFileName,".dll"); 185 } else { 186 runtimeConstants.appBaseName = baseName(runtimeConstants.appFileName,".exe"); 187 } 188 } else { 189 runtimeConstants.appBaseName = baseName(runtimeConstants.appFileName); 190 } 191 runtimeConstants.processID = thisProcessID; 192 } 193 194 static this() { 195 runtimeConstants.threadID = thisThreadID; 196 } 197 198 // the following variables may be filled in by the application... 199 200 /* string userAppVersion; // user-defined app version string. 201 string appName; // user-defined app name. 202 string orgName; // user-defined org name. 203 204 shared void registerAppVersion(vers)() { 205 userAppVersion = vers; 206 } 207 208 shared void registerAppVars(T)() { 209 orgName = T.organizationName; 210 appName = T.applicationName; 211 } */ 212 213 static __gshared shared(RTConstants) runtimeConstants; 214 215 alias constants = runtimeConstants; 216 217 unittest { 218 assert(runtimeConstants.unitTest); 219 debug { 220 assert(runtimeConstants.buildType == "Debug"); 221 } else version(Release) { 222 assert(runtimeConstants.buildType == "Release"); 223 } else { 224 assert(runtimeConstants.buildType == "<unknown-buildtype>"); 225 } 226 version(DXX_Module) { 227 assert(runtimeConstants.dxxModule); 228 } else { 229 assert(runtimeConstants.dxxModule == false); 230 } 231 } 232 233 const shared inout ref 234 auto libVersions() { 235 auto r = SemVerRange(libVersionRange); 236 assert(r.isValid); 237 return r; 238 } 239 const shared inout ref 240 auto semVer() { 241 return SemVer(libVersion); 242 } 243 const shared inout 244 bool checkVersion(SemVer v) { 245 assert(v.isValid); 246 return v.satisfies(libVersions); 247 } 248 };