121 lines · python
1import os2 3import ycm_core4 5# These are the compilation flags that will be used in case there's no6# compilation database set (by default, one is not set).7# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR.8flags = [9 "-Wall",10 "-Werror",11 "-pedantic-errors",12 "-std=c++0x",13 "-fno-strict-aliasing",14 "-O3",15 "-DNDEBUG",16 # ...and the same thing goes for the magic -x option which specifies the17 # language that the files to be compiled are written in. This is mostly18 # relevant for c++ headers.19 # For a C project, you would set this to 'c' instead of 'c++'.20 "-x",21 "c++",22 "-I",23 "include",24 "-isystem",25 "/usr/include",26 "-isystem",27 "/usr/local/include",28]29 30 31# Set this to the absolute path to the folder (NOT the file!) containing the32# compile_commands.json file to use that instead of 'flags'. See here for33# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html34#35# Most projects will NOT need to set this to anything; you can just change the36# 'flags' list of compilation flags. Notice that YCM itself uses that approach.37compilation_database_folder = ""38 39if os.path.exists(compilation_database_folder):40 database = ycm_core.CompilationDatabase(compilation_database_folder)41else:42 database = None43 44SOURCE_EXTENSIONS = [".cc"]45 46 47def DirectoryOfThisScript():48 return os.path.dirname(os.path.abspath(__file__))49 50 51def MakeRelativePathsInFlagsAbsolute(flags, working_directory):52 if not working_directory:53 return list(flags)54 new_flags = []55 make_next_absolute = False56 path_flags = ["-isystem", "-I", "-iquote", "--sysroot="]57 for flag in flags:58 new_flag = flag59 60 if make_next_absolute:61 make_next_absolute = False62 if not flag.startswith("/"):63 new_flag = os.path.join(working_directory, flag)64 65 for path_flag in path_flags:66 if flag == path_flag:67 make_next_absolute = True68 break69 70 if flag.startswith(path_flag):71 path = flag[len(path_flag) :]72 new_flag = path_flag + os.path.join(working_directory, path)73 break74 75 if new_flag:76 new_flags.append(new_flag)77 return new_flags78 79 80def IsHeaderFile(filename):81 extension = os.path.splitext(filename)[1]82 return extension in [".h", ".hxx", ".hpp", ".hh"]83 84 85def GetCompilationInfoForFile(filename):86 # The compilation_commands.json file generated by CMake does not have entries87 # for header files. So we do our best by asking the db for flags for a88 # corresponding source file, if any. If one exists, the flags for that file89 # should be good enough.90 if IsHeaderFile(filename):91 basename = os.path.splitext(filename)[0]92 for extension in SOURCE_EXTENSIONS:93 replacement_file = basename + extension94 if os.path.exists(replacement_file):95 compilation_info = database.GetCompilationInfoForFile(96 replacement_file97 )98 if compilation_info.compiler_flags_:99 return compilation_info100 return None101 return database.GetCompilationInfoForFile(filename)102 103 104def FlagsForFile(filename, **kwargs):105 if database:106 # Bear in mind that compilation_info.compiler_flags_ does NOT return a107 # python list, but a "list-like" StringVec object108 compilation_info = GetCompilationInfoForFile(filename)109 if not compilation_info:110 return None111 112 final_flags = MakeRelativePathsInFlagsAbsolute(113 compilation_info.compiler_flags_,114 compilation_info.compiler_working_dir_,115 )116 else:117 relative_to = DirectoryOfThisScript()118 final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to)119 120 return {"flags": final_flags, "do_cache": True}121