2 * Copyright (c) 1993, 19801990
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#)mkmakefile.c 8.1 (Berkeley) 6/6/93
34 * $FreeBSD: src/usr.sbin/config/mkmakefile.c,v 1.51.2.3 2001/01/23 00:09:32 peter Exp $
38 * Build the makefile for the system, from
39 * the information in the 'files' files and the
40 * additional files for the machine being compiled to.
47 #include <sys/param.h>
50 #include "configvers.h"
52 #define next_word(fp, wd) \
56 word = get_word(fp); \
57 if (word == (char *)EOF) \
62 #define next_quoted_word(fp, wd) \
66 word = get_quoted_word(fp); \
67 if (word == (char *)EOF) \
73 static struct file_list
*fcur
;
75 static char *tail(char *);
76 static void do_clean(FILE *);
77 static void do_rules(FILE *);
78 static void do_sfiles(FILE *);
79 static void do_mfiles(FILE *);
80 static void do_cfiles(FILE *);
81 static void do_objs(FILE *);
82 static void do_before_depend(FILE *);
83 static int opteq(char *, char *);
84 static void read_files(void);
87 * Lookup a file, by name.
89 static struct file_list
*
94 for (fp
= ftab
; fp
!= NULL
; fp
= fp
->f_next
) {
95 if (strcmp(fp
->f_fn
, file
) == 0)
102 * Lookup a file, by final component name.
104 static struct file_list
*
105 fltail_lookup(char *file
)
107 struct file_list
*fp
;
109 for (fp
= ftab
; fp
!= NULL
; fp
= fp
->f_next
) {
110 if (strcmp(tail(fp
->f_fn
), tail(file
)) == 0)
117 * Make a new file list entry
119 static struct file_list
*
122 struct file_list
*fp
;
124 fp
= malloc(sizeof(*fp
));
125 bzero(fp
, sizeof(*fp
));
135 * Build the makefile from the skeleton
146 snprintf(line
, sizeof(line
), "../platform/%s/conf/Makefile",
148 ifp
= fopen(line
, "r");
150 snprintf(line
, sizeof(line
), "Makefile.%s", platformname
);
151 ifp
= fopen(line
, "r");
155 ofp
= fopen(path("Makefile.new"), "w");
157 err(1, "%s", path("Makefile.new"));
158 fprintf(ofp
, "KERN_IDENT=%s\n", raisestr(ident
));
159 fprintf(ofp
, "MACHINE_PLATFORM=%s\n", platformname
);
160 fprintf(ofp
, "MACHINE=%s\n", machinename
);
161 fprintf(ofp
, "MACHINE_ARCH=%s\n", machinearchname
);
162 fprintf(ofp
, ".makeenv MACHINE_PLATFORM\n");
163 fprintf(ofp
, ".makeenv MACHINE\n");
164 fprintf(ofp
, ".makeenv MACHINE_ARCH\n");
165 fprintf(ofp
, "IDENT=");
167 fprintf(ofp
, " -DGPROF");
170 printf("cpu type must be specified\n");
174 for (op
= mkopt
; op
!= NULL
; op
= op
->op_next
)
175 fprintf(ofp
, "%s=%s\n", op
->op_name
, op
->op_value
);
177 fprintf(ofp
, "DEBUG=-g\n");
179 fprintf(ofp
, "PROF=-pg\n");
180 fprintf(ofp
, "PROFLEVEL=%d\n", profiling
);
183 fprintf(ofp
,"S=%s\n", srcdir
);
184 while (fgets(line
, BUFSIZ
, ifp
) != 0) {
186 fprintf(ofp
, "%s", line
);
189 if (strcmp(line
, "%BEFORE_DEPEND\n") == 0)
190 do_before_depend(ofp
);
191 else if (strcmp(line
, "%OBJS\n") == 0)
193 else if (strcmp(line
, "%MFILES\n") == 0)
195 else if (strcmp(line
, "%CFILES\n") == 0)
197 else if (strcmp(line
, "%SFILES\n") == 0)
199 else if (strcmp(line
, "%RULES\n") == 0)
201 else if (strcmp(line
, "%CLEAN\n") == 0)
203 else if (strncmp(line
, "%VERSREQ=", sizeof("%VERSREQ=") - 1) == 0) {
204 versreq
= atoi(line
+ sizeof("%VERSREQ=") - 1);
205 if (versreq
!= CONFIGVERS
) {
206 fprintf(stderr
, "ERROR: version of config(8) does not match kernel!\n");
207 fprintf(stderr
, "config version = %d, ", CONFIGVERS
);
208 fprintf(stderr
, "version required = %d\n\n", versreq
);
209 fprintf(stderr
, "Make sure that /usr/src/usr.sbin/config is in sync\n");
210 fprintf(stderr
, "with your /usr/src/sys and install a new config binary\n");
211 fprintf(stderr
, "before trying this again.\n\n");
212 fprintf(stderr
, "If running the new config fails check your config\n");
213 fprintf(stderr
, "file against the GENERIC or LINT config files for\n");
214 fprintf(stderr
, "changes in config syntax, or option/device naming\n");
215 fprintf(stderr
, "conventions\n\n");
220 "Unknown %% construct in generic makefile: %s",
225 moveifchanged(path("Makefile.new"), path("Makefile"));
229 * Read in the information about files used in making the system.
230 * Store it in the ftab linked list.
236 struct file_list
*tp
, *pf
;
238 struct device
*save_dp
;
240 char *wd
, *this, *needs
, *special
, *depends
, *clean
, *warning
;
241 char fname
[MAXPATHLEN
];
243 int nreqs
, first
= 1, configdep
, isdup
, std
, filetype
,
244 imp_rule
, no_obj
, before_depend
, nowerror
, mandatory
;
249 printf("no ident line specified\n");
252 snprintf(fname
, sizeof(fname
), "../conf/files");
254 fp
= fopen(fname
, "r");
259 * filename [ standard | mandatory | optional ] [ config-dependent ]
260 * [ dev* | profiling-routine ] [ no-obj ]
261 * [ compile-with "compile rule" [no-implicit-rule] ]
262 * [ dependency "dependency-list"] [ before-depend ]
263 * [ clean "file-list"] [ warning "text warning" ]
266 if (wd
== (char *)EOF
) {
270 snprintf(fname
, sizeof(fname
),
271 "../platform/%s/conf/files",
273 fp
= fopen(fname
, "r");
276 snprintf(fname
, sizeof(fname
),
277 "files.%s", platformname
);
282 snprintf(fname
, sizeof(fname
),
283 "files.%s", raisestr(ident
));
284 fp
= fopen(fname
, "r");
294 while (((wd
= get_word(fp
)) != (char *)EOF
) && wd
)
301 printf("%s: No type for %s.\n",
305 if ((pf
= fl_lookup(this)) && (pf
->f_type
!= INVISIBLE
|| pf
->f_flags
))
310 if (first
== 3 && pf
== NULL
&& (tp
= fltail_lookup(this)) != NULL
) {
311 if (tp
->f_type
!= INVISIBLE
|| tp
->f_flags
)
312 printf("%s: Local file %s overrides %s.\n",
313 fname
, this, tp
->f_fn
);
315 printf("%s: Local file %s could override %s"
316 " with a different kernel configuration.\n",
317 fname
, this, tp
->f_fn
);
326 std
= mandatory
= nonoptional
= 0;
332 if (strcmp(wd
, "standard") == 0) {
334 } else if (strcmp(wd
, "mandatory") == 0) {
336 * If an entry is marked "mandatory", config will abort if
337 * it's not called by a configuration line in the config
338 * file. Apart from this, the device is handled like one
342 } else if (strcmp(wd
, "nonoptional") == 0) {
344 } else if (strcmp(wd
, "optional") == 0) {
345 /* don't need to do anything */
347 printf("%s: %s must be optional, mandatory or standard\n",
349 printf("Alternatively, your version of config(8) may be out of sync with your\nkernel source.\n");
356 if (strcmp(wd
, "config-dependent") == 0) {
360 if (strcmp(wd
, "no-obj") == 0) {
364 if (strcmp(wd
, "no-implicit-rule") == 0) {
365 if (special
== NULL
) {
366 printf("%s: alternate rule required when "
367 "\"no-implicit-rule\" is specified.\n",
373 if (strcmp(wd
, "before-depend") == 0) {
377 if (strcmp(wd
, "dependency") == 0) {
378 next_quoted_word(fp
, wd
);
380 printf("%s: %s missing compile command string.\n",
384 depends
= strdup(wd
);
387 if (strcmp(wd
, "clean") == 0) {
388 next_quoted_word(fp
, wd
);
390 printf("%s: %s missing clean file list.\n",
397 if (strcmp(wd
, "compile-with") == 0) {
398 next_quoted_word(fp
, wd
);
400 printf("%s: %s missing compile command string.\n",
404 special
= strdup(wd
);
407 if (strcmp(wd
, "nowerror") == 0) {
411 if (strcmp(wd
, "warning") == 0) {
412 next_quoted_word(fp
, wd
);
414 printf("%s: %s missing warning text string.\n",
418 warning
= strdup(wd
);
422 if (strcmp(wd
, "local") == 0) {
426 if (strcmp(wd
, "no-depend") == 0) {
430 if (strcmp(wd
, "device-driver") == 0) {
431 printf("%s: `device-driver' flag obsolete.\n", fname
);
434 if (strcmp(wd
, "profiling-routine") == 0) {
435 filetype
= PROFILING
;
438 if (needs
== 0 && nreqs
== 1)
442 for (dp
= dtab
; dp
!= NULL
; save_dp
= dp
, dp
= dp
->d_next
)
443 if (strcmp(dp
->d_name
, wd
) == 0) {
444 if (std
&& dp
->d_type
== PSEUDO_DEVICE
&&
450 printf("%s: mandatory device \"%s\" not found\n",
455 dp
= malloc(sizeof(*dp
));
456 bzero(dp
, sizeof(*dp
));
458 dp
->d_name
= strdup(wd
);
459 dp
->d_type
= PSEUDO_DEVICE
;
461 save_dp
->d_next
= dp
;
464 for (op
= opt
; op
!= NULL
; op
= op
->op_next
) {
465 if (op
->op_value
== 0 && opteq(op
->op_name
, wd
)) {
474 printf("%s: the option \"%s\" MUST be specified\n",
479 while ((wd
= get_word(fp
)) != 0)
484 tp
->f_type
= INVISIBLE
;
487 tp
->f_special
= special
;
488 tp
->f_depends
= depends
;
490 tp
->f_warn
= warning
;
494 if (std
== 0 && nreqs
== 0) {
495 printf("%s: what is %s optional on?\n",
501 printf("%s: syntax error describing %s\n",
505 if (filetype
== PROFILING
&& profiling
== 0)
510 tp
->f_type
= filetype
;
513 tp
->f_flags
|= CONFIGDEP
;
515 tp
->f_flags
|= NO_IMPLCT_RULE
;
517 tp
->f_flags
|= NO_OBJ
;
519 tp
->f_flags
|= BEFORE_DEPEND
;
521 tp
->f_flags
|= NOWERROR
;
523 tp
->f_flags
|= NO_IMPLCT_RULE
;
525 tp
->f_flags
|= NO_OBJ
;
527 tp
->f_special
= special
;
528 tp
->f_depends
= depends
;
530 tp
->f_warn
= warning
;
531 if (pf
&& pf
->f_type
== INVISIBLE
)
532 pf
->f_flags
= 1; /* mark as duplicate */
537 opteq(char *cp
, char *dp
)
541 for (;; cp
++, dp
++) {
543 c
= isupper(*cp
) ? tolower(*cp
) : *cp
;
544 d
= isupper(*dp
) ? tolower(*dp
) : *dp
;
554 do_before_depend(FILE *fp
)
556 struct file_list
*tp
;
559 fputs("BEFORE_DEPEND=", fp
);
561 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
562 if (tp
->f_flags
& BEFORE_DEPEND
) {
563 len
= strlen(tp
->f_fn
);
564 if ((len
= 3 + len
) + lpos
> 72) {
568 if (tp
->f_flags
& NO_IMPLCT_RULE
)
569 fprintf(fp
, "%s ", tp
->f_fn
);
571 fprintf(fp
, "$S/%s ", tp
->f_fn
);
581 struct file_list
*tp
;
585 fprintf(fp
, "OBJS=");
587 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
) {
588 if (tp
->f_type
== INVISIBLE
|| tp
->f_flags
& NO_OBJ
)
591 cp
= sp
+ (len
= strlen(sp
)) - 1;
594 if (len
+ lpos
> 72) {
596 fprintf(fp
, "\\\n\t");
598 fprintf(fp
, "%s ", sp
);
609 struct file_list
*tp
;
612 fputs("CFILES=", fp
);
614 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
615 if (tp
->f_type
!= INVISIBLE
&& tp
->f_type
!= NODEPEND
) {
616 len
= strlen(tp
->f_fn
);
617 if (tp
->f_fn
[len
- 1] != 'c')
619 if ((len
= 3 + len
) + lpos
> 72) {
623 if (tp
->f_type
!= LOCAL
)
624 fprintf(fp
, "$S/%s ", tp
->f_fn
);
626 fprintf(fp
, "%s ", tp
->f_fn
);
637 struct file_list
*tp
;
640 fputs("MFILES=", fp
);
642 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
643 if (tp
->f_type
!= INVISIBLE
) {
644 len
= strlen(tp
->f_fn
);
645 if (tp
->f_fn
[len
- 1] != 'm' || tp
->f_fn
[len
- 2] != '.')
647 if ((len
= 3 + len
) + lpos
> 72) {
651 fprintf(fp
, "$S/%s ", tp
->f_fn
);
661 struct file_list
*tp
;
664 fputs("SFILES=", fp
);
666 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
667 if (tp
->f_type
!= INVISIBLE
) {
668 len
= strlen(tp
->f_fn
);
669 if (tp
->f_fn
[len
- 1] != 'S' && tp
->f_fn
[len
- 1] != 's')
671 if ((len
= 3 + len
) + lpos
> 72) {
675 fprintf(fp
, "$S/%s ", tp
->f_fn
);
688 cp
= strrchr(fn
, '/');
695 * Create the makerules for each file
696 * which is part of the system.
697 * Devices are processed with the special c2 option -i
698 * which avoids any problem areas with i/o addressing
699 * (e.g. for the VAX); assembler files are processed by as.
704 char *cp
, *np
, och
, *tp
;
705 struct file_list
*ftp
;
708 for (ftp
= ftab
; ftp
!= NULL
; ftp
= ftp
->f_next
) {
709 if (ftp
->f_type
== INVISIBLE
)
711 if (ftp
->f_warn
!= NULL
)
712 printf("WARNING: %s\n", ftp
->f_warn
);
713 cp
= (np
= ftp
->f_fn
) + strlen(ftp
->f_fn
) - 1;
715 if (ftp
->f_flags
& NO_IMPLCT_RULE
) {
717 fprintf(f
, "%s: %s\n", np
, ftp
->f_depends
);
719 fprintf(f
, "%s: \n", np
);
724 fprintf(f
, "%so:\n\t-cp $S/%so .\n\n",
729 fprintf(f
, "%so: $S/%s%c %s\n", tail(np
),
730 np
, och
, ftp
->f_depends
);
732 fprintf(f
, "%so: $S/%s%c\n", tail(np
),
736 special
= ftp
->f_special
;
737 if (special
== NULL
) {
738 const char *ftype
= NULL
;
739 static char cmd
[128];
741 switch (ftp
->f_type
) {
754 printf("config: don't know rules for %s\n", np
);
757 snprintf(cmd
, sizeof(cmd
), "${%s_%c%s}%s",
759 ftp
->f_flags
& CONFIGDEP
? "_C" : "",
760 ftp
->f_flags
& NOWERROR
? "" : " ${WERROR}");
764 fprintf(f
, "\t%s\n\n", special
);
771 struct file_list
*tp
;
776 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
778 len
= strlen(tp
->f_clean
);
779 if (len
+ lpos
> 72) {
783 fprintf(fp
, "%s ", tp
->f_clean
);
797 *str
= toupper(*str
);