.ycm_extra_conf.py
1 |
|
2 |
|
3 |
# NOTE: If the YCMD server "shuts down unexpectedly", it's possible that a new |
4 |
# version of Python's been installed (for example: 3.7 -> 3.8), but the YCMD |
5 |
# server is not updated then, so it expects 3.7, and can't find it. Check the |
6 |
# logs, and if it complains about that, go to the ycmd folder, and run |
7 |
# "python build.py --all". |
8 |
|
9 |
import os |
10 |
import ycm_core |
11 |
|
12 |
# These are the compilation flags that will be used in case there's no |
13 |
# compilation database set (by default, one is not set). |
14 |
flags = [ |
15 |
'-Wall', |
16 |
'-Wextra', |
17 |
'-Werror', |
18 |
'-Wc++98-compat', |
19 |
'-Wno-long-long', |
20 |
'-Wno-variadic-macros', |
21 |
'-fexceptions', |
22 |
'-DNDEBUG', |
23 |
# I try to refrain from having to write C++, so c99 is good for me. |
24 |
'-std=c', |
25 |
'-x', |
26 |
'c', |
27 |
'-isystem', |
28 |
'../BoostParts', |
29 |
'-isystem', |
30 |
# This path will only work on OS X, but extra paths that don't exist are not |
31 |
# harmful |
32 |
'/System/Library/Frameworks/Python.framework/Headers', |
33 |
'-isystem', |
34 |
'../llvm/include', |
35 |
'-isystem', |
36 |
'../llvm/tools/clang/include', |
37 |
'-I', |
38 |
'.', |
39 |
'-I', |
40 |
'./ClangCompleter', |
41 |
'-isystem', |
42 |
'./tests/gmock/gtest', |
43 |
'-isystem', |
44 |
'./tests/gmock/gtest/include', |
45 |
'-isystem', |
46 |
'./tests/gmock', |
47 |
'-isystem', |
48 |
'./tests/gmock/include', |
49 |
] |
50 |
|
51 |
compilation_database_folder = '' |
52 |
|
53 |
if os.path.exists( compilation_database_folder ): |
54 |
database = ycm_core.CompilationDatabase( compilation_database_folder ) |
55 |
else: |
56 |
database = None |
57 |
|
58 |
SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ] |
59 |
|
60 |
def DirectoryOfThisScript(): |
61 |
return os.path.dirname( os.path.abspath( __file__ ) ) |
62 |
|
63 |
|
64 |
def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): |
65 |
if not working_directory: |
66 |
return list( flags ) |
67 |
new_flags = [] |
68 |
make_next_absolute = False |
69 |
path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] |
70 |
for flag in flags: |
71 |
new_flag = flag |
72 |
|
73 |
if make_next_absolute: |
74 |
make_next_absolute = False |
75 |
if not flag.startswith( '/' ): |
76 |
new_flag = os.path.join( working_directory, flag ) |
77 |
|
78 |
for path_flag in path_flags: |
79 |
if flag == path_flag: |
80 |
make_next_absolute = True |
81 |
break |
82 |
|
83 |
if flag.startswith( path_flag ): |
84 |
path = flag[ len( path_flag ): ] |
85 |
new_flag = path_flag + os.path.join( working_directory, path ) |
86 |
break |
87 |
|
88 |
if new_flag: |
89 |
new_flags.append( new_flag ) |
90 |
return new_flags |
91 |
|
92 |
|
93 |
def IsHeaderFile( filename ): |
94 |
extension = os.path.splitext( filename )[ 1 ] |
95 |
return extension in [ '.h', '.hxx', '.hpp', '.hh' ] |
96 |
|
97 |
|
98 |
def GetCompilationInfoForFile( filename ): |
99 |
# The compilation_commands.json file generated by CMake does not have entries |
100 |
# for header files. So we do our best by asking the db for flags for a |
101 |
# corresponding source file, if any. If one exists, the flags for that file |
102 |
# should be good enough. |
103 |
if IsHeaderFile( filename ): |
104 |
basename = os.path.splitext( filename )[ 0 ] |
105 |
for extension in SOURCE_EXTENSIONS: |
106 |
replacement_file = basename + extension |
107 |
if os.path.exists( replacement_file ): |
108 |
compilation_info = database.GetCompilationInfoForFile( |
109 |
replacement_file ) |
110 |
if compilation_info.compiler_flags_: |
111 |
return compilation_info |
112 |
return None |
113 |
return database.GetCompilationInfoForFile( filename ) |
114 |
|
115 |
|
116 |
def FlagsForFile( filename, **kwargs ): |
117 |
if database: |
118 |
# Bear in mind that compilation_info.compiler_flags_ does NOT return a |
119 |
# python list, but a "list-like" StringVec object |
120 |
compilation_info = GetCompilationInfoForFile( filename ) |
121 |
if not compilation_info: |
122 |
return None |
123 |
|
124 |
final_flags = MakeRelativePathsInFlagsAbsolute( |
125 |
compilation_info.compiler_flags_, |
126 |
compilation_info.compiler_working_dir_ ) |
127 |
else: |
128 |
relative_to = DirectoryOfThisScript() |
129 |
final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) |
130 |
|
131 |
return { |
132 |
'flags': final_flags, |
133 |
'do_cache': True |
134 |
} |
135 |