-
Notifications
You must be signed in to change notification settings - Fork 82
Feature prepare environment script #172
base: master
Are you sure you want to change the base?
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| from __future__ import print_function | ||
|
|
||
| import argparse | ||
| import glob | ||
| import os | ||
| import sys | ||
| import textwrap | ||
| import subprocess | ||
|
|
||
|
|
||
| def ensure_dir(path): | ||
| if os.path.exists(path): | ||
| return | ||
|
|
||
| os.mkdir(path) | ||
| return path | ||
|
|
||
|
|
||
| def traverse_toolsets(f): | ||
| msbuild_dir = r'C:\Program Files (x86)\MSBuild' | ||
| toolsets = glob.glob(r'{}\Microsoft.Cpp\v4.0\*\Platforms\*\PlatformToolsets\*'.format(msbuild_dir)) | ||
| for toolset in toolsets: | ||
| f(toolset) | ||
|
|
||
|
|
||
| def clcache_props_path(toolset): | ||
| return os.path.join(toolset, 'ImportAfter', 'Clcache.props') | ||
|
|
||
|
|
||
| def generate_props_content(clcache_dir): | ||
| return textwrap.dedent(''' | ||
| <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <PropertyGroup> | ||
| <ExecutablePath>{clcache_dir};$(ExecutablePath)</ExecutablePath> | ||
| </PropertyGroup> | ||
| </Project>''').format(clcache_dir=clcache_dir)[1:] | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there some documentation on how these
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just found in MSBuild\Microsoft.Cpp\v4.0\V140\Platforms\x64\PlatformToolsets\v140\Toolset.props this lines: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildThisFileDirectory)ImportBefore\*.props" Condition="Exists('$(MSBuildThisFileDirectory)ImportBefore')" />
...
<Import Project="$(MSBuildThisFileDirectory)ImportAfter\*.props" Condition="Exists('$(MSBuildThisFileDirectory)ImportAfter')" />
</Project>
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. First my idea was to create own toolset like clang-cl. I read existing toolset files and found this extension point. |
||
|
|
||
|
|
||
| def check_call_quiet(*args, **kwargs): | ||
| with open(os.devnull, 'w') as devnull: | ||
| kwargs['stderr'] = devnull | ||
| kwargs['stdout'] = devnull | ||
| subprocess.check_call(*args, **kwargs) | ||
|
|
||
|
|
||
| def set_system_variable(var, value): | ||
| if value: | ||
| check_call_quiet(['setx', '-m', var, value]) | ||
| else: | ||
| reg_path = r'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it also be sufficient to affect just the current user, i.e. use
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Likely. Thanks, I will try it =) |
||
| try: | ||
| check_call_quiet(['reg', 'query', reg_path, '/V', var]) | ||
| except subprocess.CalledProcessError: | ||
| # Variable doesn't exists | ||
| pass | ||
| else: | ||
| check_call_quiet(['reg', 'delete', reg_path, '/F', '/V', var]) | ||
|
|
||
|
|
||
| def install(exe, cache_dir): | ||
| def f(toolset): | ||
| clcache_props = clcache_props_path(toolset) | ||
| ensure_dir(os.path.dirname(clcache_props)) | ||
| with open(clcache_props, 'w') as f: | ||
| f.write(generate_props_content(os.path.dirname(exe))) | ||
|
|
||
| traverse_toolsets(f) | ||
| set_system_variable('CLCACHE_DIR', cache_dir) | ||
| set_system_variable('CL', '/MP4') | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this script should change the
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, this is doubtful place.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm... looks like my experience about CallsWithMultipleSourceFiles is outdated now. |
||
|
|
||
|
|
||
| def uninstall(): | ||
| def f(toolset): | ||
| clcache_props = clcache_props_path(toolset) | ||
| if os.path.exists(clcache_props): | ||
| os.remove(clcache_props) | ||
|
|
||
| traverse_toolsets(f) | ||
| set_system_variable('CLCACHE_DIR', None) | ||
| set_system_variable('CL', None) | ||
|
|
||
|
|
||
| def main(args=sys.argv[1:]): | ||
| clcache_default_exe = os.path.join( | ||
| os.path.dirname(os.path.abspath(__file__)), | ||
| 'dist', | ||
| 'cl.exe') | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the executable have to be called
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll try to use |
||
|
|
||
| def cl_exe_type(exe): | ||
| if not os.path.isfile(exe): | ||
| raise argparse.ArgumentTypeError('{} is not file'.format(exe)) | ||
| if os.path.basename(exe) != 'cl.exe': | ||
| raise argparse.ArgumentTypeError('clcache executable must be named cl.exe') | ||
| return exe | ||
|
|
||
| parser = argparse.ArgumentParser() | ||
| subparsers = parser.add_subparsers(dest='action') | ||
| parser_install = subparsers.add_parser('install') | ||
| parser_install.add_argument('--exe', type=cl_exe_type, default=clcache_default_exe) | ||
| parser_install.add_argument('--cache-dir') | ||
| parser_uninstall = subparsers.add_parser('uninstall') | ||
| args = parser.parse_args(args) | ||
|
|
||
| if args.action == 'install': | ||
| install(os.path.abspath(args.exe), os.path.abspath(args.cache_dir)) | ||
| else: | ||
| uninstall() | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| sys.exit(main()) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rest of the clcache script code now requires Python 3.3 or newer. I think imposing the same requirement here would be consistent, and it would simplify things abit (e.g. this import is not needed).