ide/buildsystem; default/32/64 bit dropbox. removed old 32/64 bit stuff from compiler...
[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, CompilerConfig compiler, ProjectConfig config, int bitDepth)
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          char * configName = config && config.name && config.name[0] ? config.name : "Common";
56          char * projectName = project.name ? project.name : "";
57          char * moduleName = project.moduleName ? project.moduleName : "";
58          char * compilerName = (compiler && compiler.name) ? compiler.name : defaultCompilerName;
59          char * targetPlatformName = compiler && compiler.targetPlatform ? compiler.targetPlatform : "";
60          char buffer[MAX_LOCATION];
61          for(c = 0, d = 0; c < len; c++)
62          {
63             if(expr[c] == '$' && c < len - 1 && expr[c + 1] == '(')
64             {
65                int i;
66                for(i = c + 2; i < len; i++)
67                {
68                   if(expr[i] == ')')
69                   {
70                      int n = i - c - 2;
71                      if(n > 0)
72                      {
73                         if(!strnicmp(&expr[c + 2], "Config", n) || !strnicmp(&expr[c + 2], "Config", n))
74                         {
75                            buffer[d] = '\0';
76                            strcat(buffer, configName);
77                            CamelCase(&buffer[d]);
78                            d += strlen(configName);
79                            c = i;
80                         }
81                         else if(!strnicmp(&expr[c + 2], "Module", n) || !strnicmp(&expr[c + 2], "Project", n))
82                         {
83                            buffer[d] = '\0';
84                            strcat(buffer, moduleName);
85                            //CamelCase(&buffer[d]);
86                            d += strlen(moduleName);
87                            c = i;
88                         }
89                         else if(!strnicmp(&expr[c + 2], "Platform", n))
90                         {
91                            buffer[d] = '\0';
92                            strcat(buffer, targetPlatformName);
93                            CamelCase(&buffer[d]);
94                            d += strlen(targetPlatformName);
95                            c = i;
96                         }
97                         else if(!strnicmp(&expr[c + 2], "Compiler", n))
98                         {
99                            buffer[d] = '\0';
100                            strcat(buffer, compilerName);
101                            CamelCase(&buffer[d]);
102                            d += strlen(compilerName);
103                            c = i;
104                         }
105                         else if(!strnicmp(&expr[c + 2], "Debug_Suffix", n))
106                         {
107                            // We don't support .debug from the IDE yet...
108                            c = i;
109                         }
110                         else if(!strnicmp(&expr[c + 2], "Compiler_Suffix", n))
111                         {
112                            if(bitDepth || (compilerName[0] && strcmpi(compilerName, "default")))
113                            {
114                               if(compilerName[0] && strcmpi(compilerName, "default"))
115                               {
116                                  buffer[d] = '.';
117                                  buffer[d+1] = '\0';
118                                  strcat(buffer, compilerName);
119                                  CamelCase(&buffer[d]);
120                                  d += strlen(compilerName)+1;
121                               }
122                               if(bitDepth == 32)
123                               {
124                                  strcat(buffer, ".x32");
125                                  d += 4;
126                               }
127                               else if(bitDepth == 64)
128                               {
129                                  strcat(buffer, ".x64");
130                                  d += 4;
131                               }
132                            }
133                            c = i;
134                         }
135                         else
136                         {
137                            buffer[d++] = expr[c];
138                         }
139                      }
140                      else
141                      {
142                         buffer[d++] = expr[c];
143                      }
144                      i = len - 1;
145                      break;
146                   }
147                   else if(expr[i] == '\\' || expr[i] == '/')
148                   {
149                      buffer[d++] = '\0';
150                      strncat(buffer, &expr[i], i - c);
151                      d += i - c;
152                      c = i;
153                      i = len - 1;
154                      break;
155                   }
156                }
157                if(i == len)
158                   buffer[d++] = expr[c];
159             }
160             else
161             {
162                buffer[d++] = expr[c];
163             }
164          }
165          buffer[d] = '\0';
166          if(dir && strcmp(buffer, dir))
167             delete dir;
168          if(!dir)
169             dir = CopyString(buffer);
170       }
171       else
172       {
173          delete dir;
174          dir = CopyString("");
175       }
176    }
177 }
178
179 public enum TargetTypes { unset, executable, sharedLibrary, staticLibrary };
180 public enum OptimizationStrategy { unset, none, speed, size };
181 public enum WarningsOption { unset, normal, none, all }; // TOCHECK: More options?
182 public enum BuildBitDepth { all, bits32, bits64 };
183
184 Array<String> CopyArrayString(Array<String> array)
185 {
186    Array<String> copy = null;
187    if(array)
188    {
189       copy = { };
190       for(s : array) copy.Add(CopyString(s));
191    }
192    return copy;
193 }
194
195 public class ProjectOptions
196 {
197 public:
198    // Compiler Options
199    property SetBool allWarnings
200    {
201       set
202       {
203          if(value == true)
204             warnings = all;
205       }
206    }
207    WarningsOption warnings;
208    SetBool debug;
209    SetBool memoryGuard;
210    SetBool profile;
211    SetBool noLineNumbers;
212    OptimizationStrategy optimization;
213    Array<String> preprocessorDefinitions;
214    property Array<String> includeDirs
215    {
216       set
217       {
218          if(includeDirs)
219             includeDirs.Free();
220          if(value && value.count)
221          {
222             if(!includeDirs)
223                includeDirs = { };
224             for(s : value)
225                includeDirs.Add(CopyValidateMakefilePath(s));
226             value.Free();
227             delete value;
228          }
229          else
230             delete includeDirs;
231       }
232       get { return includeDirs; }
233       isset { return  includeDirs && includeDirs.count; }
234    }
235    String defaultNameSpace;
236    SetBool strictNameSpaces;
237
238    // Linker Options
239    TargetTypes targetType;
240    // NOTE: The JSON Parser deletes strings after setting a String property, so we do a copy here.
241    //       (This behavior is different from Objects (class instances) values which are not deleted)
242    //       Code calling these properties should *NOT* use CopyString().
243    property char * targetFileName
244    {
245       set { delete targetFileName; if(value && value[0]) targetFileName = CopyValidateMakefilePath(value); }
246       get { return targetFileName; }
247       isset { return targetFileName && targetFileName[0]; }
248    }
249    property char * targetDirectory
250    {
251       set { delete targetDirectory; if(value /*&& value[0]*/) targetDirectory = CopyValidateMakefilePath(value); }
252       get { return targetDirectory; }
253       isset { return targetDirectory != null/*&& targetDirectory[0]*/; }
254    }
255    property char * objectsDirectory
256    {
257       set { delete objectsDirectory; if(value /*&& value[0]*/) objectsDirectory = CopyValidateMakefilePath(value); }
258       get { return objectsDirectory; }
259       isset { return objectsDirectory != null/*&& objectsDirectory[0]*/; }
260    }
261    Array<String> libraries;
262    Array<String> linkerOptions;
263    property Array<String> libraryDirs
264    {
265       set
266       {
267          if(libraryDirs)
268             libraryDirs.Free();
269          if(value && value.count)
270          {
271             if(!libraryDirs)
272                libraryDirs = { };
273             for(s : value)
274                libraryDirs.Add(CopyValidateMakefilePath(s));
275             value.Free(); // why do I have to do this here? it's a property, shouldn't json deal with this?
276             delete value;
277          }
278          else
279             delete libraryDirs;
280       }
281       get { return libraryDirs; }
282       isset { return  libraryDirs && libraryDirs.count; }
283    }
284    SetBool console;
285    SetBool compress;
286
287    // todo; move those to compiler/linker sections
288    SetBool excludeFromBuild;
289    BuildBitDepth buildBitDepth;
290    SetBool fastMath;
291
292    property Array<String> prebuildCommands
293    {
294       set
295       {
296          if(prebuildCommands)
297             prebuildCommands.Free();
298          if(value && value.count)
299          {
300             if(!prebuildCommands)
301                prebuildCommands = { };
302             for(s : value)
303                prebuildCommands.Add(CopyValidateMakefilePath(s));
304             value.Free();
305             delete value;
306          }
307          else
308             delete prebuildCommands;
309       }
310       get { return prebuildCommands; }
311       isset { return  prebuildCommands && prebuildCommands.count; }
312    }
313    property Array<String> postbuildCommands
314    {
315       set
316       {
317          if(postbuildCommands)
318             postbuildCommands.Free();
319          if(value && value.count)
320          {
321             if(!postbuildCommands)
322                postbuildCommands = { };
323             for(s : value)
324                postbuildCommands.Add(CopyValidateMakefilePath(s));
325             value.Free();
326             delete value;
327          }
328          else
329             delete postbuildCommands;
330       }
331       get { return postbuildCommands; }
332       isset { return  postbuildCommands && postbuildCommands.count; }
333    }
334
335    ProjectOptions Copy()
336    {
337       // TODO: We'll want some solution so that we can use OnCopy for copying containers (Array<String>)
338       return
339       {
340          warnings = warnings,
341          debug = debug,
342          memoryGuard = memoryGuard,
343          profile = profile,
344          noLineNumbers = noLineNumbers;
345          optimization = optimization,
346          defaultNameSpace = CopyString(defaultNameSpace),
347          strictNameSpaces = strictNameSpaces,
348          targetType = targetType,
349          targetFileName = /*CopyString(*/targetFileName/*)*/,
350          targetDirectory = /*CopyString(*/targetDirectory/*)*/,
351          objectsDirectory = /*CopyString(*/objectsDirectory/*)*/,
352          console = console,
353          compress = compress,
354          excludeFromBuild = excludeFromBuild,
355          fastMath = fastMath,
356          preprocessorDefinitions = CopyArrayString(preprocessorDefinitions),
357          includeDirs = CopyArrayString(includeDirs),
358          libraries = CopyArrayString(libraries),
359          linkerOptions = CopyArrayString(linkerOptions),
360          libraryDirs = CopyArrayString(libraryDirs),
361          prebuildCommands = CopyArrayString(prebuildCommands),
362          postbuildCommands = CopyArrayString(postbuildCommands)
363       };
364    }
365
366 #ifdef _DEBUG
367    void print()
368    {
369       PrintLn("warnings:", warnings);
370       PrintLn("debug:", debug);
371       PrintLn("memoryGuard:", memoryGuard);
372       PrintLn("profile:", profile);
373       //PrintLn("noLineNumbers:", noLineNumbers);
374       PrintLn("optimization:", optimization);
375
376       //...
377       //PrintLn("dddddddd:", dddddddd);
378
379       PrintLn("fastMath:", fastMath);
380
381       PrintLn("preprocessorDefinitions:", preprocessorDefinitions);
382       PrintLn("includeDirs:", includeDirs);
383
384       //...
385       //PrintLn("dddddddd:", dddddddd);
386
387       PrintLn("");
388    }
389 #endif
390
391    ~ProjectOptions()
392    {
393       if(preprocessorDefinitions) { preprocessorDefinitions.Free(); delete preprocessorDefinitions; }
394       if(includeDirs) { includeDirs.Free(); delete includeDirs; }
395       delete defaultNameSpace;
396       delete targetFileName;
397       delete targetDirectory;
398       delete objectsDirectory;
399       if(libraries) { libraries.Free(); delete libraries; }
400       if(linkerOptions) { linkerOptions.Free(); delete linkerOptions; }
401       if(libraryDirs) { libraryDirs.Free(); delete libraryDirs; }
402       if(prebuildCommands) { prebuildCommands.Free(); delete prebuildCommands; }
403       if(postbuildCommands) { postbuildCommands.Free(); delete postbuildCommands; }
404    }
405 private:
406    Array<String> includeDirs;
407    String targetFileName;
408    String targetDirectory;
409    String objectsDirectory;
410    Array<String> libraryDirs;
411    Array<String> prebuildCommands;
412    Array<String> postbuildCommands;
413
414    property bool isEmpty
415    {
416       get
417       {
418          if(warnings == unset &&
419             debug == unset &&
420             memoryGuard == unset &&
421             profile == unset &&
422             noLineNumbers == unset &&
423             optimization == unset &&
424             !preprocessorDefinitions &&
425             (!includeDirs || !includeDirs.count) &&
426             !defaultNameSpace &&
427             strictNameSpaces == unset &&
428             targetType == unset &&
429             !targetFileName &&
430             !targetDirectory &&
431             !objectsDirectory &&
432             !libraries &&
433             !linkerOptions &&
434             (!libraryDirs || !libraryDirs.count) &&
435             console == unset &&
436             compress == unset &&
437             excludeFromBuild == unset &&
438             fastMath == unset &&
439             (!prebuildCommands || !prebuildCommands.count) &&
440             (!postbuildCommands || !postbuildCommands.count) )
441             return true;
442          return false;          
443       }
444    }
445 }
446
447 public class PlatformOptions
448 {
449 public:
450    String name;
451    property ProjectOptions options { get { return options; } set { options = value; } isset { return options && !options.isEmpty; } }
452
453    ~PlatformOptions()
454    {
455       delete name;
456       delete options;
457    }
458
459    PlatformOptions Copy()
460    {
461       return
462       {
463          CopyString(name),
464          options ? options.Copy() : null
465       };
466    }
467 private:
468    ProjectOptions options;
469 }
470
471 class ProjectConfig : struct
472 {
473 public:
474    String name;
475    property ProjectOptions options { get { return options; } set { options = value; } isset { return options && !options.isEmpty; } }
476    property Array<PlatformOptions> platforms
477    {
478       get { return platforms; }
479       set
480       {
481          if(platforms) { platforms.Free(); delete platforms; }
482          if(value)
483          {
484             List<PlatformOptions> empty { };
485             Iterator<PlatformOptions> it { value };
486             platforms = value;
487             for(p : platforms; !p.options || p.options.isEmpty) empty.Add(p);
488             for(p : empty; it.Find(p)) platforms.Delete(it.pointer);
489             delete empty;
490          }
491       }
492       isset
493       {
494          if(platforms)
495          {
496             for(p : platforms)
497             {
498                if(p.options && !p.options.isEmpty)
499                   return true;
500             }
501          }
502          return false;
503       }
504    }
505
506 private:
507    ProjectOptions options;
508    bool makingModified;
509    bool compilingModified, linkingModified, symbolGenModified;
510    Array<PlatformOptions> platforms;
511
512    ~ProjectConfig()
513    {
514       // Configuration
515       delete name;
516       delete options;
517       if(platforms) { platforms.Free(); delete platforms; }
518    }
519
520    ProjectConfig Copy()
521    {
522       Array<PlatformOptions> platforms = null;
523       if(this.platforms)
524       {
525          platforms = { };
526          for(p : this.platforms)
527          {
528             platforms.Add(p.Copy());
529          }
530       }
531       return
532       {
533          CopyString(name),
534          options ? options.Copy() : null,
535          platforms
536       };
537    }
538 }