From 40b2d81a22201ceccd9448a0b6e906a34f167314 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Tue, 8 Dec 2015 14:49:44 -0800 Subject: [core] Use compilation database for YCM Now the .ycm_extra_conf.py is very close to the YCM upstream reference file. --- .ycm_extra_conf.py | 201 ++++++++++++++++++++++------------------------------- 1 file changed, 82 insertions(+), 119 deletions(-) (limited to '.ycm_extra_conf.py') diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py index be5e3a5c1f..41578b3366 100644 --- a/.ycm_extra_conf.py +++ b/.ycm_extra_conf.py @@ -33,130 +33,93 @@ import os import subprocess -import sys import ycm_core - -def DirectoryOfThisScript(): - return os.path.dirname(os.path.abspath(__file__)) - - -default_flags = [ - '-std=c++14', - '-I%s' % (os.path.join(DirectoryOfThisScript(), 'src')), - '-I%s' % (os.path.join(DirectoryOfThisScript(), 'include')), +compilation_database_folders = [ + 'build/linux-x86_64/Release', + 'build/osx-x86_64/Release', ] +subprocess.call(['make compdb'], shell=True) -def MakeRelativePathsInFlagsAbsolute(flags, working_directory): - if not working_directory: - return list(flags) - - new_flags = [] - make_next_absolute = False - path_flags = ['-isystem', '-I', '-iquote', '--sysroot='] - - for flag in flags: - new_flag = flag - - if make_next_absolute: - make_next_absolute = False - if not flag.startswith('/'): - new_flag = os.path.join(working_directory, flag) - - for path_flag in path_flags: - if flag == path_flag: - make_next_absolute = True - break - - if flag.startswith(path_flag): - path = flag[len(path_flag):] - new_flag = path_flag + os.path.join(working_directory, path) - break - - if new_flag: - new_flags.append(new_flag) - - return new_flags - - -def FlagsForFileDefault(): - return { - 'flags': default_flags, - 'do_cache': False, - } - - -def FlagsForFileLinux(filename): - working_directory = os.path.join('build', 'linux') - - if not os.path.exists(os.path.join(DirectoryOfThisScript(), working_directory)): - return FlagsForFileDefault() - - relative_source_path = filename.replace(DirectoryOfThisScript() + '/', '') - relative_obj_path = os.path.splitext(relative_source_path)[0] + '.o' - - make_cmd = 'make -pn |grep %s: |grep GYP_CXXFLAGS |cut -d\' \' -f4-' % relative_obj_path - - p = subprocess.Popen([make_cmd], shell=True, stdout=subprocess.PIPE) - stdout, stderr = p.communicate() +for folder in compilation_database_folders: + if os.path.exists( folder ): + database = ycm_core.CompilationDatabase( folder ) - if p.returncode: - return FlagsForFileDefault() +SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ] - flags = stdout.split(' ') - flags_relative = MakeRelativePathsInFlagsAbsolute(flags, os.path.join(DirectoryOfThisScript(), working_directory)) - flags_final = [flag for flag in flags_relative if flag.startswith("-")] - return { - 'flags': flags_final, - 'do_cache': True, - } - - -def FlagsForFileDarwin(filename): - working_directory = os.path.join('build', 'osx') - - if not os.path.exists(os.path.join(DirectoryOfThisScript(), working_directory)): - return FlagsForFileDefault() - - relative_source_path = filename.replace(DirectoryOfThisScript() + '/', '') - relative_obj_path = os.path.splitext(relative_source_path)[0] + '.o' - - make_cmd = 'make -pn |grep "%s :=" |grep "NDEBUG" |tail -n 1 | cut -d\' \' -f4-' % relative_obj_path - - p = subprocess.Popen([make_cmd], shell=True, stdout=subprocess.PIPE) - stdout, stderr = p.communicate() - - if p.returncode: - return FlagsForFileDefault() - - flags = stdout.split(' ') - flags_relative = MakeRelativePathsInFlagsAbsolute(flags, os.path.join(DirectoryOfThisScript(), working_directory)) - flags_final = [flag for flag in flags_relative if flag.startswith("-")] - - # Append OSX sysroot SDK path - xcrun_cmd = 'xcrun --show-sdk-path' - - p = subprocess.Popen([xcrun_cmd], shell=True, stdout=subprocess.PIPE) - stdout, stderr = p.communicate() - - if p.returncode: - return FlagsForFileDefault() - - flags_final.append('-isysroot ' + stdout) - - return { - 'flags': flags_final, - 'do_cache': True, - } - - -def FlagsForFile(filename, **kwargs): - if sys.platform.startswith('linux'): - return FlagsForFileLinux(filename) - - if sys.platform.startswith('darwin'): - return FlagsForFileDarwin(filename) - - return FlagsForFileDefault() +def DirectoryOfThisScript(): + return os.path.dirname( os.path.abspath( __file__ ) ) + + +def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): + if not working_directory: + return list( flags ) + new_flags = [] + make_next_absolute = False + path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] + for flag in flags: + new_flag = flag + + if make_next_absolute: + make_next_absolute = False + if not flag.startswith( '/' ): + new_flag = os.path.join( working_directory, flag ) + + for path_flag in path_flags: + if flag == path_flag: + make_next_absolute = True + break + + if flag.startswith( path_flag ): + path = flag[ len( path_flag ): ] + new_flag = path_flag + os.path.join( working_directory, path ) + break + + if new_flag: + new_flags.append( new_flag ) + return new_flags + + +def IsHeaderFile( filename ): + extension = os.path.splitext( filename )[ 1 ] + return extension in [ '.h', '.hxx', '.hpp', '.hh' ] + + +def GetCompilationInfoForFile( filename ): + # The compilation_commands.json file generated by CMake does not have entries + # for header files. So we do our best by asking the db for flags for a + # corresponding source file, if any. If one exists, the flags for that file + # should be good enough. + if IsHeaderFile( filename ): + basename = os.path.splitext( filename )[ 0 ] + for extension in SOURCE_EXTENSIONS: + replacement_file = basename + extension + if os.path.exists( replacement_file ): + compilation_info = database.GetCompilationInfoForFile( + replacement_file ) + if compilation_info.compiler_flags_: + return compilation_info + return None + return database.GetCompilationInfoForFile( filename ) + + +def FlagsForFile( filename, **kwargs ): + if not database: + return None + + # Bear in mind that compilation_info.compiler_flags_ does NOT return a + # python list, but a "list-like" StringVec object + compilation_info = GetCompilationInfoForFile( filename ) + if not compilation_info: + return None + + final_flags = MakeRelativePathsInFlagsAbsolute( + compilation_info.compiler_flags_, + compilation_info.compiler_working_dir_ ) + + return { + 'flags': final_flags, + 'do_cache': True + } -- cgit v1.2.1