Initial git commit -- Transition from CodeGuard repository
[sdk] / ide / src / project / ProjectConfig.ec
1 #ifndef MAKEFILE_GENERATOR
2 import "ide"
3 #endif
4
5 import "Project"
6
7 enum DirExpressionType { unknown, targetDir, intermediateObjectsDir };  // "type" is not right
8
9 class DirExpression : struct
10 {
11    char * dir;
12    DirExpressionType type;
13
14    ~DirExpression()
15    {
16       delete dir;
17    }
18
19    property char * dir
20    {
21       get
22       {
23          return dir ? dir : "";
24       }
25       set
26       {
27          delete dir;
28          if(value && value[0])
29             dir = CopyString(value);
30          else
31             dir = CopyString("");
32       }
33    }
34
35    void Evaluate(char * expression, Project project)
36    {
37       int len;
38       char * expr = expression;
39       if(!expr || !expr[0])
40       {
41          char buffer[MAX_LOCATION];
42          if(ideSettings)
43          {
44          if(type == targetDir)
45             expr = ideSettings.projectDefaultTargetDir;
46          else if(type == intermediateObjectsDir)
47             expr = ideSettings.projectDefaultIntermediateObjDir;
48          }
49          if(!expr || !expr[0])
50             expr = defaultObjDirExpression;
51       }
52       if((len = strlen(expr)))
53       {
54          int c, d;
55          CompilerConfig compiler = GetCompilerConfig();
56          ProjectConfig config = project.config;
57          char * configName = config && config.name && config.name[0] ? config.name : "Common";
58          char * projectName = project.name ? project.name : "";
59          char * moduleName = project.moduleName ? project.moduleName : "";
60          char * compilingPlatformName = GetRuntimePlatform();
61          char * compilerName = (compiler && compiler.name) ? compiler.name : defaultCompilerName;
62          char * targetPlatformName = compiler && compiler.targetPlatform ? compiler.targetPlatform : "";
63          char buffer[MAX_LOCATION];
64          for(c = 0, d = 0; c < len; c++)
65          {
66             if(expr[c] == '$' && c < len - 1 && expr[c + 1] == '(')
67             {
68                int i;
69                for(i = c + 2; i < len; i++)
70                {
71                   if(expr[i] == ')')
72                   {
73                      int n = i - c - 2;
74                      if(n > 0)
75                      {
76                         if(!strnicmp(&expr[c + 2], "Config", n) || !strnicmp(&expr[c + 2], "Config", n))
77                         {
78                            buffer[d] = '\0';
79                            strcat(buffer, configName);
80                            CamelCase(&buffer[d]);
81                            d += strlen(configName);
82                            c = i;
83                         }
84                         else if(!strnicmp(&expr[c + 2], "Module", n) || !strnicmp(&expr[c + 2], "Project", n))
85                         {
86                            buffer[d] = '\0';
87                            strcat(buffer, moduleName);
88                            //CamelCase(&buffer[d]);
89                            d += strlen(moduleName);
90                            c = i;
91                         }
92                         else if(!strnicmp(&expr[c + 2], "Platform", n))
93                         {
94                            buffer[d] = '\0';
95                            strcat(buffer, targetPlatformName);
96                            CamelCase(&buffer[d]);
97                            d += strlen(targetPlatformName);
98                            /*if(strcmpi(targetPlatformName, compilingPlatformName))
99                            {
100                               strcat(buffer, "~");
101                               d++;
102                               strcat(buffer, compilingPlatformName);
103                               d += strlen(compilingPlatformName);
104                            }*/
105                            c = i;
106                         }
107                         else if(!strnicmp(&expr[c + 2], "Compiler", n))
108                         {
109                            buffer[d] = '\0';
110                            strcat(buffer, compilerName);
111                            CamelCase(&buffer[d]);
112                            d += strlen(compilerName);
113                            c = i;
114                         }
115                         else
116                         {
117                            buffer[d++] = expr[c];
118                         }
119                      }
120                      else
121                      {
122                         buffer[d++] = expr[c];
123                      }
124                      i = len - 1;
125                      break;
126                   }
127                   else if(expr[i] == '\\' || expr[i] == '/')
128                   {
129                      buffer[d++] = '\0';
130                      strncat(buffer, &expr[i], i - c);
131                      d += i - c;
132                      c = i;
133                      i = len - 1;
134                      break;
135                   }
136                }
137                if(i == len)
138                   buffer[d++] = expr[c];
139             }
140             else
141             {
142                buffer[d++] = expr[c];
143             }
144          }
145          buffer[d] = '\0';
146          if(dir && strcmp(buffer, dir))
147             delete dir;
148          if(!dir)
149             dir = CopyString(buffer);
150          delete compiler;
151       }
152       else
153       {
154          delete dir;
155          dir = CopyString("");
156       }
157    }
158 }
159
160 public enum TargetTypes { unset, executable, sharedLibrary, staticLibrary };
161 public enum OptimizationStrategy { unset, none, speed, size };
162 public enum WarningsOption { unset, normal, none, all }; // TOCHECK: More options?
163
164 Array<String> CopyArrayString(Array<String> array)
165 {
166    Array<String> copy = null;
167    if(array)
168    {
169       copy = { };
170       for(s : array) copy.Add(CopyString(s));
171    }
172    return copy;
173 }
174
175 public class ProjectOptions
176 {
177 public:
178    // Compiler Options
179    property SetBool allWarnings
180    {
181       set
182       {
183          if(value == true)
184             warnings = all;
185       }
186    }
187    WarningsOption warnings;
188    SetBool debug;
189    SetBool memoryGuard;
190    SetBool profile;
191    SetBool noLineNumbers;
192    OptimizationStrategy optimization;
193    Array<String> preprocessorDefinitions;
194    property Array<String> includeDirs
195    {
196       set
197       {
198          if(includeDirs)
199             includeDirs.Free();
200          if(value && value.count)
201          {
202             if(!includeDirs)
203                includeDirs = { };
204             for(s : value)
205                includeDirs.Add(CopyValidateMakefilePath(s));
206             value.Free();
207             delete value;
208          }
209          else
210             delete includeDirs;
211       }
212       get { return includeDirs; }
213       isset { return  includeDirs && includeDirs.count; }
214    }
215    String defaultNameSpace;
216    SetBool strictNameSpaces;
217
218    // Linker Options
219    TargetTypes targetType;
220    property char * targetFileName
221    {
222       set { delete targetFileName; if(value && value[0]) targetFileName = CopyValidateMakefilePath(value); }
223       get { return targetFileName; }
224       isset { return targetFileName && targetFileName[0]; }
225    }
226    property char * targetDirectory
227    {
228       set { delete targetDirectory; if(value /*&& value[0]*/) targetDirectory = CopyValidateMakefilePath(value); }
229       get { return targetDirectory; }
230       isset { return targetDirectory != null/*&& targetDirectory[0]*/; }
231    }
232    property char * objectsDirectory
233    {
234       set { delete objectsDirectory; if(value /*&& value[0]*/) objectsDirectory = CopyValidateMakefilePath(value); }
235       get { return objectsDirectory; }
236       isset { return objectsDirectory != null/*&& objectsDirectory[0]*/; }
237    }
238    Array<String> libraries;
239    Array<String> linkerOptions;
240    property Array<String> libraryDirs
241    {
242       set
243       {
244          if(libraryDirs)
245             libraryDirs.Free();
246          if(value && value.count)
247          {
248             if(!libraryDirs)
249                libraryDirs = { };
250             for(s : value)
251                libraryDirs.Add(CopyValidateMakefilePath(s));
252             value.Free(); // why do I have to do this here? it's a property, shouldn't json deal with this?
253             delete value;
254          }
255          else
256             delete libraryDirs;
257       }
258       get { return libraryDirs; }
259       isset { return  libraryDirs && libraryDirs.count; }
260    }
261    SetBool console;
262    SetBool compress;
263
264    SetBool excludeFromBuild;
265
266    property Array<String> prebuildCommands
267    {
268       set
269       {
270          if(prebuildCommands)
271             prebuildCommands.Free();
272          if(value && value.count)
273          {
274             if(!prebuildCommands)
275                prebuildCommands = { };
276             for(s : value)
277                prebuildCommands.Add(CopyValidateMakefilePath(s));
278             value.Free();
279             delete value;
280          }
281          else
282             delete prebuildCommands;
283       }
284       get { return prebuildCommands; }
285       isset { return  prebuildCommands && prebuildCommands.count; }
286    }
287    property Array<String> postbuildCommands
288    {
289       set
290       {
291          if(postbuildCommands)
292             postbuildCommands.Free();
293          if(value && value.count)
294          {
295             if(!postbuildCommands)
296                postbuildCommands = { };
297             for(s : value)
298                postbuildCommands.Add(CopyValidateMakefilePath(s));
299             value.Free();
300             delete value;
301          }
302          else
303             delete postbuildCommands;
304       }
305       get { return postbuildCommands; }
306       isset { return  postbuildCommands && postbuildCommands.count; }
307    }
308
309    ProjectOptions Copy()
310    {
311       // TODO: We'll want some solution so that we can use OnCopy for copying containers (Array<String>)
312       return
313       {
314          warnings = warnings,
315          debug = debug,
316          memoryGuard = memoryGuard,
317          profile = profile,
318          noLineNumbers = noLineNumbers;
319          optimization = optimization,
320          defaultNameSpace = CopyString(defaultNameSpace),
321          strictNameSpaces = strictNameSpaces,
322          targetType = targetType,
323          targetFileName = CopyString(targetFileName),
324          targetDirectory = CopyString(targetDirectory),
325          objectsDirectory = CopyString(objectsDirectory),
326          console = console,
327          compress = compress,
328          excludeFromBuild = excludeFromBuild,
329          preprocessorDefinitions = CopyArrayString(preprocessorDefinitions),
330          includeDirs = CopyArrayString(includeDirs),
331          libraries = CopyArrayString(libraries),
332          linkerOptions = CopyArrayString(linkerOptions),
333          libraryDirs = CopyArrayString(libraryDirs),
334          prebuildCommands = CopyArrayString(prebuildCommands),
335          postbuildCommands = CopyArrayString(postbuildCommands)
336       };
337    }
338
339    ~ProjectOptions()
340    {
341       if(preprocessorDefinitions) { preprocessorDefinitions.Free(); delete preprocessorDefinitions; }
342       if(includeDirs) { includeDirs.Free(); delete includeDirs; }
343       delete defaultNameSpace;
344       delete targetFileName;
345       delete targetDirectory;
346       delete objectsDirectory;
347       if(libraries) { libraries.Free(); delete libraries; }
348       if(linkerOptions) { linkerOptions.Free(); delete linkerOptions; }
349       if(libraryDirs) { libraryDirs.Free(); delete libraryDirs; }
350       if(prebuildCommands) { prebuildCommands.Free(); delete prebuildCommands; }
351       if(postbuildCommands) { postbuildCommands.Free(); delete postbuildCommands; }
352    }
353 private:
354    Array<String> includeDirs;
355    String targetFileName;
356    String targetDirectory;
357    String objectsDirectory;
358    Array<String> libraryDirs;
359    Array<String> prebuildCommands;
360    Array<String> postbuildCommands;
361
362    property bool isEmpty
363    {
364       get
365       {
366          if(warnings == unset &&
367             debug == unset &&
368             memoryGuard == unset &&
369             profile == unset &&
370             noLineNumbers == unset &&
371             optimization == unset &&
372             !preprocessorDefinitions &&
373             !includeDirs &&
374             !defaultNameSpace &&
375             strictNameSpaces == unset &&
376             targetType == unset &&
377             !targetFileName &&
378             !targetDirectory &&
379             !objectsDirectory &&
380             !libraries &&
381             !linkerOptions &&
382             !libraryDirs &&
383             console == unset &&
384             compress == unset &&
385             excludeFromBuild == unset &&
386             !prebuildCommands &&
387             !postbuildCommands)
388             return true;
389          return false;          
390       }
391    }
392 }
393
394 public class PlatformOptions
395 {
396 public:
397    String name;
398    ProjectOptions options;
399
400    ~PlatformOptions()
401    {
402       delete name;
403       delete options;
404    }
405
406    PlatformOptions Copy()
407    {
408       return
409       {
410          CopyString(name),
411          options ? options.Copy() : null
412       };
413    }
414 }
415
416 class ProjectConfig : struct
417 {
418 public:
419    String name;
420    ProjectOptions options;
421    Array<PlatformOptions> platforms;
422
423 private:
424
425    bool makingModified;
426    bool compilingModified, linkingModified, symbolGenModified;
427
428    ~ProjectConfig()
429    {
430       // Configuration
431       delete name;
432       delete options;
433       if(platforms) { platforms.Free(); delete platforms; }
434    }
435
436    ProjectConfig Copy()
437    {
438       Array<PlatformOptions> platforms = null;
439       if(this.platforms)
440       {
441          platforms = { };
442          for(p : this.platforms)
443          {
444             platforms.Add(p.Copy());
445          }
446       }
447       return
448       {
449          CopyString(name),
450          options ? options.Copy() : null,
451          platforms
452       };
453    }
454 }