1import os 2import ycm_core 3 4flags = [ 5'-Wall', 6'-Wextra', 7'-Werror', 8'-x', 'c', 9'-Iinclude', 10] 11 12# Set this to the absolute path to the folder (NOT the file!) containing the 13# compile_commands.json file to use that instead of 'flags'. See here for 14# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html 15# 16# Most projects will NOT need to set this to anything; you can just change the 17# 'flags' list of compilation flags. Notice that YCM itself uses that approach. 18compilation_database_folder = 'obj' 19 20if os.path.exists( compilation_database_folder ): 21 database = ycm_core.CompilationDatabase( compilation_database_folder ) 22else: 23 database = None 24 25SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ] 26 27def DirectoryOfThisScript(): 28 return os.path.dirname( os.path.abspath( __file__ ) ) 29 30 31def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): 32 if not working_directory: 33 return list( flags ) 34 new_flags = [] 35 make_next_absolute = False 36 path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] 37 for flag in flags: 38 new_flag = flag 39 40 if make_next_absolute: 41 make_next_absolute = False 42 if not flag.startswith( '/' ): 43 new_flag = os.path.join( working_directory, flag ) 44 45 for path_flag in path_flags: 46 if flag == path_flag: 47 make_next_absolute = True 48 break 49 50 if flag.startswith( path_flag ): 51 path = flag[ len( path_flag ): ] 52 new_flag = path_flag + os.path.join( working_directory, path ) 53 break 54 55 if new_flag: 56 new_flags.append( new_flag ) 57 return new_flags 58 59 60def IsHeaderFile( filename ): 61 extension = os.path.splitext( filename )[ 1 ] 62 return extension in [ '.h', '.hxx', '.hpp', '.hh' ] 63 64 65def GetCompilationInfoForFile( filename ): 66 # The compilation_commands.json file generated by CMake does not have entries 67 # for header files. So we do our best by asking the db for flags for a 68 # corresponding source file, if any. If one exists, the flags for that file 69 # should be good enough. 70 if IsHeaderFile( filename ): 71 basename = os.path.splitext( filename )[ 0 ] 72 for extension in SOURCE_EXTENSIONS: 73 replacement_file = basename + extension 74 if os.path.exists( replacement_file ): 75 compilation_info = database.GetCompilationInfoForFile( 76 replacement_file ) 77 if compilation_info.compiler_flags_: 78 return compilation_info 79 return None 80 return database.GetCompilationInfoForFile( filename ) 81 82 83def FlagsForFile( filename, **kwargs ): 84 if database: 85 # Bear in mind that compilation_info.compiler_flags_ does NOT return a 86 # python list, but a "list-like" StringVec object 87 compilation_info = GetCompilationInfoForFile( filename ) 88 if not compilation_info: 89 return None 90 91 final_flags = MakeRelativePathsInFlagsAbsolute( 92 compilation_info.compiler_flags_, 93 compilation_info.compiler_working_dir_ ) 94 95 # NOTE: This is just for YouCompleteMe; it's highly likely that your project 96 # does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR 97 # ycm_extra_conf IF YOU'RE NOT 100% SURE YOU NEED IT. 98 try: 99 final_flags.remove( '-stdlib=libc++' ) 100 except ValueError: 101 pass 102 else: 103 relative_to = DirectoryOfThisScript() 104 final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) 105 106 return { 107 'flags': final_flags, 108 'do_cache': True 109 } 110