Mercurial > vim-crosoft
comparison scripts/ycm_extra_conf.py @ 0:5d2c0db51914
Initial commit
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 17 Sep 2019 13:24:24 -0700 |
parents | |
children | f444739dd8af |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:5d2c0db51914 |
---|---|
1 import argparse | |
2 import logging | |
3 import os.path | |
4 import sys | |
5 | |
6 | |
7 if True: # 'vim' in sys.modules: | |
8 sys.path.append(os.path.dirname(__file__)) | |
9 | |
10 | |
11 from logutil import setup_logging | |
12 from vsutil import SolutionCache | |
13 | |
14 | |
15 logger = logging.getLogger(__name__) | |
16 | |
17 | |
18 def _build_cflags(filename, solution, buildenv=None, slncache=None): | |
19 # Load the solution. | |
20 if not solution: | |
21 raise Exception( | |
22 "No solution path was provided in the client data!") | |
23 | |
24 cache, loaded = SolutionCache.load_or_rebuild(solution, slncache) | |
25 if not loaded: | |
26 cache.build_cache() | |
27 | |
28 # Find the current file in the solution. | |
29 filename_lower = filename.lower() | |
30 projpath = None | |
31 for pp, pi in cache.index.items(): | |
32 if filename_lower in pi: | |
33 projpath = pp | |
34 break | |
35 else: | |
36 raise Exception("File doesn't belong to the solution: %s" % filename) | |
37 | |
38 # Find the project that our file belongs to. | |
39 proj = cache.slnobj.find_project_by_path(projpath) | |
40 if not proj: | |
41 raise Exception("Can't find project in solution: %s" % projpath) | |
42 logger.debug("Found project %s: %s" % (proj.name, proj.abspath)) | |
43 | |
44 # Get the provided config/platform combo, which represent a solution | |
45 # configuration, and find the corresponding project configuration. | |
46 # For instance, a solution configuration of "Debug|Win64" could map | |
47 # to a "MyDebug|AnyCPU" configuration on a specific project. | |
48 sln_config_platform = '%s|%s' % (buildenv['Configuration'], | |
49 buildenv['Platform']) | |
50 proj_config_platform = cache.slnobj.find_project_configuration( | |
51 proj.guid, sln_config_platform) | |
52 if not proj_config_platform: | |
53 raise Exception("Can't find project configuration and platform for " | |
54 "solution configuration and platform: %s" % | |
55 sln_config_platform) | |
56 | |
57 # Make a build environment for the project, and figure out what | |
58 # kind of project it is. | |
59 proj_config, proj_platform = proj_config_platform.split('|') | |
60 | |
61 proj_buildenv = buildenv.copy() | |
62 proj_buildenv['Configuration'] = proj_config | |
63 proj_buildenv['Platform'] = proj_platform | |
64 | |
65 cfggroup = proj.propertygroup('Configuration', proj_buildenv) | |
66 cfgtype = cfggroup.get('ConfigurationType') | |
67 if not cfgtype: | |
68 raise Exception("Can't find configuration type. Did you specify a " | |
69 "configuration name and platform? Got: %s" % | |
70 proj_buildenv) | |
71 logger.debug("Found configuration type: %s" % cfgtype) | |
72 | |
73 # Let's prepare a list of standard stuff for C++. | |
74 preproc = [] | |
75 incpaths = [] | |
76 projdir = os.path.dirname(proj.abspath) | |
77 | |
78 if cfgtype == 'Makefile': | |
79 # It's a 'Makefile' project, which means we know as little about | |
80 # compiler flags as whatever information was given to VS. As | |
81 # such, if the solution setup doesn't give enough info, VS | |
82 # intellisense won't work, and neither will YouCompleteMe. | |
83 defaultpropgroup = proj.defaultpropertygroup(proj_buildenv) | |
84 | |
85 nmake_preproc = defaultpropgroup.get('NMakePreprocessorDefinitions') | |
86 preproc += nmake_preproc.strip(';').split(';') | |
87 | |
88 nmake_incpaths = defaultpropgroup.get('NMakeIncludeSearchPath') | |
89 incpaths += [os.path.abspath(os.path.join(projdir, p)) | |
90 for p in nmake_incpaths.strip(';').split(';')] | |
91 | |
92 else: | |
93 # We should definitely support standard VC++ projects here but | |
94 # I don't need it yet :) | |
95 raise Exception("Don't know how to handle configuration type: %s" % | |
96 cfgtype) | |
97 | |
98 # Build the clang/YCM flags with what we found. | |
99 flags = ['-x', 'c++'] # TODO: check language type from project file. | |
100 | |
101 for symbol in preproc: | |
102 flags.append('-D%s' % symbol) | |
103 for path in incpaths: | |
104 if path.startswith("C:\\Program Files"): | |
105 flags.append('-isystem') | |
106 else: | |
107 flags.append('-I') | |
108 flags.append(path) | |
109 | |
110 return {'flags': flags} | |
111 | |
112 | |
113 def _build_env_from_vim(client_data): | |
114 buildenv = {} | |
115 buildenv['Configuration'] = client_data.get('g:vimcrosoft_current_config', '') | |
116 buildenv['Platform'] = client_data.get('g:vimcrosoft_current_platform', '') | |
117 return buildenv | |
118 | |
119 | |
120 def Settings(**kwargs): | |
121 language = kwargs.get('language') | |
122 filename = kwargs.get('filename') | |
123 | |
124 client_data = kwargs.get('client_data', {}) | |
125 from_cli = kwargs.get('from_cli', False) | |
126 if from_cli: | |
127 solution = client_data.get('solution') | |
128 slncache = client_data.get('slncache') | |
129 buildenv = client_data.get('env', {}) | |
130 else: | |
131 solution = client_data.get('g:vimcrosoft_current_sln') | |
132 slncache = client_data.get('g:vimcrosoft_current_sln_cache') | |
133 buildenv = _build_env_from_vim(client_data) | |
134 | |
135 flags = None | |
136 | |
137 if language == 'cfamily': | |
138 try: | |
139 flags = _build_cflags(filename, solution, | |
140 buildenv=buildenv, slncache=slncache) | |
141 except Exception as exc: | |
142 if from_cli: | |
143 raise | |
144 flags = {'error': str(exc)} | |
145 else: | |
146 flags = {'error': f"Unknown language: {language}"} | |
147 | |
148 with open("D:\\P4\\DevEditor\\debug.txt", 'w') as fp: | |
149 fp.write("kwargs:") | |
150 fp.write(str(kwargs)) | |
151 fp.write("client_data:") | |
152 fp.write(str(list(kwargs['client_data'].items()))) | |
153 fp.write("flags:") | |
154 fp.write(str(flags)) | |
155 return flags | |
156 | |
157 | |
158 languages = { | |
159 'cfamily': ['h', 'c', 'hpp', 'cpp', 'inl'] | |
160 } | |
161 | |
162 | |
163 def _get_language(filename): | |
164 _, ext = os.path.splitext(filename) | |
165 ext = ext.lstrip('.') | |
166 for lang, exts in languages.items(): | |
167 if ext in exts: | |
168 return lang | |
169 return None | |
170 | |
171 | |
172 def main(): | |
173 parser = argparse.ArgumentParser() | |
174 parser.add_argument('solution', | |
175 help="The solution file") | |
176 parser.add_argument('filename', | |
177 help="The filename for which to get flags") | |
178 parser.add_argument('-p', '--property', | |
179 action="append", | |
180 help="Specifies a build property") | |
181 parser.add_argument('-c', '--cache', | |
182 help="The solution cache to use") | |
183 parser.add_argument('-v', '--verbose', | |
184 action='store_true', | |
185 help="Show debugging information") | |
186 args = parser.parse_args() | |
187 setup_logging(args.verbose) | |
188 | |
189 lang = _get_language(args.filename) | |
190 logger.debug(f"Got language {lang} for {args.filename}") | |
191 | |
192 build_env = {} | |
193 if args.property: | |
194 for p in args.property: | |
195 pname, pval = p.split('=', 1) | |
196 build_env[pname] = pval | |
197 logger.debug(f"Got build environment: {build_env}") | |
198 client_data = {'solution': args.solution, | |
199 'slncache': args.cache, | |
200 'env': build_env} | |
201 | |
202 params = {'from_cli': True, | |
203 'language': lang, | |
204 'filename': args.filename, | |
205 'client_data': client_data | |
206 } | |
207 flags = Settings(**params) | |
208 logger.info("Flags:") | |
209 import pprint | |
210 pp = pprint.PrettyPrinter(indent=2) | |
211 pp.pprint(flags) | |
212 | |
213 | |
214 if __name__ == '__main__': | |
215 main() |