1 module mage.target;
2 
3 import pathlib;
4 
5 public __gshared ITarget[] targets;
6 
7 interface ITarget
8 {
9   string toString() const;
10   Path[] getSourceFiles();
11 }
12 
13 
14 mixin template TargetCommonMixin()
15 {
16   string name;
17   Path[] sourceFiles;
18 
19   this() {
20   }
21 
22   override string toString() const {
23     return name;
24   }
25 
26   override Path[] getSourceFiles() {
27     return sourceFiles;
28   }
29 }
30 
31 
32 // UDA
33 struct Target
34 {
35 }
36 
37 
38 class Executable : ITarget
39 {
40   mixin TargetCommonMixin;
41 }
42 
43 
44 enum LibraryType
45 {
46   Static,
47   Shared
48 }
49 
50 class Library : ITarget
51 {
52   mixin TargetCommonMixin;
53 
54   LibraryType libType = LibraryType.Static;
55 
56   this(LibraryType libType) {
57     this.libType = libType;
58   }
59 }
60 
61 
62 interface ITargetFactory
63 {
64   abstract @property Path filePath() const;
65   abstract ITarget create();
66 }
67 
68 __gshared ITargetFactory[] targetFactories;
69 
70 class TargetWrapper(TargetType) : ITargetFactory
71 {
72   import std.stdio;
73 private:
74   Path m_filePath;
75 
76 public:
77 
78   override @property Path filePath() const { return m_filePath; }
79 
80   alias WrappedType = TargetType;
81   
82   this(Path filePath) {
83     import std.conv : to;
84     m_filePath = filePath;
85   }
86 
87   override ITarget create() {
88     return new TargetType();
89   }
90 }
91 
92 mixin template registerMageFile(alias T, alias filePath) {
93   import mage.util.reflection;
94   shared static this() {
95     pragma(msg, "[mage] Reflecting module: " ~ T.stringof);
96     foreach(m; __traits(allMembers, T)) {
97       static if(!__traits(compiles, typeof(__traits(getMember, T, m)))) {
98         static if(__traits(compiles, ResolveType!(__traits(getMember, T, m)))) {
99           alias Type = ResolveType!(__traits(getMember, T, m));
100           static if(is(Type == class)) {
101             if(Type.stringof != "MageFileInstance") {
102               pragma(msg, "[mage]   Found a class: " ~ Type.stringof);
103               foreach(uda; __traits(getAttributes, Type)) {
104                 static if(is(uda == Target)) {
105                   pragma(msg, "[mage]     Found a target! " ~ uda.stringof);
106                   static if(!__traits(compiles, new Type())) {
107                     pragma(msg, "[mage] WARNING: Target is not instantiable with `new`.");
108                   }
109                   targetFactories ~= new TargetWrapper!Type(Path(filePath));
110                 }
111                 else {
112                   pragma(msg, "[mage]     Found some UDA: " ~ uda.stringof);
113                 }
114               }
115             }
116           }
117           else {
118             pragma(msg, "[mage]   Found something: " ~ Type.stringof);
119           }
120         }
121       }
122       else {
123         alias Type = typeof(__traits(getMember, T, m));
124         pragma(msg, "[mage]   Module member: " ~ Type.stringof);
125       }
126     }
127   }
128 }
129 
130 mixin template M_MageFileMixin()
131 {
132   class MageFileInstance{}
133 
134   // The parent of MageFileInstance is the module.
135   mixin registerMageFile!(__traits(parent, MageFileInstance), M_mageFilePath);
136 }