Subject: modified crunchgen
To: None <tech-userlevel@netbsd.org>
From: David Laight <david@l8s.co.uk>
List: tech-userlevel
Date: 11/13/2003 13:42:36
I've modified crunchgen so that it no longer needs to parse each program's
Makefile to find the list of objects to build.  Instead it relies on the
program's Makefile having a ${PROG}.ro: ld -r ${OBJS} ${.TARGET} rule.

If nothing else it means you only get a single 'prog.ro is upto date'
message instead of a message for each .o file.

An additional option -O reverts to the old behaviour (is this needed?)

Also changed:
- Delete code for RENAME_SYMS - all getting too hard!
- For NEW_TOOLCHAIN rename main to _crunched_<prog>_stub instead of
  generating a <prog>_stub.c file.
- Rename symbols to <sym>$$from$$<prog> instead of _$$hide$$<prog>.cro$$<sym>
  This makes gdb report the symbol name instead of "_" (thanks c++)
- Upped version to 0.4

The NetBSD source tree builds fine (the .ro rule went in a while ago...).

(is the !NEW_TOOLCHAIN code needed still?)

	David

Index: crunchgen.1
===================================================================
RCS file: /cvsroot/src/usr.bin/crunch/crunchgen/crunchgen.1,v
retrieving revision 1.21
diff -u -p -r1.21 crunchgen.1
--- crunchgen.1	31 Mar 2003 01:46:29 -0000	1.21
+++ crunchgen.1	13 Nov 2003 13:29:13 -0000
@@ -119,6 +119,14 @@ Assume that relative source directory sp
 .It Fl L Ar lib-dir
 Try to obtain libraries from
 .Ar lib-dir .
+.It Fl O
+Force
+.Nm
+to parse the program's Makefile in determine the list of .o files.
+Without this option
+.nm
+expects the program's Makefile to have a program.ro target that is all
+the program objects linked into a single relocatable.
 .El
 .Sh CRUNCHGEN CONFIGURATION FILE COMMANDS
 .Nm
Index: crunchgen.c
===================================================================
RCS file: /cvsroot/src/usr.bin/crunch/crunchgen/crunchgen.c,v
retrieving revision 1.51
diff -u -p -r1.51 crunchgen.c
--- crunchgen.c	27 Oct 2003 00:12:43 -0000	1.51
+++ crunchgen.c	13 Nov 2003 13:29:15 -0000
@@ -52,17 +52,11 @@ __RCSID("$NetBSD: crunchgen.c,v 1.51 200
 #include <sys/param.h>
 #include <sys/utsname.h>
 
-#define CRUNCH_VERSION	"0.3"
+#define CRUNCH_VERSION	"0.4"
 
 #define MAXLINELEN	16384
 #define MAXFIELDS 	 2048
 
-/*
- * Define RENAME_SYMS to rename symbols using objcopy --redefine-syms.
- * Undef RENAME_SYMS to hide globals symbols using objcopy --keep-global-symbol.
- */
-#define	RENAME_SYMS
-
 /* internal representation of conf file: */
 
 /* simple lists of strings suffice for most parms */
@@ -103,7 +97,7 @@ int goterror = 0;
 
 char *pname = "crunchgen";
 
-int verbose, readcache, useobjs;	/* options */
+int verbose, readcache, useobjs, oneobj;	/* options */
 int reading_cache;
 char *machine;
 char *makeobjdirprefix;
@@ -150,15 +144,17 @@ int main(int argc, char **argv)
     verbose = 1;
     readcache = 1;
     useobjs = 0;
+    oneobj = 1;
     *outmkname = *outcfname = *execfname = '\0';
     
     if(argc > 0) pname = argv[0];
 
-    while((optc = getopt(argc, argv, "m:c:d:e:foqD:L:")) != -1) {
+    while((optc = getopt(argc, argv, "m:c:d:e:foqD:L:O")) != -1) {
 	switch(optc) {
 	case 'f':	readcache = 0; break;
 	case 'q':	verbose = 0; break;
-	case 'o':       useobjs = 1; break;
+	case 'O':	oneobj = 0; break;
+	case 'o':       useobjs = 1, oneobj = 0; break;
 
 	case 'm':	strcpy(outmkname, optarg); break;
 	case 'c':	strcpy(outcfname, optarg); break;
@@ -443,11 +439,13 @@ void add_special(int argc, char **argv)
 	    out_of_memory();
     }
     else if(!strcmp(argv[2], "objs")) {
+	oneobj = 0;
 	p->objs = NULL;
 	for(i=3;i<argc;i++)
 	    add_string(&p->objs, argv[i]);
     }
     else if(!strcmp(argv[2], "objpaths")) {
+	oneobj = 0;
 	p->objpaths = NULL;
 	for(i=3;i<argc;i++)
 	    add_string(&p->objpaths, argv[i]);
@@ -544,6 +542,10 @@ void fillin_program(prog_t *p)
 		p->srcdir = strdup(path);
 	}
     }
+    if(!p->srcdir && verbose)
+	fprintf(stderr, "%s: %s: warning: could not find source directory.\n",
+		infilename, p->name);
+
     if(!p->objdir && p->srcdir && useobjs) {
 	if (makeobjdirprefix) {
 	    (void)snprintf(path, sizeof(path), "%s/%s", makeobjdirprefix, p->srcdir);
@@ -565,28 +567,26 @@ void fillin_program(prog_t *p)
         }
     }
 
+    if (oneobj)
+	return;
+
     if(p->srcdir)
 	(void)snprintf(path, sizeof(path), "%s/Makefile", p->srcdir);
     if(!p->objs && p->srcdir && is_nonempty_file(path))
 	fillin_program_objs(p, p->srcdir);
 
     if(!p->objpaths && p->objs) {
-	if (p->objdir && useobjs) {
-	    for(s = p->objs; s != NULL; s = s->next) {
-		(void)snprintf(line, sizeof(line), "%s/%s", p->objdir, s->str);
-		add_string(&p->objpaths, line);
-	    }
-	} else {
-	    for(s = p->objs; s != NULL; s = s->next) {
-		(void)snprintf(line, sizeof(line), "%s/%s", p->ident, s->str);
-		add_string(&p->objpaths, line);
-	    }
+	char *objdir;
+	if (p->objdir && useobjs)
+	    objdir = p->objdir;
+	else
+	    objdir = p->ident;
+	for(s = p->objs; s != NULL; s = s->next) {
+	    (void)snprintf(line, sizeof(line), "%s/%s", objdir, s->str);
+	    add_string(&p->objpaths, line);
 	}
     }
 	    
-    if(!p->srcdir && verbose)
-	fprintf(stderr, "%s: %s: warning: could not find source directory.\n",
-		infilename, p->name);
     if(!p->objs && verbose)
 	fprintf(stderr, "%s: %s: warning: could not find any .o files.\n", 
 		infilename, p->name);
@@ -702,16 +702,18 @@ void gen_specials_cache(void)
 
     for(p = progs; p != NULL; p = p->next) {
 	fprintf(cachef, "\n");
-	if(p->srcdir)
+	if (p->srcdir)
 	    fprintf(cachef, "special %s srcdir %s\n", p->name, p->srcdir);
-	if(p->objdir && useobjs)
+	if (p->objdir && useobjs)
 	    fprintf(cachef, "special %s objdir %s\n", p->name, p->objdir);
-	if(p->objs) {
+	if (p->objs) {
 	    fprintf(cachef, "special %s objs", p->name);
 	    output_strlst(cachef, p->objs);
 	}
-	fprintf(cachef, "special %s objpaths", p->name);
-	output_strlst(cachef, p->objpaths);
+	if (p->objpaths) {
+	    fprintf(cachef, "special %s objpaths", p->name);
+	    output_strlst(cachef, p->objpaths);
+	}
     }
     fclose(cachef);
 }
@@ -886,61 +888,68 @@ void prog_makefile_rules(FILE *outmk, pr
 
     fprintf(outmk, "\n# -------- %s\n\n", p->name);
 
-    fprintf(outmk,   "%s_OBJPATHS=", p->ident);
-    output_strlst(outmk, p->objpaths);
+    fprintf(outmk, "%s_OBJPATHS=", p->ident);
+#ifndef NEW_TOOLCHAIN
+    fprintf(outmk, " %s_stub.o", p->name);
+#endif
+    if (p->objs)
+	output_strlst(outmk, p->objpaths);
+    else
+	fprintf(outmk, " %s/%s.ro\n", p->ident, p->name);
 
-    if(p->srcdir && p->objs && !useobjs) {
+    if (p->srcdir && !useobjs) {
 	fprintf(outmk, "%s_SRCDIR=%s\n", p->ident, p->srcdir);
-	fprintf(outmk, "%s_OBJS=", p->ident);
-	output_strlst(outmk, p->objs);
-	fprintf(outmk, "%s_make:\n", p->ident);
-	fprintf(outmk, "\tif [ \\! -d %s ]; then mkdir %s; fi; cd %s; \\\n",
+	if (p->objs) {
+	    fprintf(outmk, "%s_OBJS=", p->ident);
+	    output_strlst(outmk, p->objs);
+	}
+	fprintf(outmk, "%s:\n\t mkdir %s\n", p->ident, p->ident);
+	fprintf(outmk, "%s_make: %s\n", p->ident, p->ident);
+	fprintf(outmk, "\tcd %s; printf \".PATH: ${%s_SRCDIR}\\n"
+		".CURDIR:= ${%s_SRCDIR}\\n"
+		".include \\\"\\$${.CURDIR}/Makefile\\\"\\n\" \\\n",
 	    p->ident, p->ident, p->ident);
-	fprintf(outmk, "\tprintf \".PATH: ${%s_SRCDIR}\\n.CURDIR:= ${%s_SRCDIR}\\n"
-	    ".include \\\"\\$${.CURDIR}/Makefile\\\"\\n\" \\\n", p->ident, p->ident);
-	fprintf(outmk, "\t| ${MAKE} CRUNCHEDPROG=1 DBG=\"${DBG}\" -f- depend ${%s_OBJS}\n\n",
-	    p->ident);
-    }
-    else
+	fprintf(outmk, "\t| ${MAKE} CRUNCHEDPROG=1 DBG=\"${DBG}\" -f- depend ");
+	if (p->objs)
+	    fprintf(outmk, "${%s_OBJS}\n\n", p->ident);
+	else
+	    fprintf(outmk, "%s.ro\n\n", p->name);
+    } else
         fprintf(outmk, "%s_make:\n\t@echo \"** Using existing objs for %s\"\n\n", 
 		p->ident, p->name);
 
+    fprintf(outmk, "%s.cro: %s .WAIT ${%s_OBJPATHS}\n",
+	p->name, p->ident, p->ident);
 
-    fprintf(outmk, "%s_stub.c:\n", p->name);
-    fprintf(outmk, "\techo \""
-	           "int _crunched_%s_stub(int argc, char **argv, char **envp)"
-	           "{return main(argc,argv,envp);}\" >%s_stub.c\n",
-	    p->ident, p->name);
-    if (useobjs)
-	    fprintf(outmk, "%s.cro: %s_stub.o\n",
-		p->name, p->name);
-    else
-	    fprintf(outmk, "%s.cro: %s_stub.o ${%s_OBJPATHS}\n",
-		p->name, p->name, p->ident);
-    fprintf(outmk, "\t${LD} -dc -r -o %s.cro %s_stub.o $(%s_OBJPATHS)\n", 
-	    p->name, p->name, p->ident);
 #ifdef NEW_TOOLCHAIN
-#ifdef RENAME_SYMS
-    fprintf(outmk, "\t${NM} -ng %s.cro | grep -wv U | ", p->name);
-    fprintf(outmk, "egrep -vw _crunched_%s_stub | ", p->ident);
+    if (p->objs)
+	fprintf(outmk, "\t${LD} -dc -r -o %s/%s.ro $(%s_OBJPATHS)\n", 
+		p->ident, p->name, p->ident);
+    /* Use one awk command.... */
+    fprintf(outmk, "\t${NM} -ng %s/%s.ro | awk '/^ *U / { next };",
+	    p->ident, p->name);
     for (lst = p->keepsymbols; lst != NULL; lst = lst->next)
-	fprintf(outmk, "egrep -vw %s | ", lst->str);
-    fprintf(outmk, "env CRO=%s.cro awk "
-	"'{ print $$3 \" _$$$$hide$$$$\" ENVIRON[\"CRO\"] \"$$$$\" $$3 }' "
+	fprintf(outmk, " / %s$$/ { next };", lst->str);
+    fprintf(outmk, " / main$$/ { print \"main _crunched_%s_stub\"; next };",
+	p->name);
+    /* gdb thinks these are C++ and ignores everthing after the first $$. */
+    fprintf(outmk, " { print $$3 \" \" $$3 \"$$$$from$$$$%s\" }' "
 	"> %s.cro.syms\n", p->name, p->name);
     fprintf(outmk, "\t${OBJCOPY} --redefine-syms %s.cro.syms ", p->name);
+    fprintf(outmk, "%s/%s.ro %s.cro\n", p->ident, p->name, p->name);
 #else
-    fprintf(outmk, "\t${OBJCOPY} --keep-global-symbol _crunched_%s_stub ",
-  	    p->ident);
-    for (lst = p->keepsymbols; lst != NULL; lst = lst->next)
-	fprintf(outmk, "--keep-global-symbol %s ", lst->str);
-#endif
-#else
+    fprintf(outmk, "\t${LD} -dc -r -o %s.cro $(%s_OBJPATHS)\n", 
+		p->name, p->ident);
     fprintf(outmk, "\t${CRUNCHIDE} -k _crunched_%s_stub ", p->ident);
     for (lst = p->keepsymbols; lst != NULL; lst = lst->next)
 	fprintf(outmk, "-k %s ", lst->str);
-#endif
     fprintf(outmk, "%s.cro\n", p->name);
+    fprintf(outmk, "%s_stub.c:\n", p->name);
+    fprintf(outmk, "\techo \""
+	           "int _crunched_%s_stub(int argc, char **argv, char **envp)"
+	           "{return main(argc,argv,envp);}\" >%s_stub.c\n",
+	    p->ident, p->name);
+#endif
 }
 
 void output_strlst(FILE *outf, strlst_t *lst)
-- 
David Laight: david@l8s.co.uk