]>
git.saurik.com Git - apple/xnu.git/blob - SETUP/config/mkmakefile.c
2 * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Mach Operating System
26 * Copyright (c) 1990 Carnegie-Mellon University
27 * Copyright (c) 1989 Carnegie-Mellon University
28 * Copyright (c) 1988 Carnegie-Mellon University
29 * Copyright (c) 1987 Carnegie-Mellon University
30 * All rights reserved. The CMU software License Agreement specifies
31 * the terms and conditions for use and redistribution.
35 * Copyright (c) 1980 Regents of the University of California.
36 * All rights reserved.
38 * Redistribution and use in source and binary forms are permitted
39 * provided that the above copyright notice and this paragraph are
40 * duplicated in all such forms and that any documentation,
41 * advertising materials, and other materials related to such
42 * distribution and use acknowledge that the software was developed
43 * by the University of California, Berkeley. The name of the
44 * University may not be used to endorse or promote products derived
45 * from this software without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
48 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
52 static char sccsid
[] __attribute__((used
)) = "@(#)mkmakefile.c 5.21 (Berkeley) 6/18/88";
56 * Build the makefile for the system, from
57 * the information in the files files and the
58 * additional files for the machine being compiled to.
62 #include <unistd.h> /* for unlink */
67 void read_files(void);
68 void do_objs(FILE *fp
, const char *msg
, int ext
, int flags
);
69 void do_files(FILE *fp
, const char *msg
, char ext
);
70 void do_machdep(FILE *ofp
);
71 void do_rules(FILE *f
);
72 void copy_dependencies(FILE *makin
, FILE *makout
);
74 struct file_list
*fl_lookup(char *file
);
75 struct file_list
*fltail_lookup(char *file
);
76 struct file_list
*new_fent(void);
78 void put_source_file_name(FILE *fp
, struct file_list
*tp
);
81 #define next_word(fp, wd) \
82 { const char *word = get_word(fp); \
83 if (word == (char *)EOF) \
89 static struct file_list
*fcur
;
90 const char *tail(const char *fn
);
91 char *allCaps(char *str
);
94 * Lookup a file, by name.
101 for (fp
= ftab
; fp
!= 0; fp
= fp
->f_next
) {
102 if (eq(fp
->f_fn
, file
)) {
110 * Lookup a file, by final component name.
113 fltail_lookup(char *file
)
115 struct file_list
*fp
;
117 for (fp
= ftab
; fp
!= 0; fp
= fp
->f_next
) {
118 if (eq(tail(fp
->f_fn
), tail(file
))) {
126 * Make a new file list entry
131 struct file_list
*fp
;
133 fp
= (struct file_list
*) malloc(sizeof *fp
);
138 fp
->f_extra
= (char *) 0;
153 static char *vpath
= NULL
;
155 if ((vpath
== NULL
) &&
156 ((vpath
= getenv("VPATH")) != NULL
) &&
158 char *buf
= malloc((unsigned)(strlen(vpath
) + 2));
160 vpath
= strcat(strcpy(buf
, ":"), vpath
);
163 return vpath
? vpath
: "";
168 * Build the makefile from the skeleton
180 (void) sprintf(line
, "%s/Makefile.template", config_directory
);
181 ifp
= fopenp(VPATH
, line
, pname
, "r");
186 dfp
= fopen(path("Makefile"), "r");
187 rename(path("Makefile"), path("Makefile.old"));
188 unlink(path("Makefile.old"));
189 ofp
= fopen(path("Makefile"), "w");
191 perror(path("Makefile"));
194 fprintf(ofp
, "SOURCE_DIR=%s\n", source_directory
);
196 fprintf(ofp
, "export CONFIG_DEFINES =");
198 fprintf(ofp
, " -DGPROF");
201 for (op
= opt
; op
; op
= op
->op_next
) {
203 fprintf(ofp
, " -D%s=\"%s\"", op
->op_name
, op
->op_value
);
205 fprintf(ofp
, " -D%s", op
->op_name
);
209 for (op
= mkopt
; op
; op
= op
->op_next
) {
211 fprintf(ofp
, "%s=%s\n", op
->op_name
, op
->op_value
);
213 fprintf(ofp
, "%s\n", op
->op_name
);
217 while (fgets(line
, BUFSIZ
, ifp
) != 0) {
221 if (profiling
&& strncmp(line
, "COPTS=", 6) == 0) {
224 "GPROF.EX=$(SOURCE_DIR)/machdep/%s/gmon.ex\n", machinename
);
225 cp
= index(line
, '\n');
230 while (*cp
&& (*cp
== ' ' || *cp
== '\t')) {
233 COPTS
= malloc((unsigned)(strlen(cp
) + 1));
235 printf("config: out of memory\n");
239 fprintf(ofp
, "%s -pg\n", line
);
242 fprintf(ofp
, "%s", line
);
245 if (eq(line
, "%OBJS\n")) {
246 do_objs(ofp
, "OBJS=", -1, 0);
247 } else if (eq(line
, "%LIBOBJS\n")) {
248 do_objs(ofp
, "LIBOBJS=", -1, LIBRARYDEP
);
249 } else if (eq(line
, "%CFILES\n")) {
250 do_files(ofp
, "CFILES=", 'c');
251 do_objs(ofp
, "COBJS=", 'c', 0);
252 } else if (eq(line
, "%CXXFILES\n")) {
253 do_files(ofp
, "CXXFILES=", 'p');
254 do_objs(ofp
, "CXXOBJS=", 'p', 0);
255 } else if (eq(line
, "%SFILES\n")) {
256 do_files(ofp
, "SFILES=", 's');
257 do_objs(ofp
, "SOBJS=", 's', 0);
258 } else if (eq(line
, "%MACHDEP\n")) {
260 } else if (eq(line
, "%RULES\n")) {
264 "Unknown %% construct in generic makefile: %s",
269 copy_dependencies(dfp
, ofp
);
277 * Read in the information about files used in making the system.
278 * Store it in the ftab linked list.
284 struct file_list
*tp
, *pf
;
289 const char *devorprof
;
295 char *rest
= (char *) 0;
296 int nreqs
, first
= 1, isdup
;
299 (void) sprintf(fname
, "%s/files", config_directory
);
301 fp
= fopenp(VPATH
, fname
, pname
, "r");
310 * filename [ standard | optional ]
311 * [ dev* | profiling-routine ] [ device-driver]
314 if (wd
== (char *)EOF
) {
317 (void) sprintf(fname
, "%s/files.%s", config_directory
, machinename
);
327 * Allow comment lines beginning witha '#' character.
330 while ((wd
= get_word(fp
)) && wd
!= (char *)EOF
) {
339 printf("%s: No type for %s.\n",
343 if ((pf
= fl_lookup(this)) && (pf
->f_type
!= INVISIBLE
|| pf
->f_flags
)) {
353 if (eq(wd
, "standard")) {
356 if (!eq(wd
, "optional")) {
357 printf("%s: %s must be optional or standard\n", fname
, this);
360 if (strncmp(this, "OPTIONS/", 8) == 0) {
370 not_option
= !not_option
;
374 if (eq(wd
, "device-driver") || eq(wd
, "profiling-routine")) {
378 if (eq(wd
, "xnu-library")) {
383 if (needs
== 0 && nreqs
== 1) {
394 * Allocate a pseudo-device entry which we will insert into
395 * the device list below. The flags field is set non-zero to
396 * indicate an internal entry rather than one generated from
397 * the configuration file. The slave field is set to define
398 * the corresponding symbol as 0 should we fail to find the
399 * option in the option list.
402 tdev
.d_name
= ns(wd
);
403 tdev
.d_type
= PSEUDO_DEVICE
;
407 for (op
= opt
; op
; lop
= op
, op
= op
->op_next
) {
408 char *od
= allCaps(ns(wd
));
411 * Found an option which matches the current device
412 * dependency identifier. Set the slave field to
413 * define the option in the header file.
415 if (strcmp(op
->op_name
, od
) == 0) {
420 lop
->op_next
= op
->op_next
;
432 for (dp
= dtab
; dp
!= 0; dp
= dp
->d_next
) {
433 if (eq(dp
->d_name
, wd
) && (dp
->d_type
!= PSEUDO_DEVICE
|| dp
->d_slave
)) {
435 goto invis
; /* dont want file if option present */
442 goto nextopt
; /* want file if option missing */
444 for (op
= opt
; op
!= 0; op
= op
->op_next
) {
445 if (op
->op_value
== 0 && opteq(op
->op_name
, wd
)) {
455 while ((wd
= get_word(fp
)) != 0) {
462 tp
->f_type
= INVISIBLE
;
469 printf("%s: what is %s optional on?\n",
480 if (wd
&& eq(wd
, "xnu-library")) {
494 rest
= ns(get_rest(fp
));
496 printf("%s: syntax error describing %s\n",
501 if (eq(devorprof
, "profiling-routine") && profiling
== 0) {
510 tp
->f_type
= INVISIBLE
;
511 } else if (eq(devorprof
, "device-driver")) {
513 } else if (eq(devorprof
, "profiling-routine")) {
514 tp
->f_type
= PROFILING
;
520 if (pf
&& pf
->f_type
== INVISIBLE
) {
521 pf
->f_flags
= 1; /* mark as duplicate */
524 tp
->f_flags
|= LIBRARYDEP
;
530 opteq(const char *cp
, const char *dp
)
534 for (;; cp
++, dp
++) {
536 c
= isupper(*cp
) ? tolower(*cp
) : *cp
;
537 d
= isupper(*dp
) ? tolower(*dp
) : *dp
;
549 put_source_file_name(FILE *fp
, struct file_list
*tp
)
551 if ((tp
->f_fn
[0] == '.') && (tp
->f_fn
[1] == '/')) {
552 fprintf(fp
, "%s ", tp
->f_fn
);
554 fprintf(fp
, "$(SOURCE_DIR)/%s ", tp
->f_fn
);
559 do_objs(FILE *fp
, const char *msg
, int ext
, int flags
)
561 struct file_list
*tp
;
567 fprintf(fp
, "%s", msg
);
569 for (tp
= ftab
; tp
!= 0; tp
= tp
->f_next
) {
570 if (tp
->f_type
== INVISIBLE
) {
575 * Check flags (if any)
577 if (flags
&& ((tp
->f_flags
& flags
) != flags
)) {
582 * Check for '.o' file in list
584 cp
= tp
->f_fn
+ (len
= strlen(tp
->f_fn
)) - 1;
585 if (ext
!= -1 && *cp
!= ext
) {
587 } else if (*cp
== 'o') {
588 if (len
+ lpos
> 72) {
590 fprintf(fp
, "\\\n\t");
592 put_source_file_name(fp
, tp
);
598 cp
= (char *)sp
+ (len
= strlen(sp
)) - 1;
601 if (len
+ lpos
> 72) {
603 fprintf(fp
, "\\\n\t");
605 fprintf(fp
, "%s ", sp
);
613 do_files(FILE *fp
, const char *msg
, char ext
)
615 struct file_list
*tp
;
616 int lpos
, len
= 0; /* dvw: init to 0 */
618 fprintf(fp
, "%s", msg
);
620 for (tp
= ftab
; tp
!= 0; tp
= tp
->f_next
) {
621 if (tp
->f_type
== INVISIBLE
) {
624 if (tp
->f_fn
[strlen(tp
->f_fn
) - 1] != ext
) {
628 * Always generate a newline.
629 * Our Makefile's aren't readable anyway.
633 fprintf(fp
, "\\\n\t");
634 put_source_file_name(fp
, tp
);
641 * Include machine dependent makefile in output
645 do_machdep(FILE *ofp
)
651 (void) sprintf(line
, "%s/Makefile.%s", config_directory
, machinename
);
652 ifp
= fopenp(VPATH
, line
, pname
, "r");
657 while (fgets(line
, BUFSIZ
, ifp
) != 0) {
658 if (profiling
&& (strncmp(line
, "LIBS=", 5) == 0)) {
659 fprintf(ofp
, "LIBS=${LIBS_P}\n");
672 cp
= rindex(fn
, '/');
680 * Create the makerules for each file
681 * which is part of the system.
682 * Devices are processed with the special c2 option -i
683 * which avoids any problem areas with i/o addressing
684 * (e.g. for the VAX); assembler files are processed by as.
692 struct file_list
*ftp
;
693 const char *extras
= ""; /* dvw: init to "" */
698 for (ftp
= ftab
; ftp
!= 0; ftp
= ftp
->f_next
) {
699 if (ftp
->f_type
== INVISIBLE
) {
702 cp
= (np
= ftp
->f_fn
) + strlen(ftp
->f_fn
) - 1;
705 * Don't compile '.o' files
711 * Determine where sources should come from
713 if ((np
[0] == '.') && (np
[1] == '/')) {
717 source_dir
= "$(SOURCE_DIR)/";
720 tp
= tail(np
); /* dvw: init tp before 'if' */
721 fprintf(f
, "-include %sd\n", tp
);
722 fprintf(f
, "%so: %s%s%c\n", tp
, source_dir
, np
, och
);
724 fprintf(f
, "\t${S_RULE_0}\n");
725 fprintf(f
, "\t${S_RULE_1A}%s%.*s${S_RULE_1B}%s\n",
726 source_dir
, (int)(tp
- np
), np
, nl
);
727 fprintf(f
, "\t${S_RULE_2}%s\n", nl
);
731 switch (ftp
->f_type
) {
747 "config: COPTS undefined in generic makefile");
754 och_upper
= och
+ 'A' - 'a';
755 fprintf(f
, "\t${%c_RULE_0%s}\n", och_upper
, extras
);
756 fprintf(f
, "\t${%c_RULE_1A%s}", och_upper
, extras
);
758 fprintf(f
, "%s", ftp
->f_extra
);
760 fprintf(f
, "%s%.*s${%c_RULE_1B%s}%s\n",
761 source_dir
, (int)(tp
- np
), np
, och_upper
, extras
, nl
);
763 fprintf(f
, "\t${%c_RULE_2%s}%s\n", och_upper
, extras
, nl
);
764 fprintf(f
, "\t${%c_RULE_3%s}%s\n", och_upper
, extras
, nl
);
765 fprintf(f
, "\t$(if ${%c_RULE_4A%s},${%c_RULE_4A%s}",
766 och_upper
, extras
, och_upper
, extras
);
768 fprintf(f
, "%s", ftp
->f_extra
);
770 fprintf(f
, "%s%.*s${%c_RULE_4B%s}%s)\n",
771 source_dir
, (int)(tp
- np
), np
, och_upper
, extras
, nl
);
775 printf("Don't know rules for %s\n", np
);
789 *str
= toupper(*str
);
796 #define OLDSALUTATION "# DO NOT DELETE THIS LINE"
798 #define LINESIZE 1024
799 static char makbuf
[LINESIZE
]; /* one line buffer for makefile */
802 copy_dependencies(FILE *makin
, FILE *makout
)
804 int oldlen
= (sizeof OLDSALUTATION
- 1);
806 while (fgets(makbuf
, LINESIZE
, makin
) != NULL
) {
807 if (!strncmp(makbuf
, OLDSALUTATION
, oldlen
)) {
811 while (fgets(makbuf
, LINESIZE
, makin
) != NULL
) {
813 if (makbuf
[0] == '\n') {
819 fputs(makbuf
, makout
);