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 $
35 * $DragonFly: src/usr.sbin/config/mkmakefile.c,v 1.18 2007/01/19 07:23:43 dillon Exp $
39 * Build the makefile for the system, from
40 * the information in the 'files' files and the
41 * additional files for the machine being compiled to.
48 #include <sys/param.h>
51 #include "configvers.h"
53 #define next_word(fp, wd) \
57 word = get_word(fp); \
58 if (word == (char *)EOF) \
63 #define next_quoted_word(fp, wd) \
67 word = get_quoted_word(fp); \
68 if (word == (char *)EOF) \
74 static struct file_list
*fcur
;
76 static char *tail(char *);
77 static void do_clean(FILE *);
78 static void do_rules(FILE *);
79 static void do_sfiles(FILE *);
80 static void do_mfiles(FILE *);
81 static void do_cfiles(FILE *);
82 static void do_objs(FILE *);
83 static void do_before_depend(FILE *);
84 static int opteq(char *, char *);
85 static void read_files(void);
88 * Lookup a file, by name.
90 static struct file_list
*
95 for (fp
= ftab
; fp
!= NULL
; fp
= fp
->f_next
) {
96 if (strcmp(fp
->f_fn
, file
) == 0)
103 * Lookup a file, by final component name.
105 static struct file_list
*
106 fltail_lookup(char *file
)
108 struct file_list
*fp
;
110 for (fp
= ftab
; fp
!= NULL
; fp
= fp
->f_next
) {
111 if (strcmp(tail(fp
->f_fn
), tail(file
)) == 0)
118 * Make a new file list entry
120 static struct file_list
*
123 struct file_list
*fp
;
125 fp
= malloc(sizeof(*fp
));
126 bzero(fp
, sizeof(*fp
));
136 * Build the makefile from the skeleton
147 snprintf(line
, sizeof(line
), "../platform/%s/conf/Makefile",
149 ifp
= fopen(line
, "r");
151 snprintf(line
, sizeof(line
), "Makefile.%s", platformname
);
152 ifp
= fopen(line
, "r");
156 ofp
= fopen(path("Makefile.new"), "w");
158 err(1, "%s", path("Makefile.new"));
159 fprintf(ofp
, "KERN_IDENT=%s\n", raisestr(ident
));
160 fprintf(ofp
, "MACHINE_PLATFORM=%s\n", platformname
);
161 fprintf(ofp
, "MACHINE=%s\n", machinename
);
162 fprintf(ofp
, "MACHINE_ARCH=%s\n", machinearchname
);
163 fprintf(ofp
, ".makeenv MACHINE_PLATFORM\n");
164 fprintf(ofp
, ".makeenv MACHINE\n");
165 fprintf(ofp
, ".makeenv MACHINE_ARCH\n");
166 fprintf(ofp
, "IDENT=");
168 fprintf(ofp
, " -DGPROF");
171 printf("cpu type must be specified\n");
175 for (op
= mkopt
; op
!= NULL
; op
= op
->op_next
)
176 fprintf(ofp
, "%s=%s\n", op
->op_name
, op
->op_value
);
178 fprintf(ofp
, "DEBUG=-g\n");
180 fprintf(ofp
, "PROF=-pg\n");
181 fprintf(ofp
, "PROFLEVEL=%d\n", profiling
);
184 fprintf(ofp
,"S=%s\n", srcdir
);
185 while (fgets(line
, BUFSIZ
, ifp
) != 0) {
187 fprintf(ofp
, "%s", line
);
190 if (strcmp(line
, "%BEFORE_DEPEND\n") == 0)
191 do_before_depend(ofp
);
192 else if (strcmp(line
, "%OBJS\n") == 0)
194 else if (strcmp(line
, "%MFILES\n") == 0)
196 else if (strcmp(line
, "%CFILES\n") == 0)
198 else if (strcmp(line
, "%SFILES\n") == 0)
200 else if (strcmp(line
, "%RULES\n") == 0)
202 else if (strcmp(line
, "%CLEAN\n") == 0)
204 else if (strncmp(line
, "%VERSREQ=", sizeof("%VERSREQ=") - 1) == 0) {
205 versreq
= atoi(line
+ sizeof("%VERSREQ=") - 1);
206 if (versreq
!= CONFIGVERS
) {
207 fprintf(stderr
, "ERROR: version of config(8) does not match kernel!\n");
208 fprintf(stderr
, "config version = %d, ", CONFIGVERS
);
209 fprintf(stderr
, "version required = %d\n\n", versreq
);
210 fprintf(stderr
, "Make sure that /usr/src/usr.sbin/config is in sync\n");
211 fprintf(stderr
, "with your /usr/src/sys and install a new config binary\n");
212 fprintf(stderr
, "before trying this again.\n\n");
213 fprintf(stderr
, "If running the new config fails check your config\n");
214 fprintf(stderr
, "file against the GENERIC or LINT config files for\n");
215 fprintf(stderr
, "changes in config syntax, or option/device naming\n");
216 fprintf(stderr
, "conventions\n\n");
221 "Unknown %% construct in generic makefile: %s",
226 moveifchanged(path("Makefile.new"), path("Makefile"));
230 * Read in the information about files used in making the system.
231 * Store it in the ftab linked list.
237 struct file_list
*tp
, *pf
;
239 struct device
*save_dp
;
241 char *wd
, *this, *needs
, *special
, *depends
, *clean
, *warning
;
242 char fname
[MAXPATHLEN
];
244 int nreqs
, first
= 1, configdep
, isdup
, std
, filetype
,
245 imp_rule
, no_obj
, before_depend
, mandatory
;
250 printf("no ident line specified\n");
253 snprintf(fname
, sizeof(fname
), "../conf/files");
255 fp
= fopen(fname
, "r");
260 * filename [ standard | mandatory | optional ] [ config-dependent ]
261 * [ dev* | profiling-routine ] [ no-obj ]
262 * [ compile-with "compile rule" [no-implicit-rule] ]
263 * [ dependency "dependency-list"] [ before-depend ]
264 * [ clean "file-list"] [ warning "text warning" ]
267 if (wd
== (char *)EOF
) {
271 snprintf(fname
, sizeof(fname
),
272 "../platform/%s/conf/files",
274 fp
= fopen(fname
, "r");
277 snprintf(fname
, sizeof(fname
),
278 "files.%s", platformname
);
283 snprintf(fname
, sizeof(fname
),
284 "files.%s", raisestr(ident
));
285 fp
= fopen(fname
, "r");
295 while (((wd
= get_word(fp
)) != (char *)EOF
) && wd
)
302 printf("%s: No type for %s.\n",
306 if ((pf
= fl_lookup(this)) && (pf
->f_type
!= INVISIBLE
|| pf
->f_flags
))
311 if (first
== 3 && pf
== NULL
&& (tp
= fltail_lookup(this)) != NULL
) {
312 if (tp
->f_type
!= INVISIBLE
|| tp
->f_flags
)
313 printf("%s: Local file %s overrides %s.\n",
314 fname
, this, tp
->f_fn
);
316 printf("%s: Local file %s could override %s"
317 " with a different kernel configuration.\n",
318 fname
, this, tp
->f_fn
);
327 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
, "warning") == 0) {
408 next_quoted_word(fp
, wd
);
410 printf("%s: %s missing warning text string.\n",
414 warning
= strdup(wd
);
418 if (strcmp(wd
, "local") == 0) {
422 if (strcmp(wd
, "no-depend") == 0) {
426 if (strcmp(wd
, "device-driver") == 0) {
427 printf("%s: `device-driver' flag obsolete.\n", fname
);
430 if (strcmp(wd
, "profiling-routine") == 0) {
431 filetype
= PROFILING
;
434 if (needs
== 0 && nreqs
== 1)
438 for (dp
= dtab
; dp
!= NULL
; save_dp
= dp
, dp
= dp
->d_next
)
439 if (strcmp(dp
->d_name
, wd
) == 0) {
440 if (std
&& dp
->d_type
== PSEUDO_DEVICE
&&
446 printf("%s: mandatory device \"%s\" not found\n",
451 dp
= malloc(sizeof(*dp
));
452 bzero(dp
, sizeof(*dp
));
454 dp
->d_name
= strdup(wd
);
455 dp
->d_type
= PSEUDO_DEVICE
;
457 save_dp
->d_next
= dp
;
460 for (op
= opt
; op
!= NULL
; op
= op
->op_next
) {
461 if (op
->op_value
== 0 && opteq(op
->op_name
, wd
)) {
470 printf("%s: the option \"%s\" MUST be specified\n",
475 while ((wd
= get_word(fp
)) != 0)
480 tp
->f_type
= INVISIBLE
;
483 tp
->f_special
= special
;
484 tp
->f_depends
= depends
;
486 tp
->f_warn
= warning
;
490 if (std
== 0 && nreqs
== 0) {
491 printf("%s: what is %s optional on?\n",
497 printf("%s: syntax error describing %s\n",
501 if (filetype
== PROFILING
&& profiling
== 0)
506 tp
->f_type
= filetype
;
509 tp
->f_flags
|= CONFIGDEP
;
511 tp
->f_flags
|= NO_IMPLCT_RULE
;
513 tp
->f_flags
|= NO_OBJ
;
515 tp
->f_flags
|= BEFORE_DEPEND
;
517 tp
->f_flags
|= NO_IMPLCT_RULE
;
519 tp
->f_flags
|= NO_OBJ
;
521 tp
->f_special
= special
;
522 tp
->f_depends
= depends
;
524 tp
->f_warn
= warning
;
525 if (pf
&& pf
->f_type
== INVISIBLE
)
526 pf
->f_flags
= 1; /* mark as duplicate */
531 opteq(char *cp
, char *dp
)
535 for (;; cp
++, dp
++) {
537 c
= isupper(*cp
) ? tolower(*cp
) : *cp
;
538 d
= isupper(*dp
) ? tolower(*dp
) : *dp
;
548 do_before_depend(FILE *fp
)
550 struct file_list
*tp
;
553 fputs("BEFORE_DEPEND=", fp
);
555 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
556 if (tp
->f_flags
& BEFORE_DEPEND
) {
557 len
= strlen(tp
->f_fn
);
558 if ((len
= 3 + len
) + lpos
> 72) {
562 if (tp
->f_flags
& NO_IMPLCT_RULE
)
563 fprintf(fp
, "%s ", tp
->f_fn
);
565 fprintf(fp
, "$S/%s ", tp
->f_fn
);
575 struct file_list
*tp
;
579 fprintf(fp
, "OBJS=");
581 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
) {
582 if (tp
->f_type
== INVISIBLE
|| tp
->f_flags
& NO_OBJ
)
585 cp
= sp
+ (len
= strlen(sp
)) - 1;
588 if (len
+ lpos
> 72) {
590 fprintf(fp
, "\\\n\t");
592 fprintf(fp
, "%s ", sp
);
603 struct file_list
*tp
;
606 fputs("CFILES=", fp
);
608 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
609 if (tp
->f_type
!= INVISIBLE
&& tp
->f_type
!= NODEPEND
) {
610 len
= strlen(tp
->f_fn
);
611 if (tp
->f_fn
[len
- 1] != 'c')
613 if ((len
= 3 + len
) + lpos
> 72) {
617 if (tp
->f_type
!= LOCAL
)
618 fprintf(fp
, "$S/%s ", tp
->f_fn
);
620 fprintf(fp
, "%s ", tp
->f_fn
);
631 struct file_list
*tp
;
634 fputs("MFILES=", fp
);
636 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
637 if (tp
->f_type
!= INVISIBLE
) {
638 len
= strlen(tp
->f_fn
);
639 if (tp
->f_fn
[len
- 1] != 'm' || tp
->f_fn
[len
- 2] != '.')
641 if ((len
= 3 + len
) + lpos
> 72) {
645 fprintf(fp
, "$S/%s ", tp
->f_fn
);
655 struct file_list
*tp
;
658 fputs("SFILES=", fp
);
660 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
661 if (tp
->f_type
!= INVISIBLE
) {
662 len
= strlen(tp
->f_fn
);
663 if (tp
->f_fn
[len
- 1] != 'S' && tp
->f_fn
[len
- 1] != 's')
665 if ((len
= 3 + len
) + lpos
> 72) {
669 fprintf(fp
, "$S/%s ", tp
->f_fn
);
682 cp
= strrchr(fn
, '/');
689 * Create the makerules for each file
690 * which is part of the system.
691 * Devices are processed with the special c2 option -i
692 * which avoids any problem areas with i/o addressing
693 * (e.g. for the VAX); assembler files are processed by as.
698 char *cp
, *np
, och
, *tp
;
699 struct file_list
*ftp
;
702 for (ftp
= ftab
; ftp
!= NULL
; ftp
= ftp
->f_next
) {
703 if (ftp
->f_type
== INVISIBLE
)
705 if (ftp
->f_warn
!= NULL
)
706 printf("WARNING: %s\n", ftp
->f_warn
);
707 cp
= (np
= ftp
->f_fn
) + strlen(ftp
->f_fn
) - 1;
709 if (ftp
->f_flags
& NO_IMPLCT_RULE
) {
711 fprintf(f
, "%s: %s\n", np
, ftp
->f_depends
);
713 fprintf(f
, "%s: \n", np
);
718 fprintf(f
, "%so:\n\t-cp $S/%so .\n\n",
723 fprintf(f
, "%so: $S/%s%c %s\n", tail(np
),
724 np
, och
, ftp
->f_depends
);
726 fprintf(f
, "%so: $S/%s%c\n", tail(np
),
730 special
= ftp
->f_special
;
731 if (special
== NULL
) {
732 const char *ftype
= NULL
;
733 static char cmd
[128];
735 switch (ftp
->f_type
) {
748 printf("config: don't know rules for %s\n", np
);
751 snprintf(cmd
, sizeof(cmd
), "${%s_%c%s}",
753 ftp
->f_flags
& CONFIGDEP
? "_C" : "");
757 fprintf(f
, "\t%s\n\n", special
);
764 struct file_list
*tp
;
769 for (tp
= ftab
; tp
!= NULL
; tp
= tp
->f_next
)
771 len
= strlen(tp
->f_clean
);
772 if (len
+ lpos
> 72) {
776 fprintf(fp
, "%s ", tp
->f_clean
);
790 *str
= toupper(*str
);