81ddb832fd50ac67959ac8ad9d2e0c05c59f2d5c
[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 <crossplatform.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                   char * compiler = getenv("COMPILER");
263                   if(!compiler) compiler = "Default";
264                   settingsContainer.Load();
265                   //incref ideSettings;
266                   delete settingsContainer;
267
268       // TODO: Command line option to choose between the two
269       // or a command line option to not use global settings 
270       //defaultCompiler = MakeDefaultCompiler();
271                   defaultCompiler = ideSettings.GetCompilerConfig(compiler);
272       // possible TODO: use the workspace to select the active compiler
273       // TODO: option to specify compiler name when using global settings
274                }
275
276                if(optionsCompiler.makeCommand)
277                   defaultCompiler.makeCommand = optionsCompiler.makeCommand;
278                if(optionsCompiler.cppCommand)
279                   defaultCompiler.cppCommand = optionsCompiler.cppCommand;
280                if(optionsCompiler.ccCommand)
281                   defaultCompiler.ccCommand = optionsCompiler.ccCommand;
282                if(optionsCompiler.ecpCommand)
283                   defaultCompiler.ecpCommand = optionsCompiler.ecpCommand;
284                if(optionsCompiler.eccCommand)
285                   defaultCompiler.eccCommand = optionsCompiler.eccCommand;
286                if(optionsCompiler.ecsCommand)
287                   defaultCompiler.ecsCommand = optionsCompiler.ecsCommand;
288                if(optionsCompiler.earCommand)
289                   defaultCompiler.earCommand = optionsCompiler.earCommand;
290                // TODO: Pass/combine/override the include and library dirs
291                for(dir : optionsCompiler.includeDirs)
292                   defaultCompiler.includeDirs.Add(dir);
293                for(dir : optionsCompiler.libraryDirs)
294                   defaultCompiler.libraryDirs.Add(dir);
295                delete optionsCompiler;
296
297                project = LoadProject(epjPath);
298                if(project)
299                {
300                   ProjectConfig defaultConfig = null;
301                   if(configName)
302                   {
303                      valid = false;
304                      for(config : project.configurations)
305                      {
306                         if(!strcmpi(configName, config.name))
307                         {
308                            project.config = config;
309                            valid = true;
310                            break;
311                         }
312                      }
313                      if(!valid)
314                         printf($"Error: Project configuration (%s) was not found.\n", configName);
315                   }
316                   else
317                   {
318                      ProjectConfig releaseConfig = null;
319                      for(config : project.configurations)
320                      {
321                         if(!strcmpi(config.name, "Release"))
322                         {
323                            releaseConfig = config;
324                            break;
325                         }
326                      }
327                      if(!releaseConfig && project.configurations.count)
328                      {
329                         releaseConfig = project.configurations[0];
330                         printf($"Notice: Project configuration (%s) will be used.\n", releaseConfig.name);
331                      }
332
333                      if(releaseConfig)
334                      {
335                         project.config = releaseConfig;
336                         if(overrideObjDir)
337                         {
338                            delete releaseConfig.options.targetDirectory;
339                            releaseConfig.options.targetDirectory = CopyString(overrideObjDir);
340                            delete releaseConfig.options.objectsDirectory;
341                            releaseConfig.options.objectsDirectory = CopyString(overrideObjDir);
342                         }
343                         if(noWarnings)
344                            releaseConfig.options.warnings = none;
345                      }
346                      else if(overrideObjDir)
347                      {
348                         delete project.options.targetDirectory;
349                         project.options.targetDirectory = CopyString(overrideObjDir);
350                         delete project.options.objectsDirectory;
351                         project.options.objectsDirectory = CopyString(overrideObjDir);
352                      }
353                      if(noWarnings)
354                         project.options.warnings = none;
355                   }
356                   if(valid)
357                   {
358                      project.GenerateCompilerCf(defaultCompiler);
359                      project.GenerateCrossPlatformMk();
360                      if(project.GenerateMakefile(makePath, noResources, includemkPath, project.config))
361                      {
362                         if(makePath)
363                            printf("%s\n", makePath);
364                      }
365                   }
366
367                   if(noGlobalSettings)
368                      delete defaultCompiler;
369
370                   delete defaultConfig;
371                   delete project;
372                }
373                else
374                   printf($"Error: Unable to open project file (%s) due to unknown error.\n", epjPath);
375             }
376          }
377          else
378             printf($"Error: Input file (%s) does not exist.\n", epjPath);
379       }
380
381       //if(optionsCompiler) // how to fix those leaks?
382       delete optionsCompiler;
383
384       delete configName;
385       delete epjPath;
386       delete makePath;
387
388       // Why do we need to free this here?
389       delete defaultCompiler;
390
391       /*
392       for(c = 0; c<argc; c++)
393          delete argv[c];
394       delete argv;
395       */
396
397       // CheckMemory();
398       delete ideSettings;
399 #ifdef _DEBUG      
400       getch();
401 #endif
402    }
403 }