Skip to content

Commit

Permalink
Use argv[0] to internally relaunch meson.py
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
em- authored and jpakkane committed Oct 8, 2016
1 parent cd6d5a6 commit 6c50253
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 23 deletions.
1 change: 1 addition & 0 deletions authors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ Patrick Griffis
Iain Lane
Daniel Brendle
Franz Zapata
Emanuele Aina
14 changes: 6 additions & 8 deletions meson.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:]))
10 changes: 4 additions & 6 deletions mesonbuild/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -198,7 +196,7 @@ def __init__(self, source_dir, build_dir, main_script_file, options, original_cm
# 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)
Expand Down Expand Up @@ -253,7 +251,7 @@ def get_coredata(self):
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)
Expand Down
12 changes: 3 additions & 9 deletions mesonbuild/mesonmain.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def add_builtin_argument(name, **kwargs):

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))
Expand All @@ -76,7 +76,7 @@ def __init__(self, dir1, dir2, script_file, handshake, options, original_cmd_lin
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

Expand Down Expand Up @@ -124,7 +124,7 @@ def check_pkgconfig_envvar(self, env):
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)
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 6c50253

Please sign in to comment.