llvm-project
120 строк · 3.8 Кб
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):
40database = ycm_core.CompilationDatabase(compilation_database_folder)
41else:
42database = None
43
44SOURCE_EXTENSIONS = [".cc"]
45
46
47def DirectoryOfThisScript():
48return os.path.dirname(os.path.abspath(__file__))
49
50
51def MakeRelativePathsInFlagsAbsolute(flags, working_directory):
52if not working_directory:
53return list(flags)
54new_flags = []
55make_next_absolute = False
56path_flags = ["-isystem", "-I", "-iquote", "--sysroot="]
57for flag in flags:
58new_flag = flag
59
60if make_next_absolute:
61make_next_absolute = False
62if not flag.startswith("/"):
63new_flag = os.path.join(working_directory, flag)
64
65for path_flag in path_flags:
66if flag == path_flag:
67make_next_absolute = True
68break
69
70if flag.startswith(path_flag):
71path = flag[len(path_flag) :]
72new_flag = path_flag + os.path.join(working_directory, path)
73break
74
75if new_flag:
76new_flags.append(new_flag)
77return new_flags
78
79
80def IsHeaderFile(filename):
81extension = os.path.splitext(filename)[1]
82return 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.
90if IsHeaderFile(filename):
91basename = os.path.splitext(filename)[0]
92for extension in SOURCE_EXTENSIONS:
93replacement_file = basename + extension
94if os.path.exists(replacement_file):
95compilation_info = database.GetCompilationInfoForFile(
96replacement_file
97)
98if compilation_info.compiler_flags_:
99return compilation_info
100return None
101return database.GetCompilationInfoForFile(filename)
102
103
104def FlagsForFile(filename, **kwargs):
105if database:
106# Bear in mind that compilation_info.compiler_flags_ does NOT return a
107# python list, but a "list-like" StringVec object
108compilation_info = GetCompilationInfoForFile(filename)
109if not compilation_info:
110return None
111
112final_flags = MakeRelativePathsInFlagsAbsolute(
113compilation_info.compiler_flags_,
114compilation_info.compiler_working_dir_,
115)
116else:
117relative_to = DirectoryOfThisScript()
118final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to)
119
120return {"flags": final_flags, "do_cache": True}
121