Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 # Autocompletion config for YouCompleteMe in Chromium. | 5 # Autocompletion config for YouCompleteMe in Chromium. |
| 6 # | 6 # |
| 7 # USAGE: | 7 # USAGE: |
| 8 # | 8 # |
| 9 # 1. Install YCM [https://github.com/Valloric/YouCompleteMe] | 9 # 1. Install YCM [https://github.com/Valloric/YouCompleteMe] |
| 10 # (Googlers should check out [go/ycm]) | 10 # (Googlers should check out [go/ycm]) |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 69 while not (PathExists(curdir, 'src') | 69 while not (PathExists(curdir, 'src') |
| 70 and (PathExists(curdir, '.gclient') | 70 and (PathExists(curdir, '.gclient') |
| 71 or PathExists(curdir, 'src', '.git'))): | 71 or PathExists(curdir, 'src', '.git'))): |
| 72 nextdir = os.path.normpath(os.path.join(curdir, '..')) | 72 nextdir = os.path.normpath(os.path.join(curdir, '..')) |
| 73 if nextdir == curdir: | 73 if nextdir == curdir: |
| 74 return None | 74 return None |
| 75 curdir = nextdir | 75 curdir = nextdir |
| 76 return os.path.join(curdir, 'src') | 76 return os.path.join(curdir, 'src') |
| 77 | 77 |
| 78 | 78 |
| 79 # Largely copied from ninja-build.vim (guess_configuration) | |
| 80 def GetNinjaOutputDirectory(chrome_root): | |
| 81 """Returns either <chrome_root>/out/Release or <chrome_root>/out/Debug. | |
| 82 | |
| 83 The configuration chosen is the one most recently generated/built.""" | |
| 84 root = os.path.join(chrome_root, 'out') | |
| 85 debug_path = os.path.join(root, 'Debug') | |
| 86 release_path = os.path.join(root, 'Release') | |
| 87 | |
| 88 def is_release_15s_newer(test_path): | |
| 89 try: | |
| 90 debug_mtime = os.path.getmtime(os.path.join(debug_path, test_path)) | |
| 91 except os.error: | |
| 92 debug_mtime = 0 | |
| 93 try: | |
| 94 rel_mtime = os.path.getmtime(os.path.join(release_path, test_path)) | |
|
James Simonsen
2013/05/07 21:33:24
too many spaces before test_path
eroman
2013/05/08 01:31:07
Done.
| |
| 95 except os.error: | |
| 96 rel_mtime = 0 | |
| 97 return rel_mtime - debug_mtime >= 15 | |
| 98 | |
| 99 if is_release_15s_newer('build.ninja') or is_release_15s_newer('protoc'): | |
| 100 return release_path | |
| 101 return debug_path | |
| 102 | |
| 103 | |
| 79 def GetClangCommandFromNinjaForFilename(chrome_root, filename): | 104 def GetClangCommandFromNinjaForFilename(chrome_root, filename): |
| 80 """Returns the command line to build |filename|. | 105 """Returns the command line to build |filename|. |
| 81 | 106 |
| 82 Asks ninja how it would build the source file. If the specified file is a | 107 Asks ninja how it would build the source file. If the specified file is a |
| 83 header, tries to find its companion source file first. | 108 header, tries to find its companion source file first. |
| 84 | 109 |
| 85 Args: | 110 Args: |
| 86 chrome_root: (String) Path to src/. | 111 chrome_root: (String) Path to src/. |
| 87 filename: (String) Path to source file being edited. | 112 filename: (String) Path to source file being edited. |
| 88 | 113 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 108 else: | 133 else: |
| 109 # If this is a standalone .h file with no source, the best we can do is | 134 # If this is a standalone .h file with no source, the best we can do is |
| 110 # try to use the default flags. | 135 # try to use the default flags. |
| 111 return chrome_flags | 136 return chrome_flags |
| 112 | 137 |
| 113 # Ninja needs the path to the source file from the output build directory. | 138 # Ninja needs the path to the source file from the output build directory. |
| 114 # Cut off the common part and /. | 139 # Cut off the common part and /. |
| 115 subdir_filename = filename[len(chrome_root)+1:] | 140 subdir_filename = filename[len(chrome_root)+1:] |
| 116 rel_filename = os.path.join('..', '..', subdir_filename) | 141 rel_filename = os.path.join('..', '..', subdir_filename) |
| 117 | 142 |
| 143 out_dir = GetNinjaOutputDirectory(chrome_root) | |
| 144 | |
| 118 # Ask ninja how it would build our source file. | 145 # Ask ninja how it would build our source file. |
| 119 p = subprocess.Popen(['ninja', '-v', '-C', chrome_root + '/out/Release', '-t', | 146 p = subprocess.Popen(['ninja', '-v', '-C', out_dir, '-t', |
| 120 'commands', rel_filename + '^'], | 147 'commands', rel_filename + '^'], |
| 121 stdout=subprocess.PIPE) | 148 stdout=subprocess.PIPE) |
| 122 stdout, stderr = p.communicate() | 149 stdout, stderr = p.communicate() |
| 123 if p.returncode: | 150 if p.returncode: |
| 124 return chrome_flags | 151 return chrome_flags |
| 125 | 152 |
| 126 # Ninja might execute several commands to build something. We want the last | 153 # Ninja might execute several commands to build something. We want the last |
| 127 # clang command. | 154 # clang command. |
| 128 clang_line = None | 155 clang_line = None |
| 129 for line in reversed(stdout.split('\n')): | 156 for line in reversed(stdout.split('\n')): |
| 130 if 'clang' in line: | 157 if 'clang' in line: |
| 131 clang_line = line | 158 clang_line = line |
| 132 break | 159 break |
| 133 else: | 160 else: |
| 134 return chrome_flags | 161 return chrome_flags |
| 135 | 162 |
| 136 # Parse out the -I and -D flags. These seem to be the only ones that are | 163 # Parse out the -I and -D flags. These seem to be the only ones that are |
| 137 # important for YCM's purposes. | 164 # important for YCM's purposes. |
| 138 for flag in clang_line.split(' '): | 165 for flag in clang_line.split(' '): |
| 139 if flag.startswith('-I'): | 166 if flag.startswith('-I'): |
| 140 # Relative paths need to be resolved, because they're relative to the | 167 # Relative paths need to be resolved, because they're relative to the |
| 141 # output dir, not the source. | 168 # output dir, not the source. |
| 142 if flag[2] == '/': | 169 if flag[2] == '/': |
| 143 chrome_flags.append(flag) | 170 chrome_flags.append(flag) |
| 144 else: | 171 else: |
| 145 abs_path = os.path.normpath(os.path.join( | 172 abs_path = os.path.normpath(os.path.join(out_dir, flag[2:])) |
| 146 chrome_root, 'out', 'Release', flag[2:])) | |
| 147 chrome_flags.append('-I' + abs_path) | 173 chrome_flags.append('-I' + abs_path) |
| 148 elif flag.startswith('-') and flag[1] in 'DWFfmO': | 174 elif flag.startswith('-') and flag[1] in 'DWFfmO': |
| 149 chrome_flags.append(flag) | 175 chrome_flags.append(flag) |
| 150 | 176 |
| 151 return chrome_flags | 177 return chrome_flags |
| 152 | 178 |
| 153 | 179 |
| 154 def FlagsForFile(filename): | 180 def FlagsForFile(filename): |
| 155 """This is the main entry point for YCM. Its interface is fixed. | 181 """This is the main entry point for YCM. Its interface is fixed. |
| 156 | 182 |
| 157 Args: | 183 Args: |
| 158 filename: (String) Path to source file being edited. | 184 filename: (String) Path to source file being edited. |
| 159 | 185 |
| 160 Returns: | 186 Returns: |
| 161 (Dictionary) | 187 (Dictionary) |
| 162 'flags': (List of Strings) Command line flags. | 188 'flags': (List of Strings) Command line flags. |
| 163 'do_cache': (Boolean) True if the result should be cached. | 189 'do_cache': (Boolean) True if the result should be cached. |
| 164 """ | 190 """ |
| 165 chrome_root = FindChromeSrcFromFilename(filename) | 191 chrome_root = FindChromeSrcFromFilename(filename) |
| 166 chrome_flags = GetClangCommandFromNinjaForFilename(chrome_root, | 192 chrome_flags = GetClangCommandFromNinjaForFilename(chrome_root, |
| 167 filename) | 193 filename) |
| 168 final_flags = flags + chrome_flags | 194 final_flags = flags + chrome_flags |
| 169 | 195 |
| 170 return { | 196 return { |
| 171 'flags': final_flags, | 197 'flags': final_flags, |
| 172 'do_cache': True | 198 'do_cache': True |
| 173 } | 199 } |
| OLD | NEW |