diff options
author | Ron Yorston <rmy@pobox.com> | 2024-04-21 10:58:52 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2024-04-21 11:05:12 +0100 |
commit | acda99ca9984570b03825c295a5617e67f0c1d7c (patch) | |
tree | e614f7774b03094330c854b95a8626a8d48a93a6 | |
parent | 90c5352a9746ee76d6219528e00ef5ef39d9dee4 (diff) | |
download | busybox-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.c | 38 | ||||
-rwxr-xr-x | testsuite/make.tests | 11 |
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 | */ |
2690 | static char ** | 2692 | static char ** |
2691 | process_macros(char **argv, int level) | 2693 | process_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 | ||
508 | testing "make allow mixed macros and targets" \ | ||
509 | "make -f - FOO=foo foo BAR=bar bar" "foo\nbar\nfoo\nbar\n" "" ' | ||
510 | foo: | ||
511 | @echo $(FOO) | ||
512 | @echo $(BAR) | ||
513 | bar: | ||
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. |