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
, ".if defined(.PARSEDIR)\n");
163 fprintf(ofp
, ".export MACHINE_PLATFORM\n");
164 fprintf(ofp
, ".export MACHINE\n");
165 fprintf(ofp
, ".export MACHINE_ARCH\n");
166 fprintf(ofp
, ".else\n");
167 fprintf(ofp
, ".makeenv MACHINE_PLATFORM\n");
168 fprintf(ofp
, ".makeenv MACHINE\n");
169 fprintf(ofp
, ".makeenv MACHINE_ARCH\n");
170 fprintf(ofp
, ".endif\n");
171 fprintf(ofp
, "IDENT=");
173 /* Don't compile kernel profiling code for vkernel */
174 if (strncmp(platformname
, "vkernel", 6) != 0)
175 fprintf(ofp
, " -DGPROF");
179 printf("cpu type must be specified\n");
183 for (op
= mkopt
; op
!= NULL
; op
= op
->op_next
)
184 fprintf(ofp
, "%s=%s\n", op
->op_name
, op
->op_value
);
186 fprintf(ofp
, "DEBUG=-g\n");
188 fprintf(ofp
, "PROF=-pg\n");
189 fprintf(ofp
, "PROFLEVEL=%d\n", profiling
);
192 fprintf(ofp
,"S=%s\n", srcdir
);
193 while (fgets(line
, BUFSIZ
, ifp
) != 0) {
195 fprintf(ofp
, "%s", line
);
198 if (strcmp(line
, "%BEFORE_DEPEND\n") == 0)
199 do_before_depend(ofp
);
200 else if (strcmp(line
, "%OBJS\n") == 0)
202 else if (strcmp(line
, "%MFILES\n") == 0)
204 else if (strcmp(line
, "%CFILES\n") == 0)
206 else if (strcmp(line
, "%SFILES\n") == 0)
208 else if (strcmp(line
, "%RULES\n") == 0)
210 else if (strcmp(line
, "%CLEAN\n") == 0)
212 else if (strncmp(line
, "%VERSREQ=", sizeof("%VERSREQ=") - 1) == 0) {
213 versreq
= atoi(line
+ sizeof("%VERSREQ=") - 1);
214 if (versreq
!= CONFIGVERS
) {
215 fprintf(stderr
, "ERROR: version of config(8) does not match kernel!\n");
216 fprintf(stderr
, "config version = %d, ", CONFIGVERS
);
217 fprintf(stderr
, "version required = %d\n\n", versreq
);
218 fprintf(stderr
, "Make sure that /usr/src/usr.sbin/config is in sync\n");
219 fprintf(stderr
, "with your /usr/src/sys and install a new config binary\n");
220 fprintf(stderr
, "before trying this again.\n\n");
221 fprintf(stderr
, "If running the new config fails check your config\n");
222 fprintf(stderr
, "file against the GENERIC or LINT config files for\n");
223 fprintf(stderr
, "changes in config syntax, or option/device naming\n");
224 fprintf(stderr
, "conventions\n\n");
229 "Unknown %% construct in generic makefile: %s",
234 moveifchanged(path("Makefile.new"), path("Makefile"));
238 * Read in the information about files used in making the system.
239 * Store it in the ftab linked list.
245 struct file_list
*tp
, *pf
;
247 struct device
*save_dp
;
249 char *wd
, *this, *needs
, *special
, *depends
, *clean
, *warning
;
250 char fname
[MAXPATHLEN
];
252 int nreqs
, first
= 1, configdep
, isdup
, std
, filetype
,
253 imp_rule
, no_obj
, before_depend
, nowerror
, mandatory
;
258 printf("no ident line specified\n");
261 snprintf(fname
, sizeof(fname
), "../conf/files");
263 fp
= fopen(fname
, "r");
268 * filename [ standard | mandatory | optional ] [ config-dependent ]
269 * [ dev* | profiling-routine ] [ no-obj ]
270 * [ compile-with "compile rule" [no-implicit-rule] ]
271 * [ dependency "dependency-list"] [ before-depend ]
272 * [ clean "file-list"] [ warning "text warning" ]
275 if (wd
== (char *)EOF
) {
279 snprintf(fname
, sizeof(fname
),
280 "../platform/%s/conf/files",
282 fp
= fopen(fname
, "r");
285 snprintf(fname
, sizeof(fname
),
286 "files.%s", platformname
);
291 snprintf(fname
, sizeof(fname
),
292 "files.%s", raisestr(ident
));
293 fp
= fopen(fname
, "r");
303 while (((wd
= get_word(fp
)) != (char *)EOF
) && wd
)
310 printf("%s: No type for %s.\n",
314 if ((pf
= fl_lookup(this)) && (pf
->f_type
!= INVISIBLE
|| pf
->f_flags
))
319 if (first
== 3 && pf
== NULL
&& (tp
= fltail_lookup(this)) != NULL
) {
320 if (tp
->f_type
!= INVISIBLE
|| tp
->f_flags
)
321 printf("%s: Local file %s overrides %s.\n",
322 fname
, this, tp
->f_fn
);
324 printf("%s: Local file %s could override %s"
325 " with a different kernel configuration.\n",
326 fname
, this, tp
->f_fn
);
335 std
= mandatory
= nonoptional
= 0;
341 if (strcmp(wd
, "standard") == 0) {
343 } else if (strcmp(wd
, "mandatory") == 0) {
345 * If an entry is marked "mandatory", config will abort if
346 * it's not called by a configuration line in the config
347 * file. Apart from this, the device is handled like one
351 } else if (strcmp(wd
, "nonoptional") == 0) {
353 } else if (strcmp(wd
, "optional") == 0) {
354 /* don't need to do anything */
356 printf("%s: %s must be optional, mandatory or standard\n",
358 printf("Alternatively, your version of config(8) may be out of sync with your\nkernel source.\n");
365 if (strcmp(wd
, "config-dependent") == 0) {
369 if (strcmp(wd
, "no-obj") == 0) {
373 if (strcmp(wd
, "no-implicit-rule") == 0) {
374 if (special
== NULL
) {
375 printf("%s: alternate rule required when "
376 "\"no-implicit-rule\" is specified.\n",
382 if (strcmp(wd
, "before-depend") == 0) {
386 if (strcmp(wd
, "dependency") == 0) {
387 next_quoted_word(fp
, wd
);
389 printf("%s: %s missing compile command string.\n",
393 depends
= strdup(wd
);
396 if (strcmp(wd
, "clean") == 0) {
397 next_quoted_word(fp
, wd
);
399 printf("%s: %s missing clean file list.\n",
406 if (strcmp(wd
, "compile-with") == 0) {
407 next_quoted_word(fp
, wd
);
409 printf("%s: %s missing compile command string.\n",
413 special
= strdup(wd
);
416 if (strcmp(wd
, "nowerror") == 0) {
420 if (strcmp(wd
, "warning") == 0) {
421 next_quoted_word(fp
, wd
);
423 printf("%s: %s missing warning text string.\n",
427 warning
= strdup(wd
);
431 if (strcmp(wd
, "local") == 0) {
435 if (strcmp(wd
, "no-depend") == 0) {
439 if (strcmp(wd
, "device-driver") == 0) {
440 printf("%s: `device-driver' flag obsolete.\n", fname
);
443 if (strcmp(wd
, "profiling-routine") == 0) {
444 filetype
= PROFILING
;
447 if (needs
== NULL
&& nreqs
== 1)
451 for (dp
= dtab
; dp
!= NULL
; save_dp
= dp
, dp
= dp
->d_next
)
452 if (strcmp(dp
->d_name
, wd
) == 0) {
453 if (std
&& dp
->d_type
== PSEUDO_DEVICE
&&
459 printf("%s: mandatory device \"%s\" not found\n",
464 dp
= malloc(sizeof(*dp
));
465 bzero(dp
, sizeof(*dp
));
467 dp
->d_name
= strdup(wd
);
468 dp
->d_type
= PSEUDO_DEVICE
;
470 save_dp
->d_next
= dp
;
473 for (op
= opt
; op
!= NULL
; op
= op
->op_next
) {
474 if (op
->op_value
== 0 && opteq(op
->op_name
, wd
)) {
483 printf("%s: the option \"%s\" MUST be specified\n",
488 while ((wd
= get_word(fp
)) != NULL
)
493 tp
->f_type
= INVISIBLE
;
496 tp
->f_special
= special
;
497 tp
->f_depends
= depends
;
499 tp
->f_warn
= warning
;
503 if (std
== 0 && nreqs
== 0) {
504 printf("%s: what is %s optional on?\n",
510 printf("%s: syntax error describing %s\n",
514 if (filetype
== PROFILING
&& profiling
== 0)
519 tp
->f_type
= filetype
;
522 tp
->f_flags
|= CONFIGDEP
;
524 tp
->f_flags
|= NO_IMPLCT_RULE
;
526 tp
->f_flags
|= NO_OBJ
;
528 tp
->f_flags
|= BEFORE_DEPEND
;
530 tp
->f_flags
|= NOWERROR
;
532 tp
->f_flags
|= NO_IMPLCT_RULE
;
534 tp
->f_flags
|= NO_OBJ
;
536 tp
->f_special
= special
;
537 tp
->f_depends
= depends
;
539 tp
->f_warn
= warning
;
540 if (pf
&& pf
->f_type
== INVISIBLE
)
541 pf
->f_flags
= 1; /* mark as duplicate */
546 opteq(char *cp
, char *dp
)
550 for (;; cp
++, dp
++) {
552 c
= isupper(*cp
) ? tolower(*cp
) : *cp
;
553 d
= isupper(*dp
) ? tolower(*dp
) : *dp
;
563 do_before_depend(FILE *fp
)
565 struct file_list
*tp
;
568 fputs("BEFORE_DEPEND=", fp
);
570 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
571 if (tp
->f_flags
& BEFORE_DEPEND
) {
572 len
= strlen(tp
->f_fn
);
573 if ((len
= 3 + len
) + lpos
> 72) {
577 if (tp
->f_flags
& NO_IMPLCT_RULE
)
578 fprintf(fp
, "%s ", tp
->f_fn
);
580 fprintf(fp
, "$S/%s ", tp
->f_fn
);
590 struct file_list
*tp
;
594 fprintf(fp
, "OBJS=");
596 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
) {
597 if (tp
->f_type
== INVISIBLE
|| tp
->f_flags
& NO_OBJ
)
600 cp
= sp
+ (len
= strlen(sp
)) - 1;
603 if (len
+ lpos
> 72) {
605 fprintf(fp
, "\\\n\t");
607 fprintf(fp
, "%s ", sp
);
618 struct file_list
*tp
;
621 fputs("CFILES=", fp
);
623 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
624 if (tp
->f_type
!= INVISIBLE
&& tp
->f_type
!= NODEPEND
) {
625 len
= strlen(tp
->f_fn
);
626 if (tp
->f_fn
[len
- 1] != 'c')
628 if ((len
= 3 + len
) + lpos
> 72) {
632 if (tp
->f_type
!= LOCAL
)
633 fprintf(fp
, "$S/%s ", tp
->f_fn
);
635 fprintf(fp
, "%s ", tp
->f_fn
);
646 struct file_list
*tp
;
649 fputs("MFILES=", fp
);
651 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
652 if (tp
->f_type
!= INVISIBLE
) {
653 len
= strlen(tp
->f_fn
);
654 if (tp
->f_fn
[len
- 1] != 'm' || tp
->f_fn
[len
- 2] != '.')
656 if ((len
= 3 + len
) + lpos
> 72) {
660 fprintf(fp
, "$S/%s ", tp
->f_fn
);
670 struct file_list
*tp
;
673 fputs("SFILES=", fp
);
675 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
676 if (tp
->f_type
!= INVISIBLE
) {
677 len
= strlen(tp
->f_fn
);
678 if (tp
->f_fn
[len
- 1] != 'S' && tp
->f_fn
[len
- 1] != 's')
680 if ((len
= 3 + len
) + lpos
> 72) {
684 fprintf(fp
, "$S/%s ", tp
->f_fn
);
697 cp
= strrchr(fn
, '/');
704 * Create the makerules for each file
705 * which is part of the system.
706 * Devices are processed with the special c2 option -i
707 * which avoids any problem areas with i/o addressing
708 * (e.g. for the VAX); assembler files are processed by as.
714 struct file_list
*ftp
;
717 for (ftp
= ftab
; ftp
!= NULL
; ftp
= ftp
->f_next
) {
718 if (ftp
->f_type
== INVISIBLE
)
720 if (ftp
->f_warn
!= NULL
)
721 printf("WARNING: %s\n", ftp
->f_warn
);
722 cp
= (np
= ftp
->f_fn
) + strlen(ftp
->f_fn
) - 1;
724 if (ftp
->f_flags
& NO_IMPLCT_RULE
) {
726 fprintf(f
, "%s: %s\n", np
, ftp
->f_depends
);
728 fprintf(f
, "%s: \n", np
);
733 fprintf(f
, "%so:\n\t-cp $S/%so .\n\n",
738 fprintf(f
, "%so: $S/%s%c %s\n", tail(np
),
739 np
, och
, ftp
->f_depends
);
741 fprintf(f
, "%so: $S/%s%c\n", tail(np
),
744 special
= ftp
->f_special
;
745 if (special
== NULL
) {
746 const char *ftype
= NULL
;
747 static char cmd
[128];
749 switch (ftp
->f_type
) {
762 printf("config: don't know rules for %s\n", np
);
765 snprintf(cmd
, sizeof(cmd
), "${%s_%c%s}%s",
767 ftp
->f_flags
& CONFIGDEP
? "_C" : "",
768 ftp
->f_flags
& NOWERROR
? "" : " ${WERROR}");
772 fprintf(f
, "\t%s\n\n", special
);
779 struct file_list
*tp
;
784 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
786 len
= strlen(tp
->f_clean
);
787 if (len
+ lpos
> 72) {
791 fprintf(fp
, "%s ", tp
->f_clean
);
805 *str
= toupper(*str
);