[SV 63552] Change directories before constructing include paths

* src/makeint.h (reset_makeflags): New function to handle changing
MAKEFLAGS from within makefiles.  Remove decode_env_switches().
* src/variable.c (set_special_var): Call reset_makeflags() instead
of various internal methods.
* src/main.c (decode_env_switches): Only internal now so make static.
(decode_switches): Don't invoke construct_include_path() yet.
(reset_makeflags): Decode env switches and construct include paths.
(main): Construct include paths after we process -C options.
* tests/scripts/options/dash-C: Rewrite to use new test constructs.
Add a test using both -C and -I together.
Add a test for multiple -C options.
This commit is contained in:
Paul Smith 2022-12-24 09:26:24 -05:00
parent a581146562
commit 76d2e5d98d
4 changed files with 53 additions and 57 deletions

View file

@ -107,6 +107,8 @@ static void print_data_base (void);
static void print_version (void);
static void decode_switches (int argc, const char **argv,
enum variable_origin origin);
static void decode_env_switches (const char *envar, size_t len,
enum variable_origin origin);
static char *quote_for_env (char *out, const char *in);
static void initialize_global_hash_tables (void);
@ -1818,6 +1820,10 @@ main (int argc, char **argv, char **envp)
define_variable_cname ("CURDIR", current_directory, o_file, 0);
/* Construct the list of include directories to search.
This will check for existence so it must be done after chdir. */
construct_include_path (include_dirs ? include_dirs->list : NULL);
/* Validate the arg_job_slots configuration before we define MAKEFLAGS so
users get an accurate value in their makefiles.
At this point arg_job_slots is the argv setting, if there is one, else
@ -3108,6 +3114,15 @@ handle_non_switch_argument (const char *arg, enum variable_origin origin)
}
}
/* Called if the makefile resets the MAKEFLAGS variable. */
void
reset_makeflags (enum variable_origin origin)
{
decode_env_switches (STRING_SIZE_TUPLE(MAKEFLAGS_NAME), origin);
construct_include_path (include_dirs ? include_dirs->list : NULL);
define_makeflags (rebuilding_makefiles);
}
/* Decode switches from ARGC and ARGV.
They came from the environment if ORIGIN is o_env. */
@ -3350,9 +3365,6 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
/* Perform any special switch handling. */
run_silent = silent_flag;
/* Construct the list of include directories to search. */
construct_include_path (include_dirs ? include_dirs->list : NULL);
}
/* Decode switches from environment variable ENVAR (which is LEN chars long).
@ -3360,7 +3372,7 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
dash to the first word if it lacks one, and passing the vector to
decode_switches. */
void
static void
decode_env_switches (const char *envar, size_t len, enum variable_origin origin)
{
char *varref = alloca (2 + len + 2);

View file

@ -571,9 +571,9 @@ void out_of_memory (void) NORETURN;
(_f), (_n), (_s))
enum variable_origin;
void decode_env_switches (const char*, size_t line,
enum variable_origin origin);
struct variable;
void reset_makeflags (enum variable_origin origin);
struct variable *define_makeflags (int makefile);
int should_print_dir (void);
void temp_stdin_unlink (void);

View file

@ -1217,18 +1217,16 @@ target_environment (struct file *file, int recursive)
static struct variable *
set_special_var (struct variable *var, enum variable_origin origin)
{
if (streq (var->name, RECIPEPREFIX_NAME))
if (streq (var->name, MAKEFLAGS_NAME))
reset_makeflags (origin);
else if (streq (var->name, RECIPEPREFIX_NAME))
{
/* The user is resetting the command introduction prefix. This has to
happen immediately, so that subsequent rules are interpreted
properly. */
cmd_prefix = var->value[0]=='\0' ? RECIPEPREFIX_DEFAULT : var->value[0];
}
else if (streq (var->name, MAKEFLAGS_NAME))
{
decode_env_switches (STRING_SIZE_TUPLE(MAKEFLAGS_NAME), origin);
define_makeflags (rebuilding_makefiles);
}
return var;
}

View file

@ -2,65 +2,51 @@
$description = "Test the -C option to GNU make.";
$details = "\
This test is similar to the clean test except that this test creates the file
to delete in the work directory instead of the current directory. Make is
called from another directory using the -C workdir option so that it can both
find the makefile and the file to delete in the work directory.";
use File::Spec;
$example = $workdir . $pathsep . "EXAMPLE";
# Pre-set $makefile to be in a subdirectory
$makefile = 'Makefile';
open(MAKEFILE,"> $makefile");
print MAKEFILE qq!
all: ; \@echo This makefile did not clean the dir ... good
clean: ; $CMD_rmfile EXAMPLE\$(ext)
!;
close(MAKEFILE);
my $_srcdir = 'src';
mkdir($_srcdir, 0775);
my $_incdir = 'inc';
mkdir($_incdir, 0775);
my $_mkpath = File::Spec->catfile($_srcdir, $makefile);
create_file($_mkpath, "include \$(file)\nall: ;\n");
# TEST #1
# -------
touch($example);
run_make_with_options("${testname}.mk", "-C $workdir clean", &get_logfile);
use Cwd;
chdir $workdir;
$wpath = cwd();
chdir $cwdpath;
if (-f $example) {
$test_passed = 0;
}
# Create the answer to what should be produced by this Makefile
$answer = "$make_name: Entering directory '$wpath'\n"
. "$CMD_rmfile EXAMPLE\n"
. "$make_name: Leaving directory '$wpath'\n";
compare_output($answer,&get_logfile(1));
run_make_test('', "-C $_srcdir --no-print-directory",
"#MAKE#: 'all' is up to date.");
# TEST #2
# -------
# Do it again with trailing "/"; this should work the same
$example .= "slash";
run_make_test(undef, "-C $_srcdir/ --no-print-directory",
"#MAKE#: 'all' is up to date.");
touch($example);
# Test stringing together multiple -C options
run_make_with_options("${testname}.mk", "-C $workdir/ clean ext=slash", &get_logfile);
run_make_test(undef, "-C $_incdir -C .. -C $_srcdir --no-print-directory",
"#MAKE#: 'all' is up to date.");
if (-f $example) {
$test_passed = 0;
}
# SV 63552 - Ensure -I is considered after -C
# Create the answer to what should be produced by this Makefile
$answer = "$make_name: Entering directory '$wpath'\n"
. "$CMD_rmfile EXAMPLEslash\n"
. "$make_name: Leaving directory '$wpath'\n";
my $_incfile = 'test';
my $_incpath = File::Spec->catfile($_incdir, $_incfile);
create_file($_incpath, '$(info included)');
&compare_output($answer,&get_logfile(1));
my $_incopt = File::Spec->catfile('..', $_incdir);
unlink($example);
run_make_test(undef, "-C src -I $_incopt --no-print-directory file=$_incfile",
"included\n#MAKE#: 'all' is up to date.");
unlink($_incpath);
rmdir($_incdir);
unlink($_mkpath);
rmdir($_srcdir);
1;