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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * @(#)mkmakefile.c 8.1 (Berkeley) 6/6/93
30 * $FreeBSD: src/usr.sbin/config/mkmakefile.c,v 1.51.2.3 2001/01/23 00:09:32 peter Exp $
34 * Build the makefile for the system, from
35 * the information in the 'files' files and the
36 * additional files for the machine being compiled to.
43 #include <sys/param.h>
46 #include "configvers.h"
48 #define next_word(fp, wd) \
52 word = get_word(fp); \
53 if (word == (char *)EOF) \
58 #define next_quoted_word(fp, wd) \
62 word = get_quoted_word(fp); \
63 if (word == (char *)EOF) \
69 static struct file_list
*fcur
;
71 static char *tail(char *);
72 static void do_clean(FILE *);
73 static void do_rules(FILE *);
74 static void do_sfiles(FILE *);
75 static void do_mfiles(FILE *);
76 static void do_cfiles(FILE *);
77 static void do_objs(FILE *);
78 static void do_before_depend(FILE *);
79 static int opteq(char *, char *);
80 static void read_files(void);
83 * Lookup a file, by name.
85 static struct file_list
*
90 for (fp
= ftab
; fp
!= NULL
; fp
= fp
->f_next
) {
91 if (strcmp(fp
->f_fn
, file
) == 0)
98 * Lookup a file, by final component name.
100 static struct file_list
*
101 fltail_lookup(char *file
)
103 struct file_list
*fp
;
105 for (fp
= ftab
; fp
!= NULL
; fp
= fp
->f_next
) {
106 if (strcmp(tail(fp
->f_fn
), tail(file
)) == 0)
113 * Make a new file list entry
115 static struct file_list
*
118 struct file_list
*fp
;
120 fp
= malloc(sizeof(*fp
));
121 bzero(fp
, sizeof(*fp
));
131 * Build the makefile from the skeleton
142 snprintf(line
, sizeof(line
), "../platform/%s/conf/Makefile",
144 ifp
= fopen(line
, "r");
146 snprintf(line
, sizeof(line
), "Makefile.%s", platformname
);
147 ifp
= fopen(line
, "r");
151 ofp
= fopen(path("Makefile.new"), "w");
153 err(1, "%s", path("Makefile.new"));
154 fprintf(ofp
, "KERN_IDENT=%s\n", raisestr(ident
));
155 fprintf(ofp
, "MACHINE_PLATFORM=%s\n", platformname
);
156 fprintf(ofp
, "MACHINE=%s\n", machinename
);
157 fprintf(ofp
, "MACHINE_ARCH=%s\n", machinearchname
);
158 fprintf(ofp
, ".export MACHINE_PLATFORM\n");
159 fprintf(ofp
, ".export MACHINE\n");
160 fprintf(ofp
, ".export MACHINE_ARCH\n");
161 fprintf(ofp
, "IDENT=");
163 /* Don't compile kernel profiling code for vkernel */
164 if (strncmp(platformname
, "vkernel", 6) != 0)
165 fprintf(ofp
, " -DGPROF");
169 printf("cpu type must be specified\n");
173 for (op
= mkopt
; op
!= NULL
; op
= op
->op_next
)
174 fprintf(ofp
, "%s=%s\n", op
->op_name
, op
->op_value
);
176 fprintf(ofp
, "DEBUG=-g\n");
178 fprintf(ofp
, "PROF=-pg\n");
179 fprintf(ofp
, "PROFLEVEL=%d\n", profiling
);
182 fprintf(ofp
,"S=%s\n", srcdir
);
183 while (fgets(line
, BUFSIZ
, ifp
) != 0) {
185 fprintf(ofp
, "%s", line
);
188 if (strcmp(line
, "%BEFORE_DEPEND\n") == 0)
189 do_before_depend(ofp
);
190 else if (strcmp(line
, "%OBJS\n") == 0)
192 else if (strcmp(line
, "%MFILES\n") == 0)
194 else if (strcmp(line
, "%CFILES\n") == 0)
196 else if (strcmp(line
, "%SFILES\n") == 0)
198 else if (strcmp(line
, "%RULES\n") == 0)
200 else if (strcmp(line
, "%CLEAN\n") == 0)
202 else if (strncmp(line
, "%VERSREQ=", sizeof("%VERSREQ=") - 1) == 0) {
203 versreq
= atoi(line
+ sizeof("%VERSREQ=") - 1);
204 if (versreq
!= CONFIGVERS
) {
205 fprintf(stderr
, "ERROR: version of config(8) does not match kernel!\n");
206 fprintf(stderr
, "config version = %d, ", CONFIGVERS
);
207 fprintf(stderr
, "version required = %d\n\n", versreq
);
208 fprintf(stderr
, "Make sure that /usr/src/usr.sbin/config is in sync\n");
209 fprintf(stderr
, "with your /usr/src/sys and install a new config binary\n");
210 fprintf(stderr
, "before trying this again.\n\n");
211 fprintf(stderr
, "If running the new config fails check your config\n");
212 fprintf(stderr
, "file against the GENERIC or LINT config files for\n");
213 fprintf(stderr
, "changes in config syntax, or option/device naming\n");
214 fprintf(stderr
, "conventions\n\n");
219 "Unknown %% construct in generic makefile: %s",
224 moveifchanged(path("Makefile.new"), path("Makefile"));
228 * Read in the information about files used in making the system.
229 * Store it in the ftab linked list.
235 struct file_list
*tp
, *pf
;
237 struct device
*save_dp
;
239 char *wd
, *this, *needs
, *special
, *depends
, *clean
, *warning
;
240 char fname
[MAXPATHLEN
];
242 int nreqs
, first
= 1, configdep
, isdup
, std
, filetype
,
243 imp_rule
, no_obj
, before_depend
, nowerror
, mandatory
;
248 printf("no ident line specified\n");
251 snprintf(fname
, sizeof(fname
), "../conf/files");
253 fp
= fopen(fname
, "r");
258 * filename [ standard | mandatory | optional ] [ config-dependent ]
259 * [ dev* | profiling-routine ] [ no-obj ]
260 * [ compile-with "compile rule" [no-implicit-rule] ]
261 * [ dependency "dependency-list"] [ before-depend ]
262 * [ clean "file-list"] [ warning "text warning" ]
265 if (wd
== (char *)EOF
) {
269 snprintf(fname
, sizeof(fname
),
270 "../platform/%s/conf/files",
272 fp
= fopen(fname
, "r");
275 snprintf(fname
, sizeof(fname
),
276 "files.%s", platformname
);
281 snprintf(fname
, sizeof(fname
),
282 "files.%s", raisestr(ident
));
283 fp
= fopen(fname
, "r");
293 while (((wd
= get_word(fp
)) != (char *)EOF
) && wd
)
300 printf("%s: No type for %s.\n",
304 if ((pf
= fl_lookup(this)) && (pf
->f_type
!= INVISIBLE
|| pf
->f_flags
))
309 if (first
== 3 && pf
== NULL
&& (tp
= fltail_lookup(this)) != NULL
) {
310 if (tp
->f_type
!= INVISIBLE
|| tp
->f_flags
)
311 printf("%s: Local file %s overrides %s.\n",
312 fname
, this, tp
->f_fn
);
314 printf("%s: Local file %s could override %s"
315 " with a different kernel configuration.\n",
316 fname
, this, tp
->f_fn
);
325 std
= mandatory
= nonoptional
= 0;
331 if (strcmp(wd
, "standard") == 0) {
333 } else if (strcmp(wd
, "mandatory") == 0) {
335 * If an entry is marked "mandatory", config will abort if
336 * it's not called by a configuration line in the config
337 * file. Apart from this, the device is handled like one
341 } else if (strcmp(wd
, "nonoptional") == 0) {
343 } else if (strcmp(wd
, "optional") == 0) {
344 /* don't need to do anything */
346 printf("%s: %s must be optional, mandatory or standard\n",
348 printf("Alternatively, your version of config(8) may be out of sync with your\nkernel source.\n");
355 if (strcmp(wd
, "config-dependent") == 0) {
359 if (strcmp(wd
, "no-obj") == 0) {
363 if (strcmp(wd
, "no-implicit-rule") == 0) {
364 if (special
== NULL
) {
365 printf("%s: alternate rule required when "
366 "\"no-implicit-rule\" is specified.\n",
372 if (strcmp(wd
, "before-depend") == 0) {
376 if (strcmp(wd
, "dependency") == 0) {
377 next_quoted_word(fp
, wd
);
379 printf("%s: %s missing compile command string.\n",
383 depends
= strdup(wd
);
386 if (strcmp(wd
, "clean") == 0) {
387 next_quoted_word(fp
, wd
);
389 printf("%s: %s missing clean file list.\n",
396 if (strcmp(wd
, "compile-with") == 0) {
397 next_quoted_word(fp
, wd
);
399 printf("%s: %s missing compile command string.\n",
403 special
= strdup(wd
);
406 if (strcmp(wd
, "nowerror") == 0) {
410 if (strcmp(wd
, "warning") == 0) {
411 next_quoted_word(fp
, wd
);
413 printf("%s: %s missing warning text string.\n",
417 warning
= strdup(wd
);
421 if (strcmp(wd
, "local") == 0) {
425 if (strcmp(wd
, "no-depend") == 0) {
429 if (strcmp(wd
, "device-driver") == 0) {
430 printf("%s: `device-driver' flag obsolete.\n", fname
);
433 if (strcmp(wd
, "profiling-routine") == 0) {
434 filetype
= PROFILING
;
437 if (needs
== NULL
&& nreqs
== 1)
441 for (dp
= dtab
; dp
!= NULL
; save_dp
= dp
, dp
= dp
->d_next
)
442 if (strcmp(dp
->d_name
, wd
) == 0) {
443 if (std
&& dp
->d_type
== PSEUDO_DEVICE
&&
449 printf("%s: mandatory device \"%s\" not found\n",
454 dp
= malloc(sizeof(*dp
));
455 bzero(dp
, sizeof(*dp
));
457 dp
->d_name
= strdup(wd
);
458 dp
->d_type
= PSEUDO_DEVICE
;
460 save_dp
->d_next
= dp
;
463 for (op
= opt
; op
!= NULL
; op
= op
->op_next
) {
464 if (op
->op_value
== 0 && opteq(op
->op_name
, wd
)) {
473 printf("%s: the option \"%s\" MUST be specified\n",
478 while ((wd
= get_word(fp
)) != NULL
)
483 tp
->f_type
= INVISIBLE
;
486 tp
->f_special
= special
;
487 tp
->f_depends
= depends
;
489 tp
->f_warn
= warning
;
493 if (std
== 0 && nreqs
== 0) {
494 printf("%s: what is %s optional on?\n",
500 printf("%s: syntax error describing %s\n",
504 if (filetype
== PROFILING
&& profiling
== 0)
509 tp
->f_type
= filetype
;
512 tp
->f_flags
|= CONFIGDEP
;
514 tp
->f_flags
|= NO_IMPLCT_RULE
;
516 tp
->f_flags
|= NO_OBJ
;
518 tp
->f_flags
|= BEFORE_DEPEND
;
520 tp
->f_flags
|= NOWERROR
;
522 tp
->f_flags
|= NO_IMPLCT_RULE
;
524 tp
->f_flags
|= NO_OBJ
;
526 tp
->f_special
= special
;
527 tp
->f_depends
= depends
;
529 tp
->f_warn
= warning
;
530 if (pf
&& pf
->f_type
== INVISIBLE
)
531 pf
->f_flags
= 1; /* mark as duplicate */
536 opteq(char *cp
, char *dp
)
540 for (;; cp
++, dp
++) {
542 c
= isupper(*cp
) ? tolower(*cp
) : *cp
;
543 d
= isupper(*dp
) ? tolower(*dp
) : *dp
;
553 do_before_depend(FILE *fp
)
555 struct file_list
*tp
;
558 fputs("BEFORE_DEPEND=", fp
);
560 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
561 if (tp
->f_flags
& BEFORE_DEPEND
) {
562 len
= strlen(tp
->f_fn
);
563 if ((len
= 3 + len
) + lpos
> 72) {
567 if (tp
->f_flags
& NO_IMPLCT_RULE
)
568 fprintf(fp
, "%s ", tp
->f_fn
);
570 fprintf(fp
, "$S/%s ", tp
->f_fn
);
580 struct file_list
*tp
;
584 fprintf(fp
, "OBJS=");
586 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
) {
587 if (tp
->f_type
== INVISIBLE
|| tp
->f_flags
& NO_OBJ
)
590 cp
= sp
+ (len
= strlen(sp
)) - 1;
593 if (len
+ lpos
> 72) {
595 fprintf(fp
, "\\\n\t");
597 fprintf(fp
, "%s ", sp
);
608 struct file_list
*tp
;
611 fputs("CFILES=", fp
);
613 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
614 if (tp
->f_type
!= INVISIBLE
&& tp
->f_type
!= NODEPEND
) {
615 len
= strlen(tp
->f_fn
);
616 if (tp
->f_fn
[len
- 1] != 'c')
618 if ((len
= 3 + len
) + lpos
> 72) {
622 if (tp
->f_type
!= LOCAL
)
623 fprintf(fp
, "$S/%s ", tp
->f_fn
);
625 fprintf(fp
, "%s ", tp
->f_fn
);
636 struct file_list
*tp
;
639 fputs("MFILES=", fp
);
641 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
642 if (tp
->f_type
!= INVISIBLE
) {
643 len
= strlen(tp
->f_fn
);
644 if (tp
->f_fn
[len
- 1] != 'm' || tp
->f_fn
[len
- 2] != '.')
646 if ((len
= 3 + len
) + lpos
> 72) {
650 fprintf(fp
, "$S/%s ", tp
->f_fn
);
660 struct file_list
*tp
;
663 fputs("SFILES=", fp
);
665 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
666 if (tp
->f_type
!= INVISIBLE
) {
667 len
= strlen(tp
->f_fn
);
668 if (tp
->f_fn
[len
- 1] != 'S' && tp
->f_fn
[len
- 1] != 's')
670 if ((len
= 3 + len
) + lpos
> 72) {
674 fprintf(fp
, "$S/%s ", tp
->f_fn
);
687 cp
= strrchr(fn
, '/');
694 * Create the makerules for each file
695 * which is part of the system.
696 * Devices are processed with the special c2 option -i
697 * which avoids any problem areas with i/o addressing
698 * (e.g. for the VAX); assembler files are processed by as.
704 struct file_list
*ftp
;
707 for (ftp
= ftab
; ftp
!= NULL
; ftp
= ftp
->f_next
) {
708 if (ftp
->f_type
== INVISIBLE
)
710 if (ftp
->f_warn
!= NULL
)
711 printf("WARNING: %s\n", ftp
->f_warn
);
712 cp
= (np
= ftp
->f_fn
) + strlen(ftp
->f_fn
) - 1;
714 if (ftp
->f_flags
& NO_IMPLCT_RULE
) {
716 fprintf(f
, "%s: %s\n", np
, ftp
->f_depends
);
718 fprintf(f
, "%s: \n", np
);
723 fprintf(f
, "%so:\n\t-cp $S/%so .\n\n",
728 fprintf(f
, "%so: $S/%s%c %s\n", tail(np
),
729 np
, och
, ftp
->f_depends
);
731 fprintf(f
, "%so: $S/%s%c\n", tail(np
),
734 special
= ftp
->f_special
;
735 if (special
== NULL
) {
736 const char *ftype
= NULL
;
737 static char cmd
[128];
739 switch (ftp
->f_type
) {
752 printf("config: don't know rules for %s\n", np
);
755 snprintf(cmd
, sizeof(cmd
), "${%s_%c%s}%s",
757 ftp
->f_flags
& CONFIGDEP
? "_C" : "",
758 ftp
->f_flags
& NOWERROR
? "" : " ${WERROR}");
762 fprintf(f
, "\t%s\n\n", special
);
769 struct file_list
*tp
;
774 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
776 len
= strlen(tp
->f_clean
);
777 if (len
+ lpos
> 72) {
781 fprintf(fp
, "%s ", tp
->f_clean
);
795 *str
= toupper(*str
);