blob: 5649ddcc749f0002829c02e6b7b10c6cd93bf7a5 [file] [log] [blame]
Dominic Hamond098d4c2014-01-15 16:11:09 -08001import os
2import ycm_core
3
4# These are the compilation flags that will be used in case there's no
5# compilation database set (by default, one is not set).
6# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR.
7flags = [
8'-Wall',
9'-Werror',
Wink Saville69a52cf2018-03-06 03:44:25 -080010'-pedantic-errors',
Dominic Hamond098d4c2014-01-15 16:11:09 -080011'-std=c++0x',
12'-fno-strict-aliasing',
13'-O3',
14'-DNDEBUG',
15# ...and the same thing goes for the magic -x option which specifies the
16# language that the files to be compiled are written in. This is mostly
17# relevant for c++ headers.
18# For a C project, you would set this to 'c' instead of 'c++'.
Dominic Hamon076f0df2014-01-16 09:12:59 -080019'-x', 'c++',
20'-I', 'include',
21'-isystem', '/usr/include',
22'-isystem', '/usr/local/include',
Dominic Hamond098d4c2014-01-15 16:11:09 -080023]
24
25
26# Set this to the absolute path to the folder (NOT the file!) containing the
27# compile_commands.json file to use that instead of 'flags'. See here for
28# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html
29#
30# Most projects will NOT need to set this to anything; you can just change the
31# 'flags' list of compilation flags. Notice that YCM itself uses that approach.
32compilation_database_folder = ''
33
34if os.path.exists( compilation_database_folder ):
35 database = ycm_core.CompilationDatabase( compilation_database_folder )
36else:
37 database = None
38
39SOURCE_EXTENSIONS = [ '.cc' ]
40
41def DirectoryOfThisScript():
42 return os.path.dirname( os.path.abspath( __file__ ) )
43
44
45def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
46 if not working_directory:
47 return list( flags )
48 new_flags = []
49 make_next_absolute = False
50 path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
51 for flag in flags:
52 new_flag = flag
53
54 if make_next_absolute:
55 make_next_absolute = False
56 if not flag.startswith( '/' ):
57 new_flag = os.path.join( working_directory, flag )
58
59 for path_flag in path_flags:
60 if flag == path_flag:
61 make_next_absolute = True
62 break
63
64 if flag.startswith( path_flag ):
65 path = flag[ len( path_flag ): ]
66 new_flag = path_flag + os.path.join( working_directory, path )
67 break
68
69 if new_flag:
70 new_flags.append( new_flag )
71 return new_flags
72
73
74def IsHeaderFile( filename ):
75 extension = os.path.splitext( filename )[ 1 ]
76 return extension in [ '.h', '.hxx', '.hpp', '.hh' ]
77
78
79def GetCompilationInfoForFile( filename ):
80 # The compilation_commands.json file generated by CMake does not have entries
81 # for header files. So we do our best by asking the db for flags for a
82 # corresponding source file, if any. If one exists, the flags for that file
83 # should be good enough.
84 if IsHeaderFile( filename ):
85 basename = os.path.splitext( filename )[ 0 ]
86 for extension in SOURCE_EXTENSIONS:
87 replacement_file = basename + extension
88 if os.path.exists( replacement_file ):
89 compilation_info = database.GetCompilationInfoForFile(
90 replacement_file )
91 if compilation_info.compiler_flags_:
92 return compilation_info
93 return None
94 return database.GetCompilationInfoForFile( filename )
95
96
97def FlagsForFile( filename, **kwargs ):
98 if database:
99 # Bear in mind that compilation_info.compiler_flags_ does NOT return a
100 # python list, but a "list-like" StringVec object
101 compilation_info = GetCompilationInfoForFile( filename )
102 if not compilation_info:
103 return None
104
105 final_flags = MakeRelativePathsInFlagsAbsolute(
106 compilation_info.compiler_flags_,
107 compilation_info.compiler_working_dir_ )
108 else:
109 relative_to = DirectoryOfThisScript()
110 final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
111
112 return {
113 'flags': final_flags,
114 'do_cache': True
115 }