version 1.74, 2007/07/24 18:58:48 |
version 1.75, 2007/07/30 09:39:18 |
|
|
bool ignoreErrors; /* -i flag */ |
bool ignoreErrors; /* -i flag */ |
bool beSilent; /* -s flag */ |
bool beSilent; /* -s flag */ |
|
|
static void MainParseArgs(int, char **); |
struct dirs { |
static char * chdir_verify_path(const char *); |
char *current; |
static int ReadMakefile(void *, void *); |
char *object; |
static void add_dirpath(Lst, const char *); |
}; |
static void usage(void); |
|
static void posixParseOptLetter(int); |
|
static void record_option(int, const char *); |
|
|
|
static char *curdir; /* startup directory */ |
static void MainParseArgs(int, char **); |
static char *objdir; /* where we chdir'ed to */ |
static void add_dirpath(Lst, const char *); |
|
static void usage(void); |
|
static void posixParseOptLetter(int); |
|
static void record_option(int, const char *); |
|
|
|
static char *figure_out_MACHINE(void); |
|
static char *figure_out_MACHINE_ARCH(void); |
|
static void no_fd_limits(void); |
|
|
|
static char *chdir_verify_path(const char *, struct dirs *); |
|
static char *concat_verify(const char *, const char *, char, struct dirs *); |
|
static char *figure_out_CURDIR(void); |
|
static void setup_CURDIR_OBJDIR(struct dirs *, const char *); |
|
|
|
static void setup_VPATH(void); |
|
|
|
static void read_all_make_rules(bool, Lst, struct dirs *); |
|
static void read_makefile_list(Lst, struct dirs *); |
|
static int ReadMakefile(void *, void *); |
|
|
|
|
static void record_option(int c, const char *arg) |
static void record_option(int c, const char *arg) |
{ |
{ |
char opt[3]; |
char opt[3]; |
|
|
opt[0] = '-'; |
opt[0] = '-'; |
opt[1] = c; |
opt[1] = c; |
opt[2] = '\0'; |
opt[2] = '\0'; |
Var_Append(MAKEFLAGS, opt, VAR_GLOBAL); |
Var_Append(MAKEFLAGS, opt, VAR_GLOBAL); |
if (arg != NULL) |
if (arg != NULL) |
Var_Append(MAKEFLAGS, arg, VAR_GLOBAL); |
Var_Append(MAKEFLAGS, arg, VAR_GLOBAL); |
} |
} |
|
|
static void |
static void |
|
|
free(argv); |
free(argv); |
} |
} |
|
|
char * |
|
chdir_verify_path(const char *path) |
|
{ |
|
struct stat sb; |
|
|
|
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { |
|
if (chdir(path)) { |
|
(void)fprintf(stderr, "make warning: %s: %s.\n", |
|
path, strerror(errno)); |
|
return NULL; |
|
} else { |
|
if (path[0] != '/') |
|
return Str_concat(curdir, path, '/'); |
|
else |
|
return estrdup(path); |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
|
|
/* Add a :-separated path to a Lst of directories. */ |
/* Add a :-separated path to a Lst of directories. */ |
static void |
static void |
add_dirpath(Lst l, const char *n) |
add_dirpath(Lst l, const char *n) |
{ |
{ |
const char *start; |
const char *start; |
const char *cp; |
const char *cp; |
|
|
for (start = n;;) { |
for (start = n;;) { |
for (cp = start; *cp != '\0' && *cp != ':';) |
for (cp = start; *cp != '\0' && *cp != ':';) |
cp++; |
cp++; |
Dir_AddDiri(l, start, cp); |
Dir_AddDiri(l, start, cp); |
if (*cp == '\0') |
if (*cp == '\0') |
break; |
break; |
else |
else |
start= cp+1; |
start= cp+1; |
} |
} |
} |
} |
|
|
int main(int, char **); |
/* |
/*- |
* Get the name of this type of MACHINE from utsname so we can share an |
* main -- |
* executable for similar machines. (i.e. m68k: amiga hp300, mac68k, sun3, ...) |
* The main function, for obvious reasons. Initializes variables |
|
* and a few modules, then parses the arguments give it in the |
|
* environment and on the command line. Reads the system makefile |
|
* followed by either Makefile, makefile or the file given by the |
|
* -f argument. Sets the .MAKEFLAGS PMake variable based on all the |
|
* flags it has received by then uses either the Make or the Compat |
|
* module to create the initial list of targets. |
|
* |
* |
* Results: |
* Note that both MACHINE and MACHINE_ARCH are decided at |
* If -q was given, exits -1 if anything was out-of-date. Else it exits |
* run-time. |
* 0. |
|
* |
|
* Side Effects: |
|
* The program exits when done. Targets are created. etc. etc. etc. |
|
*/ |
*/ |
int |
static char * |
main(int argc, char **argv) |
figure_out_MACHINE() |
{ |
{ |
static LIST targs; /* target nodes to create */ |
char *r = getenv("MACHINE"); |
bool outOfDate = true; /* false if all targets up to date */ |
if (r == NULL) { |
struct stat sb, sa; |
#ifndef MAKE_BOOTSTRAP |
char *p, *path, *pathp, *pwd; |
static struct utsname utsname; |
char *mdpath; |
|
char *machine = getenv("MACHINE"); |
|
char *machine_arch = getenv("MACHINE_ARCH"); |
|
const char *syspath = _PATH_DEFSYSPATH; |
|
|
|
#ifdef RLIMIT_NOFILE |
if (uname(&utsname) == -1) { |
/* |
perror("make: uname"); |
* get rid of resource limit on file descriptors |
exit(2); |
*/ |
|
{ |
|
struct rlimit rl; |
|
if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && |
|
rl.rlim_cur != rl.rlim_max) { |
|
rl.rlim_cur = rl.rlim_max; |
|
(void)setrlimit(RLIMIT_NOFILE, &rl); |
|
} |
} |
|
r = utsname.machine; |
|
#else |
|
r = MACHINE; |
|
#endif |
} |
} |
|
return r; |
|
} |
|
|
|
static char * |
|
figure_out_MACHINE_ARCH() |
|
{ |
|
char *r = getenv("MACHINE_ARCH"); |
|
if (r == NULL) { |
|
#ifndef MACHINE_ARCH |
|
r = "unknown"; /* XXX: no uname -p yet */ |
|
#else |
|
r = MACHINE_ARCH; |
#endif |
#endif |
/* |
} |
* Find where we are and take care of PWD for the automounter... |
return r; |
* All this code is so that we know where we are when we start up |
} |
* on a different machine with pmake. |
|
*/ |
/* get rid of resource limit on file descriptors */ |
if ((curdir = dogetcwd()) == NULL) { |
static void |
|
no_fd_limits() |
|
{ |
|
#ifdef RLIMIT_NOFILE |
|
struct rlimit rl; |
|
if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && |
|
rl.rlim_cur != rl.rlim_max) { |
|
rl.rlim_cur = rl.rlim_max; |
|
(void)setrlimit(RLIMIT_NOFILE, &rl); |
|
} |
|
#endif |
|
} |
|
|
|
static char * |
|
figure_out_CURDIR() |
|
{ |
|
char *dir, *cwd; |
|
struct stat sa, sb; |
|
|
|
/* curdir is cwd... */ |
|
cwd = dogetcwd(); |
|
if (cwd == NULL) { |
(void)fprintf(stderr, "make: %s.\n", strerror(errno)); |
(void)fprintf(stderr, "make: %s.\n", strerror(errno)); |
exit(2); |
exit(2); |
} |
} |
|
|
if (stat(curdir, &sa) == -1) { |
if (stat(cwd, &sa) == -1) { |
(void)fprintf(stderr, "make: %s: %s.\n", |
(void)fprintf(stderr, "make: %s: %s.\n", cwd, strerror(errno)); |
curdir, strerror(errno)); |
exit(2); |
exit(2); |
|
} |
} |
|
|
if ((pwd = getenv("PWD")) != NULL) { |
/* ...but we can use the alias $PWD if we can prove it is the same |
if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino && |
* directory */ |
sa.st_dev == sb.st_dev) { |
if ((dir = getenv("PWD")) != NULL) { |
free(curdir); |
if (stat(dir, &sb) == 0 && sa.st_ino == sb.st_ino && |
curdir = estrdup(pwd); |
sa.st_dev == sb.st_dev) |
} |
free(cwd); |
|
return estrdup(dir); |
} |
} |
|
|
/* |
return cwd; |
* Get the name of this type of MACHINE from utsname |
} |
* so we can share an executable for similar machines. |
|
* (i.e. m68k: amiga hp300, mac68k, sun3, ...) |
|
* |
|
* Note that both MACHINE and MACHINE_ARCH are decided at |
|
* run-time. |
|
*/ |
|
if (!machine) { |
|
#ifndef MAKE_BOOTSTRAP |
|
static struct utsname utsname; |
|
|
|
if (uname(&utsname) == -1) { |
static char * |
perror("make: uname"); |
chdir_verify_path(const char *path, struct dirs *d) |
exit(2); |
{ |
} |
struct stat sb; |
machine = utsname.machine; |
|
#else |
|
machine = MACHINE; |
|
#endif |
|
} |
|
|
|
if (!machine_arch) { |
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { |
#ifndef MACHINE_ARCH |
if (chdir(path)) { |
machine_arch = "unknown"; /* XXX: no uname -p yet */ |
(void)fprintf(stderr, "make warning: %s: %s.\n", |
#else |
path, strerror(errno)); |
machine_arch = MACHINE_ARCH; |
return NULL; |
#endif |
} else { |
|
if (path[0] != '/') |
|
return Str_concat(d->current, path, '/'); |
|
else |
|
return estrdup(path); |
|
} |
} |
} |
|
|
|
return NULL; |
|
} |
|
|
|
static char * |
|
concat_verify(const char *p1, const char *p2, char c, struct dirs *d) |
|
{ |
|
char *tmp = Str_concat(p1, p2, c); |
|
char *result = chdir_verify_path(tmp, d); |
|
free(tmp); |
|
return result; |
|
} |
|
|
|
static void |
|
setup_CURDIR_OBJDIR(struct dirs *d, const char *machine) |
|
{ |
|
char *path, *prefix; |
|
|
|
d->current = figure_out_CURDIR(); |
|
d->object = NULL; |
/* |
/* |
* If the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory |
* If the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory |
* exists, change into it and build there. (If a .${MACHINE} suffix |
* exists, change into it and build there. (If a .${MACHINE} suffix |
|
|
* and modify the paths for the Makefiles appropriately. The |
* and modify the paths for the Makefiles appropriately. The |
* current directory is also placed as a variable for make scripts. |
* current directory is also placed as a variable for make scripts. |
*/ |
*/ |
mdpath = NULL; |
if ((prefix = getenv("MAKEOBJDIRPREFIX")) != NULL) { |
if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) { |
d->object = concat_verify(prefix, d->current, 0, d); |
if (!(path = getenv("MAKEOBJDIR"))) { |
} else if ((path = getenv("MAKEOBJDIR")) != NULL) { |
path = _PATH_OBJDIR; |
d->object = chdir_verify_path(path, d); |
pathp = _PATH_OBJDIRPREFIX; |
} else { |
mdpath = Str_concat(path, machine, '.'); |
path = _PATH_OBJDIR; |
if (!(objdir = chdir_verify_path(mdpath))) |
prefix = _PATH_OBJDIRPREFIX; |
if (!(objdir=chdir_verify_path(path))) { |
d->object = concat_verify(path, machine, '.', d); |
free(mdpath); |
if (!d->object) |
mdpath = Str_concat(pathp, curdir, 0); |
d->object=chdir_verify_path(path, d); |
if (!(objdir=chdir_verify_path(mdpath))) |
if (!d->object) |
objdir = curdir; |
d->object = concat_verify(prefix, d->current, 0, d); |
} |
|
} |
|
else if (!(objdir = chdir_verify_path(path))) |
|
objdir = curdir; |
|
} |
} |
else { |
if (d->object == NULL) |
mdpath = Str_concat(pathp, curdir, 0); |
d->object = d->current; |
if (!(objdir = chdir_verify_path(mdpath))) |
} |
objdir = curdir; |
|
|
#ifdef CLEANUP |
|
static void |
|
free_CURDIR_OBJDIR(struct dirs *d) |
|
{ |
|
if (d->object != d->current) |
|
free(d->object); |
|
free(d->current); |
|
} |
|
#endif |
|
|
|
|
|
/* |
|
* if the VPATH variable is defined, add its contents to the search path. |
|
* Uses the same format as the PATH env variable, i.e., |
|
* <directory>:<directory>:<directory>... |
|
*/ |
|
static void |
|
setup_VPATH() |
|
{ |
|
if (Var_Value("VPATH") != NULL) { |
|
char *vpath; |
|
|
|
vpath = Var_Subst("${VPATH}", NULL, false); |
|
add_dirpath(dirSearchPath, vpath); |
|
(void)free(vpath); |
} |
} |
free(mdpath); |
} |
|
|
esetenv("PWD", objdir); |
static void |
|
read_makefile_list(Lst mk, struct dirs *d) |
|
{ |
|
LstNode ln; |
|
ln = Lst_Find(mk, ReadMakefile, d); |
|
if (ln != NULL) |
|
Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); |
|
} |
|
|
|
static void |
|
read_all_make_rules(bool noBuiltins, Lst makefiles, struct dirs *d) |
|
{ |
|
/* |
|
* Read in the built-in rules first, followed by the specified |
|
* makefile(s), or the default BSDmakefile, Makefile or |
|
* makefile, in that order. |
|
*/ |
|
if (!noBuiltins) { |
|
LIST sysMkPath; /* Path of sys.mk */ |
|
|
|
Lst_Init(&sysMkPath); |
|
Dir_Expand(_PATH_DEFSYSMK, sysIncPath, &sysMkPath); |
|
if (Lst_IsEmpty(&sysMkPath)) |
|
Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); |
|
|
|
read_makefile_list(&sysMkPath, d); |
|
#ifdef CLEANUP |
|
Lst_Destroy(&sysMkPath, (SimpleProc)free); |
|
#endif |
|
} |
|
|
|
if (!Lst_IsEmpty(makefiles)) { |
|
read_makefile_list(makefiles, d); |
|
} else if (!ReadMakefile("BSDmakefile", d)) |
|
if (!ReadMakefile("makefile", d)) |
|
(void)ReadMakefile("Makefile", d); |
|
|
|
/* Always read a .depend file, if it exists. */ |
|
(void)ReadMakefile(".depend", d); |
|
} |
|
|
|
|
|
int main(int, char **); |
|
/*- |
|
* main -- |
|
* The main function, for obvious reasons. Initializes variables |
|
* and a few modules, then parses the arguments give it in the |
|
* environment and on the command line. Reads the system makefile |
|
* followed by either Makefile, makefile or the file given by the |
|
* -f argument. Sets the .MAKEFLAGS PMake variable based on all the |
|
* flags it has received by then uses either the Make or the Compat |
|
* module to create the initial list of targets. |
|
* |
|
* Results: |
|
* If -q was given, exits -1 if anything was out-of-date. Else it exits |
|
* 0. |
|
* |
|
* Side Effects: |
|
* The program exits when done. Targets are created. etc. etc. etc. |
|
*/ |
|
int |
|
main(int argc, char **argv) |
|
{ |
|
static LIST targs; /* target nodes to create */ |
|
bool outOfDate = true; /* false if all targets up to date */ |
|
char *machine = figure_out_MACHINE(); |
|
char *machine_arch = figure_out_MACHINE_ARCH(); |
|
const char *syspath = _PATH_DEFSYSPATH; |
|
char *p; |
|
static struct dirs d; |
|
|
|
no_fd_limits(); |
|
setup_CURDIR_OBJDIR(&d, machine); |
|
|
|
esetenv("PWD", d.object); |
unsetenv("CDPATH"); |
unsetenv("CDPATH"); |
|
|
Static_Lst_Init(create); |
Static_Lst_Init(create); |
|
|
*/ |
*/ |
Init(); |
Init(); |
|
|
if (objdir != curdir) |
if (d.object != d.current) |
Dir_AddDir(dirSearchPath, curdir); |
Dir_AddDir(dirSearchPath, d.current); |
Var_Set(".CURDIR", curdir, VAR_GLOBAL); |
Var_Set(".CURDIR", d.current, VAR_GLOBAL); |
Var_Set(".OBJDIR", objdir, VAR_GLOBAL); |
Var_Set(".OBJDIR", d.object, VAR_GLOBAL); |
|
|
/* |
/* |
* Initialize various variables. |
* Initialize various variables. |
|
|
if (Lst_IsEmpty(sysIncPath)) |
if (Lst_IsEmpty(sysIncPath)) |
add_dirpath(sysIncPath, syspath); |
add_dirpath(sysIncPath, syspath); |
|
|
/* |
read_all_make_rules(noBuiltins, &makefiles, &d); |
* Read in the built-in rules first, followed by the specified |
|
* makefile(s), or the default BSDmakefile, Makefile or |
|
* makefile, in that order. |
|
*/ |
|
if (!noBuiltins) { |
|
LstNode ln; |
|
LIST sysMkPath; /* Path of sys.mk */ |
|
|
|
Lst_Init(&sysMkPath); |
Var_Append("MFLAGS", Var_Value(MAKEFLAGS), VAR_GLOBAL); |
Dir_Expand(_PATH_DEFSYSMK, sysIncPath, &sysMkPath); |
|
if (Lst_IsEmpty(&sysMkPath)) |
|
Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); |
|
ln = Lst_Find(&sysMkPath, ReadMakefile, NULL); |
|
if (ln != NULL) |
|
Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); |
|
#ifdef CLEANUP |
|
Lst_Destroy(&sysMkPath, (SimpleProc)free); |
|
#endif |
|
} |
|
|
|
if (!Lst_IsEmpty(&makefiles)) { |
|
LstNode ln; |
|
|
|
ln = Lst_Find(&makefiles, ReadMakefile, NULL); |
|
if (ln != NULL) |
|
Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); |
|
} else if (!ReadMakefile("BSDmakefile", NULL)) |
|
if (!ReadMakefile("makefile", NULL)) |
|
(void)ReadMakefile("Makefile", NULL); |
|
|
|
/* Always read a .depend file, if it exists. */ |
|
(void)ReadMakefile(".depend", NULL); |
|
|
|
Var_Append("MFLAGS", Var_Value(MAKEFLAGS), |
|
VAR_GLOBAL); |
|
|
|
/* Install all the flags into the MAKEFLAGS env variable. */ |
/* Install all the flags into the MAKEFLAGS env variable. */ |
if (((p = Var_Value(MAKEFLAGS)) != NULL) && *p) |
if (((p = Var_Value(MAKEFLAGS)) != NULL) && *p) |
esetenv("MAKEFLAGS", p); |
esetenv("MAKEFLAGS", p); |
|
|
/* |
setup_VPATH(); |
* For compatibility, look at the directories in the VPATH variable |
|
* and add them to the search path, if the variable is defined. The |
|
* variable's value is in the same format as the PATH envariable, i.e. |
|
* <directory>:<directory>:<directory>... |
|
*/ |
|
if (Var_Value("VPATH") != NULL) { |
|
char *vpath; |
|
|
|
vpath = Var_Subst("${VPATH}", NULL, false); |
|
add_dirpath(dirSearchPath, vpath); |
|
(void)free(vpath); |
|
} |
|
|
|
/* Now that all search paths have been read for suffixes et al, it's |
/* Now that all search paths have been read for suffixes et al, it's |
* time to add the default search path to their lists... */ |
* time to add the default search path to their lists... */ |
Suff_DoPaths(); |
Suff_DoPaths(); |
|
|
|
|
/* Print the values of any variables requested by the user. */ |
/* Print the values of any variables requested by the user. */ |
if (!Lst_IsEmpty(&varstoprint)) { |
if (!Lst_IsEmpty(&varstoprint)) { |
LstNode ln; |
LstNode ln; |
|
|
for (ln = Lst_First(&varstoprint); ln != NULL; ln = Lst_Adv(ln)) { |
for (ln = Lst_First(&varstoprint); ln != NULL; |
char *value = Var_Value((char *)Lst_Datum(ln)); |
ln = Lst_Adv(ln)) { |
|
char *value = Var_Value((char *)Lst_Datum(ln)); |
|
|
printf("%s\n", value ? value : ""); |
printf("%s\n", value ? value : ""); |
} |
} |
} else { |
} else { |
/* Have now read the entire graph and need to make a list of targets |
/* Have now read the entire graph and need to make a list |
* to create. If none was given on the command line, we consult the |
* of targets to create. If none was given on the command |
* parsing module to find the main target(s) to create. */ |
* line, we consult the parsing module to find the main |
if (Lst_IsEmpty(create)) |
* target(s) to create. */ |
Parse_MainName(&targs); |
if (Lst_IsEmpty(create)) |
else |
Parse_MainName(&targs); |
Targ_FindList(&targs, create); |
else |
|
Targ_FindList(&targs, create); |
|
|
if (compatMake) |
if (compatMake) |
/* Compat_Init will take care of creating all the targets as |
/* Compat_Init will take care of creating all the |
* well as initializing the module. */ |
* targets as well as initializing the module. */ |
Compat_Run(&targs); |
Compat_Run(&targs); |
else { |
else { |
/* Initialize job module before traversing the graph, now that |
/* Initialize job module before traversing the graph, |
* any .BEGIN and .END targets have been read. This is done |
* now that any .BEGIN and .END targets have been |
* only if the -q flag wasn't given (to prevent the .BEGIN from |
* read. This is done only if the -q flag wasn't given |
* being executed should it exist). */ |
* (to prevent the .BEGIN from being executed should |
if (!queryFlag) { |
* it exist). */ |
if (maxLocal == -1) |
if (!queryFlag) { |
maxLocal = maxJobs; |
if (maxLocal == -1) |
Job_Init(maxJobs, maxLocal); |
maxLocal = maxJobs; |
} |
Job_Init(maxJobs, maxLocal); |
|
} |
|
|
/* Traverse the graph, checking on all the targets. */ |
/* Traverse the graph, checking on all the targets. */ |
outOfDate = Make_Run(&targs); |
outOfDate = Make_Run(&targs); |
} |
} |
} |
} |
|
|
#ifdef CLEANUP |
#ifdef CLEANUP |
|
|
Targ_PrintGraph(2); |
Targ_PrintGraph(2); |
|
|
#ifdef CLEANUP |
#ifdef CLEANUP |
if (objdir != curdir) |
free_CURDIR_OBJDIR(&d); |
free(objdir); |
|
free(curdir); |
|
End(); |
End(); |
#endif |
#endif |
if (queryFlag && outOfDate) |
if (queryFlag && outOfDate) |
|
|
* lots |
* lots |
*/ |
*/ |
static bool |
static bool |
ReadMakefile(void *p, void *q UNUSED) |
ReadMakefile(void *p, void *q) |
{ |
{ |
char *fname = (char *)p; /* makefile to read */ |
char *fname = (char *)p; /* makefile to read */ |
|
struct dirs *d = (struct dirs *)q; |
FILE *stream; |
FILE *stream; |
char *name; |
char *name; |
|
|
|
|
if ((stream = fopen(fname, "r")) != NULL) |
if ((stream = fopen(fname, "r")) != NULL) |
goto found; |
goto found; |
/* if we've chdir'd, rebuild the path name */ |
/* if we've chdir'd, rebuild the path name */ |
if (curdir != objdir && *fname != '/') { |
if (d->current != d->object && *fname != '/') { |
char *path; |
char *path; |
|
|
path = Str_concat(curdir, fname, '/'); |
path = Str_concat(d->current, fname, '/'); |
if ((stream = fopen(path, "r")) == NULL) |
if ((stream = fopen(path, "r")) == NULL) |
free(path); |
free(path); |
else { |
else { |
fname = path; |
fname = path; |
goto found; |
goto found; |
} |
} |
} |
} |
/* look in -I and system include directories. */ |
/* look in -I and system include directories. */ |