rules.c (6937B)
1 /* 2 * Control of the implicit suffix rules 3 */ 4 #include "make.h" 5 6 /* 7 * Return a pointer to the suffix of a name (which may be the 8 * terminating NUL if there's no suffix). 9 */ 10 static char * 11 mk_suffix(const char *name) 12 { 13 char *p = strrchr(name, '.'); 14 return p ? p : (char *)name + strlen(name); 15 } 16 17 /* 18 * Find a name structure whose name is formed by concatenating two 19 * strings. If 'create' is TRUE the name is created if necessary. 20 */ 21 static struct name * 22 mk_namecat(MakeCtx* mc, const char *s, const char *t, int create) 23 { 24 char *p; 25 struct name *np; 26 27 p = mk_concat3(mc, s, t, ""); 28 np = create ? mk_newname(mc, p) : mk_findname(mc, p); 29 return np; 30 } 31 32 /* 33 * Search for an inference rule to convert some suffix ('psuff') 34 * to the target suffix 'tsuff'. The basename of the prerequisite 35 * is 'base'. 36 */ 37 static struct name * 38 mk_dyndep0(MakeCtx* mc, char *base, const char *tsuff, struct rule *infrule) 39 { 40 char *psuff; 41 struct name *xp; // Suffixes 42 struct name *sp; // Suffix rule 43 struct rule *rp; 44 struct depend *dp; 45 IF_NOT_FEATURE_MAKE_EXTENSIONS(const) bool chain = FALSE; 46 47 xp = mk_newname(mc, ".SUFFIXES"); 48 #if ENABLE_FEATURE_MAKE_EXTENSIONS 49 retry: 50 #endif 51 for (rp = xp->n_rule; rp; rp = rp->r_next) { 52 for (dp = rp->r_dep; dp; dp = dp->d_next) { 53 // Generate new suffix rule to try 54 psuff = dp->d_name->n_name; 55 sp = mk_namecat(mc, psuff, tsuff, FALSE); 56 if (sp && sp->n_rule) { 57 struct name *ip; 58 int got_ip; 59 60 #if ENABLE_FEATURE_MAKE_EXTENSIONS 61 // Has rule already been used in this chain? 62 if ((sp->n_flag & N_MARK)) 63 continue; 64 #endif 65 // Generate a name for an implicit prerequisite 66 ip = mk_namecat(mc, base, psuff, TRUE); 67 if ((ip->n_flag & N_DOING)) 68 continue; 69 70 if (!ip->n_tim.tv_sec) 71 mk_modtime(mc, ip); 72 73 if (!chain) { 74 got_ip = ip->n_tim.tv_sec || (ip->n_flag & N_TARGET); 75 } 76 #if ENABLE_FEATURE_MAKE_EXTENSIONS 77 else { 78 sp->n_flag |= N_MARK; 79 got_ip = mk_dyndep(mc, ip, NULL, NULL) != NULL; 80 sp->n_flag &= ~N_MARK; 81 } 82 #endif 83 84 if (got_ip) { 85 // Prerequisite exists or we know how to make it 86 if (infrule) { 87 infrule->r_dep = mk_newdep(mc, ip, NULL); 88 infrule->r_cmd = sp->n_rule->r_cmd; 89 } 90 return ip; 91 } 92 } 93 } 94 } 95 #if ENABLE_FEATURE_MAKE_EXTENSIONS 96 // If we didn't find an existing file or an explicit rule try 97 // again, this time looking for a chained inference rule. 98 if (!mc->posix && !chain) { 99 chain = TRUE; 100 goto retry; 101 } 102 #endif 103 return NULL; 104 } 105 106 #if ENABLE_FEATURE_MAKE_EXTENSIONS 107 /* 108 * If 'name' ends with 'suffix' return an allocated string containing 109 * the name with the suffix removed, else return NULL. 110 */ 111 static char * 112 mk_has_suffix(MakeCtx* mc, const char *name, const char *suffix) 113 { 114 ptrdiff_t delta = strlen(name) - strlen(suffix); 115 char *base = NULL; 116 117 if (delta > 0 && strcmp(name + delta, suffix) == 0) { 118 base = mk_strdup(mc, name); 119 base[delta] = '\0'; 120 } 121 122 return base; 123 } 124 #endif 125 126 /* 127 * Dynamic dependency. This routine applies the suffix rules 128 * to try and find a source and a set of rules for a missing 129 * target. NULL is returned on failure. On success the name of 130 * the implicit prerequisite is returned and the rule used is 131 * placed in the infrule structure provided by the caller. 132 */ 133 static struct name * 134 mk_dyndep(MakeCtx* mc, struct name *np, struct rule *infrule, const char **ptsuff) 135 { 136 const char *tsuff; 137 char *base, *name, *member; 138 struct name *pp = NULL; // Implicit prerequisite 139 140 member = NULL; 141 name = mk_splitlib(mc, np->n_name, &member); 142 143 #if ENABLE_FEATURE_MAKE_EXTENSIONS 144 // POSIX only allows inference rules with one or two periods. 145 // As an extension this restriction is lifted, but not for 146 // targets of the form lib.a(member.o). 147 if (!mc->posix && member == NULL) { 148 struct name *xp = mk_newname(mc, ".SUFFIXES"); 149 int found_suffix = FALSE; 150 151 for (struct rule *rp = xp->n_rule; rp; rp = rp->r_next) { 152 for (struct depend *dp = rp->r_dep; dp; dp = dp->d_next) { 153 tsuff = dp->d_name->n_name; 154 base = mk_has_suffix(mc, name, tsuff); 155 if (base) { 156 found_suffix = TRUE; 157 pp = mk_dyndep0(mc, base, tsuff, infrule); 158 if (pp) { 159 goto done; 160 } 161 } 162 } 163 } 164 165 if (!found_suffix) { 166 // The name didn't have a known suffix. Try single-suffix rule. 167 tsuff = ""; 168 pp = mk_dyndep0(mc, name, tsuff, infrule); 169 if (pp) { 170 done: 171 if (ptsuff) { 172 *ptsuff = tsuff; 173 } 174 } 175 } 176 } else 177 #endif 178 { 179 tsuff = mk_strdup(mc, mk_suffix(name)); 180 base = member ? member : name; 181 *mk_suffix(base) = '\0'; 182 183 pp = mk_dyndep0(mc, base, tsuff, infrule); 184 } 185 186 return pp; 187 } 188 189 #define RULES \ 190 ".c.o:\n" \ 191 " $(CC) $(CFLAGS) -c $<\n" \ 192 ".y.o:\n" \ 193 " $(YACC) $(YFLAGS) $<\n" \ 194 " $(CC) $(CFLAGS) -c y.tab.c\n" \ 195 " rm -f y.tab.c\n" \ 196 " mv y.tab.o $@\n" \ 197 ".y.c:\n" \ 198 " $(YACC) $(YFLAGS) $<\n" \ 199 " mv y.tab.c $@\n" \ 200 ".l.o:\n" \ 201 " $(LEX) $(LFLAGS) $<\n" \ 202 " $(CC) $(CFLAGS) -c lex.yy.c\n" \ 203 " rm -f lex.yy.c\n" \ 204 " mv lex.yy.o $@\n" \ 205 ".l.c:\n" \ 206 " $(LEX) $(LFLAGS) $<\n" \ 207 " mv lex.yy.c $@\n" \ 208 ".c.a:\n" \ 209 " $(CC) -c $(CFLAGS) $<\n" \ 210 " $(AR) $(ARFLAGS) $@ $*.o\n" \ 211 " rm -f $*.o\n" \ 212 ".c:\n" \ 213 " $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<\n" \ 214 ".sh:\n" \ 215 " cp $< $@\n" \ 216 " chmod a+x $@\n" 217 218 #define RULES_2017 \ 219 ".SUFFIXES:.o .c .y .l .a .sh .f\n" \ 220 ".f.o:\n" \ 221 " $(FC) $(FFLAGS) -c $<\n" \ 222 ".f.a:\n" \ 223 " $(FC) -c $(FFLAGS) $<\n" \ 224 " $(AR) $(ARFLAGS) $@ $*.o\n" \ 225 " rm -f $*.o\n" \ 226 ".f:\n" \ 227 " $(FC) $(FFLAGS) $(LDFLAGS) -o $@ $<\n" 228 229 #define RULES_2024 \ 230 ".SUFFIXES:.o .c .y .l .a .sh\n" 231 232 #define MACROS \ 233 "CFLAGS=-O1\n" \ 234 "YACC=yacc\n" \ 235 "YFLAGS=\n" \ 236 "LEX=lex\n" \ 237 "LFLAGS=\n" \ 238 "AR=ar\n" \ 239 "ARFLAGS=-rv\n" \ 240 "LDFLAGS=\n" 241 242 #define MACROS_2017 \ 243 "CC=c99\n" \ 244 "FC=fort77\n" \ 245 "FFLAGS=-O1\n" \ 246 247 #define MACROS_2024 \ 248 "CC=c17\n" 249 250 #define MACROS_EXT \ 251 "CC=cc\n" 252 253 /* 254 * Read the built-in rules using a fake fgets-like interface. 255 */ 256 static char * 257 mk_getrules(MakeCtx* mc, char *s, int size) 258 { 259 char *r = s; 260 261 if (mc->rulepos == NULL || *mc->rulepos == '\0') { 262 if (mc->rule_idx == 0) { 263 mc->rulepos = MACROS; 264 mc->rule_idx++; 265 } else if (mc->rule_idx == 1) { 266 #if ENABLE_FEATURE_MAKE_EXTENSIONS 267 if (POSIX_2017) 268 mc->rulepos = MACROS_2017; 269 else if (mc->posix) 270 mc->rulepos = MACROS_2024; 271 else 272 mc->rulepos = MACROS_EXT; 273 #elif ENABLE_FEATURE_MAKE_POSIX_2024 274 mc->rulepos = MACROS_2024; 275 #else 276 mc->rulepos = MACROS_2017; 277 #endif 278 mc->rule_idx++; 279 } else if (!norules) { 280 if (mc->rule_idx == 2) { 281 #if ENABLE_FEATURE_MAKE_EXTENSIONS 282 mc->rulepos = POSIX_2017 ? RULES_2017 : RULES_2024; 283 #elif ENABLE_FEATURE_MAKE_POSIX_2024 284 mc->rulepos = RULES_2024; 285 #else 286 mc->rulepos = RULES_2017; 287 #endif 288 mc->rule_idx++; 289 } else if (mc->rule_idx == 3) { 290 mc->rulepos = RULES; 291 mc->rule_idx++; 292 } 293 } 294 } 295 296 if (*mc->rulepos == '\0') 297 return NULL; 298 299 while (--size) { 300 if ((*r++ = *mc->rulepos++) == '\n') 301 break; 302 } 303 *r = '\0'; 304 return s; 305 }