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=");
164 printf("cpu type must be specified\n");
168 for (op
= mkopt
; op
!= NULL
; op
= op
->op_next
)
169 fprintf(ofp
, "%s=%s\n", op
->op_name
, op
->op_value
);
171 fprintf(ofp
, "DEBUG=-g\n");
173 fprintf(ofp
,"S=%s\n", srcdir
);
174 while (fgets(line
, BUFSIZ
, ifp
) != 0) {
176 fprintf(ofp
, "%s", line
);
179 if (strcmp(line
, "%BEFORE_DEPEND\n") == 0)
180 do_before_depend(ofp
);
181 else if (strcmp(line
, "%OBJS\n") == 0)
183 else if (strcmp(line
, "%MFILES\n") == 0)
185 else if (strcmp(line
, "%CFILES\n") == 0)
187 else if (strcmp(line
, "%SFILES\n") == 0)
189 else if (strcmp(line
, "%RULES\n") == 0)
191 else if (strcmp(line
, "%CLEAN\n") == 0)
193 else if (strncmp(line
, "%VERSREQ=", sizeof("%VERSREQ=") - 1) == 0) {
194 versreq
= atoi(line
+ sizeof("%VERSREQ=") - 1);
195 if (versreq
!= CONFIGVERS
) {
196 fprintf(stderr
, "ERROR: version of config(8) does not match kernel!\n");
197 fprintf(stderr
, "config version = %d, ", CONFIGVERS
);
198 fprintf(stderr
, "version required = %d\n\n", versreq
);
199 fprintf(stderr
, "Make sure that /usr/src/usr.sbin/config is in sync\n");
200 fprintf(stderr
, "with your /usr/src/sys and install a new config binary\n");
201 fprintf(stderr
, "before trying this again.\n\n");
202 fprintf(stderr
, "If running the new config fails check your config\n");
203 fprintf(stderr
, "file against the GENERIC or LINT config files for\n");
204 fprintf(stderr
, "changes in config syntax, or option/device naming\n");
205 fprintf(stderr
, "conventions\n\n");
210 "Unknown %% construct in generic makefile: %s",
215 moveifchanged(path("Makefile.new"), path("Makefile"));
219 * Read in the information about files used in making the system.
220 * Store it in the ftab linked list.
226 struct file_list
*tp
, *pf
;
228 struct device
*save_dp
;
230 char *wd
, *this, *needs
, *special
, *depends
, *clean
, *warning
;
231 char fname
[MAXPATHLEN
];
233 int nreqs
, first
= 1, configdep
, isdup
, std
, filetype
,
234 imp_rule
, no_obj
, before_depend
, nowerror
, mandatory
;
239 printf("no ident line specified\n");
242 snprintf(fname
, sizeof(fname
), "../conf/files");
244 fp
= fopen(fname
, "r");
249 * filename [ standard | mandatory | optional ] [ config-dependent ]
250 * [ dev* ] [ no-obj ]
251 * [ compile-with "compile rule" [no-implicit-rule] ]
252 * [ dependency "dependency-list"] [ before-depend ]
253 * [ clean "file-list"] [ warning "text warning" ]
256 if (wd
== (char *)EOF
) {
260 snprintf(fname
, sizeof(fname
),
261 "../platform/%s/conf/files",
263 fp
= fopen(fname
, "r");
266 snprintf(fname
, sizeof(fname
),
267 "files.%s", platformname
);
272 snprintf(fname
, sizeof(fname
),
273 "files.%s", raisestr(ident
));
274 fp
= fopen(fname
, "r");
284 while (((wd
= get_word(fp
)) != (char *)EOF
) && wd
)
291 printf("%s: No type for %s.\n",
295 if ((pf
= fl_lookup(this)) && (pf
->f_type
!= INVISIBLE
|| pf
->f_flags
))
300 if (first
== 3 && pf
== NULL
&& (tp
= fltail_lookup(this)) != NULL
) {
301 if (tp
->f_type
!= INVISIBLE
|| tp
->f_flags
)
302 printf("%s: Local file %s overrides %s.\n",
303 fname
, this, tp
->f_fn
);
305 printf("%s: Local file %s could override %s"
306 " with a different kernel configuration.\n",
307 fname
, this, tp
->f_fn
);
316 std
= mandatory
= nonoptional
= 0;
322 if (strcmp(wd
, "standard") == 0) {
324 } else if (strcmp(wd
, "mandatory") == 0) {
326 * If an entry is marked "mandatory", config will abort if
327 * it's not called by a configuration line in the config
328 * file. Apart from this, the device is handled like one
332 } else if (strcmp(wd
, "nonoptional") == 0) {
334 } else if (strcmp(wd
, "optional") == 0) {
335 /* don't need to do anything */
337 printf("%s: %s must be optional, mandatory or standard\n",
339 printf("Alternatively, your version of config(8) may be out of sync with your\nkernel source.\n");
346 if (strcmp(wd
, "config-dependent") == 0) {
350 if (strcmp(wd
, "no-obj") == 0) {
354 if (strcmp(wd
, "no-implicit-rule") == 0) {
355 if (special
== NULL
) {
356 printf("%s: alternate rule required when "
357 "\"no-implicit-rule\" is specified.\n",
363 if (strcmp(wd
, "before-depend") == 0) {
367 if (strcmp(wd
, "dependency") == 0) {
368 next_quoted_word(fp
, wd
);
370 printf("%s: %s missing compile command string.\n",
374 depends
= strdup(wd
);
377 if (strcmp(wd
, "clean") == 0) {
378 next_quoted_word(fp
, wd
);
380 printf("%s: %s missing clean file list.\n",
387 if (strcmp(wd
, "compile-with") == 0) {
388 next_quoted_word(fp
, wd
);
390 printf("%s: %s missing compile command string.\n",
394 special
= strdup(wd
);
397 if (strcmp(wd
, "nowerror") == 0) {
401 if (strcmp(wd
, "warning") == 0) {
402 next_quoted_word(fp
, wd
);
404 printf("%s: %s missing warning text string.\n",
408 warning
= strdup(wd
);
412 if (strcmp(wd
, "local") == 0) {
416 if (strcmp(wd
, "no-depend") == 0) {
420 if (strcmp(wd
, "device-driver") == 0) {
421 printf("%s: `device-driver' flag obsolete.\n", fname
);
424 if (needs
== NULL
&& nreqs
== 1)
428 for (dp
= dtab
; dp
!= NULL
; save_dp
= dp
, dp
= dp
->d_next
)
429 if (strcmp(dp
->d_name
, wd
) == 0) {
430 if (std
&& dp
->d_type
== PSEUDO_DEVICE
&&
436 printf("%s: mandatory device \"%s\" not found\n",
441 dp
= malloc(sizeof(*dp
));
442 bzero(dp
, sizeof(*dp
));
444 dp
->d_name
= strdup(wd
);
445 dp
->d_type
= PSEUDO_DEVICE
;
447 save_dp
->d_next
= dp
;
450 for (op
= opt
; op
!= NULL
; op
= op
->op_next
) {
451 if (op
->op_value
== 0 && opteq(op
->op_name
, wd
)) {
460 printf("%s: the option \"%s\" MUST be specified\n",
465 while ((wd
= get_word(fp
)) != NULL
)
470 tp
->f_type
= INVISIBLE
;
473 tp
->f_special
= special
;
474 tp
->f_depends
= depends
;
476 tp
->f_warn
= warning
;
480 if (std
== 0 && nreqs
== 0) {
481 printf("%s: what is %s optional on?\n",
487 printf("%s: syntax error describing %s\n",
494 tp
->f_type
= filetype
;
497 tp
->f_flags
|= CONFIGDEP
;
499 tp
->f_flags
|= NO_IMPLCT_RULE
;
501 tp
->f_flags
|= NO_OBJ
;
503 tp
->f_flags
|= BEFORE_DEPEND
;
505 tp
->f_flags
|= NOWERROR
;
507 tp
->f_flags
|= NO_IMPLCT_RULE
;
509 tp
->f_flags
|= NO_OBJ
;
511 tp
->f_special
= special
;
512 tp
->f_depends
= depends
;
514 tp
->f_warn
= warning
;
515 if (pf
&& pf
->f_type
== INVISIBLE
)
516 pf
->f_flags
= 1; /* mark as duplicate */
521 opteq(char *cp
, char *dp
)
525 for (;; cp
++, dp
++) {
527 c
= isupper(*cp
) ? tolower(*cp
) : *cp
;
528 d
= isupper(*dp
) ? tolower(*dp
) : *dp
;
538 do_before_depend(FILE *fp
)
540 struct file_list
*tp
;
543 fputs("BEFORE_DEPEND=", fp
);
545 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
546 if (tp
->f_flags
& BEFORE_DEPEND
) {
547 len
= strlen(tp
->f_fn
);
548 if ((len
= 3 + len
) + lpos
> 72) {
552 if (tp
->f_flags
& NO_IMPLCT_RULE
)
553 fprintf(fp
, "%s ", tp
->f_fn
);
555 fprintf(fp
, "$S/%s ", tp
->f_fn
);
565 struct file_list
*tp
;
569 fprintf(fp
, "OBJS=");
571 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
) {
572 if (tp
->f_type
== INVISIBLE
|| tp
->f_flags
& NO_OBJ
)
575 cp
= sp
+ (len
= strlen(sp
)) - 1;
578 if (len
+ lpos
> 72) {
580 fprintf(fp
, "\\\n\t");
582 fprintf(fp
, "%s ", sp
);
593 struct file_list
*tp
;
596 fputs("CFILES=", fp
);
598 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
599 if (tp
->f_type
!= INVISIBLE
&& tp
->f_type
!= NODEPEND
) {
600 len
= strlen(tp
->f_fn
);
601 if (tp
->f_fn
[len
- 1] != 'c')
603 if ((len
= 3 + len
) + lpos
> 72) {
607 if (tp
->f_type
!= LOCAL
)
608 fprintf(fp
, "$S/%s ", tp
->f_fn
);
610 fprintf(fp
, "%s ", tp
->f_fn
);
621 struct file_list
*tp
;
624 fputs("MFILES=", fp
);
626 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
627 if (tp
->f_type
!= INVISIBLE
) {
628 len
= strlen(tp
->f_fn
);
629 if (tp
->f_fn
[len
- 1] != 'm' || tp
->f_fn
[len
- 2] != '.')
631 if ((len
= 3 + len
) + lpos
> 72) {
635 fprintf(fp
, "$S/%s ", tp
->f_fn
);
645 struct file_list
*tp
;
648 fputs("SFILES=", fp
);
650 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
651 if (tp
->f_type
!= INVISIBLE
) {
652 len
= strlen(tp
->f_fn
);
653 if (tp
->f_fn
[len
- 1] != 'S' && tp
->f_fn
[len
- 1] != 's')
655 if ((len
= 3 + len
) + lpos
> 72) {
659 fprintf(fp
, "$S/%s ", tp
->f_fn
);
672 cp
= strrchr(fn
, '/');
679 * Create the makerules for each file
680 * which is part of the system.
681 * Devices are processed with the special c2 option -i
682 * which avoids any problem areas with i/o addressing
683 * (e.g. for the VAX); assembler files are processed by as.
689 struct file_list
*ftp
;
692 for (ftp
= ftab
; ftp
!= NULL
; ftp
= ftp
->f_next
) {
693 if (ftp
->f_type
== INVISIBLE
)
695 if (ftp
->f_warn
!= NULL
)
696 printf("WARNING: %s\n", ftp
->f_warn
);
697 cp
= (np
= ftp
->f_fn
) + strlen(ftp
->f_fn
) - 1;
699 if (ftp
->f_flags
& NO_IMPLCT_RULE
) {
701 fprintf(f
, "%s: %s\n", np
, ftp
->f_depends
);
703 fprintf(f
, "%s: \n", np
);
708 fprintf(f
, "%so:\n\t-cp $S/%so .\n\n",
713 fprintf(f
, "%so: $S/%s%c %s\n", tail(np
),
714 np
, och
, ftp
->f_depends
);
716 fprintf(f
, "%so: $S/%s%c\n", tail(np
),
719 special
= ftp
->f_special
;
720 if (special
== NULL
) {
721 const char *ftype
= NULL
;
722 static char cmd
[128];
724 switch (ftp
->f_type
) {
731 printf("config: don't know rules for %s\n", np
);
734 snprintf(cmd
, sizeof(cmd
), "${%s_%c%s}%s",
736 ftp
->f_flags
& CONFIGDEP
? "_C" : "",
737 ftp
->f_flags
& NOWERROR
? "" : " ${WERROR}");
741 fprintf(f
, "\t%s\n\n", special
);
748 struct file_list
*tp
;
753 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
755 len
= strlen(tp
->f_clean
);
756 if (len
+ lpos
> 72) {
760 fprintf(fp
, "%s ", tp
->f_clean
);
774 *str
= toupper(*str
);