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