1import os 2 3import ycm_core 4 5# These are the compilation flags that will be used in case there's no 6# 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 the 17 # language that the files to be compiled are written in. This is mostly 18 # 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 the 32# compile_commands.json file to use that instead of 'flags'. See here for 33# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html 34# 35# Most projects will NOT need to set this to anything; you can just change the 36# '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 = None 43 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 = False 56 path_flags = ["-isystem", "-I", "-iquote", "--sysroot="] 57 for flag in flags: 58 new_flag = flag 59 60 if make_next_absolute: 61 make_next_absolute = False 62 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 = True 68 break 69 70 if flag.startswith(path_flag): 71 path = flag[len(path_flag) :] 72 new_flag = path_flag + os.path.join(working_directory, path) 73 break 74 75 if new_flag: 76 new_flags.append(new_flag) 77 return new_flags 78 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 entries 87 # for header files. So we do our best by asking the db for flags for a 88 # corresponding source file, if any. If one exists, the flags for that file 89 # 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 + extension 94 if os.path.exists(replacement_file): 95 compilation_info = database.GetCompilationInfoForFile( 96 replacement_file 97 ) 98 if compilation_info.compiler_flags_: 99 return compilation_info 100 return None 101 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 a 107 # python list, but a "list-like" StringVec object 108 compilation_info = GetCompilationInfoForFile(filename) 109 if not compilation_info: 110 return None 111 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