]>
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
);
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);
247 } else if (eq(line
, "%CFILES\n")) {
248 do_files(ofp
, "CFILES=", 'c');
249 do_objs(ofp
, "COBJS=", 'c');
250 } else if (eq(line
, "%CXXFILES\n")) {
251 do_files(ofp
, "CXXFILES=", 'p');
252 do_objs(ofp
, "CXXOBJS=", 'p');
253 } else if (eq(line
, "%SFILES\n")) {
254 do_files(ofp
, "SFILES=", 's');
255 do_objs(ofp
, "SOBJS=", 's');
256 } else if (eq(line
, "%MACHDEP\n")) {
258 } else if (eq(line
, "%RULES\n")) {
262 "Unknown %% construct in generic makefile: %s",
267 copy_dependencies(dfp
, ofp
);
275 * Read in the information about files used in making the system.
276 * Store it in the ftab linked list.
282 struct file_list
*tp
, *pf
;
287 const char *devorprof
;
292 char *rest
= (char *) 0;
293 int nreqs
, first
= 1, isdup
;
296 (void) sprintf(fname
, "%s/files", config_directory
);
298 fp
= fopenp(VPATH
, fname
, pname
, "r");
307 * filename [ standard | optional ]
308 * [ dev* | profiling-routine ] [ device-driver]
311 if (wd
== (char *)EOF
) {
314 (void) sprintf(fname
, "%s/files.%s", config_directory
, machinename
);
324 * Allow comment lines beginning witha '#' character.
327 while ((wd
= get_word(fp
)) && wd
!= (char *)EOF
) {
336 printf("%s: No type for %s.\n",
340 if ((pf
= fl_lookup(this)) && (pf
->f_type
!= INVISIBLE
|| pf
->f_flags
)) {
349 if (eq(wd
, "standard")) {
352 if (!eq(wd
, "optional")) {
353 printf("%s: %s must be optional or standard\n", fname
, this);
356 if (strncmp(this, "OPTIONS/", 8) == 0) {
366 not_option
= !not_option
;
370 if (eq(wd
, "device-driver") || eq(wd
, "profiling-routine")) {
375 if (needs
== 0 && nreqs
== 1) {
386 * Allocate a pseudo-device entry which we will insert into
387 * the device list below. The flags field is set non-zero to
388 * indicate an internal entry rather than one generated from
389 * the configuration file. The slave field is set to define
390 * the corresponding symbol as 0 should we fail to find the
391 * option in the option list.
394 tdev
.d_name
= ns(wd
);
395 tdev
.d_type
= PSEUDO_DEVICE
;
399 for (op
= opt
; op
; lop
= op
, op
= op
->op_next
) {
400 char *od
= allCaps(ns(wd
));
403 * Found an option which matches the current device
404 * dependency identifier. Set the slave field to
405 * define the option in the header file.
407 if (strcmp(op
->op_name
, od
) == 0) {
412 lop
->op_next
= op
->op_next
;
424 for (dp
= dtab
; dp
!= 0; dp
= dp
->d_next
) {
425 if (eq(dp
->d_name
, wd
) && (dp
->d_type
!= PSEUDO_DEVICE
|| dp
->d_slave
)) {
427 goto invis
; /* dont want file if option present */
434 goto nextopt
; /* want file if option missing */
436 for (op
= opt
; op
!= 0; op
= op
->op_next
) {
437 if (op
->op_value
== 0 && opteq(op
->op_name
, wd
)) {
447 while ((wd
= get_word(fp
)) != 0) {
454 tp
->f_type
= INVISIBLE
;
461 printf("%s: what is %s optional on?\n",
482 rest
= ns(get_rest(fp
));
484 printf("%s: syntax error describing %s\n",
489 if (eq(devorprof
, "profiling-routine") && profiling
== 0) {
498 tp
->f_type
= INVISIBLE
;
499 } else if (eq(devorprof
, "device-driver")) {
501 } else if (eq(devorprof
, "profiling-routine")) {
502 tp
->f_type
= PROFILING
;
508 if (pf
&& pf
->f_type
== INVISIBLE
) {
509 pf
->f_flags
= 1; /* mark as duplicate */
515 opteq(const char *cp
, const char *dp
)
519 for (;; cp
++, dp
++) {
521 c
= isupper(*cp
) ? tolower(*cp
) : *cp
;
522 d
= isupper(*dp
) ? tolower(*dp
) : *dp
;
534 put_source_file_name(FILE *fp
, struct file_list
*tp
)
536 if ((tp
->f_fn
[0] == '.') && (tp
->f_fn
[1] == '/')) {
537 fprintf(fp
, "%s ", tp
->f_fn
);
539 fprintf(fp
, "$(SOURCE_DIR)/%s ", tp
->f_fn
);
544 do_objs(FILE *fp
, const char *msg
, int ext
)
546 struct file_list
*tp
;
552 fprintf(fp
, "%s", msg
);
554 for (tp
= ftab
; tp
!= 0; tp
= tp
->f_next
) {
555 if (tp
->f_type
== INVISIBLE
) {
560 * Check for '.o' file in list
562 cp
= tp
->f_fn
+ (len
= strlen(tp
->f_fn
)) - 1;
563 if (ext
!= -1 && *cp
!= ext
) {
565 } else if (*cp
== 'o') {
566 if (len
+ lpos
> 72) {
568 fprintf(fp
, "\\\n\t");
570 put_source_file_name(fp
, tp
);
576 cp
= (char *)sp
+ (len
= strlen(sp
)) - 1;
579 if (len
+ lpos
> 72) {
581 fprintf(fp
, "\\\n\t");
583 fprintf(fp
, "%s ", sp
);
591 do_files(FILE *fp
, const char *msg
, char ext
)
593 struct file_list
*tp
;
594 int lpos
, len
= 0; /* dvw: init to 0 */
596 fprintf(fp
, "%s", msg
);
598 for (tp
= ftab
; tp
!= 0; tp
= tp
->f_next
) {
599 if (tp
->f_type
== INVISIBLE
) {
602 if (tp
->f_fn
[strlen(tp
->f_fn
) - 1] != ext
) {
606 * Always generate a newline.
607 * Our Makefile's aren't readable anyway.
611 fprintf(fp
, "\\\n\t");
612 put_source_file_name(fp
, tp
);
619 * Include machine dependent makefile in output
623 do_machdep(FILE *ofp
)
629 (void) sprintf(line
, "%s/Makefile.%s", config_directory
, machinename
);
630 ifp
= fopenp(VPATH
, line
, pname
, "r");
635 while (fgets(line
, BUFSIZ
, ifp
) != 0) {
636 if (profiling
&& (strncmp(line
, "LIBS=", 5) == 0)) {
637 fprintf(ofp
, "LIBS=${LIBS_P}\n");
650 cp
= rindex(fn
, '/');
658 * Create the makerules for each file
659 * which is part of the system.
660 * Devices are processed with the special c2 option -i
661 * which avoids any problem areas with i/o addressing
662 * (e.g. for the VAX); assembler files are processed by as.
670 struct file_list
*ftp
;
671 const char *extras
= ""; /* dvw: init to "" */
676 for (ftp
= ftab
; ftp
!= 0; ftp
= ftp
->f_next
) {
677 if (ftp
->f_type
== INVISIBLE
) {
680 cp
= (np
= ftp
->f_fn
) + strlen(ftp
->f_fn
) - 1;
683 * Don't compile '.o' files
689 * Determine where sources should come from
691 if ((np
[0] == '.') && (np
[1] == '/')) {
695 source_dir
= "$(SOURCE_DIR)/";
698 tp
= tail(np
); /* dvw: init tp before 'if' */
699 fprintf(f
, "-include %sd\n", tp
);
700 fprintf(f
, "%so: %s%s%c\n", tp
, source_dir
, np
, och
);
702 fprintf(f
, "\t${S_RULE_0}\n");
703 fprintf(f
, "\t${S_RULE_1A}%s%.*s${S_RULE_1B}%s\n",
704 source_dir
, (int)(tp
- np
), np
, nl
);
705 fprintf(f
, "\t${S_RULE_2}%s\n", nl
);
709 switch (ftp
->f_type
) {
725 "config: COPTS undefined in generic makefile");
732 och_upper
= och
+ 'A' - 'a';
733 fprintf(f
, "\t${%c_RULE_0%s}\n", och_upper
, extras
);
734 fprintf(f
, "\t${%c_RULE_1A%s}", och_upper
, extras
);
736 fprintf(f
, "%s", ftp
->f_extra
);
738 fprintf(f
, "%s%.*s${%c_RULE_1B%s}%s\n",
739 source_dir
, (int)(tp
- np
), np
, och_upper
, extras
, nl
);
741 /* While we are still using CTF, any build that normally does not support CTF will
742 * a "standard" compile done as well that we can harvest CTF information from; do
745 fprintf(f
, "\t${%c_CTFRULE_1A%s}", och_upper
, extras
);
747 fprintf(f
, "%s", ftp
->f_extra
);
749 fprintf(f
, "%s%.*s${%c_CTFRULE_1B%s}%s\n",
750 source_dir
, (int)(tp
- np
), np
, och_upper
, extras
, nl
);
752 fprintf(f
, "\t${%c_RULE_2%s}%s\n", och_upper
, extras
, nl
);
753 fprintf(f
, "\t${%c_CTFRULE_2%s}%s\n", och_upper
, extras
, nl
);
754 fprintf(f
, "\t${%c_RULE_3%s}%s\n", och_upper
, extras
, nl
);
755 fprintf(f
, "\t${%c_RULE_4A%s}", och_upper
, extras
);
757 fprintf(f
, "%s", ftp
->f_extra
);
759 fprintf(f
, "%s%.*s${%c_RULE_4B%s}%s\n",
760 source_dir
, (int)(tp
- np
), np
, och_upper
, extras
, nl
);
764 printf("Don't know rules for %s\n", np
);
778 *str
= toupper(*str
);
785 #define OLDSALUTATION "# DO NOT DELETE THIS LINE"
787 #define LINESIZE 1024
788 static char makbuf
[LINESIZE
]; /* one line buffer for makefile */
791 copy_dependencies(FILE *makin
, FILE *makout
)
793 int oldlen
= (sizeof OLDSALUTATION
- 1);
795 while (fgets(makbuf
, LINESIZE
, makin
) != NULL
) {
796 if (!strncmp(makbuf
, OLDSALUTATION
, oldlen
)) {
800 while (fgets(makbuf
, LINESIZE
, makin
) != NULL
) {
802 if (makbuf
[0] == '\n') {
808 fputs(makbuf
, makout
);