About the most complex thing I use MMK for is building Perl and its associated extensions. I've run across two cases where MMS handles a DESCRIP.MMS with no problem, but MMK has difficulties. In both cases, implicit rules are implicated. Since Perl builds use automated procedures to create DESCRIP.MMS files (or makefiles, on Unix), it's generally not useful to "edit DESCRIP.MMS" as a workaround...such editting will be detected and the DESCRIP.MMS regenerated. And the authors (mostly on Unix systems) of the software are not particularly sympathetic about making changes to accomodate "broken utilities". So, first let me describe some test cases...these are greatly simplified from the original problematic DESCRIP.MMS, and they certainly not what you would write yourself. But they do exercise the problems. Example 1: A.C does an #include of B.C ----------------------------------------------------------- A.OBJ : B.C .C.OBJ : CC $(MMS$SOURCE) ----------------------------------------------------------- MMS results: CC A.C (Unix make does the same) MMK results CC B.C ---error message about A.OBJ not being updated What's happening here is that MMK is interpreting the implicit rule .C.OBJ as applying even if the .C and the .OBJ have different "stem" names, and that B.C should be used to create A.OBJ. This is at odds with the usual interpretation of makefiles. The first line of Example 1 DESCRIP.MMS merely states that A.OBJ should be rebuilt if it is older than B.C (not that B.C is used in the rebuilding). The rest of DESCRIP.MMS gives an implicit rule for building a file x.OBJ from x.C. We don't need to use a /OBJ=... on the compile because the implicit rule only applies to .C and .OBJ files with the same "stem" filename. Example 2A: Building .OBJ from .XS with missing intermediate file ---------------------------------------------------------------- .SUFFIXES .OBJ .C .XS A.OBJ : (some other junk) .C.OBJ : CC $(MMS$SOURCE) .XS.C : PERL (blah) $(MMS$SOURCE) >$(MMS$TARGET) ---------------------------------------------------------------- MMS/make results: PERL (blah) A.XS >A.C CC A.C MMK results: no source file A.C This situation can also occur when we have an explicit rule for building A.C: Example 2B: Building .OBJ from .XS with missing intermediate file ---------------------------------------------------------------- .SUFFIXES .OBJ .C .XS A.OBJ : (some other junk) .C.OBJ : CC $(MMS$SOURCE) A.C : A.XS PERL (blah) $(MMS$SOURCE) >$(MMS$TARGET) ---------------------------------------------------------------- What's happening is that after attempting to apply the implicit .C.OBJ rule, MMK isn't looking further to see if there is an explicit or implicit rule that would allow it to build A.C if one does not already exist. All of the above examples are easily made to work with simple changes, but (especially in the case of automatically generated DESCRIP.MMS files) it really would be better if MMK would "do the right thing". So here's a patch to MMK 3.8-1 to (a) not use dependancy files when processing implicit rules and (b) recurse through implicit rules until a source file or explicit rule is found that will allow building the target. Nearly all of the changes are in the routine Fill_In_Missing_Sources. There's a minor change in scan_rule_list because we need to find an appropriate rule even if the source file for that rule doesn't exist (yet). Please give this patch a good thorough workout; the two largest packages I've used it on were MMK itself and Perl+extensions. In particular, I haven't done any testing with CMS because I don't have CMS on my system. To put this in proper perspective, these are subtle problems with an overwhelmingly excellent piece of software. diff -uBb misc.c-orig misc.c --- misc.c-orig Fri Dec 22 08:04:38 2000 +++ misc.c Fri Dec 22 08:05:54 2000 @@ -627,8 +627,11 @@ char trgnam[MMK_S_FILE], tmpsfx[MMK_S_SFX], fspec[MMK_S_FILE], *cp; unsigned int status; int pass, passmax, check_cms, trgnamlen, maybes, i; + int nofileok; maybes = 0; + nofileok = (generalize & 0x10) != 0; + generalize = generalize & 0x0F; /* ** When there's just one rule for this suffix pair, we want to avoid @@ -641,6 +644,8 @@ ** _just_ the prefixed rules. When we call with generalize == 2, we ** want to check _just_ the non-prefixed rules. ** +** when we call with generalize +16, we don't care if the file exists. +** ** Phew! Now I understand why NMAKE doesn't have generic rules that ** work across directories. */ @@ -690,6 +695,7 @@ memcpy(fspec+r->srcpfxlen, trgnam, trgnamlen); strcpy(fspec+(r->srcpfxlen+trgnamlen), r->src); if (check_cms) status = cms_get_rdt(fspec, 0, &rdt); + else if (nofileok) status = 1; else status = file_exists(fspec, 0); if (OK(status)) break; /* diff -uBb readdesc.c-orig readdesc.c --- readdesc.c-orig Mon May 22 14:25:13 2000 +++ readdesc.c Fri Dec 22 10:15:49 2000 @@ -62,6 +62,7 @@ static void strip_comments(char *, char *); static void Process_Deferred_Dependencies(void); static void Fill_In_Missing_Sources(void); + static int Find_Usable_Object(struct SFX *s, struct DEPEND *dep); /* @@ -357,12 +358,7 @@ static void Fill_In_Missing_Sources (void) { struct DEPEND *dep; - struct OBJECT *obj, *obj2; - struct OBJREF *o; - struct RULE *r, *xr; struct SFX *s; - char trgnam[MMK_S_FILE]; - int need_extra_source, trgnamlen; /* ** We only need to fill in sources when the target is a file _and_ @@ -373,35 +369,96 @@ if (dep->cmdqptr != 0 && dep->cmdqptr->flink != dep->cmdqptr) continue; s = find_suffix(dep->target->sfx); if (s) { - need_extra_source = 1; - for (o = dep->sources.flink; o != &dep->sources; o = o->flink) { - if (o->obj->type != MMK_K_OBJ_FILE) continue; - if (find_rule(dep->target->sfx, o->obj->sfx)) { - need_extra_source = 0; - break; + Find_Usable_Object(s, dep); } } - if (need_extra_source) { +} /* Fill_In_Missing_Sources */ + - for (; s != &suffixes; s = s->flink) { +static int +Find_Usable_Object(struct SFX *s, struct DEPEND *dep) +{ int check_cms, slen; + struct SFX *s2; + struct RULE *r, *xr; + struct OBJECT *obj, *obj2; + struct OBJREF *o; + struct DEPEND *dep2; + char trgnam[MMK_S_FILE], tfile[MMK_S_FILE], sfile[MMK_S_FILE]; + int trgnamlen; /* ** Don't use the CMS suffixes if we're not using CMS */ slen = strlen(s->value); check_cms = s->value[slen-1] == '~'; - if (check_cms && !use_cms) continue; + if (check_cms && !use_cms) return 0; +/* +** go through suffixes, looking for one that (a) will get us to the +** desired suffix, and (b) has a source file. If (a) and not (b) +** then recurse to find how to get the intermediate suffix (implicit +** rule chaining) +*/ + extract_name(tfile, dep->target->name); + + for (s2 = s->flink; s2 != &suffixes; s2 = s2->flink) { + +/* first check for an explicit rule */ + + for (dep2 = dependencies.flink; dep2 != &dependencies; dep2 = dep2->flink) { + if (dep2->target->type != MMK_K_OBJ_FILE) continue; + if (dep2->cmdqptr == 0 || dep2->cmdqptr->flink == dep2->cmdqptr) continue; + if (strcmp(dep2->target->sfx, s2->value) != 0) continue; + trgnamlen = extract_name(sfile, dep2->target->name); + if (strcmp(tfile, sfile) != 0) continue; + + obj = mem_get_object(); + memcpy(obj->name, tfile, trgnamlen); + strcpy(obj->name+trgnamlen, s2->value); + strcpy(obj->sfx, s2->value); + obj->type = MMK_K_OBJ_FILE; + if ((obj2 = Find_Object(obj)) == NULL) { + Insert_Object(obj); + } else { + mem_free_object(obj); + obj = obj2; + } - xr = find_rule(dep->target->sfx, s->value); + o = mem_get_objref(); + o->obj = obj; + queue_insert(o, &dep->sources); + return 1; /* signal all recursions OK, store object! */ + } + +/* +** find a rule to get from s2 suffix to s suffix +*/ + xr = find_rule(s->value, s2->value); +/* +** found a rule, see if source file exists +*/ if (xr != 0) { r = scan_rule_list(xr, dep->target->name, 0); - if (r != 0) { +/* +** if r: +** got source file, so all previous recursions okay too, store result +*/ + if (!r) { +/* +** rule is okay, but no source file +** recurse to try and build this suffix from other sources +** if not, then have to try next suffix +*/ + if (!Find_Usable_Object(s2, dep)) continue; + r = scan_rule_list(xr, dep->target->name, 0x10); + if (!r) continue; /* should this ever happen? I think not*/ + } + obj = mem_get_object(); trgnamlen = extract_filename(trgnam, dep->target->name); memcpy(obj->name, r->srcpfx, r->srcpfxlen); memcpy(obj->name+r->srcpfxlen, trgnam, trgnamlen); - strcpy(obj->name+(r->srcpfxlen+trgnamlen), s->value); - strcpy(obj->sfx, s->value); + strcpy(obj->name+(r->srcpfxlen+trgnamlen), s2->value); + strcpy(obj->sfx, s2->value); obj->type = MMK_K_OBJ_FILE; if ((obj2 = Find_Object(obj)) == NULL) { Insert_Object(obj); @@ -412,11 +470,9 @@ o = mem_get_objref(); o->obj = obj; queue_insert(o, &dep->sources); - break; - } + return 1; /* signal all recursions OK, store object! */ } } - } - } - } -} /* Fill_In_Missing_Sources */ +/* no suffixes worked, report failure */ + return 0; +} -- Drexel University \V --Chuck Lane ======]---------->--------*------------<-------[=========== (215) 895-1545 _/ \ Particle Physics FAX: (215) 895-5934 /\ /~~~~~~~~~~~ [EMAIL PROTECTED]