only bring in as many sdl things as are strictly necessary
[tangerine.git] / tools / MetaMake / project.c
blob0d214f79e25acd343610ba65e118992976a981a6
1 /* MetaMake - A Make extension
2 Copyright © 1995-2008, The AROS Development Team. All rights reserved.
4 This file is part of MetaMake.
6 MetaMake is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 MetaMake is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 //#define DEBUG_PROJECT
23 #include "config.h"
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #ifdef HAVE_STRING_H
29 # include <string.h>
30 #else
31 # include <strings.h>
32 #endif
34 #include "project.h"
35 #include "var.h"
36 #include "mem.h"
37 #include "dep.h"
38 #include "mmake.h"
40 #if defined(DEBUG_PROJECT)
41 #define debug(a) a
42 #else
43 #define debug(v)
44 #endif
46 extern char *mm_srcdir;
47 extern char *mm_builddir;
49 List projects;
50 static Project * defaultprj = NULL;
52 static void
53 readvars (Project * prj)
55 List deps;
56 Node * node, * next;
57 Dep * dep;
59 debug(printf("MMAKE:project.c->readvars(Project @ %x)\n", prj));
61 if (!prj->readvars)
62 return;
64 prj->readvars = 0;
66 printf ("Read vars...\n");
68 setvar (&prj->vars, "TOP", prj->buildtop);
69 setvar (&prj->vars, "SRCDIR", prj->srctop);
70 setvar (&prj->vars, "CURDIR", "");
72 if (prj->globalvarfile)
74 char * fn;
75 FILE * fh;
76 char line[256];
77 char * name, * value, * ptr;
79 fn = xstrdup (substvars (&prj->vars, prj->globalvarfile));
80 fh = fopen (fn, "r");
82 if (!fh && prj->genglobalvarfile)
84 char * gen = xstrdup (substvars (&prj->vars, prj->genglobalvarfile));
86 printf ("Generating %s...\n", fn);
88 if (!execute (prj, gen, "-", "-", ""))
90 error ("Error while creating \"%s\" with \"%s\"", fn, gen);
91 exit (10);
93 else
94 fh = fopen (fn, "r");
96 xfree (gen);
99 if (!fh)
101 error ("readvars():fopen(): Opening \"%s\" for reading", fn);
102 return;
105 xfree (fn);
107 while (fgets (line, sizeof(line), fh))
109 if (*line == '\n' || *line == '#') continue;
110 line[strlen(line)-1] = 0;
112 ptr = line;
113 while (isspace (*ptr)) ptr++;
114 name = ptr;
115 while (*ptr && !isspace(*ptr) && *ptr != ':' && *ptr != '=')
116 ptr ++;
118 if (*ptr)
119 *ptr++ = 0;
121 while (isspace(*ptr) || *ptr == ':' || *ptr == '=')
122 ptr ++;
124 value = ptr;
126 while (*ptr && *ptr != '#')
127 ptr ++;
129 *ptr = 0;
131 if (debug)
132 printf ("%s=%s\n", name, substvars (&prj->vars, value));
134 setvar (&prj->vars, name, substvars (&prj->vars, value));
137 fclose (fh);
140 NewList(&deps);
141 ForeachNodeSafe (&prj->genmakefiledeps, node, next)
143 Remove (node);
144 AddTail (&deps, node);
147 ForeachNodeSafe (&deps, node, next)
149 Remove (node);
150 dep = newdepnode (substvars (&prj->vars, node->name));
151 AddTail (&prj->genmakefiledeps, dep);
152 xfree (node->name);
153 xfree (node);
156 if (debug)
158 printf ("project %s.genmfdeps=\n", prj->node.name);
159 printlist (&prj->genmakefiledeps);
162 if (debug)
164 printf ("project %s.vars=", prj->node.name);
165 printvarlist (&prj->vars);
169 static Project *
170 initproject (char * name)
172 Project * prj = new (Project);
174 memset (prj, 0, sizeof(Project));
176 debug(printf("MMAKE:project.c->initproject('%s')\n", name));
177 debug(printf("MMAKE:project.c->initproject: Project node @ %x\n", prj));
179 if (!defaultprj)
181 prj->maketool = xstrdup ("make \"TOP=$(TOP)\" \"SRCDIR=$(SRCDIR)\" \"CURDIR=$(CURDIR)\"");
182 prj->defaultmakefilename = xstrdup ("Makefile");
183 prj->srctop = mm_srcdir;
184 prj->buildtop = mm_builddir;
185 prj->defaulttarget = xstrdup ("all");
186 prj->genmakefilescript = NULL;
187 prj->globalvarfile = NULL;
188 prj->genglobalvarfile = NULL;
190 else
192 prj->maketool = xstrdup (defaultprj->maketool);
193 prj->defaultmakefilename = xstrdup (defaultprj->defaultmakefilename);
194 prj->srctop = xstrdup (defaultprj->srctop);
195 prj->buildtop = xstrdup (defaultprj->buildtop);
196 prj->defaulttarget = xstrdup (defaultprj->defaulttarget);
197 SETSTR (prj->genmakefilescript, defaultprj->genmakefilescript);
198 SETSTR (prj->globalvarfile, defaultprj->globalvarfile);
199 SETSTR (prj->genglobalvarfile, defaultprj->genglobalvarfile);
202 prj->node.name = xstrdup (name);
204 prj->readvars = 1;
206 NewList(&prj->genmakefiledeps);
207 NewList(&prj->ignoredirs);
208 NewList(&prj->vars);
209 NewList(&prj->extramakefiles);
211 return prj;
214 static void
215 freeproject (Project * prj)
217 assert (prj);
219 cfree (prj->node.name);
220 cfree (prj->maketool);
221 cfree (prj->defaultmakefilename);
222 if (prj->srctop != mm_srcdir)
223 cfree (prj->srctop);
224 if (prj->buildtop != mm_builddir)
225 cfree (prj->buildtop);
226 cfree (prj->defaulttarget);
227 cfree (prj->genmakefilescript);
228 cfree (prj->globalvarfile);
229 cfree (prj->genglobalvarfile);
231 if (prj->cache)
232 closecache (prj->cache);
234 freelist (&prj->genmakefiledeps);
235 freelist (&prj->ignoredirs);
236 freevarlist (&prj->vars);
237 freelist (&prj->extramakefiles);
239 xfree (prj);
242 static void
243 callmake (Project * prj, const char * tname, Makefile * makefile)
245 static char buffer[4096];
246 const char * path = buildpath (makefile->dir);
247 int t;
249 debug(printf("MMAKE:project.c->callmake()\n"));
251 if (makefile->generated)
252 chdir (prj->buildtop);
253 else
254 chdir (prj->srctop);
255 chdir (path);
257 setvar (&prj->vars, "CURDIR", path);
258 setvar (&prj->vars, "TARGET", tname);
260 strcpy (buffer, "");
262 for (t=0; t<mflagc; t++)
264 strcat (buffer, mflags[t]);
265 strcat (buffer, " ");
268 if (strcmp (makefile->node.name, "Makefile")!=0 && strcmp (makefile->node.name, "makefile")!=0);
270 strcat (buffer, "--file=");
271 strcat (buffer, makefile->node.name);
272 strcat (buffer, " ");
275 strcat (buffer, tname);
277 printf ("Making %s in %s\n", tname, path);
279 if (!execute (prj, prj->maketool, "-", "-", buffer))
281 error ("Error while running make in %s", path);
282 exit (10);
287 void
288 initprojects (void)
290 char * optionfile;
291 char * home;
292 char line[256];
293 FILE * optfh = NULL;
294 Project * project;
296 debug(printf("MMAKE:project.c->initprojects()\n"));
298 NewList(&projects);
299 defaultprj = project = initproject ("default");
300 AddTail(&projects, project);
303 /* Try "$MMAKE_CONFIG" */
304 if ((optionfile = getenv ("MMAKE_CONFIG")))
305 optfh = fopen (optionfile, "r");
307 /* Try "$HOME/.mmake.config" */
308 if (!optfh)
310 if ((home = getenv("HOME")))
312 optionfile = xmalloc (strlen(home) + sizeof("/.mmake.config") + 1);
313 sprintf (optionfile, "%s/.mmake.config", home);
314 optfh = fopen (optionfile, "r");
315 free (optionfile);
319 /* Try with $CWD/.mmake.config" */
320 if (!optfh)
321 optfh = fopen (".mmake.config", "r");
323 /* Try with "$CWD/mmake.config */
324 if (!optfh)
325 optfh = fopen ("mmake.config", "r");
327 /* Give up */
328 if (!optfh)
330 fprintf (stderr,
331 "Please set the HOME or MMAKE_CONFIG env var (with setenv or export)\n"
333 error ("Opening mmake.config for reading");
334 exit (10);
337 while (fgets (line, sizeof(line), optfh))
339 if (*line == '\n' || *line == '#') continue;
340 line[strlen(line)-1] = 0;
342 if (*line == '[')
344 char * name, * ptr;
346 name = ptr = line+1;
347 while (*ptr && *ptr != ']')
348 ptr ++;
350 *ptr = 0;
352 debug(printf("MMAKE:project.c->initprojects: Adding '%s' from MMAKE_CONFIG\n", name));
354 project = initproject (name);
356 AddTail(&projects,project);
358 else
360 char * cmd, * args, * ptr;
362 cmd = line;
363 while (isspace (*cmd))
364 cmd ++;
366 args = cmd;
367 while (*args && !isspace(*args))
369 *args = tolower (*args);
370 args ++;
372 if (*args)
373 *args++ = 0;
374 while (isspace (*args))
375 args ++;
377 ptr = args;
379 while (*ptr && *ptr != '\n')
380 ptr ++;
382 *ptr = 0;
384 if (!strcmp (cmd, "add"))
386 Node * n;
387 n = newnode(args);
388 AddTail(&project->extramakefiles, n);
390 else if (!strcmp (cmd, "ignoredir"))
392 Node * n;
393 n = newnode(args);
394 AddTail(&project->ignoredirs, n);
396 else if (!strcmp (cmd, "defaultmakefilename"))
398 SETSTR(project->defaultmakefilename,args);
400 else if (!strcmp (cmd, "top"))
402 SETSTR(project->srctop,args);
404 else if (!strcmp (cmd, "defaulttarget"))
406 SETSTR(project->defaulttarget,args);
408 else if (!strcmp (cmd, "genmakefilescript"))
410 SETSTR(project->genmakefilescript,args);
412 else if (!strcmp (cmd, "genmakefiledeps"))
414 Node * dep;
415 int depc, t;
416 char ** deps = getargs (args, &depc, NULL);
418 for (t=0; t<depc; t++)
420 dep = addnodeonce (&project->genmakefiledeps, deps[t]);
423 else if (!strcmp (cmd, "globalvarfile"))
425 SETSTR(project->globalvarfile,args);
427 else if (!strcmp (cmd, "genglobalvarfile"))
429 SETSTR(project->genglobalvarfile,args);
431 else if (!strcmp (cmd, "maketool"))
433 SETSTR(project->maketool,args);
435 else
437 setvar(&project->vars, cmd, args);
442 fclose (optfh);
444 /* Clean up memory from getargs */
445 getargs (NULL, NULL, NULL);
447 if (debug)
449 printf ("known projects: ");
450 printlist (&projects);
454 void
455 expungeprojects (void)
457 Project *prj, *next;
459 ForeachNodeSafe (&projects, prj, next)
461 Remove (prj);
462 freeproject (prj);
466 Project *
467 findproject (const char * pname)
469 return FindNode (&projects, pname);
472 Project *
473 getfirstproject (void)
475 Project * prj = GetHead (&projects);
477 if (prj && prj == defaultprj)
478 prj = GetNext (prj);
480 return prj;
484 execute (Project * prj, const char * cmd, const char * in,
485 const char * out, const char * args)
487 char buffer[4096];
488 char * cmdstr;
489 int rc;
491 debug(printf("MMAKE:project.c->execute(cmd '%s')\n", cmd));
493 strcpy (buffer, cmd);
494 strcat (buffer, " ");
496 if (strcmp (in, "-"))
498 strcat (buffer, "<");
499 strcat (buffer, in);
500 strcat (buffer, " ");
503 if (strcmp (out, "-"))
505 strcat (buffer, ">");
506 strcat (buffer, out);
507 strcat (buffer, " ");
510 strcat (buffer, args);
512 cmdstr = substvars (&prj->vars, buffer);
514 debug(printf("MMAKE:project.c->execute: parsed cmd '%s'\n", buffer));
516 if (verbose)
517 printf ("Executing %s...\n", cmdstr);
519 rc = system (cmdstr);
521 if (rc)
523 printf ("%s failed: %d\n", cmdstr, rc);
526 return !rc;
529 void
530 maketarget (Project * prj, char * tname)
532 Target * target, * subtarget;
533 Node * node;
534 MakefileRef * mfref;
535 MakefileTarget * mftarget;
536 List deps;
538 printf ("Building %s.%s\n", prj->node.name, tname);
540 NewList (&deps);
542 chdir (prj->srctop);
544 readvars (prj);
546 if (!prj->cache)
547 prj->cache = activatecache (prj);
549 if (!*tname)
550 tname = prj->defaulttarget;
552 target = FindNode (&prj->cache->targets, tname);
554 if (!target)
556 printf ("Nothing known about target %s in project %s\n", tname, prj->node.name);
557 return;
560 target->updated = 1;
562 ForeachNode (&target->makefiles, mfref)
564 mftarget = FindNode (&mfref->makefile->targets, tname);
566 ForeachNode (&mftarget->deps, node)
567 addnodeonce (&deps, node->name);
570 ForeachNode (&deps, node)
572 subtarget = FindNode (&prj->cache->targets, node->name);
574 if (!subtarget)
576 printf ("Nothing known about target %s in project %s\n", node->name, prj->node.name);
578 else if (!subtarget->updated)
580 maketarget (prj, node->name);
584 freelist (&deps);
586 ForeachNode (&target->makefiles, mfref)
588 if (!mfref->virtualtarget)
590 callmake (prj, tname, mfref->makefile);
594 freelist (&deps);