ecere/gui/Window: Prevent uninitialized values if base Window methods not overridden...
[sdk] / epj2make / epj2make.ec
1 #ifdef ECERE_STATIC
2 public import static "ecere"
3 #else
4 public import "ecere"
5 #endif
6
7 import "Project"
8
9 #if defined(__WIN32__)
10 define pathListSep = ";";
11 #else
12 define pathListSep = ":";
13 #endif
14
15 #if defined(_DEBUG) && defined(__WIN32__)
16 extern int getch(void);
17 #endif
18
19 IDESettings ideSettings;
20
21 IDESettingsContainer settingsContainer
22 {
23    dataOwner = &ideSettings;
24    dataClass = class(IDESettings);
25 };
26
27 IDEConfigHolder ideConfig { };
28
29 void ParseDirList(char * string, Container<String> list)
30 {
31    int c;
32    char * tokens[256];
33    int numTokens = TokenizeWith(string, sizeof(tokens) / sizeof(byte *), tokens, ";", false);
34    list.Free();
35    for(c = 0; c < numTokens; c++)
36       list.Add(CopyString(tokens[c]));
37 }
38
39 // NOTE: FileMonitors are not to be used by an Application class. globalSystem is not set up properly otherwise.
40 // Mantis ticket #545 was filed regarding this.
41 class epj2makeApp : GuiApplication
42 {
43    void Main()
44    {
45       int c;
46       bool valid = true;
47       char * configName = null;
48       char * epjPath = null;
49       char * makePath = null;
50       /*
51       char ** argv = null;
52       int argc = 0;
53       */
54
55       Project project = null;
56
57       CompilerConfig optionsCompiler { };
58
59       bool noGlobalSettings = false;
60       bool noResources = false;
61       bool noWarnings = false;
62       const char * overrideObjDir = null;
63       const char * includemkPath = null;
64
65       /*
66       for(c = 0; c < this.argc; c++)
67       {
68          char * arg = this.argv[c];
69          int argLen = strlen(arg);
70
71          argv = renew argv char *[argc + 1];
72          argv[argc] = new char[argLen + 1];
73          strcpy(argv[argc], arg);
74
75          while(argv[argc][argLen - 1] == '\\' && c < this.argc-1)
76          {
77             int len;
78
79             c++;
80             arg = this.argv[c];
81             len = strlen(arg);
82             argv[argc] = renew argv[argc] char[argLen + len + 1];
83
84             argv[argc][argLen - 1] = ' ';
85             strcpy(argv[argc] + argLen, arg);
86             argLen += len;
87          }
88          argc++;
89       }
90       */
91
92       for(c = 1; c < argc; c++)
93       {
94          const char * arg = argv[c];
95          if(arg[0] == '-')
96          {
97             if(!strcmpi(arg+1, "make"))
98             {
99                if(++c < argc)
100                   optionsCompiler.makeCommand = argv[c];
101                else
102                   valid = false;
103             }
104             else if(!strcmpi(arg+1, "cpp"))
105             {
106                if(++c < argc)
107                   optionsCompiler.cppCommand = argv[c];
108                else
109                   valid = false;
110             }
111             else if(!strcmpi(arg+1, "cc"))
112             {
113                if(++c < argc)
114                   optionsCompiler.ccCommand = argv[c];
115                else
116                   valid = false;
117             }
118             else if(!strcmpi(arg+1, "ecp"))
119             {
120                if(++c < argc)
121                   optionsCompiler.ecpCommand = argv[c];
122                else
123                   valid = false;
124             }
125             else if(!strcmpi(arg+1, "ecc"))
126             {
127                if(++c < argc)
128                   optionsCompiler.eccCommand = argv[c];
129                else
130                   valid = false;
131             }
132             else if(!strcmpi(arg+1, "ecs"))
133             {
134                if(++c < argc)
135                   optionsCompiler.ecsCommand = argv[c];
136                else
137                   valid = false;
138             }
139             else if(!strcmpi(arg+1, "ear"))
140             {
141                if(++c < argc)
142                   optionsCompiler.earCommand = argv[c];
143                else
144                   valid = false;
145             }
146             else if(!strcmpi(arg+1, "noglobalsettings"))
147             {
148                noGlobalSettings = true;
149             }
150             else if(!strcmpi(arg+1, "noresources"))
151             {
152                noResources = true;
153             }
154             else if(!strcmpi(arg+1, "includemk"))
155             {
156                if(++c < argc)
157                   includemkPath = argv[c];
158                else
159                   valid = false;
160             }
161             else if(arg[1] == 'w' && !arg[2])
162             {
163                noWarnings = true;
164             }
165             else if(arg[1] == 'c' && !arg[2])
166             {
167                if(++c < argc)
168                {
169                   int argLen = strlen(argv[c]);
170                   configName = new char[argLen + 1];
171                   strcpy(configName, argv[c]);
172                }
173                else
174                   valid = false;
175             }
176             else if(arg[1] == 't' && !arg[2])
177             {
178                // Obsolete target platform option
179                if(++c < argc);
180                else
181                   valid = false;
182             }
183             else if(arg[1] == 'o')
184             {
185                if(++c < argc)
186                {
187                   int argLen = strlen(argv[c]);
188                   makePath = new char[argLen + 1];
189                   strcpy(makePath, argv[c]);
190                }
191                else
192                   valid = false;
193             }
194             else if(arg[1] == 'i')
195             {
196                if(++c < argc)
197                   ParseDirList((char *)argv[c], optionsCompiler.includeDirs);
198                else
199                   valid = false;
200             }
201             else if(arg[1] == 'l')
202             {
203                if(++c < argc)
204                   ParseDirList((char *)argv[c], optionsCompiler.libraryDirs);
205                else
206                   valid = false;
207             }
208             else if(arg[1] == 'd' && !arg[2])
209             {
210                if(++c < argc)
211                   overrideObjDir = argv[c];
212                else
213                   valid = false;
214             }
215             else
216             {
217                valid = false;
218                printf($"invalid option: %s\n", arg);
219             }
220          }
221          else
222          {
223             if(!epjPath)
224             {
225                int argLen = strlen(arg);
226                epjPath = new char[argLen + 1];
227                strcpy(epjPath, arg);
228                c++;
229             }
230             else
231                valid = false;
232          }
233       }
234       if(!epjPath)
235          valid = false;
236
237       if(!valid)
238       {
239          printf("%s", $"Syntax:\n");
240          printf("%s", $"   epj2make [-t <target platform>] [-c <configuration>] [toolchain] [directories] [options] [-o <output>] <input>\n");
241          printf("%s", $"      toolchain:\n");
242          printf("%s", $"         [-make <make tool>]\n");
243          printf("%s", $"         [-cpp <c preprocessor>]\n");
244          printf("%s", $"         [-cc <c compiler>]\n");
245          printf("%s", $"         [-ecp <eC preprocessor>]\n");
246          printf("%s", $"         [-ecc <eC compiler>]\n");
247          printf("%s", $"         [-ecs <eC symbol generator>]\n");
248          printf("%s", $"         [-ear <Ecere Archiver>]\n");
249          printf("%s", $"      directories:\n");
250          printf("%s", $"         [-i <include dir[;inc dir[...]]>]\n");
251          printf("%s", $"         [-l <library dir[;lib dir[...]]>]\n");
252          printf("%s", $"      options:\n");
253          printf("%s", $"         [-noglobalsettings]\n");
254          printf("%s", $"         [-noresources]\n");
255          printf("%s", $"         [-d <intermediate objects directory>]\n");
256          printf("%s", $"         [-includemk <crossplatform.mk path>]\n");
257       }
258       else
259       {
260          if(FileExists(epjPath).isFile)
261          {
262             char extension[MAX_EXTENSION] = "";
263             GetExtension(epjPath, extension);
264             strlwr(extension);
265             if(!strcmp(extension, ProjectExtension))
266             {
267                if(noGlobalSettings)
268                {
269                   defaultCompiler = MakeDefaultCompiler("Default", true);
270                   delete ideSettings;
271                }
272                else
273                {
274                   const char * compiler = getenv("COMPILER");
275                   if(!compiler) compiler = "Default";
276                   settingsContainer.Load();
277                   ideConfig.compilers.read(settingsContainer);
278
279                   //incref ideSettings;
280                   delete settingsContainer;
281
282       // TODO: Command line option to choose between the two
283       // or a command line option to not use global settings
284       //defaultCompiler = MakeDefaultCompiler();
285                   defaultCompiler = ideConfig.compilers.GetCompilerConfig(compiler);
286       // possible TODO: use the workspace to select the active compiler
287       // TODO: option to specify compiler name when using global settings
288                }
289
290                if(optionsCompiler.makeCommand)
291                   defaultCompiler.makeCommand = optionsCompiler.makeCommand;
292                if(optionsCompiler.cppCommand)
293                   defaultCompiler.cppCommand = optionsCompiler.cppCommand;
294                if(optionsCompiler.ccCommand)
295                   defaultCompiler.ccCommand = optionsCompiler.ccCommand;
296                if(optionsCompiler.ecpCommand)
297                   defaultCompiler.ecpCommand = optionsCompiler.ecpCommand;
298                if(optionsCompiler.eccCommand)
299                   defaultCompiler.eccCommand = optionsCompiler.eccCommand;
300                if(optionsCompiler.ecsCommand)
301                   defaultCompiler.ecsCommand = optionsCompiler.ecsCommand;
302                if(optionsCompiler.earCommand)
303                   defaultCompiler.earCommand = optionsCompiler.earCommand;
304                // TODO: Pass/combine/override the include and library dirs
305                for(dir : optionsCompiler.includeDirs)
306                   defaultCompiler.includeDirs.Add(dir);
307                for(dir : optionsCompiler.libraryDirs)
308                   defaultCompiler.libraryDirs.Add(dir);
309                delete optionsCompiler;
310
311                project = LoadProject(epjPath, null);
312                if(project)
313                {
314                   ProjectConfig defaultConfig = null;
315                   if(configName)
316                   {
317                      valid = false;
318                      for(config : project.configurations)
319                      {
320                         if(!strcmpi(configName, config.name))
321                         {
322                            project.config = config;
323                            valid = true;
324                            break;
325                         }
326                      }
327                      if(!valid)
328                         printf($"Error: Project configuration (%s) was not found.\n", configName);
329                   }
330                   else
331                   {
332                      ProjectConfig releaseConfig = null;
333                      for(config : project.configurations)
334                      {
335                         if(!strcmpi(config.name, "Release"))
336                         {
337                            releaseConfig = config;
338                            break;
339                         }
340                      }
341                      if(!releaseConfig && project.configurations.count)
342                      {
343                         releaseConfig = project.configurations[0];
344                         printf($"Notice: Project configuration (%s) will be used.\n", releaseConfig.name);
345                      }
346
347                      if(releaseConfig)
348                      {
349                         project.config = releaseConfig;
350                         if(overrideObjDir)
351                         {
352                            delete releaseConfig.options.targetDirectory;
353                            releaseConfig.options.targetDirectory = CopyString(overrideObjDir);
354                            delete releaseConfig.options.objectsDirectory;
355                            releaseConfig.options.objectsDirectory = CopyString(overrideObjDir);
356                         }
357                         if(noWarnings)
358                            releaseConfig.options.warnings = none;
359                      }
360                      else if(overrideObjDir)
361                      {
362                         delete project.options.targetDirectory;
363                         project.options.targetDirectory = CopyString(overrideObjDir);
364                         delete project.options.objectsDirectory;
365                         project.options.objectsDirectory = CopyString(overrideObjDir);
366                      }
367                      if(noWarnings)
368                         project.options.warnings = none;
369                   }
370                   if(valid)
371                   {
372                      project.GenerateCompilerCf(defaultCompiler, project.topNode.ContainsFilesWithExtension("ec", project.config));
373                      project.GenerateCrossPlatformMk(null);
374                      if(project.GenerateMakefile(makePath, noResources, includemkPath, project.config))
375                      {
376                         if(makePath)
377                            printf("%s\n", makePath);
378                      }
379                   }
380
381                   if(noGlobalSettings)
382                      delete defaultCompiler;
383
384                   delete defaultConfig;
385                   delete project;
386                }
387                else
388                   printf($"Error: Unable to open project file (%s) due to unknown error.\n", epjPath);
389             }
390          }
391          else
392             printf($"Error: Input file (%s) does not exist.\n", epjPath);
393       }
394
395       //if(optionsCompiler) // how to fix those leaks?
396       delete optionsCompiler;
397
398       delete configName;
399       delete epjPath;
400       delete makePath;
401
402       // Why do we need to free this here?
403       delete defaultCompiler;
404
405       /*
406       for(c = 0; c<argc; c++)
407          delete argv[c];
408       delete argv;
409       */
410
411       // CheckMemory();
412       delete ideSettings;
413 #if defined(_DEBUG) && defined(__WIN32__)
414       getch();
415 #endif
416    }
417 }