From 0b2a7300c039e30d3a7430d6f77dc204876eac4b Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sat, 8 May 2021 20:21:04 +0100 Subject: Set up VS environment automatically when run. --- docs/markdown/snippets/vsenv.md | 8 +++++ mesonbuild/mesonmain.py | 70 ++++++++++++++++++++++++++++++++++++++++- run_project_tests.py | 5 +-- run_tests.py | 3 +- run_unittests.py | 5 +-- 5 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 docs/markdown/snippets/vsenv.md diff --git a/docs/markdown/snippets/vsenv.md b/docs/markdown/snippets/vsenv.md new file mode 100644 index 0000000..96d3979 --- /dev/null +++ b/docs/markdown/snippets/vsenv.md @@ -0,0 +1,8 @@ +## Automatically set up Visual Studio environment + +When Meson is run on Windows it will automatically set up the +environment to use Visual Studio if no other compiler toolchain +can be detected. This means that you can run Meson commands from +any command prompt or directly from any IDE. This sets up the +64 bit native environment. If you need any other, then you +need to set it up manually as before. diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index 208cfe4..4031b0a 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -1,4 +1,4 @@ -# Copyright 2012-2016 The Meson development team +# Copyright 2012-2021 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -27,6 +27,73 @@ from .mesonlib import MesonException from .environment import detect_msys2_arch from .wrap import wraptool +bat_template = '''@ECHO OFF + +call "{}" + +ECHO {} +SET +''' + +# If on Windows and VS is installed but not set up in the environment, +# set it to be runnable. In this way Meson can be directly invoked +# from any shell, VS Code etc. +def setup_vsenv(): + import subprocess, json, pathlib + if not mesonlib.is_windows(): + return + bat_placeholder = 'nananananananananananananananana' + # If an existing build tool chain exists in PATH -> do nothing. + if shutil.which('cc'): + return + if shutil.which('clang'): + return + if shutil.which('clang-cl'): + return + if os.environ.get('OSTYPE', bat_placeholder) == 'cygwin': + return + if 'Visual Studio' in os.environ['PATH']: + return + bat_locator_bin = r'c:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' + if not os.path.exists(bat_locator_bin): + return + bat_json = subprocess.check_output([bat_locator_bin, '-latest', '-format', 'json']) + bat_info = json.loads(bat_json) + if not bat_info: + bat_json = subprocess.check_output([bat_locator_bin, '-prerelease', '-format', 'json']) + bat_info = json.loads(bat_json) + if not bat_info: + # VS installer instelled but not VS itself maybe? + return + print('Activating VS', bat_info[0]['catalog']['productDisplayVersion']) + bat_root = bat_info[0]['installationPath'] + bat_path = bat_root + r'\VC\Auxiliary\Build\vcvars64.bat' + if not os.path.exists(bat_path): + return + + bat_file = pathlib.Path.home() / 'vsdetect.bat' + + bat_separator = '---SPLIT---' + bat_contents = bat_template.format(bat_path, bat_separator) + bat_file.write_text(bat_contents) + try: + bat_output = subprocess.check_output(str(bat_file), universal_newlines=True) + finally: + bat_file.unlink() + bat_lines = bat_output.split('\n') + bat_separator_seen = False + for bat_line in bat_lines: + if bat_line == bat_separator: + bat_separator_seen = True + continue + if not bat_separator_seen: + continue + if not bat_line: + continue + k, v = bat_line.split('=', 1) + os.environ[k] = v + + # Note: when adding arguments, please also add them to the completion # scripts in $MESONSRC/data/shell-completions/ @@ -222,6 +289,7 @@ def run(original_args, mainfile): return CommandLineParser().run(args) def main(): + setup_vsenv() # Always resolve the command path so Ninja can find it for regen, tests, etc. if 'meson.exe' in sys.executable: assert(os.path.isabs(sys.executable)) diff --git a/run_project_tests.py b/run_project_tests.py index fcb8716..f477e6c 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright 2012-2019 The Meson development team +# Copyright 2012-2021 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -46,7 +46,7 @@ from mesonbuild.build import ConfigurationData from mesonbuild.mesonlib import MachineChoice, Popen_safe, TemporaryDirectoryWinProof from mesonbuild.mlog import bold, green, red, yellow from mesonbuild.coredata import backendlist, version as meson_version - +from mesonbuild.mesonmain import setup_vsenv from run_tests import get_fake_options, run_configure, get_meson_script from run_tests import get_backend_commands, get_backend_args_for_dir, Backend from run_tests import ensure_backend_detects_changes @@ -1356,6 +1356,7 @@ def clear_transitive_files(): mesonlib.windows_proof_rm(str(d)) if __name__ == '__main__': + setup_vsenv() parser = argparse.ArgumentParser(description="Run the test suite of Meson.") parser.add_argument('extra_args', nargs='*', help='arguments that are passed directly to Meson (remember to have -- before these).') diff --git a/run_tests.py b/run_tests.py index 1d755a8..7d9a9e4 100755 --- a/run_tests.py +++ b/run_tests.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright 2012-2017 The Meson development team +# Copyright 2012-2021 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -395,5 +395,6 @@ def main(): return returncode if __name__ == '__main__': + mesonmain.setup_vsenv() print('Meson build system', meson_version, 'Project and Unit Tests') raise SystemExit(main()) diff --git a/run_unittests.py b/run_unittests.py index 256a408..fe664cb 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright 2016-2017 The Meson development team +# Copyright 2016-2021 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -69,7 +69,7 @@ import mesonbuild.modules.pkgconfig from mesonbuild.scripts import destdir_join from mesonbuild.mtest import TAPParser, TestResult - +from mesonbuild.mesonmain import setup_vsenv from mesonbuild.wrap.wrap import PackageDefinition, WrapException from run_tests import ( @@ -10066,6 +10066,7 @@ def main(): return unittest.main(defaultTest=cases, buffer=True) if __name__ == '__main__': + setup_vsenv() print('Meson build system', mesonbuild.coredata.version, 'Unit Tests') start = time.monotonic() try: -- cgit v1.1