import os import string import re import subprocess import ycm_core def IsHeaderFile( filename ): extension = os.path.splitext( filename )[ 1 ] return extension in [ '.h', '.hxx', '.hpp', '.hh' ] def ContainsJamfile(path): for file in os.listdir(path): if file == 'Jamfile.jam' or file == 'Jamroot.jam': return True return False def FindOwningJamfile(filename): path = os.path.dirname(filename) while (not ContainsJamfile(path)) or (path == '/'): path = os.path.dirname(path) return path def ExpandBackTicks(line): bts = re.search("^([^`]*)`([^`]*)`(.*)$", line) if bts and (len(bts.groups()) >= 3): p = subprocess.Popen(bts.group(2), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) line = bts.group(1) + p.stdout.read().decode("utf-8") + bts.group(3); return ExpandBackTicks(line) return line def GetBJamCommandFlags(rtarget, target): flags = [] p = subprocess.Popen(['b2', '-and2', rtarget], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) for lineBytes in p.stdout.readlines(): line = lineBytes.decode("utf-8") if str.lstrip(line).startswith('"g++"') and str.find(line, '"'+target+'"') > 0: flags = [] line = ExpandBackTicks(line) args = str.split(line) idx = 1 while args[idx] != '-c': flags.append(args[idx]) idx += 1 return flags def ApplyFlagQuirks(flags): newflags = [] for flag in flags: qs = re.search('([^"]+)"([^"]*)"$', flag) if qs: flag = qs.group(1) value = qs.group(2) newflags.append(flag) if (flag == '-I'): newflags.append(os.path.abspath(value)) else: newflags.append(value) elif flag != '-Werror': newflags.append(flag) return newflags def GuessAnIncluder(filename): cpp = str.replace(filename, ".h", ".cpp") if os.path.exists(cpp): return cpp filename = os.path.abspath(filename) basename = os.path.basename(filename) dirname = os.path.dirname(filename) p = subprocess.Popen(['grep', '-Ilrw', basename, dirname], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) f = p.stdout.readlines()[0].strip() if IsHeaderFile(f): return GuessAnIncluder(f) return f def FlagsForFile( filename, **kwargs ): if (IsHeaderFile(filename)): filename = GuessAnIncluder(filename) filename = os.path.abspath(filename) rootDir = FindOwningJamfile(filename) target = str.replace(filename, rootDir + "/", "") rtarget = str.replace(target, ".cpp", ".o") cwd = os.getcwd() os.chdir(rootDir) flags = GetBJamCommandFlags(rtarget, target) flags = ApplyFlagQuirks(flags) # Fall back to . for finding precompiled headers flags.append("-x") flags.append("c++"); flags.append("-I") flags.append(os.path.dirname(filename)) os.chdir(cwd) return { 'flags': flags, 'do_cache': False }