diff --git a/tools/regression/usr.bin/make/common.sh b/tools/regression/usr.bin/make/common.sh index 34aacf8f22e7..e685ea1197a7 100644 --- a/tools/regression/usr.bin/make/common.sh +++ b/tools/regression/usr.bin/make/common.sh @@ -233,6 +233,12 @@ reset_test() # eval_clean() { + # + # If you have special cleaning needs, provide a 'cleanup' shell script. + # + if [ -n "${TEST_CLEANUP}" ] ; then + . ${SRC_DIR}/cleanup + fi rm -rf ${WORK_DIR} rm -rf ${OUTPUT_DIR} } diff --git a/tools/regression/usr.bin/make/sysmk/t0/2/1/Makefile b/tools/regression/usr.bin/make/sysmk/t0/2/1/Makefile new file mode 100644 index 000000000000..fc95f46e679e --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t0/2/1/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ +# +# Can we traverse up to / and find a 'mk/sys.mk'? +# +all: + @echo ${DASH_M_DOTDOTDOT} diff --git a/tools/regression/usr.bin/make/sysmk/t0/2/1/expected.status.1 b/tools/regression/usr.bin/make/sysmk/t0/2/1/expected.status.1 new file mode 100644 index 000000000000..573541ac9702 --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t0/2/1/expected.status.1 @@ -0,0 +1 @@ +0 diff --git a/tools/regression/usr.bin/make/sysmk/t0/2/1/expected.stderr.1 b/tools/regression/usr.bin/make/sysmk/t0/2/1/expected.stderr.1 new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tools/regression/usr.bin/make/sysmk/t0/2/1/expected.stdout.1 b/tools/regression/usr.bin/make/sysmk/t0/2/1/expected.stdout.1 new file mode 100644 index 000000000000..6f29307aecc3 --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t0/2/1/expected.stdout.1 @@ -0,0 +1 @@ +Found_DotDotDot_sys_mk diff --git a/tools/regression/usr.bin/make/sysmk/t0/2/1/test.t b/tools/regression/usr.bin/make/sysmk/t0/2/1/test.t new file mode 100644 index 000000000000..9a781570fd15 --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t0/2/1/test.t @@ -0,0 +1,17 @@ +#!/bin/sh + +# $FreeBSD$ + +cd `dirname $0` +. ../../../../common.sh + +# Description +DESC="Can we traverse up to / and find a 'mk/sys.mk'?" + +# Run +TEST_N=1 +TEST_1="-m .../mk" +TEST_MAKE_DIRS="../../mk 755" +TEST_COPY_FILES="../../mk/sys.mk 644" + +eval_cmd $* diff --git a/tools/regression/usr.bin/make/sysmk/t0/mk/sys.mk b/tools/regression/usr.bin/make/sysmk/t0/mk/sys.mk new file mode 100644 index 000000000000..60f195533ed2 --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t0/mk/sys.mk @@ -0,0 +1,3 @@ +# $FreeBSD$ + +DASH_M_DOTDOTDOT=Found_DotDotDot_sys_mk diff --git a/tools/regression/usr.bin/make/sysmk/t1/2/1/cleanup b/tools/regression/usr.bin/make/sysmk/t1/2/1/cleanup new file mode 100644 index 000000000000..c3d58b79e422 --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t1/2/1/cleanup @@ -0,0 +1,3 @@ +# $FreeBSD$ + +rm -rf ${WORK_DIR}/../../../t0/2/1 diff --git a/tools/regression/usr.bin/make/sysmk/t1/2/1/expected.status.1 b/tools/regression/usr.bin/make/sysmk/t1/2/1/expected.status.1 new file mode 100644 index 000000000000..573541ac9702 --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t1/2/1/expected.status.1 @@ -0,0 +1 @@ +0 diff --git a/tools/regression/usr.bin/make/sysmk/t1/2/1/expected.stderr.1 b/tools/regression/usr.bin/make/sysmk/t1/2/1/expected.stderr.1 new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tools/regression/usr.bin/make/sysmk/t1/2/1/expected.stdout.1 b/tools/regression/usr.bin/make/sysmk/t1/2/1/expected.stdout.1 new file mode 100644 index 000000000000..6f29307aecc3 --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t1/2/1/expected.stdout.1 @@ -0,0 +1 @@ +Found_DotDotDot_sys_mk diff --git a/tools/regression/usr.bin/make/sysmk/t1/2/1/test.t b/tools/regression/usr.bin/make/sysmk/t1/2/1/test.t new file mode 100644 index 000000000000..ad1584f82d1d --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t1/2/1/test.t @@ -0,0 +1,19 @@ +#!/bin/sh + +# $FreeBSD$ + +cd `dirname $0` +. ../../../../common.sh + +# Description +DESC="Can we traverse up to / and find a 'mk/sys.mk' with -C -m?" + +# Run +TEST_N=1 +TEST_1="-C ../../../t0/2/1 -m .../mk" +TEST_MAKE_DIRS="../../mk 755 ../../../t0/mk 755 ../../../t0/2/1 755" +TEST_COPY_FILES="../../mk/sys.mk 644 ../../../t0/mk/sys.mk 644 ../../../t0/2/1/Makefile 644" +TEST_CLEAN_FILES="../../../t0/2/1" +TEST_CLEANUP=clean-special + +eval_cmd $* diff --git a/tools/regression/usr.bin/make/sysmk/t1/mk/sys.mk b/tools/regression/usr.bin/make/sysmk/t1/mk/sys.mk new file mode 100644 index 000000000000..99b8ecc1d389 --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t1/mk/sys.mk @@ -0,0 +1,3 @@ +# $FreeBSD$ + +DASH_M_DOTDOTDOT=Found_WRONG_DotDotDot_sys_mk__with_C_before_m diff --git a/tools/regression/usr.bin/make/sysmk/t2/2/1/cleanup b/tools/regression/usr.bin/make/sysmk/t2/2/1/cleanup new file mode 100644 index 000000000000..c3d58b79e422 --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t2/2/1/cleanup @@ -0,0 +1,3 @@ +# $FreeBSD$ + +rm -rf ${WORK_DIR}/../../../t0/2/1 diff --git a/tools/regression/usr.bin/make/sysmk/t2/2/1/expected.status.1 b/tools/regression/usr.bin/make/sysmk/t2/2/1/expected.status.1 new file mode 100644 index 000000000000..573541ac9702 --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t2/2/1/expected.status.1 @@ -0,0 +1 @@ +0 diff --git a/tools/regression/usr.bin/make/sysmk/t2/2/1/expected.stderr.1 b/tools/regression/usr.bin/make/sysmk/t2/2/1/expected.stderr.1 new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tools/regression/usr.bin/make/sysmk/t2/2/1/expected.stdout.1 b/tools/regression/usr.bin/make/sysmk/t2/2/1/expected.stdout.1 new file mode 100644 index 000000000000..70f1be3c507c --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t2/2/1/expected.stdout.1 @@ -0,0 +1 @@ +Found_DotDotDot_sys_mk__with_m_before_C diff --git a/tools/regression/usr.bin/make/sysmk/t2/2/1/test.t b/tools/regression/usr.bin/make/sysmk/t2/2/1/test.t new file mode 100644 index 000000000000..2c4dff35bde1 --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t2/2/1/test.t @@ -0,0 +1,19 @@ +#!/bin/sh + +# $FreeBSD$ + +cd `dirname $0` +. ../../../../common.sh + +# Description +DESC="Can we traverse up to / and find a 'mk/sys.mk' with -m -C?" + +# Run +TEST_N=1 +TEST_1="-m .../mk -C ../../../t0/2/1" +TEST_MAKE_DIRS="../../mk 755 ../../../t0/mk 755 ../../../t0/2/1 755" +TEST_COPY_FILES="../../mk/sys.mk 644 ../../../t0/mk/sys.mk 644 ../../../t0/2/1/Makefile 644" +TEST_CLEAN_FILES="../../../t0/2/1" +TEST_CLEANUP=clean-special + +eval_cmd $* diff --git a/tools/regression/usr.bin/make/sysmk/t2/mk/sys.mk b/tools/regression/usr.bin/make/sysmk/t2/mk/sys.mk new file mode 100644 index 000000000000..55632fdc90a4 --- /dev/null +++ b/tools/regression/usr.bin/make/sysmk/t2/mk/sys.mk @@ -0,0 +1,3 @@ +# $FreeBSD$ + +DASH_M_DOTDOTDOT=Found_DotDotDot_sys_mk__with_m_before_C diff --git a/usr.bin/make/dir.c b/usr.bin/make/dir.c index 9b529ea5fc57..7cee3d461e2b 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 +#include #include #include #include @@ -849,6 +853,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 -- diff --git a/usr.bin/make/dir.h b/usr.bin/make/dir.h index 03481b869790..1ae89aeac61e 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 eec6bbf1e247..91638d4212bf 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 @@ MainParseArgs(int argc, char **argv) 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 @@ MainParseArgs(int argc, char **argv) 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; @@ -1021,6 +1033,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 a4e837ceba49..2c478a3d1e7a 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