Better Makefile target detection (#8223)
Replace regex-based target detection for Makefiles with a preliminary "make -q" to check if a target exists. This does not work for NetBSD make; additional work is required to detect if NetBSD make is present and to use a regex in that case. The affected makefile target checks are only performed when the "--test" flag is added to a "spack install" invocation.
This commit is contained in:
parent
af8dde4dda
commit
a67139f6c5
@ -1288,43 +1288,68 @@ def do_fake_install(self):
|
|||||||
dump_packages(self.spec, packages_dir)
|
dump_packages(self.spec, packages_dir)
|
||||||
|
|
||||||
def _if_make_target_execute(self, target):
|
def _if_make_target_execute(self, target):
|
||||||
try:
|
make = inspect.getmodule(self).make
|
||||||
# Check if we have a makefile
|
|
||||||
file = [x for x in ('Makefile', 'makefile') if os.path.exists(x)]
|
# Check if we have a Makefile
|
||||||
file = file.pop()
|
for makefile in ['GNUmakefile', 'Makefile', 'makefile']:
|
||||||
except IndexError:
|
if os.path.exists(makefile):
|
||||||
|
break
|
||||||
|
else:
|
||||||
tty.msg('No Makefile found in the build directory')
|
tty.msg('No Makefile found in the build directory')
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check if 'target' is in the makefile
|
# Check if 'target' is a valid target
|
||||||
regex = re.compile('^' + target + ':')
|
#
|
||||||
with open(file, 'r') as f:
|
# -q, --question
|
||||||
matches = [line for line in f.readlines() if regex.match(line)]
|
# ``Question mode''. Do not run any commands, or print anything;
|
||||||
|
# just return an exit status that is zero if the specified
|
||||||
if not matches:
|
# targets are already up to date, nonzero otherwise.
|
||||||
tty.msg("Target '" + target + ":' not found in Makefile")
|
#
|
||||||
|
# https://www.gnu.org/software/make/manual/html_node/Options-Summary.html
|
||||||
|
#
|
||||||
|
# The exit status of make is always one of three values:
|
||||||
|
#
|
||||||
|
# 0 The exit status is zero if make is successful.
|
||||||
|
#
|
||||||
|
# 2 The exit status is two if make encounters any errors.
|
||||||
|
# It will print messages describing the particular errors.
|
||||||
|
#
|
||||||
|
# 1 The exit status is one if you use the '-q' flag and make
|
||||||
|
# determines that some target is not already up to date.
|
||||||
|
#
|
||||||
|
# https://www.gnu.org/software/make/manual/html_node/Running.html
|
||||||
|
#
|
||||||
|
# NOTE: This only works for GNU Make, not NetBSD Make.
|
||||||
|
make('-q', target, fail_on_error=False)
|
||||||
|
if make.returncode == 2:
|
||||||
|
tty.msg("Target '" + target + "' not found in " + makefile)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Execute target
|
# Execute target
|
||||||
inspect.getmodule(self).make(target)
|
make(target)
|
||||||
|
|
||||||
def _if_ninja_target_execute(self, target):
|
def _if_ninja_target_execute(self, target):
|
||||||
# Check if we have a ninja build script
|
ninja = inspect.getmodule(self).ninja
|
||||||
|
|
||||||
|
# Check if we have a Ninja build script
|
||||||
if not os.path.exists('build.ninja'):
|
if not os.path.exists('build.ninja'):
|
||||||
tty.msg('No ninja build script found in the build directory')
|
tty.msg('No Ninja build script found in the build directory')
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check if 'target' is in the ninja build script
|
# Get a list of all targets in the Ninja build script
|
||||||
regex = re.compile('^build ' + target + ':')
|
# https://ninja-build.org/manual.html#_extra_tools
|
||||||
with open('build.ninja', 'r') as f:
|
all_targets = ninja('-t', 'targets', output=str).split('\n')
|
||||||
matches = [line for line in f.readlines() if regex.match(line)]
|
|
||||||
|
# Check if 'target' is a valid target
|
||||||
|
matches = [line for line in all_targets
|
||||||
|
if line.startswith(target + ':')]
|
||||||
|
|
||||||
if not matches:
|
if not matches:
|
||||||
tty.msg("Target 'build " + target + ":' not found in build.ninja")
|
tty.msg("Target '" + target + "' not found in build.ninja")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Execute target
|
# Execute target
|
||||||
inspect.getmodule(self).ninja(target)
|
ninja(target)
|
||||||
|
|
||||||
def _get_needed_resources(self):
|
def _get_needed_resources(self):
|
||||||
resources = []
|
resources = []
|
||||||
|
Loading…
Reference in New Issue
Block a user