summaryrefslogtreecommitdiffstats
path: root/usr.bin/make
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2010-01-04 18:57:22 +0000
committerobrien <obrien@FreeBSD.org>2010-01-04 18:57:22 +0000
commitd2744b88e92689da349b5de750666f235ea9a4ce (patch)
treea3e67a307d511e8bb94e2cef9388c3b1c989d519 /usr.bin/make
parentf86eec131ecd8165dffb9b3c544d58e63f18a772 (diff)
downloadFreeBSD-src-d2744b88e92689da349b5de750666f235ea9a4ce.zip
FreeBSD-src-d2744b88e92689da349b5de750666f235ea9a4ce.tar.gz
Add ability to search up the directory hierarchy for the system directory.
Do by specifying ".../" with '-m' or MAKESYSPATH (new) environment variable. Reviewed by: <sjg@NetBSD.org> Obtained from: NetBSD (+ embellishment by me, sent back to NetBSD)
Diffstat (limited to 'usr.bin/make')
-rw-r--r--usr.bin/make/dir.c83
-rw-r--r--usr.bin/make/dir.h1
-rw-r--r--usr.bin/make/main.c52
-rw-r--r--usr.bin/make/make.133
4 files changed, 158 insertions, 11 deletions
diff --git a/usr.bin/make/dir.c b/usr.bin/make/dir.c
index 9b529ea..7cee3d4 100644
--- a/usr.bin/make/dir.c
+++ b/usr.bin/make/dir.c
@@ -61,6 +61,10 @@ __FBSDID("$FreeBSD$");
* If it exists, the entire path is returned.
* Otherwise NULL is returned.
*
+ * Dir_FindHereOrAbove Search for a path in the current directory and
+ * then all the directories above it in turn until
+ * the path is found or we reach the root ("/").
+ *
* Dir_MTime Return the modification time of a node. The file
* is searched for along the default search path.
* The path and mtime fields of the node are filled in.
@@ -83,7 +87,7 @@ __FBSDID("$FreeBSD$");
* Dir_PrintDirectories Print stats about the directory cache.
*/
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/stat.h>
#include <dirent.h>
#include <err.h>
@@ -851,6 +855,83 @@ Path_FindFile(char *name, struct Path *path)
/*-
*-----------------------------------------------------------------------
+ * Dir_FindHereOrAbove --
+ * search for a path starting at a given directory and then working
+ * our way up towards the root.
+ *
+ * Input:
+ * here starting directory
+ * search_path the path we are looking for
+ * result the result of a successful search is placed here
+ * rlen the length of the result buffer
+ * (typically MAXPATHLEN + 1)
+ *
+ * Results:
+ * 0 on failure, 1 on success [in which case the found path is put
+ * in the result buffer].
+ *
+ * Side Effects:
+ *-----------------------------------------------------------------------
+ */
+int
+Dir_FindHereOrAbove(char *here, char *search_path, char *result, int rlen)
+{
+ struct stat st;
+ char dirbase[MAXPATHLEN + 1], *db_end;
+ char try[MAXPATHLEN + 1], *try_end;
+
+ /* copy out our starting point */
+ snprintf(dirbase, sizeof(dirbase), "%s", here);
+ db_end = dirbase + strlen(dirbase);
+
+ /* loop until we determine a result */
+ while (1) {
+ /* try and stat(2) it ... */
+ snprintf(try, sizeof(try), "%s/%s", dirbase, search_path);
+ if (stat(try, &st) != -1) {
+ /*
+ * Success! If we found a file, chop off
+ * the filename so we return a directory.
+ */
+ if ((st.st_mode & S_IFMT) != S_IFDIR) {
+ try_end = try + strlen(try);
+ while (try_end > try && *try_end != '/')
+ try_end--;
+ if (try_end > try)
+ *try_end = 0; /* chop! */
+ }
+
+ /*
+ * Done!
+ */
+ snprintf(result, rlen, "%s", try);
+ return(1);
+ }
+
+ /*
+ * Nope, we didn't find it. If we used up dirbase we've
+ * reached the root and failed.
+ */
+ if (db_end == dirbase)
+ break; /* Failed! */
+
+ /*
+ * truncate dirbase from the end to move up a dir
+ */
+ while (db_end > dirbase && *db_end != '/')
+ db_end--;
+ *db_end = 0; /* chop! */
+
+ } /* while (1) */
+
+ /*
+ * We failed...
+ */
+ return(0);
+}
+
+/*-
+ *-----------------------------------------------------------------------
* Dir_MTime --
* Find the modification time of the file described by gn along the
* search path dirSearchPath.
diff --git a/usr.bin/make/dir.h b/usr.bin/make/dir.h
index 03481b8..1ae89ae 100644
--- a/usr.bin/make/dir.h
+++ b/usr.bin/make/dir.h
@@ -56,6 +56,7 @@ TAILQ_HEAD(Path, PathElement);
void Dir_Init(void);
void Dir_InitDot(void);
Boolean Dir_HasWildcards(const char *);
+int Dir_FindHereOrAbove(char *, char *, char *, int);
int Dir_MTime(struct GNode *);
void Dir_PrintDirectories(void);
diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c
index eec6bbf..91638d4 100644
--- a/usr.bin/make/main.c
+++ b/usr.bin/make/main.c
@@ -368,6 +368,7 @@ MainParseArgs(int argc, char **argv)
{
int c;
Boolean found_dd = FALSE;
+ char found_dir[MAXPATHLEN + 1]; /* for searching for sys.mk */
rearg:
optind = 1; /* since we're called more than once */
@@ -394,6 +395,8 @@ rearg:
case 'C':
if (chdir(optarg) == -1)
err(1, "chdir %s", optarg);
+ if (getcwd(curdir, MAXPATHLEN) == NULL)
+ err(2, NULL);
break;
case 'D':
Var_SetGlobal(optarg, "1");
@@ -492,7 +495,15 @@ rearg:
MFLAGS_append("-k", NULL);
break;
case 'm':
- Path_AddDir(&sysIncPath, optarg);
+ /* look for magic parent directory search string */
+ if (strncmp(".../", optarg, 4) == 0) {
+ if (!Dir_FindHereOrAbove(curdir, optarg + 4,
+ found_dir, sizeof(found_dir)))
+ break; /* nothing doing */
+ Path_AddDir(&sysIncPath, found_dir);
+ } else {
+ Path_AddDir(&sysIncPath, optarg);
+ }
MFLAGS_append("-m", optarg);
break;
case 'n':
@@ -869,6 +880,7 @@ main(int argc, char **argv)
char mdpath[MAXPATHLEN];
char obpath[MAXPATHLEN];
char cdpath[MAXPATHLEN];
+ char found_dir[MAXPATHLEN + 1]; /* for searching for sys.mk */
char *cp = NULL, *start;
save_argv = argv;
@@ -1022,6 +1034,12 @@ main(int argc, char **argv)
Job_SetPrefix();
/*
+ * Find where we are...
+ */
+ if (getcwd(curdir, MAXPATHLEN) == NULL)
+ err(2, NULL);
+
+ /*
* First snag things out of the MAKEFLAGS environment
* variable. Then parse the command line arguments.
*/
@@ -1030,11 +1048,8 @@ main(int argc, char **argv)
MainParseArgs(argc, argv);
/*
- * Find where we are...
+ * Verify that cwd is sane (after -C may have changed it).
*/
- if (getcwd(curdir, MAXPATHLEN) == NULL)
- err(2, NULL);
-
{
struct stat sa;
@@ -1132,18 +1147,37 @@ main(int argc, char **argv)
* as dir1:...:dirn) to the system include path.
*/
if (TAILQ_EMPTY(&sysIncPath)) {
- char syspath[] = PATH_DEFSYSPATH;
+ char defsyspath[] = PATH_DEFSYSPATH;
+ char *syspath = getenv("MAKESYSPATH");
+
+ /*
+ * If no user-supplied system path was given (thru -m option)
+ * add the directories from the DEFSYSPATH (more than one may
+ * be given as dir1:...:dirn) to the system include path.
+ */
+ if (syspath == NULL || *syspath == '\0')
+ syspath = defsyspath;
+ else
+ syspath = estrdup(syspath);
for (start = syspath; *start != '\0'; start = cp) {
for (cp = start; *cp != '\0' && *cp != ':'; cp++)
continue;
- if (*cp == '\0') {
- Path_AddDir(&sysIncPath, start);
- } else {
+ if (*cp == ':') {
*cp++ = '\0';
+ }
+ /* look for magic parent directory search string */
+ if (strncmp(".../", start, 4) == 0) {
+ if (Dir_FindHereOrAbove(curdir, start + 4,
+ found_dir, sizeof(found_dir))) {
+ Path_AddDir(&sysIncPath, found_dir);
+ }
+ } else {
Path_AddDir(&sysIncPath, start);
}
}
+ if (syspath != defsyspath)
+ free(syspath);
}
/*
diff --git a/usr.bin/make/make.1 b/usr.bin/make/make.1
index a4e837c..2c478a3 100644
--- a/usr.bin/make/make.1
+++ b/usr.bin/make/make.1
@@ -240,6 +240,36 @@ The system include path will always be appended to the search path used
for "..."-style inclusions and makefile searches (see the
.Fl I
option).
+.Pp
+If a file or directory name in the
+.Fl m
+argument (or the
+.Ev MAKESYSPATH
+environment variable) starts with the string
+.Qq \&.../
+then
+.Nm
+will search for the specified file or directory named in the remaining part
+of the argument string.
+The search starts with the current directory of the Makefile and then works
+upward towards the root of the filesystem.
+If the search is successful,
+then the resulting directory replaces the
+.Qq \&.../
+specification in the
+.Fl m
+argument.
+If used, this feature allows
+.Nm
+to easily search in the current source tree for customized sys.mk files
+(e.g. by using
+.Qq \&.../mk/sys.mk
+as an argument).
+Note that a
+.Fl C
+that are earlier on the command line affect where
+.Fl m Qq \&.../
+searches.
.It Fl n
Display the commands that would have been executed, but do not actually
execute them.
@@ -1665,8 +1695,9 @@ utility uses the following environment variables, if they exist:
.Ev MAKE ,
.Ev MAKEFLAGS ,
.Ev MAKEOBJDIR ,
+.Ev MAKEOBJDIRPREFIX ,
and
-.Ev MAKEOBJDIRPREFIX .
+.Ev MAKESYSPATH .
.Sh FILES
.Bl -tag -width /usr/share/doc/psd/12.make -compact
.It Pa .depend
OpenPOWER on IntegriCloud