Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright (c) 2012 Google Inc. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 """GYP backend that generates Eclipse CDT settings files. | |
| 6 | |
| 7 This backend DOES NOT generate Eclipse CDT projects. Instead, it generates XML | |
| 8 files that can be imported into an Eclipse CDT project. The XML file contains a | |
| 9 list of include paths and symbols (i.e. defines). | |
| 10 """ | |
|
Nico
2012/04/16 17:21:52
Since you don't intend this to be generally useful
Jesse Greenwald
2012/04/27 17:12:29
Done.
| |
| 11 | |
| 12 import os.path | |
| 13 import subprocess | |
| 14 import gyp | |
| 15 import gyp.common | |
| 16 import shlex | |
| 17 | |
| 18 generator_wants_static_library_dependencies_adjusted = False | |
| 19 | |
| 20 generator_default_variables = { | |
| 21 } | |
| 22 | |
| 23 for dirname in ['INTERMEDIATE_DIR', 'PRODUCT_DIR', 'LIB_DIR', 'SHARED_LIB_DIR']: | |
| 24 # Some gyp steps fail if these are empty(!). | |
| 25 generator_default_variables[dirname] = 'dir' | |
| 26 | |
| 27 for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', | |
| 28 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', | |
| 29 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX', | |
| 30 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX', | |
| 31 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX']: | |
| 32 generator_default_variables[unused] = '' | |
| 33 | |
| 34 # Include dirs will occasionaly use the SHARED_INTERMEDIATE_DIR variable as | |
| 35 # part of the path when dealing with generated headers. | |
| 36 # TODO: Make this work for all gyp generators (possible?). This currently | |
| 37 # matches what make gyp generator does. | |
| 38 generator_default_variables['SHARED_INTERMEDIATE_DIR'] = \ | |
| 39 os.getcwd() + '/out/Release/obj/gen' | |
|
Nico
2012/04/16 17:21:52
If this supports just one configuration, maybe you
Jesse Greenwald
2012/04/27 17:12:29
I've updated it to match the ninja generator behav
| |
| 40 | |
| 41 | |
| 42 def CalculateVariables(default_variables, params): | |
| 43 generator_flags = params.get('generator_flags', {}) | |
| 44 for key, val in generator_flags.items(): | |
| 45 default_variables.setdefault(key, val) | |
| 46 default_variables.setdefault('OS', gyp.common.GetFlavor(params)) | |
| 47 | |
| 48 | |
| 49 def CalculateGeneratorInputInfo(params): | |
| 50 """Calculate the generator specific info that gets fed to input (called by | |
| 51 gyp).""" | |
| 52 generator_flags = params.get('generator_flags', {}) | |
| 53 if generator_flags.get('adjust_static_libraries', False): | |
| 54 global generator_wants_static_library_dependencies_adjusted | |
| 55 generator_wants_static_library_dependencies_adjusted = True | |
| 56 | |
| 57 | |
| 58 def GetAllIncludeDirs(target_list, target_dicts): | |
| 59 """Calculate the set of include dirs to be used. | |
| 60 | |
| 61 Returns: | |
| 62 A list including all the include_dir's specified for every target followed | |
| 63 by any incude dirs that were added as cflag compiler options. | |
|
Nico
2012/04/16 16:12:12
typo incude
Jesse Greenwald
2012/04/16 17:00:55
Done.
| |
| 64 """ | |
| 65 | |
| 66 gyp_includes = [] | |
| 67 compiler_includes = [] | |
| 68 | |
| 69 for target_name in target_list: | |
| 70 target = target_dicts[target_name] | |
| 71 | |
| 72 for _, config in target['configurations'].iteritems(): | |
| 73 | |
| 74 # Look for any include dirs that were explicitly added via cflags. This | |
| 75 # may be done in gyp files to force certain includes to come at the end. | |
| 76 cflags = config['cflags'] | |
|
Nico
2012/04/16 16:12:12
'cflags' is linux-specific. It shouldn't be used t
Jesse Greenwald
2012/04/16 17:00:55
That makes sense.. but unfortunately this is being
Nico
2012/04/16 17:21:52
build/common.gypi could be changed though, right?
Jesse Greenwald
2012/04/27 17:12:29
It could probably be fixed at some point, although
| |
| 77 for cflag in cflags: | |
| 78 include_dir = '' | |
| 79 if cflag.startswith('-I'): | |
| 80 include_dir = cflag[2:] | |
| 81 if include_dir and not include_dir in compiler_includes: | |
| 82 compiler_includes.append(include_dir) | |
| 83 | |
| 84 # Find standard gyp include dirs | |
|
Nico
2012/04/16 16:12:12
add trailing .
Jesse Greenwald
2012/04/16 17:00:55
Done.
| |
| 85 if config.has_key('include_dirs'): | |
| 86 include_dirs = config['include_dirs'] | |
| 87 for include_dir in include_dirs: | |
| 88 if not os.path.isabs(include_dir): | |
| 89 base_dir = os.path.dirname(target_name) | |
| 90 | |
| 91 include_dir = base_dir + '/' + include_dir | |
| 92 include_dir = os.path.abspath(include_dir) | |
| 93 | |
| 94 if not include_dir in gyp_includes: | |
| 95 gyp_includes.append(include_dir) | |
| 96 | |
| 97 gyp_includes.sort() | |
| 98 | |
| 99 # Generate a list that has all the include dirs | |
| 100 all_includes = list(gyp_includes) | |
| 101 for compiler_include in compiler_includes: | |
| 102 if not compiler_include in all_includes: | |
| 103 all_includes.append(compiler_include) | |
| 104 | |
| 105 # All done | |
| 106 return all_includes | |
| 107 | |
| 108 | |
| 109 def GetCompilerPath(target_list, target_dicts, data): | |
| 110 """Determine a command that can be used to invoke the compiler. | |
| 111 | |
| 112 Returns: | |
| 113 If this is a gyp project that has explicit make settings, try to determine | |
| 114 the compiler from that. Otherwise, see if a compiler was specified via the | |
| 115 CC_target environment variable. | |
| 116 """ | |
| 117 | |
| 118 # First, see if the compiler is configured in make's settings | |
| 119 build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) | |
| 120 make_global_settings_dict = data[build_file].get('make_global_settings', {}) | |
| 121 for key, value in make_global_settings_dict: | |
| 122 if key in ['CC', 'CXX']: | |
| 123 return value | |
| 124 | |
| 125 # Check to see if the compiler was specified as an environment variable | |
| 126 cc_target = os.environ.get('CC_target') | |
| 127 if cc_target: | |
| 128 return cc_target | |
| 129 | |
| 130 # Default | |
| 131 return 'gcc' | |
| 132 | |
| 133 | |
| 134 def GetAllDefines(target_list, target_dicts, data): | |
| 135 """Calculate the defines for a project. | |
| 136 | |
| 137 Returns: | |
| 138 A dict that includes explict defines declared in gyp files along with all of | |
| 139 the default defines that the compiler uses. | |
| 140 """ | |
| 141 | |
| 142 # Get defines declared in the gyp files | |
| 143 all_defines = {} | |
| 144 for target_name in target_list: | |
| 145 target = target_dicts[target_name] | |
| 146 | |
| 147 for _, config in target['configurations'].iteritems(): | |
| 148 for define in config['defines']: | |
| 149 split_define = define.split('=', 1) | |
| 150 if len(split_define) == 1: | |
| 151 split_define.append('1') | |
| 152 if split_define[0].strip() in all_defines: | |
| 153 # Already defined | |
| 154 continue | |
| 155 | |
| 156 all_defines[split_define[0].strip()] = split_define[1].strip() | |
| 157 | |
| 158 # Get default compiler defines (if possible) | |
| 159 cc_target = GetCompilerPath(target_list, target_dicts, data) | |
| 160 if cc_target: | |
| 161 command = shlex.split(cc_target) | |
| 162 command.extend(['-E', '-dM', '-']) | |
| 163 cpp_proc = subprocess.Popen(args=command, cwd='.', | |
| 164 stdin=subprocess.PIPE, stdout=subprocess.PIPE) | |
| 165 cpp_output = cpp_proc.communicate()[0] | |
| 166 cpp_lines = cpp_output.split('\n') | |
| 167 for cpp_line in cpp_lines: | |
| 168 if not cpp_line.strip(): | |
| 169 continue | |
| 170 cpp_line_parts = cpp_line.split(' ', 2) | |
| 171 key = cpp_line_parts[1] | |
| 172 if len(cpp_line_parts) >= 3: | |
| 173 val = cpp_line_parts[2] | |
| 174 else: | |
| 175 val = '1' | |
| 176 all_defines[key] = val | |
| 177 | |
| 178 return all_defines | |
| 179 | |
| 180 | |
| 181 def WriteIncludePaths(out, eclipse_langs, include_dirs): | |
| 182 """Write the includes section of a CDT settings export file.""" | |
| 183 | |
| 184 out.write(' <section name="org.eclipse.cdt.internal.ui.wizards.' \ | |
| 185 'settingswizards.IncludePaths">\n') | |
| 186 out.write(' <language name="holder for library settings"></language>\n') | |
| 187 for lang in eclipse_langs: | |
| 188 out.write(' <language name="%s">\n' % lang) | |
| 189 for include_dir in include_dirs: | |
| 190 out.write(' <includepath workspace_path="false">%s</includepath>\n' % | |
| 191 include_dir) | |
| 192 out.write(' </language>\n') | |
| 193 out.write(' </section>\n') | |
| 194 | |
| 195 | |
| 196 def WriteMacros(out, eclipse_langs, defines): | |
| 197 """Write the macros section of a CDT settings export file.""" | |
| 198 | |
| 199 out.write(' <section name="org.eclipse.cdt.internal.ui.wizards.' \ | |
| 200 'settingswizards.Macros">\n') | |
| 201 out.write(' <language name="holder for library settings"></language>\n') | |
| 202 for lang in eclipse_langs: | |
| 203 out.write(' <language name="%s">\n' % lang) | |
| 204 for key in sorted(defines.iterkeys()): | |
| 205 out.write(' <macro><name>%s</name><value>%s</value></macro>\n' % | |
| 206 (key, defines[key])) | |
| 207 out.write(' </language>\n') | |
| 208 out.write(' </section>\n') | |
| 209 | |
| 210 | |
| 211 def GenerateOutput(target_list, target_dicts, data, params): | |
| 212 """Generate an XML settings file that can be imported into a CDT project.""" | |
| 213 | |
|
Nico
2012/04/16 17:21:52
You might want to print a warning or error if any
Jesse Greenwald
2012/04/27 17:12:29
Done.
| |
| 214 out = open('eclipse-cdt-settings.xml', 'w') | |
| 215 | |
| 216 out.write('<?xml version="1.0" encoding="UTF-8"?>\n') | |
| 217 out.write('<cdtprojectproperties>\n') | |
| 218 | |
| 219 eclipse_langs = ['C++ Source File', 'C Source File', 'Assembly Source File', | |
| 220 'GNU C++', 'GNU C', 'Assembly'] | |
| 221 WriteIncludePaths(out, eclipse_langs, | |
| 222 GetAllIncludeDirs(target_list, target_dicts)) | |
| 223 WriteMacros(out, eclipse_langs, GetAllDefines(target_list, target_dicts, | |
|
Nico
2012/04/16 16:12:12
This looks like it sets all defines from all targe
Jesse Greenwald
2012/04/16 17:00:55
The settings.xml file that gets generated isn't pe
| |
| 224 data)) | |
| 225 | |
| 226 out.write('</cdtprojectproperties>\n') | |
| 227 out.close() | |
| OLD | NEW |