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 };