added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / tools / MetaMake / project.c
blobea9269b055cc7a81c673ac40cba65dce71cd5a73
1 /* MetaMake - A Make extension
2 Copyright © 1995-2004, 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 #include "config.h"
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <assert.h>
26 #ifdef HAVE_STRING_H
27 # include <string.h>
28 #else
29 # include <strings.h>
30 #endif
32 #include "project.h"
33 #include "var.h"
34 #include "mem.h"
35 #include "dep.h"
36 #include "mmake.h"
38 List projects;
39 static Project * defaultprj = NULL;
41 static void
42 readvars (Project * prj)
44 List deps;
45 Node * node, * next;
46 Dep * dep;
48 if (!prj->readvars)
49 return;
51 prj->readvars = 0;
53 printf ("Read vars...\n");
55 setvar (&prj->vars, "TOP", prj->top);
56 setvar (&prj->vars, "CURDIR", "");
58 if (prj->globalvarfile)
60 char * fn;
61 FILE * fh;
62 char line[256];
63 char * name, * value, * ptr;
65 fn = xstrdup (substvars (&prj->vars, prj->globalvarfile));
66 fh = fopen (fn, "r");
68 if (!fh && prj->genglobalvarfile)
70 char * gen = xstrdup (substvars (&prj->vars, prj->genglobalvarfile));
72 printf ("Generating %s...\n", fn);
74 if (!execute (prj, gen, "-", "-", ""))
76 error ("Error while creating \"%s\" with \"%s\"", fn, gen);
77 exit (10);
79 else
80 fh = fopen (fn, "r");
82 xfree (gen);
85 if (!fh)
87 error ("readvars():fopen(): Opening \"%s\" for reading", fn);
88 return;
91 xfree (fn);
93 while (fgets (line, sizeof(line), fh))
95 if (*line == '\n' || *line == '#') continue;
96 line[strlen(line)-1] = 0;
98 ptr = line;
99 while (isspace (*ptr)) ptr++;
100 name = ptr;
101 while (*ptr && !isspace(*ptr) && *ptr != ':' && *ptr != '=')
102 ptr ++;
104 if (*ptr)
105 *ptr++ = 0;
107 while (isspace(*ptr) || *ptr == ':' || *ptr == '=')
108 ptr ++;
110 value = ptr;
112 while (*ptr && *ptr != '#')
113 ptr ++;
115 *ptr = 0;
117 #if 0
118 printf ("%s=%s\n", name, substvars (&prj->vars, value));
119 #endif
121 setvar (&prj->vars, name, substvars (&prj->vars, value));
124 fclose (fh);
127 NewList(&deps);
128 ForeachNodeSafe (&prj->genmakefiledeps, node, next)
130 Remove (node);
131 AddTail (&deps, node);
134 ForeachNodeSafe (&deps, node, next)
136 Remove (node);
137 dep = newdepnode (substvars (&prj->vars, node->name));
138 AddTail (&prj->genmakefiledeps, dep);
139 xfree (node->name);
140 xfree (node);
143 if (debug)
145 printf ("project %s.genmfdeps=\n", prj->node.name);
146 printlist (&prj->genmakefiledeps);
149 if (debug)
151 printf ("project %s.vars=", prj->node.name);
152 printvarlist (&prj->vars);
156 static Project *
157 initproject (char * name)
159 Project * prj = new (Project);
161 memset (prj, 0, sizeof(Project));
163 if (!defaultprj)
165 prj->maketool = xstrdup ("make \"TOP=$(TOP)\" \"CURDIR=$(CURDIR)\"");
166 prj->defaultmakefilename = xstrdup ("Makefile");
167 prj->top = getcwd (NULL, 1024);
168 prj->defaulttarget = xstrdup ("all");
169 prj->genmakefilescript = NULL;
170 prj->globalvarfile = NULL;
171 prj->genglobalvarfile = NULL;
173 else
175 prj->maketool = xstrdup (defaultprj->maketool);
176 prj->defaultmakefilename = xstrdup (defaultprj->defaultmakefilename);
177 prj->top = xstrdup (defaultprj->top);
178 prj->defaulttarget = xstrdup (defaultprj->defaulttarget);
179 SETSTR (prj->genmakefilescript, defaultprj->genmakefilescript);
180 SETSTR (prj->globalvarfile, defaultprj->globalvarfile);
181 SETSTR (prj->genglobalvarfile, defaultprj->genglobalvarfile);
184 prj->node.name = xstrdup (name);
186 prj->readvars = 1;
188 NewList(&prj->genmakefiledeps);
189 NewList(&prj->ignoredirs);
190 NewList(&prj->vars);
191 NewList(&prj->extramakefiles);
193 return prj;
196 static void
197 freeproject (Project * prj)
199 assert (prj);
201 cfree (prj->node.name);
202 cfree (prj->maketool);
203 cfree (prj->defaultmakefilename);
204 cfree (prj->top);
205 cfree (prj->defaulttarget);
206 cfree (prj->genmakefilescript);
207 cfree (prj->globalvarfile);
208 cfree (prj->genglobalvarfile);
210 if (prj->cache)
211 closecache (prj->cache);
213 freelist (&prj->genmakefiledeps);
214 freelist (&prj->ignoredirs);
215 freevarlist (&prj->vars);
216 freelist (&prj->extramakefiles);
218 xfree (prj);
221 static void
222 callmake (Project * prj, const char * tname, Makefile * makefile)
224 static char buffer[4096];
225 const char * path = buildpath (makefile->dir);
226 int t;
228 chdir (prj->top);
229 chdir (path);
231 setvar (&prj->vars, "CURDIR", path);
232 setvar (&prj->vars, "TARGET", tname);
234 strcpy (buffer, "");
236 for (t=0; t<mflagc; t++)
238 strcat (buffer, mflags[t]);
239 strcat (buffer, " ");
242 if (strcmp (makefile->node.name, "Makefile")!=0 && strcmp (makefile->node.name, "makefile")!=0);
244 strcat (buffer, "--file=");
245 strcat (buffer, makefile->node.name);
246 strcat (buffer, " ");
249 strcat (buffer, tname);
251 printf ("Making %s in %s\n", tname, path);
253 if (!execute (prj, prj->maketool, "-", "-", buffer))
255 error ("Error while running make in %s", path);
256 exit (10);
261 void
262 initprojects (void)
264 char * optionfile;
265 char * home;
266 char line[256];
267 FILE * optfh = NULL;
268 Project * project;
270 NewList(&projects);
271 defaultprj = project = initproject ("default");
272 AddTail(&projects, project);
275 /* Try "$MMAKE_CONFIG" */
276 if ((optionfile = getenv ("MMAKE_CONFIG")))
277 optfh = fopen (optionfile, "r");
279 /* Try "$HOME/.mmake.config" */
280 if (!optfh)
282 if ((home = getenv("HOME")))
284 optionfile = xmalloc (strlen(home) + sizeof("/.mmake.config") + 1);
285 sprintf (optionfile, "%s/.mmake.config", home);
286 optfh = fopen (optionfile, "r");
287 free (optionfile);
291 /* Try with $CWD/.mmake.config" */
292 if (!optfh)
293 optfh = fopen (".mmake.config", "r");
295 /* Try with "$CWD/mmake.config */
296 if (!optfh)
297 optfh = fopen ("mmake.config", "r");
299 /* Give up */
300 if (!optfh)
302 fprintf (stderr,
303 "Please set the HOME or MMAKE_CONFIG env var (with setenv or export)\n"
305 error ("Opening mmake.config for reading");
306 exit (10);
309 while (fgets (line, sizeof(line), optfh))
311 if (*line == '\n' || *line == '#') continue;
312 line[strlen(line)-1] = 0;
314 if (*line == '[')
316 char * name, * ptr;
318 name = ptr = line+1;
319 while (*ptr && *ptr != ']')
320 ptr ++;
322 *ptr = 0;
324 #if 0
325 printf ("name=%s\n", name);
326 #endif
328 project = initproject (name);
330 AddTail(&projects,project);
332 else
334 char * cmd, * args, * ptr;
336 cmd = line;
337 while (isspace (*cmd))
338 cmd ++;
340 args = cmd;
341 while (*args && !isspace(*args))
343 *args = tolower (*args);
344 args ++;
346 if (*args)
347 *args++ = 0;
348 while (isspace (*args))
349 args ++;
351 ptr = args;
353 while (*ptr && *ptr != '\n')
354 ptr ++;
356 *ptr = 0;
358 if (!strcmp (cmd, "add"))
360 Node * n;
361 n = newnode(args);
362 AddTail(&project->extramakefiles, n);
364 else if (!strcmp (cmd, "ignoredir"))
366 Node * n;
367 n = newnode(args);
368 AddTail(&project->ignoredirs, n);
370 else if (!strcmp (cmd, "defaultmakefilename"))
372 SETSTR(project->defaultmakefilename,args);
374 else if (!strcmp (cmd, "top"))
376 SETSTR(project->top,args);
378 else if (!strcmp (cmd, "defaulttarget"))
380 SETSTR(project->defaulttarget,args);
382 else if (!strcmp (cmd, "genmakefilescript"))
384 SETSTR(project->genmakefilescript,args);
386 else if (!strcmp (cmd, "genmakefiledeps"))
388 Node * dep;
389 int depc, t;
390 char ** deps = getargs (args, &depc, NULL);
392 for (t=0; t<depc; t++)
394 dep = addnodeonce (&project->genmakefiledeps, deps[t]);
397 else if (!strcmp (cmd, "globalvarfile"))
399 SETSTR(project->globalvarfile,args);
401 else if (!strcmp (cmd, "genglobalvarfile"))
403 SETSTR(project->genglobalvarfile,args);
405 else if (!strcmp (cmd, "maketool"))
407 SETSTR(project->maketool,args);
409 else
411 setvar(&project->vars, cmd, args);
416 fclose (optfh);
418 /* Clean up memory from getargs */
419 getargs (NULL, NULL, NULL);
421 if (debug)
423 printf ("known projects: ");
424 printlist (&projects);
428 void
429 expungeprojects (void)
431 Project *prj, *next;
433 ForeachNodeSafe (&projects, prj, next)
435 Remove (prj);
436 freeproject (prj);
440 Project *
441 findproject (const char * pname)
443 return FindNode (&projects, pname);
446 Project *
447 getfirstproject (void)
449 Project * prj = GetHead (&projects);
451 if (prj && prj == defaultprj)
452 prj = GetNext (prj);
454 return prj;
458 execute (Project * prj, const char * cmd, const char * in,
459 const char * out, const char * args)
461 char buffer[4096];
462 char * cmdstr;
463 int rc;
465 strcpy (buffer, cmd);
466 strcat (buffer, " ");
468 if (strcmp (in, "-"))
470 strcat (buffer, "<");
471 strcat (buffer, in);
472 strcat (buffer, " ");
475 if (strcmp (out, "-"))
477 strcat (buffer, ">");
478 strcat (buffer, out);
479 strcat (buffer, " ");
482 strcat (buffer, args);
484 cmdstr = substvars (&prj->vars, buffer);
486 if (verbose)
487 printf ("Executing %s...\n", cmdstr);
489 rc = system (cmdstr);
491 if (rc)
493 printf ("%s failed: %d\n", cmdstr, rc);
496 return !rc;
499 void
500 maketarget (Project * prj, char * tname)
502 Target * target, * subtarget;
503 Node * node;
504 MakefileRef * mfref;
505 MakefileTarget * mftarget;
506 List deps;
508 printf ("Building %s.%s\n", prj->node.name, tname);
510 NewList (&deps);
512 chdir (prj->top);
514 readvars (prj);
516 if (!prj->cache)
517 prj->cache = activatecache (prj);
519 if (!*tname)
520 tname = prj->defaulttarget;
522 target = FindNode (&prj->cache->targets, tname);
524 if (!target)
526 printf ("Nothing known about target %s in project %s\n", tname, prj->node.name);
527 return;
530 target->updated = 1;
532 ForeachNode (&target->makefiles, mfref)
534 mftarget = FindNode (&mfref->makefile->targets, tname);
536 ForeachNode (&mftarget->deps, node)
537 addnodeonce (&deps, node->name);
540 ForeachNode (&deps, node)
542 subtarget = FindNode (&prj->cache->targets, node->name);
544 if (!subtarget)
546 printf ("Nothing known about target %s in project %s\n", node->name, prj->node.name);
548 else if (!subtarget->updated)
550 maketarget (prj, node->name);
554 freelist (&deps);
556 ForeachNode (&target->makefiles, mfref)
558 if (!mfref->virtualtarget)
560 callmake (prj, tname, mfref->makefile);
564 freelist (&deps);