Use argv[0] to internally relaunch meson.py

When installing Meson, distutils may choose to put shim scripts in the
`PATH` that only set up the egg requirements before launching the real
`meson.py` contained in the egg.

This means that `__file__` points to the real `meson.py` file, but
launching it directly is doomed to fail as it's missing the metadata
contained in the shim to set up the path egg, resulting in errors when
trying to import the `mesonbuild` module.

A similar issue affects Meson when installed as a zipapp, with the
current code going great lengths to figure out how to relaunch itself.

Using `argv[0]` avoids these issues as it gives us the way the current
executable has been launched, so we are pretty much guaranteed that
using it will create another instance of the same executable. We only
need to resolve relative paths as the current working directory may
get changed before re-launching the script, and using `realpath()` for
that saves us the trouble of manually resolving links and getting caught
in endless loops.

This also mean that `meson_script_file` no longer necessarily point to a
absolute file, so rename it to `_launcher` which hopefully would be less
prone to inducing false assumptions.
pull/874/head
Emanuele Aina 9 years ago committed by Jussi Pakkanen
parent cd6d5a642d
commit 6c50253645
  1. 1
      authors.txt
  2. 14
      meson.py
  3. 10
      mesonbuild/environment.py
  4. 12
      mesonbuild/mesonmain.py

@ -46,3 +46,4 @@ Patrick Griffis
Iain Lane
Daniel Brendle
Franz Zapata
Emanuele Aina

@ -15,13 +15,11 @@
# limitations under the License.
from mesonbuild import mesonmain
import sys, os
import sys, os, os.path
thisfile = __file__
if not os.path.isabs(thisfile):
thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile))
launcher = sys.argv[0]
# resolve the command path if not launched from $PATH
if os.path.split(launcher)[0]:
launcher = os.path.realpath(launcher)
# The first argument *must* be an absolute path because
# the user may have launched the program from a dir
# that is not in path.
sys.exit(mesonmain.run(thisfile, sys.argv[1:]))
sys.exit(mesonmain.run(launcher, sys.argv[1:]))

@ -179,12 +179,10 @@ class Environment():
coredata_file = os.path.join(private_dir, 'coredata.dat')
version_regex = '\d+(\.\d+)+(-[a-zA-Z0-9]+)?'
def __init__(self, source_dir, build_dir, main_script_file, options, original_cmd_line_args):
assert(os.path.isabs(main_script_file))
assert(not os.path.islink(main_script_file))
def __init__(self, source_dir, build_dir, main_script_launcher, options, original_cmd_line_args):
self.source_dir = source_dir
self.build_dir = build_dir
self.meson_script_file = main_script_file
self.meson_script_launcher = main_script_launcher
self.scratch_dir = os.path.join(build_dir, Environment.private_dir)
self.log_dir = os.path.join(build_dir, Environment.log_dir)
os.makedirs(self.scratch_dir, exist_ok=True)
@ -198,7 +196,7 @@ class Environment():
# re-initialized with project options by the interpreter during
# build file parsing.
self.coredata = coredata.CoreData(options)
self.coredata.meson_script_file = self.meson_script_file
self.coredata.meson_script_launcher = self.meson_script_launcher
self.first_invocation = True
if self.coredata.cross_file:
self.cross_info = CrossBuildInfo(self.coredata.cross_file)
@ -253,7 +251,7 @@ class Environment():
return self.coredata
def get_build_command(self):
return self.meson_script_file
return self.meson_script_launcher
def is_header(self, fname):
return is_header(fname)

@ -65,7 +65,7 @@ parser.add_argument('directories', nargs='*')
class MesonApp():
def __init__(self, dir1, dir2, script_file, handshake, options, original_cmd_line_args):
def __init__(self, dir1, dir2, script_launcher, handshake, options, original_cmd_line_args):
(self.source_dir, self.build_dir) = self.validate_dirs(dir1, dir2, handshake)
if not os.path.isabs(options.prefix):
raise RuntimeError('--prefix value \'{0}\' must be an absolute path: '.format(options.prefix))
@ -76,7 +76,7 @@ class MesonApp():
pass
else:
options.prefix = options.prefix[:-1]
self.meson_script_file = script_file
self.meson_script_launcher = script_launcher
self.options = options
self.original_cmd_line_args = original_cmd_line_args
@ -124,7 +124,7 @@ itself as required.'''
env.coredata.pkgconf_envvar = curvar
def generate(self):
env = environment.Environment(self.source_dir, self.build_dir, self.meson_script_file, self.options, self.original_cmd_line_args)
env = environment.Environment(self.source_dir, self.build_dir, self.meson_script_launcher, self.options, self.original_cmd_line_args)
mlog.initialize(env.get_log_dir())
mlog.debug('Build started at', datetime.datetime.now().isoformat())
mlog.debug('Python binary:', sys.executable)
@ -262,12 +262,6 @@ def run(mainfile, args):
dir2 = args[1]
else:
dir2 = '.'
while os.path.islink(mainfile):
resolved = os.readlink(mainfile)
if resolved[0] != '/':
mainfile = os.path.join(os.path.dirname(mainfile), resolved)
else:
mainfile = resolved
try:
app = MesonApp(dir1, dir2, mainfile, handshake, options, sys.argv)
except Exception as e:

Loading…
Cancel
Save