cleaned all trailing white space from source files.
[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] = '\0';
118                                  strcat(buffer, compilerName);
119                                  CamelCase(&buffer[d]);
120                                  d += strlen(compilerName);
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> compilerOptions;
263    Array<String> linkerOptions;
264    property Array<String> libraryDirs
265    {
266       set
267       {
268          if(libraryDirs)
269             libraryDirs.Free();
270          if(value && value.count)
271          {
272             if(!libraryDirs)
273                libraryDirs = { };
274             for(s : value)
275                libraryDirs.Add(CopyValidateMakefilePath(s));
276             value.Free(); // why do I have to do this here? it's a property, shouldn't json deal with this?
277             delete value;
278          }
279          else
280             delete libraryDirs;
281       }
282       get { return libraryDirs; }
283       isset { return  libraryDirs && libraryDirs.count; }
284    }
285    SetBool console;
286    SetBool compress;
287
288    // todo; move those to compiler/linker sections
289    SetBool excludeFromBuild;
290    BuildBitDepth buildBitDepth;
291    SetBool fastMath;
292
293    property Array<String> prebuildCommands
294    {
295       set
296       {
297          if(prebuildCommands)
298             prebuildCommands.Free();
299          if(value && value.count)
300          {
301             if(!prebuildCommands)
302                prebuildCommands = { };
303             for(s : value)
304                prebuildCommands.Add(CopyValidateMakefilePath(s));
305             value.Free();
306             delete value;
307          }
308          else
309             delete prebuildCommands;
310       }
311       get { return prebuildCommands; }
312       isset { return  prebuildCommands && prebuildCommands.count; }
313    }
314    property Array<String> postbuildCommands
315    {
316       set
317       {
318          if(postbuildCommands)
319             postbuildCommands.Free();
320          if(value && value.count)
321          {
322             if(!postbuildCommands)
323                postbuildCommands = { };
324             for(s : value)
325                postbuildCommands.Add(CopyValidateMakefilePath(s));
326             value.Free();
327             delete value;
328          }
329          else
330             delete postbuildCommands;
331       }
332       get { return postbuildCommands; }
333       isset { return  postbuildCommands && postbuildCommands.count; }
334    }
335    property Array<String> installCommands
336    {
337       set
338       {
339          if(installCommands)
340             installCommands.Free();
341          if(value && value.count)
342          {
343             if(!installCommands)
344                installCommands = { };
345             for(s : value)
346                installCommands.Add(CopyValidateMakefilePath(s));
347             value.Free();
348             delete value;
349          }
350          else
351             delete installCommands;
352       }
353       get { return installCommands; }
354       isset { return  installCommands && installCommands.count; }
355    }
356
357    ProjectOptions Copy()
358    {
359       // TODO: We'll want some solution so that we can use OnCopy for copying containers (Array<String>)
360       return
361       {
362          warnings = warnings,
363          debug = debug,
364          memoryGuard = memoryGuard,
365          profile = profile,
366          noLineNumbers = noLineNumbers;
367          optimization = optimization,
368          defaultNameSpace = CopyString(defaultNameSpace),
369          strictNameSpaces = strictNameSpaces,
370          targetType = targetType,
371          targetFileName = /*CopyString(*/targetFileName/*)*/,
372          targetDirectory = /*CopyString(*/targetDirectory/*)*/,
373          objectsDirectory = /*CopyString(*/objectsDirectory/*)*/,
374          console = console,
375          compress = compress,
376          excludeFromBuild = excludeFromBuild,
377          fastMath = fastMath,
378          preprocessorDefinitions = CopyArrayString(preprocessorDefinitions),
379          includeDirs = CopyArrayString(includeDirs),
380          libraries = CopyArrayString(libraries),
381          compilerOptions = CopyArrayString(compilerOptions),
382          linkerOptions = CopyArrayString(linkerOptions),
383          libraryDirs = CopyArrayString(libraryDirs),
384          prebuildCommands = CopyArrayString(prebuildCommands),
385          postbuildCommands = CopyArrayString(postbuildCommands),
386          installCommands = CopyArrayString(installCommands)
387       };
388    }
389
390 #ifdef _DEBUG
391    void print()
392    {
393       PrintLn("warnings:", warnings);
394       PrintLn("debug:", debug);
395       PrintLn("memoryGuard:", memoryGuard);
396       PrintLn("profile:", profile);
397       //PrintLn("noLineNumbers:", noLineNumbers);
398       PrintLn("optimization:", optimization);
399
400       //...
401       //PrintLn("dddddddd:", dddddddd);
402
403       PrintLn("fastMath:", fastMath);
404
405       PrintLn("preprocessorDefinitions:", preprocessorDefinitions);
406       PrintLn("compilerOptions:", compilerOptions);
407       PrintLn("linkerOptions:", linkerOptions);
408       PrintLn("includeDirs:", includeDirs);
409
410       //...
411       //PrintLn("dddddddd:", dddddddd);
412
413       PrintLn("");
414    }
415 #endif
416
417    ~ProjectOptions()
418    {
419       if(preprocessorDefinitions) { preprocessorDefinitions.Free(); delete preprocessorDefinitions; }
420       if(includeDirs) { includeDirs.Free(); delete includeDirs; }
421       delete defaultNameSpace;
422       delete targetFileName;
423       delete targetDirectory;
424       delete objectsDirectory;
425       if(libraries) { libraries.Free(); delete libraries; }
426       if(compilerOptions) { compilerOptions.Free(); delete compilerOptions; }
427       if(linkerOptions) { linkerOptions.Free(); delete linkerOptions; }
428       if(libraryDirs) { libraryDirs.Free(); delete libraryDirs; }
429       if(prebuildCommands) { prebuildCommands.Free(); delete prebuildCommands; }
430       if(postbuildCommands) { postbuildCommands.Free(); delete postbuildCommands; }
431       if(installCommands) { installCommands.Free(); delete installCommands; }
432    }
433 private:
434    Array<String> includeDirs;
435    String targetFileName;
436    String targetDirectory;
437    String objectsDirectory;
438    Array<String> libraryDirs;
439    Array<String> prebuildCommands;
440    Array<String> postbuildCommands;
441    Array<String> installCommands;
442
443    property bool isEmpty
444    {
445       get
446       {
447          if(warnings == unset &&
448             debug == unset &&
449             memoryGuard == unset &&
450             profile == unset &&
451             noLineNumbers == unset &&
452             optimization == unset &&
453             !preprocessorDefinitions &&
454             (!includeDirs || !includeDirs.count) &&
455             !defaultNameSpace &&
456             strictNameSpaces == unset &&
457             targetType == unset &&
458             !targetFileName &&
459             !targetDirectory &&
460             !objectsDirectory &&
461             !libraries &&
462             !compilerOptions &&
463             !linkerOptions &&
464             (!libraryDirs || !libraryDirs.count) &&
465             console == unset &&
466             compress == unset &&
467             excludeFromBuild == unset &&
468             fastMath == unset &&
469             (!prebuildCommands || !prebuildCommands.count) &&
470             (!postbuildCommands || !postbuildCommands.count) &&
471             (!installCommands || !installCommands.count))
472             return true;
473          return false;
474       }
475    }
476 }
477
478 public class PlatformOptions
479 {
480 public:
481    String name;
482    property ProjectOptions options { get { return options; } set { options = value; } isset { return options && !options.isEmpty; } }
483
484    ~PlatformOptions()
485    {
486       delete name;
487       delete options;
488    }
489
490    PlatformOptions Copy()
491    {
492       return
493       {
494          CopyString(name),
495          options ? options.Copy() : null
496       };
497    }
498 private:
499    ProjectOptions options;
500 }
501
502 class ProjectConfig : struct
503 {
504 public:
505    String name;
506    property ProjectOptions options { get { return options; } set { options = value; } isset { return options && !options.isEmpty; } }
507    property Array<PlatformOptions> platforms
508    {
509       get { return platforms; }
510       set
511       {
512          if(platforms) { platforms.Free(); delete platforms; }
513          if(value)
514          {
515             List<PlatformOptions> empty { };
516             Iterator<PlatformOptions> it { value };
517             platforms = value;
518             for(p : platforms; !p.options || p.options.isEmpty) empty.Add(p);
519             for(p : empty; it.Find(p)) platforms.Delete(it.pointer);
520             delete empty;
521          }
522       }
523       isset
524       {
525          if(platforms)
526          {
527             for(p : platforms)
528             {
529                if(p.options && !p.options.isEmpty)
530                   return true;
531             }
532          }
533          return false;
534       }
535    }
536
537 private:
538    ProjectOptions options;
539    bool makingModified;
540    bool compilingModified, linkingModified, symbolGenModified;
541    Array<PlatformOptions> platforms;
542
543    ~ProjectConfig()
544    {
545       // Configuration
546       delete name;
547       delete options;
548       if(platforms) { platforms.Free(); delete platforms; }
549    }
550
551    ProjectConfig Copy()
552    {
553       Array<PlatformOptions> platforms = null;
554       if(this.platforms)
555       {
556          platforms = { };
557          for(p : this.platforms)
558          {
559             platforms.Add(p.Copy());
560          }
561       }
562       return
563       {
564          CopyString(name),
565          options ? options.Copy() : null,
566          platforms
567       };
568    }
569 }