diff options
Diffstat (limited to 'extras/msvcdeps.py')
-rw-r--r-- | extras/msvcdeps.py | 73 |
1 files changed, 34 insertions, 39 deletions
diff --git a/extras/msvcdeps.py b/extras/msvcdeps.py index fc1ecd4..873a419 100644 --- a/extras/msvcdeps.py +++ b/extras/msvcdeps.py @@ -50,28 +50,35 @@ def apply_msvcdeps_flags(taskgen): if taskgen.env.get_flat(flag).find(PREPROCESSOR_FLAG) < 0: taskgen.env.append_value(flag, PREPROCESSOR_FLAG) - # Figure out what casing conventions the user's shell used when - # launching Waf - (drive, _) = os.path.splitdrive(taskgen.bld.srcnode.abspath()) - taskgen.msvcdeps_drive_lowercase = drive == drive.lower() - def path_to_node(base_node, path, cached_nodes): - # Take the base node and the path and return a node - # Results are cached because searching the node tree is expensive - # The following code is executed by threads, it is not safe, so a lock is needed... - if getattr(path, '__hash__'): - node_lookup_key = (base_node, path) - else: - # Not hashable, assume it is a list and join into a string - node_lookup_key = (base_node, os.path.sep.join(path)) + ''' + Take the base node and the path and return a node + Results are cached because searching the node tree is expensive + The following code is executed by threads, it is not safe, so a lock is needed... + ''' + # normalize the path because ant_glob() does not understand + # parent path components (..) + path = os.path.normpath(path) + + # normalize the path case to increase likelihood of a cache hit + path = os.path.normcase(path) + + # ant_glob interprets [] and () characters, so those must be replaced + path = path.replace('[', '?').replace(']', '?').replace('(', '[(]').replace(')', '[)]') + + node_lookup_key = (base_node, path) + try: - lock.acquire() node = cached_nodes[node_lookup_key] except KeyError: - node = base_node.find_resource(path) - cached_nodes[node_lookup_key] = node - finally: - lock.release() + # retry with lock on cache miss + with lock: + try: + node = cached_nodes[node_lookup_key] + except KeyError: + node_list = base_node.ant_glob([path], ignorecase=True, remove=False, quiet=True, regex=False) + node = cached_nodes[node_lookup_key] = node_list[0] if node_list else None + return node def post_run(self): @@ -86,11 +93,6 @@ def post_run(self): unresolved_names = [] resolved_nodes = [] - lowercase = self.generator.msvcdeps_drive_lowercase - correct_case_path = bld.path.abspath() - correct_case_path_len = len(correct_case_path) - correct_case_path_norm = os.path.normcase(correct_case_path) - # Dynamically bind to the cache try: cached_nodes = bld.cached_nodes @@ -100,26 +102,15 @@ def post_run(self): for path in self.msvcdeps_paths: node = None if os.path.isabs(path): - # Force drive letter to match conventions of main source tree - drive, tail = os.path.splitdrive(path) - - if os.path.normcase(path[:correct_case_path_len]) == correct_case_path_norm: - # Path is in the sandbox, force it to be correct. MSVC sometimes returns a lowercase path. - path = correct_case_path + path[correct_case_path_len:] - else: - # Check the drive letter - if lowercase and (drive != drive.lower()): - path = drive.lower() + tail - elif (not lowercase) and (drive != drive.upper()): - path = drive.upper() + tail node = path_to_node(bld.root, path, cached_nodes) else: + # when calling find_resource, make sure the path does not begin with '..' base_node = bld.bldnode - # when calling find_resource, make sure the path does not begin by '..' path = [k for k in Utils.split_path(path) if k and k != '.'] while path[0] == '..': - path = path[1:] + path.pop(0) base_node = base_node.parent + path = os.sep.join(path) node = path_to_node(base_node, path, cached_nodes) @@ -213,8 +204,12 @@ def exec_command(self, cmd, **kw): raw_out = self.generator.bld.cmd_and_log(cmd + ['@' + tmp], **kw) ret = 0 except Errors.WafError as e: - raw_out = e.stdout - ret = e.returncode + # Use e.msg if e.stdout is not set + raw_out = getattr(e, 'stdout', e.msg) + + # Return non-zero error code even if we didn't + # get one from the exception object + ret = getattr(e, 'returncode', 1) for line in raw_out.splitlines(): if line.startswith(INCLUDE_PATTERN): |