[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH v3 1/1] Support per-target .ONESHELL
From: |
Britton Leo Kerin |
Subject: |
[RFC PATCH v3 1/1] Support per-target .ONESHELL |
Date: |
Mon, 18 Nov 2024 12:06:22 -0900 |
.ONESHELL is now handled entirely in snap_deps(). I don't think
it ever needs to happen as early as check_specials(), and doing
it in snap_deps() is easier and allows a good warning to be given
if it's used with a dependency that doesn't end up with a recipe.
The per target oneshell flag has been added to struct commands rather
than struct file. This results in the flag being easily availabe where
needed without many function signature changes. It's entirely
appropriate at the semantic level since .ONESHELL's effects are entirely
confined to the recipe part of the rule (unlike most other directives),
but slightly weird syntacticly sinced the directive is parsed as a file
target. But this oddity is intrinsic to Make's strategy of repurposing
the target-dependency sytax for directives.
---
src/commands.c | 2 +-
src/commands.h | 2 ++
src/file.c | 17 +++++++++++++++++
src/job.c | 24 ++++++++++++++++--------
src/main.c | 9 +++++----
src/makeint.h | 2 +-
src/read.c | 8 --------
7 files changed, 42 insertions(+), 22 deletions(-)
diff --git a/src/commands.c b/src/commands.c
index 343c1cb5..54c3ef1e 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -332,7 +332,7 @@ chop_commands (struct commands *cmds)
/* Chop CMDS->commands up into lines in CMDS->command_lines. */
- if (one_shell)
+ if (all_one_shell || cmds->oneshell)
{
size_t l = strlen (cmds->commands);
diff --git a/src/commands.h b/src/commands.h
index 9451b68b..84528c97 100644
--- a/src/commands.h
+++ b/src/commands.h
@@ -27,6 +27,8 @@ struct commands
char recipe_prefix; /* Recipe prefix for this command set. */
unsigned int any_recurse:1; /* Nonzero if any 'lines_flags' elt has */
/* the COMMANDS_RECURSE bit set. */
+ unsigned int oneshell:1; /* Nonzero means entire recipe should be run in
+ one shell. */
};
/* Bits in 'lines_flags'. */
diff --git a/src/file.c b/src/file.c
index 6f816c8a..dd9afef5 100644
--- a/src/file.c
+++ b/src/file.c
@@ -830,6 +830,23 @@ snap_deps (void)
else
no_intermediates = 1;
+#if !MK_OS_DOS && !MK_OS_OS2
+ for (f = lookup_file (".ONESHELL"); f != 0; f = f->prev)
+ if (f->deps)
+ for (d = f->deps; d != 0; d = d->next)
+ for (f2 = d->file; f2 != 0; f2 = f2->prev)
+ if ( f2->cmds )
+ f2->cmds->oneshell = 1;
+ else
+ OS (error, NILF,
+ _("%s doesn't have a recipe so the dependence of .ONESHELL on "
+ "it has no effect"),
+ f2->name);
+ /* .ONESHELL with no deps listd marks *all* files that way. */
+ else
+ all_one_shell = 1;
+#endif
+
/* The same file cannot be both .INTERMEDIATE and .NOTINTERMEDIATE.
However, it is possible for a file to be .INTERMEDIATE and also match a
.NOTINTERMEDIATE pattern. In that case, the intermediate file has
diff --git a/src/job.c b/src/job.c
index e54a9340..739cb3d8 100644
--- a/src/job.c
+++ b/src/job.c
@@ -1236,7 +1236,7 @@ start_job_command (struct child *child)
still includes the newlines. So detect newlines and set 'end' (which
is used for child->command_ptr) instead of (re-)writing
construct_command_argv */
- if (!one_shell)
+ if (!(all_one_shell || child->file->cmds->oneshell))
{
char *s = p;
int instring = 0;
@@ -2686,6 +2686,9 @@ exec_command (char **argv, char **envp)
If RESTP is not NULL, *RESTP is set to point to the first newline in LINE.
If *RESTP is NULL, newlines will be ignored.
+ ONE_SHELL should be true iff all the commands are to be executed in a single
+ shell, or false otherwise.
+
SHELL is the shell to use, or nil to use the default shell.
IFS is the value of $IFS, or nil (meaning the default).
@@ -2699,9 +2702,10 @@ exec_command (char **argv, char **envp)
(see the FREE_ARGV macro). */
static char **
-construct_command_argv_internal (char *line, char **restp, const char *shell,
- const char *shellflags, const char *ifs,
- int flags, char **batch_filename UNUSED)
+construct_command_argv_internal (char *line, char **restp, int one_shell,
+ const char *shell, const char *shellflags,
+ const char *ifs, int flags,
+ char **batch_filename UNUSED)
{
#if MK_OS_DOS
/* MSDOS supports both the stock DOS shell and ports of Unixy shells.
@@ -3374,7 +3378,7 @@ construct_command_argv_internal (char *line, char
**restp, const char *shell,
char **argv;
char *f = alloca (sflags_len + 1);
memcpy (f, shellflags, sflags_len + 1);
- argv = construct_command_argv_internal (f, 0, 0, 0, 0, flags, 0);
+ argv = construct_command_argv_internal (f, 0, one_shell, 0, 0,
0, flags, 0);
if (argv)
{
char **a;
@@ -3529,7 +3533,7 @@ construct_command_argv_internal (char *line, char
**restp, const char *shell,
#endif /* MK_OS_W32 */
if (unixy_shell)
- new_argv = construct_command_argv_internal (new_line, 0, 0, 0, 0,
+ new_argv = construct_command_argv_internal (new_line, 0, one_shell, 0,
0, 0,
flags, 0);
#if MK_OS_OS2
@@ -3727,8 +3731,12 @@ construct_command_argv (char *line, char **restp, struct
file *file,
warn_set (wt_undefined_var, save);
}
- argv = construct_command_argv_internal (line, restp, shell, shellflags, ifs,
- cmd_flags, batch_filename);
+ assert (file->cmds != NULL);
+
+ argv = construct_command_argv_internal (line, restp,
+ all_one_shell ||
file->cmds->oneshell,
+ shell, shellflags, ifs, cmd_flags,
+ batch_filename);
free (shell);
free (allocflags);
diff --git a/src/main.c b/src/main.c
index 78084d09..9c064c26 100644
--- a/src/main.c
+++ b/src/main.c
@@ -587,11 +587,12 @@ int posix_pedantic;
int second_expansion;
-/* Nonzero if we have seen the '.ONESHELL' target.
- This causes the entire recipe to be handed to SHELL
- as a single string, potentially containing newlines. */
+/* Nonzero if we have seen the '.ONESHELL' target without
+ prerequisites. For all targets, this causes the entire
+ recipe to be handed to SHELL as a single string, potentially
+ containing newlines. */
-int one_shell;
+int all_one_shell;
/* One of OUTPUT_SYNC_* if the "--output-sync" option was given. This
attempts to synchronize the output of parallel jobs such that the results
diff --git a/src/makeint.h b/src/makeint.h
index 61c78229..41102e43 100644
--- a/src/makeint.h
+++ b/src/makeint.h
@@ -734,7 +734,7 @@ extern int print_data_base_flag, question_flag, touch_flag,
always_make_flag;
extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag;
extern int print_version_flag, check_symlink_flag, posix_pedantic;
extern int not_parallel, second_expansion, clock_skew_detected;
-extern int rebuilding_makefiles, one_shell, output_sync, verify_flag;
+extern int rebuilding_makefiles, all_one_shell, output_sync, verify_flag;
extern int export_all_variables;
extern unsigned long command_count;
diff --git a/src/read.c b/src/read.c
index 2e30ce17..e00a4df6 100644
--- a/src/read.c
+++ b/src/read.c
@@ -1892,14 +1892,6 @@ check_specials (struct nameseq *files, int set_default)
continue;
}
-#if !MK_OS_DOS && !MK_OS_OS2
- if (!one_shell && streq (nm, ".ONESHELL"))
- {
- one_shell = 1;
- continue;
- }
-#endif
-
/* Determine if this target should be made default. */
if (set_default && default_goal_var->value[0] == '\0')
--
2.43.0