config(1): Make sort order deterministic.
Ensure we break ties in every case. This way, even though we use the
unstable qsort(3) library routine, the output is reproducible, no
matter what algorithm is behind qsort(3).
It would be nice if we could just use a stable sort function here,
but mergesort(3) is nonstandard, so we'd have to add it to
tools/compat, which is a big pain.
Instead, put a tie-breaking rule in every comparison function we use
with qsort, and abort() in the event of ties -- that way, we noisily
refuse to rely on unstable sort order.
While here, dispense with any question of integer overflow, and
sprinkle comments.
PR bin/58115
2024-04-05 03:43:42 +03:00
|
|
|
/* $NetBSD: mkmakefile.c,v 1.73 2024/04/05 00:43:42 riastradh Exp $ */
|
1996-03-03 20:21:25 +03:00
|
|
|
|
1996-03-17 09:29:19 +03:00
|
|
|
/*
|
1995-04-28 10:54:58 +04:00
|
|
|
* Copyright (c) 1992, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* This software was developed by the Computer Systems Engineering group
|
|
|
|
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
|
|
|
* contributed to Berkeley.
|
|
|
|
*
|
|
|
|
* All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the University of
|
|
|
|
* California, Lawrence Berkeley Laboratories.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2003-08-07 15:25:11 +04:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1993-03-21 12:45:37 +03:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
1995-04-28 10:54:58 +04:00
|
|
|
*
|
|
|
|
* from: @(#)mkmakefile.c 8.1 (Berkeley) 6/6/93
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
|
|
|
|
2004-06-21 02:20:14 +04:00
|
|
|
#if HAVE_NBTOOL_CONFIG_H
|
|
|
|
#include "nbtool_config.h"
|
|
|
|
#endif
|
|
|
|
|
2014-10-29 20:14:50 +03:00
|
|
|
#include <sys/cdefs.h>
|
config(1): Make sort order deterministic.
Ensure we break ties in every case. This way, even though we use the
unstable qsort(3) library routine, the output is reproducible, no
matter what algorithm is behind qsort(3).
It would be nice if we could just use a stable sort function here,
but mergesort(3) is nonstandard, so we'd have to add it to
tools/compat, which is a big pain.
Instead, put a tie-breaking rule in every comparison function we use
with qsort, and abort() in the event of ties -- that way, we noisily
refuse to rely on unstable sort order.
While here, dispense with any question of integer overflow, and
sprinkle comments.
PR bin/58115
2024-04-05 03:43:42 +03:00
|
|
|
__RCSID("$NetBSD: mkmakefile.c,v 1.73 2024/04/05 00:43:42 riastradh Exp $");
|
2014-10-29 20:14:50 +03:00
|
|
|
|
1995-04-28 10:54:58 +04:00
|
|
|
#include <sys/param.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <ctype.h>
|
1995-04-28 10:54:58 +04:00
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2007-01-14 02:47:36 +03:00
|
|
|
#include <err.h>
|
2014-11-15 11:21:38 +03:00
|
|
|
#include <util.h>
|
2002-01-29 13:20:28 +03:00
|
|
|
#include "defs.h"
|
1995-04-28 10:54:58 +04:00
|
|
|
#include "sem.h"
|
1996-03-17 16:18:15 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1995-04-28 10:54:58 +04:00
|
|
|
* Make the Makefile.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
|
|
|
|
2006-10-05 00:34:48 +04:00
|
|
|
static void emitdefs(FILE *);
|
2015-09-04 08:52:15 +03:00
|
|
|
static void emitallfiles(FILE *);
|
1996-03-17 16:18:15 +03:00
|
|
|
|
2015-09-04 08:52:15 +03:00
|
|
|
static void emitofiles(FILE *);
|
2014-10-09 21:00:15 +04:00
|
|
|
static void emitallkobjs(FILE *);
|
|
|
|
static int emitallkobjscb(const char *, void *, void *);
|
|
|
|
static void emitattrkobjs(FILE *);
|
|
|
|
static int emitattrkobjscb(const char *, void *, void *);
|
|
|
|
static void emitkobjs(FILE *);
|
2006-10-05 00:34:48 +04:00
|
|
|
static void emitcfiles(FILE *);
|
|
|
|
static void emitsfiles(FILE *);
|
|
|
|
static void emitrules(FILE *);
|
|
|
|
static void emitload(FILE *);
|
|
|
|
static void emitincludes(FILE *);
|
|
|
|
static void emitappmkoptions(FILE *);
|
2017-06-16 02:52:15 +03:00
|
|
|
static void emitmkoption(FILE *, const char *, const struct nvlist *);
|
2009-02-15 04:39:54 +03:00
|
|
|
static void emitsubs(FILE *, const char *, const char *, int);
|
2009-03-13 21:24:41 +03:00
|
|
|
static int selectopt(const char *, void *);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-12-15 18:41:18 +03:00
|
|
|
int has_build_kernel;
|
|
|
|
|
1995-04-28 10:54:58 +04:00
|
|
|
int
|
2000-10-02 23:48:34 +04:00
|
|
|
mkmakefile(void)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-10-18 11:58:56 +04:00
|
|
|
FILE *ifp, *ofp;
|
|
|
|
int lineno;
|
2006-10-05 00:34:48 +04:00
|
|
|
void (*fn)(FILE *);
|
2015-08-28 06:55:15 +03:00
|
|
|
char line[BUFSIZ], ifname[200];
|
1995-04-28 10:54:58 +04:00
|
|
|
|
2014-12-15 18:41:18 +03:00
|
|
|
/*
|
|
|
|
* Check if conf/Makefile.kern.inc defines "build_kernel".
|
|
|
|
*
|
|
|
|
* (This is usually done by checking "version" in sys/conf/files;
|
|
|
|
* unfortunately the "build_kernel" change done around 2014 Aug didn't
|
|
|
|
* bump that version. Thus this hack.)
|
|
|
|
*/
|
2015-08-28 06:55:15 +03:00
|
|
|
(void)snprintf(ifname, sizeof(ifname), "%s/conf/Makefile.kern.inc",
|
|
|
|
srcdir);
|
2014-12-15 18:49:25 +03:00
|
|
|
if ((ifp = fopen(ifname, "r")) == NULL) {
|
2014-12-15 18:41:18 +03:00
|
|
|
warn("cannot read %s", ifname);
|
|
|
|
goto bad2;
|
|
|
|
}
|
2014-12-15 18:49:25 +03:00
|
|
|
while (fgets(line, sizeof(line), ifp) != NULL) {
|
|
|
|
if (strncmp(line, "build_kernel:", 13) == 0) {
|
|
|
|
has_build_kernel = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-12-15 18:41:18 +03:00
|
|
|
(void)fclose(ifp);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Try a makefile for the port first.
|
2000-12-03 02:01:54 +03:00
|
|
|
*/
|
2015-08-28 06:55:15 +03:00
|
|
|
(void)snprintf(ifname, sizeof(ifname), "%s/arch/%s/conf/Makefile.%s",
|
|
|
|
srcdir, machine, machine);
|
2000-12-03 02:01:54 +03:00
|
|
|
if ((ifp = fopen(ifname, "r")) == NULL) {
|
2014-10-09 23:33:43 +04:00
|
|
|
/*
|
|
|
|
* Try a makefile for the architecture second.
|
2000-12-03 02:01:54 +03:00
|
|
|
*/
|
2015-08-28 06:55:15 +03:00
|
|
|
(void)snprintf(ifname, sizeof(ifname),
|
|
|
|
"%s/arch/%s/conf/Makefile.%s",
|
|
|
|
srcdir, machinearch, machinearch);
|
2006-03-19 19:27:13 +03:00
|
|
|
ifp = fopen(ifname, "r");
|
2000-12-03 02:01:54 +03:00
|
|
|
}
|
2006-03-19 19:27:13 +03:00
|
|
|
if (ifp == NULL) {
|
2007-01-14 02:47:36 +03:00
|
|
|
warn("cannot read %s", ifname);
|
2006-03-19 19:27:13 +03:00
|
|
|
goto bad2;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
2006-10-05 00:34:48 +04:00
|
|
|
|
2002-02-13 02:20:11 +03:00
|
|
|
if ((ofp = fopen("Makefile.tmp", "w")) == NULL) {
|
2007-01-14 02:47:36 +03:00
|
|
|
warn("cannot write Makefile");
|
2006-03-19 19:27:13 +03:00
|
|
|
goto bad1;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
2006-10-05 00:34:48 +04:00
|
|
|
|
|
|
|
emitdefs(ofp);
|
|
|
|
|
1995-04-28 10:54:58 +04:00
|
|
|
lineno = 0;
|
|
|
|
while (fgets(line, sizeof(line), ifp) != NULL) {
|
|
|
|
lineno++;
|
2009-02-20 08:20:25 +03:00
|
|
|
if ((version < 20090214 && line[0] != '%') || line[0] == '#') {
|
2006-10-05 00:34:48 +04:00
|
|
|
fputs(line, ofp);
|
1993-03-21 12:45:37 +03:00
|
|
|
continue;
|
|
|
|
}
|
1995-04-28 10:54:58 +04:00
|
|
|
if (strcmp(line, "%OBJS\n") == 0)
|
2015-09-04 08:52:15 +03:00
|
|
|
fn = Mflag ? emitkobjs : emitofiles;
|
1995-04-28 10:54:58 +04:00
|
|
|
else if (strcmp(line, "%CFILES\n") == 0)
|
|
|
|
fn = emitcfiles;
|
|
|
|
else if (strcmp(line, "%SFILES\n") == 0)
|
|
|
|
fn = emitsfiles;
|
|
|
|
else if (strcmp(line, "%RULES\n") == 0)
|
|
|
|
fn = emitrules;
|
|
|
|
else if (strcmp(line, "%LOAD\n") == 0)
|
|
|
|
fn = emitload;
|
1999-07-09 13:52:55 +04:00
|
|
|
else if (strcmp(line, "%INCLUDES\n") == 0)
|
|
|
|
fn = emitincludes;
|
2004-06-04 08:38:27 +04:00
|
|
|
else if (strcmp(line, "%MAKEOPTIONSAPPEND\n") == 0)
|
|
|
|
fn = emitappmkoptions;
|
2009-02-15 04:39:54 +03:00
|
|
|
else if (strncmp(line, "%VERSION ", sizeof("%VERSION ")-1) == 0) {
|
|
|
|
int newvers;
|
|
|
|
if (sscanf(line, "%%VERSION %d\n", &newvers) != 1) {
|
|
|
|
cfgxerror(ifname, lineno, "syntax error for "
|
|
|
|
"%%VERSION");
|
|
|
|
} else
|
|
|
|
setversion(newvers);
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
if (version < 20090214)
|
|
|
|
cfgxerror(ifname, lineno,
|
|
|
|
"unknown %% construct ignored: %s", line);
|
|
|
|
else
|
|
|
|
emitsubs(ofp, line, ifname, lineno);
|
1995-04-28 10:54:58 +04:00
|
|
|
continue;
|
|
|
|
}
|
2006-10-05 00:34:48 +04:00
|
|
|
(*fn)(ofp);
|
1995-04-28 10:54:58 +04:00
|
|
|
}
|
2006-10-05 00:34:48 +04:00
|
|
|
|
|
|
|
fflush(ofp);
|
|
|
|
if (ferror(ofp))
|
|
|
|
goto wrerror;
|
|
|
|
|
1995-04-28 10:54:58 +04:00
|
|
|
if (ferror(ifp)) {
|
2007-01-14 02:47:36 +03:00
|
|
|
warn("error reading %s (at line %d)", ifname, lineno);
|
1995-04-28 10:54:58 +04:00
|
|
|
goto bad;
|
|
|
|
}
|
2006-10-05 00:34:48 +04:00
|
|
|
|
1995-04-28 10:54:58 +04:00
|
|
|
if (fclose(ofp)) {
|
|
|
|
ofp = NULL;
|
|
|
|
goto wrerror;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1995-04-28 10:54:58 +04:00
|
|
|
(void)fclose(ifp);
|
2006-10-05 00:34:48 +04:00
|
|
|
|
2002-02-13 02:20:11 +03:00
|
|
|
if (moveifchanged("Makefile.tmp", "Makefile") != 0) {
|
2007-01-14 02:47:36 +03:00
|
|
|
warn("error renaming Makefile");
|
2006-03-19 19:27:13 +03:00
|
|
|
goto bad2;
|
2002-02-13 02:20:11 +03:00
|
|
|
}
|
1995-04-28 10:54:58 +04:00
|
|
|
return (0);
|
2006-03-19 19:27:13 +03:00
|
|
|
|
2002-06-05 14:56:17 +04:00
|
|
|
wrerror:
|
2007-01-14 02:47:36 +03:00
|
|
|
warn("error writing Makefile");
|
2002-06-05 14:56:17 +04:00
|
|
|
bad:
|
1995-04-28 10:54:58 +04:00
|
|
|
if (ofp != NULL)
|
|
|
|
(void)fclose(ofp);
|
2006-03-19 19:27:13 +03:00
|
|
|
bad1:
|
|
|
|
(void)fclose(ifp);
|
2002-02-13 02:20:11 +03:00
|
|
|
/* (void)unlink("Makefile.tmp"); */
|
2006-03-19 19:27:13 +03:00
|
|
|
bad2:
|
1995-04-28 10:54:58 +04:00
|
|
|
return (1);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2017-06-16 02:52:15 +03:00
|
|
|
static void
|
|
|
|
emitmkoption(FILE *fp, const char *ass, const struct nvlist *nv)
|
|
|
|
{
|
2017-06-16 05:01:10 +03:00
|
|
|
const char *p;
|
2017-06-16 02:52:15 +03:00
|
|
|
|
|
|
|
fprintf(fp, "%s%s", nv->nv_name, ass);
|
2017-06-16 05:01:10 +03:00
|
|
|
for (p = nv->nv_str; *p; p++) {
|
2017-06-16 02:52:15 +03:00
|
|
|
if (*p == '\n')
|
|
|
|
fputs(" \\", fp);
|
|
|
|
fputc(*p, fp);
|
|
|
|
}
|
|
|
|
fputc('\n', fp);
|
|
|
|
}
|
|
|
|
|
2009-02-15 04:39:54 +03:00
|
|
|
static void
|
|
|
|
emitsubs(FILE *fp, const char *line, const char *file, int lineno)
|
|
|
|
{
|
2009-02-15 06:45:44 +03:00
|
|
|
char *nextpct;
|
|
|
|
const char *optname;
|
2009-02-15 04:39:54 +03:00
|
|
|
struct nvlist *option;
|
|
|
|
|
|
|
|
while (*line != '\0') {
|
|
|
|
if (*line != '%') {
|
|
|
|
fputc(*line++, fp);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
line++;
|
|
|
|
nextpct = strchr(line, '%');
|
|
|
|
if (nextpct == NULL) {
|
|
|
|
cfgxerror(file, lineno, "unbalanced %% or "
|
|
|
|
"unknown construct");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*nextpct = '\0';
|
|
|
|
|
|
|
|
if (*line == '\0')
|
|
|
|
fputc('%', fp);
|
|
|
|
else {
|
|
|
|
optname = intern(line);
|
|
|
|
if (!DEFINED_OPTION(optname)) {
|
|
|
|
cfgxerror(file, lineno, "unknown option %s",
|
|
|
|
optname);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((option = ht_lookup(opttab, optname)) == NULL)
|
|
|
|
option = ht_lookup(fsopttab, optname);
|
|
|
|
if (option != NULL)
|
|
|
|
fputs(option->nv_str ? option->nv_str : "1",
|
|
|
|
fp);
|
2014-10-09 23:33:43 +04:00
|
|
|
/*
|
|
|
|
* Otherwise it's not a selected option and we don't
|
|
|
|
* output anything.
|
|
|
|
*/
|
2009-02-15 04:39:54 +03:00
|
|
|
}
|
|
|
|
|
2014-10-09 23:33:43 +04:00
|
|
|
line = nextpct + 1;
|
2009-02-15 04:39:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-05 00:34:48 +04:00
|
|
|
static void
|
2000-10-02 23:48:34 +04:00
|
|
|
emitdefs(FILE *fp)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2024-01-18 07:41:37 +03:00
|
|
|
struct defoptlist *dl;
|
1997-10-18 11:58:56 +04:00
|
|
|
struct nvlist *nv;
|
1995-04-28 10:54:58 +04:00
|
|
|
|
2006-10-05 00:34:48 +04:00
|
|
|
fprintf(fp, "KERNEL_BUILD=%s\n", conffile);
|
2014-11-16 17:26:14 +03:00
|
|
|
fputs("IDENT= \\\n", fp);
|
1995-04-28 10:54:58 +04:00
|
|
|
for (nv = options; nv != NULL; nv = nv->nv_next) {
|
1998-06-30 07:30:56 +04:00
|
|
|
|
2014-10-09 23:33:43 +04:00
|
|
|
/* Skip any options output to a header file */
|
1998-06-30 07:30:56 +04:00
|
|
|
if (DEFINED_OPTION(nv->nv_name))
|
1997-02-03 00:12:30 +03:00
|
|
|
continue;
|
2014-11-17 03:53:15 +03:00
|
|
|
const char *s = nv->nv_str;
|
2014-11-16 17:26:14 +03:00
|
|
|
fprintf(fp, "\t-D%s%s%s%s \\\n", nv->nv_name,
|
2014-11-17 03:53:15 +03:00
|
|
|
s ? "=\"" : "",
|
|
|
|
s ? s : "",
|
|
|
|
s ? "\"" : "");
|
1994-01-08 13:33:43 +03:00
|
|
|
}
|
2006-10-05 00:34:48 +04:00
|
|
|
putc('\n', fp);
|
|
|
|
fprintf(fp, "MACHINE=%s\n", machine);
|
2014-11-17 03:53:15 +03:00
|
|
|
|
|
|
|
const char *subdir = "";
|
|
|
|
if (*srcdir != '/' && *srcdir != '.') {
|
1996-09-23 09:04:23 +04:00
|
|
|
/*
|
|
|
|
* libkern and libcompat "Makefile.inc"s want relative S
|
|
|
|
* specification to begin with '.'.
|
|
|
|
*/
|
2014-11-17 03:53:15 +03:00
|
|
|
subdir = "./";
|
1996-09-01 00:58:16 +04:00
|
|
|
}
|
2014-11-17 03:53:15 +03:00
|
|
|
fprintf(fp, "S=\t%s%s\n", subdir, srcdir);
|
2015-09-01 19:01:23 +03:00
|
|
|
if (Sflag) {
|
|
|
|
fprintf(fp, ".PATH: $S\n");
|
|
|
|
fprintf(fp, "___USE_SUFFIX_RULES___=1\n");
|
|
|
|
}
|
1995-04-28 10:54:58 +04:00
|
|
|
for (nv = mkoptions; nv != NULL; nv = nv->nv_next)
|
2017-06-16 02:52:15 +03:00
|
|
|
emitmkoption(fp, "=", nv);
|
2024-01-18 07:41:37 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Go through the options again and emit Makefile variables
|
|
|
|
* for those specified to get one.
|
|
|
|
*/
|
|
|
|
for (nv = options; nv != NULL; nv = nv->nv_next) {
|
|
|
|
|
|
|
|
dl = find_declared_option_option(nv->nv_name);
|
|
|
|
if (dl != NULL && dl->dl_mkvar) {
|
|
|
|
const char *s = nv->nv_str;
|
|
|
|
if (s == NULL) {
|
|
|
|
s = "1";
|
|
|
|
}
|
|
|
|
fprintf(fp, "KERNEL_OPT_%s=\"%s\"\n", nv->nv_name, s);
|
|
|
|
}
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2015-09-01 03:38:30 +03:00
|
|
|
static void
|
2015-09-01 14:35:46 +03:00
|
|
|
emitfile(FILE *fp, struct files *fi)
|
2015-09-01 03:38:30 +03:00
|
|
|
{
|
2015-09-01 23:18:41 +03:00
|
|
|
const char *defprologue = "$S/";
|
2015-09-01 03:38:30 +03:00
|
|
|
const char *prologue, *prefix, *sep;
|
|
|
|
|
2015-09-01 19:01:23 +03:00
|
|
|
if (Sflag)
|
2015-09-01 23:18:41 +03:00
|
|
|
defprologue = "";
|
2015-09-01 03:38:30 +03:00
|
|
|
prologue = prefix = sep = "";
|
2015-09-01 14:35:46 +03:00
|
|
|
if (*fi->fi_path != '/') {
|
2015-09-01 23:18:41 +03:00
|
|
|
prologue = defprologue;
|
2015-09-01 14:35:46 +03:00
|
|
|
if (fi->fi_prefix != NULL) {
|
|
|
|
if (*fi->fi_prefix == '/')
|
2015-09-01 04:17:56 +03:00
|
|
|
prologue = "";
|
2015-09-01 14:35:46 +03:00
|
|
|
prefix = fi->fi_prefix;
|
2015-09-01 03:38:30 +03:00
|
|
|
sep = "/";
|
|
|
|
}
|
|
|
|
}
|
2015-09-01 14:35:46 +03:00
|
|
|
fprintf(fp, "%s%s%s%s", prologue, prefix, sep, fi->fi_path);
|
2015-09-01 03:38:30 +03:00
|
|
|
}
|
|
|
|
|
2015-09-02 16:42:14 +03:00
|
|
|
static void
|
|
|
|
emitfilerel(FILE *fp, struct files *fi)
|
|
|
|
{
|
|
|
|
const char *prefix, *sep;
|
|
|
|
|
|
|
|
prefix = sep = "";
|
|
|
|
if (*fi->fi_path != '/') {
|
|
|
|
if (fi->fi_prefix != NULL) {
|
|
|
|
prefix = fi->fi_prefix;
|
|
|
|
sep = "/";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf(fp, "%s%s%s", prefix, sep, fi->fi_path);
|
|
|
|
}
|
|
|
|
|
2006-10-05 00:34:48 +04:00
|
|
|
static void
|
2015-09-04 08:52:15 +03:00
|
|
|
emitofiles(FILE *fp)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1995-04-28 10:54:58 +04:00
|
|
|
|
2015-09-04 08:52:15 +03:00
|
|
|
emitallfiles(fp);
|
2015-09-04 09:10:47 +03:00
|
|
|
fprintf(fp, "#%%OFILES\n");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2014-10-09 21:00:15 +04:00
|
|
|
static void
|
|
|
|
emitkobjs(FILE *fp)
|
|
|
|
{
|
|
|
|
emitallkobjs(fp);
|
|
|
|
emitattrkobjs(fp);
|
|
|
|
}
|
|
|
|
|
2014-11-15 11:21:38 +03:00
|
|
|
static int emitallkobjsweighcb(const char *name, void *v, void *arg);
|
|
|
|
static void weighattr(struct attr *a);
|
|
|
|
static int attrcmp(const void *l, const void *r);
|
|
|
|
|
|
|
|
struct attr **attrbuf;
|
2014-11-21 23:46:56 +03:00
|
|
|
size_t attridx;
|
2014-11-15 11:21:38 +03:00
|
|
|
|
2014-10-09 21:00:15 +04:00
|
|
|
static void
|
|
|
|
emitallkobjs(FILE *fp)
|
|
|
|
{
|
2014-11-21 23:46:56 +03:00
|
|
|
size_t i;
|
2014-10-09 21:00:15 +04:00
|
|
|
|
2014-11-21 23:46:56 +03:00
|
|
|
attrbuf = emalloc(nattrs * sizeof(*attrbuf));
|
2014-11-15 11:21:38 +03:00
|
|
|
|
|
|
|
ht_enumerate(attrtab, emitallkobjsweighcb, NULL);
|
2014-11-15 15:18:55 +03:00
|
|
|
ht_enumerate(attrtab, emitallkobjscb, NULL);
|
2014-11-21 23:46:56 +03:00
|
|
|
qsort(attrbuf, attridx, sizeof(struct attr *), attrcmp);
|
2014-11-15 11:21:38 +03:00
|
|
|
|
2014-11-16 17:26:14 +03:00
|
|
|
fputs("OBJS= \\\n", fp);
|
2014-11-15 11:21:38 +03:00
|
|
|
for (i = 0; i < attridx; i++)
|
2014-11-16 17:26:14 +03:00
|
|
|
fprintf(fp, "\t%s.ko \\\n", attrbuf[i]->a_name);
|
2014-10-09 21:00:15 +04:00
|
|
|
putc('\n', fp);
|
2014-11-15 11:21:38 +03:00
|
|
|
|
|
|
|
free(attrbuf);
|
2014-10-09 21:00:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
emitallkobjscb(const char *name, void *v, void *arg)
|
|
|
|
{
|
|
|
|
struct attr *a = v;
|
|
|
|
|
|
|
|
if (ht_lookup(selecttab, name) == NULL)
|
|
|
|
return 0;
|
|
|
|
if (TAILQ_EMPTY(&a->a_files))
|
|
|
|
return 0;
|
config(1): Make sort order deterministic.
Ensure we break ties in every case. This way, even though we use the
unstable qsort(3) library routine, the output is reproducible, no
matter what algorithm is behind qsort(3).
It would be nice if we could just use a stable sort function here,
but mergesort(3) is nonstandard, so we'd have to add it to
tools/compat, which is a big pain.
Instead, put a tie-breaking rule in every comparison function we use
with qsort, and abort() in the event of ties -- that way, we noisily
refuse to rely on unstable sort order.
While here, dispense with any question of integer overflow, and
sprinkle comments.
PR bin/58115
2024-04-05 03:43:42 +03:00
|
|
|
a->a_idx = attridx;
|
2014-11-15 11:21:38 +03:00
|
|
|
attrbuf[attridx++] = a;
|
2014-11-15 15:18:55 +03:00
|
|
|
/* XXX nattrs tracking is not exact yet */
|
|
|
|
if (attridx == nattrs) {
|
|
|
|
nattrs *= 2;
|
2014-11-21 23:46:56 +03:00
|
|
|
attrbuf = erealloc(attrbuf, nattrs * sizeof(*attrbuf));
|
2014-11-15 15:18:55 +03:00
|
|
|
}
|
2014-10-09 21:00:15 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-15 11:21:38 +03:00
|
|
|
static int
|
|
|
|
emitallkobjsweighcb(const char *name, void *v, void *arg)
|
|
|
|
{
|
|
|
|
struct attr *a = v;
|
|
|
|
|
|
|
|
weighattr(a);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
weighattr(struct attr *a)
|
|
|
|
{
|
|
|
|
struct attrlist *al;
|
|
|
|
|
|
|
|
for (al = a->a_deps; al != NULL; al = al->al_next) {
|
|
|
|
weighattr(al->al_this);
|
|
|
|
}
|
|
|
|
a->a_weight++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
attrcmp(const void *l, const void *r)
|
|
|
|
{
|
|
|
|
const struct attr * const *a = l, * const *b = r;
|
|
|
|
const int wa = (*a)->a_weight, wb = (*b)->a_weight;
|
config(1): Make sort order deterministic.
Ensure we break ties in every case. This way, even though we use the
unstable qsort(3) library routine, the output is reproducible, no
matter what algorithm is behind qsort(3).
It would be nice if we could just use a stable sort function here,
but mergesort(3) is nonstandard, so we'd have to add it to
tools/compat, which is a big pain.
Instead, put a tie-breaking rule in every comparison function we use
with qsort, and abort() in the event of ties -- that way, we noisily
refuse to rely on unstable sort order.
While here, dispense with any question of integer overflow, and
sprinkle comments.
PR bin/58115
2024-04-05 03:43:42 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Higher-weight first; then, among equal weights, earlier
|
|
|
|
* index first.
|
|
|
|
*/
|
|
|
|
if (wa > wb)
|
|
|
|
return -1;
|
|
|
|
else if (wa < wb)
|
|
|
|
return +1;
|
|
|
|
else if ((*a)->a_idx < (*b)->a_idx)
|
|
|
|
return -1;
|
|
|
|
else if ((*a)->a_idx > (*b)->a_idx)
|
|
|
|
return +1;
|
|
|
|
else
|
|
|
|
abort(); /* no ties possible */
|
2014-11-15 11:21:38 +03:00
|
|
|
}
|
|
|
|
|
2014-10-09 21:00:15 +04:00
|
|
|
static void
|
|
|
|
emitattrkobjs(FILE *fp)
|
|
|
|
{
|
|
|
|
extern struct hashtab *attrtab;
|
|
|
|
|
|
|
|
ht_enumerate(attrtab, emitattrkobjscb, fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
emitattrkobjscb(const char *name, void *v, void *arg)
|
|
|
|
{
|
|
|
|
struct attr *a = v;
|
|
|
|
struct files *fi;
|
|
|
|
FILE *fp = arg;
|
|
|
|
|
|
|
|
if (ht_lookup(selecttab, name) == NULL)
|
|
|
|
return 0;
|
|
|
|
if (TAILQ_EMPTY(&a->a_files))
|
|
|
|
return 0;
|
|
|
|
fputc('\n', fp);
|
2014-11-15 11:21:38 +03:00
|
|
|
fprintf(fp, "# %s (%d)\n", name, a->a_weight);
|
2014-11-16 17:26:14 +03:00
|
|
|
fprintf(fp, "OBJS.%s= \\\n", name);
|
2014-10-09 21:00:15 +04:00
|
|
|
TAILQ_FOREACH(fi, &a->a_files, fi_anext) {
|
2014-11-16 17:26:14 +03:00
|
|
|
fprintf(fp, "\t%s.o \\\n", fi->fi_base);
|
2014-10-09 21:00:15 +04:00
|
|
|
}
|
|
|
|
fputc('\n', fp);
|
|
|
|
fprintf(fp, "%s.ko: ${OBJS.%s}\n", name, name);
|
|
|
|
fprintf(fp, "\t${LINK_O}\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-10-05 00:34:48 +04:00
|
|
|
static void
|
2000-10-02 23:48:34 +04:00
|
|
|
emitcfiles(FILE *fp)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
|
2015-09-04 08:52:15 +03:00
|
|
|
emitallfiles(fp);
|
2015-09-04 09:10:47 +03:00
|
|
|
fprintf(fp, "#%%CFILES\n");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2006-10-05 00:34:48 +04:00
|
|
|
static void
|
2000-10-02 23:48:34 +04:00
|
|
|
emitsfiles(FILE *fp)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
|
2015-09-04 08:52:15 +03:00
|
|
|
emitallfiles(fp);
|
2015-09-04 09:10:47 +03:00
|
|
|
fprintf(fp, "#%%SFILES\n");
|
1995-04-28 10:54:58 +04:00
|
|
|
}
|
|
|
|
|
2006-10-05 00:34:48 +04:00
|
|
|
static void
|
2015-09-04 08:52:15 +03:00
|
|
|
emitallfiles(FILE *fp)
|
1995-04-28 10:54:58 +04:00
|
|
|
{
|
1997-10-18 11:58:56 +04:00
|
|
|
struct files *fi;
|
2015-09-04 08:52:15 +03:00
|
|
|
static int called;
|
2015-09-04 13:16:35 +03:00
|
|
|
int i;
|
2015-09-03 16:32:07 +03:00
|
|
|
int found = 0;
|
1995-04-28 10:54:58 +04:00
|
|
|
|
2015-09-04 08:52:15 +03:00
|
|
|
if (called++ != 0)
|
|
|
|
return;
|
2015-09-04 13:16:35 +03:00
|
|
|
for (i = 0; i < (int)nselfiles; i++) {
|
|
|
|
fi = selfiles[i];
|
2015-09-04 08:52:15 +03:00
|
|
|
if (found++ == 0)
|
|
|
|
fprintf(fp, "ALLFILES= \\\n");
|
2015-09-01 03:38:30 +03:00
|
|
|
putc('\t', fp);
|
2015-09-02 16:42:14 +03:00
|
|
|
emitfilerel(fp, fi);
|
2015-09-01 03:38:30 +03:00
|
|
|
fputs(" \\\n", fp);
|
1993-08-03 04:02:01 +04:00
|
|
|
}
|
2015-09-04 08:52:15 +03:00
|
|
|
fputc('\n', fp);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-04-28 10:54:58 +04:00
|
|
|
* Emit the make-rules.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2006-10-05 00:34:48 +04:00
|
|
|
static void
|
2000-10-02 23:48:34 +04:00
|
|
|
emitrules(FILE *fp)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-10-18 11:58:56 +04:00
|
|
|
struct files *fi;
|
2015-09-04 13:16:35 +03:00
|
|
|
int i;
|
2015-09-03 16:32:07 +03:00
|
|
|
int found = 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2015-09-04 13:16:35 +03:00
|
|
|
for (i = 0; i < (int)nselfiles; i++) {
|
|
|
|
fi = selfiles[i];
|
2015-08-29 20:35:23 +03:00
|
|
|
if (fi->fi_mkrule == NULL)
|
|
|
|
continue;
|
2015-09-01 03:38:30 +03:00
|
|
|
fprintf(fp, "%s.o: ", fi->fi_base);
|
2015-09-01 14:35:46 +03:00
|
|
|
emitfile(fp, fi);
|
2015-09-01 03:38:30 +03:00
|
|
|
putc('\n', fp);
|
2015-08-29 20:35:23 +03:00
|
|
|
fprintf(fp, "\t%s\n\n", fi->fi_mkrule);
|
2015-09-04 13:16:35 +03:00
|
|
|
found++;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
2015-09-03 16:32:07 +03:00
|
|
|
if (found == 0)
|
|
|
|
fprintf(fp, "#%%RULES\n");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-04-28 10:54:58 +04:00
|
|
|
* Emit the load commands.
|
|
|
|
*
|
|
|
|
* This function is not to be called `spurt'.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2006-10-05 00:34:48 +04:00
|
|
|
static void
|
2000-10-02 23:48:34 +04:00
|
|
|
emitload(FILE *fp)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-10-18 11:58:56 +04:00
|
|
|
struct config *cf;
|
2015-09-03 16:32:07 +03:00
|
|
|
int found = 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-12-15 18:41:18 +03:00
|
|
|
/*
|
|
|
|
* Generate the backward-compatible "build_kernel" rule if
|
|
|
|
* sys/conf/Makefile.kern.inc doesn't define any (pre-2014 Aug).
|
|
|
|
*/
|
|
|
|
if (has_build_kernel == 0) {
|
|
|
|
fprintf(fp, "build_kernel: .USE\n"
|
|
|
|
"\t${SYSTEM_LD_HEAD}\n"
|
2015-09-01 19:01:23 +03:00
|
|
|
"\t${SYSTEM_LD}%s\n"
|
2014-12-15 18:41:18 +03:00
|
|
|
"\t${SYSTEM_LD_TAIL}\n"
|
2015-09-01 19:01:23 +03:00
|
|
|
"\n",
|
|
|
|
Sflag ? "" : " swap${.TARGET}.o");
|
2014-12-15 18:41:18 +03:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Generate per-kernel rules.
|
|
|
|
*/
|
2002-06-05 14:56:17 +04:00
|
|
|
TAILQ_FOREACH(cf, &allcf, cf_next) {
|
2015-09-01 19:01:23 +03:00
|
|
|
char swapobj[100];
|
|
|
|
|
|
|
|
if (Sflag) {
|
|
|
|
swapobj[0] = '\0';
|
|
|
|
} else {
|
|
|
|
(void)snprintf(swapobj, sizeof(swapobj), " swap%s.o",
|
|
|
|
cf->cf_name);
|
|
|
|
}
|
2014-08-18 12:07:02 +04:00
|
|
|
fprintf(fp, "KERNELS+=%s\n", cf->cf_name);
|
2015-09-03 16:32:07 +03:00
|
|
|
found = 1;
|
1995-04-28 10:54:58 +04:00
|
|
|
}
|
2015-09-03 16:32:07 +03:00
|
|
|
if (found == 0)
|
|
|
|
fprintf(fp, "#%%LOAD\n");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1999-07-09 13:52:55 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Emit include headers (for any prefixes encountered)
|
|
|
|
*/
|
2006-10-05 00:34:48 +04:00
|
|
|
static void
|
2000-10-02 23:48:34 +04:00
|
|
|
emitincludes(FILE *fp)
|
1999-07-09 13:52:55 +04:00
|
|
|
{
|
|
|
|
struct prefix *pf;
|
|
|
|
|
2002-06-05 14:56:17 +04:00
|
|
|
SLIST_FOREACH(pf, &allprefixes, pf_next) {
|
2015-09-01 03:38:30 +03:00
|
|
|
const char *prologue = (*pf->pf_prefix == '/') ? "" : "$S/";
|
|
|
|
|
2006-10-05 00:34:48 +04:00
|
|
|
fprintf(fp, "EXTRA_INCLUDES+=\t-I%s%s\n",
|
2015-09-01 03:38:30 +03:00
|
|
|
prologue, pf->pf_prefix);
|
1999-07-09 13:52:55 +04:00
|
|
|
}
|
|
|
|
}
|
2004-06-04 08:38:27 +04:00
|
|
|
|
2018-08-27 08:35:00 +03:00
|
|
|
/*
|
|
|
|
* Emit all options included in a conditional expression
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
emitopts(FILE *fp, struct condexpr *cond, int include)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (cond->cx_type) {
|
|
|
|
case CX_ATOM:
|
|
|
|
if (include && selectopt(cond->cx_u.atom, NULL))
|
|
|
|
fprintf(fp, " %s", cond->cx_u.atom);
|
|
|
|
break;
|
|
|
|
case CX_NOT:
|
|
|
|
emitopts(fp, cond->cx_u.not, !include);
|
|
|
|
break;
|
|
|
|
case CX_AND:
|
|
|
|
emitopts(fp, cond->cx_u.and.left, include);
|
|
|
|
emitopts(fp, cond->cx_u.and.right, include);
|
|
|
|
break;
|
|
|
|
case CX_OR:
|
|
|
|
emitopts(fp, cond->cx_u.and.left, include);
|
|
|
|
emitopts(fp, cond->cx_u.and.right, include);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cfgerror("bug");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-04 08:38:27 +04:00
|
|
|
/*
|
|
|
|
* Emit appending makeoptions.
|
|
|
|
*/
|
2006-10-05 00:34:48 +04:00
|
|
|
static void
|
2004-06-04 08:38:27 +04:00
|
|
|
emitappmkoptions(FILE *fp)
|
|
|
|
{
|
|
|
|
struct nvlist *nv;
|
2012-03-11 12:21:53 +04:00
|
|
|
struct condexpr *cond;
|
2018-08-27 08:35:00 +03:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < nselfiles; i++) {
|
|
|
|
struct files *const fi = selfiles[i];
|
|
|
|
|
|
|
|
if (fi->fi_optx) {
|
|
|
|
fprintf(fp, "OPT.%s.c+=", fi->fi_base);
|
|
|
|
emitopts(fp, fi->fi_optx, 1);
|
|
|
|
fprintf(fp, "\n");
|
|
|
|
}
|
|
|
|
}
|
2004-06-04 08:38:27 +04:00
|
|
|
|
|
|
|
for (nv = appmkoptions; nv != NULL; nv = nv->nv_next)
|
2006-10-05 00:34:48 +04:00
|
|
|
fprintf(fp, "%s+=%s\n", nv->nv_name, nv->nv_str);
|
2004-06-04 11:28:26 +04:00
|
|
|
|
2012-03-11 12:21:53 +04:00
|
|
|
for (nv = condmkoptions; nv != NULL; nv = nv->nv_next) {
|
|
|
|
cond = nv->nv_ptr;
|
|
|
|
if (expr_eval(cond, selectopt, NULL))
|
2017-06-16 02:52:15 +03:00
|
|
|
emitmkoption(fp, "+=", nv);
|
2012-03-11 12:21:53 +04:00
|
|
|
condexpr_destroy(cond);
|
|
|
|
nv->nv_ptr = NULL;
|
2009-03-13 21:24:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
/*ARGSUSED*/
|
|
|
|
selectopt(const char *name, void *context)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (ht_lookup(selecttab, strtolower(name)) != NULL);
|
2004-06-04 08:38:27 +04:00
|
|
|
}
|