aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2024-04-21 10:58:52 +0100
committerRon Yorston <rmy@pobox.com>2024-04-21 11:05:12 +0100
commitacda99ca9984570b03825c295a5617e67f0c1d7c (patch)
treee614f7774b03094330c854b95a8626a8d48a93a6
parent90c5352a9746ee76d6219528e00ef5ef39d9dee4 (diff)
downloadbusybox-w32-acda99ca9984570b03825c295a5617e67f0c1d7c.tar.gz
busybox-w32-acda99ca9984570b03825c295a5617e67f0c1d7c.tar.bz2
busybox-w32-acda99ca9984570b03825c295a5617e67f0c1d7c.zip
make: allow mixed macros and targets on command line
POSIX requires macro definitions to appear before targets on the command line. Allow mixed macros and targets as an extension. All macros on the command line are read first, then the targets are processed. Costs 64-80 bytes. (GitHub issue #406)
-rw-r--r--miscutils/make.c38
-rwxr-xr-xtestsuite/make.tests11
2 files changed, 41 insertions, 8 deletions
diff --git a/miscutils/make.c b/miscutils/make.c
index cc35d89eb..97ee8d879 100644
--- a/miscutils/make.c
+++ b/miscutils/make.c
@@ -2686,15 +2686,26 @@ expand_makeflags(void)
2686/* 2686/*
2687 * Instantiate all macros in an argv-style array of pointers. Stop 2687 * Instantiate all macros in an argv-style array of pointers. Stop
2688 * processing at the first string that doesn't contain an equal sign. 2688 * processing at the first string that doesn't contain an equal sign.
2689 * As an extension, target arguments on the command line (level 1)
2690 * are skipped and will be processed later.
2689 */ 2691 */
2690static char ** 2692static char **
2691process_macros(char **argv, int level) 2693process_macros(char **argv, int level)
2692{ 2694{
2693 char *p; 2695 char *p;
2694 2696
2695 while (*argv && (p = strchr(*argv, '=')) != NULL) { 2697 for (; *argv; argv++) {
2696 int immediate = 0; 2698 int immediate = 0;
2697 2699
2700 if (!(p = strchr(*argv, '='))) {
2701 // Skip targets on the command line
2702 if (!posix && level == 1)
2703 continue;
2704 else
2705 // Stop at first target
2706 break;
2707 }
2708
2698 if (p - 2 > *argv && p[-1] == ':' && p[-2] == ':') { 2709 if (p - 2 > *argv && p[-1] == ':' && p[-2] == ':') {
2699 if (POSIX_2017) 2710 if (POSIX_2017)
2700 error("invalid macro assignment"); 2711 error("invalid macro assignment");
@@ -2714,8 +2725,6 @@ process_macros(char **argv, int level)
2714 *p = '='; 2725 *p = '=';
2715 if (immediate) 2726 if (immediate)
2716 p[-2] = ':'; 2727 p[-2] = ':';
2717
2718 argv++;
2719 } 2728 }
2720 return argv; 2729 return argv;
2721} 2730}
@@ -2846,6 +2855,7 @@ int make_main(int argc UNUSED_PARAM, char **argv)
2846#endif 2855#endif
2847 char def_make[] = "makefile"; 2856 char def_make[] = "makefile";
2848 int estat; 2857 int estat;
2858 bool found_target;
2849 FILE *ifd; 2859 FILE *ifd;
2850 2860
2851 INIT_G(); 2861 INIT_G();
@@ -2923,7 +2933,12 @@ int make_main(int argc UNUSED_PARAM, char **argv)
2923 setmacro("$", "$", 0 | M_VALID); 2933 setmacro("$", "$", 0 | M_VALID);
2924 2934
2925 // Process macro definitions from the command line 2935 // Process macro definitions from the command line
2926 argv = process_macros(argv, 1); 2936 if (posix)
2937 // In POSIX mode macros must appear before targets.
2938 // argv should now point to targets only.
2939 argv = process_macros(argv, 1);
2940 else
2941 process_macros(argv, 1);
2927 2942
2928 // Process macro definitions from MAKEFLAGS 2943 // Process macro definitions from MAKEFLAGS
2929 if (fargv) { 2944 if (fargv) {
@@ -2983,13 +2998,20 @@ int make_main(int argc UNUSED_PARAM, char **argv)
2983 mark_special(".PHONY", OPT_phony, N_PHONY); 2998 mark_special(".PHONY", OPT_phony, N_PHONY);
2984 2999
2985 estat = 0; 3000 estat = 0;
2986 if (*argv == NULL) { 3001 found_target = FALSE;
3002 for (; *argv; argv++) {
3003 // In POSIX mode only targets should now be in argv.
3004 // As an extension macros may still be present: skip them.
3005 if (posix || !strchr(*argv, '='))
3006 {
3007 found_target = TRUE;
3008 estat |= make(newname(*argv), 0);
3009 }
3010 }
3011 if (!found_target) {
2987 if (!firstname) 3012 if (!firstname)
2988 error("no targets defined"); 3013 error("no targets defined");
2989 estat = make(firstname, 0); 3014 estat = make(firstname, 0);
2990 } else {
2991 while (*argv != NULL)
2992 estat |= make(newname(*argv++), 0);
2993 } 3015 }
2994 3016
2995#if ENABLE_FEATURE_CLEAN_UP 3017#if ENABLE_FEATURE_CLEAN_UP
diff --git a/testsuite/make.tests b/testsuite/make.tests
index c512fbdaa..546dca7d5 100755
--- a/testsuite/make.tests
+++ b/testsuite/make.tests
@@ -504,6 +504,17 @@ target:
504 @false; echo OK 504 @false; echo OK
505' 505'
506 506
507# Macros and targets may be mixed on the command line
508testing "make allow mixed macros and targets" \
509 "make -f - FOO=foo foo BAR=bar bar" "foo\nbar\nfoo\nbar\n" "" '
510foo:
511 @echo $(FOO)
512 @echo $(BAR)
513bar:
514 @echo $(FOO)
515 @echo $(BAR)
516'
517
507# An empty original suffix indicates that every word should have 518# An empty original suffix indicates that every word should have
508# the new suffix added. If neither suffix is provided the words 519# the new suffix added. If neither suffix is provided the words
509# remain unchanged. 520# remain unchanged.