Codebase list mozc / upstream/1.3.911.102
Imported Upstream version 1.3.911.102 Nobuhiro Iwamatsu 12 years ago
56 changed file(s) with 1622 addition(s) and 21782 deletion(s). Raw diff Collapse all Expand all
6262 {
6363 # Protobuf compiler / generator for the mozc inputmethod commands
6464 # protocol buffer.
65 'target_name': 'mozc_commands_proto',
66 'type': 'static_library',
65 'target_name': 'gen_candidates_proto',
66 'type': 'none',
6767 'sources': [
6868 '<(third_party_dir)/mozc/session/candidates_lite.proto',
6969 ],
105105 '<(third_party_dir)/protobuf/protobuf.gyp:protobuf_lite',
106106 ],
107107 },
108 {
109 'target_name': 'mozc_candidates_proto',
110 'type': 'static_library',
111 'sources': [
112 '<(protoc_out_dir)/third_party/mozc/session/candidates_lite.pb.cc',
113 ],
114 'dependencies': [
115 'gen_candidates_proto',
116 ],
117 },
108118 ]
109119 }
+0
-6
third_party/gyp/AUTHORS less more
0 # Names should be added to this file like so:
1 # Name or Organization <email address>
2
3 Google Inc.
4 Steven Knight <knight@baldmt.com>
5 Ryan Norton <rnorton10@gmail.com>
+0
-8
third_party/gyp/DEPS less more
0 # DEPS file for gclient use in buildbot execution of gyp tests.
1 #
2 # (You don't need to use gclient for normal GYP development work.)
3
4 deps = {
5 "scons":
6 "http://src.chromium.org/svn/trunk/src/third_party/scons@44099",
7 }
+0
-27
third_party/gyp/LICENSE less more
0 Copyright (c) 2009 Google Inc. All rights reserved.
1
2 Redistribution and use in source and binary forms, with or without
3 modification, are permitted provided that the following conditions are
4 met:
5
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above
9 copyright notice, this list of conditions and the following disclaimer
10 in the documentation and/or other materials provided with the
11 distribution.
12 * Neither the name of Google Inc. nor the names of its
13 contributors may be used to endorse or promote products derived from
14 this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+0
-21
third_party/gyp/MANIFEST less more
0 setup.py
1 gyp
2 LICENSE
3 AUTHORS
4 pylib/gyp/MSVSNew.py
5 pylib/gyp/MSVSProject.py
6 pylib/gyp/MSVSToolFile.py
7 pylib/gyp/MSVSUserFile.py
8 pylib/gyp/MSVSVersion.py
9 pylib/gyp/SCons.py
10 pylib/gyp/__init__.py
11 pylib/gyp/common.py
12 pylib/gyp/input.py
13 pylib/gyp/xcodeproj_file.py
14 pylib/gyp/generator/__init__.py
15 pylib/gyp/generator/gypd.py
16 pylib/gyp/generator/gypsh.py
17 pylib/gyp/generator/make.py
18 pylib/gyp/generator/msvs.py
19 pylib/gyp/generator/scons.py
20 pylib/gyp/generator/xcode.py
+0
-1
third_party/gyp/OWNERS less more
0 *
+0
-41
third_party/gyp/PRESUBMIT.py less more
0 # Copyright (c) 2011 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4
5 """Top-level presubmit script for GYP.
6
7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
8 for more details about the presubmit API built into gcl.
9 """
10
11
12 def CheckChangeOnUpload(input_api, output_api):
13 report = []
14 report.extend(input_api.canned_checks.PanProjectChecks(
15 input_api, output_api))
16 return report
17
18
19 def CheckChangeOnCommit(input_api, output_api):
20 report = []
21 license = (
22 r'.*? Copyright \(c\) %(year)s Google Inc\. All rights reserved\.\n'
23 r'.*? Use of this source code is governed by a BSD-style license that '
24 r'can be\n'
25 r'.*? found in the LICENSE file\.\n'
26 ) % {
27 'year': input_api.time.strftime('%Y'),
28 }
29
30 report.extend(input_api.canned_checks.PanProjectChecks(
31 input_api, output_api, license_header=license))
32 report.extend(input_api.canned_checks.CheckTreeIsOpen(
33 input_api, output_api,
34 'http://gyp-status.appspot.com/status',
35 'http://gyp-status.appspot.com/current'))
36 return report
37
38
39 def GetPreferredTrySlaves():
40 return ['gyp-win32', 'gyp-win64', 'gyp-linux', 'gyp-mac']
+0
-12
third_party/gyp/README.mozc less more
0 URL: http://code.google.com/p/gyp/
1 Version: r1034
2 License: New BSD License
3 License File: LICENSE
4
5 Description:
6 This is Mozc's local copy of gyp, a tool that generates native Visual Studio,
7 Xcode and SCons and/or make build files from a platform-independent input
8 format.
9
10 Local Modifications:
11 test directory is removed.
+0
-79
third_party/gyp/buildbot/buildbot_run.py less more
0 #!/usr/bin/python
1 # Copyright (c) 2011 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
6 """Argument-less script to select what to run on the buildbots."""
7
8
9 import os
10 import shutil
11 import subprocess
12 import sys
13
14
15 def GypTestFormat(title, format, msvs_version=None):
16 """Run the gyp tests for a given format, emitting annotator tags.
17
18 See annotator docs at:
19 https://sites.google.com/a/chromium.org/dev/developers/testing/chromium-build-infrastructure/buildbot-annotations
20 Args:
21 format: gyp format to test.
22 Returns:
23 0 for sucesss, 1 for failure.
24 """
25 print '@@@BUILD_STEP ' + title + '@@@'
26 sys.stdout.flush()
27 buildbot_dir = os.path.dirname(os.path.abspath(__file__))
28 trunk_dir = os.path.dirname(buildbot_dir)
29 root_dir = os.path.dirname(trunk_dir)
30 env = os.environ.copy()
31 if msvs_version:
32 env['GYP_MSVS_VERSION'] = msvs_version
33 retcode = subprocess.call(' '.join(
34 [sys.executable, 'trunk/gyptest.py',
35 '--all',
36 '--passed',
37 '--format', format,
38 '--chdir', 'trunk',
39 '--path', '../scons']),
40 cwd=root_dir, env=env, shell=True)
41 if retcode:
42 # Emit failure tag, and keep going.
43 print '@@@STEP_FAILURE@@@'
44 return 1
45 return 0
46
47
48 def GypBuild():
49 # Dump out/ directory.
50 print '@@@BUILD_STEP cleanup@@@'
51 print 'Removing out/ ...'
52 shutil.rmtree('out', ignore_errors=True)
53 print 'Done.'
54
55 retcode = 0
56 if sys.platform.startswith('linux'):
57 retcode += GypTestFormat('scons', format='scons')
58 retcode += GypTestFormat('make', format='make')
59 elif sys.platform == 'darwin':
60 retcode += GypTestFormat('xcode', format='xcode')
61 retcode += GypTestFormat('make', format='make')
62 elif sys.platform == 'win32':
63 retcode += GypTestFormat('msvs-2008', format='msvs', msvs_version='2008')
64 if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-win64':
65 retcode += GypTestFormat('msvs-2010', format='msvs', msvs_version='2010')
66 else:
67 raise Exception('Unknown platform')
68 if retcode:
69 # TODO(bradnelson): once the annotator supports a postscript (section for
70 # after the build proper that could be used for cumulative failures),
71 # use that instead of this. This isolates the final return value so
72 # that it isn't misattributed to the last stage.
73 print '@@@BUILD_STEP failures@@@'
74 sys.exit(retcode)
75
76
77 if __name__ == '__main__':
78 GypBuild()
+0
-10
third_party/gyp/codereview.settings less more
0 # This file is used by gcl to get repository specific information.
1 CODE_REVIEW_SERVER: codereview.chromium.org
2 CC_LIST: gyp-developer@googlegroups.com
3 VIEW_VC: http://code.google.com/p/gyp/source/detail?r=
4 TRY_ON_UPLOAD: True
5 TRYSERVER_PROJECT: gyp
6 TRYSERVER_PATCHLEVEL: 0
7 TRYSERVER_ROOT: trunk
8 TRYSERVER_SVN_URL: svn://svn.chromium.org/chrome-try/try-nacl
9
+0
-18
third_party/gyp/gyp less more
0 #!/usr/bin/env python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import sys
7
8 # TODO(mark): sys.path manipulation is some temporary testing stuff.
9 try:
10 import gyp
11 except ImportError, e:
12 import os.path
13 sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), 'pylib'))
14 import gyp
15
16 if __name__ == '__main__':
17 sys.exit(gyp.main(sys.argv[1:]))
+0
-5
third_party/gyp/gyp.bat less more
0 @rem Copyright (c) 2009 Google Inc. All rights reserved.
1 @rem Use of this source code is governed by a BSD-style license that can be
2 @rem found in the LICENSE file.
3
4 @python "%~dp0/gyp" %*
+0
-7
third_party/gyp/gyp_dummy.c less more
0 /* Copyright (c) 2009 Google Inc. All rights reserved.
1 * Use of this source code is governed by a BSD-style license that can be
2 * found in the LICENSE file. */
3
4 int main() {
5 return 0;
6 }
+0
-256
third_party/gyp/gyptest.py less more
0 #!/usr/bin/env python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 __doc__ = """
7 gyptest.py -- test runner for GYP tests.
8 """
9
10 import os
11 import optparse
12 import subprocess
13 import sys
14
15 class CommandRunner:
16 """
17 Executor class for commands, including "commands" implemented by
18 Python functions.
19 """
20 verbose = True
21 active = True
22
23 def __init__(self, dictionary={}):
24 self.subst_dictionary(dictionary)
25
26 def subst_dictionary(self, dictionary):
27 self._subst_dictionary = dictionary
28
29 def subst(self, string, dictionary=None):
30 """
31 Substitutes (via the format operator) the values in the specified
32 dictionary into the specified command.
33
34 The command can be an (action, string) tuple. In all cases, we
35 perform substitution on strings and don't worry if something isn't
36 a string. (It's probably a Python function to be executed.)
37 """
38 if dictionary is None:
39 dictionary = self._subst_dictionary
40 if dictionary:
41 try:
42 string = string % dictionary
43 except TypeError:
44 pass
45 return string
46
47 def display(self, command, stdout=None, stderr=None):
48 if not self.verbose:
49 return
50 if type(command) == type(()):
51 func = command[0]
52 args = command[1:]
53 s = '%s(%s)' % (func.__name__, ', '.join(map(repr, args)))
54 if type(command) == type([]):
55 # TODO: quote arguments containing spaces
56 # TODO: handle meta characters?
57 s = ' '.join(command)
58 else:
59 s = self.subst(command)
60 if not s.endswith('\n'):
61 s += '\n'
62 sys.stdout.write(s)
63 sys.stdout.flush()
64
65 def execute(self, command, stdout=None, stderr=None):
66 """
67 Executes a single command.
68 """
69 if not self.active:
70 return 0
71 if type(command) == type(''):
72 command = self.subst(command)
73 cmdargs = shlex.split(command)
74 if cmdargs[0] == 'cd':
75 command = (os.chdir,) + tuple(cmdargs[1:])
76 if type(command) == type(()):
77 func = command[0]
78 args = command[1:]
79 return func(*args)
80 else:
81 if stdout is sys.stdout:
82 # Same as passing sys.stdout, except python2.4 doesn't fail on it.
83 subout = None
84 else:
85 # Open pipe for anything else so Popen works on python2.4.
86 subout = subprocess.PIPE
87 if stderr is sys.stderr:
88 # Same as passing sys.stderr, except python2.4 doesn't fail on it.
89 suberr = None
90 elif stderr is None:
91 # Merge with stdout if stderr isn't specified.
92 suberr = subprocess.STDOUT
93 else:
94 # Open pipe for anything else so Popen works on python2.4.
95 suberr = subprocess.PIPE
96 p = subprocess.Popen(command,
97 shell=(sys.platform == 'win32'),
98 stdout=subout,
99 stderr=suberr)
100 p.wait()
101 if stdout is None:
102 self.stdout = p.stdout.read()
103 elif stdout is not sys.stdout:
104 stdout.write(p.stdout.read())
105 if stderr not in (None, sys.stderr):
106 stderr.write(p.stderr.read())
107 return p.returncode
108
109 def run(self, command, display=None, stdout=None, stderr=None):
110 """
111 Runs a single command, displaying it first.
112 """
113 if display is None:
114 display = command
115 self.display(display)
116 return self.execute(command, stdout, stderr)
117
118
119 class Unbuffered:
120 def __init__(self, fp):
121 self.fp = fp
122 def write(self, arg):
123 self.fp.write(arg)
124 self.fp.flush()
125 def __getattr__(self, attr):
126 return getattr(self.fp, attr)
127
128 sys.stdout = Unbuffered(sys.stdout)
129 sys.stderr = Unbuffered(sys.stderr)
130
131
132 def find_all_gyptest_files(directory):
133 result = []
134 for root, dirs, files in os.walk(directory):
135 if '.svn' in dirs:
136 dirs.remove('.svn')
137 result.extend([ os.path.join(root, f) for f in files
138 if f.startswith('gyptest') and f.endswith('.py') ])
139 result.sort()
140 return result
141
142
143 def main(argv=None):
144 if argv is None:
145 argv = sys.argv
146
147 usage = "gyptest.py [-ahlnq] [-f formats] [test ...]"
148 parser = optparse.OptionParser(usage=usage)
149 parser.add_option("-a", "--all", action="store_true",
150 help="run all tests")
151 parser.add_option("-C", "--chdir", action="store", default=None,
152 help="chdir to the specified directory")
153 parser.add_option("-f", "--format", action="store", default='',
154 help="run tests with the specified formats")
155 parser.add_option("-l", "--list", action="store_true",
156 help="list available tests and exit")
157 parser.add_option("-n", "--no-exec", action="store_true",
158 help="no execute, just print the command line")
159 parser.add_option("--passed", action="store_true",
160 help="report passed tests")
161 parser.add_option("--path", action="append", default=[],
162 help="additional $PATH directory")
163 parser.add_option("-q", "--quiet", action="store_true",
164 help="quiet, don't print test command lines")
165 opts, args = parser.parse_args(argv[1:])
166
167 if opts.chdir:
168 os.chdir(opts.chdir)
169
170 if opts.path:
171 os.environ['PATH'] += ':' + ':'.join(opts.path)
172
173 if not args:
174 if not opts.all:
175 sys.stderr.write('Specify -a to get all tests.\n')
176 return 1
177 args = ['test']
178
179 tests = []
180 for arg in args:
181 if os.path.isdir(arg):
182 tests.extend(find_all_gyptest_files(os.path.normpath(arg)))
183 else:
184 tests.append(arg)
185
186 if opts.list:
187 for test in tests:
188 print test
189 sys.exit(0)
190
191 CommandRunner.verbose = not opts.quiet
192 CommandRunner.active = not opts.no_exec
193 cr = CommandRunner()
194
195 os.environ['PYTHONPATH'] = os.path.abspath('test/lib')
196 if not opts.quiet:
197 sys.stdout.write('PYTHONPATH=%s\n' % os.environ['PYTHONPATH'])
198
199 passed = []
200 failed = []
201 no_result = []
202
203 if opts.format:
204 format_list = opts.format.split(',')
205 else:
206 # TODO: not duplicate this mapping from pylib/gyp/__init__.py
207 format_list = {
208 'freebsd7': ['make'],
209 'freebsd8': ['make'],
210 'cygwin': ['msvs'],
211 'win32': ['msvs'],
212 'linux2': ['make', 'ninja'],
213 'linux3': ['make', 'ninja'],
214 'darwin': ['make', 'xcode'],
215 }[sys.platform]
216
217 for format in format_list:
218 os.environ['TESTGYP_FORMAT'] = format
219 if not opts.quiet:
220 sys.stdout.write('TESTGYP_FORMAT=%s\n' % format)
221
222 for test in tests:
223 status = cr.run([sys.executable, test],
224 stdout=sys.stdout,
225 stderr=sys.stderr)
226 if status == 2:
227 no_result.append(test)
228 elif status:
229 failed.append(test)
230 else:
231 passed.append(test)
232
233 if not opts.quiet:
234 def report(description, tests):
235 if tests:
236 if len(tests) == 1:
237 sys.stdout.write("\n%s the following test:\n" % description)
238 else:
239 fmt = "\n%s the following %d tests:\n"
240 sys.stdout.write(fmt % (description, len(tests)))
241 sys.stdout.write("\t" + "\n\t".join(tests) + "\n")
242
243 if opts.passed:
244 report("Passed", passed)
245 report("Failed", failed)
246 report("No result from", no_result)
247
248 if failed:
249 return 1
250 else:
251 return 0
252
253
254 if __name__ == "__main__":
255 sys.exit(main())
+0
-340
third_party/gyp/pylib/gyp/MSVSNew.py less more
0 #!/usr/bin/python2.4
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """New implementation of Visual Studio project generation for SCons."""
7
8 import common
9 import os
10 import random
11
12 import gyp.common
13
14 # hashlib is supplied as of Python 2.5 as the replacement interface for md5
15 # and other secure hashes. In 2.6, md5 is deprecated. Import hashlib if
16 # available, avoiding a deprecation warning under 2.6. Import md5 otherwise,
17 # preserving 2.4 compatibility.
18 try:
19 import hashlib
20 _new_md5 = hashlib.md5
21 except ImportError:
22 import md5
23 _new_md5 = md5.new
24
25
26 # Initialize random number generator
27 random.seed()
28
29 # GUIDs for project types
30 ENTRY_TYPE_GUIDS = {
31 'project': '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}',
32 'folder': '{2150E333-8FDC-42A3-9474-1A3956D46DE8}',
33 }
34
35 #------------------------------------------------------------------------------
36 # Helper functions
37
38
39 def MakeGuid(name, seed='msvs_new'):
40 """Returns a GUID for the specified target name.
41
42 Args:
43 name: Target name.
44 seed: Seed for MD5 hash.
45 Returns:
46 A GUID-line string calculated from the name and seed.
47
48 This generates something which looks like a GUID, but depends only on the
49 name and seed. This means the same name/seed will always generate the same
50 GUID, so that projects and solutions which refer to each other can explicitly
51 determine the GUID to refer to explicitly. It also means that the GUID will
52 not change when the project for a target is rebuilt.
53 """
54 # Calculate a MD5 signature for the seed and name.
55 d = _new_md5(str(seed) + str(name)).hexdigest().upper()
56 # Convert most of the signature to GUID form (discard the rest)
57 guid = ('{' + d[:8] + '-' + d[8:12] + '-' + d[12:16] + '-' + d[16:20]
58 + '-' + d[20:32] + '}')
59 return guid
60
61 #------------------------------------------------------------------------------
62
63
64 class MSVSFolder:
65 """Folder in a Visual Studio project or solution."""
66
67 def __init__(self, path, name = None, entries = None,
68 guid = None, items = None):
69 """Initializes the folder.
70
71 Args:
72 path: Full path to the folder.
73 name: Name of the folder.
74 entries: List of folder entries to nest inside this folder. May contain
75 Folder or Project objects. May be None, if the folder is empty.
76 guid: GUID to use for folder, if not None.
77 items: List of solution items to include in the folder project. May be
78 None, if the folder does not directly contain items.
79 """
80 if name:
81 self.name = name
82 else:
83 # Use last layer.
84 self.name = os.path.basename(path)
85
86 self.path = path
87 self.guid = guid
88
89 # Copy passed lists (or set to empty lists)
90 self.entries = list(entries or [])
91 self.items = list(items or [])
92
93 self.entry_type_guid = ENTRY_TYPE_GUIDS['folder']
94
95 def get_guid(self):
96 if self.guid is None:
97 # Use consistent guids for folders (so things don't regenerate).
98 self.guid = MakeGuid(self.path, seed='msvs_folder')
99 return self.guid
100
101
102 #------------------------------------------------------------------------------
103
104
105 class MSVSProject:
106 """Visual Studio project."""
107
108 def __init__(self, path, name = None, dependencies = None, guid = None,
109 spec = None, build_file = None, config_platform_overrides = None,
110 fixpath_prefix = None):
111 """Initializes the project.
112
113 Args:
114 path: Absolute path to the project file.
115 name: Name of project. If None, the name will be the same as the base
116 name of the project file.
117 dependencies: List of other Project objects this project is dependent
118 upon, if not None.
119 guid: GUID to use for project, if not None.
120 spec: Dictionary specifying how to build this project.
121 build_file: Filename of the .gyp file that the vcproj file comes from.
122 config_platform_overrides: optional dict of configuration platforms to
123 used in place of the default for this target.
124 fixpath_prefix: the path used to adjust the behavior of _fixpath
125 """
126 self.path = path
127 self.guid = guid
128 self.spec = spec
129 self.build_file = build_file
130 # Use project filename if name not specified
131 self.name = name or os.path.splitext(os.path.basename(path))[0]
132
133 # Copy passed lists (or set to empty lists)
134 self.dependencies = list(dependencies or [])
135
136 self.entry_type_guid = ENTRY_TYPE_GUIDS['project']
137
138 if config_platform_overrides:
139 self.config_platform_overrides = config_platform_overrides
140 else:
141 self.config_platform_overrides = {}
142 self.fixpath_prefix = fixpath_prefix
143
144 def set_dependencies(self, dependencies):
145 self.dependencies = list(dependencies or [])
146
147 def get_guid(self):
148 if self.guid is None:
149 # Set GUID from path
150 # TODO(rspangler): This is fragile.
151 # 1. We can't just use the project filename sans path, since there could
152 # be multiple projects with the same base name (for example,
153 # foo/unittest.vcproj and bar/unittest.vcproj).
154 # 2. The path needs to be relative to $SOURCE_ROOT, so that the project
155 # GUID is the same whether it's included from base/base.sln or
156 # foo/bar/baz/baz.sln.
157 # 3. The GUID needs to be the same each time this builder is invoked, so
158 # that we don't need to rebuild the solution when the project changes.
159 # 4. We should be able to handle pre-built project files by reading the
160 # GUID from the files.
161 self.guid = MakeGuid(self.name)
162 return self.guid
163
164 #------------------------------------------------------------------------------
165
166
167 class MSVSSolution:
168 """Visual Studio solution."""
169
170 def __init__(self, path, version, entries=None, variants=None,
171 websiteProperties=True):
172 """Initializes the solution.
173
174 Args:
175 path: Path to solution file.
176 version: Format version to emit.
177 entries: List of entries in solution. May contain Folder or Project
178 objects. May be None, if the folder is empty.
179 variants: List of build variant strings. If none, a default list will
180 be used.
181 websiteProperties: Flag to decide if the website properties section
182 is generated.
183 """
184 self.path = path
185 self.websiteProperties = websiteProperties
186 self.version = version
187
188 # Copy passed lists (or set to empty lists)
189 self.entries = list(entries or [])
190
191 if variants:
192 # Copy passed list
193 self.variants = variants[:]
194 else:
195 # Use default
196 self.variants = ['Debug|Win32', 'Release|Win32']
197 # TODO(rspangler): Need to be able to handle a mapping of solution config
198 # to project config. Should we be able to handle variants being a dict,
199 # or add a separate variant_map variable? If it's a dict, we can't
200 # guarantee the order of variants since dict keys aren't ordered.
201
202
203 # TODO(rspangler): Automatically write to disk for now; should delay until
204 # node-evaluation time.
205 self.Write()
206
207
208 def Write(self, writer=common.WriteOnDiff):
209 """Writes the solution file to disk.
210
211 Raises:
212 IndexError: An entry appears multiple times.
213 """
214 # Walk the entry tree and collect all the folders and projects.
215 all_entries = set()
216 entries_to_check = self.entries[:]
217 while entries_to_check:
218 e = entries_to_check.pop(0)
219
220 # If this entry has been visited, nothing to do.
221 if e in all_entries:
222 continue
223
224 all_entries.add(e)
225
226 # If this is a folder, check its entries too.
227 if isinstance(e, MSVSFolder):
228 entries_to_check += e.entries
229
230 # Sort by name then guid (so things are in order on vs2008).
231 def NameThenGuid(a, b):
232 if a.name < b.name: return -1
233 if a.name > b.name: return 1
234 if a.get_guid() < b.get_guid(): return -1
235 if a.get_guid() > b.get_guid(): return 1
236 return 0
237
238 all_entries = sorted(all_entries, NameThenGuid)
239
240 # Open file and print header
241 f = writer(self.path)
242 f.write('Microsoft Visual Studio Solution File, '
243 'Format Version %s\r\n' % self.version.SolutionVersion())
244 f.write('# %s\r\n' % self.version.Description())
245
246 # Project entries
247 sln_root = os.path.split(self.path)[0]
248 for e in all_entries:
249 relative_path = gyp.common.RelativePath(e.path, sln_root)
250 # msbuild does not accept an empty folder_name.
251 # use '.' in case relative_path is empty.
252 folder_name = relative_path.replace('/', '\\') or '.'
253 f.write('Project("%s") = "%s", "%s", "%s"\r\n' % (
254 e.entry_type_guid, # Entry type GUID
255 e.name, # Folder name
256 folder_name, # Folder name (again)
257 e.get_guid(), # Entry GUID
258 ))
259
260 # TODO(rspangler): Need a way to configure this stuff
261 if self.websiteProperties:
262 f.write('\tProjectSection(WebsiteProperties) = preProject\r\n'
263 '\t\tDebug.AspNetCompiler.Debug = "True"\r\n'
264 '\t\tRelease.AspNetCompiler.Debug = "False"\r\n'
265 '\tEndProjectSection\r\n')
266
267 if isinstance(e, MSVSFolder):
268 if e.items:
269 f.write('\tProjectSection(SolutionItems) = preProject\r\n')
270 for i in e.items:
271 f.write('\t\t%s = %s\r\n' % (i, i))
272 f.write('\tEndProjectSection\r\n')
273
274 if isinstance(e, MSVSProject):
275 if e.dependencies:
276 f.write('\tProjectSection(ProjectDependencies) = postProject\r\n')
277 for d in e.dependencies:
278 f.write('\t\t%s = %s\r\n' % (d.get_guid(), d.get_guid()))
279 f.write('\tEndProjectSection\r\n')
280
281 f.write('EndProject\r\n')
282
283 # Global section
284 f.write('Global\r\n')
285
286 # Configurations (variants)
287 f.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n')
288 for v in self.variants:
289 f.write('\t\t%s = %s\r\n' % (v, v))
290 f.write('\tEndGlobalSection\r\n')
291
292 # Sort config guids for easier diffing of solution changes.
293 config_guids = []
294 config_guids_overrides = {}
295 for e in all_entries:
296 if isinstance(e, MSVSProject):
297 config_guids.append(e.get_guid())
298 config_guids_overrides[e.get_guid()] = e.config_platform_overrides
299 config_guids.sort()
300
301 f.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n')
302 for g in config_guids:
303 for v in self.variants:
304 nv = config_guids_overrides[g].get(v, v)
305 # Pick which project configuration to build for this solution
306 # configuration.
307 f.write('\t\t%s.%s.ActiveCfg = %s\r\n' % (
308 g, # Project GUID
309 v, # Solution build configuration
310 nv, # Project build config for that solution config
311 ))
312
313 # Enable project in this solution configuration.
314 f.write('\t\t%s.%s.Build.0 = %s\r\n' % (
315 g, # Project GUID
316 v, # Solution build configuration
317 nv, # Project build config for that solution config
318 ))
319 f.write('\tEndGlobalSection\r\n')
320
321 # TODO(rspangler): Should be able to configure this stuff too (though I've
322 # never seen this be any different)
323 f.write('\tGlobalSection(SolutionProperties) = preSolution\r\n')
324 f.write('\t\tHideSolutionNode = FALSE\r\n')
325 f.write('\tEndGlobalSection\r\n')
326
327 # Folder mappings
328 # TODO(rspangler): Should omit this section if there are no folders
329 f.write('\tGlobalSection(NestedProjects) = preSolution\r\n')
330 for e in all_entries:
331 if not isinstance(e, MSVSFolder):
332 continue # Does not apply to projects, only folders
333 for subentry in e.entries:
334 f.write('\t\t%s = %s\r\n' % (subentry.get_guid(), e.get_guid()))
335 f.write('\tEndGlobalSection\r\n')
336
337 f.write('EndGlobal\r\n')
338
339 f.close()
+0
-212
third_party/gyp/pylib/gyp/MSVSProject.py less more
0 #!/usr/bin/python2.4
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Visual Studio project reader/writer."""
7
8 import common
9 import gyp.easy_xml as easy_xml
10
11 #------------------------------------------------------------------------------
12
13
14 class Tool(object):
15 """Visual Studio tool."""
16
17 def __init__(self, name, attrs=None):
18 """Initializes the tool.
19
20 Args:
21 name: Tool name.
22 attrs: Dict of tool attributes; may be None.
23 """
24 self._attrs = attrs or {}
25 self._attrs['Name'] = name
26
27 def _GetSpecification(self):
28 """Creates an element for the tool.
29
30 Returns:
31 A new xml.dom.Element for the tool.
32 """
33 return ['Tool', self._attrs]
34
35 class Filter(object):
36 """Visual Studio filter - that is, a virtual folder."""
37
38 def __init__(self, name, contents=None):
39 """Initializes the folder.
40
41 Args:
42 name: Filter (folder) name.
43 contents: List of filenames and/or Filter objects contained.
44 """
45 self.name = name
46 self.contents = list(contents or [])
47
48
49 #------------------------------------------------------------------------------
50
51
52 class Writer(object):
53 """Visual Studio XML project writer."""
54
55 def __init__(self, project_path, version, name, guid=None, platforms=None):
56 """Initializes the project.
57
58 Args:
59 project_path: Path to the project file.
60 version: Format version to emit.
61 name: Name of the project.
62 guid: GUID to use for project, if not None.
63 platforms: Array of string, the supported platforms. If null, ['Win32']
64 """
65 self.project_path = project_path
66 self.version = version
67 self.name = name
68 self.guid = guid
69
70 # Default to Win32 for platforms.
71 if not platforms:
72 platforms = ['Win32']
73
74 # Initialize the specifications of the various sections.
75 self.platform_section = ['Platforms']
76 for platform in platforms:
77 self.platform_section.append(['Platform', {'Name': platform}])
78 self.tool_files_section = ['ToolFiles']
79 self.configurations_section = ['Configurations']
80 self.files_section = ['Files']
81
82 # Keep a dict keyed on filename to speed up access.
83 self.files_dict = dict()
84
85 def AddToolFile(self, path):
86 """Adds a tool file to the project.
87
88 Args:
89 path: Relative path from project to tool file.
90 """
91 self.tool_files_section.append(['ToolFile', {'RelativePath': path}])
92
93 def _GetSpecForConfiguration(self, config_type, config_name, attrs, tools):
94 """Returns the specification for a configuration.
95
96 Args:
97 config_type: Type of configuration node.
98 config_name: Configuration name.
99 attrs: Dict of configuration attributes; may be None.
100 tools: List of tools (strings or Tool objects); may be None.
101 Returns:
102 """
103 # Handle defaults
104 if not attrs:
105 attrs = {}
106 if not tools:
107 tools = []
108
109 # Add configuration node and its attributes
110 node_attrs = attrs.copy()
111 node_attrs['Name'] = config_name
112 specification = [config_type, node_attrs]
113
114 # Add tool nodes and their attributes
115 if tools:
116 for t in tools:
117 if isinstance(t, Tool):
118 specification.append(t._GetSpecification())
119 else:
120 specification.append(Tool(t)._GetSpecification())
121 return specification
122
123
124 def AddConfig(self, name, attrs=None, tools=None):
125 """Adds a configuration to the project.
126
127 Args:
128 name: Configuration name.
129 attrs: Dict of configuration attributes; may be None.
130 tools: List of tools (strings or Tool objects); may be None.
131 """
132 spec = self._GetSpecForConfiguration('Configuration', name, attrs, tools)
133 self.configurations_section.append(spec)
134
135 def _AddFilesToNode(self, parent, files):
136 """Adds files and/or filters to the parent node.
137
138 Args:
139 parent: Destination node
140 files: A list of Filter objects and/or relative paths to files.
141
142 Will call itself recursively, if the files list contains Filter objects.
143 """
144 for f in files:
145 if isinstance(f, Filter):
146 node = ['Filter', {'Name': f.name}]
147 self._AddFilesToNode(node, f.contents)
148 else:
149 node = ['File', {'RelativePath': f}]
150 self.files_dict[f] = node
151 parent.append(node)
152
153 def AddFiles(self, files):
154 """Adds files to the project.
155
156 Args:
157 files: A list of Filter objects and/or relative paths to files.
158
159 This makes a copy of the file/filter tree at the time of this call. If you
160 later add files to a Filter object which was passed into a previous call
161 to AddFiles(), it will not be reflected in this project.
162 """
163 self._AddFilesToNode(self.files_section, files)
164 # TODO(rspangler) This also doesn't handle adding files to an existing
165 # filter. That is, it doesn't merge the trees.
166
167 def AddFileConfig(self, path, config, attrs=None, tools=None):
168 """Adds a configuration to a file.
169
170 Args:
171 path: Relative path to the file.
172 config: Name of configuration to add.
173 attrs: Dict of configuration attributes; may be None.
174 tools: List of tools (strings or Tool objects); may be None.
175
176 Raises:
177 ValueError: Relative path does not match any file added via AddFiles().
178 """
179 # Find the file node with the right relative path
180 parent = self.files_dict.get(path)
181 if not parent:
182 raise ValueError('AddFileConfig: file "%s" not in project.' % path)
183
184 # Add the config to the file node
185 spec = self._GetSpecForConfiguration('FileConfiguration', config, attrs,
186 tools)
187 parent.append(spec)
188
189 def WriteIfChanged(self):
190 """Writes the project file."""
191 # First create XML content definition
192 content = [
193 'VisualStudioProject',
194 {'ProjectType': 'Visual C++',
195 'Version': self.version.ProjectVersion(),
196 'Name': self.name,
197 'ProjectGUID': self.guid,
198 'RootNamespace': self.name,
199 'Keyword': 'Win32Proj'
200 },
201 self.platform_section,
202 self.tool_files_section,
203 self.configurations_section,
204 ['References'], # empty section
205 self.files_section,
206 ['Globals'] # empty section
207 ]
208 easy_xml.WriteXmlIfChanged(content, self.project_path,
209 encoding="Windows-1252")
210
211 #------------------------------------------------------------------------------
+0
-1033
third_party/gyp/pylib/gyp/MSVSSettings.py less more
0 #!/usr/bin/python
1 # Copyright (c) 2011 The Chromium Authors. 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 """Code to validate and convert settings of the Microsoft build tools.
6
7 This file contains code to validate and convert settings of the Microsoft
8 build tools. The function ConvertToMSBuildSettings(), ValidateMSVSSettings(),
9 and ValidateMSBuildSettings() are the entry points.
10
11 This file was created by comparing the projects created by Visual Studio 2008
12 and Visual Studio 2010 for all available settings through the user interface.
13 The MSBuild schemas were also considered. They are typically found in the
14 MSBuild install directory, e.g. c:\Program Files (x86)\MSBuild
15 """
16
17 import sys
18
19
20 # Dictionaries of settings validators. The key is the tool name, the value is
21 # a dictionary mapping setting names to validation functions.
22 _msvs_validators = {}
23 _msbuild_validators = {}
24
25
26 # A dictionary of settings converters. The key is the tool name, the value is
27 # a dictionary mapping setting names to conversion functions.
28 _msvs_to_msbuild_converters = {}
29
30
31 # Tool name mapping from MSVS to MSBuild.
32 _msbuild_name_of_tool = {}
33
34
35 class _Tool(object):
36 """Represents a tool used by MSVS or MSBuild.
37
38 Attributes:
39 msvs_name: The name of the tool in MSVS.
40 msbuild_name: The name of the tool in MSBuild.
41 """
42
43 def __init__(self, msvs_name, msbuild_name):
44 self.msvs_name = msvs_name
45 self.msbuild_name = msbuild_name
46
47
48 def _AddTool(tool):
49 """Adds a tool to the four dictionaries used to process settings.
50
51 This only defines the tool. Each setting also needs to be added.
52
53 Args:
54 tool: The _Tool object to be added.
55 """
56 _msvs_validators[tool.msvs_name] = {}
57 _msbuild_validators[tool.msbuild_name] = {}
58 _msvs_to_msbuild_converters[tool.msvs_name] = {}
59 _msbuild_name_of_tool[tool.msvs_name] = tool.msbuild_name
60
61
62 def _GetMSBuildToolSettings(msbuild_settings, tool):
63 """Returns an MSBuild tool dictionary. Creates it if needed."""
64 return msbuild_settings.setdefault(tool.msbuild_name, {})
65
66
67 class _Type(object):
68 """Type of settings (Base class)."""
69
70 def ValidateMSVS(self, value):
71 """Verifies that the value is legal for MSVS.
72
73 Args:
74 value: the value to check for this type.
75
76 Raises:
77 ValueError if value is not valid for MSVS.
78 """
79
80 def ValidateMSBuild(self, value):
81 """Verifies that the value is legal for MSBuild.
82
83 Args:
84 value: the value to check for this type.
85
86 Raises:
87 ValueError if value is not valid for MSBuild.
88 """
89
90 def ConvertToMSBuild(self, value):
91 """Returns the MSBuild equivalent of the MSVS value given.
92
93 Args:
94 value: the MSVS value to convert.
95
96 Returns:
97 the MSBuild equivalent.
98
99 Raises:
100 ValueError if value is not valid.
101 """
102 return value
103
104
105 class _String(_Type):
106 """A setting that's just a string."""
107
108 def ValidateMSVS(self, value):
109 if not isinstance(value, basestring):
110 raise ValueError('expected string; got %r' % value)
111
112 def ValidateMSBuild(self, value):
113 if not isinstance(value, basestring):
114 raise ValueError('expected string; got %r' % value)
115
116 def ConvertToMSBuild(self, value):
117 # Convert the macros
118 return ConvertVCMacrosToMSBuild(value)
119
120
121 class _StringList(_Type):
122 """A settings that's a list of strings."""
123
124 def ValidateMSVS(self, value):
125 if not isinstance(value, basestring) and not isinstance(value, list):
126 raise ValueError('expected string list; got %r' % value)
127
128 def ValidateMSBuild(self, value):
129 if not isinstance(value, basestring) and not isinstance(value, list):
130 raise ValueError('expected string list; got %r' % value)
131
132 def ConvertToMSBuild(self, value):
133 # Convert the macros
134 if isinstance(value, list):
135 return [ConvertVCMacrosToMSBuild(i) for i in value]
136 else:
137 return ConvertVCMacrosToMSBuild(value)
138
139
140 class _Boolean(_Type):
141 """Boolean settings, can have the values 'false' or 'true'."""
142
143 def _Validate(self, value):
144 if value != 'true' and value != 'false':
145 raise ValueError('expected bool; got %r' % value)
146
147 def ValidateMSVS(self, value):
148 self._Validate(value)
149
150 def ValidateMSBuild(self, value):
151 self._Validate(value)
152
153 def ConvertToMSBuild(self, value):
154 self._Validate(value)
155 return value
156
157
158 class _Integer(_Type):
159 """Integer settings."""
160
161 def __init__(self, msbuild_base=10):
162 _Type.__init__(self)
163 self._msbuild_base = msbuild_base
164
165 def ValidateMSVS(self, value):
166 # Try to convert, this will raise ValueError if invalid.
167 self.ConvertToMSBuild(value)
168
169 def ValidateMSBuild(self, value):
170 # Try to convert, this will raise ValueError if invalid.
171 int(value, self._msbuild_base)
172
173 def ConvertToMSBuild(self, value):
174 msbuild_format = (self._msbuild_base == 10) and '%d' or '0x%04x'
175 return msbuild_format % int(value)
176
177
178 class _Enumeration(_Type):
179 """Type of settings that is an enumeration.
180
181 In MSVS, the values are indexes like '0', '1', and '2'.
182 MSBuild uses text labels that are more representative, like 'Win32'.
183
184 Constructor args:
185 label_list: an array of MSBuild labels that correspond to the MSVS index.
186 In the rare cases where MSVS has skipped an index value, None is
187 used in the array to indicate the unused spot.
188 new: an array of labels that are new to MSBuild.
189 """
190
191 def __init__(self, label_list, new=None):
192 _Type.__init__(self)
193 self._label_list = label_list
194 self._msbuild_values = set(value for value in label_list
195 if value is not None)
196 if new is not None:
197 self._msbuild_values.update(new)
198
199 def ValidateMSVS(self, value):
200 # Try to convert. It will raise an exception if not valid.
201 self.ConvertToMSBuild(value)
202
203 def ValidateMSBuild(self, value):
204 if value not in self._msbuild_values:
205 raise ValueError('unrecognized enumerated value %s' % value)
206
207 def ConvertToMSBuild(self, value):
208 index = int(value)
209 if index < 0 or index >= len(self._label_list):
210 raise ValueError('index value (%d) not in expected range [0, %d)' %
211 (index, len(self._label_list)))
212 label = self._label_list[index]
213 if label is None:
214 raise ValueError('converted value for %s not specified.' % value)
215 return label
216
217
218 # Instantiate the various generic types.
219 _boolean = _Boolean()
220 _integer = _Integer()
221 # For now, we don't do any special validation on these types:
222 _string = _String()
223 _file_name = _String()
224 _folder_name = _String()
225 _file_list = _StringList()
226 _folder_list = _StringList()
227 _string_list = _StringList()
228 # Some boolean settings went from numerical values to boolean. The
229 # mapping is 0: default, 1: false, 2: true.
230 _newly_boolean = _Enumeration(['', 'false', 'true'])
231
232
233 def _Same(tool, name, setting_type):
234 """Defines a setting that has the same name in MSVS and MSBuild.
235
236 Args:
237 tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
238 name: the name of the setting.
239 setting_type: the type of this setting.
240 """
241 _Renamed(tool, name, name, setting_type)
242
243
244 def _Renamed(tool, msvs_name, msbuild_name, setting_type):
245 """Defines a setting for which the name has changed.
246
247 Args:
248 tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
249 msvs_name: the name of the MSVS setting.
250 msbuild_name: the name of the MSBuild setting.
251 setting_type: the type of this setting.
252 """
253
254 def _Translate(value, msbuild_settings):
255 msbuild_tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
256 msbuild_tool_settings[msbuild_name] = setting_type.ConvertToMSBuild(value)
257
258 _msvs_validators[tool.msvs_name][msvs_name] = setting_type.ValidateMSVS
259 _msbuild_validators[tool.msbuild_name][msbuild_name] = (
260 setting_type.ValidateMSBuild)
261 _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate
262
263
264 def _Moved(tool, settings_name, msbuild_tool_name, setting_type):
265 _MovedAndRenamed(tool, settings_name, msbuild_tool_name, settings_name,
266 setting_type)
267
268
269 def _MovedAndRenamed(tool, msvs_settings_name, msbuild_tool_name,
270 msbuild_settings_name, setting_type):
271 """Defines a setting that may have moved to a new section.
272
273 Args:
274 tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
275 msvs_settings_name: the MSVS name of the setting.
276 msbuild_tool_name: the name of the MSBuild tool to place the setting under.
277 msbuild_settings_name: the MSBuild name of the setting.
278 setting_type: the type of this setting.
279 """
280
281 def _Translate(value, msbuild_settings):
282 tool_settings = msbuild_settings.setdefault(msbuild_tool_name, {})
283 tool_settings[msbuild_settings_name] = setting_type.ConvertToMSBuild(value)
284
285 _msvs_validators[tool.msvs_name][msvs_settings_name] = (
286 setting_type.ValidateMSVS)
287 validator = setting_type.ValidateMSBuild
288 _msbuild_validators[msbuild_tool_name][msbuild_settings_name] = validator
289 _msvs_to_msbuild_converters[tool.msvs_name][msvs_settings_name] = _Translate
290
291
292 def _MSVSOnly(tool, name, setting_type):
293 """Defines a setting that is only found in MSVS.
294
295 Args:
296 tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
297 name: the name of the setting.
298 setting_type: the type of this setting.
299 """
300
301 def _Translate(unused_value, unused_msbuild_settings):
302 # Since this is for MSVS only settings, no translation will happen.
303 pass
304
305 _msvs_validators[tool.msvs_name][name] = setting_type.ValidateMSVS
306 _msvs_to_msbuild_converters[tool.msvs_name][name] = _Translate
307
308
309 def _MSBuildOnly(tool, name, setting_type):
310 """Defines a setting that is only found in MSBuild.
311
312 Args:
313 tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
314 name: the name of the setting.
315 setting_type: the type of this setting.
316 """
317 _msbuild_validators[tool.msbuild_name][name] = setting_type.ValidateMSBuild
318
319
320 def _ConvertedToAdditionalOption(tool, msvs_name, flag):
321 """Defines a setting that's handled via a command line option in MSBuild.
322
323 Args:
324 tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
325 msvs_name: the name of the MSVS setting that if 'true' becomes a flag
326 flag: the flag to insert at the end of the AdditionalOptions
327 """
328
329 def _Translate(value, msbuild_settings):
330 if value == 'true':
331 tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
332 if 'AdditionalOptions' in tool_settings:
333 new_flags = '%s %s' % (tool_settings['AdditionalOptions'], flag)
334 else:
335 new_flags = flag
336 tool_settings['AdditionalOptions'] = new_flags
337 _msvs_validators[tool.msvs_name][msvs_name] = _boolean.ValidateMSVS
338 _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate
339
340
341 def _CustomGeneratePreprocessedFile(tool, msvs_name):
342 def _Translate(value, msbuild_settings):
343 tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
344 if value == '0':
345 tool_settings['PreprocessToFile'] = 'false'
346 tool_settings['PreprocessSuppressLineNumbers'] = 'false'
347 elif value == '1': # /P
348 tool_settings['PreprocessToFile'] = 'true'
349 tool_settings['PreprocessSuppressLineNumbers'] = 'false'
350 elif value == '2': # /EP /P
351 tool_settings['PreprocessToFile'] = 'true'
352 tool_settings['PreprocessSuppressLineNumbers'] = 'true'
353 else:
354 raise ValueError('value must be one of [0, 1, 2]; got %s' % value)
355 # Create a bogus validator that looks for '0', '1', or '2'
356 msvs_validator = _Enumeration(['a', 'b', 'c']).ValidateMSVS
357 _msvs_validators[tool.msvs_name][msvs_name] = msvs_validator
358 msbuild_validator = _boolean.ValidateMSBuild
359 msbuild_tool_validators = _msbuild_validators[tool.msbuild_name]
360 msbuild_tool_validators['PreprocessToFile'] = msbuild_validator
361 msbuild_tool_validators['PreprocessSuppressLineNumbers'] = msbuild_validator
362 _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate
363
364
365 def ConvertVCMacrosToMSBuild(s):
366 """Convert the the MSVS macros found in the string to the MSBuild equivalent.
367
368 This list is probably not exhaustive. Add as needed.
369 """
370 if '$' in s:
371 replace_map = {
372 '$(ConfigurationName)': '$(Configuration)',
373 '$(InputDir)': '%(RootDir)%(Directory)',
374 '$(InputExt)': '%(Extension)',
375 '$(InputFileName)': '%(Filename)%(Extension)',
376 '$(InputName)': '%(Filename)',
377 '$(InputPath)': '%(FullPath)',
378 '$(ParentName)': '$(ProjectFileName)',
379 '$(PlatformName)': '$(Platform)',
380 '$(SafeInputName)': '%(Filename)',
381
382 '$(IntDir)\\': '$(IntDir)',
383 '$(OutDir)\\': '$(OutDir)',
384 '$(IntDir)/': '$(IntDir)',
385 '$(OutDir)/': '$(OutDir)',
386 }
387 for old, new in replace_map.iteritems():
388 s = s.replace(old, new)
389 return s
390
391
392 def ConvertToMSBuildSettings(msvs_settings, stderr=sys.stderr):
393 """Converts MSVS settings (VS2008 and earlier) to MSBuild settings (VS2010+).
394
395 Args:
396 msvs_settings: A dictionary. The key is the tool name. The values are
397 themselves dictionaries of settings and their values.
398 stderr: The stream receiving the error messages.
399
400 Returns:
401 A dictionary of MSBuild settings. The key is either the MSBuild tool name
402 or the empty string (for the global settings). The values are themselves
403 dictionaries of settings and their values.
404 """
405 msbuild_settings = {}
406 for msvs_tool_name, msvs_tool_settings in msvs_settings.iteritems():
407 if msvs_tool_name in _msvs_to_msbuild_converters:
408 msvs_tool = _msvs_to_msbuild_converters[msvs_tool_name]
409 for msvs_setting, msvs_value in msvs_tool_settings.iteritems():
410 if msvs_setting in msvs_tool:
411 # Invoke the translation function.
412 try:
413 msvs_tool[msvs_setting](msvs_value, msbuild_settings)
414 except ValueError, e:
415 print >> stderr, ('Warning: while converting %s/%s to MSBuild, '
416 '%s' % (msvs_tool_name, msvs_setting, e))
417 else:
418 # We don't know this setting. Give a warning.
419 print >> stderr, ('Warning: unrecognized setting %s/%s '
420 'while converting to MSBuild.' %
421 (msvs_tool_name, msvs_setting))
422 else:
423 print >> stderr, ('Warning: unrecognized tool %s while converting to '
424 'MSBuild.' % msvs_tool_name)
425 return msbuild_settings
426
427
428 def ValidateMSVSSettings(settings, stderr=sys.stderr):
429 """Validates that the names of the settings are valid for MSVS.
430
431 Args:
432 settings: A dictionary. The key is the tool name. The values are
433 themselves dictionaries of settings and their values.
434 stderr: The stream receiving the error messages.
435 """
436 _ValidateSettings(_msvs_validators, settings, stderr)
437
438
439 def ValidateMSBuildSettings(settings, stderr=sys.stderr):
440 """Validates that the names of the settings are valid for MSBuild.
441
442 Args:
443 settings: A dictionary. The key is the tool name. The values are
444 themselves dictionaries of settings and their values.
445 stderr: The stream receiving the error messages.
446 """
447 _ValidateSettings(_msbuild_validators, settings, stderr)
448
449
450 def _ValidateSettings(validators, settings, stderr):
451 """Validates that the settings are valid for MSBuild or MSVS.
452
453 We currently only validate the names of the settings, not their values.
454
455 Args:
456 validators: A dictionary of tools and their validators.
457 settings: A dictionary. The key is the tool name. The values are
458 themselves dictionaries of settings and their values.
459 stderr: The stream receiving the error messages.
460 """
461 for tool_name in settings:
462 if tool_name in validators:
463 tool_validators = validators[tool_name]
464 for setting, value in settings[tool_name].iteritems():
465 if setting in tool_validators:
466 try:
467 tool_validators[setting](value)
468 except ValueError, e:
469 print >> stderr, ('Warning: for %s/%s, %s' %
470 (tool_name, setting, e))
471 else:
472 print >> stderr, ('Warning: unrecognized setting %s/%s' %
473 (tool_name, setting))
474 else:
475 print >> stderr, ('Warning: unrecognized tool %s' % tool_name)
476
477
478 # MSVS and MBuild names of the tools.
479 _compile = _Tool('VCCLCompilerTool', 'ClCompile')
480 _link = _Tool('VCLinkerTool', 'Link')
481 _midl = _Tool('VCMIDLTool', 'Midl')
482 _rc = _Tool('VCResourceCompilerTool', 'ResourceCompile')
483 _lib = _Tool('VCLibrarianTool', 'Lib')
484 _manifest = _Tool('VCManifestTool', 'Mt')
485
486
487 _AddTool(_compile)
488 _AddTool(_link)
489 _AddTool(_midl)
490 _AddTool(_rc)
491 _AddTool(_lib)
492 _AddTool(_manifest)
493 # Add sections only found in the MSBuild settings.
494 _msbuild_validators[''] = {}
495 _msbuild_validators['ProjectReference'] = {}
496 _msbuild_validators['ManifestResourceCompile'] = {}
497
498 # Descriptions of the compiler options, i.e. VCCLCompilerTool in MSVS and
499 # ClCompile in MSBuild.
500 # See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\cl.xml" for
501 # the schema of the MSBuild ClCompile settings.
502
503 # Options that have the same name in MSVS and MSBuild
504 _Same(_compile, 'AdditionalIncludeDirectories', _folder_list) # /I
505 _Same(_compile, 'AdditionalOptions', _string_list)
506 _Same(_compile, 'AdditionalUsingDirectories', _folder_list) # /AI
507 _Same(_compile, 'AssemblerListingLocation', _file_name) # /Fa
508 _Same(_compile, 'BrowseInformationFile', _file_name)
509 _Same(_compile, 'BufferSecurityCheck', _boolean) # /GS
510 _Same(_compile, 'DisableLanguageExtensions', _boolean) # /Za
511 _Same(_compile, 'DisableSpecificWarnings', _string_list) # /wd
512 _Same(_compile, 'EnableFiberSafeOptimizations', _boolean) # /GT
513 _Same(_compile, 'EnablePREfast', _boolean) # /analyze Visible='false'
514 _Same(_compile, 'ExpandAttributedSource', _boolean) # /Fx
515 _Same(_compile, 'FloatingPointExceptions', _boolean) # /fp:except
516 _Same(_compile, 'ForceConformanceInForLoopScope', _boolean) # /Zc:forScope
517 _Same(_compile, 'ForcedIncludeFiles', _file_list) # /FI
518 _Same(_compile, 'ForcedUsingFiles', _file_list) # /FU
519 _Same(_compile, 'GenerateXMLDocumentationFiles', _boolean) # /doc
520 _Same(_compile, 'IgnoreStandardIncludePath', _boolean) # /X
521 _Same(_compile, 'MinimalRebuild', _boolean) # /Gm
522 _Same(_compile, 'OmitDefaultLibName', _boolean) # /Zl
523 _Same(_compile, 'OmitFramePointers', _boolean) # /Oy
524 _Same(_compile, 'PreprocessorDefinitions', _string_list) # /D
525 _Same(_compile, 'ProgramDataBaseFileName', _file_name) # /Fd
526 _Same(_compile, 'RuntimeTypeInfo', _boolean) # /GR
527 _Same(_compile, 'ShowIncludes', _boolean) # /showIncludes
528 _Same(_compile, 'SmallerTypeCheck', _boolean) # /RTCc
529 _Same(_compile, 'StringPooling', _boolean) # /GF
530 _Same(_compile, 'SuppressStartupBanner', _boolean) # /nologo
531 _Same(_compile, 'TreatWChar_tAsBuiltInType', _boolean) # /Zc:wchar_t
532 _Same(_compile, 'UndefineAllPreprocessorDefinitions', _boolean) # /u
533 _Same(_compile, 'UndefinePreprocessorDefinitions', _string_list) # /U
534 _Same(_compile, 'UseFullPaths', _boolean) # /FC
535 _Same(_compile, 'WholeProgramOptimization', _boolean) # /GL
536 _Same(_compile, 'XMLDocumentationFileName', _file_name)
537
538 _Same(_compile, 'AssemblerOutput',
539 _Enumeration(['NoListing',
540 'AssemblyCode', # /FA
541 'All', # /FAcs
542 'AssemblyAndMachineCode', # /FAc
543 'AssemblyAndSourceCode'])) # /FAs
544 _Same(_compile, 'BasicRuntimeChecks',
545 _Enumeration(['Default',
546 'StackFrameRuntimeCheck', # /RTCs
547 'UninitializedLocalUsageCheck', # /RTCu
548 'EnableFastChecks'])) # /RTC1
549 _Same(_compile, 'BrowseInformation',
550 _Enumeration(['false',
551 'true', # /FR
552 'true'])) # /Fr
553 _Same(_compile, 'CallingConvention',
554 _Enumeration(['Cdecl', # /Gd
555 'FastCall', # /Gr
556 'StdCall'])) # /Gz
557 _Same(_compile, 'CompileAs',
558 _Enumeration(['Default',
559 'CompileAsC', # /TC
560 'CompileAsCpp'])) # /TP
561 _Same(_compile, 'DebugInformationFormat',
562 _Enumeration(['', # Disabled
563 'OldStyle', # /Z7
564 None,
565 'ProgramDatabase', # /Zi
566 'EditAndContinue'])) # /ZI
567 _Same(_compile, 'EnableEnhancedInstructionSet',
568 _Enumeration(['NotSet',
569 'StreamingSIMDExtensions', # /arch:SSE
570 'StreamingSIMDExtensions2'])) # /arch:SSE2
571 _Same(_compile, 'ErrorReporting',
572 _Enumeration(['None', # /errorReport:none
573 'Prompt', # /errorReport:prompt
574 'Queue'], # /errorReport:queue
575 new=['Send'])) # /errorReport:send"
576 _Same(_compile, 'ExceptionHandling',
577 _Enumeration(['false',
578 'Sync', # /EHsc
579 'Async'], # /EHa
580 new=['SyncCThrow'])) # /EHs
581 _Same(_compile, 'FavorSizeOrSpeed',
582 _Enumeration(['Neither',
583 'Speed', # /Ot
584 'Size'])) # /Os
585 _Same(_compile, 'FloatingPointModel',
586 _Enumeration(['Precise', # /fp:precise
587 'Strict', # /fp:strict
588 'Fast'])) # /fp:fast
589 _Same(_compile, 'InlineFunctionExpansion',
590 _Enumeration(['Default',
591 'OnlyExplicitInline', # /Ob1
592 'AnySuitable'], # /Ob2
593 new=['Disabled'])) # /Ob0
594 _Same(_compile, 'Optimization',
595 _Enumeration(['Disabled', # /Od
596 'MinSpace', # /O1
597 'MaxSpeed', # /O2
598 'Full'])) # /Ox
599 _Same(_compile, 'RuntimeLibrary',
600 _Enumeration(['MultiThreaded', # /MT
601 'MultiThreadedDebug', # /MTd
602 'MultiThreadedDLL', # /MD
603 'MultiThreadedDebugDLL'])) # /MDd
604 _Same(_compile, 'StructMemberAlignment',
605 _Enumeration(['Default',
606 '1Byte', # /Zp1
607 '2Bytes', # /Zp2
608 '4Bytes', # /Zp4
609 '8Bytes', # /Zp8
610 '16Bytes'])) # /Zp16
611 _Same(_compile, 'WarningLevel',
612 _Enumeration(['TurnOffAllWarnings', # /W0
613 'Level1', # /W1
614 'Level2', # /W2
615 'Level3', # /W3
616 'Level4'], # /W4
617 new=['EnableAllWarnings'])) # /Wall
618
619 # Options found in MSVS that have been renamed in MSBuild.
620 _Renamed(_compile, 'EnableFunctionLevelLinking', 'FunctionLevelLinking',
621 _boolean) # /Gy
622 _Renamed(_compile, 'EnableIntrinsicFunctions', 'IntrinsicFunctions',
623 _boolean) # /Oi
624 _Renamed(_compile, 'KeepComments', 'PreprocessKeepComments', _boolean) # /C
625 _Renamed(_compile, 'ObjectFile', 'ObjectFileName', _file_name) # /Fo
626 _Renamed(_compile, 'OpenMP', 'OpenMPSupport', _boolean) # /openmp
627 _Renamed(_compile, 'PrecompiledHeaderThrough', 'PrecompiledHeaderFile',
628 _file_name) # Used with /Yc and /Yu
629 _Renamed(_compile, 'PrecompiledHeaderFile', 'PrecompiledHeaderOutputFile',
630 _file_name) # /Fp
631 _Renamed(_compile, 'UsePrecompiledHeader', 'PrecompiledHeader',
632 _Enumeration(['NotUsing', # VS recognized '' for this value too.
633 'Create', # /Yc
634 'Use'])) # /Yu
635 _Renamed(_compile, 'WarnAsError', 'TreatWarningAsError', _boolean) # /WX
636
637 _ConvertedToAdditionalOption(_compile, 'DefaultCharIsUnsigned', '/J')
638
639 # MSVS options not found in MSBuild.
640 _MSVSOnly(_compile, 'Detect64BitPortabilityProblems', _boolean)
641 _MSVSOnly(_compile, 'UseUnicodeResponseFiles', _boolean)
642
643 # MSBuild options not found in MSVS.
644 _MSBuildOnly(_compile, 'BuildingInIDE', _boolean)
645 _MSBuildOnly(_compile, 'CompileAsManaged',
646 _Enumeration([], new=['false',
647 'true', # /clr
648 'Pure', # /clr:pure
649 'Safe', # /clr:safe
650 'OldSyntax'])) # /clr:oldSyntax
651 _MSBuildOnly(_compile, 'CreateHotpatchableImage', _boolean) # /hotpatch
652 _MSBuildOnly(_compile, 'MultiProcessorCompilation', _boolean) # /MP
653 _MSBuildOnly(_compile, 'PreprocessOutputPath', _string) # /Fi
654 _MSBuildOnly(_compile, 'ProcessorNumber', _integer) # the number of processors
655 _MSBuildOnly(_compile, 'TrackerLogDirectory', _folder_name)
656 _MSBuildOnly(_compile, 'TreatSpecificWarningsAsErrors', _string_list) # /we
657 _MSBuildOnly(_compile, 'UseUnicodeForAssemblerListing', _boolean) # /FAu
658
659 # Defines a setting that needs very customized processing
660 _CustomGeneratePreprocessedFile(_compile, 'GeneratePreprocessedFile')
661
662
663 # Directives for converting MSVS VCLinkerTool to MSBuild Link.
664 # See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\link.xml" for
665 # the schema of the MSBuild Link settings.
666
667 # Options that have the same name in MSVS and MSBuild
668 _Same(_link, 'AdditionalDependencies', _file_list)
669 _Same(_link, 'AdditionalLibraryDirectories', _folder_list) # /LIBPATH
670 # /MANIFESTDEPENDENCY:
671 _Same(_link, 'AdditionalManifestDependencies', _file_list)
672 _Same(_link, 'AdditionalOptions', _string_list)
673 _Same(_link, 'AddModuleNamesToAssembly', _file_list) # /ASSEMBLYMODULE
674 _Same(_link, 'AllowIsolation', _boolean) # /ALLOWISOLATION
675 _Same(_link, 'AssemblyLinkResource', _file_list) # /ASSEMBLYLINKRESOURCE
676 _Same(_link, 'BaseAddress', _string) # /BASE
677 _Same(_link, 'CLRUnmanagedCodeCheck', _boolean) # /CLRUNMANAGEDCODECHECK
678 _Same(_link, 'DelayLoadDLLs', _file_list) # /DELAYLOAD
679 _Same(_link, 'DelaySign', _boolean) # /DELAYSIGN
680 _Same(_link, 'EmbedManagedResourceFile', _file_list) # /ASSEMBLYRESOURCE
681 _Same(_link, 'EnableUAC', _boolean) # /MANIFESTUAC
682 _Same(_link, 'EntryPointSymbol', _string) # /ENTRY
683 _Same(_link, 'ForceSymbolReferences', _file_list) # /INCLUDE
684 _Same(_link, 'FunctionOrder', _file_name) # /ORDER
685 _Same(_link, 'GenerateDebugInformation', _boolean) # /DEBUG
686 _Same(_link, 'GenerateMapFile', _boolean) # /MAP
687 _Same(_link, 'HeapCommitSize', _string)
688 _Same(_link, 'HeapReserveSize', _string) # /HEAP
689 _Same(_link, 'IgnoreAllDefaultLibraries', _boolean) # /NODEFAULTLIB
690 _Same(_link, 'IgnoreEmbeddedIDL', _boolean) # /IGNOREIDL
691 _Same(_link, 'ImportLibrary', _file_name) # /IMPLIB
692 _Same(_link, 'KeyContainer', _file_name) # /KEYCONTAINER
693 _Same(_link, 'KeyFile', _file_name) # /KEYFILE
694 _Same(_link, 'ManifestFile', _file_name) # /ManifestFile
695 _Same(_link, 'MapExports', _boolean) # /MAPINFO:EXPORTS
696 _Same(_link, 'MapFileName', _file_name)
697 _Same(_link, 'MergedIDLBaseFileName', _file_name) # /IDLOUT
698 _Same(_link, 'MergeSections', _string) # /MERGE
699 _Same(_link, 'MidlCommandFile', _file_name) # /MIDL
700 _Same(_link, 'ModuleDefinitionFile', _file_name) # /DEF
701 _Same(_link, 'OutputFile', _file_name) # /OUT
702 _Same(_link, 'PerUserRedirection', _boolean)
703 _Same(_link, 'Profile', _boolean) # /PROFILE
704 _Same(_link, 'ProfileGuidedDatabase', _file_name) # /PGD
705 _Same(_link, 'ProgramDatabaseFile', _file_name) # /PDB
706 _Same(_link, 'RegisterOutput', _boolean)
707 _Same(_link, 'SetChecksum', _boolean) # /RELEASE
708 _Same(_link, 'StackCommitSize', _string)
709 _Same(_link, 'StackReserveSize', _string) # /STACK
710 _Same(_link, 'StripPrivateSymbols', _file_name) # /PDBSTRIPPED
711 _Same(_link, 'SupportUnloadOfDelayLoadedDLL', _boolean) # /DELAY:UNLOAD
712 _Same(_link, 'SuppressStartupBanner', _boolean) # /NOLOGO
713 _Same(_link, 'SwapRunFromCD', _boolean) # /SWAPRUN:CD
714 _Same(_link, 'TurnOffAssemblyGeneration', _boolean) # /NOASSEMBLY
715 _Same(_link, 'TypeLibraryFile', _file_name) # /TLBOUT
716 _Same(_link, 'TypeLibraryResourceID', _integer) # /TLBID
717 _Same(_link, 'UACUIAccess', _boolean) # /uiAccess='true'
718 _Same(_link, 'Version', _string) # /VERSION
719
720 _Same(_link, 'EnableCOMDATFolding', _newly_boolean) # /OPT:ICF
721 _Same(_link, 'FixedBaseAddress', _newly_boolean) # /FIXED
722 _Same(_link, 'LargeAddressAware', _newly_boolean) # /LARGEADDRESSAWARE
723 _Same(_link, 'OptimizeReferences', _newly_boolean) # /OPT:REF
724 _Same(_link, 'RandomizedBaseAddress', _newly_boolean) # /DYNAMICBASE
725 _Same(_link, 'TerminalServerAware', _newly_boolean) # /TSAWARE
726
727 _subsystem_enumeration = _Enumeration(
728 ['NotSet',
729 'Console', # /SUBSYSTEM:CONSOLE
730 'Windows', # /SUBSYSTEM:WINDOWS
731 'Native', # /SUBSYSTEM:NATIVE
732 'EFI Application', # /SUBSYSTEM:EFI_APPLICATION
733 'EFI Boot Service Driver', # /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER
734 'EFI ROM', # /SUBSYSTEM:EFI_ROM
735 'EFI Runtime', # /SUBSYSTEM:EFI_RUNTIME_DRIVER
736 'WindowsCE'], # /SUBSYSTEM:WINDOWSCE
737 new=['POSIX']) # /SUBSYSTEM:POSIX
738
739 _target_machine_enumeration = _Enumeration(
740 ['NotSet',
741 'MachineX86', # /MACHINE:X86
742 None,
743 'MachineARM', # /MACHINE:ARM
744 'MachineEBC', # /MACHINE:EBC
745 'MachineIA64', # /MACHINE:IA64
746 None,
747 'MachineMIPS', # /MACHINE:MIPS
748 'MachineMIPS16', # /MACHINE:MIPS16
749 'MachineMIPSFPU', # /MACHINE:MIPSFPU
750 'MachineMIPSFPU16', # /MACHINE:MIPSFPU16
751 None,
752 None,
753 None,
754 'MachineSH4', # /MACHINE:SH4
755 None,
756 'MachineTHUMB', # /MACHINE:THUMB
757 'MachineX64']) # /MACHINE:X64
758
759 _Same(_link, 'AssemblyDebug',
760 _Enumeration(['',
761 'true', # /ASSEMBLYDEBUG
762 'false'])) # /ASSEMBLYDEBUG:DISABLE
763 _Same(_link, 'CLRImageType',
764 _Enumeration(['Default',
765 'ForceIJWImage', # /CLRIMAGETYPE:IJW
766 'ForcePureILImage', # /Switch="CLRIMAGETYPE:PURE
767 'ForceSafeILImage'])) # /Switch="CLRIMAGETYPE:SAFE
768 _Same(_link, 'CLRThreadAttribute',
769 _Enumeration(['DefaultThreadingAttribute', # /CLRTHREADATTRIBUTE:NONE
770 'MTAThreadingAttribute', # /CLRTHREADATTRIBUTE:MTA
771 'STAThreadingAttribute'])) # /CLRTHREADATTRIBUTE:STA
772 _Same(_link, 'DataExecutionPrevention',
773 _Enumeration(['',
774 'false', # /NXCOMPAT:NO
775 'true'])) # /NXCOMPAT
776 _Same(_link, 'Driver',
777 _Enumeration(['NotSet',
778 'Driver', # /Driver
779 'UpOnly', # /DRIVER:UPONLY
780 'WDM'])) # /DRIVER:WDM
781 _Same(_link, 'LinkTimeCodeGeneration',
782 _Enumeration(['Default',
783 'UseLinkTimeCodeGeneration', # /LTCG
784 'PGInstrument', # /LTCG:PGInstrument
785 'PGOptimization', # /LTCG:PGOptimize
786 'PGUpdate'])) # /LTCG:PGUpdate
787 _Same(_link, 'ShowProgress',
788 _Enumeration(['NotSet',
789 'LinkVerbose', # /VERBOSE
790 'LinkVerboseLib'], # /VERBOSE:Lib
791 new=['LinkVerboseICF', # /VERBOSE:ICF
792 'LinkVerboseREF', # /VERBOSE:REF
793 'LinkVerboseSAFESEH', # /VERBOSE:SAFESEH
794 'LinkVerboseCLR'])) # /VERBOSE:CLR
795 _Same(_link, 'SubSystem', _subsystem_enumeration)
796 _Same(_link, 'TargetMachine', _target_machine_enumeration)
797 _Same(_link, 'UACExecutionLevel',
798 _Enumeration(['AsInvoker', # /level='asInvoker'
799 'HighestAvailable', # /level='highestAvailable'
800 'RequireAdministrator'])) # /level='requireAdministrator'
801
802
803 # Options found in MSVS that have been renamed in MSBuild.
804 _Renamed(_link, 'ErrorReporting', 'LinkErrorReporting',
805 _Enumeration(['NoErrorReport', # /ERRORREPORT:NONE
806 'PromptImmediately', # /ERRORREPORT:PROMPT
807 'QueueForNextLogin'], # /ERRORREPORT:QUEUE
808 new=['SendErrorReport'])) # /ERRORREPORT:SEND
809 _Renamed(_link, 'IgnoreDefaultLibraryNames', 'IgnoreSpecificDefaultLibraries',
810 _file_list) # /NODEFAULTLIB
811 _Renamed(_link, 'ResourceOnlyDLL', 'NoEntryPoint', _boolean) # /NOENTRY
812 _Renamed(_link, 'SwapRunFromNet', 'SwapRunFromNET', _boolean) # /SWAPRUN:NET
813
814 _Moved(_link, 'GenerateManifest', '', _boolean)
815 _Moved(_link, 'IgnoreImportLibrary', '', _boolean)
816 _Moved(_link, 'LinkIncremental', '', _newly_boolean)
817 _Moved(_link, 'LinkLibraryDependencies', 'ProjectReference', _boolean)
818 _Moved(_link, 'UseLibraryDependencyInputs', 'ProjectReference', _boolean)
819
820 # MSVS options not found in MSBuild.
821 _MSVSOnly(_link, 'OptimizeForWindows98', _newly_boolean)
822 _MSVSOnly(_link, 'UseUnicodeResponseFiles', _boolean)
823 # TODO(jeanluc) I don't think these are genuine settings but byproducts of Gyp.
824 _MSVSOnly(_link, 'AdditionalLibraryDirectories_excluded', _folder_list)
825
826 # MSBuild options not found in MSVS.
827 _MSBuildOnly(_link, 'BuildingInIDE', _boolean)
828 _MSBuildOnly(_link, 'ImageHasSafeExceptionHandlers', _boolean) # /SAFESEH
829 _MSBuildOnly(_link, 'LinkDLL', _boolean) # /DLL Visible='false'
830 _MSBuildOnly(_link, 'LinkStatus', _boolean) # /LTCG:STATUS
831 _MSBuildOnly(_link, 'PreventDllBinding', _boolean) # /ALLOWBIND
832 _MSBuildOnly(_link, 'SupportNobindOfDelayLoadedDLL', _boolean) # /DELAY:NOBIND
833 _MSBuildOnly(_link, 'TrackerLogDirectory', _folder_name)
834 _MSBuildOnly(_link, 'TreatLinkerWarningAsErrors', _boolean) # /WX
835 _MSBuildOnly(_link, 'MinimumRequiredVersion', _string)
836 _MSBuildOnly(_link, 'MSDOSStubFileName', _file_name) # /STUB Visible='false'
837 _MSBuildOnly(_link, 'SectionAlignment', _integer) # /ALIGN
838 _MSBuildOnly(_link, 'SpecifySectionAttributes', _string) # /SECTION
839 _MSBuildOnly(_link, 'ForceFileOutput',
840 _Enumeration([], new=['Enabled', # /FORCE
841 # /FORCE:MULTIPLE
842 'MultiplyDefinedSymbolOnly',
843 'UndefinedSymbolOnly'])) # /FORCE:UNRESOLVED
844 _MSBuildOnly(_link, 'CreateHotPatchableImage',
845 _Enumeration([], new=['Enabled', # /FUNCTIONPADMIN
846 'X86Image', # /FUNCTIONPADMIN:5
847 'X64Image', # /FUNCTIONPADMIN:6
848 'ItaniumImage'])) # /FUNCTIONPADMIN:16
849 _MSBuildOnly(_link, 'CLRSupportLastError',
850 _Enumeration([], new=['Enabled', # /CLRSupportLastError
851 'Disabled', # /CLRSupportLastError:NO
852 # /CLRSupportLastError:SYSTEMDLL
853 'SystemDlls']))
854
855
856 # Directives for converting VCResourceCompilerTool to ResourceCompile.
857 # See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\rc.xml" for
858 # the schema of the MSBuild ResourceCompile settings.
859
860 _Same(_rc, 'AdditionalOptions', _string_list)
861 _Same(_rc, 'AdditionalIncludeDirectories', _folder_list) # /I
862 _Same(_rc, 'Culture', _Integer(msbuild_base=16))
863 _Same(_rc, 'IgnoreStandardIncludePath', _boolean) # /X
864 _Same(_rc, 'PreprocessorDefinitions', _string_list) # /D
865 _Same(_rc, 'ResourceOutputFileName', _string) # /fo
866 _Same(_rc, 'ShowProgress', _boolean) # /v
867 # There is no UI in VisualStudio 2008 to set the following properties.
868 # However they are found in CL and other tools. Include them here for
869 # completeness, as they are very likely to have the same usage pattern.
870 _Same(_rc, 'SuppressStartupBanner', _boolean) # /nologo
871 _Same(_rc, 'UndefinePreprocessorDefinitions', _string_list) # /u
872
873 # MSBuild options not found in MSVS.
874 _MSBuildOnly(_rc, 'NullTerminateStrings', _boolean) # /n
875 _MSBuildOnly(_rc, 'TrackerLogDirectory', _folder_name)
876
877
878 # Directives for converting VCMIDLTool to Midl.
879 # See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\midl.xml" for
880 # the schema of the MSBuild Midl settings.
881
882 _Same(_midl, 'AdditionalIncludeDirectories', _folder_list) # /I
883 _Same(_midl, 'AdditionalOptions', _string_list)
884 _Same(_midl, 'CPreprocessOptions', _string) # /cpp_opt
885 _Same(_midl, 'ErrorCheckAllocations', _boolean) # /error allocation
886 _Same(_midl, 'ErrorCheckBounds', _boolean) # /error bounds_check
887 _Same(_midl, 'ErrorCheckEnumRange', _boolean) # /error enum
888 _Same(_midl, 'ErrorCheckRefPointers', _boolean) # /error ref
889 _Same(_midl, 'ErrorCheckStubData', _boolean) # /error stub_data
890 _Same(_midl, 'GenerateStublessProxies', _boolean) # /Oicf
891 _Same(_midl, 'GenerateTypeLibrary', _boolean)
892 _Same(_midl, 'HeaderFileName', _file_name) # /h
893 _Same(_midl, 'IgnoreStandardIncludePath', _boolean) # /no_def_idir
894 _Same(_midl, 'InterfaceIdentifierFileName', _file_name) # /iid
895 _Same(_midl, 'MkTypLibCompatible', _boolean) # /mktyplib203
896 _Same(_midl, 'OutputDirectory', _string) # /out
897 _Same(_midl, 'PreprocessorDefinitions', _string_list) # /D
898 _Same(_midl, 'ProxyFileName', _file_name) # /proxy
899 _Same(_midl, 'RedirectOutputAndErrors', _file_name) # /o
900 _Same(_midl, 'SuppressStartupBanner', _boolean) # /nologo
901 _Same(_midl, 'TypeLibraryName', _file_name) # /tlb
902 _Same(_midl, 'UndefinePreprocessorDefinitions', _string_list) # /U
903 _Same(_midl, 'WarnAsError', _boolean) # /WX
904
905 _Same(_midl, 'DefaultCharType',
906 _Enumeration(['Unsigned', # /char unsigned
907 'Signed', # /char signed
908 'Ascii'])) # /char ascii7
909 _Same(_midl, 'TargetEnvironment',
910 _Enumeration(['NotSet',
911 'Win32', # /env win32
912 'Itanium', # /env ia64
913 'X64'])) # /env x64
914 _Same(_midl, 'EnableErrorChecks',
915 _Enumeration(['EnableCustom',
916 'None', # /error none
917 'All'])) # /error all
918 _Same(_midl, 'StructMemberAlignment',
919 _Enumeration(['NotSet',
920 '1', # Zp1
921 '2', # Zp2
922 '4', # Zp4
923 '8'])) # Zp8
924 _Same(_midl, 'WarningLevel',
925 _Enumeration(['0', # /W0
926 '1', # /W1
927 '2', # /W2
928 '3', # /W3
929 '4'])) # /W4
930
931 _Renamed(_midl, 'DLLDataFileName', 'DllDataFileName', _file_name) # /dlldata
932 _Renamed(_midl, 'ValidateParameters', 'ValidateAllParameters',
933 _boolean) # /robust
934
935 # MSBuild options not found in MSVS.
936 _MSBuildOnly(_midl, 'ApplicationConfigurationMode', _boolean) # /app_config
937 _MSBuildOnly(_midl, 'ClientStubFile', _file_name) # /cstub
938 _MSBuildOnly(_midl, 'GenerateClientFiles',
939 _Enumeration([], new=['Stub', # /client stub
940 'None'])) # /client none
941 _MSBuildOnly(_midl, 'GenerateServerFiles',
942 _Enumeration([], new=['Stub', # /client stub
943 'None'])) # /client none
944 _MSBuildOnly(_midl, 'LocaleID', _integer) # /lcid DECIMAL
945 _MSBuildOnly(_midl, 'ServerStubFile', _file_name) # /sstub
946 _MSBuildOnly(_midl, 'SuppressCompilerWarnings', _boolean) # /no_warn
947 _MSBuildOnly(_midl, 'TrackerLogDirectory', _folder_name)
948 _MSBuildOnly(_midl, 'TypeLibFormat',
949 _Enumeration([], new=['NewFormat', # /newtlb
950 'OldFormat'])) # /oldtlb
951
952
953 # Directives for converting VCLibrarianTool to Lib.
954 # See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\lib.xml" for
955 # the schema of the MSBuild Lib settings.
956
957 _Same(_lib, 'AdditionalDependencies', _file_list)
958 _Same(_lib, 'AdditionalLibraryDirectories', _folder_list) # /LIBPATH
959 _Same(_lib, 'AdditionalOptions', _string_list)
960 _Same(_lib, 'ExportNamedFunctions', _string_list) # /EXPORT
961 _Same(_lib, 'ForceSymbolReferences', _string) # /INCLUDE
962 _Same(_lib, 'IgnoreAllDefaultLibraries', _boolean) # /NODEFAULTLIB
963 _Same(_lib, 'IgnoreSpecificDefaultLibraries', _file_list) # /NODEFAULTLIB
964 _Same(_lib, 'ModuleDefinitionFile', _file_name) # /DEF
965 _Same(_lib, 'OutputFile', _file_name) # /OUT
966 _Same(_lib, 'SuppressStartupBanner', _boolean) # /NOLOGO
967 _Same(_lib, 'UseUnicodeResponseFiles', _boolean)
968
969 # TODO(jeanluc) _link defines the same value that gets moved to
970 # ProjectReference. We may want to validate that they are consistent.
971 _Moved(_lib, 'LinkLibraryDependencies', 'ProjectReference', _boolean)
972
973 # TODO(jeanluc) I don't think these are genuine settings but byproducts of Gyp.
974 _MSVSOnly(_lib, 'AdditionalLibraryDirectories_excluded', _folder_list)
975
976 _MSBuildOnly(_lib, 'DisplayLibrary', _string) # /LIST Visible='false'
977 _MSBuildOnly(_lib, 'ErrorReporting',
978 _Enumeration([], new=['PromptImmediately', # /ERRORREPORT:PROMPT
979 'QueueForNextLogin', # /ERRORREPORT:QUEUE
980 'SendErrorReport', # /ERRORREPORT:SEND
981 'NoErrorReport'])) # /ERRORREPORT:NONE
982 _MSBuildOnly(_lib, 'LinkTimeCodeGeneration', _boolean) # /LTCG
983 _MSBuildOnly(_lib, 'MinimumRequiredVersion', _string)
984 _MSBuildOnly(_lib, 'Name', _file_name) # /NAME
985 _MSBuildOnly(_lib, 'RemoveObjects', _file_list) # /REMOVE
986 _MSBuildOnly(_lib, 'SubSystem', _subsystem_enumeration)
987 _MSBuildOnly(_lib, 'TargetMachine', _target_machine_enumeration)
988 _MSBuildOnly(_lib, 'TrackerLogDirectory', _folder_name)
989 _MSBuildOnly(_lib, 'TreatLibWarningAsErrors', _boolean) # /WX
990 _MSBuildOnly(_lib, 'Verbose', _boolean)
991
992
993 # Directives for converting VCManifestTool to Mt.
994 # See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\mt.xml" for
995 # the schema of the MSBuild Lib settings.
996
997 # Options that have the same name in MSVS and MSBuild
998 _Same(_manifest, 'AdditionalManifestFiles', _file_list) # /manifest
999 _Same(_manifest, 'AdditionalOptions', _string_list)
1000 _Same(_manifest, 'AssemblyIdentity', _string) # /identity:
1001 _Same(_manifest, 'ComponentFileName', _file_name) # /dll
1002 _Same(_manifest, 'GenerateCatalogFiles', _boolean) # /makecdfs
1003 _Same(_manifest, 'InputResourceManifests', _string) # /inputresource
1004 _Same(_manifest, 'OutputManifestFile', _file_name) # /out
1005 _Same(_manifest, 'RegistrarScriptFile', _file_name) # /rgs
1006 _Same(_manifest, 'ReplacementsFile', _file_name) # /replacements
1007 _Same(_manifest, 'SuppressStartupBanner', _boolean) # /nologo
1008 _Same(_manifest, 'TypeLibraryFile', _file_name) # /tlb:
1009 _Same(_manifest, 'UpdateFileHashes', _boolean) # /hashupdate
1010 _Same(_manifest, 'UpdateFileHashesSearchPath', _file_name)
1011 _Same(_manifest, 'VerboseOutput', _boolean) # /verbose
1012
1013 # Options that have moved location.
1014 _MovedAndRenamed(_manifest, 'ManifestResourceFile',
1015 'ManifestResourceCompile',
1016 'ResourceOutputFileName',
1017 _file_name)
1018 _Moved(_manifest, 'EmbedManifest', '', _boolean)
1019
1020 # MSVS options not found in MSBuild.
1021 _MSVSOnly(_manifest, 'DependencyInformationFile', _file_name)
1022 _MSVSOnly(_manifest, 'UseFAT32Workaround', _boolean)
1023 _MSVSOnly(_manifest, 'UseUnicodeResponseFiles', _boolean)
1024
1025 # MSBuild options not found in MSVS.
1026 _MSBuildOnly(_manifest, 'EnableDPIAwareness', _boolean)
1027 _MSBuildOnly(_manifest, 'GenerateCategoryTags', _boolean) # /category
1028 _MSBuildOnly(_manifest, 'ManifestFromManagedAssembly',
1029 _file_name) # /managedassemblyname
1030 _MSBuildOnly(_manifest, 'OutputResourceManifests', _string) # /outputresource
1031 _MSBuildOnly(_manifest, 'SuppressDependencyElement', _boolean) # /nodependency
1032 _MSBuildOnly(_manifest, 'TrackerLogDirectory', _folder_name)
+0
-1480
third_party/gyp/pylib/gyp/MSVSSettings_test.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Unit tests for the MSVSSettings.py file."""
7
8 import StringIO
9 import unittest
10 import gyp.MSVSSettings as MSVSSettings
11
12
13 class TestSequenceFunctions(unittest.TestCase):
14
15 def setUp(self):
16 self.stderr = StringIO.StringIO()
17
18 def _ExpectedWarnings(self, expected):
19 """Compares recorded lines to expected warnings."""
20 self.stderr.seek(0)
21 actual = self.stderr.read().split('\n')
22 actual = [line for line in actual if line]
23 self.assertEqual(sorted(expected), sorted(actual))
24
25 def testValidateMSVSSettings_tool_names(self):
26 """Tests that only MSVS tool names are allowed."""
27 MSVSSettings.ValidateMSVSSettings(
28 {'VCCLCompilerTool': {},
29 'VCLinkerTool': {},
30 'VCMIDLTool': {},
31 'foo': {},
32 'VCResourceCompilerTool': {},
33 'VCLibrarianTool': {},
34 'VCManifestTool': {},
35 'ClCompile': {}},
36 self.stderr)
37 self._ExpectedWarnings([
38 'Warning: unrecognized tool foo',
39 'Warning: unrecognized tool ClCompile'])
40
41 def testValidateMSVSSettings_settings(self):
42 """Tests that for invalid MSVS settings."""
43 MSVSSettings.ValidateMSVSSettings(
44 {'VCCLCompilerTool': {
45 'AdditionalIncludeDirectories': 'folder1;folder2',
46 'AdditionalOptions': ['string1', 'string2'],
47 'AdditionalUsingDirectories': 'folder1;folder2',
48 'AssemblerListingLocation': 'a_file_name',
49 'AssemblerOutput': '0',
50 'BasicRuntimeChecks': '5',
51 'BrowseInformation': 'fdkslj',
52 'BrowseInformationFile': 'a_file_name',
53 'BufferSecurityCheck': 'true',
54 'CallingConvention': '-1',
55 'CompileAs': '1',
56 'DebugInformationFormat': '2',
57 'DefaultCharIsUnsigned': 'true',
58 'Detect64BitPortabilityProblems': 'true',
59 'DisableLanguageExtensions': 'true',
60 'DisableSpecificWarnings': 'string1;string2',
61 'EnableEnhancedInstructionSet': '1',
62 'EnableFiberSafeOptimizations': 'true',
63 'EnableFunctionLevelLinking': 'true',
64 'EnableIntrinsicFunctions': 'true',
65 'EnablePREfast': 'true',
66 'Enableprefast': 'bogus',
67 'ErrorReporting': '1',
68 'ExceptionHandling': '1',
69 'ExpandAttributedSource': 'true',
70 'FavorSizeOrSpeed': '1',
71 'FloatingPointExceptions': 'true',
72 'FloatingPointModel': '1',
73 'ForceConformanceInForLoopScope': 'true',
74 'ForcedIncludeFiles': 'file1;file2',
75 'ForcedUsingFiles': 'file1;file2',
76 'GeneratePreprocessedFile': '1',
77 'GenerateXMLDocumentationFiles': 'true',
78 'IgnoreStandardIncludePath': 'true',
79 'InlineFunctionExpansion': '1',
80 'KeepComments': 'true',
81 'MinimalRebuild': 'true',
82 'ObjectFile': 'a_file_name',
83 'OmitDefaultLibName': 'true',
84 'OmitFramePointers': 'true',
85 'OpenMP': 'true',
86 'Optimization': '1',
87 'PrecompiledHeaderFile': 'a_file_name',
88 'PrecompiledHeaderThrough': 'a_file_name',
89 'PreprocessorDefinitions': 'string1;string2',
90 'ProgramDataBaseFileName': 'a_file_name',
91 'RuntimeLibrary': '1',
92 'RuntimeTypeInfo': 'true',
93 'ShowIncludes': 'true',
94 'SmallerTypeCheck': 'true',
95 'StringPooling': 'true',
96 'StructMemberAlignment': '1',
97 'SuppressStartupBanner': 'true',
98 'TreatWChar_tAsBuiltInType': 'true',
99 'UndefineAllPreprocessorDefinitions': 'true',
100 'UndefinePreprocessorDefinitions': 'string1;string2',
101 'UseFullPaths': 'true',
102 'UsePrecompiledHeader': '1',
103 'UseUnicodeResponseFiles': 'true',
104 'WarnAsError': 'true',
105 'WarningLevel': '1',
106 'WholeProgramOptimization': 'true',
107 'XMLDocumentationFileName': 'a_file_name',
108 'ZZXYZ': 'bogus'},
109 'VCLinkerTool': {
110 'AdditionalDependencies': 'file1;file2',
111 'AdditionalLibraryDirectories': 'folder1;folder2',
112 'AdditionalManifestDependencies': 'file1;file2',
113 'AdditionalOptions': 'a string1',
114 'AddModuleNamesToAssembly': 'file1;file2',
115 'AllowIsolation': 'true',
116 'AssemblyDebug': '2',
117 'AssemblyLinkResource': 'file1;file2',
118 'BaseAddress': 'a string1',
119 'CLRImageType': '2',
120 'CLRThreadAttribute': '2',
121 'CLRUnmanagedCodeCheck': 'true',
122 'DataExecutionPrevention': '2',
123 'DelayLoadDLLs': 'file1;file2',
124 'DelaySign': 'true',
125 'Driver': '2',
126 'EmbedManagedResourceFile': 'file1;file2',
127 'EnableCOMDATFolding': '2',
128 'EnableUAC': 'true',
129 'EntryPointSymbol': 'a string1',
130 'ErrorReporting': '2',
131 'FixedBaseAddress': '2',
132 'ForceSymbolReferences': 'file1;file2',
133 'FunctionOrder': 'a_file_name',
134 'GenerateDebugInformation': 'true',
135 'GenerateManifest': 'true',
136 'GenerateMapFile': 'true',
137 'HeapCommitSize': 'a string1',
138 'HeapReserveSize': 'a string1',
139 'IgnoreAllDefaultLibraries': 'true',
140 'IgnoreDefaultLibraryNames': 'file1;file2',
141 'IgnoreEmbeddedIDL': 'true',
142 'IgnoreImportLibrary': 'true',
143 'ImportLibrary': 'a_file_name',
144 'KeyContainer': 'a_file_name',
145 'KeyFile': 'a_file_name',
146 'LargeAddressAware': '2',
147 'LinkIncremental': '2',
148 'LinkLibraryDependencies': 'true',
149 'LinkTimeCodeGeneration': '2',
150 'ManifestFile': 'a_file_name',
151 'MapExports': 'true',
152 'MapFileName': 'a_file_name',
153 'MergedIDLBaseFileName': 'a_file_name',
154 'MergeSections': 'a string1',
155 'MidlCommandFile': 'a_file_name',
156 'ModuleDefinitionFile': 'a_file_name',
157 'OptimizeForWindows98': '1',
158 'OptimizeReferences': '2',
159 'OutputFile': 'a_file_name',
160 'PerUserRedirection': 'true',
161 'Profile': 'true',
162 'ProfileGuidedDatabase': 'a_file_name',
163 'ProgramDatabaseFile': 'a_file_name',
164 'RandomizedBaseAddress': '2',
165 'RegisterOutput': 'true',
166 'ResourceOnlyDLL': 'true',
167 'SetChecksum': 'true',
168 'ShowProgress': '2',
169 'StackCommitSize': 'a string1',
170 'StackReserveSize': 'a string1',
171 'StripPrivateSymbols': 'a_file_name',
172 'SubSystem': '2',
173 'SupportUnloadOfDelayLoadedDLL': 'true',
174 'SuppressStartupBanner': 'true',
175 'SwapRunFromCD': 'true',
176 'SwapRunFromNet': 'true',
177 'TargetMachine': '2',
178 'TerminalServerAware': '2',
179 'TurnOffAssemblyGeneration': 'true',
180 'TypeLibraryFile': 'a_file_name',
181 'TypeLibraryResourceID': '33',
182 'UACExecutionLevel': '2',
183 'UACUIAccess': 'true',
184 'UseLibraryDependencyInputs': 'true',
185 'UseUnicodeResponseFiles': 'true',
186 'Version': 'a string1'},
187 'VCMIDLTool': {
188 'AdditionalIncludeDirectories': 'folder1;folder2',
189 'AdditionalOptions': 'a string1',
190 'CPreprocessOptions': 'a string1',
191 'DefaultCharType': '1',
192 'DLLDataFileName': 'a_file_name',
193 'EnableErrorChecks': '1',
194 'ErrorCheckAllocations': 'true',
195 'ErrorCheckBounds': 'true',
196 'ErrorCheckEnumRange': 'true',
197 'ErrorCheckRefPointers': 'true',
198 'ErrorCheckStubData': 'true',
199 'GenerateStublessProxies': 'true',
200 'GenerateTypeLibrary': 'true',
201 'HeaderFileName': 'a_file_name',
202 'IgnoreStandardIncludePath': 'true',
203 'InterfaceIdentifierFileName': 'a_file_name',
204 'MkTypLibCompatible': 'true',
205 'notgood': 'bogus',
206 'OutputDirectory': 'a string1',
207 'PreprocessorDefinitions': 'string1;string2',
208 'ProxyFileName': 'a_file_name',
209 'RedirectOutputAndErrors': 'a_file_name',
210 'StructMemberAlignment': '1',
211 'SuppressStartupBanner': 'true',
212 'TargetEnvironment': '1',
213 'TypeLibraryName': 'a_file_name',
214 'UndefinePreprocessorDefinitions': 'string1;string2',
215 'ValidateParameters': 'true',
216 'WarnAsError': 'true',
217 'WarningLevel': '1'},
218 'VCResourceCompilerTool': {
219 'AdditionalOptions': 'a string1',
220 'AdditionalIncludeDirectories': 'folder1;folder2',
221 'Culture': '1003',
222 'IgnoreStandardIncludePath': 'true',
223 'notgood2': 'bogus',
224 'PreprocessorDefinitions': 'string1;string2',
225 'ResourceOutputFileName': 'a string1',
226 'ShowProgress': 'true',
227 'SuppressStartupBanner': 'true',
228 'UndefinePreprocessorDefinitions': 'string1;string2'},
229 'VCLibrarianTool': {
230 'AdditionalDependencies': 'file1;file2',
231 'AdditionalLibraryDirectories': 'folder1;folder2',
232 'AdditionalOptions': 'a string1',
233 'ExportNamedFunctions': 'string1;string2',
234 'ForceSymbolReferences': 'a string1',
235 'IgnoreAllDefaultLibraries': 'true',
236 'IgnoreSpecificDefaultLibraries': 'file1;file2',
237 'LinkLibraryDependencies': 'true',
238 'ModuleDefinitionFile': 'a_file_name',
239 'OutputFile': 'a_file_name',
240 'SuppressStartupBanner': 'true',
241 'UseUnicodeResponseFiles': 'true'},
242 'VCManifestTool': {
243 'AdditionalManifestFiles': 'file1;file2',
244 'AdditionalOptions': 'a string1',
245 'AssemblyIdentity': 'a string1',
246 'ComponentFileName': 'a_file_name',
247 'DependencyInformationFile': 'a_file_name',
248 'GenerateCatalogFiles': 'true',
249 'InputResourceManifests': 'a string1',
250 'ManifestResourceFile': 'a_file_name',
251 'OutputManifestFile': 'a_file_name',
252 'RegistrarScriptFile': 'a_file_name',
253 'ReplacementsFile': 'a_file_name',
254 'SuppressStartupBanner': 'true',
255 'TypeLibraryFile': 'a_file_name',
256 'UpdateFileHashes': 'truel',
257 'UpdateFileHashesSearchPath': 'a_file_name',
258 'UseFAT32Workaround': 'true',
259 'UseUnicodeResponseFiles': 'true',
260 'VerboseOutput': 'true'}},
261 self.stderr)
262 self._ExpectedWarnings([
263 'Warning: for VCCLCompilerTool/BasicRuntimeChecks, '
264 'index value (5) not in expected range [0, 4)',
265 'Warning: for VCCLCompilerTool/BrowseInformation, '
266 "invalid literal for int() with base 10: 'fdkslj'",
267 'Warning: for VCCLCompilerTool/CallingConvention, '
268 'index value (-1) not in expected range [0, 3)',
269 'Warning: for VCCLCompilerTool/DebugInformationFormat, '
270 'converted value for 2 not specified.',
271 'Warning: unrecognized setting VCCLCompilerTool/Enableprefast',
272 'Warning: unrecognized setting VCCLCompilerTool/ZZXYZ',
273 'Warning: for VCLinkerTool/TargetMachine, '
274 'converted value for 2 not specified.',
275 'Warning: unrecognized setting VCMIDLTool/notgood',
276 'Warning: unrecognized setting VCResourceCompilerTool/notgood2',
277 'Warning: for VCManifestTool/UpdateFileHashes, '
278 "expected bool; got 'truel'"
279 ''])
280
281 def testValidateMSBuildSettings_settings(self):
282 """Tests that for invalid MSBuild settings."""
283 MSVSSettings.ValidateMSBuildSettings(
284 {'ClCompile': {
285 'AdditionalIncludeDirectories': 'folder1;folder2',
286 'AdditionalOptions': ['string1', 'string2'],
287 'AdditionalUsingDirectories': 'folder1;folder2',
288 'AssemblerListingLocation': 'a_file_name',
289 'AssemblerOutput': 'NoListing',
290 'BasicRuntimeChecks': 'StackFrameRuntimeCheck',
291 'BrowseInformation': 'false',
292 'BrowseInformationFile': 'a_file_name',
293 'BufferSecurityCheck': 'true',
294 'BuildingInIDE': 'true',
295 'CallingConvention': 'Cdecl',
296 'CompileAs': 'CompileAsC',
297 'CompileAsManaged': 'Pure',
298 'CreateHotpatchableImage': 'true',
299 'DebugInformationFormat': 'ProgramDatabase',
300 'DisableLanguageExtensions': 'true',
301 'DisableSpecificWarnings': 'string1;string2',
302 'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions',
303 'EnableFiberSafeOptimizations': 'true',
304 'EnablePREfast': 'true',
305 'Enableprefast': 'bogus',
306 'ErrorReporting': 'Prompt',
307 'ExceptionHandling': 'SyncCThrow',
308 'ExpandAttributedSource': 'true',
309 'FavorSizeOrSpeed': 'Neither',
310 'FloatingPointExceptions': 'true',
311 'FloatingPointModel': 'Precise',
312 'ForceConformanceInForLoopScope': 'true',
313 'ForcedIncludeFiles': 'file1;file2',
314 'ForcedUsingFiles': 'file1;file2',
315 'FunctionLevelLinking': 'false',
316 'GenerateXMLDocumentationFiles': 'true',
317 'IgnoreStandardIncludePath': 'true',
318 'InlineFunctionExpansion': 'OnlyExplicitInline',
319 'IntrinsicFunctions': 'false',
320 'MinimalRebuild': 'true',
321 'MultiProcessorCompilation': 'true',
322 'ObjectFileName': 'a_file_name',
323 'OmitDefaultLibName': 'true',
324 'OmitFramePointers': 'true',
325 'OpenMPSupport': 'true',
326 'Optimization': 'Disabled',
327 'PrecompiledHeader': 'NotUsing',
328 'PrecompiledHeaderFile': 'a_file_name',
329 'PrecompiledHeaderOutputFile': 'a_file_name',
330 'PreprocessKeepComments': 'true',
331 'PreprocessorDefinitions': 'string1;string2',
332 'PreprocessOutputPath': 'a string1',
333 'PreprocessSuppressLineNumbers': 'false',
334 'PreprocessToFile': 'false',
335 'ProcessorNumber': '33',
336 'ProgramDataBaseFileName': 'a_file_name',
337 'RuntimeLibrary': 'MultiThreaded',
338 'RuntimeTypeInfo': 'true',
339 'ShowIncludes': 'true',
340 'SmallerTypeCheck': 'true',
341 'StringPooling': 'true',
342 'StructMemberAlignment': '1Byte',
343 'SuppressStartupBanner': 'true',
344 'TrackerLogDirectory': 'a_folder',
345 'TreatSpecificWarningsAsErrors': 'string1;string2',
346 'TreatWarningAsError': 'true',
347 'TreatWChar_tAsBuiltInType': 'true',
348 'UndefineAllPreprocessorDefinitions': 'true',
349 'UndefinePreprocessorDefinitions': 'string1;string2',
350 'UseFullPaths': 'true',
351 'UseUnicodeForAssemblerListing': 'true',
352 'WarningLevel': 'TurnOffAllWarnings',
353 'WholeProgramOptimization': 'true',
354 'XMLDocumentationFileName': 'a_file_name',
355 'ZZXYZ': 'bogus'},
356 'Link': {
357 'AdditionalDependencies': 'file1;file2',
358 'AdditionalLibraryDirectories': 'folder1;folder2',
359 'AdditionalManifestDependencies': 'file1;file2',
360 'AdditionalOptions': 'a string1',
361 'AddModuleNamesToAssembly': 'file1;file2',
362 'AllowIsolation': 'true',
363 'AssemblyDebug': '',
364 'AssemblyLinkResource': 'file1;file2',
365 'BaseAddress': 'a string1',
366 'BuildingInIDE': 'true',
367 'CLRImageType': 'ForceIJWImage',
368 'CLRSupportLastError': 'Enabled',
369 'CLRThreadAttribute': 'MTAThreadingAttribute',
370 'CLRUnmanagedCodeCheck': 'true',
371 'CreateHotPatchableImage': 'X86Image',
372 'DataExecutionPrevention': 'false',
373 'DelayLoadDLLs': 'file1;file2',
374 'DelaySign': 'true',
375 'Driver': 'NotSet',
376 'EmbedManagedResourceFile': 'file1;file2',
377 'EnableCOMDATFolding': 'false',
378 'EnableUAC': 'true',
379 'EntryPointSymbol': 'a string1',
380 'FixedBaseAddress': 'false',
381 'ForceFileOutput': 'Enabled',
382 'ForceSymbolReferences': 'file1;file2',
383 'FunctionOrder': 'a_file_name',
384 'GenerateDebugInformation': 'true',
385 'GenerateMapFile': 'true',
386 'HeapCommitSize': 'a string1',
387 'HeapReserveSize': 'a string1',
388 'IgnoreAllDefaultLibraries': 'true',
389 'IgnoreEmbeddedIDL': 'true',
390 'IgnoreSpecificDefaultLibraries': 'a_file_list',
391 'ImageHasSafeExceptionHandlers': 'true',
392 'ImportLibrary': 'a_file_name',
393 'KeyContainer': 'a_file_name',
394 'KeyFile': 'a_file_name',
395 'LargeAddressAware': 'false',
396 'LinkDLL': 'true',
397 'LinkErrorReporting': 'SendErrorReport',
398 'LinkStatus': 'true',
399 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration',
400 'ManifestFile': 'a_file_name',
401 'MapExports': 'true',
402 'MapFileName': 'a_file_name',
403 'MergedIDLBaseFileName': 'a_file_name',
404 'MergeSections': 'a string1',
405 'MidlCommandFile': 'a_file_name',
406 'MinimumRequiredVersion': 'a string1',
407 'ModuleDefinitionFile': 'a_file_name',
408 'MSDOSStubFileName': 'a_file_name',
409 'NoEntryPoint': 'true',
410 'OptimizeReferences': 'false',
411 'OutputFile': 'a_file_name',
412 'PerUserRedirection': 'true',
413 'PreventDllBinding': 'true',
414 'Profile': 'true',
415 'ProfileGuidedDatabase': 'a_file_name',
416 'ProgramDatabaseFile': 'a_file_name',
417 'RandomizedBaseAddress': 'false',
418 'RegisterOutput': 'true',
419 'SectionAlignment': '33',
420 'SetChecksum': 'true',
421 'ShowProgress': 'LinkVerboseREF',
422 'SpecifySectionAttributes': 'a string1',
423 'StackCommitSize': 'a string1',
424 'StackReserveSize': 'a string1',
425 'StripPrivateSymbols': 'a_file_name',
426 'SubSystem': 'Console',
427 'SupportNobindOfDelayLoadedDLL': 'true',
428 'SupportUnloadOfDelayLoadedDLL': 'true',
429 'SuppressStartupBanner': 'true',
430 'SwapRunFromCD': 'true',
431 'SwapRunFromNET': 'true',
432 'TargetMachine': 'MachineX86',
433 'TerminalServerAware': 'false',
434 'TrackerLogDirectory': 'a_folder',
435 'TreatLinkerWarningAsErrors': 'true',
436 'TurnOffAssemblyGeneration': 'true',
437 'TypeLibraryFile': 'a_file_name',
438 'TypeLibraryResourceID': '33',
439 'UACExecutionLevel': 'AsInvoker',
440 'UACUIAccess': 'true',
441 'Version': 'a string1'},
442 'ResourceCompile': {
443 'AdditionalIncludeDirectories': 'folder1;folder2',
444 'AdditionalOptions': 'a string1',
445 'Culture': '0x236',
446 'IgnoreStandardIncludePath': 'true',
447 'NullTerminateStrings': 'true',
448 'PreprocessorDefinitions': 'string1;string2',
449 'ResourceOutputFileName': 'a string1',
450 'ShowProgress': 'true',
451 'SuppressStartupBanner': 'true',
452 'TrackerLogDirectory': 'a_folder',
453 'UndefinePreprocessorDefinitions': 'string1;string2'},
454 'Midl': {
455 'AdditionalIncludeDirectories': 'folder1;folder2',
456 'AdditionalOptions': 'a string1',
457 'ApplicationConfigurationMode': 'true',
458 'ClientStubFile': 'a_file_name',
459 'CPreprocessOptions': 'a string1',
460 'DefaultCharType': 'Signed',
461 'DllDataFileName': 'a_file_name',
462 'EnableErrorChecks': 'EnableCustom',
463 'ErrorCheckAllocations': 'true',
464 'ErrorCheckBounds': 'true',
465 'ErrorCheckEnumRange': 'true',
466 'ErrorCheckRefPointers': 'true',
467 'ErrorCheckStubData': 'true',
468 'GenerateClientFiles': 'Stub',
469 'GenerateServerFiles': 'None',
470 'GenerateStublessProxies': 'true',
471 'GenerateTypeLibrary': 'true',
472 'HeaderFileName': 'a_file_name',
473 'IgnoreStandardIncludePath': 'true',
474 'InterfaceIdentifierFileName': 'a_file_name',
475 'LocaleID': '33',
476 'MkTypLibCompatible': 'true',
477 'OutputDirectory': 'a string1',
478 'PreprocessorDefinitions': 'string1;string2',
479 'ProxyFileName': 'a_file_name',
480 'RedirectOutputAndErrors': 'a_file_name',
481 'ServerStubFile': 'a_file_name',
482 'StructMemberAlignment': 'NotSet',
483 'SuppressCompilerWarnings': 'true',
484 'SuppressStartupBanner': 'true',
485 'TargetEnvironment': 'Itanium',
486 'TrackerLogDirectory': 'a_folder',
487 'TypeLibFormat': 'NewFormat',
488 'TypeLibraryName': 'a_file_name',
489 'UndefinePreprocessorDefinitions': 'string1;string2',
490 'ValidateAllParameters': 'true',
491 'WarnAsError': 'true',
492 'WarningLevel': '1'},
493 'Lib': {
494 'AdditionalDependencies': 'file1;file2',
495 'AdditionalLibraryDirectories': 'folder1;folder2',
496 'AdditionalOptions': 'a string1',
497 'DisplayLibrary': 'a string1',
498 'ErrorReporting': 'PromptImmediately',
499 'ExportNamedFunctions': 'string1;string2',
500 'ForceSymbolReferences': 'a string1',
501 'IgnoreAllDefaultLibraries': 'true',
502 'IgnoreSpecificDefaultLibraries': 'file1;file2',
503 'LinkTimeCodeGeneration': 'true',
504 'MinimumRequiredVersion': 'a string1',
505 'ModuleDefinitionFile': 'a_file_name',
506 'Name': 'a_file_name',
507 'OutputFile': 'a_file_name',
508 'RemoveObjects': 'file1;file2',
509 'SubSystem': 'Console',
510 'SuppressStartupBanner': 'true',
511 'TargetMachine': 'MachineX86i',
512 'TrackerLogDirectory': 'a_folder',
513 'TreatLibWarningAsErrors': 'true',
514 'UseUnicodeResponseFiles': 'true',
515 'Verbose': 'true'},
516 'Mt': {
517 'AdditionalManifestFiles': 'file1;file2',
518 'AdditionalOptions': 'a string1',
519 'AssemblyIdentity': 'a string1',
520 'ComponentFileName': 'a_file_name',
521 'EnableDPIAwareness': 'fal',
522 'GenerateCatalogFiles': 'truel',
523 'GenerateCategoryTags': 'true',
524 'InputResourceManifests': 'a string1',
525 'ManifestFromManagedAssembly': 'a_file_name',
526 'notgood3': 'bogus',
527 'OutputManifestFile': 'a_file_name',
528 'OutputResourceManifests': 'a string1',
529 'RegistrarScriptFile': 'a_file_name',
530 'ReplacementsFile': 'a_file_name',
531 'SuppressDependencyElement': 'true',
532 'SuppressStartupBanner': 'true',
533 'TrackerLogDirectory': 'a_folder',
534 'TypeLibraryFile': 'a_file_name',
535 'UpdateFileHashes': 'true',
536 'UpdateFileHashesSearchPath': 'a_file_name',
537 'VerboseOutput': 'true'},
538 'ProjectReference': {
539 'LinkLibraryDependencies': 'true',
540 'UseLibraryDependencyInputs': 'true'},
541 'ManifestResourceCompile': {
542 'ResourceOutputFileName': 'a_file_name'},
543 '': {
544 'EmbedManifest': 'true',
545 'GenerateManifest': 'true',
546 'IgnoreImportLibrary': 'true',
547 'LinkIncremental': 'false'}},
548 self.stderr)
549 self._ExpectedWarnings([
550 'Warning: unrecognized setting ClCompile/Enableprefast',
551 'Warning: unrecognized setting ClCompile/ZZXYZ',
552 'Warning: unrecognized setting Mt/notgood3',
553 "Warning: for Mt/GenerateCatalogFiles, expected bool; got 'truel'",
554 'Warning: for Lib/TargetMachine, unrecognized enumerated value '
555 'MachineX86i',
556 "Warning: for Mt/EnableDPIAwareness, expected bool; got 'fal'"])
557
558 def testConvertToMSBuildSettings_empty(self):
559 """Tests an empty conversion."""
560 msvs_settings = {}
561 expected_msbuild_settings = {}
562 actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
563 msvs_settings,
564 self.stderr)
565 self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
566 self._ExpectedWarnings([])
567
568 def testConvertToMSBuildSettings_minimal(self):
569 """Tests a minimal conversion."""
570 msvs_settings = {
571 'VCCLCompilerTool': {
572 'AdditionalIncludeDirectories': 'dir1',
573 'AdditionalOptions': '/foo',
574 'BasicRuntimeChecks': '0',
575 },
576 'VCLinkerTool': {
577 'LinkTimeCodeGeneration': '1',
578 'ErrorReporting': '1',
579 'DataExecutionPrevention': '2',
580 },
581 }
582 expected_msbuild_settings = {
583 'ClCompile': {
584 'AdditionalIncludeDirectories': 'dir1',
585 'AdditionalOptions': '/foo',
586 'BasicRuntimeChecks': 'Default',
587 },
588 'Link': {
589 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration',
590 'LinkErrorReporting': 'PromptImmediately',
591 'DataExecutionPrevention': 'true',
592 },
593 }
594 actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
595 msvs_settings,
596 self.stderr)
597 self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
598 self._ExpectedWarnings([])
599
600 def testConvertToMSBuildSettings_warnings(self):
601 """Tests conversion that generates warnings."""
602 msvs_settings = {
603 'VCCLCompilerTool': {
604 'AdditionalIncludeDirectories': '1',
605 'AdditionalOptions': '2',
606 # These are incorrect values:
607 'BasicRuntimeChecks': '12',
608 'BrowseInformation': '21',
609 'UsePrecompiledHeader': '13',
610 'GeneratePreprocessedFile': '14'},
611 'VCLinkerTool': {
612 # These are incorrect values:
613 'Driver': '10',
614 'LinkTimeCodeGeneration': '31',
615 'ErrorReporting': '21',
616 'FixedBaseAddress': '6'},
617 'VCResourceCompilerTool': {
618 # Custom
619 'Culture': '1003'}}
620 expected_msbuild_settings = {
621 'ClCompile': {
622 'AdditionalIncludeDirectories': '1',
623 'AdditionalOptions': '2'},
624 'Link': {},
625 'ResourceCompile': {
626 # Custom
627 'Culture': '0x03eb'}}
628 actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
629 msvs_settings,
630 self.stderr)
631 self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
632 self._ExpectedWarnings([
633 'Warning: while converting VCCLCompilerTool/BasicRuntimeChecks to '
634 'MSBuild, index value (12) not in expected range [0, 4)',
635 'Warning: while converting VCCLCompilerTool/BrowseInformation to '
636 'MSBuild, index value (21) not in expected range [0, 3)',
637 'Warning: while converting VCCLCompilerTool/UsePrecompiledHeader to '
638 'MSBuild, index value (13) not in expected range [0, 3)',
639 'Warning: while converting VCCLCompilerTool/GeneratePreprocessedFile to '
640 'MSBuild, value must be one of [0, 1, 2]; got 14',
641
642 'Warning: while converting VCLinkerTool/Driver to '
643 'MSBuild, index value (10) not in expected range [0, 4)',
644 'Warning: while converting VCLinkerTool/LinkTimeCodeGeneration to '
645 'MSBuild, index value (31) not in expected range [0, 5)',
646 'Warning: while converting VCLinkerTool/ErrorReporting to '
647 'MSBuild, index value (21) not in expected range [0, 3)',
648 'Warning: while converting VCLinkerTool/FixedBaseAddress to '
649 'MSBuild, index value (6) not in expected range [0, 3)',
650 ])
651
652 def testConvertToMSBuildSettings_full_synthetic(self):
653 """Tests conversion of all the MSBuild settings."""
654 msvs_settings = {
655 'VCCLCompilerTool': {
656 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
657 'AdditionalOptions': 'a_string',
658 'AdditionalUsingDirectories': 'folder1;folder2;folder3',
659 'AssemblerListingLocation': 'a_file_name',
660 'AssemblerOutput': '0',
661 'BasicRuntimeChecks': '1',
662 'BrowseInformation': '2',
663 'BrowseInformationFile': 'a_file_name',
664 'BufferSecurityCheck': 'true',
665 'CallingConvention': '0',
666 'CompileAs': '1',
667 'DebugInformationFormat': '4',
668 'DefaultCharIsUnsigned': 'true',
669 'Detect64BitPortabilityProblems': 'true',
670 'DisableLanguageExtensions': 'true',
671 'DisableSpecificWarnings': 'd1;d2;d3',
672 'EnableEnhancedInstructionSet': '0',
673 'EnableFiberSafeOptimizations': 'true',
674 'EnableFunctionLevelLinking': 'true',
675 'EnableIntrinsicFunctions': 'true',
676 'EnablePREfast': 'true',
677 'ErrorReporting': '1',
678 'ExceptionHandling': '2',
679 'ExpandAttributedSource': 'true',
680 'FavorSizeOrSpeed': '0',
681 'FloatingPointExceptions': 'true',
682 'FloatingPointModel': '1',
683 'ForceConformanceInForLoopScope': 'true',
684 'ForcedIncludeFiles': 'file1;file2;file3',
685 'ForcedUsingFiles': 'file1;file2;file3',
686 'GeneratePreprocessedFile': '1',
687 'GenerateXMLDocumentationFiles': 'true',
688 'IgnoreStandardIncludePath': 'true',
689 'InlineFunctionExpansion': '2',
690 'KeepComments': 'true',
691 'MinimalRebuild': 'true',
692 'ObjectFile': 'a_file_name',
693 'OmitDefaultLibName': 'true',
694 'OmitFramePointers': 'true',
695 'OpenMP': 'true',
696 'Optimization': '3',
697 'PrecompiledHeaderFile': 'a_file_name',
698 'PrecompiledHeaderThrough': 'a_file_name',
699 'PreprocessorDefinitions': 'd1;d2;d3',
700 'ProgramDataBaseFileName': 'a_file_name',
701 'RuntimeLibrary': '0',
702 'RuntimeTypeInfo': 'true',
703 'ShowIncludes': 'true',
704 'SmallerTypeCheck': 'true',
705 'StringPooling': 'true',
706 'StructMemberAlignment': '1',
707 'SuppressStartupBanner': 'true',
708 'TreatWChar_tAsBuiltInType': 'true',
709 'UndefineAllPreprocessorDefinitions': 'true',
710 'UndefinePreprocessorDefinitions': 'd1;d2;d3',
711 'UseFullPaths': 'true',
712 'UsePrecompiledHeader': '1',
713 'UseUnicodeResponseFiles': 'true',
714 'WarnAsError': 'true',
715 'WarningLevel': '2',
716 'WholeProgramOptimization': 'true',
717 'XMLDocumentationFileName': 'a_file_name'},
718 'VCLinkerTool': {
719 'AdditionalDependencies': 'file1;file2;file3',
720 'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
721 'AdditionalLibraryDirectories_excluded': 'folder1;folder2;folder3',
722 'AdditionalManifestDependencies': 'file1;file2;file3',
723 'AdditionalOptions': 'a_string',
724 'AddModuleNamesToAssembly': 'file1;file2;file3',
725 'AllowIsolation': 'true',
726 'AssemblyDebug': '0',
727 'AssemblyLinkResource': 'file1;file2;file3',
728 'BaseAddress': 'a_string',
729 'CLRImageType': '1',
730 'CLRThreadAttribute': '2',
731 'CLRUnmanagedCodeCheck': 'true',
732 'DataExecutionPrevention': '0',
733 'DelayLoadDLLs': 'file1;file2;file3',
734 'DelaySign': 'true',
735 'Driver': '1',
736 'EmbedManagedResourceFile': 'file1;file2;file3',
737 'EnableCOMDATFolding': '0',
738 'EnableUAC': 'true',
739 'EntryPointSymbol': 'a_string',
740 'ErrorReporting': '0',
741 'FixedBaseAddress': '1',
742 'ForceSymbolReferences': 'file1;file2;file3',
743 'FunctionOrder': 'a_file_name',
744 'GenerateDebugInformation': 'true',
745 'GenerateManifest': 'true',
746 'GenerateMapFile': 'true',
747 'HeapCommitSize': 'a_string',
748 'HeapReserveSize': 'a_string',
749 'IgnoreAllDefaultLibraries': 'true',
750 'IgnoreDefaultLibraryNames': 'file1;file2;file3',
751 'IgnoreEmbeddedIDL': 'true',
752 'IgnoreImportLibrary': 'true',
753 'ImportLibrary': 'a_file_name',
754 'KeyContainer': 'a_file_name',
755 'KeyFile': 'a_file_name',
756 'LargeAddressAware': '2',
757 'LinkIncremental': '1',
758 'LinkLibraryDependencies': 'true',
759 'LinkTimeCodeGeneration': '2',
760 'ManifestFile': 'a_file_name',
761 'MapExports': 'true',
762 'MapFileName': 'a_file_name',
763 'MergedIDLBaseFileName': 'a_file_name',
764 'MergeSections': 'a_string',
765 'MidlCommandFile': 'a_file_name',
766 'ModuleDefinitionFile': 'a_file_name',
767 'OptimizeForWindows98': '1',
768 'OptimizeReferences': '0',
769 'OutputFile': 'a_file_name',
770 'PerUserRedirection': 'true',
771 'Profile': 'true',
772 'ProfileGuidedDatabase': 'a_file_name',
773 'ProgramDatabaseFile': 'a_file_name',
774 'RandomizedBaseAddress': '1',
775 'RegisterOutput': 'true',
776 'ResourceOnlyDLL': 'true',
777 'SetChecksum': 'true',
778 'ShowProgress': '0',
779 'StackCommitSize': 'a_string',
780 'StackReserveSize': 'a_string',
781 'StripPrivateSymbols': 'a_file_name',
782 'SubSystem': '2',
783 'SupportUnloadOfDelayLoadedDLL': 'true',
784 'SuppressStartupBanner': 'true',
785 'SwapRunFromCD': 'true',
786 'SwapRunFromNet': 'true',
787 'TargetMachine': '3',
788 'TerminalServerAware': '2',
789 'TurnOffAssemblyGeneration': 'true',
790 'TypeLibraryFile': 'a_file_name',
791 'TypeLibraryResourceID': '33',
792 'UACExecutionLevel': '1',
793 'UACUIAccess': 'true',
794 'UseLibraryDependencyInputs': 'false',
795 'UseUnicodeResponseFiles': 'true',
796 'Version': 'a_string'},
797 'VCResourceCompilerTool': {
798 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
799 'AdditionalOptions': 'a_string',
800 'Culture': '1003',
801 'IgnoreStandardIncludePath': 'true',
802 'PreprocessorDefinitions': 'd1;d2;d3',
803 'ResourceOutputFileName': 'a_string',
804 'ShowProgress': 'true',
805 'SuppressStartupBanner': 'true',
806 'UndefinePreprocessorDefinitions': 'd1;d2;d3'},
807 'VCMIDLTool': {
808 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
809 'AdditionalOptions': 'a_string',
810 'CPreprocessOptions': 'a_string',
811 'DefaultCharType': '0',
812 'DLLDataFileName': 'a_file_name',
813 'EnableErrorChecks': '2',
814 'ErrorCheckAllocations': 'true',
815 'ErrorCheckBounds': 'true',
816 'ErrorCheckEnumRange': 'true',
817 'ErrorCheckRefPointers': 'true',
818 'ErrorCheckStubData': 'true',
819 'GenerateStublessProxies': 'true',
820 'GenerateTypeLibrary': 'true',
821 'HeaderFileName': 'a_file_name',
822 'IgnoreStandardIncludePath': 'true',
823 'InterfaceIdentifierFileName': 'a_file_name',
824 'MkTypLibCompatible': 'true',
825 'OutputDirectory': 'a_string',
826 'PreprocessorDefinitions': 'd1;d2;d3',
827 'ProxyFileName': 'a_file_name',
828 'RedirectOutputAndErrors': 'a_file_name',
829 'StructMemberAlignment': '3',
830 'SuppressStartupBanner': 'true',
831 'TargetEnvironment': '1',
832 'TypeLibraryName': 'a_file_name',
833 'UndefinePreprocessorDefinitions': 'd1;d2;d3',
834 'ValidateParameters': 'true',
835 'WarnAsError': 'true',
836 'WarningLevel': '4'},
837 'VCLibrarianTool': {
838 'AdditionalDependencies': 'file1;file2;file3',
839 'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
840 'AdditionalLibraryDirectories_excluded': 'folder1;folder2;folder3',
841 'AdditionalOptions': 'a_string',
842 'ExportNamedFunctions': 'd1;d2;d3',
843 'ForceSymbolReferences': 'a_string',
844 'IgnoreAllDefaultLibraries': 'true',
845 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3',
846 'LinkLibraryDependencies': 'true',
847 'ModuleDefinitionFile': 'a_file_name',
848 'OutputFile': 'a_file_name',
849 'SuppressStartupBanner': 'true',
850 'UseUnicodeResponseFiles': 'true'},
851 'VCManifestTool': {
852 'AdditionalManifestFiles': 'file1;file2;file3',
853 'AdditionalOptions': 'a_string',
854 'AssemblyIdentity': 'a_string',
855 'ComponentFileName': 'a_file_name',
856 'DependencyInformationFile': 'a_file_name',
857 'EmbedManifest': 'true',
858 'GenerateCatalogFiles': 'true',
859 'InputResourceManifests': 'a_string',
860 'ManifestResourceFile': 'my_name',
861 'OutputManifestFile': 'a_file_name',
862 'RegistrarScriptFile': 'a_file_name',
863 'ReplacementsFile': 'a_file_name',
864 'SuppressStartupBanner': 'true',
865 'TypeLibraryFile': 'a_file_name',
866 'UpdateFileHashes': 'true',
867 'UpdateFileHashesSearchPath': 'a_file_name',
868 'UseFAT32Workaround': 'true',
869 'UseUnicodeResponseFiles': 'true',
870 'VerboseOutput': 'true'}}
871 expected_msbuild_settings = {
872 'ClCompile': {
873 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
874 'AdditionalOptions': 'a_string /J',
875 'AdditionalUsingDirectories': 'folder1;folder2;folder3',
876 'AssemblerListingLocation': 'a_file_name',
877 'AssemblerOutput': 'NoListing',
878 'BasicRuntimeChecks': 'StackFrameRuntimeCheck',
879 'BrowseInformation': 'true',
880 'BrowseInformationFile': 'a_file_name',
881 'BufferSecurityCheck': 'true',
882 'CallingConvention': 'Cdecl',
883 'CompileAs': 'CompileAsC',
884 'DebugInformationFormat': 'EditAndContinue',
885 'DisableLanguageExtensions': 'true',
886 'DisableSpecificWarnings': 'd1;d2;d3',
887 'EnableEnhancedInstructionSet': 'NotSet',
888 'EnableFiberSafeOptimizations': 'true',
889 'EnablePREfast': 'true',
890 'ErrorReporting': 'Prompt',
891 'ExceptionHandling': 'Async',
892 'ExpandAttributedSource': 'true',
893 'FavorSizeOrSpeed': 'Neither',
894 'FloatingPointExceptions': 'true',
895 'FloatingPointModel': 'Strict',
896 'ForceConformanceInForLoopScope': 'true',
897 'ForcedIncludeFiles': 'file1;file2;file3',
898 'ForcedUsingFiles': 'file1;file2;file3',
899 'FunctionLevelLinking': 'true',
900 'GenerateXMLDocumentationFiles': 'true',
901 'IgnoreStandardIncludePath': 'true',
902 'InlineFunctionExpansion': 'AnySuitable',
903 'IntrinsicFunctions': 'true',
904 'MinimalRebuild': 'true',
905 'ObjectFileName': 'a_file_name',
906 'OmitDefaultLibName': 'true',
907 'OmitFramePointers': 'true',
908 'OpenMPSupport': 'true',
909 'Optimization': 'Full',
910 'PrecompiledHeader': 'Create',
911 'PrecompiledHeaderFile': 'a_file_name',
912 'PrecompiledHeaderOutputFile': 'a_file_name',
913 'PreprocessKeepComments': 'true',
914 'PreprocessorDefinitions': 'd1;d2;d3',
915 'PreprocessSuppressLineNumbers': 'false',
916 'PreprocessToFile': 'true',
917 'ProgramDataBaseFileName': 'a_file_name',
918 'RuntimeLibrary': 'MultiThreaded',
919 'RuntimeTypeInfo': 'true',
920 'ShowIncludes': 'true',
921 'SmallerTypeCheck': 'true',
922 'StringPooling': 'true',
923 'StructMemberAlignment': '1Byte',
924 'SuppressStartupBanner': 'true',
925 'TreatWarningAsError': 'true',
926 'TreatWChar_tAsBuiltInType': 'true',
927 'UndefineAllPreprocessorDefinitions': 'true',
928 'UndefinePreprocessorDefinitions': 'd1;d2;d3',
929 'UseFullPaths': 'true',
930 'WarningLevel': 'Level2',
931 'WholeProgramOptimization': 'true',
932 'XMLDocumentationFileName': 'a_file_name'},
933 'Link': {
934 'AdditionalDependencies': 'file1;file2;file3',
935 'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
936 'AdditionalManifestDependencies': 'file1;file2;file3',
937 'AdditionalOptions': 'a_string',
938 'AddModuleNamesToAssembly': 'file1;file2;file3',
939 'AllowIsolation': 'true',
940 'AssemblyDebug': '',
941 'AssemblyLinkResource': 'file1;file2;file3',
942 'BaseAddress': 'a_string',
943 'CLRImageType': 'ForceIJWImage',
944 'CLRThreadAttribute': 'STAThreadingAttribute',
945 'CLRUnmanagedCodeCheck': 'true',
946 'DataExecutionPrevention': '',
947 'DelayLoadDLLs': 'file1;file2;file3',
948 'DelaySign': 'true',
949 'Driver': 'Driver',
950 'EmbedManagedResourceFile': 'file1;file2;file3',
951 'EnableCOMDATFolding': '',
952 'EnableUAC': 'true',
953 'EntryPointSymbol': 'a_string',
954 'FixedBaseAddress': 'false',
955 'ForceSymbolReferences': 'file1;file2;file3',
956 'FunctionOrder': 'a_file_name',
957 'GenerateDebugInformation': 'true',
958 'GenerateMapFile': 'true',
959 'HeapCommitSize': 'a_string',
960 'HeapReserveSize': 'a_string',
961 'IgnoreAllDefaultLibraries': 'true',
962 'IgnoreEmbeddedIDL': 'true',
963 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3',
964 'ImportLibrary': 'a_file_name',
965 'KeyContainer': 'a_file_name',
966 'KeyFile': 'a_file_name',
967 'LargeAddressAware': 'true',
968 'LinkErrorReporting': 'NoErrorReport',
969 'LinkTimeCodeGeneration': 'PGInstrument',
970 'ManifestFile': 'a_file_name',
971 'MapExports': 'true',
972 'MapFileName': 'a_file_name',
973 'MergedIDLBaseFileName': 'a_file_name',
974 'MergeSections': 'a_string',
975 'MidlCommandFile': 'a_file_name',
976 'ModuleDefinitionFile': 'a_file_name',
977 'NoEntryPoint': 'true',
978 'OptimizeReferences': '',
979 'OutputFile': 'a_file_name',
980 'PerUserRedirection': 'true',
981 'Profile': 'true',
982 'ProfileGuidedDatabase': 'a_file_name',
983 'ProgramDatabaseFile': 'a_file_name',
984 'RandomizedBaseAddress': 'false',
985 'RegisterOutput': 'true',
986 'SetChecksum': 'true',
987 'ShowProgress': 'NotSet',
988 'StackCommitSize': 'a_string',
989 'StackReserveSize': 'a_string',
990 'StripPrivateSymbols': 'a_file_name',
991 'SubSystem': 'Windows',
992 'SupportUnloadOfDelayLoadedDLL': 'true',
993 'SuppressStartupBanner': 'true',
994 'SwapRunFromCD': 'true',
995 'SwapRunFromNET': 'true',
996 'TargetMachine': 'MachineARM',
997 'TerminalServerAware': 'true',
998 'TurnOffAssemblyGeneration': 'true',
999 'TypeLibraryFile': 'a_file_name',
1000 'TypeLibraryResourceID': '33',
1001 'UACExecutionLevel': 'HighestAvailable',
1002 'UACUIAccess': 'true',
1003 'Version': 'a_string'},
1004 'ResourceCompile': {
1005 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
1006 'AdditionalOptions': 'a_string',
1007 'Culture': '0x03eb',
1008 'IgnoreStandardIncludePath': 'true',
1009 'PreprocessorDefinitions': 'd1;d2;d3',
1010 'ResourceOutputFileName': 'a_string',
1011 'ShowProgress': 'true',
1012 'SuppressStartupBanner': 'true',
1013 'UndefinePreprocessorDefinitions': 'd1;d2;d3'},
1014 'Midl': {
1015 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
1016 'AdditionalOptions': 'a_string',
1017 'CPreprocessOptions': 'a_string',
1018 'DefaultCharType': 'Unsigned',
1019 'DllDataFileName': 'a_file_name',
1020 'EnableErrorChecks': 'All',
1021 'ErrorCheckAllocations': 'true',
1022 'ErrorCheckBounds': 'true',
1023 'ErrorCheckEnumRange': 'true',
1024 'ErrorCheckRefPointers': 'true',
1025 'ErrorCheckStubData': 'true',
1026 'GenerateStublessProxies': 'true',
1027 'GenerateTypeLibrary': 'true',
1028 'HeaderFileName': 'a_file_name',
1029 'IgnoreStandardIncludePath': 'true',
1030 'InterfaceIdentifierFileName': 'a_file_name',
1031 'MkTypLibCompatible': 'true',
1032 'OutputDirectory': 'a_string',
1033 'PreprocessorDefinitions': 'd1;d2;d3',
1034 'ProxyFileName': 'a_file_name',
1035 'RedirectOutputAndErrors': 'a_file_name',
1036 'StructMemberAlignment': '4',
1037 'SuppressStartupBanner': 'true',
1038 'TargetEnvironment': 'Win32',
1039 'TypeLibraryName': 'a_file_name',
1040 'UndefinePreprocessorDefinitions': 'd1;d2;d3',
1041 'ValidateAllParameters': 'true',
1042 'WarnAsError': 'true',
1043 'WarningLevel': '4'},
1044 'Lib': {
1045 'AdditionalDependencies': 'file1;file2;file3',
1046 'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
1047 'AdditionalOptions': 'a_string',
1048 'ExportNamedFunctions': 'd1;d2;d3',
1049 'ForceSymbolReferences': 'a_string',
1050 'IgnoreAllDefaultLibraries': 'true',
1051 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3',
1052 'ModuleDefinitionFile': 'a_file_name',
1053 'OutputFile': 'a_file_name',
1054 'SuppressStartupBanner': 'true',
1055 'UseUnicodeResponseFiles': 'true'},
1056 'Mt': {
1057 'AdditionalManifestFiles': 'file1;file2;file3',
1058 'AdditionalOptions': 'a_string',
1059 'AssemblyIdentity': 'a_string',
1060 'ComponentFileName': 'a_file_name',
1061 'GenerateCatalogFiles': 'true',
1062 'InputResourceManifests': 'a_string',
1063 'OutputManifestFile': 'a_file_name',
1064 'RegistrarScriptFile': 'a_file_name',
1065 'ReplacementsFile': 'a_file_name',
1066 'SuppressStartupBanner': 'true',
1067 'TypeLibraryFile': 'a_file_name',
1068 'UpdateFileHashes': 'true',
1069 'UpdateFileHashesSearchPath': 'a_file_name',
1070 'VerboseOutput': 'true'},
1071 'ManifestResourceCompile': {
1072 'ResourceOutputFileName': 'my_name'},
1073 'ProjectReference': {
1074 'LinkLibraryDependencies': 'true',
1075 'UseLibraryDependencyInputs': 'false'},
1076 '': {
1077 'EmbedManifest': 'true',
1078 'GenerateManifest': 'true',
1079 'IgnoreImportLibrary': 'true',
1080 'LinkIncremental': 'false'}}
1081 actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
1082 msvs_settings,
1083 self.stderr)
1084 self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
1085 self._ExpectedWarnings([])
1086
1087 def testConvertToMSBuildSettings_actual(self):
1088 """Tests the conversion of an actual project.
1089
1090 A VS2008 project with most of the options defined was created through the
1091 VS2008 IDE. It was then converted to VS2010. The tool settings found in
1092 the .vcproj and .vcxproj files were converted to the two dictionaries
1093 msvs_settings and expected_msbuild_settings.
1094
1095 Note that for many settings, the VS2010 converter adds macros like
1096 %(AdditionalIncludeDirectories) to make sure than inherited values are
1097 included. Since the Gyp projects we generate do not use inheritance,
1098 we removed these macros. They were:
1099 ClCompile:
1100 AdditionalIncludeDirectories: ';%(AdditionalIncludeDirectories)'
1101 AdditionalOptions: ' %(AdditionalOptions)'
1102 AdditionalUsingDirectories: ';%(AdditionalUsingDirectories)'
1103 DisableSpecificWarnings: ';%(DisableSpecificWarnings)',
1104 ForcedIncludeFiles: ';%(ForcedIncludeFiles)',
1105 ForcedUsingFiles: ';%(ForcedUsingFiles)',
1106 PreprocessorDefinitions: ';%(PreprocessorDefinitions)',
1107 UndefinePreprocessorDefinitions:
1108 ';%(UndefinePreprocessorDefinitions)',
1109 Link:
1110 AdditionalDependencies: ';%(AdditionalDependencies)',
1111 AdditionalLibraryDirectories: ';%(AdditionalLibraryDirectories)',
1112 AdditionalManifestDependencies:
1113 ';%(AdditionalManifestDependencies)',
1114 AdditionalOptions: ' %(AdditionalOptions)',
1115 AddModuleNamesToAssembly: ';%(AddModuleNamesToAssembly)',
1116 AssemblyLinkResource: ';%(AssemblyLinkResource)',
1117 DelayLoadDLLs: ';%(DelayLoadDLLs)',
1118 EmbedManagedResourceFile: ';%(EmbedManagedResourceFile)',
1119 ForceSymbolReferences: ';%(ForceSymbolReferences)',
1120 IgnoreSpecificDefaultLibraries:
1121 ';%(IgnoreSpecificDefaultLibraries)',
1122 ResourceCompile:
1123 AdditionalIncludeDirectories: ';%(AdditionalIncludeDirectories)',
1124 AdditionalOptions: ' %(AdditionalOptions)',
1125 PreprocessorDefinitions: ';%(PreprocessorDefinitions)',
1126 Mt:
1127 AdditionalManifestFiles: ';%(AdditionalManifestFiles)',
1128 AdditionalOptions: ' %(AdditionalOptions)',
1129 InputResourceManifests: ';%(InputResourceManifests)',
1130 """
1131 msvs_settings = {
1132 'VCCLCompilerTool': {
1133 'AdditionalIncludeDirectories': 'dir1',
1134 'AdditionalOptions': '/more',
1135 'AdditionalUsingDirectories': 'test',
1136 'AssemblerListingLocation': '$(IntDir)\\a',
1137 'AssemblerOutput': '1',
1138 'BasicRuntimeChecks': '3',
1139 'BrowseInformation': '1',
1140 'BrowseInformationFile': '$(IntDir)\\e',
1141 'BufferSecurityCheck': 'false',
1142 'CallingConvention': '1',
1143 'CompileAs': '1',
1144 'DebugInformationFormat': '4',
1145 'DefaultCharIsUnsigned': 'true',
1146 'Detect64BitPortabilityProblems': 'true',
1147 'DisableLanguageExtensions': 'true',
1148 'DisableSpecificWarnings': 'abc',
1149 'EnableEnhancedInstructionSet': '1',
1150 'EnableFiberSafeOptimizations': 'true',
1151 'EnableFunctionLevelLinking': 'true',
1152 'EnableIntrinsicFunctions': 'true',
1153 'EnablePREfast': 'true',
1154 'ErrorReporting': '2',
1155 'ExceptionHandling': '2',
1156 'ExpandAttributedSource': 'true',
1157 'FavorSizeOrSpeed': '2',
1158 'FloatingPointExceptions': 'true',
1159 'FloatingPointModel': '1',
1160 'ForceConformanceInForLoopScope': 'false',
1161 'ForcedIncludeFiles': 'def',
1162 'ForcedUsingFiles': 'ge',
1163 'GeneratePreprocessedFile': '2',
1164 'GenerateXMLDocumentationFiles': 'true',
1165 'IgnoreStandardIncludePath': 'true',
1166 'InlineFunctionExpansion': '1',
1167 'KeepComments': 'true',
1168 'MinimalRebuild': 'true',
1169 'ObjectFile': '$(IntDir)\\b',
1170 'OmitDefaultLibName': 'true',
1171 'OmitFramePointers': 'true',
1172 'OpenMP': 'true',
1173 'Optimization': '3',
1174 'PrecompiledHeaderFile': '$(IntDir)\\$(TargetName).pche',
1175 'PrecompiledHeaderThrough': 'StdAfx.hd',
1176 'PreprocessorDefinitions': 'WIN32;_DEBUG;_CONSOLE',
1177 'ProgramDataBaseFileName': '$(IntDir)\\vc90b.pdb',
1178 'RuntimeLibrary': '3',
1179 'RuntimeTypeInfo': 'false',
1180 'ShowIncludes': 'true',
1181 'SmallerTypeCheck': 'true',
1182 'StringPooling': 'true',
1183 'StructMemberAlignment': '3',
1184 'SuppressStartupBanner': 'false',
1185 'TreatWChar_tAsBuiltInType': 'false',
1186 'UndefineAllPreprocessorDefinitions': 'true',
1187 'UndefinePreprocessorDefinitions': 'wer',
1188 'UseFullPaths': 'true',
1189 'UsePrecompiledHeader': '0',
1190 'UseUnicodeResponseFiles': 'false',
1191 'WarnAsError': 'true',
1192 'WarningLevel': '3',
1193 'WholeProgramOptimization': 'true',
1194 'XMLDocumentationFileName': '$(IntDir)\\c'},
1195 'VCLinkerTool': {
1196 'AdditionalDependencies': 'zx',
1197 'AdditionalLibraryDirectories': 'asd',
1198 'AdditionalManifestDependencies': 's2',
1199 'AdditionalOptions': '/mor2',
1200 'AddModuleNamesToAssembly': 'd1',
1201 'AllowIsolation': 'false',
1202 'AssemblyDebug': '1',
1203 'AssemblyLinkResource': 'd5',
1204 'BaseAddress': '23423',
1205 'CLRImageType': '3',
1206 'CLRThreadAttribute': '1',
1207 'CLRUnmanagedCodeCheck': 'true',
1208 'DataExecutionPrevention': '0',
1209 'DelayLoadDLLs': 'd4',
1210 'DelaySign': 'true',
1211 'Driver': '2',
1212 'EmbedManagedResourceFile': 'd2',
1213 'EnableCOMDATFolding': '1',
1214 'EnableUAC': 'false',
1215 'EntryPointSymbol': 'f5',
1216 'ErrorReporting': '2',
1217 'FixedBaseAddress': '1',
1218 'ForceSymbolReferences': 'd3',
1219 'FunctionOrder': 'fssdfsd',
1220 'GenerateDebugInformation': 'true',
1221 'GenerateManifest': 'false',
1222 'GenerateMapFile': 'true',
1223 'HeapCommitSize': '13',
1224 'HeapReserveSize': '12',
1225 'IgnoreAllDefaultLibraries': 'true',
1226 'IgnoreDefaultLibraryNames': 'flob;flok',
1227 'IgnoreEmbeddedIDL': 'true',
1228 'IgnoreImportLibrary': 'true',
1229 'ImportLibrary': 'f4',
1230 'KeyContainer': 'f7',
1231 'KeyFile': 'f6',
1232 'LargeAddressAware': '2',
1233 'LinkIncremental': '0',
1234 'LinkLibraryDependencies': 'false',
1235 'LinkTimeCodeGeneration': '1',
1236 'ManifestFile':
1237 '$(IntDir)\\$(TargetFileName).2intermediate.manifest',
1238 'MapExports': 'true',
1239 'MapFileName': 'd5',
1240 'MergedIDLBaseFileName': 'f2',
1241 'MergeSections': 'f5',
1242 'MidlCommandFile': 'f1',
1243 'ModuleDefinitionFile': 'sdsd',
1244 'OptimizeForWindows98': '2',
1245 'OptimizeReferences': '2',
1246 'OutputFile': '$(OutDir)\\$(ProjectName)2.exe',
1247 'PerUserRedirection': 'true',
1248 'Profile': 'true',
1249 'ProfileGuidedDatabase': '$(TargetDir)$(TargetName).pgdd',
1250 'ProgramDatabaseFile': 'Flob.pdb',
1251 'RandomizedBaseAddress': '1',
1252 'RegisterOutput': 'true',
1253 'ResourceOnlyDLL': 'true',
1254 'SetChecksum': 'false',
1255 'ShowProgress': '1',
1256 'StackCommitSize': '15',
1257 'StackReserveSize': '14',
1258 'StripPrivateSymbols': 'd3',
1259 'SubSystem': '1',
1260 'SupportUnloadOfDelayLoadedDLL': 'true',
1261 'SuppressStartupBanner': 'false',
1262 'SwapRunFromCD': 'true',
1263 'SwapRunFromNet': 'true',
1264 'TargetMachine': '1',
1265 'TerminalServerAware': '1',
1266 'TurnOffAssemblyGeneration': 'true',
1267 'TypeLibraryFile': 'f3',
1268 'TypeLibraryResourceID': '12',
1269 'UACExecutionLevel': '2',
1270 'UACUIAccess': 'true',
1271 'UseLibraryDependencyInputs': 'true',
1272 'UseUnicodeResponseFiles': 'false',
1273 'Version': '333'},
1274 'VCResourceCompilerTool': {
1275 'AdditionalIncludeDirectories': 'f3',
1276 'AdditionalOptions': '/more3',
1277 'Culture': '3084',
1278 'IgnoreStandardIncludePath': 'true',
1279 'PreprocessorDefinitions': '_UNICODE;UNICODE2',
1280 'ResourceOutputFileName': '$(IntDir)/$(InputName)3.res',
1281 'ShowProgress': 'true'},
1282 'VCManifestTool': {
1283 'AdditionalManifestFiles': 'sfsdfsd',
1284 'AdditionalOptions': 'afdsdafsd',
1285 'AssemblyIdentity': 'sddfdsadfsa',
1286 'ComponentFileName': 'fsdfds',
1287 'DependencyInformationFile': '$(IntDir)\\mt.depdfd',
1288 'EmbedManifest': 'false',
1289 'GenerateCatalogFiles': 'true',
1290 'InputResourceManifests': 'asfsfdafs',
1291 'ManifestResourceFile':
1292 '$(IntDir)\\$(TargetFileName).embed.manifest.resfdsf',
1293 'OutputManifestFile': '$(TargetPath).manifestdfs',
1294 'RegistrarScriptFile': 'sdfsfd',
1295 'ReplacementsFile': 'sdffsd',
1296 'SuppressStartupBanner': 'false',
1297 'TypeLibraryFile': 'sfsd',
1298 'UpdateFileHashes': 'true',
1299 'UpdateFileHashesSearchPath': 'sfsd',
1300 'UseFAT32Workaround': 'true',
1301 'UseUnicodeResponseFiles': 'false',
1302 'VerboseOutput': 'true'}}
1303 expected_msbuild_settings = {
1304 'ClCompile': {
1305 'AdditionalIncludeDirectories': 'dir1',
1306 'AdditionalOptions': '/more /J',
1307 'AdditionalUsingDirectories': 'test',
1308 'AssemblerListingLocation': '$(IntDir)a',
1309 'AssemblerOutput': 'AssemblyCode',
1310 'BasicRuntimeChecks': 'EnableFastChecks',
1311 'BrowseInformation': 'true',
1312 'BrowseInformationFile': '$(IntDir)e',
1313 'BufferSecurityCheck': 'false',
1314 'CallingConvention': 'FastCall',
1315 'CompileAs': 'CompileAsC',
1316 'DebugInformationFormat': 'EditAndContinue',
1317 'DisableLanguageExtensions': 'true',
1318 'DisableSpecificWarnings': 'abc',
1319 'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions',
1320 'EnableFiberSafeOptimizations': 'true',
1321 'EnablePREfast': 'true',
1322 'ErrorReporting': 'Queue',
1323 'ExceptionHandling': 'Async',
1324 'ExpandAttributedSource': 'true',
1325 'FavorSizeOrSpeed': 'Size',
1326 'FloatingPointExceptions': 'true',
1327 'FloatingPointModel': 'Strict',
1328 'ForceConformanceInForLoopScope': 'false',
1329 'ForcedIncludeFiles': 'def',
1330 'ForcedUsingFiles': 'ge',
1331 'FunctionLevelLinking': 'true',
1332 'GenerateXMLDocumentationFiles': 'true',
1333 'IgnoreStandardIncludePath': 'true',
1334 'InlineFunctionExpansion': 'OnlyExplicitInline',
1335 'IntrinsicFunctions': 'true',
1336 'MinimalRebuild': 'true',
1337 'ObjectFileName': '$(IntDir)b',
1338 'OmitDefaultLibName': 'true',
1339 'OmitFramePointers': 'true',
1340 'OpenMPSupport': 'true',
1341 'Optimization': 'Full',
1342 'PrecompiledHeader': 'NotUsing', # Actual conversion gives ''
1343 'PrecompiledHeaderFile': 'StdAfx.hd',
1344 'PrecompiledHeaderOutputFile': '$(IntDir)$(TargetName).pche',
1345 'PreprocessKeepComments': 'true',
1346 'PreprocessorDefinitions': 'WIN32;_DEBUG;_CONSOLE',
1347 'PreprocessSuppressLineNumbers': 'true',
1348 'PreprocessToFile': 'true',
1349 'ProgramDataBaseFileName': '$(IntDir)vc90b.pdb',
1350 'RuntimeLibrary': 'MultiThreadedDebugDLL',
1351 'RuntimeTypeInfo': 'false',
1352 'ShowIncludes': 'true',
1353 'SmallerTypeCheck': 'true',
1354 'StringPooling': 'true',
1355 'StructMemberAlignment': '4Bytes',
1356 'SuppressStartupBanner': 'false',
1357 'TreatWarningAsError': 'true',
1358 'TreatWChar_tAsBuiltInType': 'false',
1359 'UndefineAllPreprocessorDefinitions': 'true',
1360 'UndefinePreprocessorDefinitions': 'wer',
1361 'UseFullPaths': 'true',
1362 'WarningLevel': 'Level3',
1363 'WholeProgramOptimization': 'true',
1364 'XMLDocumentationFileName': '$(IntDir)c'},
1365 'Link': {
1366 'AdditionalDependencies': 'zx',
1367 'AdditionalLibraryDirectories': 'asd',
1368 'AdditionalManifestDependencies': 's2',
1369 'AdditionalOptions': '/mor2',
1370 'AddModuleNamesToAssembly': 'd1',
1371 'AllowIsolation': 'false',
1372 'AssemblyDebug': 'true',
1373 'AssemblyLinkResource': 'd5',
1374 'BaseAddress': '23423',
1375 'CLRImageType': 'ForceSafeILImage',
1376 'CLRThreadAttribute': 'MTAThreadingAttribute',
1377 'CLRUnmanagedCodeCheck': 'true',
1378 'DataExecutionPrevention': '',
1379 'DelayLoadDLLs': 'd4',
1380 'DelaySign': 'true',
1381 'Driver': 'UpOnly',
1382 'EmbedManagedResourceFile': 'd2',
1383 'EnableCOMDATFolding': 'false',
1384 'EnableUAC': 'false',
1385 'EntryPointSymbol': 'f5',
1386 'FixedBaseAddress': 'false',
1387 'ForceSymbolReferences': 'd3',
1388 'FunctionOrder': 'fssdfsd',
1389 'GenerateDebugInformation': 'true',
1390 'GenerateMapFile': 'true',
1391 'HeapCommitSize': '13',
1392 'HeapReserveSize': '12',
1393 'IgnoreAllDefaultLibraries': 'true',
1394 'IgnoreEmbeddedIDL': 'true',
1395 'IgnoreSpecificDefaultLibraries': 'flob;flok',
1396 'ImportLibrary': 'f4',
1397 'KeyContainer': 'f7',
1398 'KeyFile': 'f6',
1399 'LargeAddressAware': 'true',
1400 'LinkErrorReporting': 'QueueForNextLogin',
1401 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration',
1402 'ManifestFile': '$(IntDir)$(TargetFileName).2intermediate.manifest',
1403 'MapExports': 'true',
1404 'MapFileName': 'd5',
1405 'MergedIDLBaseFileName': 'f2',
1406 'MergeSections': 'f5',
1407 'MidlCommandFile': 'f1',
1408 'ModuleDefinitionFile': 'sdsd',
1409 'NoEntryPoint': 'true',
1410 'OptimizeReferences': 'true',
1411 'OutputFile': '$(OutDir)$(ProjectName)2.exe',
1412 'PerUserRedirection': 'true',
1413 'Profile': 'true',
1414 'ProfileGuidedDatabase': '$(TargetDir)$(TargetName).pgdd',
1415 'ProgramDatabaseFile': 'Flob.pdb',
1416 'RandomizedBaseAddress': 'false',
1417 'RegisterOutput': 'true',
1418 'SetChecksum': 'false',
1419 'ShowProgress': 'LinkVerbose',
1420 'StackCommitSize': '15',
1421 'StackReserveSize': '14',
1422 'StripPrivateSymbols': 'd3',
1423 'SubSystem': 'Console',
1424 'SupportUnloadOfDelayLoadedDLL': 'true',
1425 'SuppressStartupBanner': 'false',
1426 'SwapRunFromCD': 'true',
1427 'SwapRunFromNET': 'true',
1428 'TargetMachine': 'MachineX86',
1429 'TerminalServerAware': 'false',
1430 'TurnOffAssemblyGeneration': 'true',
1431 'TypeLibraryFile': 'f3',
1432 'TypeLibraryResourceID': '12',
1433 'UACExecutionLevel': 'RequireAdministrator',
1434 'UACUIAccess': 'true',
1435 'Version': '333'},
1436 'ResourceCompile': {
1437 'AdditionalIncludeDirectories': 'f3',
1438 'AdditionalOptions': '/more3',
1439 'Culture': '0x0c0c',
1440 'IgnoreStandardIncludePath': 'true',
1441 'PreprocessorDefinitions': '_UNICODE;UNICODE2',
1442 'ResourceOutputFileName': '$(IntDir)%(Filename)3.res',
1443 'ShowProgress': 'true'},
1444 'Mt': {
1445 'AdditionalManifestFiles': 'sfsdfsd',
1446 'AdditionalOptions': 'afdsdafsd',
1447 'AssemblyIdentity': 'sddfdsadfsa',
1448 'ComponentFileName': 'fsdfds',
1449 'GenerateCatalogFiles': 'true',
1450 'InputResourceManifests': 'asfsfdafs',
1451 'OutputManifestFile': '$(TargetPath).manifestdfs',
1452 'RegistrarScriptFile': 'sdfsfd',
1453 'ReplacementsFile': 'sdffsd',
1454 'SuppressStartupBanner': 'false',
1455 'TypeLibraryFile': 'sfsd',
1456 'UpdateFileHashes': 'true',
1457 'UpdateFileHashesSearchPath': 'sfsd',
1458 'VerboseOutput': 'true'},
1459 'ProjectReference': {
1460 'LinkLibraryDependencies': 'false',
1461 'UseLibraryDependencyInputs': 'true'},
1462 '': {
1463 'EmbedManifest': 'false',
1464 'GenerateManifest': 'false',
1465 'IgnoreImportLibrary': 'true',
1466 'LinkIncremental': ''
1467 },
1468 'ManifestResourceCompile': {
1469 'ResourceOutputFileName':
1470 '$(IntDir)$(TargetFileName).embed.manifest.resfdsf'}
1471 }
1472 actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
1473 msvs_settings,
1474 self.stderr)
1475 self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
1476 self._ExpectedWarnings([])
1477
1478 if __name__ == '__main__':
1479 unittest.main()
+0
-60
third_party/gyp/pylib/gyp/MSVSToolFile.py less more
0 #!/usr/bin/python2.4
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Visual Studio project reader/writer."""
7
8 import common
9 import gyp.easy_xml as easy_xml
10
11
12 class Writer(object):
13 """Visual Studio XML tool file writer."""
14
15 def __init__(self, tool_file_path, name):
16 """Initializes the tool file.
17
18 Args:
19 tool_file_path: Path to the tool file.
20 name: Name of the tool file.
21 """
22 self.tool_file_path = tool_file_path
23 self.name = name
24 self.rules_section = ['Rules']
25
26 def AddCustomBuildRule(self, name, cmd, description,
27 additional_dependencies,
28 outputs, extensions):
29 """Adds a rule to the tool file.
30
31 Args:
32 name: Name of the rule.
33 description: Description of the rule.
34 cmd: Command line of the rule.
35 additional_dependencies: other files which may trigger the rule.
36 outputs: outputs of the rule.
37 extensions: extensions handled by the rule.
38 """
39 rule = ['CustomBuildRule',
40 {'Name': name,
41 'ExecutionDescription': description,
42 'CommandLine': cmd,
43 'Outputs': ';'.join(outputs),
44 'FileExtensions': ';'.join(extensions),
45 'AdditionalDependencies':
46 ';'.join(additional_dependencies)
47 }]
48 self.rules_section.append(rule)
49
50 def WriteIfChanged(self):
51 """Writes the tool file."""
52 content = ['VisualStudioToolFile',
53 {'Version': '8.00',
54 'Name': self.name
55 },
56 self.rules_section
57 ]
58 easy_xml.WriteXmlIfChanged(content, self.tool_file_path,
59 encoding="Windows-1252")
+0
-148
third_party/gyp/pylib/gyp/MSVSUserFile.py less more
0 #!/usr/bin/python2.4
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Visual Studio user preferences file writer."""
7
8 import common
9 import os
10 import re
11 import socket # for gethostname
12 import gyp.easy_xml as easy_xml
13
14
15 #------------------------------------------------------------------------------
16
17 def _FindCommandInPath(command):
18 """If there are no slashes in the command given, this function
19 searches the PATH env to find the given command, and converts it
20 to an absolute path. We have to do this because MSVS is looking
21 for an actual file to launch a debugger on, not just a command
22 line. Note that this happens at GYP time, so anything needing to
23 be built needs to have a full path."""
24 if '/' in command or '\\' in command:
25 # If the command already has path elements (either relative or
26 # absolute), then assume it is constructed properly.
27 return command
28 else:
29 # Search through the path list and find an existing file that
30 # we can access.
31 paths = os.environ.get('PATH','').split(os.pathsep)
32 for path in paths:
33 item = os.path.join(path, command)
34 if os.path.isfile(item) and os.access(item, os.X_OK):
35 return item
36 return command
37
38 def _QuoteWin32CommandLineArgs(args):
39 new_args = []
40 for arg in args:
41 # Replace all double-quotes with double-double-quotes to escape
42 # them for cmd shell, and then quote the whole thing if there
43 # are any.
44 if arg.find('"') != -1:
45 arg = '""'.join(arg.split('"'))
46 arg = '"%s"' % arg
47
48 # Otherwise, if there are any spaces, quote the whole arg.
49 elif re.search(r'[ \t\n]', arg):
50 arg = '"%s"' % arg
51 new_args.append(arg)
52 return new_args
53
54 class Writer(object):
55 """Visual Studio XML user user file writer."""
56
57 def __init__(self, user_file_path, version, name):
58 """Initializes the user file.
59
60 Args:
61 user_file_path: Path to the user file.
62 version: Version info.
63 name: Name of the user file.
64 """
65 self.user_file_path = user_file_path
66 self.version = version
67 self.name = name
68 self.configurations = {}
69
70 def AddConfig(self, name):
71 """Adds a configuration to the project.
72
73 Args:
74 name: Configuration name.
75 """
76 self.configurations[name] = ['Configuration', {'Name': name}]
77
78 def AddDebugSettings(self, config_name, command, environment = {},
79 working_directory=""):
80 """Adds a DebugSettings node to the user file for a particular config.
81
82 Args:
83 command: command line to run. First element in the list is the
84 executable. All elements of the command will be quoted if
85 necessary.
86 working_directory: other files which may trigger the rule. (optional)
87 """
88 command = _QuoteWin32CommandLineArgs(command)
89
90 abs_command = _FindCommandInPath(command[0])
91
92 if environment and isinstance(environment, dict):
93 env_list = ['%s="%s"' % (key, val)
94 for (key,val) in environment.iteritems()]
95 environment = ' '.join(env_list)
96 else:
97 environment = ''
98
99 n_cmd = ['DebugSettings',
100 {'Command': abs_command,
101 'WorkingDirectory': working_directory,
102 'CommandArguments': " ".join(command[1:]),
103 'RemoteMachine': socket.gethostname(),
104 'Environment': environment,
105 'EnvironmentMerge': 'true',
106 # Currently these are all "dummy" values that we're just setting
107 # in the default manner that MSVS does it. We could use some of
108 # these to add additional capabilities, I suppose, but they might
109 # not have parity with other platforms then.
110 'Attach': 'false',
111 'DebuggerType': '3', # 'auto' debugger
112 'Remote': '1',
113 'RemoteCommand': '',
114 'HttpUrl': '',
115 'PDBPath': '',
116 'SQLDebugging': '',
117 'DebuggerFlavor': '0',
118 'MPIRunCommand': '',
119 'MPIRunArguments': '',
120 'MPIRunWorkingDirectory': '',
121 'ApplicationCommand': '',
122 'ApplicationArguments': '',
123 'ShimCommand': '',
124 'MPIAcceptMode': '',
125 'MPIAcceptFilter': ''
126 }]
127
128 # Find the config, and add it if it doesn't exist.
129 if config_name not in self.configurations:
130 self.AddConfig(config_name)
131
132 # Add the DebugSettings onto the appropriate config.
133 self.configurations[config_name].append(n_cmd)
134
135 def WriteIfChanged(self):
136 """Writes the user file."""
137 configs = ['Configurations']
138 for config, spec in sorted(self.configurations.iteritems()):
139 configs.append(spec)
140
141 content = ['VisualStudioUserFile',
142 {'Version': self.version.ProjectVersion(),
143 'Name': self.name
144 },
145 configs]
146 easy_xml.WriteXmlIfChanged(content, self.user_file_path,
147 encoding="Windows-1252")
+0
-262
third_party/gyp/pylib/gyp/MSVSVersion.py less more
0 #!/usr/bin/python
1 # Copyright (c) 2011 The Chromium Authors. 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 """Handle version information related to Visual Stuio."""
6
7 import errno
8 import os
9 import re
10 import subprocess
11 import sys
12
13
14 class VisualStudioVersion:
15 """Information regarding a version of Visual Studio."""
16
17 def __init__(self, short_name, description,
18 solution_version, project_version, flat_sln, uses_vcxproj):
19 self.short_name = short_name
20 self.description = description
21 self.solution_version = solution_version
22 self.project_version = project_version
23 self.flat_sln = flat_sln
24 self.uses_vcxproj = uses_vcxproj
25
26 def ShortName(self):
27 return self.short_name
28
29 def Description(self):
30 """Get the full description of the version."""
31 return self.description
32
33 def SolutionVersion(self):
34 """Get the version number of the sln files."""
35 return self.solution_version
36
37 def ProjectVersion(self):
38 """Get the version number of the vcproj or vcxproj files."""
39 return self.project_version
40
41 def FlatSolution(self):
42 return self.flat_sln
43
44 def UsesVcxproj(self):
45 """Returns true if this version uses a vcxproj file."""
46 return self.uses_vcxproj
47
48 def ProjectExtension(self):
49 """Returns the file extension for the project."""
50 return self.uses_vcxproj and '.vcxproj' or '.vcproj'
51
52 def _RegistryQueryBase(sysdir, key, value):
53 """Use reg.exe to read a particular key.
54
55 While ideally we might use the win32 module, we would like gyp to be
56 python neutral, so for instance cygwin python lacks this module.
57
58 Arguments:
59 sysdir: The system subdirectory to attempt to launch reg.exe from.
60 key: The registry key to read from.
61 value: The particular value to read.
62 Return:
63 stdout from reg.exe, or None for failure.
64 """
65 # Skip if not on Windows or Python Win32 setup issue
66 if sys.platform not in ('win32', 'cygwin'):
67 return None
68 # Setup params to pass to and attempt to launch reg.exe
69 cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'),
70 'query', key]
71 if value:
72 cmd.extend(['/v', value])
73 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
74 # Obtain the stdout from reg.exe, reading to the end so p.returncode is valid
75 # Note that the error text may be in [1] in some cases
76 text = p.communicate()[0]
77 # Check return code from reg.exe; officially 0==success and 1==error
78 if p.returncode:
79 return None
80 return text
81
82 def _RegistryQuery(key, value=None):
83 """Use reg.exe to read a particular key through _RegistryQueryBase.
84
85 First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If
86 that fails, it falls back to System32. Sysnative is available on Vista and
87 up and available on Windows Server 2003 and XP through KB patch 942589. Note
88 that Sysnative will always fail if using 64-bit python due to it being a
89 virtual directory and System32 will work correctly in the first place.
90
91 KB 942589 - http://support.microsoft.com/kb/942589/en-us.
92
93 Arguments:
94 key: The registry key.
95 value: The particular registry value to read (optional).
96 Return:
97 stdout from reg.exe, or None for failure.
98 """
99 text = None
100 try:
101 text = _RegistryQueryBase('Sysnative', key, value)
102 except OSError, e:
103 if e.errno == errno.ENOENT:
104 text = _RegistryQueryBase('System32', key, value)
105 else:
106 raise
107 return text
108
109 def _RegistryGetValue(key, value):
110 """Use reg.exe to obtain the value of a registry key.
111
112 Args:
113 key: The registry key.
114 value: The particular registry value to read.
115 Return:
116 contents of the registry key's value, or None on failure.
117 """
118 text = _RegistryQuery(key, value)
119 if not text:
120 return None
121 # Extract value.
122 match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text)
123 if not match:
124 return None
125 return match.group(1)
126
127 def _RegistryKeyExists(key):
128 """Use reg.exe to see if a key exists.
129
130 Args:
131 key: The registry key to check.
132 Return:
133 True if the key exists
134 """
135 if not _RegistryQuery(key):
136 return False
137 return True
138
139
140 def _CreateVersion(name):
141 """Sets up MSVS project generation.
142
143 Setup is based off the GYP_MSVS_VERSION environment variable or whatever is
144 autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is
145 passed in that doesn't match a value in versions python will throw a error.
146 """
147 versions = {
148 '2010': VisualStudioVersion('2010',
149 'Visual Studio 2010',
150 solution_version='11.00',
151 project_version='4.0',
152 flat_sln=False,
153 uses_vcxproj=True),
154 '2010e': VisualStudioVersion('2010e',
155 'Visual Studio 2010',
156 solution_version='11.00',
157 project_version='4.0',
158 flat_sln=True,
159 uses_vcxproj=True),
160 '2008': VisualStudioVersion('2008',
161 'Visual Studio 2008',
162 solution_version='10.00',
163 project_version='9.00',
164 flat_sln=False,
165 uses_vcxproj=False),
166 '2008e': VisualStudioVersion('2008e',
167 'Visual Studio 2008',
168 solution_version='10.00',
169 project_version='9.00',
170 flat_sln=True,
171 uses_vcxproj=False),
172 '2005': VisualStudioVersion('2005',
173 'Visual Studio 2005',
174 solution_version='9.00',
175 project_version='8.00',
176 flat_sln=False,
177 uses_vcxproj=False),
178 '2005e': VisualStudioVersion('2005e',
179 'Visual Studio 2005',
180 solution_version='9.00',
181 project_version='8.00',
182 flat_sln=True,
183 uses_vcxproj=False),
184 }
185 return versions[str(name)]
186
187
188 def _DetectVisualStudioVersions():
189 """Collect the list of installed visual studio versions.
190
191 Returns:
192 A list of visual studio versions installed in descending order of
193 usage preference.
194 Base this on the registry and a quick check if devenv.exe exists.
195 Only versions 8-10 are considered.
196 Possibilities are:
197 2005(e) - Visual Studio 2005 (8)
198 2008(e) - Visual Studio 2008 (9)
199 2010(e) - Visual Studio 2010 (10)
200 Where (e) is e for express editions of MSVS and blank otherwise.
201 """
202 version_to_year = {'8.0': '2005', '9.0': '2008', '10.0': '2010'}
203 versions = []
204 # For now, prefer versions before VS2010
205 for version in ('9.0', '8.0', '10.0'):
206 # Check if VS2010 and later is installed as specified by
207 # http://msdn.microsoft.com/en-us/library/bb164659.aspx
208 keys = [r'HKLM\SOFTWARE\Microsoft\DevDiv\VS\Servicing\%s' % version,
209 r'HKLM\SOFTWARE\Wow6432Node\Microsoft\DevDiv\VS\Servicing\%s' % (
210 version)]
211 for index in range(len(keys)):
212 if not _RegistryKeyExists(keys[index]):
213 continue
214 # Check for express
215 if _RegistryKeyExists(keys[index] + '\\expbsln'):
216 # Add this one
217 versions.append(_CreateVersion(version_to_year[version] + 'e'))
218 else:
219 # Add this one
220 versions.append(_CreateVersion(version_to_year[version]))
221
222 # Old (pre-VS2010) method of searching for which VS version is installed
223 keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version,
224 r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version,
225 r'HKLM\Software\Microsoft\VCExpress\%s' % version,
226 r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version]
227 for index in range(len(keys)):
228 path = _RegistryGetValue(keys[index], 'InstallDir')
229 if not path:
230 continue
231 # Check for full.
232 if os.path.exists(os.path.join(path, 'devenv.exe')):
233 # Add this one.
234 versions.append(_CreateVersion(version_to_year[version]))
235 # Check for express.
236 elif os.path.exists(os.path.join(path, 'vcexpress.exe')):
237 # Add this one.
238 versions.append(_CreateVersion(version_to_year[version] + 'e'))
239 return versions
240
241
242 def SelectVisualStudioVersion(version='auto'):
243 """Select which version of Visual Studio projects to generate.
244
245 Arguments:
246 version: Hook to allow caller to force a particular version (vs auto).
247 Returns:
248 An object representing a visual studio project format version.
249 """
250 # In auto mode, check environment variable for override.
251 if version == 'auto':
252 version = os.environ.get('GYP_MSVS_VERSION', 'auto')
253 # In auto mode, pick the most preferred version present.
254 if version == 'auto':
255 versions = _DetectVisualStudioVersions()
256 if not versions:
257 # Default to 2005.
258 return _CreateVersion('2005')
259 return versions[0]
260 # Convert version string into a version object.
261 return _CreateVersion(version)
+0
-200
third_party/gyp/pylib/gyp/SCons.py less more
0 #!/usr/bin/env python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 SCons generator.
8
9 This contains class definitions and supporting functions for generating
10 pieces of SCons files for the different types of GYP targets.
11 """
12
13 import os
14
15
16 def WriteList(fp, list, prefix='',
17 separator=',\n ',
18 preamble=None,
19 postamble=None):
20 fp.write(preamble or '')
21 fp.write((separator or ' ').join([prefix + l for l in list]))
22 fp.write(postamble or '')
23
24
25 class TargetBase(object):
26 """
27 Base class for a SCons representation of a GYP target.
28 """
29 is_ignored = False
30 target_prefix = ''
31 target_suffix = ''
32 def __init__(self, spec):
33 self.spec = spec
34 def full_product_name(self):
35 """
36 Returns the full name of the product being built:
37
38 * Uses 'product_name' if it's set, else prefix + 'target_name'.
39 * Prepends 'product_dir' if set.
40 * Appends SCons suffix variables for the target type (or
41 product_extension).
42 """
43 suffix = self.target_suffix
44 product_extension = self.spec.get('product_extension')
45 if product_extension:
46 suffix = '.' + product_extension
47 prefix = self.spec.get('product_prefix', self.target_prefix)
48 name = self.spec['target_name']
49 name = prefix + self.spec.get('product_name', name) + suffix
50 product_dir = self.spec.get('product_dir')
51 if product_dir:
52 name = os.path.join(product_dir, name)
53 else:
54 name = os.path.join(self.out_dir, name)
55 return name
56
57 def write_input_files(self, fp):
58 """
59 Writes the definition of the input files (sources).
60 """
61 sources = self.spec.get('sources')
62 if not sources:
63 fp.write('\ninput_files = []\n')
64 return
65 preamble = '\ninput_files = [\n '
66 postamble = ',\n]\n'
67 WriteList(fp, map(repr, sources), preamble=preamble, postamble=postamble)
68
69 def builder_call(self):
70 """
71 Returns the actual SCons builder call to build this target.
72 """
73 name = self.full_product_name()
74 return 'env.%s(env.File(%r), input_files)' % (self.builder_name, name)
75 def write_target(self, fp, src_dir='', pre=''):
76 """
77 Writes the lines necessary to build this target.
78 """
79 fp.write('\n' + pre)
80 fp.write('_outputs = %s\n' % self.builder_call())
81 fp.write('target_files.extend(_outputs)\n')
82
83
84 class NoneTarget(TargetBase):
85 """
86 A GYP target type of 'none', implicitly or explicitly.
87 """
88 def write_target(self, fp, pre=''):
89 fp.write('\ntarget_files.extend(input_files)\n')
90
91
92 class SettingsTarget(TargetBase):
93 """
94 A GYP target type of 'settings'.
95 """
96 is_ignored = True
97
98
99 compilable_sources_template = """
100 _result = []
101 for infile in input_files:
102 if env.compilable(infile):
103 if (type(infile) == type('')
104 and (infile.startswith(%(src_dir)r)
105 or not os.path.isabs(env.subst(infile)))):
106 # Force files below the build directory by replacing all '..'
107 # elements in the path with '__':
108 base, ext = os.path.splitext(os.path.normpath(infile))
109 base = [d == '..' and '__' or d for d in base.split('/')]
110 base = os.path.join(*base)
111 object = '${OBJ_DIR}/${COMPONENT_NAME}/${TARGET_NAME}/' + base
112 if not infile.startswith(%(src_dir)r):
113 infile = %(src_dir)r + infile
114 infile = env.%(name)s(object, infile)[0]
115 else:
116 infile = env.%(name)s(infile)[0]
117 _result.append(infile)
118 input_files = _result
119 """
120
121 class CompilableSourcesTargetBase(TargetBase):
122 """
123 An abstract base class for targets that compile their source files.
124
125 We explicitly transform compilable files into object files,
126 even though SCons could infer that for us, because we want
127 to control where the object file ends up. (The implicit rules
128 in SCons always put the object file next to the source file.)
129 """
130 intermediate_builder_name = None
131 def write_target(self, fp, src_dir='', pre=''):
132 if self.intermediate_builder_name is None:
133 raise NotImplementedError
134 if src_dir and not src_dir.endswith('/'):
135 src_dir += '/'
136 variables = {
137 'src_dir': src_dir,
138 'name': self.intermediate_builder_name,
139 }
140 fp.write(compilable_sources_template % variables)
141 super(CompilableSourcesTargetBase, self).write_target(fp)
142
143
144 class ProgramTarget(CompilableSourcesTargetBase):
145 """
146 A GYP target type of 'executable'.
147 """
148 builder_name = 'GypProgram'
149 intermediate_builder_name = 'StaticObject'
150 target_prefix = '${PROGPREFIX}'
151 target_suffix = '${PROGSUFFIX}'
152 out_dir = '${TOP_BUILDDIR}'
153
154
155 class StaticLibraryTarget(CompilableSourcesTargetBase):
156 """
157 A GYP target type of 'static_library'.
158 """
159 builder_name = 'GypStaticLibrary'
160 intermediate_builder_name = 'StaticObject'
161 target_prefix = '${LIBPREFIX}'
162 target_suffix = '${LIBSUFFIX}'
163 out_dir = '${LIB_DIR}'
164
165
166 class SharedLibraryTarget(CompilableSourcesTargetBase):
167 """
168 A GYP target type of 'shared_library'.
169 """
170 builder_name = 'GypSharedLibrary'
171 intermediate_builder_name = 'SharedObject'
172 target_prefix = '${SHLIBPREFIX}'
173 target_suffix = '${SHLIBSUFFIX}'
174 out_dir = '${LIB_DIR}'
175
176
177 class LoadableModuleTarget(CompilableSourcesTargetBase):
178 """
179 A GYP target type of 'loadable_module'.
180 """
181 builder_name = 'GypLoadableModule'
182 intermediate_builder_name = 'SharedObject'
183 target_prefix = '${SHLIBPREFIX}'
184 target_suffix = '${SHLIBSUFFIX}'
185 out_dir = '${TOP_BUILDDIR}'
186
187
188 TargetMap = {
189 None : NoneTarget,
190 'none' : NoneTarget,
191 'settings' : SettingsTarget,
192 'executable' : ProgramTarget,
193 'static_library' : StaticLibraryTarget,
194 'shared_library' : SharedLibraryTarget,
195 'loadable_module' : LoadableModuleTarget,
196 }
197
198 def Target(spec):
199 return TargetMap[spec.get('type')](spec)
+0
-479
third_party/gyp/pylib/gyp/__init__.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import copy
7 import gyp.input
8 import optparse
9 import os.path
10 import re
11 import shlex
12 import sys
13
14 # Default debug modes for GYP
15 debug = {}
16
17 # List of "official" debug modes, but you can use anything you like.
18 DEBUG_GENERAL = 'general'
19 DEBUG_VARIABLES = 'variables'
20 DEBUG_INCLUDES = 'includes'
21
22 def DebugOutput(mode, message):
23 if mode in gyp.debug.keys():
24 print "%s: %s" % (mode.upper(), message)
25
26 def FindBuildFiles():
27 extension = '.gyp'
28 files = os.listdir(os.getcwd())
29 build_files = []
30 for file in files:
31 if file[-len(extension):] == extension:
32 build_files.append(file)
33 return build_files
34
35
36 def Load(build_files, format, default_variables={},
37 includes=[], depth='.', params=None, check=False, circular_check=True):
38 """
39 Loads one or more specified build files.
40 default_variables and includes will be copied before use.
41 Returns the generator for the specified format and the
42 data returned by loading the specified build files.
43 """
44 if params is None:
45 params = {}
46
47 flavor = None
48 if '-' in format:
49 format, params['flavor'] = format.split('-', 1)
50
51 default_variables = copy.copy(default_variables)
52
53 # Default variables provided by this program and its modules should be
54 # named WITH_CAPITAL_LETTERS to provide a distinct "best practice" namespace,
55 # avoiding collisions with user and automatic variables.
56 default_variables['GENERATOR'] = format
57
58 generator_name = 'gyp.generator.' + format
59 # These parameters are passed in order (as opposed to by key)
60 # because ActivePython cannot handle key parameters to __import__.
61 generator = __import__(generator_name, globals(), locals(), generator_name)
62 for (key, val) in generator.generator_default_variables.items():
63 default_variables.setdefault(key, val)
64
65 # Give the generator the opportunity to set additional variables based on
66 # the params it will receive in the output phase.
67 if getattr(generator, 'CalculateVariables', None):
68 generator.CalculateVariables(default_variables, params)
69
70 # Give the generator the opportunity to set generator_input_info based on
71 # the params it will receive in the output phase.
72 if getattr(generator, 'CalculateGeneratorInputInfo', None):
73 generator.CalculateGeneratorInputInfo(params)
74
75 # Fetch the generator specific info that gets fed to input, we use getattr
76 # so we can default things and the generators only have to provide what
77 # they need.
78 generator_input_info = {
79 'generator_wants_absolute_build_file_paths':
80 getattr(generator, 'generator_wants_absolute_build_file_paths', False),
81 'generator_handles_variants':
82 getattr(generator, 'generator_handles_variants', False),
83 'non_configuration_keys':
84 getattr(generator, 'generator_additional_non_configuration_keys', []),
85 'path_sections':
86 getattr(generator, 'generator_additional_path_sections', []),
87 'extra_sources_for_rules':
88 getattr(generator, 'generator_extra_sources_for_rules', []),
89 'generator_supports_multiple_toolsets':
90 getattr(generator, 'generator_supports_multiple_toolsets', False),
91 'generator_wants_static_library_dependencies_adjusted':
92 getattr(generator,
93 'generator_wants_static_library_dependencies_adjusted', True),
94 'generator_wants_sorted_dependencies':
95 getattr(generator, 'generator_wants_sorted_dependencies', False),
96 }
97
98 # Process the input specific to this generator.
99 result = gyp.input.Load(build_files, default_variables, includes[:],
100 depth, generator_input_info, check, circular_check)
101 return [generator] + result
102
103 def NameValueListToDict(name_value_list):
104 """
105 Takes an array of strings of the form 'NAME=VALUE' and creates a dictionary
106 of the pairs. If a string is simply NAME, then the value in the dictionary
107 is set to True. If VALUE can be converted to an integer, it is.
108 """
109 result = { }
110 for item in name_value_list:
111 tokens = item.split('=', 1)
112 if len(tokens) == 2:
113 # If we can make it an int, use that, otherwise, use the string.
114 try:
115 token_value = int(tokens[1])
116 except ValueError:
117 token_value = tokens[1]
118 # Set the variable to the supplied value.
119 result[tokens[0]] = token_value
120 else:
121 # No value supplied, treat it as a boolean and set it.
122 result[tokens[0]] = True
123 return result
124
125 def ShlexEnv(env_name):
126 flags = os.environ.get(env_name, [])
127 if flags:
128 flags = shlex.split(flags)
129 return flags
130
131 def FormatOpt(opt, value):
132 if opt.startswith('--'):
133 return '%s=%s' % (opt, value)
134 return opt + value
135
136 def RegenerateAppendFlag(flag, values, predicate, env_name, options):
137 """Regenerate a list of command line flags, for an option of action='append'.
138
139 The |env_name|, if given, is checked in the environment and used to generate
140 an initial list of options, then the options that were specified on the
141 command line (given in |values|) are appended. This matches the handling of
142 environment variables and command line flags where command line flags override
143 the environment, while not requiring the environment to be set when the flags
144 are used again.
145 """
146 flags = []
147 if options.use_environment and env_name:
148 for flag_value in ShlexEnv(env_name):
149 flags.append(FormatOpt(flag, predicate(flag_value)))
150 if values:
151 for flag_value in values:
152 flags.append(FormatOpt(flag, predicate(flag_value)))
153 return flags
154
155 def RegenerateFlags(options):
156 """Given a parsed options object, and taking the environment variables into
157 account, returns a list of flags that should regenerate an equivalent options
158 object (even in the absence of the environment variables.)
159
160 Any path options will be normalized relative to depth.
161
162 The format flag is not included, as it is assumed the calling generator will
163 set that as appropriate.
164 """
165 def FixPath(path):
166 path = gyp.common.FixIfRelativePath(path, options.depth)
167 if not path:
168 return os.path.curdir
169 return path
170
171 def Noop(value):
172 return value
173
174 # We always want to ignore the environment when regenerating, to avoid
175 # duplicate or changed flags in the environment at the time of regeneration.
176 flags = ['--ignore-environment']
177 for name, metadata in options._regeneration_metadata.iteritems():
178 opt = metadata['opt']
179 value = getattr(options, name)
180 value_predicate = metadata['type'] == 'path' and FixPath or Noop
181 action = metadata['action']
182 env_name = metadata['env_name']
183 if action == 'append':
184 flags.extend(RegenerateAppendFlag(opt, value, value_predicate,
185 env_name, options))
186 elif action in ('store', None): # None is a synonym for 'store'.
187 if value:
188 flags.append(FormatOpt(opt, value_predicate(value)))
189 elif options.use_environment and env_name and os.environ.get(env_name):
190 flags.append(FormatOpt(opt, value_predicate(os.environ.get(env_name))))
191 elif action in ('store_true', 'store_false'):
192 if ((action == 'store_true' and value) or
193 (action == 'store_false' and not value)):
194 flags.append(opt)
195 elif options.use_environment and env_name:
196 print >>sys.stderr, ('Warning: environment regeneration unimplemented '
197 'for %s flag %r env_name %r' % (action, opt,
198 env_name))
199 else:
200 print >>sys.stderr, ('Warning: regeneration unimplemented for action %r '
201 'flag %r' % (action, opt))
202
203 return flags
204
205 class RegeneratableOptionParser(optparse.OptionParser):
206 def __init__(self):
207 self.__regeneratable_options = {}
208 optparse.OptionParser.__init__(self)
209
210 def add_option(self, *args, **kw):
211 """Add an option to the parser.
212
213 This accepts the same arguments as OptionParser.add_option, plus the
214 following:
215 regenerate: can be set to False to prevent this option from being included
216 in regeneration.
217 env_name: name of environment variable that additional values for this
218 option come from.
219 type: adds type='path', to tell the regenerator that the values of
220 this option need to be made relative to options.depth
221 """
222 env_name = kw.pop('env_name', None)
223 if 'dest' in kw and kw.pop('regenerate', True):
224 dest = kw['dest']
225
226 # The path type is needed for regenerating, for optparse we can just treat
227 # it as a string.
228 type = kw.get('type')
229 if type == 'path':
230 kw['type'] = 'string'
231
232 self.__regeneratable_options[dest] = {
233 'action': kw.get('action'),
234 'type': type,
235 'env_name': env_name,
236 'opt': args[0],
237 }
238
239 optparse.OptionParser.add_option(self, *args, **kw)
240
241 def parse_args(self, *args):
242 values, args = optparse.OptionParser.parse_args(self, *args)
243 values._regeneration_metadata = self.__regeneratable_options
244 return values, args
245
246 def main(args):
247 my_name = os.path.basename(sys.argv[0])
248
249 parser = RegeneratableOptionParser()
250 usage = 'usage: %s [options ...] [build_file ...]'
251 parser.set_usage(usage.replace('%s', '%prog'))
252 parser.add_option('-D', dest='defines', action='append', metavar='VAR=VAL',
253 env_name='GYP_DEFINES',
254 help='sets variable VAR to value VAL')
255 parser.add_option('-f', '--format', dest='formats', action='append',
256 env_name='GYP_GENERATORS', regenerate=False,
257 help='output formats to generate')
258 parser.add_option('--msvs-version', dest='msvs_version',
259 regenerate=False,
260 help='Deprecated; use -G msvs_version=MSVS_VERSION instead')
261 parser.add_option('-I', '--include', dest='includes', action='append',
262 metavar='INCLUDE', type='path',
263 help='files to include in all loaded .gyp files')
264 parser.add_option('--depth', dest='depth', metavar='PATH', type='path',
265 help='set DEPTH gyp variable to a relative path to PATH')
266 parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE',
267 action='append', default=[], help='turn on a debugging '
268 'mode for debugging GYP. Supported modes are "variables" '
269 'and "general"')
270 parser.add_option('-S', '--suffix', dest='suffix', default='',
271 help='suffix to add to generated files')
272 parser.add_option('-G', dest='generator_flags', action='append', default=[],
273 metavar='FLAG=VAL', env_name='GYP_GENERATOR_FLAGS',
274 help='sets generator flag FLAG to VAL')
275 parser.add_option('--generator-output', dest='generator_output',
276 action='store', default=None, metavar='DIR', type='path',
277 env_name='GYP_GENERATOR_OUTPUT',
278 help='puts generated build files under DIR')
279 parser.add_option('--ignore-environment', dest='use_environment',
280 action='store_false', default=True, regenerate=False,
281 help='do not read options from environment variables')
282 parser.add_option('--check', dest='check', action='store_true',
283 help='check format of gyp files')
284 parser.add_option('--toplevel-dir', dest='toplevel_dir', action='store',
285 default=None, metavar='DIR', type='path',
286 help='directory to use as the root of the source tree')
287 # --no-circular-check disables the check for circular relationships between
288 # .gyp files. These relationships should not exist, but they've only been
289 # observed to be harmful with the Xcode generator. Chromium's .gyp files
290 # currently have some circular relationships on non-Mac platforms, so this
291 # option allows the strict behavior to be used on Macs and the lenient
292 # behavior to be used elsewhere.
293 # TODO(mark): Remove this option when http://crbug.com/35878 is fixed.
294 parser.add_option('--no-circular-check', dest='circular_check',
295 action='store_false', default=True, regenerate=False,
296 help="don't check for circular relationships between files")
297
298 # We read a few things from ~/.gyp, so set up a var for that.
299 home_vars = ['HOME']
300 if sys.platform in ('cygwin', 'win32'):
301 home_vars.append('USERPROFILE')
302 home = None
303 home_dot_gyp = None
304 for home_var in home_vars:
305 home = os.getenv(home_var)
306 if home != None:
307 home_dot_gyp = os.path.join(home, '.gyp')
308 if not os.path.exists(home_dot_gyp):
309 home_dot_gyp = None
310 else:
311 break
312
313 # TODO(thomasvl): add support for ~/.gyp/defaults
314
315 options, build_files_arg = parser.parse_args(args)
316 build_files = build_files_arg
317
318 if not options.formats:
319 # If no format was given on the command line, then check the env variable.
320 generate_formats = []
321 if options.use_environment:
322 generate_formats = os.environ.get('GYP_GENERATORS', [])
323 if generate_formats:
324 generate_formats = re.split('[\s,]', generate_formats)
325 if generate_formats:
326 options.formats = generate_formats
327 else:
328 # Nothing in the variable, default based on platform.
329 options.formats = [ {'darwin': 'xcode',
330 'win32': 'msvs',
331 'cygwin': 'msvs',
332 'freebsd7': 'make',
333 'freebsd8': 'make',
334 'linux2': 'make',
335 'linux3': 'make',
336 'openbsd4': 'make',
337 'sunos5': 'make',}[sys.platform] ]
338
339 if not options.generator_output and options.use_environment:
340 g_o = os.environ.get('GYP_GENERATOR_OUTPUT')
341 if g_o:
342 options.generator_output = g_o
343
344 for mode in options.debug:
345 gyp.debug[mode] = 1
346
347 # Do an extra check to avoid work when we're not debugging.
348 if DEBUG_GENERAL in gyp.debug.keys():
349 DebugOutput(DEBUG_GENERAL, 'running with these options:')
350 for option, value in sorted(options.__dict__.items()):
351 if option[0] == '_':
352 continue
353 if isinstance(value, basestring):
354 DebugOutput(DEBUG_GENERAL, " %s: '%s'" % (option, value))
355 else:
356 DebugOutput(DEBUG_GENERAL, " %s: %s" % (option, str(value)))
357
358 if not build_files:
359 build_files = FindBuildFiles()
360 if not build_files:
361 print >>sys.stderr, (usage + '\n\n%s: error: no build_file') % \
362 (my_name, my_name)
363 return 1
364
365 # TODO(mark): Chromium-specific hack!
366 # For Chromium, the gyp "depth" variable should always be a relative path
367 # to Chromium's top-level "src" directory. If no depth variable was set
368 # on the command line, try to find a "src" directory by looking at the
369 # absolute path to each build file's directory. The first "src" component
370 # found will be treated as though it were the path used for --depth.
371 if not options.depth:
372 for build_file in build_files:
373 build_file_dir = os.path.abspath(os.path.dirname(build_file))
374 build_file_dir_components = build_file_dir.split(os.path.sep)
375 components_len = len(build_file_dir_components)
376 for index in xrange(components_len - 1, -1, -1):
377 if build_file_dir_components[index] == 'src':
378 options.depth = os.path.sep.join(build_file_dir_components)
379 break
380 del build_file_dir_components[index]
381
382 # If the inner loop found something, break without advancing to another
383 # build file.
384 if options.depth:
385 break
386
387 if not options.depth:
388 raise Exception, \
389 'Could not automatically locate src directory. This is a ' + \
390 'temporary Chromium feature that will be removed. Use ' + \
391 '--depth as a workaround.'
392
393 # If toplevel-dir is not set, we assume that depth is the root of our source
394 # tree.
395 if not options.toplevel_dir:
396 options.toplevel_dir = options.depth
397
398 # -D on the command line sets variable defaults - D isn't just for define,
399 # it's for default. Perhaps there should be a way to force (-F?) a
400 # variable's value so that it can't be overridden by anything else.
401 cmdline_default_variables = {}
402 defines = []
403 if options.use_environment:
404 defines += ShlexEnv('GYP_DEFINES')
405 if options.defines:
406 defines += options.defines
407 cmdline_default_variables = NameValueListToDict(defines)
408 if DEBUG_GENERAL in gyp.debug.keys():
409 DebugOutput(DEBUG_GENERAL,
410 "cmdline_default_variables: %s" % cmdline_default_variables)
411
412 # Set up includes.
413 includes = []
414
415 # If ~/.gyp/include.gypi exists, it'll be forcibly included into every
416 # .gyp file that's loaded, before anything else is included.
417 if home_dot_gyp != None:
418 default_include = os.path.join(home_dot_gyp, 'include.gypi')
419 if os.path.exists(default_include):
420 includes.append(default_include)
421
422 # Command-line --include files come after the default include.
423 if options.includes:
424 includes.extend(options.includes)
425
426 # Generator flags should be prefixed with the target generator since they
427 # are global across all generator runs.
428 gen_flags = []
429 if options.use_environment:
430 gen_flags += ShlexEnv('GYP_GENERATOR_FLAGS')
431 if options.generator_flags:
432 gen_flags += options.generator_flags
433 generator_flags = NameValueListToDict(gen_flags)
434 if DEBUG_GENERAL in gyp.debug.keys():
435 DebugOutput(DEBUG_GENERAL, "generator_flags: %s" % generator_flags)
436
437 # TODO: Remove this and the option after we've gotten folks to move to the
438 # generator flag.
439 if options.msvs_version:
440 print >>sys.stderr, \
441 'DEPRECATED: Use generator flag (-G msvs_version=' + \
442 options.msvs_version + ') instead of --msvs-version=' + \
443 options.msvs_version
444 generator_flags['msvs_version'] = options.msvs_version
445
446 # Generate all requested formats (use a set in case we got one format request
447 # twice)
448 for format in set(options.formats):
449 params = {'options': options,
450 'build_files': build_files,
451 'generator_flags': generator_flags,
452 'cwd': os.getcwd(),
453 'build_files_arg': build_files_arg,
454 'gyp_binary': sys.argv[0],
455 'home_dot_gyp': home_dot_gyp}
456
457 # Start with the default variables from the command line.
458 [generator, flat_list, targets, data] = Load(build_files, format,
459 cmdline_default_variables,
460 includes, options.depth,
461 params, options.check,
462 options.circular_check)
463
464 # TODO(mark): Pass |data| for now because the generator needs a list of
465 # build files that came in. In the future, maybe it should just accept
466 # a list, and not the whole data dict.
467 # NOTE: flat_list is the flattened dependency graph specifying the order
468 # that targets may be built. Build systems that operate serially or that
469 # need to have dependencies defined before dependents reference them should
470 # generate targets in the order specified in flat_list.
471 generator.GenerateOutput(flat_list, targets, data, params)
472
473 # Done
474 return 0
475
476
477 if __name__ == '__main__':
478 sys.exit(main(sys.argv[1:]))
+0
-362
third_party/gyp/pylib/gyp/common.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import errno
7 import filecmp
8 import os.path
9 import re
10 import tempfile
11 import sys
12
13
14 # A minimal memoizing decorator. It'll blow up if the args aren't immutable,
15 # among other "problems".
16 class memoize(object):
17 def __init__(self, func):
18 self.func = func
19 self.cache = {}
20 def __call__(self, *args):
21 try:
22 return self.cache[args]
23 except KeyError:
24 result = self.func(*args)
25 self.cache[args] = result
26 return result
27
28
29 def ExceptionAppend(e, msg):
30 """Append a message to the given exception's message."""
31 if not e.args:
32 e.args = (msg,)
33 elif len(e.args) == 1:
34 e.args = (str(e.args[0]) + ' ' + msg,)
35 else:
36 e.args = (str(e.args[0]) + ' ' + msg,) + e.args[1:]
37
38
39 def ParseQualifiedTarget(target):
40 # Splits a qualified target into a build file, target name and toolset.
41
42 # NOTE: rsplit is used to disambiguate the Windows drive letter separator.
43 target_split = target.rsplit(':', 1)
44 if len(target_split) == 2:
45 [build_file, target] = target_split
46 else:
47 build_file = None
48
49 target_split = target.rsplit('#', 1)
50 if len(target_split) == 2:
51 [target, toolset] = target_split
52 else:
53 toolset = None
54
55 return [build_file, target, toolset]
56
57
58 def ResolveTarget(build_file, target, toolset):
59 # This function resolves a target into a canonical form:
60 # - a fully defined build file, either absolute or relative to the current
61 # directory
62 # - a target name
63 # - a toolset
64 #
65 # build_file is the file relative to which 'target' is defined.
66 # target is the qualified target.
67 # toolset is the default toolset for that target.
68 [parsed_build_file, target, parsed_toolset] = ParseQualifiedTarget(target)
69
70 if parsed_build_file:
71 if build_file:
72 # If a relative path, parsed_build_file is relative to the directory
73 # containing build_file. If build_file is not in the current directory,
74 # parsed_build_file is not a usable path as-is. Resolve it by
75 # interpreting it as relative to build_file. If parsed_build_file is
76 # absolute, it is usable as a path regardless of the current directory,
77 # and os.path.join will return it as-is.
78 build_file = os.path.normpath(os.path.join(os.path.dirname(build_file),
79 parsed_build_file))
80 else:
81 build_file = parsed_build_file
82
83 if parsed_toolset:
84 toolset = parsed_toolset
85
86 return [build_file, target, toolset]
87
88
89 def BuildFile(fully_qualified_target):
90 # Extracts the build file from the fully qualified target.
91 return ParseQualifiedTarget(fully_qualified_target)[0]
92
93
94 def QualifiedTarget(build_file, target, toolset):
95 # "Qualified" means the file that a target was defined in and the target
96 # name, separated by a colon, suffixed by a # and the toolset name:
97 # /path/to/file.gyp:target_name#toolset
98 fully_qualified = build_file + ':' + target
99 if toolset:
100 fully_qualified = fully_qualified + '#' + toolset
101 return fully_qualified
102
103
104 @memoize
105 def RelativePath(path, relative_to):
106 # Assuming both |path| and |relative_to| are relative to the current
107 # directory, returns a relative path that identifies path relative to
108 # relative_to.
109
110 # Convert to absolute (and therefore normalized paths).
111 path = os.path.abspath(path)
112 relative_to = os.path.abspath(relative_to)
113
114 # Split the paths into components.
115 path_split = path.split(os.path.sep)
116 relative_to_split = relative_to.split(os.path.sep)
117
118 # Determine how much of the prefix the two paths share.
119 prefix_len = len(os.path.commonprefix([path_split, relative_to_split]))
120
121 # Put enough ".." components to back up out of relative_to to the common
122 # prefix, and then append the part of path_split after the common prefix.
123 relative_split = [os.path.pardir] * (len(relative_to_split) - prefix_len) + \
124 path_split[prefix_len:]
125
126 if len(relative_split) == 0:
127 # The paths were the same.
128 return ''
129
130 # Turn it back into a string and we're done.
131 return os.path.join(*relative_split)
132
133
134 def FixIfRelativePath(path, relative_to):
135 # Like RelativePath but returns |path| unchanged if it is absolute.
136 if os.path.isabs(path):
137 return path
138 return RelativePath(path, relative_to)
139
140
141 def UnrelativePath(path, relative_to):
142 # Assuming that |relative_to| is relative to the current directory, and |path|
143 # is a path relative to the dirname of |relative_to|, returns a path that
144 # identifies |path| relative to the current directory.
145 rel_dir = os.path.dirname(relative_to)
146 return os.path.normpath(os.path.join(rel_dir, path))
147
148
149 # re objects used by EncodePOSIXShellArgument. See IEEE 1003.1 XCU.2.2 at
150 # http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_02
151 # and the documentation for various shells.
152
153 # _quote is a pattern that should match any argument that needs to be quoted
154 # with double-quotes by EncodePOSIXShellArgument. It matches the following
155 # characters appearing anywhere in an argument:
156 # \t, \n, space parameter separators
157 # # comments
158 # $ expansions (quoted to always expand within one argument)
159 # % called out by IEEE 1003.1 XCU.2.2
160 # & job control
161 # ' quoting
162 # (, ) subshell execution
163 # *, ?, [ pathname expansion
164 # ; command delimiter
165 # <, >, | redirection
166 # = assignment
167 # {, } brace expansion (bash)
168 # ~ tilde expansion
169 # It also matches the empty string, because "" (or '') is the only way to
170 # represent an empty string literal argument to a POSIX shell.
171 #
172 # This does not match the characters in _escape, because those need to be
173 # backslash-escaped regardless of whether they appear in a double-quoted
174 # string.
175 _quote = re.compile('[\t\n #$%&\'()*;<=>?[{|}~]|^$')
176
177 # _escape is a pattern that should match any character that needs to be
178 # escaped with a backslash, whether or not the argument matched the _quote
179 # pattern. _escape is used with re.sub to backslash anything in _escape's
180 # first match group, hence the (parentheses) in the regular expression.
181 #
182 # _escape matches the following characters appearing anywhere in an argument:
183 # " to prevent POSIX shells from interpreting this character for quoting
184 # \ to prevent POSIX shells from interpreting this character for escaping
185 # ` to prevent POSIX shells from interpreting this character for command
186 # substitution
187 # Missing from this list is $, because the desired behavior of
188 # EncodePOSIXShellArgument is to permit parameter (variable) expansion.
189 #
190 # Also missing from this list is !, which bash will interpret as the history
191 # expansion character when history is enabled. bash does not enable history
192 # by default in non-interactive shells, so this is not thought to be a problem.
193 # ! was omitted from this list because bash interprets "\!" as a literal string
194 # including the backslash character (avoiding history expansion but retaining
195 # the backslash), which would not be correct for argument encoding. Handling
196 # this case properly would also be problematic because bash allows the history
197 # character to be changed with the histchars shell variable. Fortunately,
198 # as history is not enabled in non-interactive shells and
199 # EncodePOSIXShellArgument is only expected to encode for non-interactive
200 # shells, there is no room for error here by ignoring !.
201 _escape = re.compile(r'(["\\`])')
202
203 def EncodePOSIXShellArgument(argument):
204 """Encodes |argument| suitably for consumption by POSIX shells.
205
206 argument may be quoted and escaped as necessary to ensure that POSIX shells
207 treat the returned value as a literal representing the argument passed to
208 this function. Parameter (variable) expansions beginning with $ are allowed
209 to remain intact without escaping the $, to allow the argument to contain
210 references to variables to be expanded by the shell.
211 """
212
213 if not isinstance(argument, str):
214 argument = str(argument)
215
216 if _quote.search(argument):
217 quote = '"'
218 else:
219 quote = ''
220
221 encoded = quote + re.sub(_escape, r'\\\1', argument) + quote
222
223 return encoded
224
225
226 def EncodePOSIXShellList(list):
227 """Encodes |list| suitably for consumption by POSIX shells.
228
229 Returns EncodePOSIXShellArgument for each item in list, and joins them
230 together using the space character as an argument separator.
231 """
232
233 encoded_arguments = []
234 for argument in list:
235 encoded_arguments.append(EncodePOSIXShellArgument(argument))
236 return ' '.join(encoded_arguments)
237
238
239 def DeepDependencyTargets(target_dicts, roots):
240 """Returns the recursive list of target dependencies."""
241 dependencies = set()
242 pending = set(roots)
243 while pending:
244 # Pluck out one.
245 r = pending.pop()
246 # Skip if visited already.
247 if r in dependencies:
248 continue
249 # Add it.
250 dependencies.add(r)
251 # Add its children.
252 spec = target_dicts[r]
253 pending.update(set(spec.get('dependencies', [])))
254 pending.update(set(spec.get('dependencies_original', [])))
255 return list(dependencies - set(roots))
256
257
258 def BuildFileTargets(target_list, build_file):
259 """From a target_list, returns the subset from the specified build_file.
260 """
261 return [p for p in target_list if BuildFile(p) == build_file]
262
263
264 def AllTargets(target_list, target_dicts, build_file):
265 """Returns all targets (direct and dependencies) for the specified build_file.
266 """
267 bftargets = BuildFileTargets(target_list, build_file)
268 deptargets = DeepDependencyTargets(target_dicts, bftargets)
269 return bftargets + deptargets
270
271
272 def WriteOnDiff(filename):
273 """Write to a file only if the new contents differ.
274
275 Arguments:
276 filename: name of the file to potentially write to.
277 Returns:
278 A file like object which will write to temporary file and only overwrite
279 the target if it differs (on close).
280 """
281
282 class Writer:
283 """Wrapper around file which only covers the target if it differs."""
284 def __init__(self):
285 # Pick temporary file.
286 tmp_fd, self.tmp_path = tempfile.mkstemp(
287 suffix='.tmp',
288 prefix=os.path.split(filename)[1] + '.gyp.',
289 dir=os.path.split(filename)[0])
290 try:
291 self.tmp_file = os.fdopen(tmp_fd, 'wb')
292 except Exception:
293 # Don't leave turds behind.
294 os.unlink(self.tmp_path)
295 raise
296
297 def __getattr__(self, attrname):
298 # Delegate everything else to self.tmp_file
299 return getattr(self.tmp_file, attrname)
300
301 def close(self):
302 try:
303 # Close tmp file.
304 self.tmp_file.close()
305 # Determine if different.
306 same = False
307 try:
308 same = filecmp.cmp(self.tmp_path, filename, False)
309 except OSError, e:
310 if e.errno != errno.ENOENT:
311 raise
312
313 if same:
314 # The new file is identical to the old one, just get rid of the new
315 # one.
316 os.unlink(self.tmp_path)
317 else:
318 # The new file is different from the old one, or there is no old one.
319 # Rename the new file to the permanent name.
320 #
321 # tempfile.mkstemp uses an overly restrictive mode, resulting in a
322 # file that can only be read by the owner, regardless of the umask.
323 # There's no reason to not respect the umask here, which means that
324 # an extra hoop is required to fetch it and reset the new file's mode.
325 #
326 # No way to get the umask without setting a new one? Set a safe one
327 # and then set it back to the old value.
328 umask = os.umask(077)
329 os.umask(umask)
330 os.chmod(self.tmp_path, 0666 & ~umask)
331 if sys.platform == 'win32' and os.path.exists(filename):
332 # NOTE: on windows (but not cygwin) rename will not replace an
333 # existing file, so it must be preceded with a remove. Sadly there
334 # is no way to make the switch atomic.
335 os.remove(filename)
336 os.rename(self.tmp_path, filename)
337 except Exception:
338 # Don't leave turds behind.
339 os.unlink(self.tmp_path)
340 raise
341
342 return Writer()
343
344
345 # From Alex Martelli,
346 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560
347 # ASPN: Python Cookbook: Remove duplicates from a sequence
348 # First comment, dated 2001/10/13.
349 # (Also in the printed Python Cookbook.)
350
351 def uniquer(seq, idfun=None):
352 if idfun is None:
353 def idfun(x): return x
354 seen = {}
355 result = []
356 for item in seq:
357 marker = idfun(item)
358 if marker in seen: continue
359 seen[marker] = 1
360 result.append(item)
361 return result
+0
-150
third_party/gyp/pylib/gyp/easy_xml.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import re
7
8
9 def XmlToString(content, encoding='utf-8', pretty=False):
10 """ Writes the XML content to disk, touching the file only if it has changed.
11
12 Visual Studio files have a lot of pre-defined structures. This function makes
13 it easy to represent these structures as Python data structures, instead of
14 having to create a lot of function calls.
15
16 Each XML element of the content is represented as a list composed of:
17 1. The name of the element, a string,
18 2. The attributes of the element, a dictionary (optional), and
19 3+. The content of the element, if any. Strings are simple text nodes and
20 lists are child elements.
21
22 Example 1:
23 <test/>
24 becomes
25 ['test']
26
27 Example 2:
28 <myelement a='value1' b='value2'>
29 <childtype>This is</childtype>
30 <childtype>it!</childtype>
31 </myelement>
32
33 becomes
34 ['myelement', {'a':'value1', 'b':'value2'},
35 ['childtype', 'This is'],
36 ['childtype', 'it!'],
37 ]
38
39 Args:
40 content: The structured content to be converted.
41 encoding: The encoding to report on the first XML line.
42 pretty: True if we want pretty printing with indents and new lines.
43
44 Returns:
45 The XML content as a string.
46 """
47 # We create a huge list of all the elements of the file.
48 xml_parts = ['<?xml version="1.0" encoding="%s"?>' % encoding]
49 if pretty:
50 xml_parts.append('\n')
51 _ConstructContentList(xml_parts, content, pretty)
52
53 # Convert it to a string
54 return ''.join(xml_parts)
55
56
57 def _ConstructContentList(xml_parts, specification, pretty, level=0):
58 """ Appends the XML parts corresponding to the specification.
59
60 Args:
61 xml_parts: A list of XML parts to be appended to.
62 specification: The specification of the element. See EasyXml docs.
63 pretty: True if we want pretty printing with indents and new lines.
64 level: Indentation level.
65 """
66 # The first item in a specification is the name of the element.
67 if pretty:
68 indentation = ' ' * level
69 new_line = '\n'
70 else:
71 indentation = ''
72 new_line = ''
73 name = specification[0]
74 if not isinstance(name, str):
75 raise Exception('The first item of an EasyXml specification should be '
76 'a string. Specification was ' + str(specification))
77 xml_parts.append(indentation + '<' + name)
78
79 # Optionally in second position is a dictionary of the attributes.
80 rest = specification[1:]
81 if rest and isinstance(rest[0], dict):
82 for at, val in sorted(rest[0].iteritems()):
83 xml_parts.append(' %s="%s"' % (at, _XmlEscape(val)))
84 rest = rest[1:]
85 if rest:
86 xml_parts.append('>')
87 all_strings = reduce(lambda x, y: x and isinstance(y, str), rest, True)
88 multi_line = not all_strings
89 if multi_line and new_line:
90 xml_parts.append(new_line)
91 for child_spec in rest:
92 # If it's a string, append a text node.
93 # Otherwise recurse over that child definition
94 if isinstance(child_spec, str):
95 xml_parts.append(_XmlEscape(child_spec))
96 else:
97 _ConstructContentList(xml_parts, child_spec, pretty, level + 1)
98 if multi_line and indentation:
99 xml_parts.append(indentation)
100 xml_parts.append('</%s>%s' % (name, new_line))
101 else:
102 xml_parts.append('/>%s' % new_line)
103
104
105 def WriteXmlIfChanged(content, path, encoding='utf-8', pretty=False):
106 """ Writes the XML content to disk, touching the file only if it has changed.
107
108 Args:
109 content: The structured content to be written.
110 path: Location of the file.
111 encoding: The encoding to report on the first line of the XML file.
112 pretty: True if we want pretty printing with indents and new lines.
113 """
114 xml_string = XmlToString(content, encoding, pretty)
115
116 # Get the old content
117 try:
118 f = open(path, 'r')
119 existing = f.read()
120 f.close()
121 except:
122 existing = None
123
124 # It has changed, write it
125 if existing != xml_string:
126 f = open(path, 'w')
127 f.write(xml_string)
128 f.close()
129
130
131 _xml_escape_map = {
132 '"': '&quot;',
133 "'": '&apos;',
134 '<': '&lt;',
135 '>': '&gt;',
136 '&': '&amp;',
137 '\n': '&#xA;',
138 '\r': '&#xD;',
139 }
140
141
142 _xml_escape_re = re.compile(
143 "(%s)" % "|".join(map(re.escape, _xml_escape_map.keys())))
144
145
146 def _XmlEscape(value):
147 """ Escape a string for inclusion in XML."""
148 replace = lambda m: _xml_escape_map[m.string[m.start() : m.end()]]
149 return _xml_escape_re.sub(replace, value)
+0
-102
third_party/gyp/pylib/gyp/easy_xml_test.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """ Unit tests for the easy_xml.py file. """
7
8 import gyp.easy_xml as easy_xml
9 import unittest
10 import StringIO
11
12
13 class TestSequenceFunctions(unittest.TestCase):
14
15 def setUp(self):
16 self.stderr = StringIO.StringIO()
17
18 def test_EasyXml_simple(self):
19 self.assertEqual(
20 easy_xml.XmlToString(['test']),
21 '<?xml version="1.0" encoding="utf-8"?><test/>')
22
23 self.assertEqual(
24 easy_xml.XmlToString(['test'], encoding='Windows-1252'),
25 '<?xml version="1.0" encoding="Windows-1252"?><test/>')
26
27 def test_EasyXml_simple_with_attributes(self):
28 self.assertEqual(
29 easy_xml.XmlToString(['test2', {'a': 'value1', 'b': 'value2'}]),
30 '<?xml version="1.0" encoding="utf-8"?><test2 a="value1" b="value2"/>')
31
32 def test_EasyXml_escaping(self):
33 original = '<test>\'"\r&\nfoo'
34 converted = '&lt;test&gt;&apos;&quot;&#xD;&amp;&#xA;foo'
35 self.assertEqual(
36 easy_xml.XmlToString(['test3', {'a': original}, original]),
37 '<?xml version="1.0" encoding="utf-8"?><test3 a="%s">%s</test3>' %
38 (converted, converted))
39
40 def test_EasyXml_pretty(self):
41 self.assertEqual(
42 easy_xml.XmlToString(
43 ['test3',
44 ['GrandParent',
45 ['Parent1',
46 ['Child']
47 ],
48 ['Parent2']
49 ]
50 ],
51 pretty=True),
52 '<?xml version="1.0" encoding="utf-8"?>\n'
53 '<test3>\n'
54 ' <GrandParent>\n'
55 ' <Parent1>\n'
56 ' <Child/>\n'
57 ' </Parent1>\n'
58 ' <Parent2/>\n'
59 ' </GrandParent>\n'
60 '</test3>\n')
61
62
63 def test_EasyXml_complex(self):
64 # We want to create:
65 target = (
66 '<?xml version="1.0" encoding="utf-8"?>'
67 '<Project>'
68 '<PropertyGroup Label="Globals">'
69 '<ProjectGuid>{D2250C20-3A94-4FB9-AF73-11BC5B73884B}</ProjectGuid>'
70 '<Keyword>Win32Proj</Keyword>'
71 '<RootNamespace>automated_ui_tests</RootNamespace>'
72 '</PropertyGroup>'
73 '<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props"/>'
74 '<PropertyGroup '
75 'Condition="&apos;$(Configuration)|$(Platform)&apos;=='
76 '&apos;Debug|Win32&apos;" Label="Configuration">'
77 '<ConfigurationType>Application</ConfigurationType>'
78 '<CharacterSet>Unicode</CharacterSet>'
79 '</PropertyGroup>'
80 '</Project>')
81
82 xml = easy_xml.XmlToString(
83 ['Project',
84 ['PropertyGroup', {'Label': 'Globals'},
85 ['ProjectGuid', '{D2250C20-3A94-4FB9-AF73-11BC5B73884B}'],
86 ['Keyword', 'Win32Proj'],
87 ['RootNamespace', 'automated_ui_tests']
88 ],
89 ['Import', {'Project': '$(VCTargetsPath)\\Microsoft.Cpp.props'}],
90 ['PropertyGroup',
91 {'Condition': "'$(Configuration)|$(Platform)'=='Debug|Win32'",
92 'Label': 'Configuration'},
93 ['ConfigurationType', 'Application'],
94 ['CharacterSet', 'Unicode']
95 ]
96 ])
97 self.assertEqual(xml, target)
98
99
100 if __name__ == '__main__':
101 unittest.main()
+0
-0
third_party/gyp/pylib/gyp/generator/__init__.py less more
(Empty file)
+0
-65
third_party/gyp/pylib/gyp/generator/dump_dependency_json.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import collections
7 import gyp
8 import gyp.common
9 import json
10
11 generator_wants_static_library_dependencies_adjusted = False
12
13 generator_default_variables = {
14 'OS': 'linux',
15 }
16 for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR',
17 'LIB_DIR', 'SHARED_LIB_DIR']:
18 # Some gyp steps fail if these are empty(!).
19 generator_default_variables[dirname] = 'dir'
20 for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
21 'RULE_INPUT_EXT',
22 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX',
23 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX',
24 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX',
25 'LINKER_SUPPORTS_ICF']:
26 generator_default_variables[unused] = ''
27
28
29 def CalculateVariables(default_variables, params):
30 generator_flags = params.get('generator_flags', {})
31 default_variables['OS'] = generator_flags.get('os', 'linux')
32
33
34 def CalculateGeneratorInputInfo(params):
35 """Calculate the generator specific info that gets fed to input (called by
36 gyp)."""
37 generator_flags = params.get('generator_flags', {})
38 if generator_flags.get('adjust_static_libraries', False):
39 global generator_wants_static_library_dependencies_adjusted
40 generator_wants_static_library_dependencies_adjusted = True
41
42
43 def GenerateOutput(target_list, target_dicts, data, params):
44 # Map of target -> list of targets it depends on.
45 edges = {}
46
47 # Queue of targets to visit.
48 targets_to_visit = target_list[:]
49
50 while len(targets_to_visit) > 0:
51 target = targets_to_visit.pop()
52 if target in edges:
53 continue
54 edges[target] = []
55
56 for dep in target_dicts[target].get('dependencies', []):
57 edges[target].append(dep)
58 targets_to_visit.append(dep)
59
60 filename = 'dump.json'
61 f = open(filename, 'w')
62 json.dump(edges, f)
63 f.close()
64 print 'Wrote json to %s.' % filename
+0
-88
third_party/gyp/pylib/gyp/generator/gypd.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """gypd output module
7
8 This module produces gyp input as its output. Output files are given the
9 .gypd extension to avoid overwriting the .gyp files that they are generated
10 from. Internal references to .gyp files (such as those found in
11 "dependencies" sections) are not adjusted to point to .gypd files instead;
12 unlike other paths, which are relative to the .gyp or .gypd file, such paths
13 are relative to the directory from which gyp was run to create the .gypd file.
14
15 This generator module is intended to be a sample and a debugging aid, hence
16 the "d" for "debug" in .gypd. It is useful to inspect the results of the
17 various merges, expansions, and conditional evaluations performed by gyp
18 and to see a representation of what would be fed to a generator module.
19
20 It's not advisable to rename .gypd files produced by this module to .gyp,
21 because they will have all merges, expansions, and evaluations already
22 performed and the relevant constructs not present in the output; paths to
23 dependencies may be wrong; and various sections that do not belong in .gyp
24 files such as such as "included_files" and "*_excluded" will be present.
25 Output will also be stripped of comments. This is not intended to be a
26 general-purpose gyp pretty-printer; for that, you probably just want to
27 run "pprint.pprint(eval(open('source.gyp').read()))", which will still strip
28 comments but won't do all of the other things done to this module's output.
29
30 The specific formatting of the output generated by this module is subject
31 to change.
32 """
33
34
35 import gyp.common
36 import errno
37 import os
38 import pprint
39
40
41 # These variables should just be spit back out as variable references.
42 _generator_identity_variables = [
43 'EXECUTABLE_PREFIX',
44 'EXECUTABLE_SUFFIX',
45 'INTERMEDIATE_DIR',
46 'PRODUCT_DIR',
47 'RULE_INPUT_ROOT',
48 'RULE_INPUT_EXT',
49 'RULE_INPUT_NAME',
50 'RULE_INPUT_PATH',
51 'SHARED_INTERMEDIATE_DIR',
52 ]
53
54 # gypd doesn't define a default value for OS like many other generator
55 # modules. Specify "-D OS=whatever" on the command line to provide a value.
56 generator_default_variables = {
57 }
58
59 # gypd supports multiple toolsets
60 generator_supports_multiple_toolsets = True
61
62 # TODO(mark): This always uses <, which isn't right. The input module should
63 # notify the generator to tell it which phase it is operating in, and this
64 # module should use < for the early phase and then switch to > for the late
65 # phase. Bonus points for carrying @ back into the output too.
66 for v in _generator_identity_variables:
67 generator_default_variables[v] = '<(%s)' % v
68
69
70 def GenerateOutput(target_list, target_dicts, data, params):
71 output_files = {}
72 for qualified_target in target_list:
73 [input_file, target] = \
74 gyp.common.ParseQualifiedTarget(qualified_target)[0:2]
75
76 if input_file[-4:] != '.gyp':
77 continue
78 input_file_stem = input_file[:-4]
79 output_file = input_file_stem + params['options'].suffix + '.gypd'
80
81 if not output_file in output_files:
82 output_files[output_file] = input_file
83
84 for output_file, input_file in output_files.iteritems():
85 output = open(output_file, 'w')
86 pprint.pprint(data[input_file], output)
87 output.close()
+0
-57
third_party/gyp/pylib/gyp/generator/gypsh.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """gypsh output module
7
8 gypsh is a GYP shell. It's not really a generator per se. All it does is
9 fire up an interactive Python session with a few local variables set to the
10 variables passed to the generator. Like gypd, it's intended as a debugging
11 aid, to facilitate the exploration of .gyp structures after being processed
12 by the input module.
13
14 The expected usage is "gyp -f gypsh -D OS=desired_os".
15 """
16
17
18 import code
19 import sys
20
21
22 # All of this stuff about generator variables was lovingly ripped from gypd.py.
23 # That module has a much better description of what's going on and why.
24 _generator_identity_variables = [
25 'EXECUTABLE_PREFIX',
26 'EXECUTABLE_SUFFIX',
27 'INTERMEDIATE_DIR',
28 'PRODUCT_DIR',
29 'RULE_INPUT_ROOT',
30 'RULE_INPUT_EXT',
31 'RULE_INPUT_NAME',
32 'RULE_INPUT_PATH',
33 'SHARED_INTERMEDIATE_DIR',
34 ]
35
36 generator_default_variables = {
37 }
38
39 for v in _generator_identity_variables:
40 generator_default_variables[v] = '<(%s)' % v
41
42
43 def GenerateOutput(target_list, target_dicts, data, params):
44 locals = {
45 'target_list': target_list,
46 'target_dicts': target_dicts,
47 'data': data,
48 }
49
50 # Use a banner that looks like the stock Python one and like what
51 # code.interact uses by default, but tack on something to indicate what
52 # locals are available, and identify gypsh.
53 banner='Python %s on %s\nlocals.keys() = %s\ngypsh' % \
54 (sys.version, sys.platform, repr(sorted(locals.keys())))
55
56 code.interact(banner, local=locals)
+0
-2624
third_party/gyp/pylib/gyp/generator/make.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 # Notes:
7 #
8 # This is all roughly based on the Makefile system used by the Linux
9 # kernel, but is a non-recursive make -- we put the entire dependency
10 # graph in front of make and let it figure it out.
11 #
12 # The code below generates a separate .mk file for each target, but
13 # all are sourced by the top-level Makefile. This means that all
14 # variables in .mk-files clobber one another. Be careful to use :=
15 # where appropriate for immediate evaluation, and similarly to watch
16 # that you're not relying on a variable value to last beween different
17 # .mk files.
18 #
19 # TODOs:
20 #
21 # Global settings and utility functions are currently stuffed in the
22 # toplevel Makefile. It may make sense to generate some .mk files on
23 # the side to keep the the files readable.
24
25 import gyp
26 import gyp.common
27 import gyp.system_test
28 import os.path
29 import os
30 import sys
31
32 # Debugging-related imports -- remove me once we're solid.
33 import code
34 import pprint
35
36 generator_default_variables = {
37 'EXECUTABLE_PREFIX': '',
38 'EXECUTABLE_SUFFIX': '',
39 'STATIC_LIB_PREFIX': 'lib',
40 'SHARED_LIB_PREFIX': 'lib',
41 'STATIC_LIB_SUFFIX': '.a',
42 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/geni',
43 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen',
44 'PRODUCT_DIR': '$(builddir)',
45 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python.
46 'RULE_INPUT_PATH': '$(abspath $<)',
47 'RULE_INPUT_EXT': '$(suffix $<)',
48 'RULE_INPUT_NAME': '$(notdir $<)',
49
50 # This appears unused --- ?
51 'CONFIGURATION_NAME': '$(BUILDTYPE)',
52 }
53
54 # Make supports multiple toolsets
55 generator_supports_multiple_toolsets = True
56
57 # Request sorted dependencies in the order from dependents to dependencies.
58 generator_wants_sorted_dependencies = False
59
60
61 def GetFlavor(params):
62 """Returns |params.flavor| if it's set, the system's default flavor else."""
63 return params.get('flavor', 'mac' if sys.platform == 'darwin' else 'linux')
64
65
66 def CalculateVariables(default_variables, params):
67 """Calculate additional variables for use in the build (called by gyp)."""
68 cc_target = os.environ.get('CC.target', os.environ.get('CC', 'cc'))
69 default_variables['LINKER_SUPPORTS_ICF'] = \
70 gyp.system_test.TestLinkerSupportsICF(cc_command=cc_target)
71
72 if GetFlavor(params) == 'mac':
73 default_variables.setdefault('OS', 'mac')
74 default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib')
75 default_variables.setdefault('SHARED_LIB_DIR',
76 generator_default_variables['PRODUCT_DIR'])
77 default_variables.setdefault('LIB_DIR',
78 generator_default_variables['PRODUCT_DIR'])
79
80 # Copy additional generator configuration data from Xcode, which is shared
81 # by the Mac Make generator.
82 import gyp.generator.xcode as xcode_generator
83 global generator_additional_non_configuration_keys
84 generator_additional_non_configuration_keys = getattr(xcode_generator,
85 'generator_additional_non_configuration_keys', [])
86 global generator_additional_path_sections
87 generator_additional_path_sections = getattr(xcode_generator,
88 'generator_additional_path_sections', [])
89 global generator_extra_sources_for_rules
90 generator_extra_sources_for_rules = getattr(xcode_generator,
91 'generator_extra_sources_for_rules', [])
92 global COMPILABLE_EXTENSIONS
93 COMPILABLE_EXTENSIONS.update({'.m': 'objc', '.mm' : 'objcxx'})
94 else:
95 default_variables.setdefault('OS', 'linux')
96 default_variables.setdefault('SHARED_LIB_SUFFIX', '.so')
97 default_variables.setdefault('SHARED_LIB_DIR','$(builddir)/lib.$(TOOLSET)')
98 default_variables.setdefault('LIB_DIR', '$(obj).$(TOOLSET)')
99
100
101 def CalculateGeneratorInputInfo(params):
102 """Calculate the generator specific info that gets fed to input (called by
103 gyp)."""
104 generator_flags = params.get('generator_flags', {})
105 android_ndk_version = generator_flags.get('android_ndk_version', None)
106 # Android NDK requires a strict link order.
107 if android_ndk_version:
108 global generator_wants_sorted_dependencies
109 generator_wants_sorted_dependencies = True
110
111
112 def ensure_directory_exists(path):
113 dir = os.path.dirname(path)
114 if dir and not os.path.exists(dir):
115 os.makedirs(dir)
116
117
118 # The .d checking code below uses these functions:
119 # wildcard, sort, foreach, shell, wordlist
120 # wildcard can handle spaces, the rest can't.
121 # Since I could find no way to make foreach work with spaces in filenames
122 # correctly, the .d files have spaces replaced with another character. The .d
123 # file for
124 # Chromium\ Framework.framework/foo
125 # is for example
126 # out/Release/.deps/out/Release/Chromium?Framework.framework/foo
127 # This is the replacement character.
128 SPACE_REPLACEMENT = '?'
129
130
131 LINK_COMMANDS_LINUX = """\
132 quiet_cmd_alink = AR($(TOOLSET)) $@
133 cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) $(ARFLAGS.$(TOOLSET)) $@ $(filter %.o,$^)
134
135 # Due to circular dependencies between libraries :(, we wrap the
136 # special "figure out circular dependencies" flags around the entire
137 # input list during linking.
138 quiet_cmd_link = LINK($(TOOLSET)) $@
139 cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
140
141 # We support two kinds of shared objects (.so):
142 # 1) shared_library, which is just bundling together many dependent libraries
143 # into a link line.
144 # 2) loadable_module, which is generating a module intended for dlopen().
145 #
146 # They differ only slightly:
147 # In the former case, we want to package all dependent code into the .so.
148 # In the latter case, we want to package just the API exposed by the
149 # outermost module.
150 # This means shared_library uses --whole-archive, while loadable_module doesn't.
151 # (Note that --whole-archive is incompatible with the --start-group used in
152 # normal linking.)
153
154 # Other shared-object link notes:
155 # - Set SONAME to the library filename so our binaries don't reference
156 # the local, absolute paths used on the link command-line.
157 quiet_cmd_solink = SOLINK($(TOOLSET)) $@
158 cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
159
160 quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
161 cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
162 """
163
164 LINK_COMMANDS_MAC = """\
165 quiet_cmd_alink = LIBTOOL-STATIC $@
166 cmd_alink = rm -f $@ && libtool -static -o $@ $(filter %.o,$^)
167
168 quiet_cmd_link = LINK($(TOOLSET)) $@
169 cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
170
171 # TODO(thakis): Find out and document the difference between shared_library and
172 # loadable_module on mac.
173 quiet_cmd_solink = SOLINK($(TOOLSET)) $@
174 cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
175
176 # TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
177 # -bundle -single_module here (for osmesa.so).
178 quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
179 cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
180 """
181
182 # Header of toplevel Makefile.
183 # This should go into the build tree, but it's easier to keep it here for now.
184 SHARED_HEADER = ("""\
185 # We borrow heavily from the kernel build setup, though we are simpler since
186 # we don't have Kconfig tweaking settings on us.
187
188 # The implicit make rules have it looking for RCS files, among other things.
189 # We instead explicitly write all the rules we care about.
190 # It's even quicker (saves ~200ms) to pass -r on the command line.
191 MAKEFLAGS=-r
192
193 # The source directory tree.
194 srcdir := %(srcdir)s
195
196 # The name of the builddir.
197 builddir_name ?= %(builddir)s
198
199 # The V=1 flag on command line makes us verbosely print command lines.
200 ifdef V
201 quiet=
202 else
203 quiet=quiet_
204 endif
205
206 # Specify BUILDTYPE=Release on the command line for a release build.
207 BUILDTYPE ?= %(default_configuration)s
208
209 # Directory all our build output goes into.
210 # Note that this must be two directories beneath src/ for unit tests to pass,
211 # as they reach into the src/ directory for data with relative paths.
212 builddir ?= $(builddir_name)/$(BUILDTYPE)
213 abs_builddir := $(abspath $(builddir))
214 depsdir := $(builddir)/.deps
215
216 # Object output directory.
217 obj := $(builddir)/obj
218 abs_obj := $(abspath $(obj))
219
220 # We build up a list of every single one of the targets so we can slurp in the
221 # generated dependency rule Makefiles in one pass.
222 all_deps :=
223
224 # C++ apps need to be linked with g++. Not sure what's appropriate.
225 #
226 # Note, the flock is used to seralize linking. Linking is a memory-intensive
227 # process so running parallel links can often lead to thrashing. To disable
228 # the serialization, override FLOCK via an envrionment variable as follows:
229 #
230 # export FLOCK=
231 #
232 # This will allow make to invoke N linker processes as specified in -jN.
233 FLOCK ?= %(flock)s $(builddir)/linker.lock
234
235 %(make_global_settings)s
236
237 LINK ?= $(FLOCK) $(CXX)
238 CC.target ?= $(CC)
239 CFLAGS.target ?= $(CFLAGS)
240 CXX.target ?= $(CXX)
241 CXXFLAGS.target ?= $(CXXFLAGS)
242 LINK.target ?= $(LINK)
243 LDFLAGS.target ?= $(LDFLAGS) %(LINK_flags)s
244 AR.target ?= $(AR)
245 ARFLAGS.target ?= %(ARFLAGS.target)s
246
247 # N.B.: the logic of which commands to run should match the computation done
248 # in gyp's make.py where ARFLAGS.host etc. is computed.
249 # TODO(evan): move all cross-compilation logic to gyp-time so we don't need
250 # to replicate this environment fallback in make as well.
251 CC.host ?= gcc
252 CFLAGS.host ?=
253 CXX.host ?= g++
254 CXXFLAGS.host ?=
255 LINK.host ?= g++
256 LDFLAGS.host ?=
257 AR.host ?= ar
258 ARFLAGS.host := %(ARFLAGS.host)s
259
260 # Define a dir function that can handle spaces.
261 # http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
262 # "leading spaces cannot appear in the text of the first argument as written.
263 # These characters can be put into the argument value by variable substitution."
264 empty :=
265 space := $(empty) $(empty)
266
267 # http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
268 replace_spaces = $(subst $(space),""" + SPACE_REPLACEMENT + """,$1)
269 unreplace_spaces = $(subst """ + SPACE_REPLACEMENT + """,$(space),$1)
270 dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
271
272 # Flags to make gcc output dependency info. Note that you need to be
273 # careful here to use the flags that ccache and distcc can understand.
274 # We write to a dep file on the side first and then rename at the end
275 # so we can't end up with a broken dep file.
276 depfile = $(depsdir)/$(call replace_spaces,$@).d
277 DEPFLAGS = -MMD -MF $(depfile).raw
278
279 # We have to fixup the deps output in a few ways.
280 # (1) the file output should mention the proper .o file.
281 # ccache or distcc lose the path to the target, so we convert a rule of
282 # the form:
283 # foobar.o: DEP1 DEP2
284 # into
285 # path/to/foobar.o: DEP1 DEP2
286 # (2) we want missing files not to cause us to fail to build.
287 # We want to rewrite
288 # foobar.o: DEP1 DEP2 \\
289 # DEP3
290 # to
291 # DEP1:
292 # DEP2:
293 # DEP3:
294 # so if the files are missing, they're just considered phony rules.
295 # We have to do some pretty insane escaping to get those backslashes
296 # and dollar signs past make, the shell, and sed at the same time.
297 # Doesn't work with spaces, but that's fine: .d files have spaces in
298 # their names replaced with other characters."""
299 r"""
300 define fixup_dep
301 # The depfile may not exist if the input file didn't have any #includes.
302 touch $(depfile).raw
303 # Fixup path as in (1).
304 sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
305 # Add extra rules as in (2).
306 # We remove slashes and replace spaces with new lines;
307 # remove blank lines;
308 # delete the first line and append a colon to the remaining lines.
309 sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
310 grep -v '^$$' |\
311 sed -e 1d -e 's|$$|:|' \
312 >> $(depfile)
313 rm $(depfile).raw
314 endef
315 """
316 """
317 # Command definitions:
318 # - cmd_foo is the actual command to run;
319 # - quiet_cmd_foo is the brief-output summary of the command.
320
321 quiet_cmd_cc = CC($(TOOLSET)) $@
322 cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
323
324 quiet_cmd_cxx = CXX($(TOOLSET)) $@
325 cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
326 %(mac_commands)s
327 quiet_cmd_touch = TOUCH $@
328 cmd_touch = touch $@
329
330 quiet_cmd_copy = COPY $@
331 # send stderr to /dev/null to ignore messages when linking directories.
332 cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
333
334 %(link_commands)s
335 """
336
337 r"""
338 # Define an escape_quotes function to escape single quotes.
339 # This allows us to handle quotes properly as long as we always use
340 # use single quotes and escape_quotes.
341 escape_quotes = $(subst ','\'',$(1))
342 # This comment is here just to include a ' to unconfuse syntax highlighting.
343 # Define an escape_vars function to escape '$' variable syntax.
344 # This allows us to read/write command lines with shell variables (e.g.
345 # $LD_LIBRARY_PATH), without triggering make substitution.
346 escape_vars = $(subst $$,$$$$,$(1))
347 # Helper that expands to a shell command to echo a string exactly as it is in
348 # make. This uses printf instead of echo because printf's behaviour with respect
349 # to escape sequences is more portable than echo's across different shells
350 # (e.g., dash, bash).
351 exact_echo = printf '%%s\n' '$(call escape_quotes,$(1))'
352 """
353 """
354 # Helper to compare the command we're about to run against the command
355 # we logged the last time we ran the command. Produces an empty
356 # string (false) when the commands match.
357 # Tricky point: Make has no string-equality test function.
358 # The kernel uses the following, but it seems like it would have false
359 # positives, where one string reordered its arguments.
360 # arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \\
361 # $(filter-out $(cmd_$@), $(cmd_$(1))))
362 # We instead substitute each for the empty string into the other, and
363 # say they're equal if both substitutions produce the empty string.
364 # .d files contain """ + SPACE_REPLACEMENT + \
365 """ instead of spaces, take that into account.
366 command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\\
367 $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
368
369 # Helper that is non-empty when a prerequisite changes.
370 # Normally make does this implicitly, but we force rules to always run
371 # so we can check their command lines.
372 # $? -- new prerequisites
373 # $| -- order-only dependencies
374 prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
375
376 # do_cmd: run a command via the above cmd_foo names, if necessary.
377 # Should always run for a given target to handle command-line changes.
378 # Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
379 # Third argument, if non-zero, makes it do POSTBUILDS processing.
380 # Note: We intentionally do NOT call dirx for depfile, since it contains """ + \
381 SPACE_REPLACEMENT + """ for
382 # spaces already and dirx strips the """ + SPACE_REPLACEMENT + \
383 """ characters.
384 define do_cmd
385 $(if $(or $(command_changed),$(prereq_changed)),
386 @$(call exact_echo, $($(quiet)cmd_$(1)))
387 @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
388 $(if $(findstring flock,$(word %(flock_index)d,$(cmd_$1))),
389 @$(cmd_$(1))
390 @echo " $(quiet_cmd_$(1)): Finished",
391 @$(cmd_$(1))
392 )
393 @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
394 @$(if $(2),$(fixup_dep))
395 $(if $(and $(3), $(POSTBUILDS)),
396 @for p in $(POSTBUILDS); do eval $$p; done
397 )
398 )
399 endef
400
401 # Declare "all" target first so it is the default, even though we don't have the
402 # deps yet.
403 .PHONY: all
404 all:
405
406 # Use FORCE_DO_CMD to force a target to run. Should be coupled with
407 # do_cmd.
408 .PHONY: FORCE_DO_CMD
409 FORCE_DO_CMD:
410
411 """)
412
413 SHARED_HEADER_MAC_COMMANDS = """
414 quiet_cmd_objc = CXX($(TOOLSET)) $@
415 cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
416
417 quiet_cmd_objcxx = CXX($(TOOLSET)) $@
418 cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
419
420 # Commands for precompiled header files.
421 quiet_cmd_pch_c = CXX($(TOOLSET)) $@
422 cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
423 quiet_cmd_pch_cc = CXX($(TOOLSET)) $@
424 cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CCFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
425 quiet_cmd_pch_m = CXX($(TOOLSET)) $@
426 cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
427 quiet_cmd_pch_mm = CXX($(TOOLSET)) $@
428 cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
429
430 # gyp-mac-tool is written next to the root Makefile by gyp.
431 # Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
432 # already.
433 quiet_cmd_mac_tool = MACTOOL $(4) $<
434 cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
435
436 quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
437 cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
438 """
439
440
441 def WriteRootHeaderSuffixRules(writer):
442 extensions = sorted(COMPILABLE_EXTENSIONS.keys(), key=str.lower)
443
444 writer.write('# Suffix rules, putting all outputs into $(obj).\n')
445 for ext in extensions:
446 writer.write('$(obj).$(TOOLSET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD\n' % ext)
447 writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext])
448
449 writer.write('\n# Try building from generated source, too.\n')
450 for ext in extensions:
451 writer.write(
452 '$(obj).$(TOOLSET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD\n' % ext)
453 writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext])
454 writer.write('\n')
455 for ext in extensions:
456 writer.write('$(obj).$(TOOLSET)/%%.o: $(obj)/%%%s FORCE_DO_CMD\n' % ext)
457 writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext])
458 writer.write('\n')
459
460
461 SHARED_HEADER_SUFFIX_RULES_COMMENT1 = ("""\
462 # Suffix rules, putting all outputs into $(obj).
463 """)
464
465
466 SHARED_HEADER_SUFFIX_RULES_COMMENT2 = ("""\
467 # Try building from generated source, too.
468 """)
469
470
471 SHARED_FOOTER = """\
472 # "all" is a concatenation of the "all" targets from all the included
473 # sub-makefiles. This is just here to clarify.
474 all:
475
476 # Add in dependency-tracking rules. $(all_deps) is the list of every single
477 # target in our tree. Only consider the ones with .d (dependency) info:
478 d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
479 ifneq ($(d_files),)
480 # Rather than include each individual .d file, concatenate them into a
481 # single file which make is able to load faster. We split this into
482 # commands that take 1000 files at a time to avoid overflowing the
483 # command line.
484 $(shell cat $(wordlist 1,1000,$(d_files)) > $(depsdir)/all.deps)
485 %(generate_all_deps)s
486 # make looks for ways to re-generate included makefiles, but in our case, we
487 # don't have a direct way. Explicitly telling make that it has nothing to do
488 # for them makes it go faster.
489 $(depsdir)/all.deps: ;
490
491 include $(depsdir)/all.deps
492 endif
493 """
494
495 header = """\
496 # This file is generated by gyp; do not edit.
497
498 """
499
500 # Maps every compilable file extension to the do_cmd that compiles it.
501 COMPILABLE_EXTENSIONS = {
502 '.c': 'cc',
503 '.cc': 'cxx',
504 '.cpp': 'cxx',
505 '.cxx': 'cxx',
506 '.s': 'cc',
507 '.S': 'cc',
508 }
509
510 def Compilable(filename):
511 """Return true if the file is compilable (should be in OBJS)."""
512 for res in (filename.endswith(e) for e in COMPILABLE_EXTENSIONS):
513 if res:
514 return True
515 return False
516
517
518 def Linkable(filename):
519 """Return true if the file is linkable (should be on the link line)."""
520 return filename.endswith('.o')
521
522
523 def Target(filename):
524 """Translate a compilable filename to its .o target."""
525 return os.path.splitext(filename)[0] + '.o'
526
527
528 def EscapeShellArgument(s):
529 """Quotes an argument so that it will be interpreted literally by a POSIX
530 shell. Taken from
531 http://stackoverflow.com/questions/35817/whats-the-best-way-to-escape-ossystem-calls-in-python
532 """
533 return "'" + s.replace("'", "'\\''") + "'"
534
535
536 def EscapeMakeVariableExpansion(s):
537 """Make has its own variable expansion syntax using $. We must escape it for
538 string to be interpreted literally."""
539 return s.replace('$', '$$')
540
541
542 def EscapeCppDefine(s):
543 """Escapes a CPP define so that it will reach the compiler unaltered."""
544 s = EscapeShellArgument(s)
545 s = EscapeMakeVariableExpansion(s)
546 return s
547
548
549 def QuoteIfNecessary(string):
550 """TODO: Should this ideally be replaced with one or more of the above
551 functions?"""
552 if '"' in string:
553 string = '"' + string.replace('"', '\\"') + '"'
554 return string
555
556
557 def StringToMakefileVariable(string):
558 """Convert a string to a value that is acceptable as a make variable name."""
559 # TODO: replace other metacharacters that we encounter.
560 return string.replace(' ', '_')
561
562
563 srcdir_prefix = ''
564 def Sourceify(path):
565 """Convert a path to its source directory form."""
566 if '$(' in path:
567 return path
568 if os.path.isabs(path):
569 return path
570 return srcdir_prefix + path
571
572
573 def QuoteSpaces(s):
574 return s.replace(' ', r'\ ')
575
576
577 def ReplaceQuotedSpaces(s):
578 return s.replace(r'\ ', SPACE_REPLACEMENT)
579
580
581 # Map from qualified target to path to output.
582 target_outputs = {}
583 # Map from qualified target to any linkable output. A subset
584 # of target_outputs. E.g. when mybinary depends on liba, we want to
585 # include liba in the linker line; when otherbinary depends on
586 # mybinary, we just want to build mybinary first.
587 target_link_deps = {}
588
589
590 class XcodeSettings(object):
591 """A class that understands the gyp 'xcode_settings' object."""
592
593 def __init__(self, spec):
594 self.spec = spec
595
596 # Per-target 'xcode_settings' are pushed down into configs earlier by gyp.
597 # This means self.xcode_settings[config] always contains all settings
598 # for that config -- the per-target settings as well. Settings that are
599 # the same for all configs are implicitly per-target settings.
600 self.xcode_settings = {}
601 configs = spec['configurations']
602 for configname, config in configs.iteritems():
603 self.xcode_settings[configname] = config.get('xcode_settings', {})
604
605 # This is only non-None temporarily during the execution of some methods.
606 self.configname = None
607
608 def _Settings(self):
609 assert self.configname
610 return self.xcode_settings[self.configname]
611
612 def _Test(self, test_key, cond_key, default):
613 return self._Settings().get(test_key, default) == cond_key
614
615 def _Appendf(self, lst, test_key, format_str):
616 if test_key in self._Settings():
617 lst.append(format_str % str(self._Settings()[test_key]))
618
619 def _WarnUnimplemented(self, test_key):
620 if test_key in self._Settings():
621 print 'Warning: Ignoring not yet implemented key "%s".' % test_key
622
623 def _IsBundle(self):
624 return int(self.spec.get('mac_bundle', 0)) != 0
625
626 def GetFrameworkVersion(self):
627 """Returns the framework version of the current target. Only valid for
628 bundles."""
629 assert self._IsBundle()
630 return self.GetPerTargetSetting('FRAMEWORK_VERSION', default='A')
631
632 def GetWrapperExtension(self):
633 """Returns the bundle extension (.app, .framework, .plugin, etc). Only
634 valid for bundles."""
635 assert self._IsBundle()
636 if self.spec['type'] in ('loadable_module', 'shared_library'):
637 wrapper_extension = self.GetPerTargetSetting(
638 'WRAPPER_EXTENSION', default='framework')
639 return '.' + self.spec.get('product_extension', wrapper_extension)
640 elif self.spec['type'] == 'executable':
641 return '.app'
642 else:
643 assert False, "Don't know extension for '%s', target '%s'" % (
644 self.spec['type'], self.spec['target_name'])
645
646 def GetProductName(self):
647 """Returns PRODUCT_NAME."""
648 return self.spec.get('product_name', self.spec['target_name'])
649
650 def GetWrapperName(self):
651 """Returns the directory name of the bundle represented by this target.
652 Only valid for bundles."""
653 assert self._IsBundle()
654 return self.GetProductName() + self.GetWrapperExtension()
655
656 def GetBundleContentsFolderPath(self):
657 """Returns the qualified path to the bundle's contents folder. E.g.
658 Chromium.app/Contents or Foo.bundle/Versions/A. Only valid for bundles."""
659 assert self._IsBundle()
660 if self.spec['type'] == 'shared_library':
661 return os.path.join(
662 self.GetWrapperName(), 'Versions', self.GetFrameworkVersion())
663 else:
664 # loadable_modules have a 'Contents' folder like executables.
665 return os.path.join(self.GetWrapperName(), 'Contents')
666
667 def GetBundleResourceFolder(self):
668 """Returns the qualified path to the bundle's resource folder. E.g.
669 Chromium.app/Contents/Resources. Only valid for bundles."""
670 assert self._IsBundle()
671 return os.path.join(self.GetBundleContentsFolderPath(), 'Resources')
672
673 def GetBundlePlistPath(self):
674 """Returns the qualified path to the bundle's plist file. E.g.
675 Chromium.app/Contents/Info.plist. Only valid for bundles."""
676 assert self._IsBundle()
677 assert self.spec['type'] != 'loadable_modules', (
678 "Info.plist files for loadable_modules not yet supported by the "
679 "make generator (target %s)" % self.spec['target_name']) # Not tested.
680 if self.spec['type'] == 'executable':
681 return os.path.join(self.GetBundleContentsFolderPath(), 'Info.plist')
682 else:
683 return os.path.join(self.GetBundleContentsFolderPath(),
684 'Resources', 'Info.plist')
685
686 def _GetBundleBinaryPath(self):
687 """Returns the name of the bundle binary of by this target.
688 E.g. Chromium.app/Contents/MacOS/Chromium. Only valid for bundles."""
689 assert self._IsBundle()
690 if self.spec['type'] in ('loadable_module', 'shared_library'):
691 path = self.GetBundleContentsFolderPath()
692 elif self.spec['type'] == 'executable':
693 path = os.path.join(self.GetBundleContentsFolderPath(), 'MacOS')
694 return os.path.join(path, self.spec.get('product_name',
695 self.spec['target_name']))
696
697 def _GetStandaloneExecutableSuffix(self):
698 if 'product_extension' in self.spec:
699 return '.' + self.spec['product_extension']
700 return {
701 'executable': '',
702 'static_library': '.a',
703 'shared_library': '.dylib',
704 'loadable_module': '.so',
705 }[self.spec['type']]
706
707 def _GetStandaloneExecutablePrefix(self):
708 return self.spec.get('product_prefix', {
709 'executable': '',
710 'static_library': 'lib',
711 'shared_library': 'lib',
712 # Non-bundled loadable_modules are called foo.so for some reason
713 # (that is, .so and no prefix) with the xcode build -- match that.
714 'loadable_module': '',
715 }[self.spec['type']])
716
717 def _GetStandaloneBinaryPath(self):
718 """Returns the name of the non-bundle binary represented by this target.
719 E.g. hello_world. Only valid for non-bundles."""
720 assert not self._IsBundle()
721 assert self.spec['type'] in (
722 'executable', 'shared_library', 'static_library', 'loadable_module')
723 target = self.spec['target_name']
724 if self.spec['type'] == 'static_library':
725 if target[:3] == 'lib':
726 target = target[3:]
727 elif self.spec['type'] in ('loadable_module', 'shared_library'):
728 if target[:3] == 'lib':
729 target = target[3:]
730
731 target_prefix = self._GetStandaloneExecutablePrefix()
732 target = self.spec.get('product_name', target)
733 target_ext = self._GetStandaloneExecutableSuffix()
734 return target_prefix + target + target_ext
735
736 def GetExecutablePath(self):
737 """Returns the directory name of the bundle represented by this target. E.g.
738 Chromium.app/Contents/MacOS/Chromium."""
739 if self._IsBundle():
740 return self._GetBundleBinaryPath()
741 else:
742 return self._GetStandaloneBinaryPath()
743
744 def _SdkPath(self):
745 sdk_root = 'macosx10.5'
746 if 'SDKROOT' in self._Settings():
747 sdk_root = self._Settings()['SDKROOT']
748 if sdk_root.startswith('macosx'):
749 sdk_root = 'MacOSX' + sdk_root[len('macosx'):]
750 return '/Developer/SDKs/%s.sdk' % sdk_root
751
752 def GetCflags(self, configname):
753 """Returns flags that need to be added to .c, .cc, .m, and .mm
754 compilations."""
755 # This functions (and the similar ones below) do not offer complete
756 # emulation of all xcode_settings keys. They're implemented on demand.
757
758 self.configname = configname
759 cflags = []
760
761 sdk_root = self._SdkPath()
762 if 'SDKROOT' in self._Settings():
763 cflags.append('-isysroot %s' % sdk_root)
764
765 if self._Test('GCC_CW_ASM_SYNTAX', 'YES', default='YES'):
766 cflags.append('-fasm-blocks')
767
768 if 'GCC_DYNAMIC_NO_PIC' in self._Settings():
769 if self._Settings()['GCC_DYNAMIC_NO_PIC'] == 'YES':
770 cflags.append('-mdynamic-no-pic')
771 else:
772 pass
773 # TODO: In this case, it depends on the target. xcode passes
774 # mdynamic-no-pic by default for executable and possibly static lib
775 # according to mento
776
777 if self._Test('GCC_ENABLE_PASCAL_STRINGS', 'YES', default='YES'):
778 cflags.append('-mpascal-strings')
779
780 self._Appendf(cflags, 'GCC_OPTIMIZATION_LEVEL', '-O%s')
781
782 if self._Test('GCC_GENERATE_DEBUGGING_SYMBOLS', 'YES', default='YES'):
783 dbg_format = self._Settings().get('DEBUG_INFORMATION_FORMAT', 'dwarf')
784 if dbg_format == 'dwarf':
785 cflags.append('-gdwarf-2')
786 elif dbg_format == 'stabs':
787 raise NotImplementedError('stabs debug format is not supported yet.')
788 elif dbg_format == 'dwarf-with-dsym':
789 # TODO(thakis): this is needed for mac_breakpad chromium builds, but not
790 # for regular chromium builds.
791 # -gdwarf-2 as well, but needs to invoke dsymutil after linking too:
792 # dsymutil build/Default/TestAppGyp.app/Contents/MacOS/TestAppGyp \
793 # -o build/Default/TestAppGyp.app.dSYM
794 raise NotImplementedError('dsym debug format is not supported yet.')
795 else:
796 raise NotImplementedError('Unknown debug format %s' % dbg_format)
797
798 if self._Test('GCC_SYMBOLS_PRIVATE_EXTERN', 'YES', default='NO'):
799 cflags.append('-fvisibility=hidden')
800
801 if self._Test('GCC_TREAT_WARNINGS_AS_ERRORS', 'YES', default='NO'):
802 cflags.append('-Werror')
803
804 if self._Test('GCC_WARN_ABOUT_MISSING_NEWLINE', 'YES', default='NO'):
805 cflags.append('-Wnewline-eof')
806
807 self._Appendf(cflags, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s')
808
809 # TODO:
810 self._WarnUnimplemented('ARCHS')
811 self._WarnUnimplemented('COPY_PHASE_STRIP')
812 self._WarnUnimplemented('DEPLOYMENT_POSTPROCESSING')
813 self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS')
814 self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS')
815 self._WarnUnimplemented('GCC_ENABLE_OBJC_GC')
816 self._WarnUnimplemented('INFOPLIST_PREPROCESS')
817 self._WarnUnimplemented('INFOPLIST_PREPROCESSOR_DEFINITIONS')
818 self._WarnUnimplemented('STRIPFLAGS')
819 self._WarnUnimplemented('STRIP_INSTALLED_PRODUCT')
820
821 # TODO: Do not hardcode arch. Supporting fat binaries will be annoying.
822 cflags.append('-arch i386')
823
824 cflags += self._Settings().get('OTHER_CFLAGS', [])
825 cflags += self._Settings().get('WARNING_CFLAGS', [])
826
827 config = self.spec['configurations'][self.configname]
828 framework_dirs = config.get('mac_framework_dirs', [])
829 for directory in framework_dirs:
830 cflags.append('-F ' + os.path.join(sdk_root, directory))
831
832 self.configname = None
833 return cflags
834
835 def GetCflagsC(self, configname):
836 """Returns flags that need to be added to .c, and .m compilations."""
837 self.configname = configname
838 cflags_c = []
839 self._Appendf(cflags_c, 'GCC_C_LANGUAGE_STANDARD', '-std=%s')
840 self.configname = None
841 return cflags_c
842
843 def GetCflagsCC(self, configname):
844 """Returns flags that need to be added to .cc, and .mm compilations."""
845 self.configname = configname
846 cflags_cc = []
847 if self._Test('GCC_ENABLE_CPP_RTTI', 'NO', default='YES'):
848 cflags_cc.append('-fno-rtti')
849 if self._Test('GCC_ENABLE_CPP_EXCEPTIONS', 'NO', default='YES'):
850 cflags_cc.append('-fno-exceptions')
851 if self._Test('GCC_INLINES_ARE_PRIVATE_EXTERN', 'YES', default='NO'):
852 cflags_cc.append('-fvisibility-inlines-hidden')
853 if self._Test('GCC_THREADSAFE_STATICS', 'NO', default='YES'):
854 cflags_cc.append('-fno-threadsafe-statics')
855 self.configname = None
856 return cflags_cc
857
858 def GetCflagsObjC(self, configname):
859 """Returns flags that need to be added to .m compilations."""
860 self.configname = configname
861 self.configname = None
862 return []
863
864 def GetCflagsObjCC(self, configname):
865 """Returns flags that need to be added to .mm compilations."""
866 self.configname = configname
867 cflags_objcc = []
868 if self._Test('GCC_OBJC_CALL_CXX_CDTORS', 'YES', default='NO'):
869 cflags_objcc.append('-fobjc-call-cxx-cdtors')
870 self.configname = None
871 return cflags_objcc
872
873 def GetLdflags(self, target, configname):
874 """Returns flags that need to be passed to the linker."""
875 self.configname = configname
876 ldflags = []
877
878 # The xcode build is relative to a gyp file's directory, and OTHER_LDFLAGS
879 # contains two entries that depend on this. Explicitly absolutify for these
880 # two cases.
881 def AbsolutifyPrefix(flag, prefix):
882 if flag.startswith(prefix):
883 flag = prefix + target.Absolutify(flag[len(prefix):])
884 return flag
885 for ldflag in self._Settings().get('OTHER_LDFLAGS', []):
886 # Required for ffmpeg (no idea why they don't use LIBRARY_SEARCH_PATHS,
887 # TODO(thakis): Update ffmpeg.gyp):
888 ldflag = AbsolutifyPrefix(ldflag, '-L')
889 # Required for the nacl plugin:
890 ldflag = AbsolutifyPrefix(ldflag, '-Wl,-exported_symbols_list ')
891 ldflags.append(ldflag)
892
893 if self._Test('DEAD_CODE_STRIPPING', 'YES', default='NO'):
894 ldflags.append('-Wl,-dead_strip')
895
896 if self._Test('PREBINDING', 'YES', default='NO'):
897 ldflags.append('-Wl,-prebind')
898
899 self._Appendf(
900 ldflags, 'DYLIB_COMPATIBILITY_VERSION', '-compatibility_version %s')
901 self._Appendf(
902 ldflags, 'DYLIB_CURRENT_VERSION', '-current_version %s')
903 self._Appendf(
904 ldflags, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s')
905 if 'SDKROOT' in self._Settings():
906 ldflags.append('-isysroot ' + self._SdkPath())
907
908 for library_path in self._Settings().get('LIBRARY_SEARCH_PATHS', []):
909 ldflags.append('-L' + library_path)
910
911 if 'ORDER_FILE' in self._Settings():
912 ldflags.append('-Wl,-order_file ' +
913 '-Wl,' + target.Absolutify(self._Settings()['ORDER_FILE']))
914
915 # TODO: Do not hardcode arch. Supporting fat binaries will be annoying.
916 ldflags.append('-arch i386')
917
918 # Xcode adds the product directory by default.
919 ldflags.append('-L' + generator_default_variables['PRODUCT_DIR'])
920
921 install_name = self.GetPerTargetSetting('LD_DYLIB_INSTALL_NAME')
922 install_base = self.GetPerTargetSetting('DYLIB_INSTALL_NAME_BASE')
923 default_install_name = \
924 '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)'
925 if not install_name and install_base:
926 install_name = default_install_name
927
928 if install_name:
929 # Hardcode support for the variables used in chromium for now, to unblock
930 # people using the make build.
931 if '$' in install_name:
932 assert install_name in ('$(DYLIB_INSTALL_NAME_BASE:standardizepath)/'
933 '$(WRAPPER_NAME)/$(PRODUCT_NAME)', default_install_name), (
934 'Variables in LD_DYLIB_INSTALL_NAME are not generally supported yet'
935 ' in target \'%s\' (got \'%s\')' %
936 (self.spec['target_name'], install_name))
937 # I'm not quite sure what :standardizepath does. Just call normpath(),
938 # but don't let @executable_path/../foo collapse to foo.
939 if '/' in install_base:
940 prefix, rest = '', install_base
941 if install_base.startswith('@'):
942 prefix, rest = install_base.split('/', 1)
943 rest = os.path.normpath(rest) # :standardizepath
944 install_base = os.path.join(prefix, rest)
945
946 install_name = install_name.replace(
947 '$(DYLIB_INSTALL_NAME_BASE:standardizepath)', install_base)
948 if self._IsBundle():
949 # These are only valid for bundles, hence the |if|.
950 install_name = install_name.replace(
951 '$(WRAPPER_NAME)', self.GetWrapperName())
952 install_name = install_name.replace(
953 '$(PRODUCT_NAME)', self.GetProductName())
954 else:
955 assert '$(WRAPPER_NAME)' not in install_name
956 assert '$(PRODUCT_NAME)' not in install_name
957
958 install_name = install_name.replace(
959 '$(EXECUTABLE_PATH)', self.GetExecutablePath())
960
961 install_name = QuoteSpaces(install_name)
962 ldflags.append('-install_name ' + install_name)
963
964 self.configname = None
965 return ldflags
966
967 def GetPerTargetSettings(self):
968 """Gets a list of all the per-target settings. This will only fetch keys
969 whose values are the same across all configurations."""
970 first_pass = True
971 result = {}
972 for configname in sorted(self.xcode_settings.keys()):
973 if first_pass:
974 result = dict(self.xcode_settings[configname])
975 first_pass = False
976 else:
977 for key, value in self.xcode_settings[configname].iteritems():
978 if key not in result:
979 continue
980 elif result[key] != value:
981 del result[key]
982 return result
983
984 def GetPerTargetSetting(self, setting, default=None):
985 """Tries to get xcode_settings.setting from spec. Assumes that the setting
986 has the same value in all configurations and throws otherwise."""
987 first_pass = True
988 result = None
989 for configname in sorted(self.xcode_settings.keys()):
990 if first_pass:
991 result = self.xcode_settings[configname].get(setting, None)
992 first_pass = False
993 else:
994 assert result == self.xcode_settings[configname].get(setting, None), (
995 "Expected per-target setting for '%s', got per-config setting "
996 "(target %s)" % (setting, spec['target_name']))
997 if result is None:
998 return default
999 return result
1000
1001
1002 class MacPrefixHeader(object):
1003 """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature. If
1004 GCC_PREFIX_HEADER isn't present (in most gyp targets on mac, and always on
1005 non-mac systems), all methods of this class are no-ops."""
1006
1007 def __init__(self, path_provider):
1008 # This doesn't support per-configuration prefix headers. Good enough
1009 # for now.
1010 self.header = None
1011 if path_provider.flavor == 'mac':
1012 self.header = path_provider.xcode_settings.GetPerTargetSetting(
1013 'GCC_PREFIX_HEADER')
1014 self.compiled_headers = {}
1015 if self.header:
1016 self.header = path_provider.Absolutify(self.header)
1017 for lang in ['c', 'cc', 'm', 'mm']:
1018 self.compiled_headers[lang] = path_provider.Pchify(self.header, lang)
1019
1020 def _Gch(self, lang):
1021 """Returns the actual file name of the prefix header for language |lang|."""
1022 return self.compiled_headers[lang] + '.gch'
1023
1024 def WriteObjDependencies(self, compilable, objs, writer):
1025 """Writes dependencies from the object files in |objs| to the corresponding
1026 precompiled header file. |compilable[i]| has to be the source file belonging
1027 to |objs[i]|."""
1028 if not self.header:
1029 return
1030
1031 writer.WriteLn('# Dependencies from obj files to their precompiled headers')
1032 for source, obj in zip(compilable, objs):
1033 ext = os.path.splitext(source)[1]
1034 lang = {
1035 '.c': 'c',
1036 '.cpp': 'cc', '.cc': 'cc', '.cxx': 'cc',
1037 '.m': 'm',
1038 '.mm': 'mm',
1039 }.get(ext, None)
1040 if lang:
1041 writer.WriteLn('%s: %s' % (obj, self._Gch(lang)))
1042 writer.WriteLn('# End precompiled header dependencies')
1043
1044 def GetInclude(self, lang):
1045 """Gets the cflags to include the prefix header for language |lang|."""
1046 if lang not in self.compiled_headers:
1047 return ''
1048 return '-include %s ' % self.compiled_headers[lang]
1049
1050 def WritePchTargets(self, writer):
1051 """Writes make rules to compile the prefix headers."""
1052 if not self.header:
1053 return
1054
1055 writer.WriteLn(self._Gch('c') + ": GYP_PCH_CFLAGS := "
1056 "-x c-header "
1057 "$(DEFS_$(BUILDTYPE)) "
1058 "$(INCS_$(BUILDTYPE)) "
1059 "$(CFLAGS_$(BUILDTYPE)) "
1060 "$(CFLAGS_C_$(BUILDTYPE))")
1061
1062 writer.WriteLn(self._Gch('cc') + ": GYP_PCH_CCFLAGS := "
1063 "-x c++-header "
1064 "$(DEFS_$(BUILDTYPE)) "
1065 "$(INCS_$(BUILDTYPE)) "
1066 "$(CFLAGS_$(BUILDTYPE)) "
1067 "$(CFLAGS_CC_$(BUILDTYPE))")
1068
1069 writer.WriteLn(self._Gch('m') + ": GYP_PCH_OBJCFLAGS := "
1070 "-x objective-c-header "
1071 "$(DEFS_$(BUILDTYPE)) "
1072 "$(INCS_$(BUILDTYPE)) "
1073 "$(CFLAGS_$(BUILDTYPE)) "
1074 "$(CFLAGS_C_$(BUILDTYPE)) "
1075 "$(CFLAGS_OBJC_$(BUILDTYPE))")
1076
1077 writer.WriteLn(self._Gch('mm') + ": GYP_PCH_OBJCXXFLAGS := "
1078 "-x objective-c++-header "
1079 "$(DEFS_$(BUILDTYPE)) "
1080 "$(INCS_$(BUILDTYPE)) "
1081 "$(CFLAGS_$(BUILDTYPE)) "
1082 "$(CFLAGS_CC_$(BUILDTYPE)) "
1083 "$(CFLAGS_OBJCC_$(BUILDTYPE))")
1084
1085 for lang in self.compiled_headers:
1086 writer.WriteLn('%s: %s FORCE_DO_CMD' % (self._Gch(lang), self.header))
1087 writer.WriteLn('\t@$(call do_cmd,pch_%s,1)' % lang)
1088 writer.WriteLn('')
1089 assert ' ' not in self._Gch(lang), (
1090 "Spaces in gch filenames not supported (%s)" % self._Gch(lang))
1091 writer.WriteLn('all_deps += %s' % self._Gch(lang))
1092 writer.WriteLn('')
1093
1094
1095 class MakefileWriter:
1096 """MakefileWriter packages up the writing of one target-specific foobar.mk.
1097
1098 Its only real entry point is Write(), and is mostly used for namespacing.
1099 """
1100
1101 def __init__(self, generator_flags, flavor):
1102 self.generator_flags = generator_flags
1103 self.flavor = flavor
1104 # Keep track of the total number of outputs for this makefile.
1105 self._num_outputs = 0
1106
1107 self.suffix_rules_srcdir = {}
1108 self.suffix_rules_objdir1 = {}
1109 self.suffix_rules_objdir2 = {}
1110
1111 # Generate suffix rules for all compilable extensions.
1112 for ext in COMPILABLE_EXTENSIONS.keys():
1113 # Suffix rules for source folder.
1114 self.suffix_rules_srcdir.update({ext: ("""\
1115 $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD
1116 @$(call do_cmd,%s,1)
1117 """ % (ext, COMPILABLE_EXTENSIONS[ext]))})
1118
1119 # Suffix rules for generated source files.
1120 self.suffix_rules_objdir1.update({ext: ("""\
1121 $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD
1122 @$(call do_cmd,%s,1)
1123 """ % (ext, COMPILABLE_EXTENSIONS[ext]))})
1124 self.suffix_rules_objdir2.update({ext: ("""\
1125 $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
1126 @$(call do_cmd,%s,1)
1127 """ % (ext, COMPILABLE_EXTENSIONS[ext]))})
1128
1129
1130 def NumOutputs(self):
1131 return self._num_outputs
1132
1133
1134 def Write(self, qualified_target, base_path, output_filename, spec, configs,
1135 part_of_all):
1136 """The main entry point: writes a .mk file for a single target.
1137
1138 Arguments:
1139 qualified_target: target we're generating
1140 base_path: path relative to source root we're building in, used to resolve
1141 target-relative paths
1142 output_filename: output .mk file name to write
1143 spec, configs: gyp info
1144 part_of_all: flag indicating this target is part of 'all'
1145 """
1146 ensure_directory_exists(output_filename)
1147
1148 self.fp = open(output_filename, 'w')
1149
1150 self.fp.write(header)
1151
1152 self.path = base_path
1153 self.target = spec['target_name']
1154 self.type = spec['type']
1155 self.toolset = spec['toolset']
1156
1157 # Bundles are directories with a certain subdirectory structure, instead of
1158 # just a single file. Bundle rules do not produce a binary but also package
1159 # resources into that directory.
1160 self.is_mac_bundle = (int(spec.get('mac_bundle', 0)) != 0 and
1161 self.flavor == 'mac')
1162 if self.is_mac_bundle:
1163 assert self.type != 'none', (
1164 'mac_bundle targets cannot have type none (target "%s")' %
1165 self.target)
1166
1167 if self.flavor == 'mac':
1168 self.xcode_settings = XcodeSettings(spec)
1169
1170 deps, link_deps = self.ComputeDeps(spec)
1171
1172 # Some of the generation below can add extra output, sources, or
1173 # link dependencies. All of the out params of the functions that
1174 # follow use names like extra_foo.
1175 extra_outputs = []
1176 extra_sources = []
1177 extra_link_deps = []
1178 extra_mac_bundle_resources = []
1179 mac_bundle_deps = []
1180
1181 if self.is_mac_bundle:
1182 self.output = self.ComputeMacBundleOutput(spec)
1183 self.output_binary = self.ComputeMacBundleBinaryOutput(spec)
1184 else:
1185 self.output = self.output_binary = self.ComputeOutput(spec)
1186
1187 self.output = QuoteSpaces(self.output)
1188 self.output_binary = QuoteSpaces(self.output_binary)
1189
1190 self._INSTALLABLE_TARGETS = ('executable', 'loadable_module',
1191 'shared_library')
1192 if self.type in self._INSTALLABLE_TARGETS:
1193 self.alias = os.path.basename(self.output)
1194 install_path = self._InstallableTargetInstallPath()
1195 else:
1196 self.alias = self.output
1197 install_path = self.output
1198
1199 self.WriteLn("TOOLSET := " + self.toolset)
1200 self.WriteLn("TARGET := " + self.target)
1201
1202 # Actions must come first, since they can generate more OBJs for use below.
1203 if 'actions' in spec:
1204 self.WriteActions(spec['actions'], extra_sources, extra_outputs,
1205 extra_mac_bundle_resources, part_of_all, spec)
1206
1207 # Rules must be early like actions.
1208 if 'rules' in spec:
1209 self.WriteRules(spec['rules'], extra_sources, extra_outputs,
1210 extra_mac_bundle_resources, part_of_all)
1211
1212 if 'copies' in spec:
1213 self.WriteCopies(spec['copies'], extra_outputs, part_of_all, spec)
1214
1215 # Bundle resources.
1216 if self.is_mac_bundle:
1217 all_mac_bundle_resources = (
1218 spec.get('mac_bundle_resources', []) + extra_mac_bundle_resources)
1219 if all_mac_bundle_resources:
1220 self.WriteMacBundleResources(
1221 all_mac_bundle_resources, mac_bundle_deps, spec)
1222 info_plist = self.xcode_settings.GetPerTargetSetting('INFOPLIST_FILE')
1223 if info_plist:
1224 self.WriteMacInfoPlist(info_plist, mac_bundle_deps, spec)
1225
1226 # Sources.
1227 all_sources = spec.get('sources', []) + extra_sources
1228 if all_sources:
1229 self.WriteSources(
1230 configs, deps, all_sources, extra_outputs,
1231 extra_link_deps, part_of_all, MacPrefixHeader(self))
1232 sources = filter(Compilable, all_sources)
1233 if sources:
1234 self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT1)
1235 extensions = set([os.path.splitext(s)[1] for s in sources])
1236 for ext in extensions:
1237 if ext in self.suffix_rules_srcdir:
1238 self.WriteLn(self.suffix_rules_srcdir[ext])
1239 self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT2)
1240 for ext in extensions:
1241 if ext in self.suffix_rules_objdir1:
1242 self.WriteLn(self.suffix_rules_objdir1[ext])
1243 for ext in extensions:
1244 if ext in self.suffix_rules_objdir2:
1245 self.WriteLn(self.suffix_rules_objdir2[ext])
1246 self.WriteLn('# End of this set of suffix rules')
1247
1248 # Add dependency from bundle to bundle binary.
1249 if self.is_mac_bundle:
1250 mac_bundle_deps.append(self.output_binary)
1251
1252 self.WriteTarget(spec, configs, deps, extra_link_deps + link_deps,
1253 mac_bundle_deps, extra_outputs, part_of_all)
1254
1255 # Update global list of target outputs, used in dependency tracking.
1256 target_outputs[qualified_target] = install_path
1257
1258 # Update global list of link dependencies.
1259 if self.type in ('static_library', 'shared_library'):
1260 target_link_deps[qualified_target] = self.output_binary
1261
1262 # Currently any versions have the same effect, but in future the behavior
1263 # could be different.
1264 if self.generator_flags.get('android_ndk_version', None):
1265 self.WriteAndroidNdkModuleRule(self.target, all_sources, link_deps)
1266
1267 self.fp.close()
1268
1269
1270 def WriteSubMake(self, output_filename, makefile_path, targets, build_dir):
1271 """Write a "sub-project" Makefile.
1272
1273 This is a small, wrapper Makefile that calls the top-level Makefile to build
1274 the targets from a single gyp file (i.e. a sub-project).
1275
1276 Arguments:
1277 output_filename: sub-project Makefile name to write
1278 makefile_path: path to the top-level Makefile
1279 targets: list of "all" targets for this sub-project
1280 build_dir: build output directory, relative to the sub-project
1281 """
1282 ensure_directory_exists(output_filename)
1283 self.fp = open(output_filename, 'w')
1284 self.fp.write(header)
1285 # For consistency with other builders, put sub-project build output in the
1286 # sub-project dir (see test/subdirectory/gyptest-subdir-all.py).
1287 self.WriteLn('export builddir_name ?= %s' %
1288 os.path.join(os.path.dirname(output_filename), build_dir))
1289 self.WriteLn('.PHONY: all')
1290 self.WriteLn('all:')
1291 if makefile_path:
1292 makefile_path = ' -C ' + makefile_path
1293 self.WriteLn('\t$(MAKE)%s %s' % (makefile_path, ' '.join(targets)))
1294 self.fp.close()
1295
1296
1297 def WriteActions(self, actions, extra_sources, extra_outputs,
1298 extra_mac_bundle_resources, part_of_all, spec):
1299 """Write Makefile code for any 'actions' from the gyp input.
1300
1301 extra_sources: a list that will be filled in with newly generated source
1302 files, if any
1303 extra_outputs: a list that will be filled in with any outputs of these
1304 actions (used to make other pieces dependent on these
1305 actions)
1306 part_of_all: flag indicating this target is part of 'all'
1307 """
1308 for action in actions:
1309 name = self.target + '_' + StringToMakefileVariable(action['action_name'])
1310 self.WriteLn('### Rules for action "%s":' % action['action_name'])
1311 inputs = action['inputs']
1312 outputs = action['outputs']
1313
1314 # Build up a list of outputs.
1315 # Collect the output dirs we'll need.
1316 dirs = set()
1317 for out in outputs:
1318 dir = os.path.split(out)[0]
1319 if dir:
1320 dirs.add(dir)
1321 if int(action.get('process_outputs_as_sources', False)):
1322 extra_sources += outputs
1323 if int(action.get('process_outputs_as_mac_bundle_resources', False)):
1324 extra_mac_bundle_resources += outputs
1325
1326 # Write the actual command.
1327 command = gyp.common.EncodePOSIXShellList(action['action'])
1328 if 'message' in action:
1329 self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, action['message']))
1330 else:
1331 self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, name))
1332 if len(dirs) > 0:
1333 command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command
1334
1335 cd_action = 'cd %s; ' % Sourceify(self.path or '.')
1336
1337 # Set LD_LIBRARY_PATH in case the action runs an executable from this
1338 # build which links to shared libs from this build.
1339 # actions run on the host, so they should in theory only use host
1340 # libraries, but until everything is made cross-compile safe, also use
1341 # target libraries.
1342 # TODO(piman): when everything is cross-compile safe, remove lib.target
1343 self.WriteLn('cmd_%s = export LD_LIBRARY_PATH=$(builddir)/lib.host:'
1344 '$(builddir)/lib.target:$$LD_LIBRARY_PATH; %s%s'
1345 % (name, cd_action, command))
1346 self.WriteLn()
1347 outputs = map(self.Absolutify, outputs)
1348 # The makefile rules are all relative to the top dir, but the gyp actions
1349 # are defined relative to their containing dir. This replaces the obj
1350 # variable for the action rule with an absolute version so that the output
1351 # goes in the right place.
1352 # Only write the 'obj' and 'builddir' rules for the "primary" output (:1);
1353 # it's superfluous for the "extra outputs", and this avoids accidentally
1354 # writing duplicate dummy rules for those outputs.
1355 # Same for environment.
1356 self.WriteMakeRule(outputs[:1], ['obj := $(abs_obj)'])
1357 # Needs to be before builddir is redefined in the next line!
1358 self.WriteXcodeEnv(outputs[0], spec, target_relative_path=True)
1359 self.WriteMakeRule(outputs[:1], ['builddir := $(abs_builddir)'])
1360
1361 for input in inputs:
1362 assert ' ' not in input, (
1363 "Spaces in action input filenames not supported (%s)" % input)
1364 for output in outputs:
1365 assert ' ' not in output, (
1366 "Spaces in action output filenames not supported (%s)" % output)
1367
1368 self.WriteDoCmd(outputs, map(Sourceify, map(self.Absolutify, inputs)),
1369 part_of_all=part_of_all, command=name)
1370
1371 # Stuff the outputs in a variable so we can refer to them later.
1372 outputs_variable = 'action_%s_outputs' % name
1373 self.WriteLn('%s := %s' % (outputs_variable, ' '.join(outputs)))
1374 extra_outputs.append('$(%s)' % outputs_variable)
1375 self.WriteLn()
1376
1377 self.WriteLn()
1378
1379
1380 def WriteRules(self, rules, extra_sources, extra_outputs,
1381 extra_mac_bundle_resources, part_of_all):
1382 """Write Makefile code for any 'rules' from the gyp input.
1383
1384 extra_sources: a list that will be filled in with newly generated source
1385 files, if any
1386 extra_outputs: a list that will be filled in with any outputs of these
1387 rules (used to make other pieces dependent on these rules)
1388 part_of_all: flag indicating this target is part of 'all'
1389 """
1390 for rule in rules:
1391 name = self.target + '_' + StringToMakefileVariable(rule['rule_name'])
1392 count = 0
1393 self.WriteLn('### Generated for rule %s:' % name)
1394
1395 all_outputs = []
1396
1397 for rule_source in rule.get('rule_sources', []):
1398 dirs = set()
1399 rule_source_basename = os.path.basename(rule_source)
1400 (rule_source_root, rule_source_ext) = \
1401 os.path.splitext(rule_source_basename)
1402
1403 outputs = [self.ExpandInputRoot(out, rule_source_root)
1404 for out in rule['outputs']]
1405 for out in outputs:
1406 dir = os.path.dirname(out)
1407 if dir:
1408 dirs.add(dir)
1409 if int(rule.get('process_outputs_as_sources', False)):
1410 extra_sources += outputs
1411 if int(rule.get('process_outputs_as_mac_bundle_resources', False)):
1412 extra_mac_bundle_resources += outputs
1413 all_outputs += outputs
1414 inputs = map(Sourceify, map(self.Absolutify, [rule_source] +
1415 rule.get('inputs', [])))
1416 actions = ['$(call do_cmd,%s_%d)' % (name, count)]
1417
1418 if name == 'resources_grit':
1419 # HACK: This is ugly. Grit intentionally doesn't touch the
1420 # timestamp of its output file when the file doesn't change,
1421 # which is fine in hash-based dependency systems like scons
1422 # and forge, but not kosher in the make world. After some
1423 # discussion, hacking around it here seems like the least
1424 # amount of pain.
1425 actions += ['@touch --no-create $@']
1426
1427 # Only write the 'obj' and 'builddir' rules for the "primary" output
1428 # (:1); it's superfluous for the "extra outputs", and this avoids
1429 # accidentally writing duplicate dummy rules for those outputs.
1430 self.WriteMakeRule(outputs[:1], ['obj := $(abs_obj)'])
1431 self.WriteMakeRule(outputs[:1], ['builddir := $(abs_builddir)'])
1432 self.WriteMakeRule(outputs, inputs + ['FORCE_DO_CMD'], actions)
1433 for output in outputs:
1434 assert ' ' not in output, (
1435 "Spaces in rule filenames not yet supported (%s)" % output)
1436 self.WriteLn('all_deps += %s' % ' '.join(outputs))
1437 self._num_outputs += len(outputs)
1438
1439 action = [self.ExpandInputRoot(ac, rule_source_root)
1440 for ac in rule['action']]
1441 mkdirs = ''
1442 if len(dirs) > 0:
1443 mkdirs = 'mkdir -p %s; ' % ' '.join(dirs)
1444 cd_action = 'cd %s; ' % Sourceify(self.path or '.')
1445 # Set LD_LIBRARY_PATH in case the rule runs an executable from this
1446 # build which links to shared libs from this build.
1447 # rules run on the host, so they should in theory only use host
1448 # libraries, but until everything is made cross-compile safe, also use
1449 # target libraries.
1450 # TODO(piman): when everything is cross-compile safe, remove lib.target
1451 self.WriteLn(
1452 "cmd_%(name)s_%(count)d = export LD_LIBRARY_PATH="
1453 "$(builddir)/lib.host:$(builddir)/lib.target:$$LD_LIBRARY_PATH; "
1454 "%(cd_action)s%(mkdirs)s%(action)s" % {
1455 'action': gyp.common.EncodePOSIXShellList(action),
1456 'cd_action': cd_action,
1457 'count': count,
1458 'mkdirs': mkdirs,
1459 'name': name,
1460 })
1461 self.WriteLn(
1462 'quiet_cmd_%(name)s_%(count)d = RULE %(name)s_%(count)d $@' % {
1463 'count': count,
1464 'name': name,
1465 })
1466 self.WriteLn()
1467 count += 1
1468
1469 outputs_variable = 'rule_%s_outputs' % name
1470 self.WriteList(all_outputs, outputs_variable)
1471 extra_outputs.append('$(%s)' % outputs_variable)
1472
1473 self.WriteLn('### Finished generating for rule: %s' % name)
1474 self.WriteLn()
1475 self.WriteLn('### Finished generating for all rules')
1476 self.WriteLn('')
1477
1478
1479 def WriteCopies(self, copies, extra_outputs, part_of_all, spec):
1480 """Write Makefile code for any 'copies' from the gyp input.
1481
1482 extra_outputs: a list that will be filled in with any outputs of this action
1483 (used to make other pieces dependent on this action)
1484 part_of_all: flag indicating this target is part of 'all'
1485 """
1486 self.WriteLn('### Generated for copy rule.')
1487
1488 variable = self.target + '_copies'
1489 outputs = []
1490 for copy in copies:
1491 for path in copy['files']:
1492 path = Sourceify(self.Absolutify(path))
1493 filename = os.path.split(path)[1]
1494 output = Sourceify(self.Absolutify(os.path.join(copy['destination'],
1495 filename)))
1496 path = QuoteSpaces(path)
1497 output = QuoteSpaces(output)
1498
1499 # If the output path has variables in it, which happens in practice for
1500 # 'copies', writing the environment as target-local doesn't work,
1501 # because the variables are already needed for the target name.
1502 # Copying the environment variables into global make variables doesn't
1503 # work either, because then the .d files will potentially contain spaces
1504 # after variable expansion, and .d file handling cannot handle spaces.
1505 # As a workaround, manually expand variables at gyp time. Since 'copies'
1506 # can't run scripts, there's no need to write the env then.
1507 # WriteDoCmd() will escape spaces for .d files.
1508 import gyp.generator.xcode as xcode_generator
1509 env = self.GetXcodeEnv(spec)
1510 output = xcode_generator.ExpandXcodeVariables(output, env)
1511 path = xcode_generator.ExpandXcodeVariables(path, env)
1512 self.WriteDoCmd([output], [path], 'copy', part_of_all)
1513 outputs.append(output)
1514 self.WriteLn('%s = %s' % (variable, ' '.join(outputs)))
1515 extra_outputs.append('$(%s)' % variable)
1516 self.WriteLn()
1517
1518
1519 def WriteMacBundleResources(self, resources, bundle_deps, spec):
1520 """Writes Makefile code for 'mac_bundle_resources'."""
1521 self.WriteLn('### Generated for mac_bundle_resources')
1522 variable = self.target + '_mac_bundle_resources'
1523 path = generator_default_variables['PRODUCT_DIR']
1524 dest = os.path.join(path, self.xcode_settings.GetBundleResourceFolder())
1525 dest = QuoteSpaces(dest)
1526 for res in resources:
1527 output = dest
1528
1529 assert ' ' not in res, (
1530 "Spaces in resource filenames not supported (%s)" % res)
1531
1532 # Split into (path,file).
1533 path = Sourceify(self.Absolutify(res))
1534 path_parts = os.path.split(path)
1535
1536 # Now split the path into (prefix,maybe.lproj).
1537 lproj_parts = os.path.split(path_parts[0])
1538 # If the resource lives in a .lproj bundle, add that to the destination.
1539 if lproj_parts[1].endswith('.lproj'):
1540 output = os.path.join(output, lproj_parts[1])
1541
1542 output = Sourceify(self.Absolutify(os.path.join(output, path_parts[1])))
1543 # Compiled XIB files are referred to by .nib.
1544 if output.endswith('.xib'):
1545 output = output[0:-3] + 'nib'
1546
1547 self.WriteDoCmd([output], [path], 'mac_tool,,,copy-bundle-resource',
1548 part_of_all=True)
1549 bundle_deps.append(output)
1550
1551
1552 def WriteMacInfoPlist(self, info_plist, bundle_deps, spec):
1553 """Write Makefile code for bundle Info.plist files."""
1554 assert ' ' not in info_plist, (
1555 "Spaces in resource filenames not supported (%s)" % info_plist)
1556 info_plist = self.Absolutify(info_plist)
1557 path = generator_default_variables['PRODUCT_DIR']
1558 dest_plist = os.path.join(path, self.xcode_settings.GetBundlePlistPath())
1559 dest_plist = QuoteSpaces(dest_plist)
1560 extra_settings = self.xcode_settings.GetPerTargetSettings()
1561 # plists can contain envvars and substitute them into the file..
1562 self.WriteXcodeEnv(dest_plist, spec, additional_settings=extra_settings)
1563 self.WriteDoCmd([dest_plist], [info_plist], 'mac_tool,,,copy-info-plist',
1564 part_of_all=True)
1565 bundle_deps.append(dest_plist)
1566
1567
1568 def WriteSources(self, configs, deps, sources,
1569 extra_outputs, extra_link_deps,
1570 part_of_all, precompiled_header):
1571 """Write Makefile code for any 'sources' from the gyp input.
1572 These are source files necessary to build the current target.
1573
1574 configs, deps, sources: input from gyp.
1575 extra_outputs: a list of extra outputs this action should be dependent on;
1576 used to serialize action/rules before compilation
1577 extra_link_deps: a list that will be filled in with any outputs of
1578 compilation (to be used in link lines)
1579 part_of_all: flag indicating this target is part of 'all'
1580 """
1581
1582 # Write configuration-specific variables for CFLAGS, etc.
1583 for configname in sorted(configs.keys()):
1584 config = configs[configname]
1585 self.WriteList(config.get('defines'), 'DEFS_%s' % configname, prefix='-D',
1586 quoter=EscapeCppDefine)
1587
1588 if self.flavor == 'mac':
1589 cflags = self.xcode_settings.GetCflags(configname)
1590 cflags_c = self.xcode_settings.GetCflagsC(configname)
1591 cflags_cc = self.xcode_settings.GetCflagsCC(configname)
1592 cflags_objc = self.xcode_settings.GetCflagsObjC(configname)
1593 cflags_objcc = self.xcode_settings.GetCflagsObjCC(configname)
1594 else:
1595 cflags = config.get('cflags')
1596 cflags_c = config.get('cflags_c')
1597 cflags_cc = config.get('cflags_cc')
1598
1599 self.WriteLn("# Flags passed to all source files.");
1600 self.WriteList(cflags, 'CFLAGS_%s' % configname)
1601 self.WriteLn("# Flags passed to only C files.");
1602 self.WriteList(cflags_c, 'CFLAGS_C_%s' % configname)
1603 self.WriteLn("# Flags passed to only C++ files.");
1604 self.WriteList(cflags_cc, 'CFLAGS_CC_%s' % configname)
1605 if self.flavor == 'mac':
1606 self.WriteLn("# Flags passed to only ObjC files.");
1607 self.WriteList(cflags_objc, 'CFLAGS_OBJC_%s' % configname)
1608 self.WriteLn("# Flags passed to only ObjC++ files.");
1609 self.WriteList(cflags_objcc, 'CFLAGS_OBJCC_%s' % configname)
1610 includes = config.get('include_dirs')
1611 if includes:
1612 includes = map(Sourceify, map(self.Absolutify, includes))
1613 self.WriteList(includes, 'INCS_%s' % configname, prefix='-I')
1614
1615 compilable = filter(Compilable, sources)
1616 objs = map(self.Objectify, map(self.Absolutify, map(Target, compilable)))
1617 self.WriteList(objs, 'OBJS')
1618
1619 for obj in objs:
1620 assert ' ' not in obj, (
1621 "Spaces in object filenames not supported (%s)" % obj)
1622 self.WriteLn('# Add to the list of files we specially track '
1623 'dependencies for.')
1624 self.WriteLn('all_deps += $(OBJS)')
1625 self._num_outputs += len(objs)
1626 self.WriteLn()
1627
1628 # Make sure our dependencies are built first.
1629 if deps:
1630 self.WriteMakeRule(['$(OBJS)'], deps,
1631 comment = 'Make sure our dependencies are built '
1632 'before any of us.',
1633 order_only = True)
1634
1635 # Make sure the actions and rules run first.
1636 # If they generate any extra headers etc., the per-.o file dep tracking
1637 # will catch the proper rebuilds, so order only is still ok here.
1638 if extra_outputs:
1639 self.WriteMakeRule(['$(OBJS)'], extra_outputs,
1640 comment = 'Make sure our actions/rules run '
1641 'before any of us.',
1642 order_only = True)
1643
1644 precompiled_header.WriteObjDependencies(compilable, objs, self)
1645
1646 if objs:
1647 extra_link_deps.append('$(OBJS)')
1648 self.WriteLn("""\
1649 # CFLAGS et al overrides must be target-local.
1650 # See "Target-specific Variable Values" in the GNU Make manual.""")
1651 self.WriteLn("$(OBJS): TOOLSET := $(TOOLSET)")
1652 self.WriteLn("$(OBJS): GYP_CFLAGS := "
1653 "$(DEFS_$(BUILDTYPE)) "
1654 "$(INCS_$(BUILDTYPE)) "
1655 "%s" % precompiled_header.GetInclude('c') +
1656 "$(CFLAGS_$(BUILDTYPE)) "
1657 "$(CFLAGS_C_$(BUILDTYPE))")
1658 self.WriteLn("$(OBJS): GYP_CXXFLAGS := "
1659 "$(DEFS_$(BUILDTYPE)) "
1660 "$(INCS_$(BUILDTYPE)) "
1661 "%s" % precompiled_header.GetInclude('cc') +
1662 "$(CFLAGS_$(BUILDTYPE)) "
1663 "$(CFLAGS_CC_$(BUILDTYPE))")
1664 if self.flavor == 'mac':
1665 self.WriteLn("$(OBJS): GYP_OBJCFLAGS := "
1666 "$(DEFS_$(BUILDTYPE)) "
1667 "$(INCS_$(BUILDTYPE)) "
1668 "%s" % precompiled_header.GetInclude('m') +
1669 "$(CFLAGS_$(BUILDTYPE)) "
1670 "$(CFLAGS_C_$(BUILDTYPE)) "
1671 "$(CFLAGS_OBJC_$(BUILDTYPE))")
1672 self.WriteLn("$(OBJS): GYP_OBJCXXFLAGS := "
1673 "$(DEFS_$(BUILDTYPE)) "
1674 "$(INCS_$(BUILDTYPE)) "
1675 "%s" % precompiled_header.GetInclude('mm') +
1676 "$(CFLAGS_$(BUILDTYPE)) "
1677 "$(CFLAGS_CC_$(BUILDTYPE)) "
1678 "$(CFLAGS_OBJCC_$(BUILDTYPE))")
1679
1680 precompiled_header.WritePchTargets(self)
1681
1682 # If there are any object files in our input file list, link them into our
1683 # output.
1684 extra_link_deps += filter(Linkable, sources)
1685
1686 self.WriteLn()
1687
1688
1689 def ComputeOutputBasename(self, spec):
1690 """Return the 'output basename' of a gyp spec.
1691
1692 E.g., the loadable module 'foobar' in directory 'baz' will produce
1693 'libfoobar.so'
1694 """
1695 assert not self.is_mac_bundle
1696
1697 if self.flavor == 'mac' and self.type in (
1698 'static_library', 'executable', 'shared_library', 'loadable_module'):
1699 return self.xcode_settings.GetExecutablePath()
1700
1701 target = spec['target_name']
1702 target_prefix = ''
1703 target_ext = ''
1704 if self.type == 'static_library':
1705 if target[:3] == 'lib':
1706 target = target[3:]
1707 target_prefix = 'lib'
1708 target_ext = '.a'
1709 elif self.type in ('loadable_module', 'shared_library'):
1710 if target[:3] == 'lib':
1711 target = target[3:]
1712 target_prefix = 'lib'
1713 target_ext = '.so'
1714 elif self.type == 'none':
1715 target = '%s.stamp' % target
1716 elif self.type != 'executable':
1717 print ("ERROR: What output file should be generated?",
1718 "type", self.type, "target", target)
1719
1720 target_prefix = spec.get('product_prefix', target_prefix)
1721 target = spec.get('product_name', target)
1722 product_ext = spec.get('product_extension')
1723 if product_ext:
1724 target_ext = '.' + product_ext
1725
1726 return target_prefix + target + target_ext
1727
1728
1729 def _InstallImmediately(self):
1730 return self.toolset == 'target' and self.flavor == 'mac' and self.type in (
1731 'static_library', 'executable', 'shared_library', 'loadable_module')
1732
1733
1734 def ComputeOutput(self, spec):
1735 """Return the 'output' (full output path) of a gyp spec.
1736
1737 E.g., the loadable module 'foobar' in directory 'baz' will produce
1738 '$(obj)/baz/libfoobar.so'
1739 """
1740 assert not self.is_mac_bundle
1741
1742 if self.type == 'settings':
1743 return '' # Doesn't have any output.
1744
1745 path = os.path.join('$(obj).' + self.toolset, self.path)
1746 if self.type == 'executable' or self._InstallImmediately():
1747 path = '$(builddir)'
1748 path = spec.get('product_dir', path)
1749 return os.path.join(path, self.ComputeOutputBasename(spec))
1750
1751
1752 def ComputeMacBundleOutput(self, spec):
1753 """Return the 'output' (full output path) to a bundle output directory."""
1754 assert self.is_mac_bundle
1755 path = generator_default_variables['PRODUCT_DIR']
1756 return os.path.join(path, self.xcode_settings.GetWrapperName())
1757
1758
1759 def ComputeMacBundleBinaryOutput(self, spec):
1760 """Return the 'output' (full output path) to the binary in a bundle."""
1761 path = generator_default_variables['PRODUCT_DIR']
1762 return os.path.join(path, self.xcode_settings.GetExecutablePath())
1763
1764
1765 def ComputeDeps(self, spec):
1766 """Compute the dependencies of a gyp spec.
1767
1768 Returns a tuple (deps, link_deps), where each is a list of
1769 filenames that will need to be put in front of make for either
1770 building (deps) or linking (link_deps).
1771 """
1772 deps = []
1773 link_deps = []
1774 if 'dependencies' in spec:
1775 deps.extend([target_outputs[dep] for dep in spec['dependencies']
1776 if target_outputs[dep]])
1777 for dep in spec['dependencies']:
1778 if dep in target_link_deps:
1779 link_deps.append(target_link_deps[dep])
1780 deps.extend(link_deps)
1781 # TODO: It seems we need to transitively link in libraries (e.g. -lfoo)?
1782 # This hack makes it work:
1783 # link_deps.extend(spec.get('libraries', []))
1784 return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps))
1785
1786
1787 def WriteDependencyOnExtraOutputs(self, target, extra_outputs):
1788 self.WriteMakeRule([self.output_binary], extra_outputs,
1789 comment = 'Build our special outputs first.',
1790 order_only = True)
1791
1792
1793 def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps,
1794 extra_outputs, part_of_all):
1795 """Write Makefile code to produce the final target of the gyp spec.
1796
1797 spec, configs: input from gyp.
1798 deps, link_deps: dependency lists; see ComputeDeps()
1799 extra_outputs: any extra outputs that our target should depend on
1800 part_of_all: flag indicating this target is part of 'all'
1801 """
1802
1803 self.WriteLn('### Rules for final target.')
1804
1805 if extra_outputs:
1806 self.WriteDependencyOnExtraOutputs(self.output_binary, extra_outputs)
1807 self.WriteMakeRule(extra_outputs, deps,
1808 comment=('Preserve order dependency of '
1809 'special output on deps.'),
1810 order_only = True,
1811 multiple_output_trick = False)
1812
1813 if self.type not in ('settings', 'none'):
1814 for configname in sorted(configs.keys()):
1815 config = configs[configname]
1816 if self.flavor == 'mac':
1817 ldflags = self.xcode_settings.GetLdflags(self, configname)
1818 else:
1819 ldflags = config.get('ldflags', [])
1820 # Compute an rpath for this output if needed.
1821 if any(dep.endswith('.so') for dep in deps):
1822 # We want to get the literal string "$ORIGIN" into the link command,
1823 # so we need lots of escaping.
1824 ldflags.append(r'-Wl,-rpath=\$$ORIGIN/lib.%s/' % self.toolset)
1825 self.WriteList(ldflags, 'LDFLAGS_%s' % configname)
1826 libraries = spec.get('libraries')
1827 if libraries:
1828 # Remove duplicate entries
1829 libraries = gyp.common.uniquer(libraries)
1830 # On Mac, framework libraries need to be passed as '-framework Cocoa'.
1831 if self.flavor == 'mac':
1832 libraries = [
1833 '-framework ' + os.path.splitext(os.path.basename(library))[0]
1834 if library.endswith('.framework') else library
1835 for library in libraries]
1836 self.WriteList(libraries, 'LIBS')
1837 self.WriteLn(
1838 '%s: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))' % self.output_binary)
1839 self.WriteLn('%s: LIBS := $(LIBS)' % self.output_binary)
1840
1841 postbuilds = []
1842 if self.flavor == 'mac':
1843 # Postbuild actions. Like actions, but implicitly depend on the target's
1844 # output.
1845 for postbuild in spec.get('postbuilds', []):
1846 postbuilds.append('echo POSTBUILD\\(%s\\) %s' % (
1847 self.target, postbuild['postbuild_name']))
1848 shell_list = postbuild['action']
1849 # The first element is the command. If it's a relative path, it's
1850 # a script in the source tree relative to the gyp file and needs to be
1851 # absolutified. Else, it's in the PATH (e.g. install_name_tool, ln).
1852 if os.path.sep in shell_list[0]:
1853 shell_list[0] = self.Absolutify(shell_list[0])
1854 postbuilds.append('%s' % gyp.common.EncodePOSIXShellList(shell_list))
1855
1856 # A bundle directory depends on its dependencies such as bundle resources
1857 # and bundle binary. When all dependencies have been built, the bundle
1858 # needs to be packaged.
1859 if self.is_mac_bundle:
1860 self.WriteXcodeEnv(self.output, spec) # For postbuilds
1861
1862 # If the framework doesn't contain a binary, then nothing depends
1863 # on the actions -- make the framework depend on them directly too.
1864 self.WriteDependencyOnExtraOutputs(self.output, extra_outputs)
1865
1866 # Bundle dependencies. Note that the code below adds actions to this
1867 # target, so if you move these two lines, move the lines below as well.
1868 self.WriteList(bundle_deps, 'BUNDLE_DEPS')
1869 self.WriteLn('%s: $(BUNDLE_DEPS)' % self.output)
1870
1871 # After the framework is built, package it. Needs to happen before
1872 # postbuilds, since postbuilds depend on this.
1873 if self.type in ('shared_library', 'loadable_module'):
1874 self.WriteLn('\t@$(call do_cmd,mac_package_framework,,,%s)' %
1875 self.xcode_settings.GetFrameworkVersion())
1876
1877 # Bundle postbuilds can depend on the whole bundle, so run them after
1878 # the bundle is packaged, not already after the bundle binary is done.
1879 for postbuild in postbuilds:
1880 self.WriteLn('\t@' + postbuild)
1881 postbuilds = [] # Don't write postbuilds for target's output.
1882
1883 # Needed by test/mac/gyptest-rebuild.py.
1884 self.WriteLn('\t@true # No-op, used by tests')
1885
1886 # Since this target depends on binary and resources which are in
1887 # nested subfolders, the framework directory will be older than
1888 # its dependencies usually. To prevent this rule from executing
1889 # on every build (expensive, especially with postbuilds), expliclity
1890 # update the time on the framework directory.
1891 self.WriteLn('\t@touch -c %s' % self.output)
1892
1893 if postbuilds:
1894 assert not self.is_mac_bundle, ('Postbuilds for bundles should be done '
1895 'on the bundle, not the binary (target \'%s\')' % self.target)
1896 assert 'product_dir' not in spec, ('Postbuilds do not work with '
1897 'custom product_dir')
1898 self.WriteXcodeEnv(self.output_binary, spec) # For postbuilds
1899 postbuilds = [EscapeShellArgument(p) for p in postbuilds]
1900 self.WriteLn('%s: builddir := $(abs_builddir)' % self.output_binary)
1901 self.WriteLn('%s: POSTBUILDS := %s' % (
1902 self.output_binary, ' '.join(postbuilds)))
1903
1904 if self.type == 'executable':
1905 self.WriteLn(
1906 '%s: LD_INPUTS := %s' % (self.output_binary, ' '.join(link_deps)))
1907 self.WriteDoCmd([self.output_binary], link_deps, 'link', part_of_all,
1908 postbuilds=postbuilds)
1909 elif self.type == 'static_library':
1910 for link_dep in link_deps:
1911 assert ' ' not in link_dep, (
1912 "Spaces in alink input filenames not supported (%s)" % link_dep)
1913 self.WriteDoCmd([self.output_binary], link_deps, 'alink', part_of_all,
1914 postbuilds=postbuilds)
1915 elif self.type == 'shared_library':
1916 self.WriteLn(
1917 '%s: LD_INPUTS := %s' % (self.output_binary, ' '.join(link_deps)))
1918 self.WriteDoCmd([self.output_binary], link_deps, 'solink', part_of_all,
1919 postbuilds=postbuilds)
1920 elif self.type == 'loadable_module':
1921 for link_dep in link_deps:
1922 assert ' ' not in link_dep, (
1923 "Spaces in module input filenames not supported (%s)" % link_dep)
1924 self.WriteDoCmd(
1925 [self.output_binary], link_deps, 'solink_module', part_of_all,
1926 postbuilds=postbuilds)
1927 elif self.type == 'none':
1928 # Write a stamp line.
1929 self.WriteDoCmd([self.output_binary], deps, 'touch', part_of_all,
1930 postbuilds=postbuilds)
1931 elif self.type == 'settings':
1932 # Only used for passing flags around.
1933 pass
1934 else:
1935 print "WARNING: no output for", self.type, target
1936
1937 # Add an alias for each target (if there are any outputs).
1938 # Installable target aliases are created below.
1939 if ((self.output and self.output != self.target) and
1940 (self.type not in self._INSTALLABLE_TARGETS)):
1941 self.WriteMakeRule([self.target], [self.output],
1942 comment='Add target alias', phony = True)
1943 if part_of_all:
1944 self.WriteMakeRule(['all'], [self.target],
1945 comment = 'Add target alias to "all" target.',
1946 phony = True)
1947
1948 # Add special-case rules for our installable targets.
1949 # 1) They need to install to the build dir or "product" dir.
1950 # 2) They get shortcuts for building (e.g. "make chrome").
1951 # 3) They are part of "make all".
1952 if self.type in self._INSTALLABLE_TARGETS:
1953 if self.type == 'shared_library':
1954 file_desc = 'shared library'
1955 else:
1956 file_desc = 'executable'
1957 install_path = self._InstallableTargetInstallPath()
1958 installable_deps = [self.output]
1959 if self.flavor == 'mac' and not 'product_dir' in spec:
1960 # On mac, products are created in install_path immediately.
1961 assert install_path == self.output, '%s != %s' % (
1962 install_path, self.output)
1963
1964 # Point the target alias to the final binary output.
1965 self.WriteMakeRule([self.target], [install_path],
1966 comment='Add target alias', phony = True)
1967 if install_path != self.output:
1968 assert not self.is_mac_bundle # See comment a few lines above.
1969 self.WriteDoCmd([install_path], [self.output], 'copy',
1970 comment = 'Copy this to the %s output path.' %
1971 file_desc, part_of_all=part_of_all)
1972 installable_deps.append(install_path)
1973 if self.output != self.alias and self.alias != self.target:
1974 self.WriteMakeRule([self.alias], installable_deps,
1975 comment = 'Short alias for building this %s.' %
1976 file_desc, phony = True)
1977 if part_of_all:
1978 self.WriteMakeRule(['all'], [install_path],
1979 comment = 'Add %s to "all" target.' % file_desc,
1980 phony = True)
1981
1982
1983 def WriteList(self, list, variable=None, prefix='', quoter=QuoteIfNecessary):
1984 """Write a variable definition that is a list of values.
1985
1986 E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out
1987 foo = blaha blahb
1988 but in a pretty-printed style.
1989 """
1990 self.fp.write(variable + " := ")
1991 if list:
1992 list = [quoter(prefix + l) for l in list]
1993 self.fp.write(" \\\n\t".join(list))
1994 self.fp.write("\n\n")
1995
1996
1997 def WriteDoCmd(self, outputs, inputs, command, part_of_all, comment=None,
1998 postbuilds=False):
1999 """Write a Makefile rule that uses do_cmd.
2000
2001 This makes the outputs dependent on the command line that was run,
2002 as well as support the V= make command line flag.
2003 """
2004 suffix = ''
2005 if postbuilds:
2006 assert ',' not in command
2007 suffix = ',,1' # Tell do_cmd to honor $POSTBUILDS
2008 self.WriteMakeRule(outputs, inputs,
2009 actions = ['$(call do_cmd,%s%s)' % (command, suffix)],
2010 comment = comment,
2011 force = True)
2012 # Add our outputs to the list of targets we read depfiles from.
2013 # all_deps is only used for deps file reading, and for deps files we replace
2014 # spaces with ? because escaping doesn't work with make's $(sort) and
2015 # other functions.
2016 outputs = [ReplaceQuotedSpaces(o) for o in outputs]
2017 self.WriteLn('all_deps += %s' % ' '.join(outputs))
2018 self._num_outputs += len(outputs)
2019
2020
2021 def WriteMakeRule(self, outputs, inputs, actions=None, comment=None,
2022 order_only=False, force=False, phony=False,
2023 multiple_output_trick=True):
2024 """Write a Makefile rule, with some extra tricks.
2025
2026 outputs: a list of outputs for the rule (note: this is not directly
2027 supported by make; see comments below)
2028 inputs: a list of inputs for the rule
2029 actions: a list of shell commands to run for the rule
2030 comment: a comment to put in the Makefile above the rule (also useful
2031 for making this Python script's code self-documenting)
2032 order_only: if true, makes the dependency order-only
2033 force: if true, include FORCE_DO_CMD as an order-only dep
2034 phony: if true, the rule does not actually generate the named output, the
2035 output is just a name to run the rule
2036 multiple_output_trick: if true (the default), perform tricks such as dummy
2037 rules to avoid problems with multiple outputs.
2038 """
2039 if comment:
2040 self.WriteLn('# ' + comment)
2041 if phony:
2042 self.WriteLn('.PHONY: ' + ' '.join(outputs))
2043 # TODO(evanm): just make order_only a list of deps instead of these hacks.
2044 if order_only:
2045 order_insert = '| '
2046 else:
2047 order_insert = ''
2048 if force:
2049 force_append = ' FORCE_DO_CMD'
2050 else:
2051 force_append = ''
2052 if actions:
2053 self.WriteLn("%s: TOOLSET := $(TOOLSET)" % outputs[0])
2054 self.WriteLn('%s: %s%s%s' % (outputs[0], order_insert, ' '.join(inputs),
2055 force_append))
2056 if actions:
2057 for action in actions:
2058 self.WriteLn('\t%s' % action)
2059 if multiple_output_trick and len(outputs) > 1:
2060 # If we have more than one output, a rule like
2061 # foo bar: baz
2062 # that for *each* output we must run the action, potentially
2063 # in parallel. That is not what we're trying to write -- what
2064 # we want is that we run the action once and it generates all
2065 # the files.
2066 # http://www.gnu.org/software/hello/manual/automake/Multiple-Outputs.html
2067 # discusses this problem and has this solution:
2068 # 1) Write the naive rule that would produce parallel runs of
2069 # the action.
2070 # 2) Make the outputs seralized on each other, so we won't start
2071 # a parallel run until the first run finishes, at which point
2072 # we'll have generated all the outputs and we're done.
2073 self.WriteLn('%s: %s' % (' '.join(outputs[1:]), outputs[0]))
2074 # Add a dummy command to the "extra outputs" rule, otherwise make seems to
2075 # think these outputs haven't (couldn't have?) changed, and thus doesn't
2076 # flag them as changed (i.e. include in '$?') when evaluating dependent
2077 # rules, which in turn causes do_cmd() to skip running dependent commands.
2078 self.WriteLn('%s: ;' % (' '.join(outputs[1:])))
2079 self.WriteLn()
2080
2081
2082 def WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps):
2083 """Write a set of LOCAL_XXX definitions for Android NDK.
2084
2085 These variable definitions will be used by Android NDK but do nothing for
2086 non-Android applications.
2087
2088 Arguments:
2089 module_name: Android NDK module name, which must be unique among all
2090 module names.
2091 all_sources: A list of source files (will be filtered by Compilable).
2092 link_deps: A list of link dependencies, which must be sorted in
2093 the order from dependencies to dependents.
2094 """
2095 if self.type not in ('executable', 'shared_library', 'static_library'):
2096 return
2097
2098 self.WriteLn('# Variable definitions for Android applications')
2099 self.WriteLn('include $(CLEAR_VARS)')
2100 self.WriteLn('LOCAL_MODULE := ' + module_name)
2101 self.WriteLn('LOCAL_CFLAGS := $(CFLAGS_$(BUILDTYPE)) '
2102 '$(DEFS_$(BUILDTYPE)) '
2103 # LOCAL_CFLAGS is applied to both of C and C++. There is
2104 # no way to specify $(CFLAGS_C_$(BUILDTYPE)) only for C
2105 # sources.
2106 '$(CFLAGS_C_$(BUILDTYPE)) '
2107 # $(INCS_$(BUILDTYPE)) includes the prefix '-I' while
2108 # LOCAL_C_INCLUDES does not expect it. So put it in
2109 # LOCAL_CFLAGS.
2110 '$(INCS_$(BUILDTYPE))')
2111 # LOCAL_CXXFLAGS is obsolete and LOCAL_CPPFLAGS is preferred.
2112 self.WriteLn('LOCAL_CPPFLAGS := $(CFLAGS_CC_$(BUILDTYPE))')
2113 self.WriteLn('LOCAL_C_INCLUDES :=')
2114 self.WriteLn('LOCAL_LDLIBS := $(LDFLAGS_$(BUILDTYPE)) $(LIBS)')
2115
2116 # Detect the C++ extension.
2117 cpp_ext = {'.cc': 0, '.cpp': 0, '.cxx': 0}
2118 default_cpp_ext = '.cpp'
2119 for filename in all_sources:
2120 ext = os.path.splitext(filename)[1]
2121 if ext in cpp_ext:
2122 cpp_ext[ext] += 1
2123 if cpp_ext[ext] > cpp_ext[default_cpp_ext]:
2124 default_cpp_ext = ext
2125 self.WriteLn('LOCAL_CPP_EXTENSION := ' + default_cpp_ext)
2126
2127 self.WriteList(map(self.Absolutify, filter(Compilable, all_sources)),
2128 'LOCAL_SRC_FILES')
2129
2130 # Filter out those which do not match prefix and suffix and produce
2131 # the resulting list without prefix and suffix.
2132 def DepsToModules(deps, prefix, suffix):
2133 modules = []
2134 for filepath in deps:
2135 filename = os.path.basename(filepath)
2136 if filename.startswith(prefix) and filename.endswith(suffix):
2137 modules.append(filename[len(prefix):-len(suffix)])
2138 return modules
2139
2140 # Retrieve the default value of 'SHARED_LIB_SUFFIX'
2141 params = {'flavor': 'linux'}
2142 default_variables = {}
2143 CalculateVariables(default_variables, params)
2144
2145 self.WriteList(
2146 DepsToModules(link_deps,
2147 generator_default_variables['SHARED_LIB_PREFIX'],
2148 default_variables['SHARED_LIB_SUFFIX']),
2149 'LOCAL_SHARED_LIBRARIES')
2150 self.WriteList(
2151 DepsToModules(link_deps,
2152 generator_default_variables['STATIC_LIB_PREFIX'],
2153 generator_default_variables['STATIC_LIB_SUFFIX']),
2154 'LOCAL_STATIC_LIBRARIES')
2155
2156 if self.type == 'executable':
2157 self.WriteLn('include $(BUILD_EXECUTABLE)')
2158 elif self.type == 'shared_library':
2159 self.WriteLn('include $(BUILD_SHARED_LIBRARY)')
2160 elif self.type == 'static_library':
2161 self.WriteLn('include $(BUILD_STATIC_LIBRARY)')
2162 self.WriteLn()
2163
2164
2165 def WriteLn(self, text=''):
2166 self.fp.write(text + '\n')
2167
2168
2169 def GetXcodeEnv(self, spec, target_relative_path=False):
2170 """Return the environment variables that Xcode would set. See
2171 http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW153
2172 for a full list."""
2173 if self.flavor != 'mac': return {}
2174
2175 built_products_dir = generator_default_variables['PRODUCT_DIR']
2176 def StripProductDir(s):
2177 assert s.startswith(built_products_dir), s
2178 return s[len(built_products_dir) + 1:]
2179
2180 product_name = spec.get('product_name', self.output)
2181
2182 if self._InstallImmediately():
2183 if product_name.startswith(built_products_dir):
2184 product_name = StripProductDir(product_name)
2185
2186 srcroot = self.path
2187 if target_relative_path:
2188 built_products_dir = os.path.relpath(built_products_dir, srcroot)
2189 srcroot = '.'
2190 # These are filled in on a as-needed basis.
2191 env = {
2192 'BUILT_PRODUCTS_DIR' : built_products_dir,
2193 'CONFIGURATION' : '$(BUILDTYPE)',
2194 'PRODUCT_NAME' : product_name,
2195 # See /Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX\ Product\ Types.xcspec for FULL_PRODUCT_NAME
2196 'FULL_PRODUCT_NAME' : product_name,
2197 'SRCROOT' : srcroot,
2198 # This is not true for static libraries, but currently the env is only
2199 # written for bundles:
2200 'TARGET_BUILD_DIR' : built_products_dir,
2201 'TEMP_DIR' : '$(TMPDIR)',
2202 }
2203 if self.type in ('executable', 'shared_library'):
2204 env['EXECUTABLE_NAME'] = os.path.basename(self.output_binary)
2205 if self.type in (
2206 'executable', 'static_library', 'shared_library', 'loadable_module'):
2207 env['EXECUTABLE_PATH'] = self.xcode_settings.GetExecutablePath()
2208 if self.is_mac_bundle:
2209 env['CONTENTS_FOLDER_PATH'] = \
2210 self.xcode_settings.GetBundleContentsFolderPath()
2211 env['UNLOCALIZED_RESOURCES_FOLDER_PATH'] = \
2212 self.xcode_settings.GetBundleResourceFolder()
2213 env['INFOPLIST_PATH'] = self.xcode_settings.GetBundlePlistPath()
2214
2215 # TODO(thakis): Remove this.
2216 env['EXECUTABLE_PATH'] = QuoteSpaces(env['EXECUTABLE_PATH'])
2217 env['CONTENTS_FOLDER_PATH'] = QuoteSpaces(env['CONTENTS_FOLDER_PATH'])
2218 env['INFOPLIST_PATH'] = QuoteSpaces(env['INFOPLIST_PATH'])
2219
2220 return env
2221
2222
2223 def WriteXcodeEnv(self,
2224 target,
2225 spec,
2226 target_relative_path=False,
2227 additional_settings={}):
2228 env = additional_settings
2229 env.update(self.GetXcodeEnv(spec, target_relative_path))
2230
2231 # Keys whose values will not have $(builddir) replaced with $(abs_builddir).
2232 # These have special substitution rules in some cases; see above in
2233 # GetXcodeEnv() for the full rationale.
2234 keys_to_not_absolutify = ('PRODUCT_NAME', 'FULL_PRODUCT_NAME')
2235
2236 # Perform some transformations that are required to mimic Xcode behavior.
2237 for k in env:
2238 # Values that are not strings but are, for example, lists or tuples such
2239 # as LDFLAGS or CFLAGS, should not be written out because they are
2240 # not needed and it's undefined how multi-valued keys should be written.
2241 if not isinstance(env[k], str):
2242 continue
2243
2244 # For
2245 # foo := a\ b
2246 # the escaped space does the right thing. For
2247 # export foo := a\ b
2248 # it does not -- the backslash is written to the env as literal character.
2249 # Hence, unescape all spaces here.
2250 v = env[k].replace(r'\ ', ' ')
2251
2252 # Xcode works purely with absolute paths. When writing env variables to
2253 # mimic its usage, replace $(builddir) with $(abs_builddir).
2254 if k not in keys_to_not_absolutify:
2255 v = v.replace('$(builddir)', '$(abs_builddir)')
2256
2257 self.WriteLn('%s: export %s := %s' % (target, k, v))
2258
2259
2260 def Objectify(self, path):
2261 """Convert a path to its output directory form."""
2262 if '$(' in path:
2263 path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/' % self.toolset)
2264 return path
2265 return '$(obj).%s/$(TARGET)/%s' % (self.toolset, path)
2266
2267
2268 def Pchify(self, path, lang):
2269 """Convert a prefix header path to its output directory form."""
2270 if '$(' in path:
2271 path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/pch-%s' %
2272 (self.toolset, lang))
2273 return path
2274 return '$(obj).%s/$(TARGET)/pch-%s/%s' % (self.toolset, lang, path)
2275
2276
2277 def Absolutify(self, path):
2278 """Convert a subdirectory-relative path into a base-relative path.
2279 Skips over paths that contain variables."""
2280 if '$(' in path:
2281 return path
2282 return os.path.normpath(os.path.join(self.path, path))
2283
2284
2285 def FixupArgPath(self, arg):
2286 if '/' in arg or '.h.' in arg:
2287 return self.Absolutify(arg)
2288 return arg
2289
2290
2291 def ExpandInputRoot(self, template, expansion):
2292 if '%(INPUT_ROOT)s' not in template:
2293 return template
2294 path = template % { 'INPUT_ROOT': expansion }
2295 if not os.path.dirname(path):
2296 # If it's just the file name, turn it into a path so FixupArgPath()
2297 # will know to Absolutify() it.
2298 path = os.path.join('.', path)
2299 return path
2300
2301
2302 def _InstallableTargetInstallPath(self):
2303 """Returns the location of the final output for an installable target."""
2304 # Xcode puts shared_library results into PRODUCT_DIR, and some gyp files
2305 # rely on this. Emulate this behavior for mac.
2306 if self.type == 'shared_library' and self.flavor != 'mac':
2307 # Install all shared libs into a common directory (per toolset) for
2308 # convenient access with LD_LIBRARY_PATH.
2309 return '$(builddir)/lib.%s/%s' % (self.toolset, self.alias)
2310 return '$(builddir)/' + self.alias
2311
2312
2313 def WriteAutoRegenerationRule(params, root_makefile, makefile_name,
2314 build_files):
2315 """Write the target to regenerate the Makefile."""
2316 options = params['options']
2317 build_files_args = [gyp.common.RelativePath(filename, options.toplevel_dir)
2318 for filename in params['build_files_arg']]
2319 gyp_binary = gyp.common.FixIfRelativePath(params['gyp_binary'],
2320 options.toplevel_dir)
2321 if not gyp_binary.startswith(os.sep):
2322 gyp_binary = os.path.join('.', gyp_binary)
2323 root_makefile.write(
2324 "quiet_cmd_regen_makefile = ACTION Regenerating $@\n"
2325 "cmd_regen_makefile = %(cmd)s\n"
2326 "%(makefile_name)s: %(deps)s\n"
2327 "\t$(call do_cmd,regen_makefile)\n\n" % {
2328 'makefile_name': makefile_name,
2329 'deps': ' '.join(map(Sourceify, build_files)),
2330 'cmd': gyp.common.EncodePOSIXShellList(
2331 [gyp_binary, '-fmake'] +
2332 gyp.RegenerateFlags(options) +
2333 build_files_args)})
2334
2335
2336 def RunSystemTests(flavor):
2337 """Run tests against the system to compute default settings for commands.
2338
2339 Returns:
2340 dictionary of settings matching the block of command-lines used in
2341 SHARED_HEADER. E.g. the dictionary will contain a ARFLAGS.target
2342 key for the default ARFLAGS for the target ar command.
2343 """
2344 # Compute flags used for building static archives.
2345 # N.B.: this fallback logic should match the logic in SHARED_HEADER.
2346 # See comment there for more details.
2347 ar_target = os.environ.get('AR.target', os.environ.get('AR', 'ar'))
2348 cc_target = os.environ.get('CC.target', os.environ.get('CC', 'cc'))
2349 arflags_target = 'crs'
2350 # ar -T enables thin archives on Linux. OS X's ar supports a -T flag, but it
2351 # does something useless (it limits filenames in the archive to 15 chars).
2352 if flavor != 'mac' and gyp.system_test.TestArSupportsT(ar_command=ar_target,
2353 cc_command=cc_target):
2354 arflags_target = 'crsT'
2355
2356 ar_host = os.environ.get('AR.host', 'ar')
2357 cc_host = os.environ.get('CC.host', 'gcc')
2358 arflags_host = 'crs'
2359 # It feels redundant to compute this again given that most builds aren't
2360 # cross-compiles, but due to quirks of history CC.host defaults to 'gcc'
2361 # while CC.target defaults to 'cc', so the commands really are different
2362 # even though they're nearly guaranteed to run the same code underneath.
2363 if flavor != 'mac' and gyp.system_test.TestArSupportsT(ar_command=ar_host,
2364 cc_command=cc_host):
2365 arflags_host = 'crsT'
2366
2367 link_flags = ''
2368 if gyp.system_test.TestLinkerSupportsThreads(cc_command=cc_target):
2369 # N.B. we don't test for cross-compilation; as currently written, we
2370 # don't even use flock when linking in the cross-compile setup!
2371 # TODO(evan): refactor cross-compilation such that this code can
2372 # be reused.
2373 link_flags = '-Wl,--threads -Wl,--thread-count=4'
2374
2375 # TODO(evan): cache this output. (But then we'll need to add extra
2376 # flags to gyp to flush the cache, yuk! It's fast enough for now to
2377 # just run it every time.)
2378
2379 return { 'ARFLAGS.target': arflags_target,
2380 'ARFLAGS.host': arflags_host,
2381 'LINK_flags': link_flags }
2382
2383
2384 def CopyMacTool(out_path):
2385 """Finds mac_tool.gyp in the gyp directory and copies it to |out_path|."""
2386 source_path = os.path.join(
2387 os.path.dirname(os.path.abspath(__file__)), '..', 'mac_tool.py')
2388 source_file = open(source_path)
2389 source = source_file.readlines()
2390 source_file.close()
2391 mactool_file = open(out_path, 'w')
2392 mactool_file.write(
2393 ''.join([source[0], '# Generated by gyp. Do not edit.\n'] + source[1:]))
2394 mactool_file.close()
2395
2396
2397 def GenerateOutput(target_list, target_dicts, data, params):
2398 options = params['options']
2399 flavor = GetFlavor(params)
2400 generator_flags = params.get('generator_flags', {})
2401 builddir_name = generator_flags.get('output_dir', 'out')
2402 android_ndk_version = generator_flags.get('android_ndk_version', None)
2403
2404 def CalculateMakefilePath(build_file, base_name):
2405 """Determine where to write a Makefile for a given gyp file."""
2406 # Paths in gyp files are relative to the .gyp file, but we want
2407 # paths relative to the source root for the master makefile. Grab
2408 # the path of the .gyp file as the base to relativize against.
2409 # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp".
2410 base_path = gyp.common.RelativePath(os.path.dirname(build_file),
2411 options.depth)
2412 # We write the file in the base_path directory.
2413 output_file = os.path.join(options.depth, base_path, base_name)
2414 if options.generator_output:
2415 output_file = os.path.join(options.generator_output, output_file)
2416 base_path = gyp.common.RelativePath(os.path.dirname(build_file),
2417 options.toplevel_dir)
2418 return base_path, output_file
2419
2420 # TODO: search for the first non-'Default' target. This can go
2421 # away when we add verification that all targets have the
2422 # necessary configurations.
2423 default_configuration = None
2424 toolsets = set([target_dicts[target]['toolset'] for target in target_list])
2425 for target in target_list:
2426 spec = target_dicts[target]
2427 if spec['default_configuration'] != 'Default':
2428 default_configuration = spec['default_configuration']
2429 break
2430 if not default_configuration:
2431 default_configuration = 'Default'
2432
2433 srcdir = '.'
2434 makefile_name = 'Makefile' + options.suffix
2435 makefile_path = os.path.join(options.toplevel_dir, makefile_name)
2436 if options.generator_output:
2437 global srcdir_prefix
2438 makefile_path = os.path.join(options.generator_output, makefile_path)
2439 srcdir = gyp.common.RelativePath(srcdir, options.generator_output)
2440 srcdir_prefix = '$(srcdir)/'
2441
2442 header_params = {
2443 'builddir': builddir_name,
2444 'default_configuration': default_configuration,
2445 'flock': 'flock',
2446 'flock_index': 1,
2447 'link_commands': LINK_COMMANDS_LINUX,
2448 'mac_commands': '',
2449 'srcdir': srcdir,
2450 }
2451 if flavor == 'mac':
2452 header_params.update({
2453 'flock': './gyp-mac-tool flock',
2454 'flock_index': 2,
2455 'link_commands': LINK_COMMANDS_MAC,
2456 'mac_commands': SHARED_HEADER_MAC_COMMANDS,
2457 })
2458 header_params.update(RunSystemTests(flavor))
2459
2460 build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
2461 make_global_settings_dict = data[build_file].get('make_global_settings', {})
2462 make_global_settings = ''
2463 for key, value in make_global_settings_dict:
2464 if value[0] != '$':
2465 value = '$(abspath %s)' % value
2466 if key == 'LINK':
2467 make_global_settings += '%s ?= $(FLOCK) %s\n' % (key, value)
2468 elif key in ['CC', 'CXX']:
2469 make_global_settings += (
2470 'ifneq (,$(filter $(origin %s), undefined default))\n' % key)
2471 # Let gyp-time envvars win over global settings.
2472 if key in os.environ:
2473 value = os.environ[key]
2474 make_global_settings += ' %s = %s\n' % (key, value)
2475 make_global_settings += 'endif\n'
2476 else:
2477 make_global_settings += '%s ?= %s\n' % (key, value)
2478 header_params['make_global_settings'] = make_global_settings
2479
2480 ensure_directory_exists(makefile_path)
2481 root_makefile = open(makefile_path, 'w')
2482 root_makefile.write(SHARED_HEADER % header_params)
2483 # Currently any versions have the same effect, but in future the behavior
2484 # could be different.
2485 if android_ndk_version:
2486 root_makefile.write(
2487 '# Define LOCAL_PATH for build of Android applications.\n'
2488 'LOCAL_PATH := $(call my-dir)\n'
2489 '\n')
2490 for toolset in toolsets:
2491 root_makefile.write('TOOLSET := %s\n' % toolset)
2492 WriteRootHeaderSuffixRules(root_makefile)
2493
2494 # Put mac_tool next to the root Makefile.
2495 if flavor == 'mac':
2496 mactool_path = os.path.join(os.path.dirname(makefile_path), 'gyp-mac-tool')
2497 if os.path.exists(mactool_path):
2498 os.remove(mactool_path)
2499 CopyMacTool(mactool_path)
2500 os.chmod(mactool_path, 0o755) # Make file executable.
2501
2502 # Find the list of targets that derive from the gyp file(s) being built.
2503 needed_targets = set()
2504 for build_file in params['build_files']:
2505 for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
2506 needed_targets.add(target)
2507
2508 num_outputs = 0
2509 build_files = set()
2510 include_list = set()
2511 for qualified_target in target_list:
2512 build_file, target, toolset = gyp.common.ParseQualifiedTarget(
2513 qualified_target)
2514
2515 this_make_global_settings = data[build_file].get('make_global_settings', {})
2516 assert make_global_settings_dict == this_make_global_settings, (
2517 "make_global_settings needs to be the same for all targets.")
2518
2519 build_files.add(gyp.common.RelativePath(build_file, options.toplevel_dir))
2520 included_files = data[build_file]['included_files']
2521 for included_file in included_files:
2522 # The included_files entries are relative to the dir of the build file
2523 # that included them, so we have to undo that and then make them relative
2524 # to the root dir.
2525 relative_include_file = gyp.common.RelativePath(
2526 gyp.common.UnrelativePath(included_file, build_file),
2527 options.toplevel_dir)
2528 abs_include_file = os.path.abspath(relative_include_file)
2529 # If the include file is from the ~/.gyp dir, we should use absolute path
2530 # so that relocating the src dir doesn't break the path.
2531 if (params['home_dot_gyp'] and
2532 abs_include_file.startswith(params['home_dot_gyp'])):
2533 build_files.add(abs_include_file)
2534 else:
2535 build_files.add(relative_include_file)
2536
2537 base_path, output_file = CalculateMakefilePath(build_file,
2538 target + '.' + toolset + options.suffix + '.mk')
2539
2540 spec = target_dicts[qualified_target]
2541 configs = spec['configurations']
2542
2543 # The xcode generator special-cases global xcode_settings and does something
2544 # that amounts to merging in the global xcode_settings into each local
2545 # xcode_settings dict.
2546 if flavor == 'mac':
2547 global_xcode_settings = data[build_file].get('xcode_settings', {})
2548 for configname in configs.keys():
2549 config = configs[configname]
2550 if 'xcode_settings' in config:
2551 new_settings = global_xcode_settings.copy()
2552 new_settings.update(config['xcode_settings'])
2553 config['xcode_settings'] = new_settings
2554
2555 writer = MakefileWriter(generator_flags, flavor)
2556 writer.Write(qualified_target, base_path, output_file, spec, configs,
2557 part_of_all=qualified_target in needed_targets)
2558 num_outputs += writer.NumOutputs()
2559
2560 # Our root_makefile lives at the source root. Compute the relative path
2561 # from there to the output_file for including.
2562 mkfile_rel_path = gyp.common.RelativePath(output_file,
2563 os.path.dirname(makefile_path))
2564 include_list.add(mkfile_rel_path)
2565
2566 # Write out per-gyp (sub-project) Makefiles.
2567 depth_rel_path = gyp.common.RelativePath(options.depth, os.getcwd())
2568 for build_file in build_files:
2569 # The paths in build_files were relativized above, so undo that before
2570 # testing against the non-relativized items in target_list and before
2571 # calculating the Makefile path.
2572 build_file = os.path.join(depth_rel_path, build_file)
2573 gyp_targets = [target_dicts[target]['target_name'] for target in target_list
2574 if target.startswith(build_file) and
2575 target in needed_targets]
2576 # Only generate Makefiles for gyp files with targets.
2577 if not gyp_targets:
2578 continue
2579 base_path, output_file = CalculateMakefilePath(build_file,
2580 os.path.splitext(os.path.basename(build_file))[0] + '.Makefile')
2581 makefile_rel_path = gyp.common.RelativePath(os.path.dirname(makefile_path),
2582 os.path.dirname(output_file))
2583 writer.WriteSubMake(output_file, makefile_rel_path, gyp_targets,
2584 builddir_name)
2585
2586
2587 # Write out the sorted list of includes.
2588 root_makefile.write('\n')
2589 for include_file in sorted(include_list):
2590 # We wrap each .mk include in an if statement so users can tell make to
2591 # not load a file by setting NO_LOAD. The below make code says, only
2592 # load the .mk file if the .mk filename doesn't start with a token in
2593 # NO_LOAD.
2594 root_makefile.write(
2595 "ifeq ($(strip $(foreach prefix,$(NO_LOAD),\\\n"
2596 " $(findstring $(join ^,$(prefix)),\\\n"
2597 " $(join ^," + include_file + ")))),)\n")
2598 root_makefile.write(" include " + include_file + "\n")
2599 root_makefile.write("endif\n")
2600 root_makefile.write('\n')
2601
2602 if generator_flags.get('auto_regeneration', True):
2603 WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files)
2604
2605 # Write the rule to load dependencies. We batch 1000 files at a time to
2606 # avoid overflowing the command line.
2607 all_deps = ""
2608 for i in range(1001, num_outputs, 1000):
2609 all_deps += ("""
2610 ifneq ($(word %(start)d,$(d_files)),)
2611 $(shell cat $(wordlist %(start)d,%(end)d,$(d_files)) >> $(depsdir)/all.deps)
2612 endif""" % { 'start': i, 'end': i + 999 })
2613
2614 # Add a check to make sure we tried to process all the .d files.
2615 all_deps += """
2616 ifneq ($(word %(last)d,$(d_files)),)
2617 $(error Found unprocessed dependency files (gyp didn't generate enough rules!))
2618 endif
2619 """ % { 'last': ((num_outputs / 1000) + 1) * 1000 + 1 }
2620
2621 root_makefile.write(SHARED_FOOTER % { 'generate_all_deps': all_deps })
2622
2623 root_makefile.close()
+0
-2876
third_party/gyp/pylib/gyp/generator/msvs.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import copy
7 import ntpath
8 import os
9 import posixpath
10 import re
11 import subprocess
12 import sys
13
14 import gyp.common
15 import gyp.easy_xml as easy_xml
16 import gyp.MSVSNew as MSVSNew
17 import gyp.MSVSProject as MSVSProject
18 import gyp.MSVSSettings as MSVSSettings
19 import gyp.MSVSToolFile as MSVSToolFile
20 import gyp.MSVSUserFile as MSVSUserFile
21 import gyp.MSVSVersion as MSVSVersion
22
23
24 # Regular expression for validating Visual Studio GUIDs. If the GUID
25 # contains lowercase hex letters, MSVS will be fine. However,
26 # IncrediBuild BuildConsole will parse the solution file, but then
27 # silently skip building the target causing hard to track down errors.
28 # Note that this only happens with the BuildConsole, and does not occur
29 # if IncrediBuild is executed from inside Visual Studio. This regex
30 # validates that the string looks like a GUID with all uppercase hex
31 # letters.
32 VALID_MSVS_GUID_CHARS = re.compile('^[A-F0-9\-]+$')
33
34
35 generator_default_variables = {
36 'EXECUTABLE_PREFIX': '',
37 'EXECUTABLE_SUFFIX': '.exe',
38 'STATIC_LIB_PREFIX': '',
39 'SHARED_LIB_PREFIX': '',
40 'STATIC_LIB_SUFFIX': '.lib',
41 'SHARED_LIB_SUFFIX': '.dll',
42 'INTERMEDIATE_DIR': '$(IntDir)',
43 'SHARED_INTERMEDIATE_DIR': '$(OutDir)/obj/global_intermediate',
44 'OS': 'win',
45 'PRODUCT_DIR': '$(OutDir)',
46
47 # TODO(jeanluc) The way we currently generate libraries makes Visual
48 # Studio 2010 unhappy. We get a lot of warnings like:
49 # warning MSB8012: TargetPath(...\Debug\gles2_c_lib.lib) does not match
50 # the Library's OutputFile property value (...\Debug\lib\gles2_c_lib.lib).
51 # This may cause your project to build incorrectly. To correct this,
52 # please make sure that $(OutDir), $(TargetName) and $(TargetExt) property
53 # values match the value specified in %(Lib.OutputFile).
54 # Despite the warnings, this compile correctly. It would be nice to get rid
55 # of the warnings.
56
57 # TODO(jeanluc) I had: 'LIB_DIR': '$(OutDir)lib',
58 'LIB_DIR': '$(OutDir)/lib',
59 'RULE_INPUT_ROOT': '$(InputName)',
60 'RULE_INPUT_EXT': '$(InputExt)',
61 'RULE_INPUT_NAME': '$(InputFileName)',
62 'RULE_INPUT_PATH': '$(InputPath)',
63 'CONFIGURATION_NAME': '$(ConfigurationName)',
64 }
65
66
67 # The msvs specific sections that hold paths
68 generator_additional_path_sections = [
69 'msvs_cygwin_dirs',
70 'msvs_props',
71 ]
72
73
74 generator_additional_non_configuration_keys = [
75 'msvs_cygwin_dirs',
76 'msvs_cygwin_shell',
77 'msvs_shard',
78 ]
79
80
81 # List of precompiled header related keys.
82 precomp_keys = [
83 'msvs_precompiled_header',
84 'msvs_precompiled_source',
85 ]
86
87
88 cached_username = None
89
90
91 cached_domain = None
92
93
94 # TODO(gspencer): Switch the os.environ calls to be
95 # win32api.GetDomainName() and win32api.GetUserName() once the
96 # python version in depot_tools has been updated to work on Vista
97 # 64-bit.
98 def _GetDomainAndUserName():
99 if sys.platform not in ('win32', 'cygwin'):
100 return ('DOMAIN', 'USERNAME')
101 global cached_username
102 global cached_domain
103 if not cached_domain or not cached_username:
104 domain = os.environ.get('USERDOMAIN')
105 username = os.environ.get('USERNAME')
106 if not domain or not username:
107 call = subprocess.Popen(['net', 'config', 'Workstation'],
108 stdout=subprocess.PIPE)
109 config = call.communicate()[0]
110 username_re = re.compile('^User name\s+(\S+)', re.MULTILINE)
111 username_match = username_re.search(config)
112 if username_match:
113 username = username_match.group(1)
114 domain_re = re.compile('^Logon domain\s+(\S+)', re.MULTILINE)
115 domain_match = domain_re.search(config)
116 if domain_match:
117 domain = domain_match.group(1)
118 cached_domain = domain
119 cached_username = username
120 return (cached_domain, cached_username)
121
122 fixpath_prefix = None
123
124
125 def _NormalizedSource(source):
126 """Normalize the path.
127
128 But not if that gets rid of a variable, as this may expand to something
129 larger than one directory.
130
131 Arguments:
132 source: The path to be normalize.d
133
134 Returns:
135 The normalized path.
136 """
137 normalized = os.path.normpath(source)
138 if source.count('$') == normalized.count('$'):
139 source = normalized
140 return source
141
142
143 def _FixPath(path):
144 """Convert paths to a form that will make sense in a vcproj file.
145
146 Arguments:
147 path: The path to convert, may contain / etc.
148 Returns:
149 The path with all slashes made into backslashes.
150 """
151 if fixpath_prefix and path and not os.path.isabs(path) and not path[0] == '$':
152 path = os.path.join(fixpath_prefix, path)
153 path = path.replace('/', '\\')
154 path = _NormalizedSource(path)
155 if path and path[-1] == '\\':
156 path = path[:-1]
157 return path
158
159
160 def _FixPaths(paths):
161 """Fix each of the paths of the list."""
162 return [_FixPath(i) for i in paths]
163
164
165 def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None):
166 """Converts a list split source file paths into a vcproj folder hierarchy.
167
168 Arguments:
169 sources: A list of source file paths split.
170 prefix: A list of source file path layers meant to apply to each of sources.
171 excluded: A set of excluded files.
172
173 Returns:
174 A hierarchy of filenames and MSVSProject.Filter objects that matches the
175 layout of the source tree.
176 For example:
177 _ConvertSourcesToFilterHierarchy([['a', 'bob1.c'], ['b', 'bob2.c']],
178 prefix=['joe'])
179 -->
180 [MSVSProject.Filter('a', contents=['joe\\a\\bob1.c']),
181 MSVSProject.Filter('b', contents=['joe\\b\\bob2.c'])]
182 """
183 if not prefix: prefix = []
184 result = []
185 excluded_result = []
186 folders = dict()
187 # Gather files into the final result, excluded, or folders.
188 for s in sources:
189 if len(s) == 1:
190 filename = _NormalizedSource('\\'.join(prefix + s))
191 if filename in excluded:
192 excluded_result.append(filename)
193 else:
194 result.append(filename)
195 else:
196 if not folders.get(s[0]):
197 folders[s[0]] = []
198 folders[s[0]].append(s[1:])
199 # Add a folder for excluded files.
200 if excluded_result:
201 excluded_folder = MSVSProject.Filter('_excluded_files',
202 contents=excluded_result)
203 result.append(excluded_folder)
204 # Populate all the folders.
205 for f in folders:
206 contents = _ConvertSourcesToFilterHierarchy(folders[f], prefix=prefix + [f],
207 excluded=excluded)
208 contents = MSVSProject.Filter(f, contents=contents)
209 result.append(contents)
210
211 return result
212
213
214 def _ToolAppend(tools, tool_name, setting, value, only_if_unset=False):
215 if not value: return
216 # TODO(bradnelson): ugly hack, fix this more generally!!!
217 if 'Directories' in setting or 'Dependencies' in setting:
218 if type(value) == str:
219 value = value.replace('/', '\\')
220 else:
221 value = [i.replace('/', '\\') for i in value]
222 if not tools.get(tool_name):
223 tools[tool_name] = dict()
224 tool = tools[tool_name]
225 if tool.get(setting):
226 if only_if_unset: return
227 if type(tool[setting]) == list:
228 tool[setting] += value
229 else:
230 raise TypeError(
231 'Appending "%s" to a non-list setting "%s" for tool "%s" is '
232 'not allowed, previous value: %s' % (
233 value, setting, tool_name, str(tool[setting])))
234 else:
235 tool[setting] = value
236
237
238 def _ConfigPlatform(config_data):
239 return config_data.get('msvs_configuration_platform', 'Win32')
240
241
242 def _ConfigBaseName(config_name, platform_name):
243 if config_name.endswith('_' + platform_name):
244 return config_name[0:-len(platform_name)-1]
245 else:
246 return config_name
247
248
249 def _ConfigFullName(config_name, config_data):
250 platform_name = _ConfigPlatform(config_data)
251 return '%s|%s' % (_ConfigBaseName(config_name, platform_name), platform_name)
252
253
254 def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path,
255 quote_cmd):
256 if cygwin_shell:
257 # Find path to cygwin.
258 cygwin_dir = _FixPath(spec.get('msvs_cygwin_dirs', ['.'])[0])
259 # Prepare command.
260 direct_cmd = cmd
261 direct_cmd = [i.replace('$(IntDir)',
262 '`cygpath -m "${INTDIR}"`') for i in direct_cmd]
263 direct_cmd = [i.replace('$(OutDir)',
264 '`cygpath -m "${OUTDIR}"`') for i in direct_cmd]
265 if has_input_path:
266 direct_cmd = [i.replace('$(InputPath)',
267 '`cygpath -m "${INPUTPATH}"`')
268 for i in direct_cmd]
269 direct_cmd = ['"%s"' % i for i in direct_cmd]
270 direct_cmd = [i.replace('"', '\\"') for i in direct_cmd]
271 #direct_cmd = gyp.common.EncodePOSIXShellList(direct_cmd)
272 direct_cmd = ' '.join(direct_cmd)
273 # TODO(quote): regularize quoting path names throughout the module
274 cmd = (
275 'call "$(ProjectDir)%(cygwin_dir)s\\setup_env.bat" && '
276 'set CYGWIN=nontsec&& ')
277 if direct_cmd.find('NUMBER_OF_PROCESSORS') >= 0:
278 cmd += 'set /a NUMBER_OF_PROCESSORS_PLUS_1=%%NUMBER_OF_PROCESSORS%%+1&& '
279 if direct_cmd.find('INTDIR') >= 0:
280 cmd += 'set INTDIR=$(IntDir)&& '
281 if direct_cmd.find('OUTDIR') >= 0:
282 cmd += 'set OUTDIR=$(OutDir)&& '
283 if has_input_path and direct_cmd.find('INPUTPATH') >= 0:
284 cmd += 'set INPUTPATH=$(InputPath) && '
285 cmd += 'bash -c "%(cmd)s"'
286 cmd = cmd % {'cygwin_dir': cygwin_dir,
287 'cmd': direct_cmd}
288 return cmd
289 else:
290 # Convert cat --> type to mimic unix.
291 if cmd[0] == 'cat':
292 command = ['type']
293 else:
294 command = [cmd[0].replace('/', '\\')]
295 # Fix the paths
296 # If the argument starts with a slash, it's probably a command line switch
297 arguments = [i.startswith('/') and i or _FixPath(i) for i in cmd[1:]]
298 if quote_cmd:
299 # Support a mode for using cmd directly.
300 # Convert any paths to native form (first element is used directly).
301 # TODO(quote): regularize quoting path names throughout the module
302 arguments = ['"%s"' % i for i in arguments]
303 # Collapse into a single command.
304 return ' '.join(command + arguments)
305
306
307 def _BuildCommandLineForRule(spec, rule, has_input_path):
308 # Find path to cygwin.
309 cygwin_dir = _FixPath(spec.get('msvs_cygwin_dirs', ['.'])[0])
310
311 # Currently this weird argument munging is used to duplicate the way a
312 # python script would need to be run as part of the chrome tree.
313 # Eventually we should add some sort of rule_default option to set this
314 # per project. For now the behavior chrome needs is the default.
315 mcs = rule.get('msvs_cygwin_shell')
316 if mcs is None:
317 mcs = int(spec.get('msvs_cygwin_shell', 1))
318 elif isinstance(mcs, str):
319 mcs = int(mcs)
320 quote_cmd = int(rule.get('msvs_quote_cmd', 1))
321 return _BuildCommandLineForRuleRaw(spec, rule['action'], mcs, has_input_path,
322 quote_cmd)
323
324
325 def _AddActionStep(actions_dict, inputs, outputs, description, command):
326 """Merge action into an existing list of actions.
327
328 Care must be taken so that actions which have overlapping inputs either don't
329 get assigned to the same input, or get collapsed into one.
330
331 Arguments:
332 actions_dict: dictionary keyed on input name, which maps to a list of
333 dicts describing the actions attached to that input file.
334 inputs: list of inputs
335 outputs: list of outputs
336 description: description of the action
337 command: command line to execute
338 """
339 # Require there to be at least one input (call sites will ensure this).
340 assert inputs
341
342 action = {
343 'inputs': inputs,
344 'outputs': outputs,
345 'description': description,
346 'command': command,
347 }
348
349 # Pick where to stick this action.
350 # While less than optimal in terms of build time, attach them to the first
351 # input for now.
352 chosen_input = inputs[0]
353
354 # Add it there.
355 if chosen_input not in actions_dict:
356 actions_dict[chosen_input] = []
357 actions_dict[chosen_input].append(action)
358
359
360 def _AddCustomBuildToolForMSVS(p, spec, primary_input,
361 inputs, outputs, description, cmd):
362 """Add a custom build tool to execute something.
363
364 Arguments:
365 p: the target project
366 spec: the target project dict
367 primary_input: input file to attach the build tool to
368 inputs: list of inputs
369 outputs: list of outputs
370 description: description of the action
371 cmd: command line to execute
372 """
373 inputs = _FixPaths(inputs)
374 outputs = _FixPaths(outputs)
375 tool = MSVSProject.Tool(
376 'VCCustomBuildTool',
377 {'Description': description,
378 'AdditionalDependencies': ';'.join(inputs),
379 'Outputs': ';'.join(outputs),
380 'CommandLine': cmd,
381 })
382 # Add to the properties of primary input for each config.
383 for config_name, c_data in spec['configurations'].iteritems():
384 p.AddFileConfig(_FixPath(primary_input),
385 _ConfigFullName(config_name, c_data), tools=[tool])
386
387
388 def _AddAccumulatedActionsToMSVS(p, spec, actions_dict):
389 """Add actions accumulated into an actions_dict, merging as needed.
390
391 Arguments:
392 p: the target project
393 spec: the target project dict
394 actions_dict: dictionary keyed on input name, which maps to a list of
395 dicts describing the actions attached to that input file.
396 """
397 for primary_input in actions_dict:
398 inputs = set()
399 outputs = set()
400 descriptions = []
401 commands = []
402 for action in actions_dict[primary_input]:
403 inputs.update(set(action['inputs']))
404 outputs.update(set(action['outputs']))
405 descriptions.append(action['description'])
406 commands.append(action['command'])
407 # Add the custom build step for one input file.
408 description = ', and also '.join(descriptions)
409 command = '\r\n'.join(commands)
410 _AddCustomBuildToolForMSVS(p, spec,
411 primary_input=primary_input,
412 inputs=inputs,
413 outputs=outputs,
414 description=description,
415 cmd=command)
416
417
418 def _RuleExpandPath(path, input_file):
419 """Given the input file to which a rule applied, string substitute a path.
420
421 Arguments:
422 path: a path to string expand
423 input_file: the file to which the rule applied.
424 Returns:
425 The string substituted path.
426 """
427 path = path.replace('$(InputName)',
428 os.path.splitext(os.path.split(input_file)[1])[0])
429 path = path.replace('$(InputExt)',
430 os.path.splitext(os.path.split(input_file)[1])[1])
431 path = path.replace('$(InputFileName)', os.path.split(input_file)[1])
432 path = path.replace('$(InputPath)', input_file)
433 return path
434
435
436 def _FindRuleTriggerFiles(rule, sources):
437 """Find the list of files which a particular rule applies to.
438
439 Arguments:
440 rule: the rule in question
441 sources: the set of all known source files for this project
442 Returns:
443 The list of sources that trigger a particular rule.
444 """
445 rule_ext = rule['extension']
446 return [s for s in sources if s.endswith('.' + rule_ext)]
447
448
449 def _RuleInputsAndOutputs(rule, trigger_file):
450 """Find the inputs and outputs generated by a rule.
451
452 Arguments:
453 rule: the rule in question.
454 trigger_file: the main trigger for this rule.
455 Returns:
456 The pair of (inputs, outputs) involved in this rule.
457 """
458 raw_inputs = _FixPaths(rule.get('inputs', []))
459 raw_outputs = _FixPaths(rule.get('outputs', []))
460 inputs = set()
461 outputs = set()
462 inputs.add(trigger_file)
463 for i in raw_inputs:
464 inputs.add(_RuleExpandPath(i, trigger_file))
465 for o in raw_outputs:
466 outputs.add(_RuleExpandPath(o, trigger_file))
467 return (inputs, outputs)
468
469
470 def _GenerateNativeRulesForMSVS(p, rules, output_dir, spec, options):
471 """Generate a native rules file.
472
473 Arguments:
474 p: the target project
475 rules: the set of rules to include
476 output_dir: the directory in which the project/gyp resides
477 spec: the project dict
478 options: global generator options
479 """
480 rules_filename = '%s%s.rules' % (spec['target_name'],
481 options.suffix)
482 rules_file = MSVSToolFile.Writer(os.path.join(output_dir, rules_filename),
483 spec['target_name'])
484 # Add each rule.
485 for r in rules:
486 rule_name = r['rule_name']
487 rule_ext = r['extension']
488 inputs = _FixPaths(r.get('inputs', []))
489 outputs = _FixPaths(r.get('outputs', []))
490 cmd = _BuildCommandLineForRule(spec, r, has_input_path=True)
491 rules_file.AddCustomBuildRule(name=rule_name,
492 description=r.get('message', rule_name),
493 extensions=[rule_ext],
494 additional_dependencies=inputs,
495 outputs=outputs,
496 cmd=cmd)
497 # Write out rules file.
498 rules_file.WriteIfChanged()
499
500 # Add rules file to project.
501 p.AddToolFile(rules_filename)
502
503
504 def _Cygwinify(path):
505 path = path.replace('$(OutDir)', '$(OutDirCygwin)')
506 path = path.replace('$(IntDir)', '$(IntDirCygwin)')
507 return path
508
509
510 def _GenerateExternalRules(rules, output_dir, spec,
511 sources, options, actions_to_add):
512 """Generate an external makefile to do a set of rules.
513
514 Arguments:
515 rules: the list of rules to include
516 output_dir: path containing project and gyp files
517 spec: project specification data
518 sources: set of sources known
519 options: global generator options
520 actions_to_add: The list of actions we will add to.
521 """
522 filename = '%s_rules%s.mk' % (spec['target_name'], options.suffix)
523 mk_file = gyp.common.WriteOnDiff(os.path.join(output_dir, filename))
524 # Find cygwin style versions of some paths.
525 mk_file.write('OutDirCygwin:=$(shell cygpath -u "$(OutDir)")\n')
526 mk_file.write('IntDirCygwin:=$(shell cygpath -u "$(IntDir)")\n')
527 # Gather stuff needed to emit all: target.
528 all_inputs = set()
529 all_outputs = set()
530 all_output_dirs = set()
531 first_outputs = []
532 for rule in rules:
533 trigger_files = _FindRuleTriggerFiles(rule, sources)
534 for tf in trigger_files:
535 inputs, outputs = _RuleInputsAndOutputs(rule, tf)
536 all_inputs.update(set(inputs))
537 all_outputs.update(set(outputs))
538 # Only use one target from each rule as the dependency for
539 # 'all' so we don't try to build each rule multiple times.
540 first_outputs.append(list(outputs)[0])
541 # Get the unique output directories for this rule.
542 output_dirs = [os.path.split(i)[0] for i in outputs]
543 for od in output_dirs:
544 all_output_dirs.add(od)
545 first_outputs_cyg = [_Cygwinify(i) for i in first_outputs]
546 # Write out all: target, including mkdir for each output directory.
547 mk_file.write('all: %s\n' % ' '.join(first_outputs_cyg))
548 for od in all_output_dirs:
549 mk_file.write('\tmkdir -p %s\n' % od)
550 mk_file.write('\n')
551 # Define how each output is generated.
552 for rule in rules:
553 trigger_files = _FindRuleTriggerFiles(rule, sources)
554 for tf in trigger_files:
555 # Get all the inputs and outputs for this rule for this trigger file.
556 inputs, outputs = _RuleInputsAndOutputs(rule, tf)
557 inputs = [_Cygwinify(i) for i in inputs]
558 outputs = [_Cygwinify(i) for i in outputs]
559 # Prepare the command line for this rule.
560 cmd = [_RuleExpandPath(c, tf) for c in rule['action']]
561 cmd = ['"%s"' % i for i in cmd]
562 cmd = ' '.join(cmd)
563 # Add it to the makefile.
564 mk_file.write('%s: %s\n' % (' '.join(outputs), ' '.join(inputs)))
565 mk_file.write('\t%s\n\n' % cmd)
566 # Close up the file.
567 mk_file.close()
568
569 # Add makefile to list of sources.
570 sources.add(filename)
571 # Add a build action to call makefile.
572 cmd = ['make',
573 'OutDir=$(OutDir)',
574 'IntDir=$(IntDir)',
575 '-j', '${NUMBER_OF_PROCESSORS_PLUS_1}',
576 '-f', filename]
577 cmd = _BuildCommandLineForRuleRaw(spec, cmd, True, False, True)
578 # Insert makefile as 0'th input, so it gets the action attached there,
579 # as this is easier to understand from in the IDE.
580 all_inputs = list(all_inputs)
581 all_inputs.insert(0, filename)
582 _AddActionStep(actions_to_add,
583 inputs=_FixPaths(all_inputs),
584 outputs=_FixPaths(all_outputs),
585 description='Running %s' % cmd,
586 command=cmd)
587
588
589 def _EscapeEnvironmentVariableExpansion(s):
590 """Escapes % characters.
591
592 Escapes any % characters so that Windows-style environment variable
593 expansions will leave them alone.
594 See http://connect.microsoft.com/VisualStudio/feedback/details/106127/cl-d-name-text-containing-percentage-characters-doesnt-compile
595 to understand why we have to do this.
596
597 Args:
598 s: The string to be escaped.
599
600 Returns:
601 The escaped string.
602 """
603 s = s.replace('%', '%%')
604 return s
605
606
607 quote_replacer_regex = re.compile(r'(\\*)"')
608
609
610 def _EscapeCommandLineArgumentForMSVS(s):
611 """Escapes a Windows command-line argument.
612
613 So that the Win32 CommandLineToArgv function will turn the escaped result back
614 into the original string.
615 See http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
616 ("Parsing C++ Command-Line Arguments") to understand why we have to do
617 this.
618
619 Args:
620 s: the string to be escaped.
621 Returns:
622 the escaped string.
623 """
624
625 def _Replace(match):
626 # For a literal quote, CommandLineToArgv requires an odd number of
627 # backslashes preceding it, and it produces half as many literal backslashes
628 # (rounded down). So we need to produce 2n+1 backslashes.
629 return 2 * match.group(1) + '\\"'
630
631 # Escape all quotes so that they are interpreted literally.
632 s = quote_replacer_regex.sub(_Replace, s)
633 # Now add unescaped quotes so that any whitespace is interpreted literally.
634 s = '"' + s + '"'
635 return s
636
637
638 delimiters_replacer_regex = re.compile(r'(\\*)([,;]+)')
639
640
641 def _EscapeVCProjCommandLineArgListItem(s):
642 """Escapes command line arguments for MSVS.
643
644 The VCProj format stores string lists in a single string using commas and
645 semi-colons as separators, which must be quoted if they are to be
646 interpreted literally. However, command-line arguments may already have
647 quotes, and the VCProj parser is ignorant of the backslash escaping
648 convention used by CommandLineToArgv, so the command-line quotes and the
649 VCProj quotes may not be the same quotes. So to store a general
650 command-line argument in a VCProj list, we need to parse the existing
651 quoting according to VCProj's convention and quote any delimiters that are
652 not already quoted by that convention. The quotes that we add will also be
653 seen by CommandLineToArgv, so if backslashes precede them then we also have
654 to escape those backslashes according to the CommandLineToArgv
655 convention.
656
657 Args:
658 s: the string to be escaped.
659 Returns:
660 the escaped string.
661 """
662
663 def _Replace(match):
664 # For a non-literal quote, CommandLineToArgv requires an even number of
665 # backslashes preceding it, and it produces half as many literal
666 # backslashes. So we need to produce 2n backslashes.
667 return 2 * match.group(1) + '"' + match.group(2) + '"'
668
669 segments = s.split('"')
670 # The unquoted segments are at the even-numbered indices.
671 for i in range(0, len(segments), 2):
672 segments[i] = delimiters_replacer_regex.sub(_Replace, segments[i])
673 # Concatenate back into a single string
674 s = '"'.join(segments)
675 if len(segments) % 2 == 0:
676 # String ends while still quoted according to VCProj's convention. This
677 # means the delimiter and the next list item that follow this one in the
678 # .vcproj file will be misinterpreted as part of this item. There is nothing
679 # we can do about this. Adding an extra quote would correct the problem in
680 # the VCProj but cause the same problem on the final command-line. Moving
681 # the item to the end of the list does works, but that's only possible if
682 # there's only one such item. Let's just warn the user.
683 print >> sys.stderr, ('Warning: MSVS may misinterpret the odd number of ' +
684 'quotes in ' + s)
685 return s
686
687
688 def _EscapeCppDefineForMSVS(s):
689 """Escapes a CPP define so that it will reach the compiler unaltered."""
690 s = _EscapeEnvironmentVariableExpansion(s)
691 s = _EscapeCommandLineArgumentForMSVS(s)
692 s = _EscapeVCProjCommandLineArgListItem(s)
693 return s
694
695
696 quote_replacer_regex2 = re.compile(r'(\\+)"')
697
698
699 def _EscapeCommandLineArgumentForMSBuild(s):
700 """Escapes a Windows command-line argument for use by MSBuild."""
701
702 def _Replace(match):
703 return (len(match.group(1))/2*4)*'\\' + '\\"'
704
705 # Escape all quotes so that they are interpreted literally.
706 s = quote_replacer_regex2.sub(_Replace, s)
707 return s
708
709
710 def _EscapeMSBuildSpecialCharacters(s):
711 escape_dictionary = {
712 '%': '%25',
713 '$': '%24',
714 '@': '%40',
715 "'": '%27',
716 ';': '%3B',
717 '?': '%3F',
718 '*': '%2A'
719 }
720 result = ''.join([escape_dictionary.get(c, c) for c in s])
721 return result
722
723
724 def _EscapeCppDefineForMSBuild(s):
725 """Escapes a CPP define so that it will reach the compiler unaltered."""
726 s = _EscapeEnvironmentVariableExpansion(s)
727 s = _EscapeCommandLineArgumentForMSBuild(s)
728 s = _EscapeMSBuildSpecialCharacters(s)
729 return s
730
731
732 def _GenerateRulesForMSVS(p, output_dir, options, spec,
733 sources, excluded_sources,
734 actions_to_add):
735 """Generate all the rules for a particular project.
736
737 Arguments:
738 p: the project
739 output_dir: directory to emit rules to
740 options: global options passed to the generator
741 spec: the specification for this project
742 sources: the set of all known source files in this project
743 excluded_sources: the set of sources excluded from normal processing
744 actions_to_add: deferred list of actions to add in
745 """
746 rules = spec.get('rules', [])
747 rules_native = [r for r in rules if not int(r.get('msvs_external_rule', 0))]
748 rules_external = [r for r in rules if int(r.get('msvs_external_rule', 0))]
749
750 # Handle rules that use a native rules file.
751 if rules_native:
752 _GenerateNativeRulesForMSVS(p, rules_native, output_dir, spec, options)
753
754 # Handle external rules (non-native rules).
755 if rules_external:
756 _GenerateExternalRules(rules_external, output_dir, spec,
757 sources, options, actions_to_add)
758 _AdjustSourcesForRules(rules, sources, excluded_sources)
759
760
761 def _AdjustSourcesForRules(rules, sources, excluded_sources):
762 # Add outputs generated by each rule (if applicable).
763 for rule in rules:
764 # Done if not processing outputs as sources.
765 if int(rule.get('process_outputs_as_sources', False)):
766 # Add in the outputs from this rule.
767 trigger_files = _FindRuleTriggerFiles(rule, sources)
768 for trigger_file in trigger_files:
769 inputs, outputs = _RuleInputsAndOutputs(rule, trigger_file)
770 inputs = set(_FixPaths(inputs))
771 outputs = set(_FixPaths(outputs))
772 inputs.remove(_FixPath(trigger_file))
773 sources.update(inputs)
774 excluded_sources.update(inputs)
775 sources.update(outputs)
776
777
778 def _FilterActionsFromExcluded(excluded_sources, actions_to_add):
779 """Take inputs with actions attached out of the list of exclusions.
780
781 Arguments:
782 excluded_sources: list of source files not to be built.
783 actions_to_add: dict of actions keyed on source file they're attached to.
784 Returns:
785 excluded_sources with files that have actions attached removed.
786 """
787 must_keep = set(_FixPaths(actions_to_add.keys()))
788 return [s for s in excluded_sources if s not in must_keep]
789
790
791 def _GetDefaultConfiguration(spec):
792 return spec['configurations'][spec['default_configuration']]
793
794
795 def _GetGuidOfProject(proj_path, spec):
796 """Get the guid for the project.
797
798 Arguments:
799 proj_path: Path of the vcproj or vcxproj file to generate.
800 spec: The target dictionary containing the properties of the target.
801 Returns:
802 the guid.
803 Raises:
804 ValueError: if the specified GUID is invalid.
805 """
806 # Pluck out the default configuration.
807 default_config = _GetDefaultConfiguration(spec)
808 # Decide the guid of the project.
809 guid = default_config.get('msvs_guid')
810 if guid:
811 if VALID_MSVS_GUID_CHARS.match(guid) is None:
812 raise ValueError('Invalid MSVS guid: "%s". Must match regex: "%s".' %
813 (guid, VALID_MSVS_GUID_CHARS.pattern))
814 guid = '{%s}' % guid
815 guid = guid or MSVSNew.MakeGuid(proj_path)
816 return guid
817
818
819 def _GenerateProject(project, options, version):
820 """Generates a vcproj file.
821
822 Arguments:
823 project: the MSVSProject object.
824 options: global generator options.
825 version: the MSVSVersion object.
826 """
827 default_config = _GetDefaultConfiguration(project.spec)
828
829 # Skip emitting anything if told to with msvs_existing_vcproj option.
830 if default_config.get('msvs_existing_vcproj'):
831 return
832
833 if version.UsesVcxproj():
834 _GenerateMSBuildProject(project, options, version)
835 else:
836 _GenerateMSVSProject(project, options, version)
837
838
839 def _GenerateMSVSProject(project, options, version):
840 """Generates a .vcproj file. It may create .rules and .user files too.
841
842 Arguments:
843 project: The project object we will generate the file for.
844 options: Global options passed to the generator.
845 version: The VisualStudioVersion object.
846 """
847 spec = project.spec
848 vcproj_dir = os.path.dirname(project.path)
849 if vcproj_dir and not os.path.exists(vcproj_dir):
850 os.makedirs(vcproj_dir)
851
852 platforms = _GetUniquePlatforms(spec)
853 p = MSVSProject.Writer(project.path, version, spec['target_name'],
854 project.guid, platforms)
855
856 # Get directory project file is in.
857 gyp_dir = os.path.split(project.path)[0]
858 gyp_file = posixpath.split(project.build_file)[1]
859 gyp_path = _NormalizedSource(gyp_file)
860 relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, gyp_dir)
861
862 config_type = _GetMSVSConfigurationType(spec, project.build_file)
863 for config_name, config in spec['configurations'].iteritems():
864 _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config)
865
866 # Prepare list of sources and excluded sources.
867 sources, excluded_sources = _PrepareListOfSources(spec,
868 relative_path_of_gyp_file)
869
870 # Add rules.
871 actions_to_add = {}
872 _GenerateRulesForMSVS(p, gyp_dir, options, spec,
873 sources, excluded_sources,
874 actions_to_add)
875 sources, excluded_sources, excluded_idl = (
876 _AdjustSourcesAndConvertToFilterHierarchy(
877 spec, options, gyp_dir, sources, excluded_sources))
878
879 # Add in files.
880 _VerifySourcesExist(sources, gyp_dir)
881 p.AddFiles(sources)
882
883 _AddToolFilesToMSVS(p, spec)
884 _HandlePreCompileHeaderStubs(p, spec)
885 _AddActions(actions_to_add, spec, relative_path_of_gyp_file)
886 _AddCopies(actions_to_add, spec)
887 _WriteMSVSUserFile(project.path, version, spec)
888
889 # NOTE: this stanza must appear after all actions have been decided.
890 # Don't excluded sources with actions attached, or they won't run.
891 excluded_sources = _FilterActionsFromExcluded(
892 excluded_sources, actions_to_add)
893 _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl)
894 _AddAccumulatedActionsToMSVS(p, spec, actions_to_add)
895
896 # Write it out.
897 p.WriteIfChanged()
898
899
900 def _GetUniquePlatforms(spec):
901 """Returns the list of unique platforms for this spec, e.g ['win32', ...].
902
903 Arguments:
904 spec: The target dictionary containing the properties of the target.
905 Returns:
906 The MSVSUserFile object created.
907 """
908 # Gather list of unique platforms.
909 platforms = set()
910 for configuration in spec['configurations']:
911 platforms.add(_ConfigPlatform(spec['configurations'][configuration]))
912 platforms = list(platforms)
913 return platforms
914
915
916 def _CreateMSVSUserFile(proj_path, version, spec):
917 """Generates a .user file for the user running this Gyp program.
918
919 Arguments:
920 proj_path: The path of the project file being created. The .user file
921 shares the same path (with an appropriate suffix).
922 version: The VisualStudioVersion object.
923 spec: The target dictionary containing the properties of the target.
924 Returns:
925 The MSVSUserFile object created.
926 """
927 (domain, username) = _GetDomainAndUserName()
928 vcuser_filename = '.'.join([proj_path, domain, username, 'user'])
929 user_file = MSVSUserFile.Writer(vcuser_filename, version,
930 spec['target_name'])
931 return user_file
932
933
934 def _GetMSVSConfigurationType(spec, build_file):
935 """Returns the configuration type for this project.
936
937 It's a number defined by Microsoft. May raise an exception.
938
939 Args:
940 spec: The target dictionary containing the properties of the target.
941 build_file: The path of the gyp file.
942 Returns:
943 An integer, the configuration type.
944 """
945 try:
946 config_type = {
947 'executable': '1', # .exe
948 'shared_library': '2', # .dll
949 'loadable_module': '2', # .dll
950 'static_library': '4', # .lib
951 'none': '10', # Utility type
952 'dummy_executable': '1', # .exe
953 }[spec['type']]
954 except KeyError:
955 if spec.get('type'):
956 raise Exception('Target type %s is not a valid target type for '
957 'target %s in %s.' %
958 (spec['type'], spec['target_name'], build_file))
959 else:
960 raise Exception('Missing type field for target %s in %s.' %
961 (spec['target_name'], build_file))
962 return config_type
963
964
965 def _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config):
966 """Adds a configuration to the MSVS project.
967
968 Many settings in a vcproj file are specific to a configuration. This
969 function the main part of the vcproj file that's configuration specific.
970
971 Arguments:
972 p: The target project being generated.
973 spec: The target dictionary containing the properties of the target.
974 config_type: The configuration type, a number as defined by Microsoft.
975 config_name: The name of the configuration.
976 config: The dictionnary that defines the special processing to be done
977 for this configuration.
978 """
979 # Get the information for this configuration
980 include_dirs, resource_include_dirs = _GetIncludeDirs(config)
981 libraries = _GetLibraries(spec)
982 out_file, vc_tool, _ = _GetOutputFilePathAndTool(spec)
983 defines = _GetDefines(config)
984 defines = [_EscapeCppDefineForMSVS(d) for d in defines]
985 disabled_warnings = _GetDisabledWarnings(config)
986 prebuild = config.get('msvs_prebuild')
987 postbuild = config.get('msvs_postbuild')
988 def_file = _GetModuleDefinition(spec)
989 precompiled_header = config.get('msvs_precompiled_header')
990
991 # Prepare the list of tools as a dictionary.
992 tools = dict()
993 # Add in user specified msvs_settings.
994 msvs_settings = config.get('msvs_settings', {})
995 MSVSSettings.ValidateMSVSSettings(msvs_settings)
996 for tool in msvs_settings:
997 settings = config['msvs_settings'][tool]
998 for setting in settings:
999 _ToolAppend(tools, tool, setting, settings[setting])
1000 # Add the information to the appropriate tool
1001 _ToolAppend(tools, 'VCCLCompilerTool',
1002 'AdditionalIncludeDirectories', include_dirs)
1003 _ToolAppend(tools, 'VCResourceCompilerTool',
1004 'AdditionalIncludeDirectories', resource_include_dirs)
1005 # Add in libraries.
1006 _ToolAppend(tools, 'VCLinkerTool', 'AdditionalDependencies', libraries)
1007 if out_file:
1008 _ToolAppend(tools, vc_tool, 'OutputFile', out_file, only_if_unset=True)
1009 # Add defines.
1010 _ToolAppend(tools, 'VCCLCompilerTool', 'PreprocessorDefinitions', defines)
1011 _ToolAppend(tools, 'VCResourceCompilerTool', 'PreprocessorDefinitions',
1012 defines)
1013 # Change program database directory to prevent collisions.
1014 _ToolAppend(tools, 'VCCLCompilerTool', 'ProgramDataBaseFileName',
1015 '$(IntDir)\\$(ProjectName)\\vc80.pdb')
1016 # Add disabled warnings.
1017 _ToolAppend(tools, 'VCCLCompilerTool',
1018 'DisableSpecificWarnings', disabled_warnings)
1019 # Add Pre-build.
1020 _ToolAppend(tools, 'VCPreBuildEventTool', 'CommandLine', prebuild)
1021 # Add Post-build.
1022 _ToolAppend(tools, 'VCPostBuildEventTool', 'CommandLine', postbuild)
1023 # Turn on precompiled headers if appropriate.
1024 if precompiled_header:
1025 precompiled_header = os.path.split(precompiled_header)[1]
1026 _ToolAppend(tools, 'VCCLCompilerTool', 'UsePrecompiledHeader', '2')
1027 _ToolAppend(tools, 'VCCLCompilerTool',
1028 'PrecompiledHeaderThrough', precompiled_header)
1029 _ToolAppend(tools, 'VCCLCompilerTool',
1030 'ForcedIncludeFiles', precompiled_header)
1031 # Loadable modules don't generate import libraries;
1032 # tell dependent projects to not expect one.
1033 if spec['type'] == 'loadable_module':
1034 _ToolAppend(tools, 'VCLinkerTool', 'IgnoreImportLibrary', 'true')
1035 # Set the module definition file if any.
1036 if def_file:
1037 _ToolAppend(tools, 'VCLinkerTool', 'ModuleDefinitionFile', def_file)
1038
1039 _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name)
1040
1041
1042 def _GetIncludeDirs(config):
1043 """Returns the list of directories to be used for #include directives.
1044
1045 Arguments:
1046 config: The dictionnary that defines the special processing to be done
1047 for this configuration.
1048 Returns:
1049 The list of directory paths.
1050 """
1051 # TODO(bradnelson): include_dirs should really be flexible enough not to
1052 # require this sort of thing.
1053 include_dirs = (
1054 config.get('include_dirs', []) +
1055 config.get('msvs_system_include_dirs', []))
1056 resource_include_dirs = config.get('resource_include_dirs', include_dirs)
1057 include_dirs = _FixPaths(include_dirs)
1058 resource_include_dirs = _FixPaths(resource_include_dirs)
1059 return include_dirs, resource_include_dirs
1060
1061
1062 def _GetLibraries(spec):
1063 """Returns the list of libraries for this configuration.
1064
1065 Arguments:
1066 spec: The target dictionary containing the properties of the target.
1067 Returns:
1068 The list of directory paths.
1069 """
1070 libraries = spec.get('libraries', [])
1071 # Strip out -l, as it is not used on windows (but is needed so we can pass
1072 # in libraries that are assumed to be in the default library path).
1073 # Also remove duplicate entries, leaving only the last duplicate, while
1074 # preserving order.
1075 found = set()
1076 unique_libraries_list = []
1077 for entry in reversed(libraries):
1078 library = re.sub('^\-l', '', entry)
1079 if library not in found:
1080 found.add(library)
1081 unique_libraries_list.append(library)
1082 unique_libraries_list.reverse()
1083 return unique_libraries_list
1084
1085
1086 def _GetOutputFilePathAndTool(spec):
1087 """Returns the path and tool to use for this target.
1088
1089 Figures out the path of the file this spec will create and the name of
1090 the VC tool that will create it.
1091
1092 Arguments:
1093 spec: The target dictionary containing the properties of the target.
1094 Returns:
1095 A triple of (file path, name of the vc tool, name of the msbuild tool)
1096 """
1097 # Select a name for the output file.
1098 out_file = ''
1099 vc_tool = ''
1100 msbuild_tool = ''
1101 output_file_map = {
1102 'executable': ('VCLinkerTool', 'Link', '$(OutDir)\\', '.exe'),
1103 'shared_library': ('VCLinkerTool', 'Link', '$(OutDir)\\', '.dll'),
1104 'loadable_module': ('VCLinkerTool', 'Link', '$(OutDir)\\', '.dll'),
1105 # TODO(jeanluc) If we want to avoid the MSB8012 warnings in
1106 # VisualStudio 2010, we will have to change the value of $(OutDir)
1107 # to contain the \lib suffix, rather than doing it as below.
1108 'static_library': ('VCLibrarianTool', 'Lib', '$(OutDir)\\lib\\', '.lib'),
1109 'dummy_executable': ('VCLinkerTool', 'Link', '$(IntDir)\\', '.junk'),
1110 }
1111 output_file_props = output_file_map.get(spec['type'])
1112 if output_file_props and int(spec.get('msvs_auto_output_file', 1)):
1113 vc_tool, msbuild_tool, out_dir, suffix = output_file_props
1114 out_dir = spec.get('product_dir', out_dir)
1115 product_extension = spec.get('product_extension')
1116 if product_extension:
1117 suffix = '.' + product_extension
1118 prefix = spec.get('product_prefix', '')
1119 product_name = spec.get('product_name', '$(ProjectName)')
1120 out_file = ntpath.join(out_dir, prefix + product_name + suffix)
1121 return out_file, vc_tool, msbuild_tool
1122
1123
1124 def _GetDefines(config):
1125 """Returns the list of preprocessor definitions for this configuation.
1126
1127 Arguments:
1128 config: The dictionnary that defines the special processing to be done
1129 for this configuration.
1130 Returns:
1131 The list of preprocessor definitions.
1132 """
1133 defines = []
1134 for d in config.get('defines', []):
1135 if type(d) == list:
1136 fd = '='.join([str(dpart) for dpart in d])
1137 else:
1138 fd = str(d)
1139 defines.append(fd)
1140 return defines
1141
1142
1143 def _GetDisabledWarnings(config):
1144 return [str(i) for i in config.get('msvs_disabled_warnings', [])]
1145
1146
1147 def _GetModuleDefinition(spec):
1148 def_file = ''
1149 if spec['type'] in ['shared_library', 'loadable_module']:
1150 def_files = [s for s in spec.get('sources', []) if s.endswith('.def')]
1151 if len(def_files) == 1:
1152 def_file = _FixPath(def_files[0])
1153 elif def_files:
1154 raise ValueError(
1155 'Multiple module definition files in one target, target %s lists '
1156 'multiple .def files: %s' % (
1157 spec['target_name'], ' '.join(def_files)))
1158 return def_file
1159
1160
1161 def _ConvertToolsToExpectedForm(tools):
1162 """Convert tools to a form expected by Visual Studio.
1163
1164 Arguments:
1165 tools: A dictionnary of settings; the tool name is the key.
1166 Returns:
1167 A list of Tool objects.
1168 """
1169 tool_list = []
1170 for tool, settings in tools.iteritems():
1171 # Collapse settings with lists.
1172 settings_fixed = {}
1173 for setting, value in settings.iteritems():
1174 if type(value) == list:
1175 if ((tool == 'VCLinkerTool' and
1176 setting == 'AdditionalDependencies') or
1177 setting == 'AdditionalOptions'):
1178 settings_fixed[setting] = ' '.join(value)
1179 else:
1180 settings_fixed[setting] = ';'.join(value)
1181 else:
1182 settings_fixed[setting] = value
1183 # Add in this tool.
1184 tool_list.append(MSVSProject.Tool(tool, settings_fixed))
1185 return tool_list
1186
1187
1188 def _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name):
1189 """Add to the project file the configuration specified by config.
1190
1191 Arguments:
1192 p: The target project being generated.
1193 spec: the target project dict.
1194 tools: A dictionnary of settings; the tool name is the key.
1195 config: The dictionnary that defines the special processing to be done
1196 for this configuration.
1197 config_type: The configuration type, a number as defined by Microsoft.
1198 config_name: The name of the configuration.
1199 """
1200 attributes = _GetMSVSAttributes(spec, config, config_type)
1201 # Add in this configuration.
1202 tool_list = _ConvertToolsToExpectedForm(tools)
1203 p.AddConfig(_ConfigFullName(config_name, config),
1204 attrs=attributes, tools=tool_list)
1205
1206
1207 def _GetMSVSAttributes(spec, config, config_type):
1208 # Prepare configuration attributes.
1209 prepared_attrs = {}
1210 source_attrs = config.get('msvs_configuration_attributes', {})
1211 for a in source_attrs:
1212 prepared_attrs[a] = source_attrs[a]
1213 # Add props files.
1214 vsprops_dirs = config.get('msvs_props', [])
1215 vsprops_dirs = _FixPaths(vsprops_dirs)
1216 if vsprops_dirs:
1217 prepared_attrs['InheritedPropertySheets'] = ';'.join(vsprops_dirs)
1218 # Set configuration type.
1219 prepared_attrs['ConfigurationType'] = config_type
1220 output_dir = prepared_attrs.get('OutputDirectory',
1221 '$(SolutionDir)$(ConfigurationName)')
1222 # TODO(jeanluc) If we want to avoid the MSB8012 warning, we should
1223 # add code like the following to place libraries in their own directory.
1224 # if config_type == '4':
1225 # output_dir = spec.get('product_dir', output_dir + '\\lib')
1226 prepared_attrs['OutputDirectory'] = output_dir
1227 if 'IntermediateDirectory' not in prepared_attrs:
1228 intermediate = '$(ConfigurationName)\\obj\\$(ProjectName)'
1229 prepared_attrs['IntermediateDirectory'] = intermediate
1230 return prepared_attrs
1231
1232
1233 def _AddNormalizedSources(sources_set, sources_array):
1234 sources = [_NormalizedSource(s) for s in sources_array]
1235 sources_set.update(set(sources))
1236
1237
1238 def _PrepareListOfSources(spec, relative_path_of_gyp_file):
1239 """Prepare list of sources and excluded sources.
1240
1241 Besides the sources specified directly in the spec, adds the gyp file so
1242 that a change to it will cause a re-compile. Also adds appropriate sources
1243 for actions and copies. Assumes later stage will un-exclude files which
1244 have custom build steps attached.
1245
1246 Arguments:
1247 spec: The target dictionary containing the properties of the target.
1248 relative_path_of_gyp_file: The relative path of the gyp file.
1249 Returns:
1250 A pair of (list of sources, list of excluded sources)
1251 """
1252 sources = set()
1253 _AddNormalizedSources(sources, spec.get('sources', []))
1254 excluded_sources = set()
1255 # Add in the gyp file.
1256 sources.add(relative_path_of_gyp_file)
1257
1258 # Add in 'action' inputs and outputs.
1259 for a in spec.get('actions', []):
1260 inputs = a.get('inputs', [])
1261 inputs = [_NormalizedSource(i) for i in inputs]
1262 # Add all inputs to sources and excluded sources.
1263 inputs = set(inputs)
1264 sources.update(inputs)
1265 excluded_sources.update(inputs)
1266 if int(a.get('process_outputs_as_sources', False)):
1267 _AddNormalizedSources(sources, a.get('outputs', []))
1268 # Add in 'copies' inputs and outputs.
1269 for cpy in spec.get('copies', []):
1270 _AddNormalizedSources(sources, cpy.get('files', []))
1271 return (sources, excluded_sources)
1272
1273
1274 def _AdjustSourcesAndConvertToFilterHierarchy(
1275 spec, options, gyp_dir, sources, excluded_sources):
1276 """Adjusts the list of sources and excluded sources.
1277
1278 Also converts the sets to lists.
1279
1280 Arguments:
1281 spec: The target dictionary containing the properties of the target.
1282 options: Global generator options.
1283 gyp_dir: The path to the gyp file being processed.
1284 sources: A set of sources to be included for this project.
1285 excluded_sources: A set of sources to be excluded for this project.
1286 Returns:
1287 A trio of (list of sources, list of excluded sources,
1288 path of excluded IDL file)
1289 """
1290 # Exclude excluded sources coming into the generator.
1291 excluded_sources.update(set(spec.get('sources_excluded', [])))
1292 # Add excluded sources into sources for good measure.
1293 sources.update(excluded_sources)
1294 # Convert to proper windows form.
1295 # NOTE: sources goes from being a set to a list here.
1296 # NOTE: excluded_sources goes from being a set to a list here.
1297 sources = _FixPaths(sources)
1298 # Convert to proper windows form.
1299 excluded_sources = _FixPaths(excluded_sources)
1300
1301 excluded_idl = _IdlFilesHandledNonNatively(spec, sources)
1302
1303 precompiled_related = _GetPrecompileRelatedFiles(spec)
1304 # Find the excluded ones, minus the precompiled header related ones.
1305 fully_excluded = [i for i in excluded_sources if i not in precompiled_related]
1306
1307 # Convert to folders and the right slashes.
1308 sources = [i.split('\\') for i in sources]
1309 sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_excluded)
1310 # Add in dummy file for type none.
1311 if spec['type'] == 'dummy_executable':
1312 # Pull in a dummy main so it can link successfully.
1313 dummy_relpath = gyp.common.RelativePath(
1314 options.depth + '\\tools\\gyp\\gyp_dummy.c', gyp_dir)
1315 sources.append(dummy_relpath)
1316
1317 return sources, excluded_sources, excluded_idl
1318
1319
1320 def _IdlFilesHandledNonNatively(spec, sources):
1321 # If any non-native rules use 'idl' as an extension exclude idl files.
1322 # Gather a list here to use later.
1323 using_idl = False
1324 for rule in spec.get('rules', []):
1325 if rule['extension'] == 'idl' and int(rule.get('msvs_external_rule', 0)):
1326 using_idl = True
1327 break
1328 if using_idl:
1329 excluded_idl = [i for i in sources if i.endswith('.idl')]
1330 else:
1331 excluded_idl = []
1332 return excluded_idl
1333
1334
1335 def _GetPrecompileRelatedFiles(spec):
1336 # Gather a list of precompiled header related sources.
1337 precompiled_related = []
1338 for _, config in spec['configurations'].iteritems():
1339 for k in precomp_keys:
1340 f = config.get(k)
1341 if f:
1342 precompiled_related.append(_FixPath(f))
1343 return precompiled_related
1344
1345
1346 def _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl):
1347 exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl)
1348 for file_name, excluded_configs in exclusions.iteritems():
1349 for config_name, config in excluded_configs:
1350 p.AddFileConfig(file_name, _ConfigFullName(config_name, config),
1351 {'ExcludedFromBuild': 'true'})
1352
1353
1354 def _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl):
1355 exclusions = {}
1356 # Exclude excluded sources from being built.
1357 for f in excluded_sources:
1358 excluded_configs = []
1359 for config_name, config in spec['configurations'].iteritems():
1360 precomped = [_FixPath(config.get(i, '')) for i in precomp_keys]
1361 # Don't do this for ones that are precompiled header related.
1362 if f not in precomped:
1363 excluded_configs.append((config_name, config))
1364 exclusions[f] = excluded_configs
1365 # If any non-native rules use 'idl' as an extension exclude idl files.
1366 # Exclude them now.
1367 for f in excluded_idl:
1368 excluded_configs = []
1369 for config_name, config in spec['configurations'].iteritems():
1370 excluded_configs.append((config_name, config))
1371 exclusions[f] = excluded_configs
1372 return exclusions
1373
1374
1375 def _AddToolFilesToMSVS(p, spec):
1376 # Add in tool files (rules).
1377 tool_files = set()
1378 for _, config in spec['configurations'].iteritems():
1379 for f in config.get('msvs_tool_files', []):
1380 tool_files.add(f)
1381 for f in tool_files:
1382 p.AddToolFile(f)
1383
1384
1385 def _HandlePreCompileHeaderStubs(p, spec):
1386 # Handle pre-compiled headers source stubs specially.
1387 for config_name, config in spec['configurations'].iteritems():
1388 source = config.get('msvs_precompiled_source')
1389 if source:
1390 source = _FixPath(source)
1391 # UsePrecompiledHeader=1 for if using precompiled headers.
1392 tool = MSVSProject.Tool('VCCLCompilerTool',
1393 {'UsePrecompiledHeader': '1'})
1394 p.AddFileConfig(source, _ConfigFullName(config_name, config),
1395 {}, tools=[tool])
1396
1397
1398 def _AddActions(actions_to_add, spec, relative_path_of_gyp_file):
1399 # Add actions.
1400 actions = spec.get('actions', [])
1401 for a in actions:
1402 cmd = _BuildCommandLineForRule(spec, a, has_input_path=False)
1403 # Attach actions to the gyp file if nothing else is there.
1404 inputs = a.get('inputs') or [relative_path_of_gyp_file]
1405 # Add the action.
1406 _AddActionStep(actions_to_add,
1407 inputs=inputs,
1408 outputs=a.get('outputs', []),
1409 description=a.get('message', a['action_name']),
1410 command=cmd)
1411
1412
1413 def _WriteMSVSUserFile(project_path, version, spec):
1414 # Add run_as and test targets.
1415 if 'run_as' in spec:
1416 run_as = spec['run_as']
1417 action = run_as.get('action', [])
1418 environment = run_as.get('environment', [])
1419 working_directory = run_as.get('working_directory', '.')
1420 elif int(spec.get('test', 0)):
1421 action = ['$(TargetPath)', '--gtest_print_time']
1422 environment = []
1423 working_directory = '.'
1424 else:
1425 return # Nothing to add
1426 # Write out the user file.
1427 user_file = _CreateMSVSUserFile(project_path, version, spec)
1428 for config_name, c_data in spec['configurations'].iteritems():
1429 user_file.AddDebugSettings(_ConfigFullName(config_name, c_data),
1430 action, environment, working_directory)
1431 user_file.WriteIfChanged()
1432
1433
1434 def _AddCopies(actions_to_add, spec):
1435 copies = _GetCopies(spec)
1436 for inputs, outputs, cmd, description in copies:
1437 _AddActionStep(actions_to_add, inputs=inputs, outputs=outputs,
1438 description=description, command=cmd)
1439
1440
1441 def _GetCopies(spec):
1442 copies = []
1443 # Add copies.
1444 for cpy in spec.get('copies', []):
1445 for src in cpy.get('files', []):
1446 dst = os.path.join(cpy['destination'], os.path.basename(src))
1447 # _AddCustomBuildToolForMSVS() will call _FixPath() on the inputs and
1448 # outputs, so do the same for our generated command line.
1449 if src.endswith('/'):
1450 src_bare = src[:-1]
1451 base_dir = posixpath.split(src_bare)[0]
1452 outer_dir = posixpath.split(src_bare)[1]
1453 cmd = 'cd "%s" && xcopy /e /f /y "%s" "%s\\%s\\"' % (
1454 _FixPath(base_dir), outer_dir, _FixPath(dst), outer_dir)
1455 copies.append(([src], ['dummy_copies', dst], cmd,
1456 'Copying %s to %s' % (src, dst)))
1457 else:
1458 cmd = 'mkdir "%s" 2>nul & set ERRORLEVEL=0 & copy /Y "%s" "%s"' % (
1459 _FixPath(cpy['destination']), _FixPath(src), _FixPath(dst))
1460 copies.append(([src], [dst], cmd, 'Copying %s to %s' % (src, dst)))
1461 return copies
1462
1463
1464 def _GetPathDict(root, path):
1465 if not path:
1466 return root
1467 parent, folder = os.path.split(path)
1468 parent_dict = _GetPathDict(root, parent)
1469 if folder not in parent_dict:
1470 parent_dict[folder] = dict()
1471 return parent_dict[folder]
1472
1473
1474 def _DictsToFolders(base_path, bucket, flat):
1475 # Convert to folders recursively.
1476 children = []
1477 for folder, contents in bucket.iteritems():
1478 if type(contents) == dict:
1479 folder_children = _DictsToFolders(os.path.join(base_path, folder),
1480 contents, flat)
1481 if flat:
1482 children += folder_children
1483 else:
1484 folder_children = MSVSNew.MSVSFolder(os.path.join(base_path, folder),
1485 name='(' + folder + ')',
1486 entries=folder_children)
1487 children.append(folder_children)
1488 else:
1489 children.append(contents)
1490 return children
1491
1492
1493 def _CollapseSingles(parent, node):
1494 # Recursively explorer the tree of dicts looking for projects which are
1495 # the sole item in a folder which has the same name as the project. Bring
1496 # such projects up one level.
1497 if (type(node) == dict and
1498 len(node) == 1 and
1499 node.keys()[0] == parent + '.vcproj'):
1500 return node[node.keys()[0]]
1501 if type(node) != dict:
1502 return node
1503 for child in node:
1504 node[child] = _CollapseSingles(child, node[child])
1505 return node
1506
1507
1508 def _GatherSolutionFolders(sln_projects, project_objects, flat):
1509 root = {}
1510 # Convert into a tree of dicts on path.
1511 for p in sln_projects:
1512 gyp_file, target = gyp.common.ParseQualifiedTarget(p)[0:2]
1513 gyp_dir = os.path.dirname(gyp_file)
1514 path_dict = _GetPathDict(root, gyp_dir)
1515 path_dict[target + '.vcproj'] = project_objects[p]
1516 # Walk down from the top until we hit a folder that has more than one entry.
1517 # In practice, this strips the top-level "src/" dir from the hierarchy in
1518 # the solution.
1519 while len(root) == 1 and type(root[root.keys()[0]]) == dict:
1520 root = root[root.keys()[0]]
1521 # Collapse singles.
1522 root = _CollapseSingles('', root)
1523 # Merge buckets until everything is a root entry.
1524 return _DictsToFolders('', root, flat)
1525
1526
1527 def _GetPathOfProject(qualified_target, spec, options, msvs_version):
1528 default_config = _GetDefaultConfiguration(spec)
1529 proj_filename = default_config.get('msvs_existing_vcproj')
1530 if not proj_filename:
1531 proj_filename = (spec['target_name'] + options.suffix +
1532 msvs_version.ProjectExtension())
1533
1534 build_file = gyp.common.BuildFile(qualified_target)
1535 proj_path = os.path.join(os.path.split(build_file)[0], proj_filename)
1536 fix_prefix = None
1537 if options.generator_output:
1538 project_dir_path = os.path.dirname(os.path.abspath(proj_path))
1539 proj_path = os.path.join(options.generator_output, proj_path)
1540 fix_prefix = gyp.common.RelativePath(project_dir_path,
1541 os.path.dirname(proj_path))
1542 return proj_path, fix_prefix
1543
1544
1545 def _GetPlatformOverridesOfProject(spec):
1546 # Prepare a dict indicating which project configurations are used for which
1547 # solution configurations for this target.
1548 config_platform_overrides = {}
1549 for config_name, c in spec['configurations'].iteritems():
1550 config_fullname = _ConfigFullName(config_name, c)
1551 platform = c.get('msvs_target_platform', _ConfigPlatform(c))
1552 fixed_config_fullname = '%s|%s' % (
1553 _ConfigBaseName(config_name, _ConfigPlatform(c)), platform)
1554 config_platform_overrides[config_fullname] = fixed_config_fullname
1555 return config_platform_overrides
1556
1557
1558 def _CreateProjectObjects(target_list, target_dicts, options, msvs_version):
1559 """Create a MSVSProject object for the targets found in target list.
1560
1561 Arguments:
1562 target_list: the list of targets to generate project objects for.
1563 target_dicts: the dictionary of specifications.
1564 options: global generator options.
1565 msvs_version: the MSVSVersion object.
1566 Returns:
1567 A set of created projects, keyed by target.
1568 """
1569 global fixpath_prefix
1570 # Generate each project.
1571 projects = {}
1572 for qualified_target in target_list:
1573 spec = target_dicts[qualified_target]
1574 if spec['toolset'] != 'target':
1575 raise Exception(
1576 'Multiple toolsets not supported in msvs build (target %s)' %
1577 qualified_target)
1578 proj_path, fixpath_prefix = _GetPathOfProject(qualified_target, spec,
1579 options, msvs_version)
1580 guid = _GetGuidOfProject(proj_path, spec)
1581 overrides = _GetPlatformOverridesOfProject(spec)
1582 build_file = gyp.common.BuildFile(qualified_target)
1583 # Create object for this project.
1584 obj = MSVSNew.MSVSProject(
1585 _FixPath(proj_path),
1586 name=spec['target_name'],
1587 guid=guid,
1588 spec=spec,
1589 build_file=build_file,
1590 config_platform_overrides=overrides,
1591 fixpath_prefix=fixpath_prefix)
1592 projects[qualified_target] = obj
1593 # Set all the dependencies
1594 for project in projects.values():
1595 deps = project.spec.get('dependencies', [])
1596 deps = [projects[d] for d in deps]
1597 project.set_dependencies(deps)
1598 return projects
1599
1600
1601 def CalculateVariables(default_variables, params):
1602 """Generated variables that require params to be known."""
1603
1604 generator_flags = params.get('generator_flags', {})
1605
1606 # Select project file format version (if unset, default to auto detecting).
1607 msvs_version = MSVSVersion.SelectVisualStudioVersion(
1608 generator_flags.get('msvs_version', 'auto'))
1609 # Stash msvs_version for later (so we don't have to probe the system twice).
1610 params['msvs_version'] = msvs_version
1611
1612 # Set a variable so conditions can be based on msvs_version.
1613 default_variables['MSVS_VERSION'] = msvs_version.ShortName()
1614
1615 # To determine processor word size on Windows, in addition to checking
1616 # PROCESSOR_ARCHITECTURE (which reflects the word size of the current
1617 # process), it is also necessary to check PROCESSOR_ARCITEW6432 (which
1618 # contains the actual word size of the system when running thru WOW64).
1619 if (os.environ.get('PROCESSOR_ARCHITECTURE', '').find('64') >= 0 or
1620 os.environ.get('PROCESSOR_ARCHITEW6432', '').find('64') >= 0):
1621 default_variables['MSVS_OS_BITS'] = 64
1622 else:
1623 default_variables['MSVS_OS_BITS'] = 32
1624
1625
1626 def _ShardName(name, number):
1627 """Add a shard number to the end of a target.
1628
1629 Arguments:
1630 name: name of the target (foo#target)
1631 number: shard number
1632 Returns:
1633 Target name with shard added (foo_1#target)
1634 """
1635 parts = name.rsplit('#', 1)
1636 parts[0] = '%s_%d' % (parts[0], number)
1637 return '#'.join(parts)
1638
1639
1640 def _ShardTargets(target_list, target_dicts):
1641 """Shard some targets apart to work around the linkers limits.
1642
1643 Arguments:
1644 target_list: List of target pairs: 'base/base.gyp:base'.
1645 target_dicts: Dict of target properties keyed on target pair.
1646 Returns:
1647 Tuple of the new sharded versions of the inputs.
1648 """
1649 # Gather the targets to shard, and how many pieces.
1650 targets_to_shard = {}
1651 for t in target_dicts:
1652 shards = int(target_dicts[t].get('msvs_shard', 0))
1653 if shards:
1654 targets_to_shard[t] = shards
1655 # Shard target_list.
1656 new_target_list = []
1657 for t in target_list:
1658 if t in targets_to_shard:
1659 for i in range(targets_to_shard[t]):
1660 new_target_list.append(_ShardName(t, i))
1661 else:
1662 new_target_list.append(t)
1663 # Shard target_dict.
1664 new_target_dicts = {}
1665 for t in target_dicts:
1666 if t in targets_to_shard:
1667 for i in range(targets_to_shard[t]):
1668 name = _ShardName(t, i)
1669 new_target_dicts[name] = copy.copy(target_dicts[t])
1670 new_target_dicts[name]['target_name'] = _ShardName(
1671 new_target_dicts[name]['target_name'], i)
1672 sources = new_target_dicts[name].get('sources', [])
1673 new_sources = []
1674 for pos in range(i, len(sources), targets_to_shard[t]):
1675 new_sources.append(sources[pos])
1676 new_target_dicts[name]['sources'] = new_sources
1677 else:
1678 new_target_dicts[t] = target_dicts[t]
1679 # Shard dependencies.
1680 for t in new_target_dicts:
1681 dependencies = copy.copy(new_target_dicts[t].get('dependencies', []))
1682 new_dependencies = []
1683 for d in dependencies:
1684 if d in targets_to_shard:
1685 for i in range(targets_to_shard[d]):
1686 new_dependencies.append(_ShardName(d, i))
1687 else:
1688 new_dependencies.append(d)
1689 new_target_dicts[t]['dependencies'] = new_dependencies
1690
1691 return (new_target_list, new_target_dicts)
1692
1693
1694 def GenerateOutput(target_list, target_dicts, data, params):
1695 """Generate .sln and .vcproj files.
1696
1697 This is the entry point for this generator.
1698 Arguments:
1699 target_list: List of target pairs: 'base/base.gyp:base'.
1700 target_dicts: Dict of target properties keyed on target pair.
1701 data: Dictionary containing per .gyp data.
1702 """
1703 global fixpath_prefix
1704
1705 options = params['options']
1706
1707 # Get the project file format version back out of where we stashed it in
1708 # GeneratorCalculatedVariables.
1709 msvs_version = params['msvs_version']
1710
1711 # Optionally shard targets marked with 'msvs_shard': SHARD_COUNT.
1712 (target_list, target_dicts) = _ShardTargets(target_list, target_dicts)
1713
1714 # Prepare the set of configurations.
1715 configs = set()
1716 for qualified_target in target_list:
1717 spec = target_dicts[qualified_target]
1718 for config_name, config in spec['configurations'].iteritems():
1719 configs.add(_ConfigFullName(config_name, config))
1720 configs = list(configs)
1721
1722 # Figure out all the projects that will be generated and their guids
1723 project_objects = _CreateProjectObjects(target_list, target_dicts, options,
1724 msvs_version)
1725
1726 # Generate each project.
1727 for project in project_objects.values():
1728 fixpath_prefix = project.fixpath_prefix
1729 _GenerateProject(project, options, msvs_version)
1730 fixpath_prefix = None
1731
1732 for build_file in data:
1733 # Validate build_file extension
1734 if build_file[-4:] != '.gyp':
1735 continue
1736 sln_path = build_file[:-4] + options.suffix + '.sln'
1737 if options.generator_output:
1738 sln_path = os.path.join(options.generator_output, sln_path)
1739 # Get projects in the solution, and their dependents.
1740 sln_projects = gyp.common.BuildFileTargets(target_list, build_file)
1741 sln_projects += gyp.common.DeepDependencyTargets(target_dicts, sln_projects)
1742 # Create folder hierarchy.
1743 root_entries = _GatherSolutionFolders(
1744 sln_projects, project_objects, flat=msvs_version.FlatSolution())
1745 # Create solution.
1746 sln = MSVSNew.MSVSSolution(sln_path,
1747 entries=root_entries,
1748 variants=configs,
1749 websiteProperties=False,
1750 version=msvs_version)
1751 sln.Write()
1752
1753
1754 def _GenerateMSBuildFiltersFile(filters_path, source_files,
1755 extension_to_rule_name):
1756 """Generate the filters file.
1757
1758 This file is used by Visual Studio to organize the presentation of source
1759 files into folders.
1760
1761 Arguments:
1762 filters_path: The path of the file to be created.
1763 source_files: The hierarchical structure of all the sources.
1764 extension_to_rule_name: A dictionary mapping file extensions to rules.
1765 """
1766 filter_group = []
1767 source_group = []
1768 _AppendFiltersForMSBuild('', source_files, extension_to_rule_name,
1769 filter_group, source_group)
1770 if filter_group:
1771 content = ['Project',
1772 {'ToolsVersion': '4.0',
1773 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'
1774 },
1775 ['ItemGroup'] + filter_group,
1776 ['ItemGroup'] + source_group
1777 ]
1778 easy_xml.WriteXmlIfChanged(content, filters_path)
1779 elif os.path.exists(filters_path):
1780 # We don't need this filter anymore. Delete the old filter file.
1781 os.unlink(filters_path)
1782
1783
1784 def _AppendFiltersForMSBuild(parent_filter_name, sources,
1785 extension_to_rule_name,
1786 filter_group, source_group):
1787 """Creates the list of filters and sources to be added in the filter file.
1788
1789 Args:
1790 parent_filter_name: The name of the filter under which the sources are
1791 found.
1792 sources: The hierarchy of filters and sources to process.
1793 extension_to_rule_name: A dictionary mapping file extensions to rules.
1794 filter_group: The list to which filter entries will be appended.
1795 source_group: The list to which source entries will be appeneded.
1796 """
1797 for source in sources:
1798 if isinstance(source, MSVSProject.Filter):
1799 # We have a sub-filter. Create the name of that sub-filter.
1800 if not parent_filter_name:
1801 filter_name = source.name
1802 else:
1803 filter_name = '%s\\%s' % (parent_filter_name, source.name)
1804 # Add the filter to the group.
1805 filter_group.append(
1806 ['Filter', {'Include': filter_name},
1807 ['UniqueIdentifier', MSVSNew.MakeGuid(source.name)]])
1808 # Recurse and add its dependents.
1809 _AppendFiltersForMSBuild(filter_name, source.contents,
1810 extension_to_rule_name,
1811 filter_group, source_group)
1812 else:
1813 # It's a source. Create a source entry.
1814 _, element = _MapFileToMsBuildSourceType(source, extension_to_rule_name)
1815 source_entry = [element, {'Include': source}]
1816 # Specify the filter it is part of, if any.
1817 if parent_filter_name:
1818 source_entry.append(['Filter', parent_filter_name])
1819 source_group.append(source_entry)
1820
1821
1822 def _MapFileToMsBuildSourceType(source, extension_to_rule_name):
1823 """Returns the group and element type of the source file.
1824
1825 Arguments:
1826 source: The source file name.
1827 extension_to_rule_name: A dictionary mapping file extensions to rules.
1828
1829 Returns:
1830 A pair of (group this file should be part of, the label of element)
1831 """
1832 _, ext = os.path.splitext(source)
1833 if ext in ['.cc', '.cpp', '.c', '.cxx']:
1834 group = 'compile'
1835 element = 'ClCompile'
1836 elif ext in ['.h', '.hxx']:
1837 group = 'include'
1838 element = 'ClInclude'
1839 elif ext == '.rc':
1840 group = 'resource'
1841 element = 'ResourceCompile'
1842 elif ext == '.idl':
1843 group = 'midl'
1844 element = 'Midl'
1845 elif ext in extension_to_rule_name:
1846 group = 'rule'
1847 element = extension_to_rule_name[ext]
1848 else:
1849 group = 'none'
1850 element = 'None'
1851 return (group, element)
1852
1853
1854 def _GenerateRulesForMSBuild(output_dir, options, spec,
1855 sources, excluded_sources,
1856 props_files_of_rules, targets_files_of_rules,
1857 actions_to_add, extension_to_rule_name):
1858 # MSBuild rules are implemented using three files: an XML file, a .targets
1859 # file and a .props file.
1860 # See http://blogs.msdn.com/b/vcblog/archive/2010/04/21/quick-help-on-vs2010-custom-build-rule.aspx
1861 # for more details.
1862 rules = spec.get('rules', [])
1863 rules_native = [r for r in rules if not int(r.get('msvs_external_rule', 0))]
1864 rules_external = [r for r in rules if int(r.get('msvs_external_rule', 0))]
1865
1866 msbuild_rules = []
1867 for rule in rules_native:
1868 msbuild_rule = MSBuildRule(rule, spec)
1869 msbuild_rules.append(msbuild_rule)
1870 extension_to_rule_name[msbuild_rule.extension] = msbuild_rule.rule_name
1871 if msbuild_rules:
1872 base = spec['target_name'] + options.suffix
1873 props_name = base + '.props'
1874 targets_name = base + '.targets'
1875 xml_name = base + '.xml'
1876
1877 props_files_of_rules.add(props_name)
1878 targets_files_of_rules.add(targets_name)
1879
1880 props_path = os.path.join(output_dir, props_name)
1881 targets_path = os.path.join(output_dir, targets_name)
1882 xml_path = os.path.join(output_dir, xml_name)
1883
1884 _GenerateMSBuildRulePropsFile(props_path, msbuild_rules)
1885 _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules)
1886 _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules)
1887
1888 if rules_external:
1889 _GenerateExternalRules(rules_external, output_dir, spec,
1890 sources, options, actions_to_add)
1891 _AdjustSourcesForRules(rules, sources, excluded_sources)
1892
1893
1894 class MSBuildRule(object):
1895 """Used to store information used to generate an MSBuild rule.
1896
1897 Attributes:
1898 rule_name: The rule name, sanitized to use in XML.
1899 target_name: The name of the target.
1900 after_targets: The name of the AfterTargets element.
1901 before_targets: The name of the BeforeTargets element.
1902 depends_on: The name of the DependsOn element.
1903 compute_output: The name of the ComputeOutput element.
1904 dirs_to_make: The name of the DirsToMake element.
1905 tlog: The name of the _tlog element.
1906 extension: The extension this rule applies to.
1907 description: The message displayed when this rule is invoked.
1908 additional_dependencies: A string listing additional dependencies.
1909 outputs: The outputs of this rule.
1910 command: The command used to run the rule.
1911 """
1912
1913 def __init__(self, rule, spec):
1914 self.display_name = rule['rule_name']
1915 # Assure that the rule name is only characters and numbers
1916 self.rule_name = re.sub(r'\W', '_', self.display_name)
1917 # Create the various element names, following the example set by the
1918 # Visual Studio 2008 to 2010 conversion. I don't know if VS2010
1919 # is sensitive to the exact names.
1920 self.target_name = '_' + self.rule_name
1921 self.after_targets = self.rule_name + 'AfterTargets'
1922 self.before_targets = self.rule_name + 'BeforeTargets'
1923 self.depends_on = self.rule_name + 'DependsOn'
1924 self.compute_output = 'Compute%sOutput' % self.rule_name
1925 self.dirs_to_make = self.rule_name + 'DirsToMake'
1926 self.tlog = self.rule_name + '_tlog'
1927 self.extension = rule['extension']
1928 if not self.extension.startswith('.'):
1929 self.extension = '.' + self.extension
1930
1931 self.description = MSVSSettings.ConvertVCMacrosToMSBuild(
1932 rule.get('message', self.rule_name))
1933 old_additional_dependencies = _FixPaths(rule.get('inputs', []))
1934 self.additional_dependencies = (
1935 ';'.join([MSVSSettings.ConvertVCMacrosToMSBuild(i)
1936 for i in old_additional_dependencies]))
1937 old_outputs = _FixPaths(rule.get('outputs', []))
1938 self.outputs = ';'.join([MSVSSettings.ConvertVCMacrosToMSBuild(i)
1939 for i in old_outputs])
1940 old_command = _BuildCommandLineForRule(spec, rule, has_input_path=True)
1941 self.command = MSVSSettings.ConvertVCMacrosToMSBuild(old_command)
1942
1943
1944 def _GenerateMSBuildRulePropsFile(props_path, msbuild_rules):
1945 """Generate the .props file."""
1946 content = ['Project',
1947 {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}]
1948 for rule in msbuild_rules:
1949 content.extend([
1950 ['PropertyGroup',
1951 {'Condition': "'$(%s)' == '' and '$(%s)' == '' and "
1952 "'$(ConfigurationType)' != 'Makefile'" % (rule.before_targets,
1953 rule.after_targets)
1954 },
1955 [rule.before_targets, 'Midl'],
1956 [rule.after_targets, 'CustomBuild'],
1957 ],
1958 ['PropertyGroup',
1959 [rule.depends_on,
1960 {'Condition': "'$(ConfigurationType)' != 'Makefile'"},
1961 '_SelectedFiles;$(%s)' % rule.depends_on
1962 ],
1963 ],
1964 ['ItemDefinitionGroup',
1965 [rule.rule_name,
1966 ['CommandLineTemplate', rule.command],
1967 ['Outputs', rule.outputs],
1968 ['ExecutionDescription', rule.description],
1969 ['AdditionalDependencies', rule.additional_dependencies],
1970 ],
1971 ]
1972 ])
1973 easy_xml.WriteXmlIfChanged(content, props_path)
1974
1975
1976 def _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules):
1977 """Generate the .targets file."""
1978 content = ['Project',
1979 {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'
1980 }
1981 ]
1982 item_group = [
1983 'ItemGroup',
1984 ['PropertyPageSchema',
1985 {'Include': '$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml'}
1986 ]
1987 ]
1988 for rule in msbuild_rules:
1989 item_group.append(
1990 ['AvailableItemName',
1991 {'Include': rule.rule_name},
1992 ['Targets', rule.target_name],
1993 ])
1994 content.append(item_group)
1995
1996 for rule in msbuild_rules:
1997 content.append(
1998 ['UsingTask',
1999 {'TaskName': rule.rule_name,
2000 'TaskFactory': 'XamlTaskFactory',
2001 'AssemblyName': 'Microsoft.Build.Tasks.v4.0'
2002 },
2003 ['Task', '$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml'],
2004 ])
2005 for rule in msbuild_rules:
2006 rule_name = rule.rule_name
2007 target_outputs = '%%(%s.Outputs)' % rule_name
2008 target_inputs = ('%%(%s.Identity);%%(%s.AdditionalDependencies);'
2009 '$(MSBuildProjectFile)') % (rule_name, rule_name)
2010 rule_inputs = '%%(%s.Identity)' % rule_name
2011 extension_condition = ("'%(Extension)'=='.obj' or "
2012 "'%(Extension)'=='.res' or "
2013 "'%(Extension)'=='.rsc' or "
2014 "'%(Extension)'=='.lib'")
2015 remove_section = [
2016 'ItemGroup',
2017 {'Condition': "'@(SelectedFiles)' != ''"},
2018 [rule_name,
2019 {'Remove': '@(%s)' % rule_name,
2020 'Condition': "'%(Identity)' != '@(SelectedFiles)'"
2021 }
2022 ]
2023 ]
2024 logging_section = [
2025 'ItemGroup',
2026 [rule.tlog,
2027 {'Include': '%%(%s.Outputs)' % rule_name,
2028 'Condition': ("'%%(%s.Outputs)' != '' and "
2029 "'%%(%s.ExcludedFromBuild)' != 'true'" %
2030 (rule_name, rule_name))
2031 },
2032 ['Source', "@(%s, '|')" % rule_name],
2033 ],
2034 ]
2035 message_section = [
2036 'Message',
2037 {'Importance': 'High',
2038 'Text': '%%(%s.ExecutionDescription)' % rule_name
2039 }
2040 ]
2041 write_lines_section = [
2042 'WriteLinesToFile',
2043 {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != "
2044 "'true'" % (rule.tlog, rule.tlog),
2045 'File': '$(IntDir)$(ProjectName).write.1.tlog',
2046 'Lines': "^%%(%s.Source);@(%s->'%%(Fullpath)')" % (rule.tlog,
2047 rule.tlog)
2048 }
2049 ]
2050 command_and_input_section = [
2051 rule_name,
2052 {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != "
2053 "'true'" % (rule_name, rule_name),
2054 'CommandLineTemplate': '%%(%s.CommandLineTemplate)' % rule_name,
2055 'AdditionalOptions': '%%(%s.AdditionalOptions)' % rule_name,
2056 'Inputs': rule_inputs
2057 }
2058 ]
2059 content.extend([
2060 ['Target',
2061 {'Name': rule.target_name,
2062 'BeforeTargets': '$(%s)' % rule.before_targets,
2063 'AfterTargets': '$(%s)' % rule.after_targets,
2064 'Condition': "'@(%s)' != ''" % rule_name,
2065 'DependsOnTargets': '$(%s);%s' % (rule.depends_on,
2066 rule.compute_output),
2067 'Outputs': target_outputs,
2068 'Inputs': target_inputs
2069 },
2070 remove_section,
2071 logging_section,
2072 message_section,
2073 write_lines_section,
2074 command_and_input_section,
2075 ],
2076 ['PropertyGroup',
2077 ['ComputeLinkInputsTargets',
2078 '$(ComputeLinkInputsTargets);',
2079 '%s;' % rule.compute_output
2080 ],
2081 ['ComputeLibInputsTargets',
2082 '$(ComputeLibInputsTargets);',
2083 '%s;' % rule.compute_output
2084 ],
2085 ],
2086 ['Target',
2087 {'Name': rule.compute_output,
2088 'Condition': "'@(%s)' != ''" % rule_name
2089 },
2090 ['ItemGroup',
2091 [rule.dirs_to_make,
2092 {'Condition': "'@(%s)' != '' and "
2093 "'%%(%s.ExcludedFromBuild)' != 'true'" % (rule_name, rule_name),
2094 'Include': '%%(%s.Outputs)' % rule_name
2095 }
2096 ],
2097 ['Link',
2098 {'Include': '%%(%s.Identity)' % rule.dirs_to_make,
2099 'Condition': extension_condition
2100 }
2101 ],
2102 ['Lib',
2103 {'Include': '%%(%s.Identity)' % rule.dirs_to_make,
2104 'Condition': extension_condition
2105 }
2106 ],
2107 ['ImpLib',
2108 {'Include': '%%(%s.Identity)' % rule.dirs_to_make,
2109 'Condition': extension_condition
2110 }
2111 ],
2112 ],
2113 ['MakeDir',
2114 {'Directories': ("@(%s->'%%(RootDir)%%(Directory)')" %
2115 rule.dirs_to_make)
2116 }
2117 ]
2118 ],
2119 ])
2120 easy_xml.WriteXmlIfChanged(content, targets_path)
2121
2122
2123 def _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules):
2124 # Generate the .xml file
2125 content = [
2126 'ProjectSchemaDefinitions',
2127 {'xmlns': ('clr-namespace:Microsoft.Build.Framework.XamlTypes;'
2128 'assembly=Microsoft.Build.Framework'),
2129 'xmlns:x': 'http://schemas.microsoft.com/winfx/2006/xaml',
2130 'xmlns:sys': 'clr-namespace:System;assembly=mscorlib',
2131 'xmlns:transformCallback':
2132 'Microsoft.Cpp.Dev10.ConvertPropertyCallback'
2133 }
2134 ]
2135 for rule in msbuild_rules:
2136 content.extend([
2137 ['Rule',
2138 {'Name': rule.rule_name,
2139 'PageTemplate': 'tool',
2140 'DisplayName': rule.display_name,
2141 'Order': '200'
2142 },
2143 ['Rule.DataSource',
2144 ['DataSource',
2145 {'Persistence': 'ProjectFile',
2146 'ItemType': rule.rule_name
2147 }
2148 ]
2149 ],
2150 ['Rule.Categories',
2151 ['Category',
2152 {'Name': 'General'},
2153 ['Category.DisplayName',
2154 ['sys:String', 'General'],
2155 ],
2156 ],
2157 ['Category',
2158 {'Name': 'Command Line',
2159 'Subtype': 'CommandLine'
2160 },
2161 ['Category.DisplayName',
2162 ['sys:String', 'Command Line'],
2163 ],
2164 ],
2165 ],
2166 ['StringListProperty',
2167 {'Name': 'Inputs',
2168 'Category': 'Command Line',
2169 'IsRequired': 'true',
2170 'Switch': ' '
2171 },
2172 ['StringListProperty.DataSource',
2173 ['DataSource',
2174 {'Persistence': 'ProjectFile',
2175 'ItemType': rule.rule_name,
2176 'SourceType': 'Item'
2177 }
2178 ]
2179 ],
2180 ],
2181 ['StringProperty',
2182 {'Name': 'CommandLineTemplate',
2183 'DisplayName': 'Command Line',
2184 'Visible': 'False',
2185 'IncludeInCommandLine': 'False'
2186 }
2187 ],
2188 ['DynamicEnumProperty',
2189 {'Name': rule.before_targets,
2190 'Category': 'General',
2191 'EnumProvider': 'Targets',
2192 'IncludeInCommandLine': 'False'
2193 },
2194 ['DynamicEnumProperty.DisplayName',
2195 ['sys:String', 'Execute Before'],
2196 ],
2197 ['DynamicEnumProperty.Description',
2198 ['sys:String', 'Specifies the targets for the build customization'
2199 ' to run before.'
2200 ],
2201 ],
2202 ['DynamicEnumProperty.ProviderSettings',
2203 ['NameValuePair',
2204 {'Name': 'Exclude',
2205 'Value': '^%s|^Compute' % rule.before_targets
2206 }
2207 ]
2208 ],
2209 ['DynamicEnumProperty.DataSource',
2210 ['DataSource',
2211 {'Persistence': 'ProjectFile',
2212 'HasConfigurationCondition': 'true'
2213 }
2214 ]
2215 ],
2216 ],
2217 ['DynamicEnumProperty',
2218 {'Name': rule.after_targets,
2219 'Category': 'General',
2220 'EnumProvider': 'Targets',
2221 'IncludeInCommandLine': 'False'
2222 },
2223 ['DynamicEnumProperty.DisplayName',
2224 ['sys:String', 'Execute After'],
2225 ],
2226 ['DynamicEnumProperty.Description',
2227 ['sys:String', ('Specifies the targets for the build customization'
2228 ' to run after.')
2229 ],
2230 ],
2231 ['DynamicEnumProperty.ProviderSettings',
2232 ['NameValuePair',
2233 {'Name': 'Exclude',
2234 'Value': '^%s|^Compute' % rule.after_targets
2235 }
2236 ]
2237 ],
2238 ['DynamicEnumProperty.DataSource',
2239 ['DataSource',
2240 {'Persistence': 'ProjectFile',
2241 'ItemType': '',
2242 'HasConfigurationCondition': 'true'
2243 }
2244 ]
2245 ],
2246 ],
2247 ['StringListProperty',
2248 {'Name': 'Outputs',
2249 'DisplayName': 'Outputs',
2250 'Visible': 'False',
2251 'IncludeInCommandLine': 'False'
2252 }
2253 ],
2254 ['StringProperty',
2255 {'Name': 'ExecutionDescription',
2256 'DisplayName': 'Execution Description',
2257 'Visible': 'False',
2258 'IncludeInCommandLine': 'False'
2259 }
2260 ],
2261 ['StringListProperty',
2262 {'Name': 'AdditionalDependencies',
2263 'DisplayName': 'Additional Dependencies',
2264 'IncludeInCommandLine': 'False',
2265 'Visible': 'false'
2266 }
2267 ],
2268 ['StringProperty',
2269 {'Subtype': 'AdditionalOptions',
2270 'Name': 'AdditionalOptions',
2271 'Category': 'Command Line'
2272 },
2273 ['StringProperty.DisplayName',
2274 ['sys:String', 'Additional Options'],
2275 ],
2276 ['StringProperty.Description',
2277 ['sys:String', 'Additional Options'],
2278 ],
2279 ],
2280 ],
2281 ['ItemType',
2282 {'Name': rule.rule_name,
2283 'DisplayName': rule.display_name
2284 }
2285 ],
2286 ['FileExtension',
2287 {'Name': '*' + rule.extension,
2288 'ContentType': rule.rule_name
2289 }
2290 ],
2291 ['ContentType',
2292 {'Name': rule.rule_name,
2293 'DisplayName': '',
2294 'ItemType': rule.rule_name
2295 }
2296 ]
2297 ])
2298 easy_xml.WriteXmlIfChanged(content, xml_path)
2299
2300
2301 def _GetConfigurationAndPlatform(name, settings):
2302 configuration = name.rsplit('_', 1)[0]
2303 platform = settings.get('msvs_configuration_platform', 'Win32')
2304 return (configuration, platform)
2305
2306
2307 def _GetConfigurationCondition(name, settings):
2308 return (r"'$(Configuration)|$(Platform)'=='%s|%s'" %
2309 _GetConfigurationAndPlatform(name, settings))
2310
2311
2312 def _GetMSBuildProjectConfigurations(configurations):
2313 group = ['ItemGroup', {'Label': 'ProjectConfigurations'}]
2314 for (name, settings) in sorted(configurations.iteritems()):
2315 configuration, platform = _GetConfigurationAndPlatform(name, settings)
2316 designation = '%s|%s' % (configuration, platform)
2317 group.append(
2318 ['ProjectConfiguration', {'Include': designation},
2319 ['Configuration', configuration],
2320 ['Platform', platform]])
2321 return [group]
2322
2323
2324 def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name):
2325 prefix = spec.get('product_prefix', '')
2326 product_name = spec.get('product_name', '$(ProjectName)')
2327 target_name = prefix + product_name
2328 namespace = os.path.splitext(gyp_file_name)[0]
2329 return [
2330 ['PropertyGroup', {'Label': 'Globals'},
2331 ['ProjectGuid', guid],
2332 ['Keyword', 'Win32Proj'],
2333 ['RootNamespace', namespace],
2334 ['TargetName', target_name],
2335 ]
2336 ]
2337
2338
2339 def _GetMSBuildConfigurationDetails(spec, build_file):
2340 properties = {}
2341 for name, settings in spec['configurations'].iteritems():
2342 msbuild_attributes = _GetMSBuildAttributes(spec, settings, build_file)
2343 condition = _GetConfigurationCondition(name, settings)
2344 character_set = msbuild_attributes.get('CharacterSet')
2345 _AddConditionalProperty(properties, condition, 'ConfigurationType',
2346 msbuild_attributes['ConfigurationType'])
2347 if character_set:
2348 _AddConditionalProperty(properties, condition, 'CharacterSet',
2349 character_set)
2350 return _GetMSBuildPropertyGroup(spec, 'Configuration', properties)
2351
2352
2353 def _GetMSBuildPropertySheets(configurations):
2354 user_props = r'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props'
2355 return [
2356 ['ImportGroup',
2357 {'Label': 'PropertySheets'},
2358 ['Import',
2359 {'Project': user_props,
2360 'Condition': "exists('%s')" % user_props,
2361 'Label': 'LocalAppDataPlatform'
2362 }
2363 ]
2364 ]
2365 ]
2366
2367
2368 def _GetMSBuildAttributes(spec, config, build_file):
2369 # Use the MSVS attributes and convert them. In the future, we may want to
2370 # support Gyp files specifying 'msbuild_configuration_attributes' directly.
2371 config_type = _GetMSVSConfigurationType(spec, build_file)
2372 msvs_attributes = _GetMSVSAttributes(spec, config, config_type)
2373 msbuild_attributes = {}
2374 for a in msvs_attributes:
2375 if a in ['IntermediateDirectory', 'OutputDirectory']:
2376 directory = MSVSSettings.ConvertVCMacrosToMSBuild(msvs_attributes[a])
2377 if not directory.endswith('\\'):
2378 directory += '\\'
2379 msbuild_attributes[a] = directory
2380 elif a == 'CharacterSet':
2381 msbuild_attributes[a] = {
2382 '0': 'MultiByte',
2383 '1': 'Unicode'
2384 }[msvs_attributes[a]]
2385 elif a == 'ConfigurationType':
2386 msbuild_attributes[a] = {
2387 '1': 'Application',
2388 '2': 'DynamicLibrary',
2389 '4': 'StaticLibrary',
2390 '10': 'Utility'
2391 }[msvs_attributes[a]]
2392 else:
2393 print 'Warning: Do not know how to convert MSVS attribute ' + a
2394 return msbuild_attributes
2395
2396
2397 def _GetMSBuildConfigurationGlobalProperties(spec, configurations, build_file):
2398 # TODO(jeanluc) We could optimize out the following and do it only if
2399 # there are actions.
2400 # TODO(jeanluc) Handle the equivalent of setting 'CYGWIN=nontsec'.
2401 new_paths = []
2402 cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.'])[0]
2403 if cygwin_dirs:
2404 cyg_path = '$(MSBuildProjectDirectory)\\%s\\bin\\' % _FixPath(cygwin_dirs)
2405 new_paths.append(cyg_path)
2406 # TODO(jeanluc) Change the convention to have both a cygwin_dir and a
2407 # python_dir.
2408 python_path = cyg_path.replace('cygwin\\bin', 'python_26')
2409 new_paths.append(python_path)
2410 if new_paths:
2411 new_paths = '$(ExecutablePath);' + ';'.join(new_paths)
2412
2413 properties = {}
2414 for (name, configuration) in sorted(configurations.iteritems()):
2415 condition = _GetConfigurationCondition(name, configuration)
2416 attributes = _GetMSBuildAttributes(spec, configuration, build_file)
2417 msbuild_settings = configuration['finalized_msbuild_settings']
2418 _AddConditionalProperty(properties, condition, 'IntDir',
2419 attributes['IntermediateDirectory'])
2420 _AddConditionalProperty(properties, condition, 'OutDir',
2421 attributes['OutputDirectory'])
2422 if new_paths:
2423 _AddConditionalProperty(properties, condition, 'ExecutablePath',
2424 new_paths)
2425 tool_settings = msbuild_settings.get('', {})
2426 for name, value in sorted(tool_settings.iteritems()):
2427 formatted_value = _GetValueFormattedForMSBuild('', name, value)
2428 _AddConditionalProperty(properties, condition, name, formatted_value)
2429 return _GetMSBuildPropertyGroup(spec, None, properties)
2430
2431
2432 def _AddConditionalProperty(properties, condition, name, value):
2433 """Adds a property / conditional value pair to a dictionary.
2434
2435 Arguments:
2436 properties: The dictionary to be modified. The key is the name of the
2437 property. The value is itself a dictionary; its key is the value and
2438 the value a list of condition for which this value is true.
2439 condition: The condition under which the named property has the value.
2440 name: The name of the property.
2441 value: The value of the property.
2442 """
2443 if name not in properties:
2444 properties[name] = {}
2445 values = properties[name]
2446 if value not in values:
2447 values[value] = []
2448 conditions = values[value]
2449 conditions.append(condition)
2450
2451
2452 def _GetMSBuildPropertyGroup(spec, label, properties):
2453 """Returns a PropertyGroup definition for the specified properties.
2454
2455 Arguments:
2456 spec: The target project dict.
2457 label: An optional label for the PropertyGroup.
2458 properties: The dictionary to be converted. The key is the name of the
2459 property. The value is itself a dictionary; its key is the value and
2460 the value a list of condition for which this value is true.
2461 """
2462 group = ['PropertyGroup']
2463 if label:
2464 group.append({'Label': label})
2465 num_configurations = len(spec['configurations'])
2466 for name, values in sorted(properties.iteritems()):
2467 for value, conditions in sorted(values.iteritems()):
2468 if len(conditions) == num_configurations:
2469 # If the value is the same all configurations,
2470 # just add one unconditional entry.
2471 group.append([name, value])
2472 else:
2473 for condition in conditions:
2474 group.append([name, {'Condition': condition}, value])
2475 return [group]
2476
2477
2478 def _GetMSBuildToolSettingsSections(spec, configurations):
2479 groups = []
2480 for (name, configuration) in sorted(configurations.iteritems()):
2481 msbuild_settings = configuration['finalized_msbuild_settings']
2482 group = ['ItemDefinitionGroup',
2483 {'Condition': _GetConfigurationCondition(name, configuration)}
2484 ]
2485 for tool_name, tool_settings in sorted(msbuild_settings.iteritems()):
2486 # Skip the tool named '' which is a holder of global settings handled
2487 # by _GetMSBuildConfigurationGlobalProperties.
2488 if tool_name:
2489 if tool_settings:
2490 tool = [tool_name]
2491 for name, value in sorted(tool_settings.iteritems()):
2492 formatted_value = _GetValueFormattedForMSBuild(tool_name, name,
2493 value)
2494 tool.append([name, formatted_value])
2495 group.append(tool)
2496 groups.append(group)
2497 return groups
2498
2499
2500 def _FinalizeMSBuildSettings(spec, configuration):
2501 if 'msbuild_settings' in configuration:
2502 converted = False
2503 msbuild_settings = configuration['msbuild_settings']
2504 MSVSSettings.ValidateMSBuildSettings(msbuild_settings)
2505 else:
2506 converted = True
2507 msvs_settings = configuration.get('msvs_settings', {})
2508 msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(msvs_settings)
2509 include_dirs, resource_include_dirs = _GetIncludeDirs(configuration)
2510 libraries = _GetLibraries(spec)
2511 out_file, _, msbuild_tool = _GetOutputFilePathAndTool(spec)
2512 defines = _GetDefines(configuration)
2513 if converted:
2514 # Visual Studio 2010 has TR1
2515 defines = [d for d in defines if d != '_HAS_TR1=0']
2516 # Warn of ignored settings
2517 ignored_settings = ['msvs_prebuild', 'msvs_postbuild', 'msvs_tool_files']
2518 for ignored_setting in ignored_settings:
2519 value = configuration.get(ignored_setting)
2520 if value:
2521 print ('Warning: The automatic conversion to MSBuild does not handle '
2522 '%s. Ignoring setting of %s' % (ignored_setting, str(value)))
2523
2524 defines = [_EscapeCppDefineForMSBuild(d) for d in defines]
2525 disabled_warnings = _GetDisabledWarnings(configuration)
2526 # TODO(jeanluc) Validate & warn that we don't translate
2527 # prebuild = configuration.get('msvs_prebuild')
2528 # postbuild = configuration.get('msvs_postbuild')
2529 def_file = _GetModuleDefinition(spec)
2530 precompiled_header = configuration.get('msvs_precompiled_header')
2531
2532 # Add the information to the appropriate tool
2533 # TODO(jeanluc) We could optimize and generate these settings only if
2534 # the corresponding files are found, e.g. don't generate ResourceCompile
2535 # if you don't have any resources.
2536 _ToolAppend(msbuild_settings, 'ClCompile',
2537 'AdditionalIncludeDirectories', include_dirs)
2538 _ToolAppend(msbuild_settings, 'ResourceCompile',
2539 'AdditionalIncludeDirectories', resource_include_dirs)
2540 # Add in libraries.
2541 _ToolAppend(msbuild_settings, 'Link', 'AdditionalDependencies', libraries)
2542 if out_file:
2543 _ToolAppend(msbuild_settings, msbuild_tool, 'OutputFile', out_file,
2544 only_if_unset=True)
2545 # Add defines.
2546 _ToolAppend(msbuild_settings, 'ClCompile',
2547 'PreprocessorDefinitions', defines)
2548 _ToolAppend(msbuild_settings, 'ResourceCompile',
2549 'PreprocessorDefinitions', defines)
2550 # Add disabled warnings.
2551 _ToolAppend(msbuild_settings, 'ClCompile',
2552 'DisableSpecificWarnings', disabled_warnings)
2553 # Turn on precompiled headers if appropriate.
2554 if precompiled_header:
2555 precompiled_header = os.path.split(precompiled_header)[1]
2556 _ToolAppend(msbuild_settings, 'ClCompile', 'PrecompiledHeader', 'Use')
2557 _ToolAppend(msbuild_settings, 'ClCompile',
2558 'PrecompiledHeaderFile', precompiled_header)
2559 _ToolAppend(msbuild_settings, 'ClCompile',
2560 'ForcedIncludeFiles', precompiled_header)
2561 # Loadable modules don't generate import libraries;
2562 # tell dependent projects to not expect one.
2563 if spec['type'] == 'loadable_module':
2564 _ToolAppend(msbuild_settings, '', 'IgnoreImportLibrary', 'true')
2565 # Set the module definition file if any.
2566 if def_file:
2567 _ToolAppend(msbuild_settings, 'Link', 'ModuleDefinitionFile', def_file)
2568 configuration['finalized_msbuild_settings'] = msbuild_settings
2569
2570
2571 def _GetValueFormattedForMSBuild(tool_name, name, value):
2572 if type(value) == list:
2573 # For some settings, VS2010 does not automatically extends the settings
2574 # TODO(jeanluc) Is this what we want?
2575 if name in ['AdditionalDependencies',
2576 'AdditionalIncludeDirectories',
2577 'AdditionalLibraryDirectories',
2578 'AdditionalOptions',
2579 'DelayLoadDLLs',
2580 'DisableSpecificWarnings',
2581 'PreprocessorDefinitions']:
2582 value.append('%%(%s)' % name)
2583 # For most tools, entries in a list should be separated with ';' but some
2584 # settings use a space. Check for those first.
2585 exceptions = {
2586 'ClCompile': ['AdditionalOptions'],
2587 'Link': ['AdditionalOptions'],
2588 'Lib': ['AdditionalOptions']}
2589 if tool_name in exceptions and name in exceptions[tool_name]:
2590 char = ' '
2591 else:
2592 char = ';'
2593 formatted_value = char.join(
2594 [MSVSSettings.ConvertVCMacrosToMSBuild(i) for i in value])
2595 else:
2596 formatted_value = MSVSSettings.ConvertVCMacrosToMSBuild(value)
2597 return formatted_value
2598
2599
2600 def _VerifySourcesExist(sources, root_dir):
2601 """Verifies that all source files exist on disk.
2602
2603 Checks that all regular source files, i.e. not created at run time,
2604 exist on disk. Missing files cause needless recompilation but no otherwise
2605 visible errors.
2606
2607 Arguments:
2608 sources: A recursive list of Filter/file names.
2609 root_dir: The root directory for the relative path names.
2610 """
2611 for source in sources:
2612 if isinstance(source, MSVSProject.Filter):
2613 _VerifySourcesExist(source.contents, root_dir)
2614 else:
2615 if '$' not in source:
2616 full_path = os.path.join(root_dir, source)
2617 if not os.path.exists(full_path):
2618 print 'Error: Missing input file ' + full_path
2619
2620
2621 def _GetMSBuildSources(spec, sources, exclusions, extension_to_rule_name,
2622 actions_spec, sources_handled_by_action):
2623 groups = ['none', 'midl', 'include', 'compile', 'resource', 'rule']
2624 grouped_sources = {}
2625 for g in groups:
2626 grouped_sources[g] = []
2627
2628 _AddSources2(spec, sources, exclusions, grouped_sources,
2629 extension_to_rule_name, sources_handled_by_action)
2630 sources = []
2631 for g in groups:
2632 if grouped_sources[g]:
2633 sources.append(['ItemGroup'] + grouped_sources[g])
2634 if actions_spec:
2635 sources.append(['ItemGroup'] + actions_spec)
2636 return sources
2637
2638
2639 def _AddSources2(spec, sources, exclusions, grouped_sources,
2640 extension_to_rule_name, sources_handled_by_action):
2641 extensions_excluded_from_precompile = []
2642 for source in sources:
2643 if isinstance(source, MSVSProject.Filter):
2644 _AddSources2(spec, source.contents, exclusions, grouped_sources,
2645 extension_to_rule_name, sources_handled_by_action)
2646 else:
2647 if not source in sources_handled_by_action:
2648 detail = []
2649 excluded_configurations = exclusions.get(source, [])
2650 if len(excluded_configurations) == len(spec['configurations']):
2651 detail.append(['ExcludedFromBuild', 'true'])
2652 else:
2653 for config_name, configuration in sorted(excluded_configurations):
2654 condition = _GetConfigurationCondition(config_name, configuration)
2655 detail.append(['ExcludedFromBuild',
2656 {'Condition': condition},
2657 'true'])
2658 # Add precompile if needed
2659 for config_name, configuration in spec['configurations'].iteritems():
2660 precompiled_source = configuration.get('msvs_precompiled_source', '')
2661 precompiled_source = _FixPath(precompiled_source)
2662 if not extensions_excluded_from_precompile:
2663 # If the precompiled header is generated by a C source, we must
2664 # not try to use it for C++ sources, and vice versa.
2665 basename, extension = os.path.splitext(precompiled_source)
2666 if extension == '.c':
2667 extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx']
2668 else:
2669 extensions_excluded_from_precompile = ['.c']
2670
2671 if precompiled_source == source:
2672 condition = _GetConfigurationCondition(config_name, configuration)
2673 detail.append(['PrecompiledHeader',
2674 {'Condition': condition},
2675 'Create'
2676 ])
2677 else:
2678 # Turn off precompiled header usage for source files of a
2679 # different type than the file that generated the
2680 # precompiled header.
2681 for extension in extensions_excluded_from_precompile:
2682 if source.endswith(extension):
2683 detail.append(['PrecompiledHeader', ''])
2684 detail.append(['ForcedIncludeFiles', ''])
2685
2686 group, element = _MapFileToMsBuildSourceType(source,
2687 extension_to_rule_name)
2688 grouped_sources[group].append([element, {'Include': source}] + detail)
2689
2690
2691 def _GetMSBuildProjectReferences(project):
2692 references = []
2693 if project.dependencies:
2694 group = ['ItemGroup']
2695 for dependency in project.dependencies:
2696 guid = dependency.guid
2697 project_dir = os.path.split(project.path)[0]
2698 relative_path = gyp.common.RelativePath(dependency.path, project_dir)
2699 group.append(
2700 ['ProjectReference',
2701 {'Include': relative_path},
2702 ['Project', guid],
2703 ['ReferenceOutputAssembly', 'false']
2704 ])
2705 references.append(group)
2706 return references
2707
2708
2709 def _GenerateMSBuildProject(project, options, version):
2710 spec = project.spec
2711 configurations = spec['configurations']
2712 gyp_dir, gyp_file_name = os.path.split(project.path)
2713 msbuildproj_dir = os.path.dirname(project.path)
2714 if msbuildproj_dir and not os.path.exists(msbuildproj_dir):
2715 os.makedirs(msbuildproj_dir)
2716 # Prepare list of sources and excluded sources.
2717 gyp_dir = os.path.split(project.path)[0]
2718 gyp_file = posixpath.split(project.build_file)[1]
2719 gyp_path = _NormalizedSource(gyp_file)
2720 relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, gyp_dir)
2721
2722 sources, excluded_sources = _PrepareListOfSources(spec,
2723 relative_path_of_gyp_file)
2724 # Add rules.
2725 actions_to_add = {}
2726 props_files_of_rules = set()
2727 targets_files_of_rules = set()
2728 extension_to_rule_name = {}
2729 _GenerateRulesForMSBuild(gyp_dir, options, spec,
2730 sources, excluded_sources,
2731 props_files_of_rules, targets_files_of_rules,
2732 actions_to_add, extension_to_rule_name)
2733 sources, excluded_sources, excluded_idl = (
2734 _AdjustSourcesAndConvertToFilterHierarchy(spec, options,
2735 gyp_dir, sources,
2736 excluded_sources))
2737 _AddActions(actions_to_add, spec, project.build_file)
2738 _AddCopies(actions_to_add, spec)
2739
2740 # NOTE: this stanza must appear after all actions have been decided.
2741 # Don't excluded sources with actions attached, or they won't run.
2742 excluded_sources = _FilterActionsFromExcluded(
2743 excluded_sources, actions_to_add)
2744
2745 exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl)
2746 actions_spec, sources_handled_by_action = _GenerateActionsForMSBuild(
2747 spec, actions_to_add)
2748
2749 _GenerateMSBuildFiltersFile(project.path + '.filters', sources,
2750 extension_to_rule_name)
2751 _VerifySourcesExist(sources, gyp_dir)
2752
2753 for (_, configuration) in configurations.iteritems():
2754 _FinalizeMSBuildSettings(spec, configuration)
2755
2756 # Add attributes to root element
2757
2758 import_default_section = [
2759 ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.Default.props'}]]
2760 import_cpp_props_section = [
2761 ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.props'}]]
2762 import_cpp_targets_section = [
2763 ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.targets'}]]
2764 macro_section = [['PropertyGroup', {'Label': 'UserMacros'}]]
2765
2766 content = [
2767 'Project',
2768 {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003',
2769 'ToolsVersion': version.ProjectVersion(),
2770 'DefaultTargets': 'Build'
2771 }]
2772
2773 content += _GetMSBuildProjectConfigurations(configurations)
2774 content += _GetMSBuildGlobalProperties(spec, project.guid, gyp_file_name)
2775 content += import_default_section
2776 content += _GetMSBuildConfigurationDetails(spec, project.build_file)
2777 content += import_cpp_props_section
2778 content += _GetMSBuildExtensions(props_files_of_rules)
2779 content += _GetMSBuildPropertySheets(configurations)
2780 content += macro_section
2781 content += _GetMSBuildConfigurationGlobalProperties(spec, configurations,
2782 project.build_file)
2783 content += _GetMSBuildToolSettingsSections(spec, configurations)
2784 content += _GetMSBuildSources(
2785 spec, sources, exclusions, extension_to_rule_name, actions_spec,
2786 sources_handled_by_action)
2787 content += _GetMSBuildProjectReferences(project)
2788 content += import_cpp_targets_section
2789 content += _GetMSBuildExtensionTargets(targets_files_of_rules)
2790
2791 # TODO(jeanluc) File a bug to get rid of runas. We had in MSVS:
2792 # has_run_as = _WriteMSVSUserFile(project.path, version, spec)
2793
2794 easy_xml.WriteXmlIfChanged(content, project.path)
2795
2796
2797 def _GetMSBuildExtensions(props_files_of_rules):
2798 extensions = ['ImportGroup', {'Label': 'ExtensionSettings'}]
2799 for props_file in props_files_of_rules:
2800 extensions.append(['Import', {'Project': props_file}])
2801 return [extensions]
2802
2803
2804 def _GetMSBuildExtensionTargets(targets_files_of_rules):
2805 targets_node = ['ImportGroup', {'Label': 'ExtensionTargets'}]
2806 for targets_file in sorted(targets_files_of_rules):
2807 targets_node.append(['Import', {'Project': targets_file}])
2808 return [targets_node]
2809
2810
2811 def _GenerateActionsForMSBuild(spec, actions_to_add):
2812 """Add actions accumulated into an actions_to_add, merging as needed.
2813
2814 Arguments:
2815 spec: the target project dict
2816 actions_to_add: dictionary keyed on input name, which maps to a list of
2817 dicts describing the actions attached to that input file.
2818
2819 Returns:
2820 A pair of (action specification, the sources handled by this action).
2821 """
2822 sources_handled_by_action = set()
2823 actions_spec = []
2824 for primary_input, actions in actions_to_add.iteritems():
2825 inputs = set()
2826 outputs = set()
2827 descriptions = []
2828 commands = []
2829 for action in actions:
2830 inputs.update(set(action['inputs']))
2831 outputs.update(set(action['outputs']))
2832 descriptions.append(action['description'])
2833 cmd = action['command']
2834 # For most actions, add 'call' so that actions that invoke batch files
2835 # return and continue executing. msbuild_use_call provides a way to
2836 # disable this but I have not seen any adverse effect from doing that
2837 # for everything.
2838 if action.get('msbuild_use_call', True):
2839 cmd = 'call ' + cmd
2840 commands.append(cmd)
2841 # Add the custom build action for one input file.
2842 description = ', and also '.join(descriptions)
2843 command = ' && '.join(commands)
2844 _AddMSBuildAction(spec,
2845 primary_input,
2846 inputs,
2847 outputs,
2848 command,
2849 description,
2850 sources_handled_by_action,
2851 actions_spec)
2852 return actions_spec, sources_handled_by_action
2853
2854
2855 def _AddMSBuildAction(spec, primary_input, inputs, outputs, cmd, description,
2856 sources_handled_by_action, actions_spec):
2857 command = MSVSSettings.ConvertVCMacrosToMSBuild(cmd)
2858 primary_input = _FixPath(primary_input)
2859 inputs_array = _FixPaths(inputs)
2860 outputs_array = _FixPaths(outputs)
2861 additional_inputs = ';'.join([i for i in inputs_array
2862 if i != primary_input])
2863 outputs = ';'.join(outputs_array)
2864 sources_handled_by_action.add(primary_input)
2865 action_spec = ['CustomBuild', {'Include': primary_input}]
2866 action_spec.extend(
2867 # TODO(jeanluc) 'Document' for all or just if as_sources?
2868 [['FileType', 'Document'],
2869 ['Command', command],
2870 ['Message', description],
2871 ['Outputs', outputs]
2872 ])
2873 if additional_inputs:
2874 action_spec.append(['AdditionalInputs', additional_inputs])
2875 actions_spec.append(action_spec)
+0
-35
third_party/gyp/pylib/gyp/generator/msvs_test.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """ Unit tests for the msvs.py file. """
7
8 import gyp.generator.msvs as msvs
9 import unittest
10 import StringIO
11
12
13 class TestSequenceFunctions(unittest.TestCase):
14
15 def setUp(self):
16 self.stderr = StringIO.StringIO()
17
18 def test_GetLibraries(self):
19 self.assertEqual(
20 msvs._GetLibraries({}),
21 [])
22 self.assertEqual(
23 msvs._GetLibraries({'libraries': []}),
24 [])
25 self.assertEqual(
26 msvs._GetLibraries({'other':'foo', 'libraries': ['a.lib']}),
27 ['a.lib'])
28 self.assertEqual(
29 msvs._GetLibraries({'libraries': ['a.lib', 'b.lib', 'c.lib', '-lb.lib',
30 '-lb.lib', 'd.lib', 'a.lib']}),
31 ['c.lib', 'b.lib', 'd.lib', 'a.lib'])
32
33 if __name__ == '__main__':
34 unittest.main()
+0
-713
third_party/gyp/pylib/gyp/generator/ninja.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import gyp
7 import gyp.common
8 import gyp.system_test
9 import os.path
10 import pprint
11 import subprocess
12 import sys
13
14 import gyp.ninja_syntax as ninja_syntax
15
16 generator_default_variables = {
17 'OS': 'linux',
18
19 'EXECUTABLE_PREFIX': '',
20 'EXECUTABLE_SUFFIX': '',
21 'STATIC_LIB_PREFIX': '',
22 'STATIC_LIB_SUFFIX': '.a',
23 'SHARED_LIB_PREFIX': 'lib',
24 'SHARED_LIB_SUFFIX': '.so',
25
26 # Gyp expects the following variables to be expandable by the build
27 # system to the appropriate locations. Ninja prefers paths to be
28 # known at compile time. To resolve this, introduce special
29 # variables starting with $! (which begin with a $ so gyp knows it
30 # should be treated as a path, but is otherwise an invalid
31 # ninja/shell variable) that are passed to gyp here but expanded
32 # before writing out into the target .ninja files; see
33 # ExpandSpecial.
34 'INTERMEDIATE_DIR': '$!INTERMEDIATE_DIR',
35 'SHARED_INTERMEDIATE_DIR': '$!PRODUCT_DIR/gen',
36 'PRODUCT_DIR': '$!PRODUCT_DIR',
37 'SHARED_LIB_DIR': '$!PRODUCT_DIR/lib',
38 'LIB_DIR': '',
39
40 # Special variables that may be used by gyp 'rule' targets.
41 # We generate definitions for these variables on the fly when processing a
42 # rule.
43 'RULE_INPUT_ROOT': '$root',
44 'RULE_INPUT_PATH': '$source',
45 'RULE_INPUT_EXT': '$ext',
46 'RULE_INPUT_NAME': '$name',
47 }
48
49 # TODO: enable cross compiling once we figure out:
50 # - how to not build extra host objects in the non-cross-compile case.
51 # - how to decide what the host compiler is (should not just be $cc).
52 # - need ld_host as well.
53 generator_supports_multiple_toolsets = False
54
55
56 def StripPrefix(arg, prefix):
57 if arg.startswith(prefix):
58 return arg[len(prefix):]
59 return arg
60
61
62 def QuoteShellArgument(arg):
63 return "'" + arg.replace("'", "'" + '"\'"' + "'") + "'"
64
65
66 def MaybeQuoteShellArgument(arg):
67 if '"' in arg or ' ' in arg:
68 return QuoteShellArgument(arg)
69 return arg
70
71
72 def InvertRelativePath(path):
73 """Given a relative path like foo/bar, return the inverse relative path:
74 the path from the relative path back to the origin dir.
75
76 E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path)))
77 should always produce the empty string."""
78
79 if not path:
80 return path
81 # Only need to handle relative paths into subdirectories for now.
82 assert '..' not in path, path
83 depth = len(path.split('/'))
84 return '/'.join(['..'] * depth)
85
86
87 # A small discourse on paths as used within the Ninja build:
88 # All files we produce (both at gyp and at build time) appear in the
89 # build directory (e.g. out/Debug).
90 #
91 # Paths within a given .gyp file are always relative to the directory
92 # containing the .gyp file. Call these "gyp paths". This includes
93 # sources as well as the starting directory a given gyp rule/action
94 # expects to be run from. We call the path from the source root to
95 # the gyp file the "base directory" within the per-.gyp-file
96 # NinjaWriter code.
97 #
98 # All paths as written into the .ninja files are relative to the build
99 # directory. Call these paths "ninja paths".
100 #
101 # We translate between these two notions of paths with two helper
102 # functions:
103 #
104 # - GypPathToNinja translates a gyp path (i.e. relative to the .gyp file)
105 # into the equivalent ninja path.
106 #
107 # - GypPathToUniqueOutput translates a gyp path into a ninja path to write
108 # an output file; the result can be namespaced such that is unique
109 # to the input file name as well as the output target name.
110
111 class NinjaWriter:
112 def __init__(self, target_outputs, base_dir, build_dir, output_file):
113 """
114 base_dir: path from source root to directory containing this gyp file,
115 by gyp semantics, all input paths are relative to this
116 build_dir: path from source root to build output
117 """
118
119 self.target_outputs = target_outputs
120 self.base_dir = base_dir
121 self.build_dir = build_dir
122 self.ninja = ninja_syntax.Writer(output_file)
123
124 # Relative path from build output dir to base dir.
125 self.build_to_base = os.path.join(InvertRelativePath(build_dir), base_dir)
126 # Relative path from base dir to build dir.
127 self.base_to_build = os.path.join(InvertRelativePath(base_dir), build_dir)
128
129 def ExpandSpecial(self, path, product_dir=None):
130 """Expand specials like $!PRODUCT_DIR in |path|.
131
132 If |product_dir| is None, assumes the cwd is already the product
133 dir. Otherwise, |product_dir| is the relative path to the product
134 dir.
135 """
136
137 PRODUCT_DIR = '$!PRODUCT_DIR'
138 if PRODUCT_DIR in path:
139 if product_dir:
140 path = path.replace(PRODUCT_DIR, product_dir)
141 else:
142 path = path.replace(PRODUCT_DIR + '/', '')
143 path = path.replace(PRODUCT_DIR, '.')
144
145 INTERMEDIATE_DIR = '$!INTERMEDIATE_DIR'
146 if INTERMEDIATE_DIR in path:
147 int_dir = self.GypPathToUniqueOutput('gen')
148 # GypPathToUniqueOutput generates a path relative to the product dir,
149 # so insert product_dir in front if it is provided.
150 path = path.replace(INTERMEDIATE_DIR,
151 os.path.join(product_dir or '', int_dir))
152
153 return path
154
155 def GypPathToNinja(self, path):
156 """Translate a gyp path to a ninja path.
157
158 See the above discourse on path conversions."""
159 if path.startswith('$!'):
160 return self.ExpandSpecial(path)
161 assert '$' not in path, path
162 return os.path.normpath(os.path.join(self.build_to_base, path))
163
164 def GypPathToUniqueOutput(self, path, qualified=True):
165 """Translate a gyp path to a ninja path for writing output.
166
167 If qualified is True, qualify the resulting filename with the name
168 of the target. This is necessary when e.g. compiling the same
169 path twice for two separate output targets.
170
171 See the above discourse on path conversions."""
172
173 path = self.ExpandSpecial(path)
174 assert not path.startswith('$'), path
175
176 # Translate the path following this scheme:
177 # Input: foo/bar.gyp, target targ, references baz/out.o
178 # Output: obj/foo/baz/targ.out.o (if qualified)
179 # obj/foo/baz/out.o (otherwise)
180 # (and obj.host instead of obj for cross-compiles)
181 #
182 # Why this scheme and not some other one?
183 # 1) for a given input, you can compute all derived outputs by matching
184 # its path, even if the input is brought via a gyp file with '..'.
185 # 2) simple files like libraries and stamps have a simple filename.
186
187 obj = 'obj'
188 if self.toolset != 'target':
189 obj += '.' + self.toolset
190
191 path_dir, path_basename = os.path.split(path)
192 if qualified:
193 path_basename = self.name + '.' + path_basename
194 return os.path.normpath(os.path.join(obj, self.base_dir, path_dir,
195 path_basename))
196
197 def StampPath(self, name):
198 """Return a path for a stamp file with a particular name.
199
200 Stamp files are used to collapse a dependency on a bunch of files
201 into a single file."""
202 return self.GypPathToUniqueOutput(name + '.stamp')
203
204 def WriteSpec(self, spec, config):
205 """The main entry point for NinjaWriter: write the build rules for a spec.
206
207 Returns the path to the build output, or None."""
208
209 if spec['type'] == 'settings':
210 # TODO: 'settings' is not actually part of gyp; it was
211 # accidentally introduced somehow into just the Linux build files.
212 return None
213
214 self.name = spec['target_name']
215 self.toolset = spec['toolset']
216
217 # Compute predepends for all rules.
218 # prebuild is the dependencies this target depends on before
219 # running any of its internal steps.
220 prebuild = []
221 if 'dependencies' in spec:
222 prebuild_deps = []
223 for dep in spec['dependencies']:
224 if dep in self.target_outputs:
225 prebuild_deps.append(self.target_outputs[dep][0])
226 if prebuild_deps:
227 stamp = self.StampPath('predepends')
228 prebuild = self.ninja.build(stamp, 'stamp', prebuild_deps)
229 self.ninja.newline()
230
231 # Write out actions, rules, and copies. These must happen before we
232 # compile any sources, so compute a list of predependencies for sources
233 # while we do it.
234 extra_sources = []
235 sources_predepends = self.WriteActionsRulesCopies(spec, extra_sources,
236 prebuild)
237
238 # Write out the compilation steps, if any.
239 link_deps = []
240 sources = spec.get('sources', []) + extra_sources
241 if sources:
242 link_deps = self.WriteSources(config, sources,
243 sources_predepends or prebuild)
244 # Some actions/rules output 'sources' that are already object files.
245 link_deps += [self.GypPathToNinja(f) for f in sources if f.endswith('.o')]
246
247 # The final output of our target depends on the last output of the
248 # above steps.
249 output = None
250 final_deps = link_deps or sources_predepends or prebuild
251 if final_deps:
252 output = self.WriteTarget(spec, config, final_deps)
253 if self.name != output and self.toolset == 'target':
254 # Write a short name to build this target. This benefits both the
255 # "build chrome" case as well as the gyp tests, which expect to be
256 # able to run actions and build libraries by their short name.
257 self.ninja.build(self.name, 'phony', output)
258 return output
259
260 def WriteActionsRulesCopies(self, spec, extra_sources, prebuild):
261 """Write out the Actions, Rules, and Copies steps. Return any outputs
262 of these steps (or a stamp file if there are lots of outputs)."""
263 outputs = []
264
265 if 'actions' in spec:
266 outputs += self.WriteActions(spec['actions'], extra_sources, prebuild)
267 if 'rules' in spec:
268 outputs += self.WriteRules(spec['rules'], extra_sources, prebuild)
269 if 'copies' in spec:
270 outputs += self.WriteCopies(spec['copies'], prebuild)
271
272 # To simplify downstream build edges, ensure we generate a single
273 # stamp file that represents the results of all of the above.
274 if len(outputs) > 1:
275 stamp = self.StampPath('actions_rules_copies')
276 outputs = self.ninja.build(stamp, 'stamp', outputs)
277
278 return outputs
279
280 def GenerateDescription(self, verb, message, fallback):
281 """Generate and return a description of a build step.
282
283 |verb| is the short summary, e.g. ACTION or RULE.
284 |message| is a hand-written description, or None if not available.
285 |fallback| is the gyp-level name of the step, usable as a fallback.
286 """
287 if self.toolset != 'target':
288 verb += '(%s)' % self.toolset
289 if message:
290 return '%s %s' % (verb, self.ExpandSpecial(message))
291 else:
292 return '%s %s: %s' % (verb, self.name, fallback)
293
294 def WriteActions(self, actions, extra_sources, prebuild):
295 all_outputs = []
296 for action in actions:
297 # First write out a rule for the action.
298 name = action['action_name']
299 description = self.GenerateDescription('ACTION',
300 action.get('message', None),
301 name)
302 rule_name = self.WriteNewNinjaRule(name, action['action'], description)
303
304 inputs = [self.GypPathToNinja(i) for i in action['inputs']]
305 if int(action.get('process_outputs_as_sources', False)):
306 extra_sources += action['outputs']
307 outputs = [self.GypPathToNinja(o) for o in action['outputs']]
308
309 # Then write out an edge using the rule.
310 self.ninja.build(outputs, rule_name, inputs,
311 order_only=prebuild)
312 all_outputs += outputs
313
314 self.ninja.newline()
315
316 return all_outputs
317
318 def WriteRules(self, rules, extra_sources, prebuild):
319 all_outputs = []
320 for rule in rules:
321 # First write out a rule for the rule action.
322 name = rule['rule_name']
323 args = rule['action']
324 description = self.GenerateDescription('RULE',
325 rule.get('message', None),
326 '%s $source' % name)
327 rule_name = self.WriteNewNinjaRule(name, args, description)
328
329 # TODO: if the command references the outputs directly, we should
330 # simplify it to just use $out.
331
332 # Rules can potentially make use of some special variables which
333 # must vary per source file.
334 # Compute the list of variables we'll need to provide.
335 special_locals = ('source', 'root', 'ext', 'name')
336 needed_variables = set(['source'])
337 for argument in args:
338 for var in special_locals:
339 if '$' + var in argument:
340 needed_variables.add(var)
341
342 # For each source file, write an edge that generates all the outputs.
343 for source in rule.get('rule_sources', []):
344 basename = os.path.basename(source)
345 root, ext = os.path.splitext(basename)
346
347 # Gather the list of outputs, expanding $vars if possible.
348 outputs = []
349 for output in rule['outputs']:
350 outputs.append(output.replace('$root', root))
351
352 if int(rule.get('process_outputs_as_sources', False)):
353 extra_sources += outputs
354
355 extra_bindings = []
356 for var in needed_variables:
357 if var == 'root':
358 extra_bindings.append(('root', root))
359 elif var == 'source':
360 # '$source' is a parameter to the rule action, which means
361 # it shouldn't be converted to a Ninja path. But we don't
362 # want $!PRODUCT_DIR in there either.
363 source_expanded = self.ExpandSpecial(source, self.base_to_build)
364 extra_bindings.append(('source', source_expanded))
365 elif var == 'ext':
366 extra_bindings.append(('ext', ext))
367 elif var == 'name':
368 extra_bindings.append(('name', basename))
369 else:
370 assert var == None, repr(var)
371
372 inputs = map(self.GypPathToNinja, rule.get('inputs', []))
373 outputs = map(self.GypPathToNinja, outputs)
374 self.ninja.build(outputs, rule_name, self.GypPathToNinja(source),
375 implicit=inputs,
376 order_only=prebuild,
377 variables=extra_bindings)
378
379 all_outputs.extend(outputs)
380
381 return all_outputs
382
383 def WriteCopies(self, copies, prebuild):
384 outputs = []
385 for copy in copies:
386 for path in copy['files']:
387 # Normalize the path so trailing slashes don't confuse us.
388 path = os.path.normpath(path)
389 basename = os.path.split(path)[1]
390 src = self.GypPathToNinja(path)
391 dst = self.GypPathToNinja(os.path.join(copy['destination'], basename))
392 outputs += self.ninja.build(dst, 'copy', src,
393 order_only=prebuild)
394
395 return outputs
396
397 def WriteSources(self, config, sources, predepends):
398 """Write build rules to compile all of |sources|."""
399 if self.toolset == 'host':
400 self.ninja.variable('cc', '$cc_host')
401 self.ninja.variable('cxx', '$cxx_host')
402
403 self.WriteVariableList('defines',
404 ['-D' + MaybeQuoteShellArgument(ninja_syntax.escape(d))
405 for d in config.get('defines', [])])
406 self.WriteVariableList('includes',
407 ['-I' + self.GypPathToNinja(i)
408 for i in config.get('include_dirs', [])])
409 self.WriteVariableList('cflags', config.get('cflags'))
410 self.WriteVariableList('cflags_c', config.get('cflags_c'))
411 self.WriteVariableList('cflags_cc', config.get('cflags_cc'))
412 self.ninja.newline()
413 outputs = []
414 for source in sources:
415 filename, ext = os.path.splitext(source)
416 ext = ext[1:]
417 if ext in ('cc', 'cpp', 'cxx'):
418 command = 'cxx'
419 elif ext in ('c', 's', 'S'):
420 command = 'cc'
421 else:
422 # TODO: should we assert here on unexpected extensions?
423 continue
424 input = self.GypPathToNinja(source)
425 output = self.GypPathToUniqueOutput(filename + '.o')
426 self.ninja.build(output, command, input,
427 order_only=predepends)
428 outputs.append(output)
429 self.ninja.newline()
430 return outputs
431
432 def WriteTarget(self, spec, config, final_deps):
433 if spec['type'] == 'none':
434 # This target doesn't have any explicit final output, but is instead
435 # used for its effects before the final output (e.g. copies steps).
436 # Reuse the existing output if it's easy.
437 if len(final_deps) == 1:
438 return final_deps[0]
439 # Otherwise, fall through to writing out a stamp file.
440
441 output = self.ComputeOutput(spec)
442
443 output_uses_linker = spec['type'] in ('executable', 'loadable_module',
444 'shared_library')
445
446 implicit_deps = set()
447 if 'dependencies' in spec:
448 # Two kinds of dependencies:
449 # - Linkable dependencies (like a .a or a .so): add them to the link line.
450 # - Non-linkable dependencies (like a rule that generates a file
451 # and writes a stamp file): add them to implicit_deps
452 if output_uses_linker:
453 extra_deps = set()
454 for dep in spec['dependencies']:
455 input, linkable = self.target_outputs.get(dep, (None, False))
456 if not input:
457 continue
458 if linkable:
459 extra_deps.add(input)
460 else:
461 # TODO: Chrome-specific HACK. Chrome runs this lastchange rule on
462 # every build, but we don't want to rebuild when it runs.
463 if 'lastchange' not in input:
464 implicit_deps.add(input)
465 final_deps.extend(list(extra_deps))
466 command_map = {
467 'executable': 'link',
468 'static_library': 'alink',
469 'loadable_module': 'solink',
470 'shared_library': 'solink',
471 'none': 'stamp',
472 }
473 command = command_map[spec['type']]
474
475 if output_uses_linker:
476 self.WriteVariableList('ldflags',
477 gyp.common.uniquer(map(self.ExpandSpecial,
478 config.get('ldflags', []))))
479 self.WriteVariableList('libs',
480 gyp.common.uniquer(map(self.ExpandSpecial,
481 spec.get('libraries', []))))
482
483 extra_bindings = []
484 if command == 'solink':
485 extra_bindings.append(('soname', os.path.split(output)[1]))
486
487 self.ninja.build(output, command, final_deps,
488 implicit=list(implicit_deps),
489 variables=extra_bindings)
490
491 return output
492
493 def ComputeOutputFileName(self, spec):
494 """Compute the filename of the final output for the current target."""
495
496 # Compute filename prefix: the product prefix, or a default for
497 # the product type.
498 DEFAULT_PREFIX = {
499 'loadable_module': 'lib',
500 'shared_library': 'lib',
501 }
502 prefix = spec.get('product_prefix', DEFAULT_PREFIX.get(spec['type'], ''))
503
504 # Compute filename extension: the product extension, or a default
505 # for the product type.
506 DEFAULT_EXTENSION = {
507 'static_library': 'a',
508 'loadable_module': 'so',
509 'shared_library': 'so',
510 }
511 extension = spec.get('product_extension',
512 DEFAULT_EXTENSION.get(spec['type'], ''))
513 if extension:
514 extension = '.' + extension
515
516 if 'product_name' in spec:
517 # If we were given an explicit name, use that.
518 target = spec['product_name']
519 else:
520 # Otherwise, derive a name from the target name.
521 target = spec['target_name']
522 if prefix == 'lib':
523 # Snip out an extra 'lib' from libs if appropriate.
524 target = StripPrefix(target, 'lib')
525
526 if spec['type'] in ('static_library', 'loadable_module', 'shared_library',
527 'executable'):
528 return '%s%s%s' % (prefix, target, extension)
529 elif spec['type'] == 'none':
530 return '%s.stamp' % target
531 elif spec['type'] == 'settings':
532 return None
533 else:
534 raise 'Unhandled output type', spec['type']
535
536 def ComputeOutput(self, spec):
537 """Compute the path for the final output of the spec."""
538
539 filename = self.ComputeOutputFileName(spec)
540
541 if 'product_dir' in spec:
542 path = os.path.join(spec['product_dir'], filename)
543 return self.ExpandSpecial(path)
544
545 # Executables and loadable modules go into the output root,
546 # libraries go into shared library dir, and everything else
547 # goes into the normal place.
548 if spec['type'] in ('executable', 'loadable_module'):
549 return filename
550 elif spec['type'] == 'shared_library':
551 libdir = 'lib'
552 if self.toolset != 'target':
553 libdir = 'lib/%s' % self.toolset
554 return os.path.join(libdir, filename)
555 else:
556 return self.GypPathToUniqueOutput(filename, qualified=False)
557
558 def WriteVariableList(self, var, values):
559 if values is None:
560 values = []
561 self.ninja.variable(var, ' '.join(values))
562
563 def WriteNewNinjaRule(self, name, args, description):
564 """Write out a new ninja "rule" statement for a given command.
565
566 Returns the name of the new rule."""
567
568 # TODO: we shouldn't need to qualify names; we do it because
569 # currently the ninja rule namespace is global, but it really
570 # should be scoped to the subninja.
571 rule_name = self.name
572 if self.toolset == 'target':
573 rule_name += '.' + self.toolset
574 rule_name += '.' + name
575 rule_name = rule_name.replace(' ', '_')
576
577 args = args[:]
578
579 # gyp dictates that commands are run from the base directory.
580 # cd into the directory before running, and adjust paths in
581 # the arguments to point to the proper locations.
582 cd = 'cd %s; ' % self.build_to_base
583 args = [self.ExpandSpecial(arg, self.base_to_build) for arg in args]
584
585 command = cd + gyp.common.EncodePOSIXShellList(args)
586 self.ninja.rule(rule_name, command, description)
587 self.ninja.newline()
588
589 return rule_name
590
591
592 def CalculateVariables(default_variables, params):
593 """Calculate additional variables for use in the build (called by gyp)."""
594 cc_target = os.environ.get('CC.target', os.environ.get('CC', 'cc'))
595 default_variables['LINKER_SUPPORTS_ICF'] = \
596 gyp.system_test.TestLinkerSupportsICF(cc_command=cc_target)
597
598
599 def OpenOutput(path):
600 """Open |path| for writing, creating directories if necessary."""
601 try:
602 os.makedirs(os.path.dirname(path))
603 except OSError:
604 pass
605 return open(path, 'w')
606
607
608 def GenerateOutput(target_list, target_dicts, data, params):
609 options = params['options']
610 generator_flags = params.get('generator_flags', {})
611
612 if options.generator_output:
613 raise NotImplementedError, "--generator_output not implemented for ninja"
614
615 config_name = generator_flags.get('config', None)
616 if config_name is None:
617 # Guess which config we want to use: pick the first one from the
618 # first target.
619 config_name = target_dicts[target_list[0]]['default_configuration']
620
621 # builddir: relative path from source root to our output files.
622 # e.g. "out/Debug"
623 builddir = os.path.join(generator_flags.get('output_dir', 'out'), config_name)
624
625 master_ninja = ninja_syntax.Writer(
626 OpenOutput(os.path.join(options.toplevel_dir, builddir, 'build.ninja')),
627 width=120)
628
629 # TODO: compute cc/cxx/ld/etc. by command-line arguments and system tests.
630 master_ninja.variable('cc', os.environ.get('CC', 'gcc'))
631 master_ninja.variable('cxx', os.environ.get('CXX', 'g++'))
632 master_ninja.variable('ld', '$cxx -Wl,--threads -Wl,--thread-count=4')
633 master_ninja.variable('cc_host', '$cc')
634 master_ninja.variable('cxx_host', '$cxx')
635 master_ninja.newline()
636
637 master_ninja.rule(
638 'cc',
639 description='CC $out',
640 command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c '
641 '-c $in -o $out'),
642 depfile='$out.d')
643 master_ninja.rule(
644 'cxx',
645 description='CXX $out',
646 command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
647 '-c $in -o $out'),
648 depfile='$out.d')
649 master_ninja.rule(
650 'alink',
651 description='AR $out',
652 command='rm -f $out && ar rcsT $out $in')
653 master_ninja.rule(
654 'solink',
655 description='SOLINK $out',
656 command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname '
657 '-Wl,--whole-archive $in -Wl,--no-whole-archive $libs'))
658 master_ninja.rule(
659 'link',
660 description='LINK $out',
661 command=('$ld $ldflags -o $out -Wl,-rpath=\$$ORIGIN/lib '
662 '-Wl,--start-group $in -Wl,--end-group $libs'))
663 master_ninja.rule(
664 'stamp',
665 description='STAMP $out',
666 command='touch $out')
667 master_ninja.rule(
668 'copy',
669 description='COPY $in $out',
670 command='ln -f $in $out 2>/dev/null || cp -af $in $out')
671 master_ninja.newline()
672
673 all_targets = set()
674 for build_file in params['build_files']:
675 for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
676 all_targets.add(target)
677 all_outputs = set()
678
679 target_outputs = {}
680 for qualified_target in target_list:
681 # qualified_target is like: third_party/icu/icu.gyp:icui18n#target
682 build_file, name, toolset = \
683 gyp.common.ParseQualifiedTarget(qualified_target)
684
685 # TODO: what is options.depth and how is it different than
686 # options.toplevel_dir?
687 build_file = gyp.common.RelativePath(build_file, options.depth)
688
689 base_path = os.path.dirname(build_file)
690 obj = 'obj'
691 if toolset != 'target':
692 obj += '.' + toolset
693 output_file = os.path.join(obj, base_path, name + '.ninja')
694 spec = target_dicts[qualified_target]
695 config = spec['configurations'][config_name]
696
697 writer = NinjaWriter(target_outputs, base_path, builddir,
698 OpenOutput(os.path.join(options.toplevel_dir,
699 builddir,
700 output_file)))
701 master_ninja.subninja(output_file)
702
703 output = writer.WriteSpec(spec, config)
704 if output:
705 linkable = spec['type'] in ('static_library', 'shared_library')
706 target_outputs[qualified_target] = (output, linkable)
707
708 if qualified_target in all_targets:
709 all_outputs.add(output)
710
711 if all_outputs:
712 master_ninja.build('all', 'phony', list(all_outputs))
+0
-1045
third_party/gyp/pylib/gyp/generator/scons.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import gyp
7 import gyp.common
8 import gyp.SCons as SCons
9 import os.path
10 import pprint
11 import re
12
13
14 # TODO: remove when we delete the last WriteList() call in this module
15 WriteList = SCons.WriteList
16
17
18 generator_default_variables = {
19 'EXECUTABLE_PREFIX': '',
20 'EXECUTABLE_SUFFIX': '',
21 'STATIC_LIB_PREFIX': '${LIBPREFIX}',
22 'SHARED_LIB_PREFIX': '${SHLIBPREFIX}',
23 'STATIC_LIB_SUFFIX': '${LIBSUFFIX}',
24 'SHARED_LIB_SUFFIX': '${SHLIBSUFFIX}',
25 'INTERMEDIATE_DIR': '${INTERMEDIATE_DIR}',
26 'SHARED_INTERMEDIATE_DIR': '${SHARED_INTERMEDIATE_DIR}',
27 'OS': 'linux',
28 'PRODUCT_DIR': '$TOP_BUILDDIR',
29 'SHARED_LIB_DIR': '$LIB_DIR',
30 'LIB_DIR': '$LIB_DIR',
31 'RULE_INPUT_ROOT': '${SOURCE.filebase}',
32 'RULE_INPUT_EXT': '${SOURCE.suffix}',
33 'RULE_INPUT_NAME': '${SOURCE.file}',
34 'RULE_INPUT_PATH': '${SOURCE.abspath}',
35 'CONFIGURATION_NAME': '${CONFIG_NAME}',
36 }
37
38 # Tell GYP how to process the input for us.
39 generator_handles_variants = True
40 generator_wants_absolute_build_file_paths = True
41
42
43 def FixPath(path, prefix):
44 if not os.path.isabs(path) and not path[0] == '$':
45 path = prefix + path
46 return path
47
48
49 header = """\
50 # This file is generated; do not edit.
51 """
52
53
54 _alias_template = """
55 if GetOption('verbose'):
56 _action = Action([%(action)s])
57 else:
58 _action = Action([%(action)s], %(message)s)
59 _outputs = env.Alias(
60 ['_%(target_name)s_action'],
61 %(inputs)s,
62 _action
63 )
64 env.AlwaysBuild(_outputs)
65 """
66
67 _run_as_template = """
68 if GetOption('verbose'):
69 _action = Action([%(action)s])
70 else:
71 _action = Action([%(action)s], %(message)s)
72 """
73
74 _run_as_template_suffix = """
75 _run_as_target = env.Alias('run_%(target_name)s', target_files, _action)
76 env.Requires(_run_as_target, [
77 Alias('%(target_name)s'),
78 ])
79 env.AlwaysBuild(_run_as_target)
80 """
81
82 _command_template = """
83 if GetOption('verbose'):
84 _action = Action([%(action)s])
85 else:
86 _action = Action([%(action)s], %(message)s)
87 _outputs = env.Command(
88 %(outputs)s,
89 %(inputs)s,
90 _action
91 )
92 """
93
94 # This is copied from the default SCons action, updated to handle symlinks.
95 _copy_action_template = """
96 import shutil
97 import SCons.Action
98
99 def _copy_files_or_dirs_or_symlinks(dest, src):
100 SCons.Node.FS.invalidate_node_memos(dest)
101 if SCons.Util.is_List(src) and os.path.isdir(dest):
102 for file in src:
103 shutil.copy2(file, dest)
104 return 0
105 elif os.path.islink(src):
106 linkto = os.readlink(src)
107 os.symlink(linkto, dest)
108 return 0
109 elif os.path.isfile(src):
110 return shutil.copy2(src, dest)
111 else:
112 return shutil.copytree(src, dest, 1)
113
114 def _copy_files_or_dirs_or_symlinks_str(dest, src):
115 return 'Copying %s to %s ...' % (src, dest)
116
117 GYPCopy = SCons.Action.ActionFactory(_copy_files_or_dirs_or_symlinks,
118 _copy_files_or_dirs_or_symlinks_str,
119 convert=str)
120 """
121
122 _rule_template = """
123 %(name)s_additional_inputs = %(inputs)s
124 %(name)s_outputs = %(outputs)s
125 def %(name)s_emitter(target, source, env):
126 return (%(name)s_outputs, source + %(name)s_additional_inputs)
127 if GetOption('verbose'):
128 %(name)s_action = Action([%(action)s])
129 else:
130 %(name)s_action = Action([%(action)s], %(message)s)
131 env['BUILDERS']['%(name)s'] = Builder(action=%(name)s_action,
132 emitter=%(name)s_emitter)
133
134 _outputs = []
135 _processed_input_files = []
136 for infile in input_files:
137 if (type(infile) == type('')
138 and not os.path.isabs(infile)
139 and not infile[0] == '$'):
140 infile = %(src_dir)r + infile
141 if str(infile).endswith('.%(extension)s'):
142 _generated = env.%(name)s(infile)
143 env.Precious(_generated)
144 _outputs.append(_generated)
145 %(process_outputs_as_sources_line)s
146 else:
147 _processed_input_files.append(infile)
148 prerequisites.extend(_outputs)
149 input_files = _processed_input_files
150 """
151
152 _spawn_hack = """
153 import re
154 import SCons.Platform.posix
155 needs_shell = re.compile('["\\'><!^&]')
156 def gyp_spawn(sh, escape, cmd, args, env):
157 def strip_scons_quotes(arg):
158 if arg[0] == '"' and arg[-1] == '"':
159 return arg[1:-1]
160 return arg
161 stripped_args = [strip_scons_quotes(a) for a in args]
162 if needs_shell.search(' '.join(stripped_args)):
163 return SCons.Platform.posix.exec_spawnvpe([sh, '-c', ' '.join(args)], env)
164 else:
165 return SCons.Platform.posix.exec_spawnvpe(stripped_args, env)
166 """
167
168
169 def EscapeShellArgument(s):
170 """Quotes an argument so that it will be interpreted literally by a POSIX
171 shell. Taken from
172 http://stackoverflow.com/questions/35817/whats-the-best-way-to-escape-ossystem-calls-in-python
173 """
174 return "'" + s.replace("'", "'\\''") + "'"
175
176
177 def InvertNaiveSConsQuoting(s):
178 """SCons tries to "help" with quoting by naively putting double-quotes around
179 command-line arguments containing space or tab, which is broken for all
180 but trivial cases, so we undo it. (See quote_spaces() in Subst.py)"""
181 if ' ' in s or '\t' in s:
182 # Then SCons will put double-quotes around this, so add our own quotes
183 # to close its quotes at the beginning and end.
184 s = '"' + s + '"'
185 return s
186
187
188 def EscapeSConsVariableExpansion(s):
189 """SCons has its own variable expansion syntax using $. We must escape it for
190 strings to be interpreted literally. For some reason this requires four
191 dollar signs, not two, even without the shell involved."""
192 return s.replace('$', '$$$$')
193
194
195 def EscapeCppDefine(s):
196 """Escapes a CPP define so that it will reach the compiler unaltered."""
197 s = EscapeShellArgument(s)
198 s = InvertNaiveSConsQuoting(s)
199 s = EscapeSConsVariableExpansion(s)
200 return s
201
202
203 def GenerateConfig(fp, config, indent='', src_dir=''):
204 """
205 Generates SCons dictionary items for a gyp configuration.
206
207 This provides the main translation between the (lower-case) gyp settings
208 keywords and the (upper-case) SCons construction variables.
209 """
210 var_mapping = {
211 'ASFLAGS' : 'asflags',
212 'CCFLAGS' : 'cflags',
213 'CFLAGS' : 'cflags_c',
214 'CXXFLAGS' : 'cflags_cc',
215 'CPPDEFINES' : 'defines',
216 'CPPPATH' : 'include_dirs',
217 # Add the ldflags value to $LINKFLAGS, but not $SHLINKFLAGS.
218 # SCons defines $SHLINKFLAGS to incorporate $LINKFLAGS, so
219 # listing both here would case 'ldflags' to get appended to
220 # both, and then have it show up twice on the command line.
221 'LINKFLAGS' : 'ldflags',
222 }
223 postamble='\n%s],\n' % indent
224 for scons_var in sorted(var_mapping.keys()):
225 gyp_var = var_mapping[scons_var]
226 value = config.get(gyp_var)
227 if value:
228 if gyp_var in ('defines',):
229 value = [EscapeCppDefine(v) for v in value]
230 if gyp_var in ('include_dirs',):
231 if src_dir and not src_dir.endswith('/'):
232 src_dir += '/'
233 result = []
234 for v in value:
235 v = FixPath(v, src_dir)
236 # Force SCons to evaluate the CPPPATH directories at
237 # SConscript-read time, so delayed evaluation of $SRC_DIR
238 # doesn't point it to the --generator-output= directory.
239 result.append('env.Dir(%r)' % v)
240 value = result
241 else:
242 value = map(repr, value)
243 WriteList(fp,
244 value,
245 prefix=indent,
246 preamble='%s%s = [\n ' % (indent, scons_var),
247 postamble=postamble)
248
249
250 def GenerateSConscript(output_filename, spec, build_file, build_file_data):
251 """
252 Generates a SConscript file for a specific target.
253
254 This generates a SConscript file suitable for building any or all of
255 the target's configurations.
256
257 A SConscript file may be called multiple times to generate targets for
258 multiple configurations. Consequently, it needs to be ready to build
259 the target for any requested configuration, and therefore contains
260 information about the settings for all configurations (generated into
261 the SConscript file at gyp configuration time) as well as logic for
262 selecting (at SCons build time) the specific configuration being built.
263
264 The general outline of a generated SConscript file is:
265
266 -- Header
267
268 -- Import 'env'. This contains a $CONFIG_NAME construction
269 variable that specifies what configuration to build
270 (e.g. Debug, Release).
271
272 -- Configurations. This is a dictionary with settings for
273 the different configurations (Debug, Release) under which this
274 target can be built. The values in the dictionary are themselves
275 dictionaries specifying what construction variables should added
276 to the local copy of the imported construction environment
277 (Append), should be removed (FilterOut), and should outright
278 replace the imported values (Replace).
279
280 -- Clone the imported construction environment and update
281 with the proper configuration settings.
282
283 -- Initialize the lists of the targets' input files and prerequisites.
284
285 -- Target-specific actions and rules. These come after the
286 input file and prerequisite initializations because the
287 outputs of the actions and rules may affect the input file
288 list (process_outputs_as_sources) and get added to the list of
289 prerequisites (so that they're guaranteed to be executed before
290 building the target).
291
292 -- Call the Builder for the target itself.
293
294 -- Arrange for any copies to be made into installation directories.
295
296 -- Set up the {name} Alias (phony Node) for the target as the
297 primary handle for building all of the target's pieces.
298
299 -- Use env.Require() to make sure the prerequisites (explicitly
300 specified, but also including the actions and rules) are built
301 before the target itself.
302
303 -- Return the {name} Alias to the calling SConstruct file
304 so it can be added to the list of default targets.
305 """
306 scons_target = SCons.Target(spec)
307
308 gyp_dir = os.path.dirname(output_filename)
309 if not gyp_dir:
310 gyp_dir = '.'
311 gyp_dir = os.path.abspath(gyp_dir)
312
313 output_dir = os.path.dirname(output_filename)
314 src_dir = build_file_data['_DEPTH']
315 src_dir_rel = gyp.common.RelativePath(src_dir, output_dir)
316 subdir = gyp.common.RelativePath(os.path.dirname(build_file), src_dir)
317 src_subdir = '$SRC_DIR/' + subdir
318 src_subdir_ = src_subdir + '/'
319
320 component_name = os.path.splitext(os.path.basename(build_file))[0]
321 target_name = spec['target_name']
322
323 if not os.path.exists(gyp_dir):
324 os.makedirs(gyp_dir)
325 fp = open(output_filename, 'w')
326 fp.write(header)
327
328 fp.write('\nimport os\n')
329 fp.write('\nImport("env")\n')
330
331 #
332 fp.write('\n')
333 fp.write('env = env.Clone(COMPONENT_NAME=%s,\n' % repr(component_name))
334 fp.write(' TARGET_NAME=%s)\n' % repr(target_name))
335
336 #
337 for config in spec['configurations'].itervalues():
338 if config.get('scons_line_length'):
339 fp.write(_spawn_hack)
340 break
341
342 #
343 indent = ' ' * 12
344 fp.write('\n')
345 fp.write('configurations = {\n')
346 for config_name, config in spec['configurations'].iteritems():
347 fp.write(' \'%s\' : {\n' % config_name)
348
349 fp.write(' \'Append\' : dict(\n')
350 GenerateConfig(fp, config, indent, src_subdir)
351 libraries = spec.get('libraries')
352 if libraries:
353 WriteList(fp,
354 map(repr, libraries),
355 prefix=indent,
356 preamble='%sLIBS = [\n ' % indent,
357 postamble='\n%s],\n' % indent)
358 fp.write(' ),\n')
359
360 fp.write(' \'FilterOut\' : dict(\n' )
361 for key, var in config.get('scons_remove', {}).iteritems():
362 fp.write(' %s = %s,\n' % (key, repr(var)))
363 fp.write(' ),\n')
364
365 fp.write(' \'Replace\' : dict(\n' )
366 scons_settings = config.get('scons_variable_settings', {})
367 for key in sorted(scons_settings.keys()):
368 val = pprint.pformat(scons_settings[key])
369 fp.write(' %s = %s,\n' % (key, val))
370 if 'c++' in spec.get('link_languages', []):
371 fp.write(' %s = %s,\n' % ('LINK', repr('$CXX')))
372 if config.get('scons_line_length'):
373 fp.write(' SPAWN = gyp_spawn,\n')
374 fp.write(' ),\n')
375
376 fp.write(' \'ImportExternal\' : [\n' )
377 for var in config.get('scons_import_variables', []):
378 fp.write(' %s,\n' % repr(var))
379 fp.write(' ],\n')
380
381 fp.write(' \'PropagateExternal\' : [\n' )
382 for var in config.get('scons_propagate_variables', []):
383 fp.write(' %s,\n' % repr(var))
384 fp.write(' ],\n')
385
386 fp.write(' },\n')
387 fp.write('}\n')
388
389 fp.write('\n'
390 'config = configurations[env[\'CONFIG_NAME\']]\n'
391 'env.Append(**config[\'Append\'])\n'
392 'env.FilterOut(**config[\'FilterOut\'])\n'
393 'env.Replace(**config[\'Replace\'])\n')
394
395 fp.write('\n'
396 '# Scons forces -fPIC for SHCCFLAGS on some platforms.\n'
397 '# Disable that so we can control it from cflags in gyp.\n'
398 '# Note that Scons itself is inconsistent with its -fPIC\n'
399 '# setting. SHCCFLAGS forces -fPIC, and SHCFLAGS does not.\n'
400 '# This will make SHCCFLAGS consistent with SHCFLAGS.\n'
401 'env[\'SHCCFLAGS\'] = [\'$CCFLAGS\']\n')
402
403 fp.write('\n'
404 'for _var in config[\'ImportExternal\']:\n'
405 ' if _var in ARGUMENTS:\n'
406 ' env[_var] = ARGUMENTS[_var]\n'
407 ' elif _var in os.environ:\n'
408 ' env[_var] = os.environ[_var]\n'
409 'for _var in config[\'PropagateExternal\']:\n'
410 ' if _var in ARGUMENTS:\n'
411 ' env[_var] = ARGUMENTS[_var]\n'
412 ' elif _var in os.environ:\n'
413 ' env[\'ENV\'][_var] = os.environ[_var]\n')
414
415 fp.write('\n'
416 "env['ENV']['LD_LIBRARY_PATH'] = env.subst('$LIB_DIR')\n")
417
418 #
419 #fp.write("\nif env.has_key('CPPPATH'):\n")
420 #fp.write(" env['CPPPATH'] = map(env.Dir, env['CPPPATH'])\n")
421
422 variants = spec.get('variants', {})
423 for setting in sorted(variants.keys()):
424 if_fmt = 'if ARGUMENTS.get(%s) not in (None, \'0\'):\n'
425 fp.write('\n')
426 fp.write(if_fmt % repr(setting.upper()))
427 fp.write(' env.AppendUnique(\n')
428 GenerateConfig(fp, variants[setting], indent, src_subdir)
429 fp.write(' )\n')
430
431 #
432 scons_target.write_input_files(fp)
433
434 fp.write('\n')
435 fp.write('target_files = []\n')
436 prerequisites = spec.get('scons_prerequisites', [])
437 fp.write('prerequisites = %s\n' % pprint.pformat(prerequisites))
438
439 actions = spec.get('actions', [])
440 for action in actions:
441 a = ['cd', src_subdir, '&&'] + action['action']
442 message = action.get('message')
443 if message:
444 message = repr(message)
445 inputs = [FixPath(f, src_subdir_) for f in action.get('inputs', [])]
446 outputs = [FixPath(f, src_subdir_) for f in action.get('outputs', [])]
447 if outputs:
448 template = _command_template
449 else:
450 template = _alias_template
451 fp.write(template % {
452 'inputs' : pprint.pformat(inputs),
453 'outputs' : pprint.pformat(outputs),
454 'action' : pprint.pformat(a),
455 'message' : message,
456 'target_name': target_name,
457 })
458 if int(action.get('process_outputs_as_sources', 0)):
459 fp.write('input_files.extend(_outputs)\n')
460 fp.write('prerequisites.extend(_outputs)\n')
461 fp.write('target_files.extend(_outputs)\n')
462
463 rules = spec.get('rules', [])
464 for rule in rules:
465 name = rule['rule_name']
466 a = ['cd', src_subdir, '&&'] + rule['action']
467 message = rule.get('message')
468 if message:
469 message = repr(message)
470 if int(rule.get('process_outputs_as_sources', 0)):
471 poas_line = '_processed_input_files.extend(_generated)'
472 else:
473 poas_line = '_processed_input_files.append(infile)'
474 inputs = [FixPath(f, src_subdir_) for f in rule.get('inputs', [])]
475 outputs = [FixPath(f, src_subdir_) for f in rule.get('outputs', [])]
476 fp.write(_rule_template % {
477 'inputs' : pprint.pformat(inputs),
478 'outputs' : pprint.pformat(outputs),
479 'action' : pprint.pformat(a),
480 'extension' : rule['extension'],
481 'name' : name,
482 'message' : message,
483 'process_outputs_as_sources_line' : poas_line,
484 'src_dir' : src_subdir_,
485 })
486
487 scons_target.write_target(fp, src_subdir)
488
489 copies = spec.get('copies', [])
490 if copies:
491 fp.write(_copy_action_template)
492 for copy in copies:
493 destdir = None
494 files = None
495 try:
496 destdir = copy['destination']
497 except KeyError, e:
498 gyp.common.ExceptionAppend(
499 e,
500 "Required 'destination' key missing for 'copies' in %s." % build_file)
501 raise
502 try:
503 files = copy['files']
504 except KeyError, e:
505 gyp.common.ExceptionAppend(
506 e, "Required 'files' key missing for 'copies' in %s." % build_file)
507 raise
508 if not files:
509 # TODO: should probably add a (suppressible) warning;
510 # a null file list may be unintentional.
511 continue
512 if not destdir:
513 raise Exception(
514 "Required 'destination' key is empty for 'copies' in %s." % build_file)
515
516 fmt = ('\n'
517 '_outputs = env.Command(%s,\n'
518 ' %s,\n'
519 ' GYPCopy(\'$TARGET\', \'$SOURCE\'))\n')
520 for f in copy['files']:
521 # Remove trailing separators so basename() acts like Unix basename and
522 # always returns the last element, whether a file or dir. Without this,
523 # only the contents, not the directory itself, are copied (and nothing
524 # might be copied if dest already exists, since scons thinks nothing needs
525 # to be done).
526 dest = os.path.join(destdir, os.path.basename(f.rstrip(os.sep)))
527 f = FixPath(f, src_subdir_)
528 dest = FixPath(dest, src_subdir_)
529 fp.write(fmt % (repr(dest), repr(f)))
530 fp.write('target_files.extend(_outputs)\n')
531
532 run_as = spec.get('run_as')
533 if run_as:
534 action = run_as.get('action', [])
535 working_directory = run_as.get('working_directory')
536 if not working_directory:
537 working_directory = gyp_dir
538 else:
539 if not os.path.isabs(working_directory):
540 working_directory = os.path.normpath(os.path.join(gyp_dir,
541 working_directory))
542 if run_as.get('environment'):
543 for (key, val) in run_as.get('environment').iteritems():
544 action = ['%s="%s"' % (key, val)] + action
545 action = ['cd', '"%s"' % working_directory, '&&'] + action
546 fp.write(_run_as_template % {
547 'action' : pprint.pformat(action),
548 'message' : run_as.get('message', ''),
549 })
550
551 fmt = "\ngyp_target = env.Alias('%s', target_files)\n"
552 fp.write(fmt % target_name)
553
554 dependencies = spec.get('scons_dependencies', [])
555 if dependencies:
556 WriteList(fp, dependencies, preamble='dependencies = [\n ',
557 postamble='\n]\n')
558 fp.write('env.Requires(target_files, dependencies)\n')
559 fp.write('env.Requires(gyp_target, dependencies)\n')
560 fp.write('for prerequisite in prerequisites:\n')
561 fp.write(' env.Requires(prerequisite, dependencies)\n')
562 fp.write('env.Requires(gyp_target, prerequisites)\n')
563
564 if run_as:
565 fp.write(_run_as_template_suffix % {
566 'target_name': target_name,
567 })
568
569 fp.write('Return("gyp_target")\n')
570
571 fp.close()
572
573
574 #############################################################################
575 # TEMPLATE BEGIN
576
577 _wrapper_template = """\
578
579 __doc__ = '''
580 Wrapper configuration for building this entire "solution,"
581 including all the specific targets in various *.scons files.
582 '''
583
584 import os
585 import sys
586
587 import SCons.Environment
588 import SCons.Util
589
590 def GetProcessorCount():
591 '''
592 Detects the number of CPUs on the system. Adapted form:
593 http://codeliberates.blogspot.com/2008/05/detecting-cpuscores-in-python.html
594 '''
595 # Linux, Unix and Mac OS X:
596 if hasattr(os, 'sysconf'):
597 if os.sysconf_names.has_key('SC_NPROCESSORS_ONLN'):
598 # Linux and Unix or Mac OS X with python >= 2.5:
599 return os.sysconf('SC_NPROCESSORS_ONLN')
600 else: # Mac OS X with Python < 2.5:
601 return int(os.popen2("sysctl -n hw.ncpu")[1].read())
602 # Windows:
603 if os.environ.has_key('NUMBER_OF_PROCESSORS'):
604 return max(int(os.environ.get('NUMBER_OF_PROCESSORS', '1')), 1)
605 return 1 # Default
606
607 # Support PROGRESS= to show progress in different ways.
608 p = ARGUMENTS.get('PROGRESS')
609 if p == 'spinner':
610 Progress(['/\\r', '|\\r', '\\\\\\r', '-\\r'],
611 interval=5,
612 file=open('/dev/tty', 'w'))
613 elif p == 'name':
614 Progress('$TARGET\\r', overwrite=True, file=open('/dev/tty', 'w'))
615
616 # Set the default -j value based on the number of processors.
617 SetOption('num_jobs', GetProcessorCount() + 1)
618
619 # Have SCons use its cached dependency information.
620 SetOption('implicit_cache', 1)
621
622 # Only re-calculate MD5 checksums if a timestamp has changed.
623 Decider('MD5-timestamp')
624
625 # Since we set the -j value by default, suppress SCons warnings about being
626 # unable to support parallel build on versions of Python with no threading.
627 default_warnings = ['no-no-parallel-support']
628 SetOption('warn', default_warnings + GetOption('warn'))
629
630 AddOption('--mode', nargs=1, dest='conf_list', default=[],
631 action='append', help='Configuration to build.')
632
633 AddOption('--verbose', dest='verbose', default=False,
634 action='store_true', help='Verbose command-line output.')
635
636
637 #
638 sconscript_file_map = %(sconscript_files)s
639
640 class LoadTarget:
641 '''
642 Class for deciding if a given target sconscript is to be included
643 based on a list of included target names, optionally prefixed with '-'
644 to exclude a target name.
645 '''
646 def __init__(self, load):
647 '''
648 Initialize a class with a list of names for possible loading.
649
650 Arguments:
651 load: list of elements in the LOAD= specification
652 '''
653 self.included = set([c for c in load if not c.startswith('-')])
654 self.excluded = set([c[1:] for c in load if c.startswith('-')])
655
656 if not self.included:
657 self.included = set(['all'])
658
659 def __call__(self, target):
660 '''
661 Returns True if the specified target's sconscript file should be
662 loaded, based on the initialized included and excluded lists.
663 '''
664 return (target in self.included or
665 ('all' in self.included and not target in self.excluded))
666
667 if 'LOAD' in ARGUMENTS:
668 load = ARGUMENTS['LOAD'].split(',')
669 else:
670 load = []
671 load_target = LoadTarget(load)
672
673 sconscript_files = []
674 for target, sconscript in sconscript_file_map.iteritems():
675 if load_target(target):
676 sconscript_files.append(sconscript)
677
678
679 target_alias_list= []
680
681 conf_list = GetOption('conf_list')
682 if conf_list:
683 # In case the same --mode= value was specified multiple times.
684 conf_list = list(set(conf_list))
685 else:
686 conf_list = [%(default_configuration)r]
687
688 sconsbuild_dir = Dir(%(sconsbuild_dir)s)
689
690
691 def FilterOut(self, **kw):
692 kw = SCons.Environment.copy_non_reserved_keywords(kw)
693 for key, val in kw.items():
694 envval = self.get(key, None)
695 if envval is None:
696 # No existing variable in the environment, so nothing to delete.
697 continue
698
699 for vremove in val:
700 # Use while not if, so we can handle duplicates.
701 while vremove in envval:
702 envval.remove(vremove)
703
704 self[key] = envval
705
706 # TODO(sgk): SCons.Environment.Append() has much more logic to deal
707 # with various types of values. We should handle all those cases in here
708 # too. (If variable is a dict, etc.)
709
710
711 non_compilable_suffixes = {
712 'LINUX' : set([
713 '.bdic',
714 '.css',
715 '.dat',
716 '.fragment',
717 '.gperf',
718 '.h',
719 '.hh',
720 '.hpp',
721 '.html',
722 '.hxx',
723 '.idl',
724 '.in',
725 '.in0',
726 '.in1',
727 '.js',
728 '.mk',
729 '.rc',
730 '.sigs',
731 '',
732 ]),
733 'WINDOWS' : set([
734 '.h',
735 '.hh',
736 '.hpp',
737 '.dat',
738 '.idl',
739 '.in',
740 '.in0',
741 '.in1',
742 ]),
743 }
744
745 def compilable(env, file):
746 base, ext = os.path.splitext(str(file))
747 if ext in non_compilable_suffixes[env['TARGET_PLATFORM']]:
748 return False
749 return True
750
751 def compilable_files(env, sources):
752 return [x for x in sources if compilable(env, x)]
753
754 def GypProgram(env, target, source, *args, **kw):
755 source = compilable_files(env, source)
756 result = env.Program(target, source, *args, **kw)
757 if env.get('INCREMENTAL'):
758 env.Precious(result)
759 return result
760
761 def GypTestProgram(env, target, source, *args, **kw):
762 source = compilable_files(env, source)
763 result = env.Program(target, source, *args, **kw)
764 if env.get('INCREMENTAL'):
765 env.Precious(*result)
766 return result
767
768 def GypLibrary(env, target, source, *args, **kw):
769 source = compilable_files(env, source)
770 result = env.Library(target, source, *args, **kw)
771 return result
772
773 def GypLoadableModule(env, target, source, *args, **kw):
774 source = compilable_files(env, source)
775 result = env.LoadableModule(target, source, *args, **kw)
776 return result
777
778 def GypStaticLibrary(env, target, source, *args, **kw):
779 source = compilable_files(env, source)
780 result = env.StaticLibrary(target, source, *args, **kw)
781 return result
782
783 def GypSharedLibrary(env, target, source, *args, **kw):
784 source = compilable_files(env, source)
785 result = env.SharedLibrary(target, source, *args, **kw)
786 if env.get('INCREMENTAL'):
787 env.Precious(result)
788 return result
789
790 def add_gyp_methods(env):
791 env.AddMethod(GypProgram)
792 env.AddMethod(GypTestProgram)
793 env.AddMethod(GypLibrary)
794 env.AddMethod(GypLoadableModule)
795 env.AddMethod(GypStaticLibrary)
796 env.AddMethod(GypSharedLibrary)
797
798 env.AddMethod(FilterOut)
799
800 env.AddMethod(compilable)
801
802
803 base_env = Environment(
804 tools = %(scons_tools)s,
805 INTERMEDIATE_DIR='$OBJ_DIR/${COMPONENT_NAME}/_${TARGET_NAME}_intermediate',
806 LIB_DIR='$TOP_BUILDDIR/lib',
807 OBJ_DIR='$TOP_BUILDDIR/obj',
808 SCONSBUILD_DIR=sconsbuild_dir.abspath,
809 SHARED_INTERMEDIATE_DIR='$OBJ_DIR/_global_intermediate',
810 SRC_DIR=Dir(%(src_dir)r),
811 TARGET_PLATFORM='LINUX',
812 TOP_BUILDDIR='$SCONSBUILD_DIR/$CONFIG_NAME',
813 LIBPATH=['$LIB_DIR'],
814 )
815
816 if not GetOption('verbose'):
817 base_env.SetDefault(
818 ARCOMSTR='Creating library $TARGET',
819 ASCOMSTR='Assembling $TARGET',
820 CCCOMSTR='Compiling $TARGET',
821 CONCATSOURCECOMSTR='ConcatSource $TARGET',
822 CXXCOMSTR='Compiling $TARGET',
823 LDMODULECOMSTR='Building loadable module $TARGET',
824 LINKCOMSTR='Linking $TARGET',
825 MANIFESTCOMSTR='Updating manifest for $TARGET',
826 MIDLCOMSTR='Compiling IDL $TARGET',
827 PCHCOMSTR='Precompiling $TARGET',
828 RANLIBCOMSTR='Indexing $TARGET',
829 RCCOMSTR='Compiling resource $TARGET',
830 SHCCCOMSTR='Compiling $TARGET',
831 SHCXXCOMSTR='Compiling $TARGET',
832 SHLINKCOMSTR='Linking $TARGET',
833 SHMANIFESTCOMSTR='Updating manifest for $TARGET',
834 )
835
836 add_gyp_methods(base_env)
837
838 for conf in conf_list:
839 env = base_env.Clone(CONFIG_NAME=conf)
840 SConsignFile(env.File('$TOP_BUILDDIR/.sconsign').abspath)
841 for sconscript in sconscript_files:
842 target_alias = env.SConscript(sconscript, exports=['env'])
843 if target_alias:
844 target_alias_list.extend(target_alias)
845
846 Default(Alias('all', target_alias_list))
847
848 help_fmt = '''
849 Usage: hammer [SCONS_OPTIONS] [VARIABLES] [TARGET] ...
850
851 Local command-line build options:
852 --mode=CONFIG Configuration to build:
853 --mode=Debug [default]
854 --mode=Release
855 --verbose Print actual executed command lines.
856
857 Supported command-line build variables:
858 LOAD=[module,...] Comma-separated list of components to load in the
859 dependency graph ('-' prefix excludes)
860 PROGRESS=type Display a progress indicator:
861 name: print each evaluated target name
862 spinner: print a spinner every 5 targets
863
864 The following TARGET names can also be used as LOAD= module names:
865
866 %%s
867 '''
868
869 if GetOption('help'):
870 def columnar_text(items, width=78, indent=2, sep=2):
871 result = []
872 colwidth = max(map(len, items)) + sep
873 cols = (width - indent) / colwidth
874 if cols < 1:
875 cols = 1
876 rows = (len(items) + cols - 1) / cols
877 indent = '%%*s' %% (indent, '')
878 sep = indent
879 for row in xrange(0, rows):
880 result.append(sep)
881 for i in xrange(row, len(items), rows):
882 result.append('%%-*s' %% (colwidth, items[i]))
883 sep = '\\n' + indent
884 result.append('\\n')
885 return ''.join(result)
886
887 load_list = set(sconscript_file_map.keys())
888 target_aliases = set(map(str, target_alias_list))
889
890 common = load_list and target_aliases
891 load_only = load_list - common
892 target_only = target_aliases - common
893 help_text = [help_fmt %% columnar_text(sorted(list(common)))]
894 if target_only:
895 fmt = "The following are additional TARGET names:\\n\\n%%s\\n"
896 help_text.append(fmt %% columnar_text(sorted(list(target_only))))
897 if load_only:
898 fmt = "The following are additional LOAD= module names:\\n\\n%%s\\n"
899 help_text.append(fmt %% columnar_text(sorted(list(load_only))))
900 Help(''.join(help_text))
901 """
902
903 # TEMPLATE END
904 #############################################################################
905
906
907 def GenerateSConscriptWrapper(build_file, build_file_data, name,
908 output_filename, sconscript_files,
909 default_configuration):
910 """
911 Generates the "wrapper" SConscript file (analogous to the Visual Studio
912 solution) that calls all the individual target SConscript files.
913 """
914 output_dir = os.path.dirname(output_filename)
915 src_dir = build_file_data['_DEPTH']
916 src_dir_rel = gyp.common.RelativePath(src_dir, output_dir)
917 if not src_dir_rel:
918 src_dir_rel = '.'
919 scons_settings = build_file_data.get('scons_settings', {})
920 sconsbuild_dir = scons_settings.get('sconsbuild_dir', '#')
921 scons_tools = scons_settings.get('tools', ['default'])
922
923 sconscript_file_lines = ['dict(']
924 for target in sorted(sconscript_files.keys()):
925 sconscript = sconscript_files[target]
926 sconscript_file_lines.append(' %s = %r,' % (target, sconscript))
927 sconscript_file_lines.append(')')
928
929 fp = open(output_filename, 'w')
930 fp.write(header)
931 fp.write(_wrapper_template % {
932 'default_configuration' : default_configuration,
933 'name' : name,
934 'scons_tools' : repr(scons_tools),
935 'sconsbuild_dir' : repr(sconsbuild_dir),
936 'sconscript_files' : '\n'.join(sconscript_file_lines),
937 'src_dir' : src_dir_rel,
938 })
939 fp.close()
940
941 # Generate the SConstruct file that invokes the wrapper SConscript.
942 dir, fname = os.path.split(output_filename)
943 SConstruct = os.path.join(dir, 'SConstruct')
944 fp = open(SConstruct, 'w')
945 fp.write(header)
946 fp.write('SConscript(%s)\n' % repr(fname))
947 fp.close()
948
949
950 def TargetFilename(target, build_file=None, output_suffix=''):
951 """Returns the .scons file name for the specified target.
952 """
953 if build_file is None:
954 build_file, target = gyp.common.ParseQualifiedTarget(target)[:2]
955 output_file = os.path.join(os.path.dirname(build_file),
956 target + output_suffix + '.scons')
957 return output_file
958
959
960 def GenerateOutput(target_list, target_dicts, data, params):
961 """
962 Generates all the output files for the specified targets.
963 """
964 options = params['options']
965
966 if options.generator_output:
967 def output_path(filename):
968 return filename.replace(params['cwd'], options.generator_output)
969 else:
970 def output_path(filename):
971 return filename
972
973 default_configuration = None
974
975 for qualified_target in target_list:
976 spec = target_dicts[qualified_target]
977 if spec['toolset'] != 'target':
978 raise Exception(
979 'Multiple toolsets not supported in scons build (target %s)' %
980 qualified_target)
981 scons_target = SCons.Target(spec)
982 if scons_target.is_ignored:
983 continue
984
985 # TODO: assumes the default_configuration of the first target
986 # non-Default target is the correct default for all targets.
987 # Need a better model for handle variation between targets.
988 if (not default_configuration and
989 spec['default_configuration'] != 'Default'):
990 default_configuration = spec['default_configuration']
991
992 build_file, target = gyp.common.ParseQualifiedTarget(qualified_target)[:2]
993 output_file = TargetFilename(target, build_file, options.suffix)
994 if options.generator_output:
995 output_file = output_path(output_file)
996
997 if not spec.has_key('libraries'):
998 spec['libraries'] = []
999
1000 # Add dependent static library targets to the 'libraries' value.
1001 deps = spec.get('dependencies', [])
1002 spec['scons_dependencies'] = []
1003 for d in deps:
1004 td = target_dicts[d]
1005 target_name = td['target_name']
1006 spec['scons_dependencies'].append("Alias('%s')" % target_name)
1007 if td['type'] in ('static_library', 'shared_library'):
1008 libname = td.get('product_name', target_name)
1009 spec['libraries'].append('lib' + libname)
1010 if td['type'] == 'loadable_module':
1011 prereqs = spec.get('scons_prerequisites', [])
1012 # TODO: parameterize with <(SHARED_LIBRARY_*) variables?
1013 td_target = SCons.Target(td)
1014 td_target.target_prefix = '${SHLIBPREFIX}'
1015 td_target.target_suffix = '${SHLIBSUFFIX}'
1016
1017 GenerateSConscript(output_file, spec, build_file, data[build_file])
1018
1019 if not default_configuration:
1020 default_configuration = 'Default'
1021
1022 for build_file in sorted(data.keys()):
1023 path, ext = os.path.splitext(build_file)
1024 if ext != '.gyp':
1025 continue
1026 output_dir, basename = os.path.split(path)
1027 output_filename = path + '_main' + options.suffix + '.scons'
1028
1029 all_targets = gyp.common.AllTargets(target_list, target_dicts, build_file)
1030 sconscript_files = {}
1031 for t in all_targets:
1032 scons_target = SCons.Target(target_dicts[t])
1033 if scons_target.is_ignored:
1034 continue
1035 bf, target = gyp.common.ParseQualifiedTarget(t)[:2]
1036 target_filename = TargetFilename(target, bf, options.suffix)
1037 tpath = gyp.common.RelativePath(target_filename, output_dir)
1038 sconscript_files[target] = tpath
1039
1040 output_filename = output_path(output_filename)
1041 if sconscript_files:
1042 GenerateSConscriptWrapper(build_file, data[build_file], basename,
1043 output_filename, sconscript_files,
1044 default_configuration)
+0
-1204
third_party/gyp/pylib/gyp/generator/xcode.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import filecmp
7 import gyp.common
8 import gyp.xcodeproj_file
9 import errno
10 import os
11 import posixpath
12 import re
13 import shutil
14 import subprocess
15 import tempfile
16
17
18 # Project files generated by this module will use _intermediate_var as a
19 # custom Xcode setting whose value is a DerivedSources-like directory that's
20 # project-specific and configuration-specific. The normal choice,
21 # DERIVED_FILE_DIR, is target-specific, which is thought to be too restrictive
22 # as it is likely that multiple targets within a single project file will want
23 # to access the same set of generated files. The other option,
24 # PROJECT_DERIVED_FILE_DIR, is unsuitable because while it is project-specific,
25 # it is not configuration-specific. INTERMEDIATE_DIR is defined as
26 # $(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION).
27 _intermediate_var = 'INTERMEDIATE_DIR'
28
29 # SHARED_INTERMEDIATE_DIR is the same, except that it is shared among all
30 # targets that share the same BUILT_PRODUCTS_DIR.
31 _shared_intermediate_var = 'SHARED_INTERMEDIATE_DIR'
32
33 _library_search_paths_var = 'LIBRARY_SEARCH_PATHS'
34
35 generator_default_variables = {
36 'EXECUTABLE_PREFIX': '',
37 'EXECUTABLE_SUFFIX': '',
38 'STATIC_LIB_PREFIX': 'lib',
39 'SHARED_LIB_PREFIX': 'lib',
40 'STATIC_LIB_SUFFIX': '.a',
41 'SHARED_LIB_SUFFIX': '.dylib',
42 # INTERMEDIATE_DIR is a place for targets to build up intermediate products.
43 # It is specific to each build environment. It is only guaranteed to exist
44 # and be constant within the context of a project, corresponding to a single
45 # input file. Some build environments may allow their intermediate directory
46 # to be shared on a wider scale, but this is not guaranteed.
47 'INTERMEDIATE_DIR': '$(%s)' % _intermediate_var,
48 'OS': 'mac',
49 'PRODUCT_DIR': '$(BUILT_PRODUCTS_DIR)',
50 'LIB_DIR': '$(BUILT_PRODUCTS_DIR)',
51 'RULE_INPUT_ROOT': '$(INPUT_FILE_BASE)',
52 'RULE_INPUT_EXT': '$(INPUT_FILE_SUFFIX)',
53 'RULE_INPUT_NAME': '$(INPUT_FILE_NAME)',
54 'RULE_INPUT_PATH': '$(INPUT_FILE_PATH)',
55 'SHARED_INTERMEDIATE_DIR': '$(%s)' % _shared_intermediate_var,
56 'CONFIGURATION_NAME': '$(CONFIGURATION)',
57 }
58
59 # The Xcode-specific sections that hold paths.
60 generator_additional_path_sections = [
61 'mac_bundle_resources',
62 'mac_framework_headers',
63 'mac_framework_private_headers',
64 # 'mac_framework_dirs', input already handles _dirs endings.
65 ]
66
67 # The Xcode-specific keys that exist on targets and aren't moved down to
68 # configurations.
69 generator_additional_non_configuration_keys = [
70 'mac_bundle',
71 'mac_bundle_resources',
72 'mac_framework_headers',
73 'mac_framework_private_headers',
74 'xcode_create_dependents_test_runner',
75 ]
76
77 # We want to let any rules apply to files that are resources also.
78 generator_extra_sources_for_rules = [
79 'mac_bundle_resources',
80 'mac_framework_headers',
81 'mac_framework_private_headers',
82 ]
83
84 # Xcode's standard set of library directories, which don't need to be duplicated
85 # in LIBRARY_SEARCH_PATHS. This list is not exhaustive, but that's okay.
86 xcode_standard_library_dirs = frozenset([
87 '$(SDKROOT)/usr/lib',
88 '$(SDKROOT)/usr/local/lib',
89 ])
90
91 def CreateXCConfigurationList(configuration_names):
92 xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []})
93 if len(configuration_names) == 0:
94 configuration_names = ['Default']
95 for configuration_name in configuration_names:
96 xcbc = gyp.xcodeproj_file.XCBuildConfiguration({
97 'name': configuration_name})
98 xccl.AppendProperty('buildConfigurations', xcbc)
99 xccl.SetProperty('defaultConfigurationName', configuration_names[0])
100 return xccl
101
102
103 class XcodeProject(object):
104 def __init__(self, gyp_path, path, build_file_dict):
105 self.gyp_path = gyp_path
106 self.path = path
107 self.project = gyp.xcodeproj_file.PBXProject(path=path)
108 projectDirPath = gyp.common.RelativePath(
109 os.path.dirname(os.path.abspath(self.gyp_path)),
110 os.path.dirname(path) or '.')
111 self.project.SetProperty('projectDirPath', projectDirPath)
112 self.project_file = \
113 gyp.xcodeproj_file.XCProjectFile({'rootObject': self.project})
114 self.build_file_dict = build_file_dict
115
116 # TODO(mark): add destructor that cleans up self.path if created_dir is
117 # True and things didn't complete successfully. Or do something even
118 # better with "try"?
119 self.created_dir = False
120 try:
121 os.makedirs(self.path)
122 self.created_dir = True
123 except OSError, e:
124 if e.errno != errno.EEXIST:
125 raise
126
127 def Finalize1(self, xcode_targets, serialize_all_tests):
128 # Collect a list of all of the build configuration names used by the
129 # various targets in the file. It is very heavily advised to keep each
130 # target in an entire project (even across multiple project files) using
131 # the same set of configuration names.
132 configurations = []
133 for xct in self.project.GetProperty('targets'):
134 xccl = xct.GetProperty('buildConfigurationList')
135 xcbcs = xccl.GetProperty('buildConfigurations')
136 for xcbc in xcbcs:
137 name = xcbc.GetProperty('name')
138 if name not in configurations:
139 configurations.append(name)
140
141 # Replace the XCConfigurationList attached to the PBXProject object with
142 # a new one specifying all of the configuration names used by the various
143 # targets.
144 try:
145 xccl = CreateXCConfigurationList(configurations)
146 self.project.SetProperty('buildConfigurationList', xccl)
147 except:
148 import sys
149 sys.stderr.write("Problem with gyp file %s\n" % self.gyp_path)
150 raise
151
152 # The need for this setting is explained above where _intermediate_var is
153 # defined. The comments below about wanting to avoid project-wide build
154 # settings apply here too, but this needs to be set on a project-wide basis
155 # so that files relative to the _intermediate_var setting can be displayed
156 # properly in the Xcode UI.
157 #
158 # Note that for configuration-relative files such as anything relative to
159 # _intermediate_var, for the purposes of UI tree view display, Xcode will
160 # only resolve the configuration name once, when the project file is
161 # opened. If the active build configuration is changed, the project file
162 # must be closed and reopened if it is desired for the tree view to update.
163 # This is filed as Apple radar 6588391.
164 xccl.SetBuildSetting(_intermediate_var,
165 '$(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION)')
166 xccl.SetBuildSetting(_shared_intermediate_var,
167 '$(SYMROOT)/DerivedSources/$(CONFIGURATION)')
168
169 # Set user-specified project-wide build settings and config files. This
170 # is intended to be used very sparingly. Really, almost everything should
171 # go into target-specific build settings sections. The project-wide
172 # settings are only intended to be used in cases where Xcode attempts to
173 # resolve variable references in a project context as opposed to a target
174 # context, such as when resolving sourceTree references while building up
175 # the tree tree view for UI display.
176 # Any values set globally are applied to all configurations, then any
177 # per-configuration values are applied.
178 for xck, xcv in self.build_file_dict.get('xcode_settings', {}).iteritems():
179 xccl.SetBuildSetting(xck, xcv)
180 if 'xcode_config_file' in self.build_file_dict:
181 config_ref = self.project.AddOrGetFileInRootGroup(
182 self.build_file_dict['xcode_config_file'])
183 xccl.SetBaseConfiguration(config_ref)
184 build_file_configurations = self.build_file_dict.get('configurations', {})
185 if build_file_configurations:
186 for config_name in configurations:
187 build_file_configuration_named = \
188 build_file_configurations.get(config_name, {})
189 if build_file_configuration_named:
190 xcc = xccl.ConfigurationNamed(config_name)
191 for xck, xcv in build_file_configuration_named.get('xcode_settings',
192 {}).iteritems():
193 xcc.SetBuildSetting(xck, xcv)
194 if 'xcode_config_file' in build_file_configuration_named:
195 config_ref = self.project.AddOrGetFileInRootGroup(
196 build_file_configurations[config_name]['xcode_config_file'])
197 xcc.SetBaseConfiguration(config_ref)
198
199 # Sort the targets based on how they appeared in the input.
200 # TODO(mark): Like a lot of other things here, this assumes internal
201 # knowledge of PBXProject - in this case, of its "targets" property.
202
203 # ordinary_targets are ordinary targets that are already in the project
204 # file. run_test_targets are the targets that run unittests and should be
205 # used for the Run All Tests target. support_targets are the action/rule
206 # targets used by GYP file targets, just kept for the assert check.
207 ordinary_targets = []
208 run_test_targets = []
209 support_targets = []
210
211 # targets is full list of targets in the project.
212 targets = []
213
214 # does the it define it's own "all"?
215 has_custom_all = False
216
217 # targets_for_all is the list of ordinary_targets that should be listed
218 # in this project's "All" target. It includes each non_runtest_target
219 # that does not have suppress_wildcard set.
220 targets_for_all = []
221
222 for target in self.build_file_dict['targets']:
223 target_name = target['target_name']
224 toolset = target['toolset']
225 qualified_target = gyp.common.QualifiedTarget(self.gyp_path, target_name,
226 toolset)
227 xcode_target = xcode_targets[qualified_target]
228 # Make sure that the target being added to the sorted list is already in
229 # the unsorted list.
230 assert xcode_target in self.project._properties['targets']
231 targets.append(xcode_target)
232 ordinary_targets.append(xcode_target)
233 if xcode_target.support_target:
234 support_targets.append(xcode_target.support_target)
235 targets.append(xcode_target.support_target)
236
237 if not int(target.get('suppress_wildcard', False)):
238 targets_for_all.append(xcode_target)
239
240 if target_name.lower() == 'all':
241 has_custom_all = True;
242
243 # If this target has a 'run_as' attribute, add its target to the
244 # targets, and add it to the test targets.
245 if target.get('run_as'):
246 # Make a target to run something. It should have one
247 # dependency, the parent xcode target.
248 xccl = CreateXCConfigurationList(configurations)
249 run_target = gyp.xcodeproj_file.PBXAggregateTarget({
250 'name': 'Run ' + target_name,
251 'productName': xcode_target.GetProperty('productName'),
252 'buildConfigurationList': xccl,
253 },
254 parent=self.project)
255 run_target.AddDependency(xcode_target)
256
257 command = target['run_as']
258 script = ''
259 if command.get('working_directory'):
260 script = script + 'cd "%s"\n' % \
261 gyp.xcodeproj_file.ConvertVariablesToShellSyntax(
262 command.get('working_directory'))
263
264 if command.get('environment'):
265 script = script + "\n".join(
266 ['export %s="%s"' %
267 (key, gyp.xcodeproj_file.ConvertVariablesToShellSyntax(val))
268 for (key, val) in command.get('environment').iteritems()]) + "\n"
269
270 # Some test end up using sockets, files on disk, etc. and can get
271 # confused if more then one test runs at a time. The generator
272 # flag 'xcode_serialize_all_test_runs' controls the forcing of all
273 # tests serially. It defaults to True. To get serial runs this
274 # little bit of python does the same as the linux flock utility to
275 # make sure only one runs at a time.
276 command_prefix = ''
277 if serialize_all_tests:
278 command_prefix = \
279 """python -c "import fcntl, subprocess, sys
280 file = open('$TMPDIR/GYP_serialize_test_runs', 'a')
281 fcntl.flock(file.fileno(), fcntl.LOCK_EX)
282 sys.exit(subprocess.call(sys.argv[1:]))" """
283
284 # If we were unable to exec for some reason, we want to exit
285 # with an error, and fixup variable references to be shell
286 # syntax instead of xcode syntax.
287 script = script + 'exec ' + command_prefix + '%s\nexit 1\n' % \
288 gyp.xcodeproj_file.ConvertVariablesToShellSyntax(
289 gyp.common.EncodePOSIXShellList(command.get('action')))
290
291 ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
292 'shellScript': script,
293 'showEnvVarsInLog': 0,
294 })
295 run_target.AppendProperty('buildPhases', ssbp)
296
297 # Add the run target to the project file.
298 targets.append(run_target)
299 run_test_targets.append(run_target)
300 xcode_target.test_runner = run_target
301
302
303 # Make sure that the list of targets being replaced is the same length as
304 # the one replacing it, but allow for the added test runner targets.
305 assert len(self.project._properties['targets']) == \
306 len(ordinary_targets) + len(support_targets)
307
308 self.project._properties['targets'] = targets
309
310 # Get rid of unnecessary levels of depth in groups like the Source group.
311 self.project.RootGroupsTakeOverOnlyChildren(True)
312
313 # Sort the groups nicely. Do this after sorting the targets, because the
314 # Products group is sorted based on the order of the targets.
315 self.project.SortGroups()
316
317 # Create an "All" target if there's more than one target in this project
318 # file and the project didn't define its own "All" target. Put a generated
319 # "All" target first so that people opening up the project for the first
320 # time will build everything by default.
321 if len(targets_for_all) > 1 and not has_custom_all:
322 xccl = CreateXCConfigurationList(configurations)
323 all_target = gyp.xcodeproj_file.PBXAggregateTarget(
324 {
325 'buildConfigurationList': xccl,
326 'name': 'All',
327 },
328 parent=self.project)
329
330 for target in targets_for_all:
331 all_target.AddDependency(target)
332
333 # TODO(mark): This is evil because it relies on internal knowledge of
334 # PBXProject._properties. It's important to get the "All" target first,
335 # though.
336 self.project._properties['targets'].insert(0, all_target)
337
338 # The same, but for run_test_targets.
339 if len(run_test_targets) > 1:
340 xccl = CreateXCConfigurationList(configurations)
341 run_all_tests_target = gyp.xcodeproj_file.PBXAggregateTarget(
342 {
343 'buildConfigurationList': xccl,
344 'name': 'Run All Tests',
345 },
346 parent=self.project)
347 for run_test_target in run_test_targets:
348 run_all_tests_target.AddDependency(run_test_target)
349
350 # Insert after the "All" target, which must exist if there is more than
351 # one run_test_target.
352 self.project._properties['targets'].insert(1, run_all_tests_target)
353
354 def Finalize2(self, xcode_targets, xcode_target_to_target_dict):
355 # Finalize2 needs to happen in a separate step because the process of
356 # updating references to other projects depends on the ordering of targets
357 # within remote project files. Finalize1 is responsible for sorting duty,
358 # and once all project files are sorted, Finalize2 can come in and update
359 # these references.
360
361 # To support making a "test runner" target that will run all the tests
362 # that are direct dependents of any given target, we look for
363 # xcode_create_dependents_test_runner being set on an Aggregate target,
364 # and generate a second target that will run the tests runners found under
365 # the marked target.
366 for bf_tgt in self.build_file_dict['targets']:
367 if int(bf_tgt.get('xcode_create_dependents_test_runner', 0)):
368 tgt_name = bf_tgt['target_name']
369 toolset = bf_tgt['toolset']
370 qualified_target = gyp.common.QualifiedTarget(self.gyp_path,
371 tgt_name, toolset)
372 xcode_target = xcode_targets[qualified_target]
373 if isinstance(xcode_target, gyp.xcodeproj_file.PBXAggregateTarget):
374 # Collect all the run test targets.
375 all_run_tests = []
376 pbxtds = xcode_target.GetProperty('dependencies')
377 for pbxtd in pbxtds:
378 pbxcip = pbxtd.GetProperty('targetProxy')
379 dependency_xct = pbxcip.GetProperty('remoteGlobalIDString')
380 if hasattr(dependency_xct, 'test_runner'):
381 all_run_tests.append(dependency_xct.test_runner)
382
383 # Directly depend on all the runners as they depend on the target
384 # that builds them.
385 if len(all_run_tests) > 0:
386 run_all_target = gyp.xcodeproj_file.PBXAggregateTarget({
387 'name': 'Run %s Tests' % tgt_name,
388 'productName': tgt_name,
389 },
390 parent=self.project)
391 for run_test_target in all_run_tests:
392 run_all_target.AddDependency(run_test_target)
393
394 # Insert the test runner after the related target.
395 idx = self.project._properties['targets'].index(xcode_target)
396 self.project._properties['targets'].insert(idx + 1, run_all_target)
397
398 # Update all references to other projects, to make sure that the lists of
399 # remote products are complete. Otherwise, Xcode will fill them in when
400 # it opens the project file, which will result in unnecessary diffs.
401 # TODO(mark): This is evil because it relies on internal knowledge of
402 # PBXProject._other_pbxprojects.
403 for other_pbxproject in self.project._other_pbxprojects.keys():
404 self.project.AddOrGetProjectReference(other_pbxproject)
405
406 self.project.SortRemoteProductReferences()
407
408 # Give everything an ID.
409 self.project_file.ComputeIDs()
410
411 # Make sure that no two objects in the project file have the same ID. If
412 # multiple objects wind up with the same ID, upon loading the file, Xcode
413 # will only recognize one object (the last one in the file?) and the
414 # results are unpredictable.
415 self.project_file.EnsureNoIDCollisions()
416
417 def Write(self):
418 # Write the project file to a temporary location first. Xcode watches for
419 # changes to the project file and presents a UI sheet offering to reload
420 # the project when it does change. However, in some cases, especially when
421 # multiple projects are open or when Xcode is busy, things don't work so
422 # seamlessly. Sometimes, Xcode is able to detect that a project file has
423 # changed but can't unload it because something else is referencing it.
424 # To mitigate this problem, and to avoid even having Xcode present the UI
425 # sheet when an open project is rewritten for inconsequential changes, the
426 # project file is written to a temporary file in the xcodeproj directory
427 # first. The new temporary file is then compared to the existing project
428 # file, if any. If they differ, the new file replaces the old; otherwise,
429 # the new project file is simply deleted. Xcode properly detects a file
430 # being renamed over an open project file as a change and so it remains
431 # able to present the "project file changed" sheet under this system.
432 # Writing to a temporary file first also avoids the possible problem of
433 # Xcode rereading an incomplete project file.
434 (output_fd, new_pbxproj_path) = \
435 tempfile.mkstemp(suffix='.tmp', prefix='project.pbxproj.gyp.',
436 dir=self.path)
437
438 try:
439 output_file = os.fdopen(output_fd, 'wb')
440
441 self.project_file.Print(output_file)
442 output_file.close()
443
444 pbxproj_path = os.path.join(self.path, 'project.pbxproj')
445
446 same = False
447 try:
448 same = filecmp.cmp(pbxproj_path, new_pbxproj_path, False)
449 except OSError, e:
450 if e.errno != errno.ENOENT:
451 raise
452
453 if same:
454 # The new file is identical to the old one, just get rid of the new
455 # one.
456 os.unlink(new_pbxproj_path)
457 else:
458 # The new file is different from the old one, or there is no old one.
459 # Rename the new file to the permanent name.
460 #
461 # tempfile.mkstemp uses an overly restrictive mode, resulting in a
462 # file that can only be read by the owner, regardless of the umask.
463 # There's no reason to not respect the umask here, which means that
464 # an extra hoop is required to fetch it and reset the new file's mode.
465 #
466 # No way to get the umask without setting a new one? Set a safe one
467 # and then set it back to the old value.
468 umask = os.umask(077)
469 os.umask(umask)
470
471 os.chmod(new_pbxproj_path, 0666 & ~umask)
472 os.rename(new_pbxproj_path, pbxproj_path)
473
474 except Exception:
475 # Don't leave turds behind. In fact, if this code was responsible for
476 # creating the xcodeproj directory, get rid of that too.
477 os.unlink(new_pbxproj_path)
478 if self.created_dir:
479 shutil.rmtree(self.path, True)
480 raise
481
482
483 cached_xcode_version = None
484 def InstalledXcodeVersion():
485 """Fetches the installed version of Xcode, returns empty string if it is
486 unable to figure it out."""
487
488 global cached_xcode_version
489 if not cached_xcode_version is None:
490 return cached_xcode_version
491
492 # Default to an empty string
493 cached_xcode_version = ''
494
495 # Collect the xcodebuild's version information.
496 try:
497 import subprocess
498 cmd = ['/usr/bin/xcodebuild', '-version']
499 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
500 xcodebuild_version_info = proc.communicate()[0]
501 # Any error, return empty string
502 if proc.returncode:
503 xcodebuild_version_info = ''
504 except OSError:
505 # We failed to launch the tool
506 xcodebuild_version_info = ''
507
508 # Pull out the Xcode version itself.
509 match_line = re.search('^Xcode (.*)$', xcodebuild_version_info, re.MULTILINE)
510 if match_line:
511 cached_xcode_version = match_line.group(1)
512 # Done!
513 return cached_xcode_version
514
515
516 def AddSourceToTarget(source, pbxp, xct):
517 # TODO(mark): Perhaps source_extensions and library_extensions can be made a
518 # little bit fancier.
519 source_extensions = ['c', 'cc', 'cpp', 'cxx', 'm', 'mm', 's']
520
521 # .o is conceptually more of a "source" than a "library," but Xcode thinks
522 # of "sources" as things to compile and "libraries" (or "frameworks") as
523 # things to link with. Adding an object file to an Xcode target's frameworks
524 # phase works properly.
525 library_extensions = ['a', 'dylib', 'framework', 'o']
526
527 basename = posixpath.basename(source)
528 (root, ext) = posixpath.splitext(basename)
529 if ext != '':
530 ext = ext[1:].lower()
531
532 if ext in source_extensions:
533 xct.SourcesPhase().AddFile(source)
534 elif ext in library_extensions:
535 xct.FrameworksPhase().AddFile(source)
536 else:
537 # Files that aren't added to a sources or frameworks build phase can still
538 # go into the project file, just not as part of a build phase.
539 pbxp.AddOrGetFileInRootGroup(source)
540
541
542 def AddResourceToTarget(resource, pbxp, xct):
543 # TODO(mark): Combine with AddSourceToTarget above? Or just inline this call
544 # where it's used.
545 xct.ResourcesPhase().AddFile(resource)
546
547
548 def AddHeaderToTarget(header, pbxp, xct, is_public):
549 # TODO(mark): Combine with AddSourceToTarget above? Or just inline this call
550 # where it's used.
551 settings = '{ATTRIBUTES = (%s, ); }' % ('Private', 'Public')[is_public]
552 xct.HeadersPhase().AddFile(header, settings)
553
554
555 _xcode_variable_re = re.compile('(\$\((.*?)\))')
556 def ExpandXcodeVariables(string, expansions):
557 """Expands Xcode-style $(VARIABLES) in string per the expansions dict.
558
559 In some rare cases, it is appropriate to expand Xcode variables when a
560 project file is generated. For any substring $(VAR) in string, if VAR is a
561 key in the expansions dict, $(VAR) will be replaced with expansions[VAR].
562 Any $(VAR) substring in string for which VAR is not a key in the expansions
563 dict will remain in the returned string.
564 """
565
566 matches = _xcode_variable_re.findall(string)
567 if matches == None:
568 return string
569
570 matches.reverse()
571 for match in matches:
572 (to_replace, variable) = match
573 if not variable in expansions:
574 continue
575
576 replacement = expansions[variable]
577 string = re.sub(re.escape(to_replace), replacement, string)
578
579 return string
580
581
582 def EscapeXCodeArgument(s):
583 """We must escape the arguments that we give to XCode so that it knows not to
584 split on spaces and to respect backslash and quote literals."""
585 s = s.replace('\\', '\\\\')
586 s = s.replace('"', '\\"')
587 return '"' + s + '"'
588
589
590 def GenerateOutput(target_list, target_dicts, data, params):
591 options = params['options']
592 generator_flags = params.get('generator_flags', {})
593 parallel_builds = generator_flags.get('xcode_parallel_builds', True)
594 serialize_all_tests = \
595 generator_flags.get('xcode_serialize_all_test_runs', True)
596 project_version = generator_flags.get('xcode_project_version', None)
597 skip_excluded_files = \
598 not generator_flags.get('xcode_list_excluded_files', True)
599 xcode_projects = {}
600 for build_file, build_file_dict in data.iteritems():
601 (build_file_root, build_file_ext) = os.path.splitext(build_file)
602 if build_file_ext != '.gyp':
603 continue
604 xcodeproj_path = build_file_root + options.suffix + '.xcodeproj'
605 if options.generator_output:
606 xcodeproj_path = os.path.join(options.generator_output, xcodeproj_path)
607 xcp = XcodeProject(build_file, xcodeproj_path, build_file_dict)
608 xcode_projects[build_file] = xcp
609 pbxp = xcp.project
610
611 if parallel_builds:
612 pbxp.SetProperty('attributes',
613 {'BuildIndependentTargetsInParallel': 'YES'})
614 if project_version:
615 xcp.project_file.SetXcodeVersion(project_version)
616
617 main_group = pbxp.GetProperty('mainGroup')
618 build_group = gyp.xcodeproj_file.PBXGroup({'name': 'Build'})
619 main_group.AppendChild(build_group)
620 for included_file in build_file_dict['included_files']:
621 build_group.AddOrGetFileByPath(included_file, False)
622
623 xcode_targets = {}
624 xcode_target_to_target_dict = {}
625 for qualified_target in target_list:
626 [build_file, target_name, toolset] = \
627 gyp.common.ParseQualifiedTarget(qualified_target)
628
629 spec = target_dicts[qualified_target]
630 if spec['toolset'] != 'target':
631 raise Exception(
632 'Multiple toolsets not supported in xcode build (target %s)' %
633 qualified_target)
634 configuration_names = [spec['default_configuration']]
635 for configuration_name in sorted(spec['configurations'].keys()):
636 if configuration_name not in configuration_names:
637 configuration_names.append(configuration_name)
638 xcp = xcode_projects[build_file]
639 pbxp = xcp.project
640
641 # Set up the configurations for the target according to the list of names
642 # supplied.
643 xccl = CreateXCConfigurationList(configuration_names)
644
645 # Create an XCTarget subclass object for the target. The type with
646 # "+bundle" appended will be used if the target has "mac_bundle" set.
647 # loadable_modules not in a mac_bundle are mapped to
648 # com.googlecode.gyp.xcode.bundle, a pseudo-type that xcode.py interprets
649 # to create a single-file mh_bundle.
650 _types = {
651 'executable': 'com.apple.product-type.tool',
652 'loadable_module': 'com.googlecode.gyp.xcode.bundle',
653 'shared_library': 'com.apple.product-type.library.dynamic',
654 'static_library': 'com.apple.product-type.library.static',
655 'executable+bundle': 'com.apple.product-type.application',
656 'loadable_module+bundle': 'com.apple.product-type.bundle',
657 'shared_library+bundle': 'com.apple.product-type.framework',
658 }
659
660 target_properties = {
661 'buildConfigurationList': xccl,
662 'name': target_name,
663 }
664
665 type = spec['type']
666 is_bundle = int(spec.get('mac_bundle', 0))
667 if type != 'none':
668 type_bundle_key = type
669 if is_bundle:
670 type_bundle_key += '+bundle'
671 xctarget_type = gyp.xcodeproj_file.PBXNativeTarget
672 try:
673 target_properties['productType'] = _types[type_bundle_key]
674 except KeyError, e:
675 gyp.common.ExceptionAppend(e, "-- unknown product type while "
676 "writing target %s" % target_name)
677 raise
678 else:
679 xctarget_type = gyp.xcodeproj_file.PBXAggregateTarget
680 assert not is_bundle, (
681 'mac_bundle targets cannot have type none (target "%s")' %
682 target_name)
683
684 target_product_name = spec.get('product_name')
685 if target_product_name is not None:
686 target_properties['productName'] = target_product_name
687
688 xct = xctarget_type(target_properties, parent=pbxp,
689 force_outdir=spec.get('product_dir'),
690 force_prefix=spec.get('product_prefix'),
691 force_extension=spec.get('product_extension'))
692 pbxp.AppendProperty('targets', xct)
693 xcode_targets[qualified_target] = xct
694 xcode_target_to_target_dict[xct] = spec
695
696 spec_actions = spec.get('actions', [])
697 spec_rules = spec.get('rules', [])
698
699 # Xcode has some "issues" with checking dependencies for the "Compile
700 # sources" step with any source files/headers generated by actions/rules.
701 # To work around this, if a target is building anything directly (not
702 # type "none"), then a second target as used to run the GYP actions/rules
703 # and is made a dependency of this target. This way the work is done
704 # before the dependency checks for what should be recompiled.
705 support_xct = None
706 if type != 'none' and (spec_actions or spec_rules):
707 support_xccl = CreateXCConfigurationList(configuration_names);
708 support_target_properties = {
709 'buildConfigurationList': support_xccl,
710 'name': target_name + ' Support',
711 }
712 if target_product_name:
713 support_target_properties['productName'] = \
714 target_product_name + ' Support'
715 support_xct = \
716 gyp.xcodeproj_file.PBXAggregateTarget(support_target_properties,
717 parent=pbxp)
718 pbxp.AppendProperty('targets', support_xct)
719 xct.AddDependency(support_xct)
720 # Hang the support target off the main target so it can be tested/found
721 # by the generator during Finalize.
722 xct.support_target = support_xct
723
724 prebuild_index = 0
725
726 # Add custom shell script phases for "actions" sections.
727 for action in spec_actions:
728 # There's no need to write anything into the script to ensure that the
729 # output directories already exist, because Xcode will look at the
730 # declared outputs and automatically ensure that they exist for us.
731
732 # Do we have a message to print when this action runs?
733 message = action.get('message')
734 if message:
735 message = 'echo note: ' + gyp.common.EncodePOSIXShellArgument(message)
736 else:
737 message = ''
738
739 # Turn the list into a string that can be passed to a shell.
740 action_string = gyp.common.EncodePOSIXShellList(action['action'])
741
742 # Convert Xcode-type variable references to sh-compatible environment
743 # variable references.
744 message_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax(message)
745 action_string_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax(
746 action_string)
747
748 script = ''
749 # Include the optional message
750 if message_sh:
751 script += message_sh + '\n'
752 # Be sure the script runs in exec, and that if exec fails, the script
753 # exits signalling an error.
754 script += 'exec ' + action_string_sh + '\nexit 1\n'
755 ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
756 'inputPaths': action['inputs'],
757 'name': 'Action "' + action['action_name'] + '"',
758 'outputPaths': action['outputs'],
759 'shellScript': script,
760 'showEnvVarsInLog': 0,
761 })
762
763 if support_xct:
764 support_xct.AppendProperty('buildPhases', ssbp)
765 else:
766 # TODO(mark): this assumes too much knowledge of the internals of
767 # xcodeproj_file; some of these smarts should move into xcodeproj_file
768 # itself.
769 xct._properties['buildPhases'].insert(prebuild_index, ssbp)
770 prebuild_index = prebuild_index + 1
771
772 # TODO(mark): Should verify that at most one of these is specified.
773 if int(action.get('process_outputs_as_sources', False)):
774 for output in action['outputs']:
775 AddSourceToTarget(output, pbxp, xct)
776
777 if int(action.get('process_outputs_as_mac_bundle_resources', False)):
778 for output in action['outputs']:
779 AddResourceToTarget(output, pbxp, xct)
780
781 # tgt_mac_bundle_resources holds the list of bundle resources so
782 # the rule processing can check against it.
783 if is_bundle:
784 tgt_mac_bundle_resources = spec.get('mac_bundle_resources', [])
785 else:
786 tgt_mac_bundle_resources = []
787
788 # Add custom shell script phases driving "make" for "rules" sections.
789 #
790 # Xcode's built-in rule support is almost powerful enough to use directly,
791 # but there are a few significant deficiencies that render them unusable.
792 # There are workarounds for some of its inadequacies, but in aggregate,
793 # the workarounds added complexity to the generator, and some workarounds
794 # actually require input files to be crafted more carefully than I'd like.
795 # Consequently, until Xcode rules are made more capable, "rules" input
796 # sections will be handled in Xcode output by shell script build phases
797 # performed prior to the compilation phase.
798 #
799 # The following problems with Xcode rules were found. The numbers are
800 # Apple radar IDs. I hope that these shortcomings are addressed, I really
801 # liked having the rules handled directly in Xcode during the period that
802 # I was prototyping this.
803 #
804 # 6588600 Xcode compiles custom script rule outputs too soon, compilation
805 # fails. This occurs when rule outputs from distinct inputs are
806 # interdependent. The only workaround is to put rules and their
807 # inputs in a separate target from the one that compiles the rule
808 # outputs. This requires input file cooperation and it means that
809 # process_outputs_as_sources is unusable.
810 # 6584932 Need to declare that custom rule outputs should be excluded from
811 # compilation. A possible workaround is to lie to Xcode about a
812 # rule's output, giving it a dummy file it doesn't know how to
813 # compile. The rule action script would need to touch the dummy.
814 # 6584839 I need a way to declare additional inputs to a custom rule.
815 # A possible workaround is a shell script phase prior to
816 # compilation that touches a rule's primary input files if any
817 # would-be additional inputs are newer than the output. Modifying
818 # the source tree - even just modification times - feels dirty.
819 # 6564240 Xcode "custom script" build rules always dump all environment
820 # variables. This is a low-prioroty problem and is not a
821 # show-stopper.
822 rules_by_ext = {}
823 for rule in spec_rules:
824 rules_by_ext[rule['extension']] = rule
825
826 # First, some definitions:
827 #
828 # A "rule source" is a file that was listed in a target's "sources"
829 # list and will have a rule applied to it on the basis of matching the
830 # rule's "extensions" attribute. Rule sources are direct inputs to
831 # rules.
832 #
833 # Rule definitions may specify additional inputs in their "inputs"
834 # attribute. These additional inputs are used for dependency tracking
835 # purposes.
836 #
837 # A "concrete output" is a rule output with input-dependent variables
838 # resolved. For example, given a rule with:
839 # 'extension': 'ext', 'outputs': ['$(INPUT_FILE_BASE).cc'],
840 # if the target's "sources" list contained "one.ext" and "two.ext",
841 # the "concrete output" for rule input "two.ext" would be "two.cc". If
842 # a rule specifies multiple outputs, each input file that the rule is
843 # applied to will have the same number of concrete outputs.
844 #
845 # If any concrete outputs are outdated or missing relative to their
846 # corresponding rule_source or to any specified additional input, the
847 # rule action must be performed to generate the concrete outputs.
848
849 # concrete_outputs_by_rule_source will have an item at the same index
850 # as the rule['rule_sources'] that it corresponds to. Each item is a
851 # list of all of the concrete outputs for the rule_source.
852 concrete_outputs_by_rule_source = []
853
854 # concrete_outputs_all is a flat list of all concrete outputs that this
855 # rule is able to produce, given the known set of input files
856 # (rule_sources) that apply to it.
857 concrete_outputs_all = []
858
859 # messages & actions are keyed by the same indices as rule['rule_sources']
860 # and concrete_outputs_by_rule_source. They contain the message and
861 # action to perform after resolving input-dependent variables. The
862 # message is optional, in which case None is stored for each rule source.
863 messages = []
864 actions = []
865
866 for rule_source in rule.get('rule_sources', []):
867 rule_source_basename = posixpath.basename(rule_source)
868 (rule_source_root, rule_source_ext) = \
869 posixpath.splitext(rule_source_basename)
870
871 # These are the same variable names that Xcode uses for its own native
872 # rule support. Because Xcode's rule engine is not being used, they
873 # need to be expanded as they are written to the makefile.
874 rule_input_dict = {
875 'INPUT_FILE_BASE': rule_source_root,
876 'INPUT_FILE_SUFFIX': rule_source_ext,
877 'INPUT_FILE_NAME': rule_source_basename,
878 'INPUT_FILE_PATH': rule_source,
879 }
880
881 concrete_outputs_for_this_rule_source = []
882 for output in rule.get('outputs', []):
883 # Fortunately, Xcode and make both use $(VAR) format for their
884 # variables, so the expansion is the only transformation necessary.
885 # Any remaning $(VAR)-type variables in the string can be given
886 # directly to make, which will pick up the correct settings from
887 # what Xcode puts into the environment.
888 concrete_output = ExpandXcodeVariables(output, rule_input_dict)
889 concrete_outputs_for_this_rule_source.append(concrete_output)
890
891 # Add all concrete outputs to the project.
892 pbxp.AddOrGetFileInRootGroup(concrete_output)
893
894 concrete_outputs_by_rule_source.append( \
895 concrete_outputs_for_this_rule_source)
896 concrete_outputs_all.extend(concrete_outputs_for_this_rule_source)
897
898 # TODO(mark): Should verify that at most one of these is specified.
899 if int(rule.get('process_outputs_as_sources', False)):
900 for output in concrete_outputs_for_this_rule_source:
901 AddSourceToTarget(output, pbxp, xct)
902
903 # If the file came from the mac_bundle_resources list or if the rule
904 # is marked to process outputs as bundle resource, do so.
905 was_mac_bundle_resource = rule_source in tgt_mac_bundle_resources
906 if was_mac_bundle_resource or \
907 int(rule.get('process_outputs_as_mac_bundle_resources', False)):
908 for output in concrete_outputs_for_this_rule_source:
909 AddResourceToTarget(output, pbxp, xct)
910
911 # Do we have a message to print when this rule runs?
912 message = rule.get('message')
913 if message:
914 message = gyp.common.EncodePOSIXShellArgument(message)
915 message = ExpandXcodeVariables(message, rule_input_dict)
916 messages.append(message)
917
918 # Turn the list into a string that can be passed to a shell.
919 action_string = gyp.common.EncodePOSIXShellList(rule['action'])
920
921 action = ExpandXcodeVariables(action_string, rule_input_dict)
922 actions.append(action)
923
924 if len(concrete_outputs_all) > 0:
925 # TODO(mark): There's a possibilty for collision here. Consider
926 # target "t" rule "A_r" and target "t_A" rule "r".
927 makefile_name = '%s_%s.make' % (target_name, rule['rule_name'])
928 makefile_path = os.path.join(xcode_projects[build_file].path,
929 makefile_name)
930 # TODO(mark): try/close? Write to a temporary file and swap it only
931 # if it's got changes?
932 makefile = open(makefile_path, 'wb')
933
934 # make will build the first target in the makefile by default. By
935 # convention, it's called "all". List all (or at least one)
936 # concrete output for each rule source as a prerequisite of the "all"
937 # target.
938 makefile.write('all: \\\n')
939 for concrete_output_index in \
940 xrange(0, len(concrete_outputs_by_rule_source)):
941 # Only list the first (index [0]) concrete output of each input
942 # in the "all" target. Otherwise, a parallel make (-j > 1) would
943 # attempt to process each input multiple times simultaneously.
944 # Otherwise, "all" could just contain the entire list of
945 # concrete_outputs_all.
946 concrete_output = \
947 concrete_outputs_by_rule_source[concrete_output_index][0]
948 if concrete_output_index == len(concrete_outputs_by_rule_source) - 1:
949 eol = ''
950 else:
951 eol = ' \\'
952 makefile.write(' %s%s\n' % (concrete_output, eol))
953
954 for (rule_source, concrete_outputs, message, action) in \
955 zip(rule['rule_sources'], concrete_outputs_by_rule_source,
956 messages, actions):
957 makefile.write('\n')
958
959 # Add a rule that declares it can build each concrete output of a
960 # rule source. Collect the names of the directories that are
961 # required.
962 concrete_output_dirs = []
963 for concrete_output_index in xrange(0, len(concrete_outputs)):
964 concrete_output = concrete_outputs[concrete_output_index]
965 if concrete_output_index == 0:
966 bol = ''
967 else:
968 bol = ' '
969 makefile.write('%s%s \\\n' % (bol, concrete_output))
970
971 concrete_output_dir = posixpath.dirname(concrete_output)
972 if (concrete_output_dir and
973 concrete_output_dir not in concrete_output_dirs):
974 concrete_output_dirs.append(concrete_output_dir)
975
976 makefile.write(' : \\\n')
977
978 # The prerequisites for this rule are the rule source itself and
979 # the set of additional rule inputs, if any.
980 prerequisites = [rule_source]
981 prerequisites.extend(rule.get('inputs', []))
982 for prerequisite_index in xrange(0, len(prerequisites)):
983 prerequisite = prerequisites[prerequisite_index]
984 if prerequisite_index == len(prerequisites) - 1:
985 eol = ''
986 else:
987 eol = ' \\'
988 makefile.write(' %s%s\n' % (prerequisite, eol))
989
990 # Make sure that output directories exist before executing the rule
991 # action.
992 if len(concrete_output_dirs) > 0:
993 makefile.write('\t@mkdir -p "%s"\n' %
994 '" "'.join(concrete_output_dirs))
995
996 # The rule message and action have already had the necessary variable
997 # substitutions performed.
998 if message:
999 # Mark it with note: so Xcode picks it up in build output.
1000 makefile.write('\t@echo note: %s\n' % message)
1001 makefile.write('\t%s\n' % action)
1002
1003 makefile.close()
1004
1005 # It might be nice to ensure that needed output directories exist
1006 # here rather than in each target in the Makefile, but that wouldn't
1007 # work if there ever was a concrete output that had an input-dependent
1008 # variable anywhere other than in the leaf position.
1009
1010 # Don't declare any inputPaths or outputPaths. If they're present,
1011 # Xcode will provide a slight optimization by only running the script
1012 # phase if any output is missing or outdated relative to any input.
1013 # Unfortunately, it will also assume that all outputs are touched by
1014 # the script, and if the outputs serve as files in a compilation
1015 # phase, they will be unconditionally rebuilt. Since make might not
1016 # rebuild everything that could be declared here as an output, this
1017 # extra compilation activity is unnecessary. With inputPaths and
1018 # outputPaths not supplied, make will always be called, but it knows
1019 # enough to not do anything when everything is up-to-date.
1020
1021 # To help speed things up, pass -j COUNT to make so it does some work
1022 # in parallel. Don't use ncpus because Xcode will build ncpus targets
1023 # in parallel and if each target happens to have a rules step, there
1024 # would be ncpus^2 things going. With a machine that has 2 quad-core
1025 # Xeons, a build can quickly run out of processes based on
1026 # scheduling/other tasks, and randomly failing builds are no good.
1027 script = \
1028 """JOB_COUNT="$(/usr/sbin/sysctl -n hw.ncpu)"
1029 if [ "${JOB_COUNT}" -gt 4 ]; then
1030 JOB_COUNT=4
1031 fi
1032 exec "${DEVELOPER_BIN_DIR}/make" -f "${PROJECT_FILE_PATH}/%s" -j "${JOB_COUNT}"
1033 exit 1
1034 """ % makefile_name
1035 ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
1036 'name': 'Rule "' + rule['rule_name'] + '"',
1037 'shellScript': script,
1038 'showEnvVarsInLog': 0,
1039 })
1040
1041 if support_xct:
1042 support_xct.AppendProperty('buildPhases', ssbp)
1043 else:
1044 # TODO(mark): this assumes too much knowledge of the internals of
1045 # xcodeproj_file; some of these smarts should move into xcodeproj_file
1046 # itself.
1047 xct._properties['buildPhases'].insert(prebuild_index, ssbp)
1048 prebuild_index = prebuild_index + 1
1049
1050 # Extra rule inputs also go into the project file. Concrete outputs were
1051 # already added when they were computed.
1052 groups = ['inputs', 'inputs_excluded']
1053 if skip_excluded_files:
1054 groups = [x for x in groups if not x.endswith('_excluded')]
1055 for group in groups:
1056 for item in rule.get(group, []):
1057 pbxp.AddOrGetFileInRootGroup(item)
1058
1059 # Add "sources".
1060 for source in spec.get('sources', []):
1061 (source_root, source_extension) = posixpath.splitext(source)
1062 if source_extension[1:] not in rules_by_ext:
1063 # AddSourceToTarget will add the file to a root group if it's not
1064 # already there.
1065 AddSourceToTarget(source, pbxp, xct)
1066 else:
1067 pbxp.AddOrGetFileInRootGroup(source)
1068
1069 # Add "mac_bundle_resources", "mac_framework_headers", and
1070 # "mac_framework_private_headers" if it's a bundle of any type.
1071 if is_bundle:
1072 for resource in tgt_mac_bundle_resources:
1073 (resource_root, resource_extension) = posixpath.splitext(resource)
1074 if resource_extension[1:] not in rules_by_ext:
1075 AddResourceToTarget(resource, pbxp, xct)
1076 else:
1077 pbxp.AddOrGetFileInRootGroup(resource)
1078
1079 for header in spec.get('mac_framework_headers', []):
1080 AddHeaderToTarget(header, pbxp, xct, True)
1081
1082 for header in spec.get('mac_framework_private_headers', []):
1083 AddHeaderToTarget(header, pbxp, xct, False)
1084
1085 # Add "copies".
1086 for copy_group in spec.get('copies', []):
1087 pbxcp = gyp.xcodeproj_file.PBXCopyFilesBuildPhase({
1088 'name': 'Copy to ' + copy_group['destination']
1089 },
1090 parent=xct)
1091 dest = copy_group['destination']
1092 if dest[0] not in ('/', '$'):
1093 # Relative paths are relative to $(SRCROOT).
1094 dest = '$(SRCROOT)/' + dest
1095 pbxcp.SetDestination(dest)
1096
1097 # TODO(mark): The usual comment about this knowing too much about
1098 # gyp.xcodeproj_file internals applies.
1099 xct._properties['buildPhases'].insert(prebuild_index, pbxcp)
1100
1101 for file in copy_group['files']:
1102 pbxcp.AddFile(file)
1103
1104 # Excluded files can also go into the project file.
1105 if not skip_excluded_files:
1106 for key in ['sources', 'mac_bundle_resources', 'mac_framework_headers',
1107 'mac_framework_private_headers']:
1108 excluded_key = key + '_excluded'
1109 for item in spec.get(excluded_key, []):
1110 pbxp.AddOrGetFileInRootGroup(item)
1111
1112 # So can "inputs" and "outputs" sections of "actions" groups.
1113 groups = ['inputs', 'inputs_excluded', 'outputs', 'outputs_excluded']
1114 if skip_excluded_files:
1115 groups = [x for x in groups if not x.endswith('_excluded')]
1116 for action in spec.get('actions', []):
1117 for group in groups:
1118 for item in action.get(group, []):
1119 # Exclude anything in BUILT_PRODUCTS_DIR. They're products, not
1120 # sources.
1121 if not item.startswith('$(BUILT_PRODUCTS_DIR)/'):
1122 pbxp.AddOrGetFileInRootGroup(item)
1123
1124 for postbuild in spec.get('postbuilds', []):
1125 action_string_sh = gyp.common.EncodePOSIXShellList(postbuild['action'])
1126 script = 'exec ' + action_string_sh + '\nexit 1\n'
1127
1128 # Make the postbuild step depend on the output of ld or ar from this
1129 # target. Apparently putting the script step after the link step isn't
1130 # sufficient to ensure proper ordering in all cases. With an input
1131 # declared but no outputs, the script step should run every time, as
1132 # desired.
1133 ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
1134 'inputPaths': ['$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_PATH)'],
1135 'name': 'Postbuild "' + postbuild['postbuild_name'] + '"',
1136 'shellScript': script,
1137 'showEnvVarsInLog': 0,
1138 })
1139 xct.AppendProperty('buildPhases', ssbp)
1140
1141 # Add dependencies before libraries, because adding a dependency may imply
1142 # adding a library. It's preferable to keep dependencies listed first
1143 # during a link phase so that they can override symbols that would
1144 # otherwise be provided by libraries, which will usually include system
1145 # libraries. On some systems, ld is finicky and even requires the
1146 # libraries to be ordered in such a way that unresolved symbols in
1147 # earlier-listed libraries may only be resolved by later-listed libraries.
1148 # The Mac linker doesn't work that way, but other platforms do, and so
1149 # their linker invocations need to be constructed in this way. There's
1150 # no compelling reason for Xcode's linker invocations to differ.
1151
1152 if 'dependencies' in spec:
1153 for dependency in spec['dependencies']:
1154 xct.AddDependency(xcode_targets[dependency])
1155 # The support project also gets the dependencies (in case they are
1156 # needed for the actions/rules to work).
1157 if support_xct:
1158 support_xct.AddDependency(xcode_targets[dependency])
1159
1160 if 'libraries' in spec:
1161 for library in spec['libraries']:
1162 xct.FrameworksPhase().AddFile(library)
1163 # Add the library's directory to LIBRARY_SEARCH_PATHS if necessary.
1164 # I wish Xcode handled this automatically.
1165 library_dir = posixpath.dirname(library)
1166 if library_dir not in xcode_standard_library_dirs and (
1167 not xct.HasBuildSetting(_library_search_paths_var) or
1168 library_dir not in xct.GetBuildSetting(_library_search_paths_var)):
1169 xct.AppendBuildSetting(_library_search_paths_var, library_dir)
1170
1171 for configuration_name in configuration_names:
1172 configuration = spec['configurations'][configuration_name]
1173 xcbc = xct.ConfigurationNamed(configuration_name)
1174 for include_dir in configuration.get('mac_framework_dirs', []):
1175 xcbc.AppendBuildSetting('FRAMEWORK_SEARCH_PATHS', include_dir)
1176 for include_dir in configuration.get('include_dirs', []):
1177 xcbc.AppendBuildSetting('HEADER_SEARCH_PATHS', include_dir)
1178 if 'defines' in configuration:
1179 for define in configuration['defines']:
1180 set_define = EscapeXCodeArgument(define)
1181 xcbc.AppendBuildSetting('GCC_PREPROCESSOR_DEFINITIONS', set_define)
1182 if 'xcode_settings' in configuration:
1183 for xck, xcv in configuration['xcode_settings'].iteritems():
1184 xcbc.SetBuildSetting(xck, xcv)
1185 if 'xcode_config_file' in configuration:
1186 config_ref = pbxp.AddOrGetFileInRootGroup(
1187 configuration['xcode_config_file'])
1188 xcbc.SetBaseConfiguration(config_ref)
1189
1190 build_files = []
1191 for build_file, build_file_dict in data.iteritems():
1192 if build_file.endswith('.gyp'):
1193 build_files.append(build_file)
1194
1195 for build_file in build_files:
1196 xcode_projects[build_file].Finalize1(xcode_targets, serialize_all_tests)
1197
1198 for build_file in build_files:
1199 xcode_projects[build_file].Finalize2(xcode_targets,
1200 xcode_target_to_target_dict)
1201
1202 for build_file in build_files:
1203 xcode_projects[build_file].Write()
+0
-2361
third_party/gyp/pylib/gyp/input.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 from compiler.ast import Const
7 from compiler.ast import Dict
8 from compiler.ast import Discard
9 from compiler.ast import List
10 from compiler.ast import Module
11 from compiler.ast import Node
12 from compiler.ast import Stmt
13 import compiler
14 import copy
15 import gyp.common
16 import optparse
17 import os.path
18 import re
19 import shlex
20 import subprocess
21 import sys
22
23
24 # A list of types that are treated as linkable.
25 linkable_types = ['executable', 'shared_library', 'loadable_module']
26
27 # A list of sections that contain links to other targets.
28 dependency_sections = ['dependencies', 'export_dependent_settings']
29
30 # base_path_sections is a list of sections defined by GYP that contain
31 # pathnames. The generators can provide more keys, the two lists are merged
32 # into path_sections, but you should call IsPathSection instead of using either
33 # list directly.
34 base_path_sections = [
35 'destination',
36 'files',
37 'include_dirs',
38 'inputs',
39 'libraries',
40 'outputs',
41 'sources',
42 ]
43 path_sections = []
44
45
46 def IsPathSection(section):
47 # If section ends in one of these characters, it's applied to a section
48 # without the trailing characters. '/' is notably absent from this list,
49 # because there's no way for a regular expression to be treated as a path.
50 while section[-1:] in ('=', '+', '?', '!'):
51 section = section[0:-1]
52
53 if section in path_sections or \
54 section.endswith('_dir') or section.endswith('_dirs') or \
55 section.endswith('_file') or section.endswith('_files') or \
56 section.endswith('_path') or section.endswith('_paths'):
57 return True
58 return False
59
60
61 # base_non_configuraiton_keys is a list of key names that belong in the target
62 # itself and should not be propagated into its configurations. It is merged
63 # with a list that can come from the generator to
64 # create non_configuration_keys.
65 base_non_configuration_keys = [
66 # Sections that must exist inside targets and not configurations.
67 'actions',
68 'configurations',
69 'copies',
70 'default_configuration',
71 'dependencies',
72 'dependencies_original',
73 'link_languages',
74 'libraries',
75 'postbuilds',
76 'product_dir',
77 'product_extension',
78 'product_name',
79 'product_prefix',
80 'rules',
81 'run_as',
82 'sources',
83 'suppress_wildcard',
84 'target_name',
85 'toolset',
86 'toolsets',
87 'type',
88 'variants',
89
90 # Sections that can be found inside targets or configurations, but that
91 # should not be propagated from targets into their configurations.
92 'variables',
93 ]
94 non_configuration_keys = []
95
96 # Keys that do not belong inside a configuration dictionary.
97 invalid_configuration_keys = [
98 'actions',
99 'all_dependent_settings',
100 'configurations',
101 'dependencies',
102 'direct_dependent_settings',
103 'libraries',
104 'link_settings',
105 'sources',
106 'target_name',
107 'type',
108 ]
109
110 # Controls how the generator want the build file paths.
111 absolute_build_file_paths = False
112
113 # Controls whether or not the generator supports multiple toolsets.
114 multiple_toolsets = False
115
116
117 def GetIncludedBuildFiles(build_file_path, aux_data, included=None):
118 """Return a list of all build files included into build_file_path.
119
120 The returned list will contain build_file_path as well as all other files
121 that it included, either directly or indirectly. Note that the list may
122 contain files that were included into a conditional section that evaluated
123 to false and was not merged into build_file_path's dict.
124
125 aux_data is a dict containing a key for each build file or included build
126 file. Those keys provide access to dicts whose "included" keys contain
127 lists of all other files included by the build file.
128
129 included should be left at its default None value by external callers. It
130 is used for recursion.
131
132 The returned list will not contain any duplicate entries. Each build file
133 in the list will be relative to the current directory.
134 """
135
136 if included == None:
137 included = []
138
139 if build_file_path in included:
140 return included
141
142 included.append(build_file_path)
143
144 for included_build_file in aux_data[build_file_path].get('included', []):
145 GetIncludedBuildFiles(included_build_file, aux_data, included)
146
147 return included
148
149
150 def CheckedEval(file_contents):
151 """Return the eval of a gyp file.
152
153 The gyp file is restricted to dictionaries and lists only, and
154 repeated keys are not allowed.
155
156 Note that this is slower than eval() is.
157 """
158
159 ast = compiler.parse(file_contents)
160 assert isinstance(ast, Module)
161 c1 = ast.getChildren()
162 assert c1[0] is None
163 assert isinstance(c1[1], Stmt)
164 c2 = c1[1].getChildren()
165 assert isinstance(c2[0], Discard)
166 c3 = c2[0].getChildren()
167 assert len(c3) == 1
168 return CheckNode(c3[0], [])
169
170
171 def CheckNode(node, keypath):
172 if isinstance(node, Dict):
173 c = node.getChildren()
174 dict = {}
175 for n in range(0, len(c), 2):
176 assert isinstance(c[n], Const)
177 key = c[n].getChildren()[0]
178 if key in dict:
179 raise KeyError, "Key '" + key + "' repeated at level " + \
180 repr(len(keypath) + 1) + " with key path '" + \
181 '.'.join(keypath) + "'"
182 kp = list(keypath) # Make a copy of the list for descending this node.
183 kp.append(key)
184 dict[key] = CheckNode(c[n + 1], kp)
185 return dict
186 elif isinstance(node, List):
187 c = node.getChildren()
188 children = []
189 for index, child in enumerate(c):
190 kp = list(keypath) # Copy list.
191 kp.append(repr(index))
192 children.append(CheckNode(child, kp))
193 return children
194 elif isinstance(node, Const):
195 return node.getChildren()[0]
196 else:
197 raise TypeError, "Unknown AST node at key path '" + '.'.join(keypath) + \
198 "': " + repr(node)
199
200
201 def LoadOneBuildFile(build_file_path, data, aux_data, variables, includes,
202 is_target, check):
203 if build_file_path in data:
204 return data[build_file_path]
205
206 if os.path.exists(build_file_path):
207 build_file_contents = open(build_file_path).read()
208 else:
209 raise Exception("%s not found (cwd: %s)" % (build_file_path, os.getcwd()))
210
211 build_file_data = None
212 try:
213 if check:
214 build_file_data = CheckedEval(build_file_contents)
215 else:
216 build_file_data = eval(build_file_contents, {'__builtins__': None},
217 None)
218 except SyntaxError, e:
219 e.filename = build_file_path
220 raise
221 except Exception, e:
222 gyp.common.ExceptionAppend(e, 'while reading ' + build_file_path)
223 raise
224
225 data[build_file_path] = build_file_data
226 aux_data[build_file_path] = {}
227
228 # Scan for includes and merge them in.
229 try:
230 if is_target:
231 LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data,
232 aux_data, variables, includes, check)
233 else:
234 LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data,
235 aux_data, variables, None, check)
236 except Exception, e:
237 gyp.common.ExceptionAppend(e,
238 'while reading includes of ' + build_file_path)
239 raise
240
241 return build_file_data
242
243
244 def LoadBuildFileIncludesIntoDict(subdict, subdict_path, data, aux_data,
245 variables, includes, check):
246 includes_list = []
247 if includes != None:
248 includes_list.extend(includes)
249 if 'includes' in subdict:
250 for include in subdict['includes']:
251 # "include" is specified relative to subdict_path, so compute the real
252 # path to include by appending the provided "include" to the directory
253 # in which subdict_path resides.
254 relative_include = \
255 os.path.normpath(os.path.join(os.path.dirname(subdict_path), include))
256 includes_list.append(relative_include)
257 # Unhook the includes list, it's no longer needed.
258 del subdict['includes']
259
260 # Merge in the included files.
261 for include in includes_list:
262 if not 'included' in aux_data[subdict_path]:
263 aux_data[subdict_path]['included'] = []
264 aux_data[subdict_path]['included'].append(include)
265
266 gyp.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Included File: '%s'" % include)
267
268 MergeDicts(subdict,
269 LoadOneBuildFile(include, data, aux_data, variables, None,
270 False, check),
271 subdict_path, include)
272
273 # Recurse into subdictionaries.
274 for k, v in subdict.iteritems():
275 if v.__class__ == dict:
276 LoadBuildFileIncludesIntoDict(v, subdict_path, data, aux_data, variables,
277 None, check)
278 elif v.__class__ == list:
279 LoadBuildFileIncludesIntoList(v, subdict_path, data, aux_data, variables,
280 check)
281
282
283 # This recurses into lists so that it can look for dicts.
284 def LoadBuildFileIncludesIntoList(sublist, sublist_path, data, aux_data,
285 variables, check):
286 for item in sublist:
287 if item.__class__ == dict:
288 LoadBuildFileIncludesIntoDict(item, sublist_path, data, aux_data,
289 variables, None, check)
290 elif item.__class__ == list:
291 LoadBuildFileIncludesIntoList(item, sublist_path, data, aux_data,
292 variables, check)
293
294 # Processes toolsets in all the targets. This recurses into condition entries
295 # since they can contain toolsets as well.
296 def ProcessToolsetsInDict(data):
297 if 'targets' in data:
298 target_list = data['targets']
299 new_target_list = []
300 for target in target_list:
301 # If this target already has an explicit 'toolset', and no 'toolsets'
302 # list, don't modify it further.
303 if 'toolset' in target and 'toolsets' not in target:
304 new_target_list.append(target)
305 continue
306 global multiple_toolsets
307 if multiple_toolsets:
308 toolsets = target.get('toolsets', ['target'])
309 else:
310 toolsets = ['target']
311 # Make sure this 'toolsets' definition is only processed once.
312 if 'toolsets' in target:
313 del target['toolsets']
314 if len(toolsets) > 0:
315 # Optimization: only do copies if more than one toolset is specified.
316 for build in toolsets[1:]:
317 new_target = copy.deepcopy(target)
318 new_target['toolset'] = build
319 new_target_list.append(new_target)
320 target['toolset'] = toolsets[0]
321 new_target_list.append(target)
322 data['targets'] = new_target_list
323 if 'conditions' in data:
324 for condition in data['conditions']:
325 if isinstance(condition, list):
326 for condition_dict in condition[1:]:
327 ProcessToolsetsInDict(condition_dict)
328
329
330 # TODO(mark): I don't love this name. It just means that it's going to load
331 # a build file that contains targets and is expected to provide a targets dict
332 # that contains the targets...
333 def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes,
334 depth, check):
335 global absolute_build_file_paths
336
337 # If depth is set, predefine the DEPTH variable to be a relative path from
338 # this build file's directory to the directory identified by depth.
339 if depth:
340 # TODO(dglazkov) The backslash/forward-slash replacement at the end is a
341 # temporary measure. This should really be addressed by keeping all paths
342 # in POSIX until actual project generation.
343 d = gyp.common.RelativePath(depth, os.path.dirname(build_file_path))
344 if d == '':
345 variables['DEPTH'] = '.'
346 else:
347 variables['DEPTH'] = d.replace('\\', '/')
348
349 # If the generator needs absolue paths, then do so.
350 if absolute_build_file_paths:
351 build_file_path = os.path.abspath(build_file_path)
352
353 if build_file_path in data['target_build_files']:
354 # Already loaded.
355 return
356 data['target_build_files'].add(build_file_path)
357
358 gyp.DebugOutput(gyp.DEBUG_INCLUDES,
359 "Loading Target Build File '%s'" % build_file_path)
360
361 build_file_data = LoadOneBuildFile(build_file_path, data, aux_data, variables,
362 includes, True, check)
363
364 # Store DEPTH for later use in generators.
365 build_file_data['_DEPTH'] = depth
366
367 # Set up the included_files key indicating which .gyp files contributed to
368 # this target dict.
369 if 'included_files' in build_file_data:
370 raise KeyError, build_file_path + ' must not contain included_files key'
371
372 included = GetIncludedBuildFiles(build_file_path, aux_data)
373 build_file_data['included_files'] = []
374 for included_file in included:
375 # included_file is relative to the current directory, but it needs to
376 # be made relative to build_file_path's directory.
377 included_relative = \
378 gyp.common.RelativePath(included_file,
379 os.path.dirname(build_file_path))
380 build_file_data['included_files'].append(included_relative)
381
382 # Do a first round of toolsets expansion so that conditions can be defined
383 # per toolset.
384 ProcessToolsetsInDict(build_file_data)
385
386 # Apply "pre"/"early" variable expansions and condition evaluations.
387 ProcessVariablesAndConditionsInDict(build_file_data, False, variables,
388 build_file_path)
389
390 # Since some toolsets might have been defined conditionally, perform
391 # a second round of toolsets expansion now.
392 ProcessToolsetsInDict(build_file_data)
393
394 # Look at each project's target_defaults dict, and merge settings into
395 # targets.
396 if 'target_defaults' in build_file_data:
397 index = 0
398 if 'targets' in build_file_data:
399 while index < len(build_file_data['targets']):
400 # This procedure needs to give the impression that target_defaults is
401 # used as defaults, and the individual targets inherit from that.
402 # The individual targets need to be merged into the defaults. Make
403 # a deep copy of the defaults for each target, merge the target dict
404 # as found in the input file into that copy, and then hook up the
405 # copy with the target-specific data merged into it as the replacement
406 # target dict.
407 old_target_dict = build_file_data['targets'][index]
408 new_target_dict = copy.deepcopy(build_file_data['target_defaults'])
409 MergeDicts(new_target_dict, old_target_dict,
410 build_file_path, build_file_path)
411 build_file_data['targets'][index] = new_target_dict
412 index = index + 1
413 else:
414 raise Exception, \
415 "Unable to find targets in build file %s" % build_file_path
416
417 # No longer needed.
418 del build_file_data['target_defaults']
419
420 # Look for dependencies. This means that dependency resolution occurs
421 # after "pre" conditionals and variable expansion, but before "post" -
422 # in other words, you can't put a "dependencies" section inside a "post"
423 # conditional within a target.
424
425 if 'targets' in build_file_data:
426 for target_dict in build_file_data['targets']:
427 if 'dependencies' not in target_dict:
428 continue
429 for dependency in target_dict['dependencies']:
430 other_build_file = \
431 gyp.common.ResolveTarget(build_file_path, dependency, None)[0]
432 try:
433 LoadTargetBuildFile(other_build_file, data, aux_data, variables,
434 includes, depth, check)
435 except Exception, e:
436 gyp.common.ExceptionAppend(
437 e, 'while loading dependencies of %s' % build_file_path)
438 raise
439
440 return data
441
442
443 # Look for the bracket that matches the first bracket seen in a
444 # string, and return the start and end as a tuple. For example, if
445 # the input is something like "<(foo <(bar)) blah", then it would
446 # return (1, 13), indicating the entire string except for the leading
447 # "<" and trailing " blah".
448 def FindEnclosingBracketGroup(input):
449 brackets = { '}': '{',
450 ']': '[',
451 ')': '(', }
452 stack = []
453 count = 0
454 start = -1
455 for char in input:
456 if char in brackets.values():
457 stack.append(char)
458 if start == -1:
459 start = count
460 if char in brackets.keys():
461 try:
462 last_bracket = stack.pop()
463 except IndexError:
464 return (-1, -1)
465 if last_bracket != brackets[char]:
466 return (-1, -1)
467 if len(stack) == 0:
468 return (start, count + 1)
469 count = count + 1
470 return (-1, -1)
471
472
473 canonical_int_re = re.compile('^(0|-?[1-9][0-9]*)$')
474
475
476 def IsStrCanonicalInt(string):
477 """Returns True if |string| is in its canonical integer form.
478
479 The canonical form is such that str(int(string)) == string.
480 """
481 if not isinstance(string, str) or not canonical_int_re.match(string):
482 return False
483
484 return True
485
486
487 # This matches things like "<(asdf)", "<!(cmd)", "<!@(cmd)", "<|(list)",
488 # "<!interpreter(arguments)", "<([list])", and even "<([)" and "<(<())".
489 # In the last case, the inner "<()" is captured in match['content'].
490 early_variable_re = re.compile(
491 '(?P<replace>(?P<type><(?:(?:!?@?)|\|)?)'
492 '(?P<command_string>[-a-zA-Z0-9_.]+)?'
493 '\((?P<is_array>\s*\[?)'
494 '(?P<content>.*?)(\]?)\))')
495
496 # This matches the same as early_variable_re, but with '>' instead of '<'.
497 late_variable_re = re.compile(
498 '(?P<replace>(?P<type>>(?:(?:!?@?)|\|)?)'
499 '(?P<command_string>[-a-zA-Z0-9_.]+)?'
500 '\((?P<is_array>\s*\[?)'
501 '(?P<content>.*?)(\]?)\))')
502
503 # Global cache of results from running commands so they don't have to be run
504 # more then once.
505 cached_command_results = {}
506
507
508 def FixupPlatformCommand(cmd):
509 if sys.platform == 'win32':
510 if type(cmd) == list:
511 cmd = [re.sub('^cat ', 'type ', cmd[0])] + cmd[1:]
512 else:
513 cmd = re.sub('^cat ', 'type ', cmd)
514 return cmd
515
516
517 def ExpandVariables(input, is_late, variables, build_file):
518 # Look for the pattern that gets expanded into variables
519 if not is_late:
520 variable_re = early_variable_re
521 expansion_symbol = '<'
522 else:
523 variable_re = late_variable_re
524 expansion_symbol = '>'
525
526 input_str = str(input)
527 # Do a quick scan to determine if an expensive regex search is warranted.
528 if expansion_symbol in input_str:
529 # Get the entire list of matches as a list of MatchObject instances.
530 # (using findall here would return strings instead of MatchObjects).
531 matches = [match for match in variable_re.finditer(input_str)]
532 else:
533 matches = None
534
535 output = input_str
536 if matches:
537 # Reverse the list of matches so that replacements are done right-to-left.
538 # That ensures that earlier replacements won't mess up the string in a
539 # way that causes later calls to find the earlier substituted text instead
540 # of what's intended for replacement.
541 matches.reverse()
542 for match_group in matches:
543 match = match_group.groupdict()
544 gyp.DebugOutput(gyp.DEBUG_VARIABLES,
545 "Matches: %s" % repr(match))
546 # match['replace'] is the substring to look for, match['type']
547 # is the character code for the replacement type (< > <! >! <| >| <@
548 # >@ <!@ >!@), match['is_array'] contains a '[' for command
549 # arrays, and match['content'] is the name of the variable (< >)
550 # or command to run (<! >!). match['command_string'] is an optional
551 # command string. Currently, only 'pymod_do_main' is supported.
552
553 # run_command is true if a ! variant is used.
554 run_command = '!' in match['type']
555 command_string = match['command_string']
556
557 # file_list is true if a | variant is used.
558 file_list = '|' in match['type']
559
560 # Capture these now so we can adjust them later.
561 replace_start = match_group.start('replace')
562 replace_end = match_group.end('replace')
563
564 # Find the ending paren, and re-evaluate the contained string.
565 (c_start, c_end) = FindEnclosingBracketGroup(input_str[replace_start:])
566
567 # Adjust the replacement range to match the entire command
568 # found by FindEnclosingBracketGroup (since the variable_re
569 # probably doesn't match the entire command if it contained
570 # nested variables).
571 replace_end = replace_start + c_end
572
573 # Find the "real" replacement, matching the appropriate closing
574 # paren, and adjust the replacement start and end.
575 replacement = input_str[replace_start:replace_end]
576
577 # Figure out what the contents of the variable parens are.
578 contents_start = replace_start + c_start + 1
579 contents_end = replace_end - 1
580 contents = input_str[contents_start:contents_end]
581
582 # Do filter substitution now for <|().
583 # Admittedly, this is different than the evaluation order in other
584 # contexts. However, since filtration has no chance to run on <|(),
585 # this seems like the only obvious way to give them access to filters.
586 if file_list:
587 processed_variables = copy.deepcopy(variables)
588 ProcessListFiltersInDict(contents, processed_variables)
589 # Recurse to expand variables in the contents
590 contents = ExpandVariables(contents, is_late,
591 processed_variables, build_file)
592 else:
593 # Recurse to expand variables in the contents
594 contents = ExpandVariables(contents, is_late, variables, build_file)
595
596 # Strip off leading/trailing whitespace so that variable matches are
597 # simpler below (and because they are rarely needed).
598 contents = contents.strip()
599
600 # expand_to_list is true if an @ variant is used. In that case,
601 # the expansion should result in a list. Note that the caller
602 # is to be expecting a list in return, and not all callers do
603 # because not all are working in list context. Also, for list
604 # expansions, there can be no other text besides the variable
605 # expansion in the input string.
606 expand_to_list = '@' in match['type'] and input_str == replacement
607
608 if run_command or file_list:
609 # Find the build file's directory, so commands can be run or file lists
610 # generated relative to it.
611 build_file_dir = os.path.dirname(build_file)
612 if build_file_dir == '':
613 # If build_file is just a leaf filename indicating a file in the
614 # current directory, build_file_dir might be an empty string. Set
615 # it to None to signal to subprocess.Popen that it should run the
616 # command in the current directory.
617 build_file_dir = None
618
619 # Support <|(listfile.txt ...) which generates a file
620 # containing items from a gyp list, generated at gyp time.
621 # This works around actions/rules which have more inputs than will
622 # fit on the command line.
623 if file_list:
624 if type(contents) == list:
625 contents_list = contents
626 else:
627 contents_list = contents.split(' ')
628 replacement = contents_list[0]
629 path = replacement
630 if not os.path.isabs(path):
631 path = os.path.join(build_file_dir, path)
632 f = gyp.common.WriteOnDiff(path)
633 for i in contents_list[1:]:
634 f.write('%s\n' % i)
635 f.close()
636
637 elif run_command:
638 use_shell = True
639 if match['is_array']:
640 contents = eval(contents)
641 use_shell = False
642
643 # Check for a cached value to avoid executing commands, or generating
644 # file lists more than once.
645 # TODO(http://code.google.com/p/gyp/issues/detail?id=112): It is
646 # possible that the command being invoked depends on the current
647 # directory. For that case the syntax needs to be extended so that the
648 # directory is also used in cache_key (it becomes a tuple).
649 # TODO(http://code.google.com/p/gyp/issues/detail?id=111): In theory,
650 # someone could author a set of GYP files where each time the command
651 # is invoked it produces different output by design. When the need
652 # arises, the syntax should be extended to support no caching off a
653 # command's output so it is run every time.
654 cache_key = str(contents)
655 cached_value = cached_command_results.get(cache_key, None)
656 if cached_value is None:
657 gyp.DebugOutput(gyp.DEBUG_VARIABLES,
658 "Executing command '%s' in directory '%s'" %
659 (contents,build_file_dir))
660
661 replacement = ''
662
663 if command_string == 'pymod_do_main':
664 # <!pymod_do_main(modulename param eters) loads |modulename| as a
665 # python module and then calls that module's DoMain() function,
666 # passing ["param", "eters"] as a single list argument. For modules
667 # that don't load quickly, this can be faster than
668 # <!(python modulename param eters). Do this in |build_file_dir|.
669 oldwd = os.getcwd() # Python doesn't like os.open('.'): no fchdir.
670 os.chdir(build_file_dir)
671
672 parsed_contents = shlex.split(contents)
673 py_module = __import__(parsed_contents[0])
674 replacement = str(py_module.DoMain(parsed_contents[1:])).rstrip()
675
676 os.chdir(oldwd)
677 assert replacement != None
678 elif command_string:
679 raise Exception("Unknown command string '%s' in '%s'." %
680 (command_string, contents))
681 else:
682 # Fix up command with platform specific workarounds.
683 contents = FixupPlatformCommand(contents)
684 p = subprocess.Popen(contents, shell=use_shell,
685 stdout=subprocess.PIPE,
686 stderr=subprocess.PIPE,
687 stdin=subprocess.PIPE,
688 cwd=build_file_dir)
689
690 p_stdout, p_stderr = p.communicate('')
691
692 if p.wait() != 0 or p_stderr:
693 sys.stderr.write(p_stderr)
694 # Simulate check_call behavior, since check_call only exists
695 # in python 2.5 and later.
696 raise Exception("Call to '%s' returned exit status %d." %
697 (contents, p.returncode))
698 replacement = p_stdout.rstrip()
699
700 cached_command_results[cache_key] = replacement
701 else:
702 gyp.DebugOutput(gyp.DEBUG_VARIABLES,
703 "Had cache value for command '%s' in directory '%s'" %
704 (contents,build_file_dir))
705 replacement = cached_value
706
707 else:
708 if not contents in variables:
709 raise KeyError, 'Undefined variable ' + contents + \
710 ' in ' + build_file
711 replacement = variables[contents]
712
713 if isinstance(replacement, list):
714 for item in replacement:
715 if not isinstance(item, str) and not isinstance(item, int):
716 raise TypeError, 'Variable ' + contents + \
717 ' must expand to a string or list of strings; ' + \
718 'list contains a ' + \
719 item.__class__.__name__
720 # Run through the list and handle variable expansions in it. Since
721 # the list is guaranteed not to contain dicts, this won't do anything
722 # with conditions sections.
723 ProcessVariablesAndConditionsInList(replacement, is_late, variables,
724 build_file)
725 elif not isinstance(replacement, str) and \
726 not isinstance(replacement, int):
727 raise TypeError, 'Variable ' + contents + \
728 ' must expand to a string or list of strings; ' + \
729 'found a ' + replacement.__class__.__name__
730
731 if expand_to_list:
732 # Expanding in list context. It's guaranteed that there's only one
733 # replacement to do in |input_str| and that it's this replacement. See
734 # above.
735 if isinstance(replacement, list):
736 # If it's already a list, make a copy.
737 output = replacement[:]
738 else:
739 # Split it the same way sh would split arguments.
740 output = shlex.split(str(replacement))
741 else:
742 # Expanding in string context.
743 encoded_replacement = ''
744 if isinstance(replacement, list):
745 # When expanding a list into string context, turn the list items
746 # into a string in a way that will work with a subprocess call.
747 #
748 # TODO(mark): This isn't completely correct. This should
749 # call a generator-provided function that observes the
750 # proper list-to-argument quoting rules on a specific
751 # platform instead of just calling the POSIX encoding
752 # routine.
753 encoded_replacement = gyp.common.EncodePOSIXShellList(replacement)
754 else:
755 encoded_replacement = replacement
756
757 output = output[:replace_start] + str(encoded_replacement) + \
758 output[replace_end:]
759 # Prepare for the next match iteration.
760 input_str = output
761
762 # Look for more matches now that we've replaced some, to deal with
763 # expanding local variables (variables defined in the same
764 # variables block as this one).
765 gyp.DebugOutput(gyp.DEBUG_VARIABLES,
766 "Found output %s, recursing." % repr(output))
767 if isinstance(output, list):
768 new_output = []
769 for item in output:
770 new_output.append(ExpandVariables(item, is_late, variables, build_file))
771 output = new_output
772 else:
773 output = ExpandVariables(output, is_late, variables, build_file)
774
775 # Convert all strings that are canonically-represented integers into integers.
776 if isinstance(output, list):
777 for index in xrange(0, len(output)):
778 if IsStrCanonicalInt(output[index]):
779 output[index] = int(output[index])
780 elif IsStrCanonicalInt(output):
781 output = int(output)
782
783 gyp.DebugOutput(gyp.DEBUG_VARIABLES,
784 "Expanding %s to %s" % (repr(input), repr(output)))
785 return output
786
787
788 def ProcessConditionsInDict(the_dict, is_late, variables, build_file):
789 # Process a 'conditions' or 'target_conditions' section in the_dict,
790 # depending on is_late. If is_late is False, 'conditions' is used.
791 #
792 # Each item in a conditions list consists of cond_expr, a string expression
793 # evaluated as the condition, and true_dict, a dict that will be merged into
794 # the_dict if cond_expr evaluates to true. Optionally, a third item,
795 # false_dict, may be present. false_dict is merged into the_dict if
796 # cond_expr evaluates to false.
797 #
798 # Any dict merged into the_dict will be recursively processed for nested
799 # conditionals and other expansions, also according to is_late, immediately
800 # prior to being merged.
801
802 if not is_late:
803 conditions_key = 'conditions'
804 else:
805 conditions_key = 'target_conditions'
806
807 if not conditions_key in the_dict:
808 return
809
810 conditions_list = the_dict[conditions_key]
811 # Unhook the conditions list, it's no longer needed.
812 del the_dict[conditions_key]
813
814 for condition in conditions_list:
815 if not isinstance(condition, list):
816 raise TypeError, conditions_key + ' must be a list'
817 if len(condition) != 2 and len(condition) != 3:
818 # It's possible that condition[0] won't work in which case this
819 # attempt will raise its own IndexError. That's probably fine.
820 raise IndexError, conditions_key + ' ' + condition[0] + \
821 ' must be length 2 or 3, not ' + str(len(condition))
822
823 [cond_expr, true_dict] = condition[0:2]
824 false_dict = None
825 if len(condition) == 3:
826 false_dict = condition[2]
827
828 # Do expansions on the condition itself. Since the conditon can naturally
829 # contain variable references without needing to resort to GYP expansion
830 # syntax, this is of dubious value for variables, but someone might want to
831 # use a command expansion directly inside a condition.
832 cond_expr_expanded = ExpandVariables(cond_expr, is_late, variables,
833 build_file)
834 if not isinstance(cond_expr_expanded, str) and \
835 not isinstance(cond_expr_expanded, int):
836 raise ValueError, \
837 'Variable expansion in this context permits str and int ' + \
838 'only, found ' + expanded.__class__.__name__
839
840 try:
841 ast_code = compile(cond_expr_expanded, '<string>', 'eval')
842
843 if eval(ast_code, {'__builtins__': None}, variables):
844 merge_dict = true_dict
845 else:
846 merge_dict = false_dict
847 except SyntaxError, e:
848 syntax_error = SyntaxError('%s while evaluating condition \'%s\' in %s '
849 'at character %d.' %
850 (str(e.args[0]), e.text, build_file, e.offset),
851 e.filename, e.lineno, e.offset, e.text)
852 raise syntax_error
853 except NameError, e:
854 gyp.common.ExceptionAppend(e, 'while evaluating condition \'%s\' in %s' %
855 (cond_expr_expanded, build_file))
856 raise
857
858 if merge_dict != None:
859 # Expand variables and nested conditinals in the merge_dict before
860 # merging it.
861 ProcessVariablesAndConditionsInDict(merge_dict, is_late,
862 variables, build_file)
863
864 MergeDicts(the_dict, merge_dict, build_file, build_file)
865
866
867 def LoadAutomaticVariablesFromDict(variables, the_dict):
868 # Any keys with plain string values in the_dict become automatic variables.
869 # The variable name is the key name with a "_" character prepended.
870 for key, value in the_dict.iteritems():
871 if isinstance(value, str) or isinstance(value, int) or \
872 isinstance(value, list):
873 variables['_' + key] = value
874
875
876 def LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key):
877 # Any keys in the_dict's "variables" dict, if it has one, becomes a
878 # variable. The variable name is the key name in the "variables" dict.
879 # Variables that end with the % character are set only if they are unset in
880 # the variables dict. the_dict_key is the name of the key that accesses
881 # the_dict in the_dict's parent dict. If the_dict's parent is not a dict
882 # (it could be a list or it could be parentless because it is a root dict),
883 # the_dict_key will be None.
884 for key, value in the_dict.get('variables', {}).iteritems():
885 if not isinstance(value, str) and not isinstance(value, int) and \
886 not isinstance(value, list):
887 continue
888
889 if key.endswith('%'):
890 variable_name = key[:-1]
891 if variable_name in variables:
892 # If the variable is already set, don't set it.
893 continue
894 if the_dict_key is 'variables' and variable_name in the_dict:
895 # If the variable is set without a % in the_dict, and the_dict is a
896 # variables dict (making |variables| a varaibles sub-dict of a
897 # variables dict), use the_dict's definition.
898 value = the_dict[variable_name]
899 else:
900 variable_name = key
901
902 variables[variable_name] = value
903
904
905 def ProcessVariablesAndConditionsInDict(the_dict, is_late, variables_in,
906 build_file, the_dict_key=None):
907 """Handle all variable and command expansion and conditional evaluation.
908
909 This function is the public entry point for all variable expansions and
910 conditional evaluations. The variables_in dictionary will not be modified
911 by this function.
912 """
913
914 # Make a copy of the variables_in dict that can be modified during the
915 # loading of automatics and the loading of the variables dict.
916 variables = variables_in.copy()
917 LoadAutomaticVariablesFromDict(variables, the_dict)
918
919 if 'variables' in the_dict:
920 # Make sure all the local variables are added to the variables
921 # list before we process them so that you can reference one
922 # variable from another. They will be fully expanded by recursion
923 # in ExpandVariables.
924 for key, value in the_dict['variables'].iteritems():
925 variables[key] = value
926
927 # Handle the associated variables dict first, so that any variable
928 # references within can be resolved prior to using them as variables.
929 # Pass a copy of the variables dict to avoid having it be tainted.
930 # Otherwise, it would have extra automatics added for everything that
931 # should just be an ordinary variable in this scope.
932 ProcessVariablesAndConditionsInDict(the_dict['variables'], is_late,
933 variables, build_file, 'variables')
934
935 LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key)
936
937 for key, value in the_dict.iteritems():
938 # Skip "variables", which was already processed if present.
939 if key != 'variables' and isinstance(value, str):
940 expanded = ExpandVariables(value, is_late, variables, build_file)
941 if not isinstance(expanded, str) and not isinstance(expanded, int):
942 raise ValueError, \
943 'Variable expansion in this context permits str and int ' + \
944 'only, found ' + expanded.__class__.__name__ + ' for ' + key
945 the_dict[key] = expanded
946
947 # Variable expansion may have resulted in changes to automatics. Reload.
948 # TODO(mark): Optimization: only reload if no changes were made.
949 variables = variables_in.copy()
950 LoadAutomaticVariablesFromDict(variables, the_dict)
951 LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key)
952
953 # Process conditions in this dict. This is done after variable expansion
954 # so that conditions may take advantage of expanded variables. For example,
955 # if the_dict contains:
956 # {'type': '<(library_type)',
957 # 'conditions': [['_type=="static_library"', { ... }]]},
958 # _type, as used in the condition, will only be set to the value of
959 # library_type if variable expansion is performed before condition
960 # processing. However, condition processing should occur prior to recursion
961 # so that variables (both automatic and "variables" dict type) may be
962 # adjusted by conditions sections, merged into the_dict, and have the
963 # intended impact on contained dicts.
964 #
965 # This arrangement means that a "conditions" section containing a "variables"
966 # section will only have those variables effective in subdicts, not in
967 # the_dict. The workaround is to put a "conditions" section within a
968 # "variables" section. For example:
969 # {'conditions': [['os=="mac"', {'variables': {'define': 'IS_MAC'}}]],
970 # 'defines': ['<(define)'],
971 # 'my_subdict': {'defines': ['<(define)']}},
972 # will not result in "IS_MAC" being appended to the "defines" list in the
973 # current scope but would result in it being appended to the "defines" list
974 # within "my_subdict". By comparison:
975 # {'variables': {'conditions': [['os=="mac"', {'define': 'IS_MAC'}]]},
976 # 'defines': ['<(define)'],
977 # 'my_subdict': {'defines': ['<(define)']}},
978 # will append "IS_MAC" to both "defines" lists.
979
980 # Evaluate conditions sections, allowing variable expansions within them
981 # as well as nested conditionals. This will process a 'conditions' or
982 # 'target_conditions' section, perform appropriate merging and recursive
983 # conditional and variable processing, and then remove the conditions section
984 # from the_dict if it is present.
985 ProcessConditionsInDict(the_dict, is_late, variables, build_file)
986
987 # Conditional processing may have resulted in changes to automatics or the
988 # variables dict. Reload.
989 variables = variables_in.copy()
990 LoadAutomaticVariablesFromDict(variables, the_dict)
991 LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key)
992
993 # Recurse into child dicts, or process child lists which may result in
994 # further recursion into descendant dicts.
995 for key, value in the_dict.iteritems():
996 # Skip "variables" and string values, which were already processed if
997 # present.
998 if key == 'variables' or isinstance(value, str):
999 continue
1000 if isinstance(value, dict):
1001 # Pass a copy of the variables dict so that subdicts can't influence
1002 # parents.
1003 ProcessVariablesAndConditionsInDict(value, is_late, variables,
1004 build_file, key)
1005 elif isinstance(value, list):
1006 # The list itself can't influence the variables dict, and
1007 # ProcessVariablesAndConditionsInList will make copies of the variables
1008 # dict if it needs to pass it to something that can influence it. No
1009 # copy is necessary here.
1010 ProcessVariablesAndConditionsInList(value, is_late, variables,
1011 build_file)
1012 elif not isinstance(value, int):
1013 raise TypeError, 'Unknown type ' + value.__class__.__name__ + \
1014 ' for ' + key
1015
1016
1017 def ProcessVariablesAndConditionsInList(the_list, is_late, variables,
1018 build_file):
1019 # Iterate using an index so that new values can be assigned into the_list.
1020 index = 0
1021 while index < len(the_list):
1022 item = the_list[index]
1023 if isinstance(item, dict):
1024 # Make a copy of the variables dict so that it won't influence anything
1025 # outside of its own scope.
1026 ProcessVariablesAndConditionsInDict(item, is_late, variables, build_file)
1027 elif isinstance(item, list):
1028 ProcessVariablesAndConditionsInList(item, is_late, variables, build_file)
1029 elif isinstance(item, str):
1030 expanded = ExpandVariables(item, is_late, variables, build_file)
1031 if isinstance(expanded, str) or isinstance(expanded, int):
1032 the_list[index] = expanded
1033 elif isinstance(expanded, list):
1034 del the_list[index]
1035 for expanded_item in expanded:
1036 the_list.insert(index, expanded_item)
1037 index = index + 1
1038
1039 # index now identifies the next item to examine. Continue right now
1040 # without falling into the index increment below.
1041 continue
1042 else:
1043 raise ValueError, \
1044 'Variable expansion in this context permits strings and ' + \
1045 'lists only, found ' + expanded.__class__.__name__ + ' at ' + \
1046 index
1047 elif not isinstance(item, int):
1048 raise TypeError, 'Unknown type ' + item.__class__.__name__ + \
1049 ' at index ' + index
1050 index = index + 1
1051
1052
1053 def BuildTargetsDict(data):
1054 """Builds a dict mapping fully-qualified target names to their target dicts.
1055
1056 |data| is a dict mapping loaded build files by pathname relative to the
1057 current directory. Values in |data| are build file contents. For each
1058 |data| value with a "targets" key, the value of the "targets" key is taken
1059 as a list containing target dicts. Each target's fully-qualified name is
1060 constructed from the pathname of the build file (|data| key) and its
1061 "target_name" property. These fully-qualified names are used as the keys
1062 in the returned dict. These keys provide access to the target dicts,
1063 the dicts in the "targets" lists.
1064 """
1065
1066 targets = {}
1067 for build_file in data['target_build_files']:
1068 for target in data[build_file].get('targets', []):
1069 target_name = gyp.common.QualifiedTarget(build_file,
1070 target['target_name'],
1071 target['toolset'])
1072 if target_name in targets:
1073 raise KeyError, 'Duplicate target definitions for ' + target_name
1074 targets[target_name] = target
1075
1076 return targets
1077
1078
1079 def QualifyDependencies(targets):
1080 """Make dependency links fully-qualified relative to the current directory.
1081
1082 |targets| is a dict mapping fully-qualified target names to their target
1083 dicts. For each target in this dict, keys known to contain dependency
1084 links are examined, and any dependencies referenced will be rewritten
1085 so that they are fully-qualified and relative to the current directory.
1086 All rewritten dependencies are suitable for use as keys to |targets| or a
1087 similar dict.
1088 """
1089
1090 all_dependency_sections = [dep + op
1091 for dep in dependency_sections
1092 for op in ('', '!', '/')]
1093
1094 for target, target_dict in targets.iteritems():
1095 target_build_file = gyp.common.BuildFile(target)
1096 toolset = target_dict['toolset']
1097 for dependency_key in all_dependency_sections:
1098 dependencies = target_dict.get(dependency_key, [])
1099 for index in xrange(0, len(dependencies)):
1100 dep_file, dep_target, dep_toolset = gyp.common.ResolveTarget(
1101 target_build_file, dependencies[index], toolset)
1102 global multiple_toolsets
1103 if not multiple_toolsets:
1104 # Ignore toolset specification in the dependency if it is specified.
1105 dep_toolset = toolset
1106 dependency = gyp.common.QualifiedTarget(dep_file,
1107 dep_target,
1108 dep_toolset)
1109 dependencies[index] = dependency
1110
1111 # Make sure anything appearing in a list other than "dependencies" also
1112 # appears in the "dependencies" list.
1113 if dependency_key != 'dependencies' and \
1114 dependency not in target_dict['dependencies']:
1115 raise KeyError, 'Found ' + dependency + ' in ' + dependency_key + \
1116 ' of ' + target + ', but not in dependencies'
1117
1118
1119 def ExpandWildcardDependencies(targets, data):
1120 """Expands dependencies specified as build_file:*.
1121
1122 For each target in |targets|, examines sections containing links to other
1123 targets. If any such section contains a link of the form build_file:*, it
1124 is taken as a wildcard link, and is expanded to list each target in
1125 build_file. The |data| dict provides access to build file dicts.
1126
1127 Any target that does not wish to be included by wildcard can provide an
1128 optional "suppress_wildcard" key in its target dict. When present and
1129 true, a wildcard dependency link will not include such targets.
1130
1131 All dependency names, including the keys to |targets| and the values in each
1132 dependency list, must be qualified when this function is called.
1133 """
1134
1135 for target, target_dict in targets.iteritems():
1136 toolset = target_dict['toolset']
1137 target_build_file = gyp.common.BuildFile(target)
1138 for dependency_key in dependency_sections:
1139 dependencies = target_dict.get(dependency_key, [])
1140
1141 # Loop this way instead of "for dependency in" or "for index in xrange"
1142 # because the dependencies list will be modified within the loop body.
1143 index = 0
1144 while index < len(dependencies):
1145 (dependency_build_file, dependency_target, dependency_toolset) = \
1146 gyp.common.ParseQualifiedTarget(dependencies[index])
1147 if dependency_target != '*' and dependency_toolset != '*':
1148 # Not a wildcard. Keep it moving.
1149 index = index + 1
1150 continue
1151
1152 if dependency_build_file == target_build_file:
1153 # It's an error for a target to depend on all other targets in
1154 # the same file, because a target cannot depend on itself.
1155 raise KeyError, 'Found wildcard in ' + dependency_key + ' of ' + \
1156 target + ' referring to same build file'
1157
1158 # Take the wildcard out and adjust the index so that the next
1159 # dependency in the list will be processed the next time through the
1160 # loop.
1161 del dependencies[index]
1162 index = index - 1
1163
1164 # Loop through the targets in the other build file, adding them to
1165 # this target's list of dependencies in place of the removed
1166 # wildcard.
1167 dependency_target_dicts = data[dependency_build_file]['targets']
1168 for dependency_target_dict in dependency_target_dicts:
1169 if int(dependency_target_dict.get('suppress_wildcard', False)):
1170 continue
1171 dependency_target_name = dependency_target_dict['target_name']
1172 if (dependency_target != '*' and
1173 dependency_target != dependency_target_name):
1174 continue
1175 dependency_target_toolset = dependency_target_dict['toolset']
1176 if (dependency_toolset != '*' and
1177 dependency_toolset != dependency_target_toolset):
1178 continue
1179 dependency = gyp.common.QualifiedTarget(dependency_build_file,
1180 dependency_target_name,
1181 dependency_target_toolset)
1182 index = index + 1
1183 dependencies.insert(index, dependency)
1184
1185 index = index + 1
1186
1187
1188 class DependencyGraphNode(object):
1189 """
1190
1191 Attributes:
1192 ref: A reference to an object that this DependencyGraphNode represents.
1193 dependencies: List of DependencyGraphNodes on which this one depends.
1194 dependents: List of DependencyGraphNodes that depend on this one.
1195 """
1196
1197 class CircularException(Exception):
1198 pass
1199
1200 def __init__(self, ref):
1201 self.ref = ref
1202 self.dependencies = []
1203 self.dependents = []
1204
1205 def FlattenToList(self):
1206 # flat_list is the sorted list of dependencies - actually, the list items
1207 # are the "ref" attributes of DependencyGraphNodes. Every target will
1208 # appear in flat_list after all of its dependencies, and before all of its
1209 # dependents.
1210 flat_list = []
1211
1212 # in_degree_zeros is the list of DependencyGraphNodes that have no
1213 # dependencies not in flat_list. Initially, it is a copy of the children
1214 # of this node, because when the graph was built, nodes with no
1215 # dependencies were made implicit dependents of the root node.
1216 in_degree_zeros = self.dependents[:]
1217
1218 while in_degree_zeros:
1219 # Nodes in in_degree_zeros have no dependencies not in flat_list, so they
1220 # can be appended to flat_list. Take these nodes out of in_degree_zeros
1221 # as work progresses, so that the next node to process from the list can
1222 # always be accessed at a consistent position.
1223 node = in_degree_zeros.pop(0)
1224 flat_list.append(node.ref)
1225
1226 # Look at dependents of the node just added to flat_list. Some of them
1227 # may now belong in in_degree_zeros.
1228 for node_dependent in node.dependents:
1229 is_in_degree_zero = True
1230 for node_dependent_dependency in node_dependent.dependencies:
1231 if not node_dependent_dependency.ref in flat_list:
1232 # The dependent one or more dependencies not in flat_list. There
1233 # will be more chances to add it to flat_list when examining
1234 # it again as a dependent of those other dependencies, provided
1235 # that there are no cycles.
1236 is_in_degree_zero = False
1237 break
1238
1239 if is_in_degree_zero:
1240 # All of the dependent's dependencies are already in flat_list. Add
1241 # it to in_degree_zeros where it will be processed in a future
1242 # iteration of the outer loop.
1243 in_degree_zeros.append(node_dependent)
1244
1245 return flat_list
1246
1247 def DirectDependencies(self, dependencies=None):
1248 """Returns a list of just direct dependencies."""
1249 if dependencies == None:
1250 dependencies = []
1251
1252 for dependency in self.dependencies:
1253 # Check for None, corresponding to the root node.
1254 if dependency.ref != None and dependency.ref not in dependencies:
1255 dependencies.append(dependency.ref)
1256
1257 return dependencies
1258
1259 def _AddImportedDependencies(self, targets, dependencies=None):
1260 """Given a list of direct dependencies, adds indirect dependencies that
1261 other dependencies have declared to export their settings.
1262
1263 This method does not operate on self. Rather, it operates on the list
1264 of dependencies in the |dependencies| argument. For each dependency in
1265 that list, if any declares that it exports the settings of one of its
1266 own dependencies, those dependencies whose settings are "passed through"
1267 are added to the list. As new items are added to the list, they too will
1268 be processed, so it is possible to import settings through multiple levels
1269 of dependencies.
1270
1271 This method is not terribly useful on its own, it depends on being
1272 "primed" with a list of direct dependencies such as one provided by
1273 DirectDependencies. DirectAndImportedDependencies is intended to be the
1274 public entry point.
1275 """
1276
1277 if dependencies == None:
1278 dependencies = []
1279
1280 index = 0
1281 while index < len(dependencies):
1282 dependency = dependencies[index]
1283 dependency_dict = targets[dependency]
1284 # Add any dependencies whose settings should be imported to the list
1285 # if not already present. Newly-added items will be checked for
1286 # their own imports when the list iteration reaches them.
1287 # Rather than simply appending new items, insert them after the
1288 # dependency that exported them. This is done to more closely match
1289 # the depth-first method used by DeepDependencies.
1290 add_index = 1
1291 for imported_dependency in \
1292 dependency_dict.get('export_dependent_settings', []):
1293 if imported_dependency not in dependencies:
1294 dependencies.insert(index + add_index, imported_dependency)
1295 add_index = add_index + 1
1296 index = index + 1
1297
1298 return dependencies
1299
1300 def DirectAndImportedDependencies(self, targets, dependencies=None):
1301 """Returns a list of a target's direct dependencies and all indirect
1302 dependencies that a dependency has advertised settings should be exported
1303 through the dependency for.
1304 """
1305
1306 dependencies = self.DirectDependencies(dependencies)
1307 return self._AddImportedDependencies(targets, dependencies)
1308
1309 def DeepDependencies(self, dependencies=None):
1310 """Returns a list of all of a target's dependencies, recursively."""
1311 if dependencies == None:
1312 dependencies = []
1313
1314 for dependency in self.dependencies:
1315 # Check for None, corresponding to the root node.
1316 if dependency.ref != None and dependency.ref not in dependencies:
1317 dependencies.append(dependency.ref)
1318 dependency.DeepDependencies(dependencies)
1319
1320 return dependencies
1321
1322 def LinkDependencies(self, targets, dependencies=None, initial=True):
1323 """Returns a list of dependency targets that are linked into this target.
1324
1325 This function has a split personality, depending on the setting of
1326 |initial|. Outside callers should always leave |initial| at its default
1327 setting.
1328
1329 When adding a target to the list of dependencies, this function will
1330 recurse into itself with |initial| set to False, to collect depenedencies
1331 that are linked into the linkable target for which the list is being built.
1332 """
1333 if dependencies == None:
1334 dependencies = []
1335
1336 # Check for None, corresponding to the root node.
1337 if self.ref == None:
1338 return dependencies
1339
1340 # It's kind of sucky that |targets| has to be passed into this function,
1341 # but that's presently the easiest way to access the target dicts so that
1342 # this function can find target types.
1343
1344 if not 'target_name' in targets[self.ref]:
1345 raise Exception("Missing 'target_name' field in target.")
1346
1347 try:
1348 target_type = targets[self.ref]['type']
1349 except KeyError, e:
1350 raise Exception("Missing 'type' field in target %s" %
1351 targets[self.ref]['target_name'])
1352
1353 is_linkable = target_type in linkable_types
1354
1355 if initial and not is_linkable:
1356 # If this is the first target being examined and it's not linkable,
1357 # return an empty list of link dependencies, because the link
1358 # dependencies are intended to apply to the target itself (initial is
1359 # True) and this target won't be linked.
1360 return dependencies
1361
1362 # Executables and loadable modules are already fully and finally linked.
1363 # Nothing else can be a link dependency of them, there can only be
1364 # dependencies in the sense that a dependent target might run an
1365 # executable or load the loadable_module.
1366 if not initial and target_type in ('executable', 'loadable_module'):
1367 return dependencies
1368
1369 # The target is linkable, add it to the list of link dependencies.
1370 if self.ref not in dependencies:
1371 if target_type != 'none':
1372 # Special case: "none" type targets don't produce any linkable products
1373 # and shouldn't be exposed as link dependencies, although dependencies
1374 # of "none" type targets may still be link dependencies.
1375 dependencies.append(self.ref)
1376 if initial or not is_linkable:
1377 # If this is a subsequent target and it's linkable, don't look any
1378 # further for linkable dependencies, as they'll already be linked into
1379 # this target linkable. Always look at dependencies of the initial
1380 # target, and always look at dependencies of non-linkables.
1381 for dependency in self.dependencies:
1382 dependency.LinkDependencies(targets, dependencies, False)
1383
1384 return dependencies
1385
1386
1387 def BuildDependencyList(targets):
1388 # Create a DependencyGraphNode for each target. Put it into a dict for easy
1389 # access.
1390 dependency_nodes = {}
1391 for target, spec in targets.iteritems():
1392 if not target in dependency_nodes:
1393 dependency_nodes[target] = DependencyGraphNode(target)
1394
1395 # Set up the dependency links. Targets that have no dependencies are treated
1396 # as dependent on root_node.
1397 root_node = DependencyGraphNode(None)
1398 for target, spec in targets.iteritems():
1399 target_node = dependency_nodes[target]
1400 target_build_file = gyp.common.BuildFile(target)
1401 if not 'dependencies' in spec or len(spec['dependencies']) == 0:
1402 target_node.dependencies = [root_node]
1403 root_node.dependents.append(target_node)
1404 else:
1405 dependencies = spec['dependencies']
1406 for index in xrange(0, len(dependencies)):
1407 try:
1408 dependency = dependencies[index]
1409 dependency_node = dependency_nodes[dependency]
1410 target_node.dependencies.append(dependency_node)
1411 dependency_node.dependents.append(target_node)
1412 except KeyError, e:
1413 gyp.common.ExceptionAppend(e,
1414 'while trying to load target %s' % target)
1415 raise
1416
1417 flat_list = root_node.FlattenToList()
1418
1419 # If there's anything left unvisited, there must be a circular dependency
1420 # (cycle). If you need to figure out what's wrong, look for elements of
1421 # targets that are not in flat_list.
1422 if len(flat_list) != len(targets):
1423 raise DependencyGraphNode.CircularException, \
1424 'Some targets not reachable, cycle in dependency graph detected'
1425
1426 return [dependency_nodes, flat_list]
1427
1428
1429 def VerifyNoGYPFileCircularDependencies(targets):
1430 # Create a DependencyGraphNode for each gyp file containing a target. Put
1431 # it into a dict for easy access.
1432 dependency_nodes = {}
1433 for target in targets.iterkeys():
1434 build_file = gyp.common.BuildFile(target)
1435 if not build_file in dependency_nodes:
1436 dependency_nodes[build_file] = DependencyGraphNode(build_file)
1437
1438 # Set up the dependency links.
1439 for target, spec in targets.iteritems():
1440 build_file = gyp.common.BuildFile(target)
1441 build_file_node = dependency_nodes[build_file]
1442 target_dependencies = spec.get('dependencies', [])
1443 for dependency in target_dependencies:
1444 try:
1445 dependency_build_file = gyp.common.BuildFile(dependency)
1446 if dependency_build_file == build_file:
1447 # A .gyp file is allowed to refer back to itself.
1448 continue
1449 dependency_node = dependency_nodes[dependency_build_file]
1450 if dependency_node not in build_file_node.dependencies:
1451 build_file_node.dependencies.append(dependency_node)
1452 dependency_node.dependents.append(build_file_node)
1453 except KeyError, e:
1454 gyp.common.ExceptionAppend(
1455 e, 'while computing dependencies of .gyp file %s' % build_file)
1456 raise
1457
1458 # Files that have no dependencies are treated as dependent on root_node.
1459 root_node = DependencyGraphNode(None)
1460 for build_file_node in dependency_nodes.itervalues():
1461 if len(build_file_node.dependencies) == 0:
1462 build_file_node.dependencies.append(root_node)
1463 root_node.dependents.append(build_file_node)
1464
1465 flat_list = root_node.FlattenToList()
1466
1467 # If there's anything left unvisited, there must be a circular dependency
1468 # (cycle).
1469 if len(flat_list) != len(dependency_nodes):
1470 bad_files = []
1471 for file in dependency_nodes.iterkeys():
1472 if not file in flat_list:
1473 bad_files.append(file)
1474 raise DependencyGraphNode.CircularException, \
1475 'Some files not reachable, cycle in .gyp file dependency graph ' + \
1476 'detected involving some or all of: ' + \
1477 ' '.join(bad_files)
1478
1479
1480 def DoDependentSettings(key, flat_list, targets, dependency_nodes):
1481 # key should be one of all_dependent_settings, direct_dependent_settings,
1482 # or link_settings.
1483
1484 for target in flat_list:
1485 target_dict = targets[target]
1486 build_file = gyp.common.BuildFile(target)
1487
1488 if key == 'all_dependent_settings':
1489 dependencies = dependency_nodes[target].DeepDependencies()
1490 elif key == 'direct_dependent_settings':
1491 dependencies = \
1492 dependency_nodes[target].DirectAndImportedDependencies(targets)
1493 elif key == 'link_settings':
1494 dependencies = dependency_nodes[target].LinkDependencies(targets)
1495 else:
1496 raise KeyError, "DoDependentSettings doesn't know how to determine " + \
1497 'dependencies for ' + key
1498
1499 for dependency in dependencies:
1500 dependency_dict = targets[dependency]
1501 if not key in dependency_dict:
1502 continue
1503 dependency_build_file = gyp.common.BuildFile(dependency)
1504 MergeDicts(target_dict, dependency_dict[key],
1505 build_file, dependency_build_file)
1506
1507
1508 def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes,
1509 sort_dependencies):
1510 # Recompute target "dependencies" properties. For each static library
1511 # target, remove "dependencies" entries referring to other static libraries,
1512 # unless the dependency has the "hard_dependency" attribute set. For each
1513 # linkable target, add a "dependencies" entry referring to all of the
1514 # target's computed list of link dependencies (including static libraries
1515 # if no such entry is already present.
1516 for target in flat_list:
1517 target_dict = targets[target]
1518 target_type = target_dict['type']
1519
1520 if target_type == 'static_library':
1521 if not 'dependencies' in target_dict:
1522 continue
1523
1524 target_dict['dependencies_original'] = target_dict.get(
1525 'dependencies', [])[:]
1526
1527 # A static library should not depend on another static library unless
1528 # the dependency relationship is "hard," which should only be done when
1529 # a dependent relies on some side effect other than just the build
1530 # product, like a rule or action output. Further, if a target has a
1531 # non-hard dependency, but that dependency exports a hard dependency,
1532 # the non-hard dependency can safely be removed, but the exported hard
1533 # dependency must be added to the target to keep the same dependency
1534 # ordering.
1535 dependencies = \
1536 dependency_nodes[target].DirectAndImportedDependencies(targets)
1537 index = 0
1538 while index < len(dependencies):
1539 dependency = dependencies[index]
1540 dependency_dict = targets[dependency]
1541
1542 # Remove every non-hard static library dependency and remove every
1543 # non-static library dependency that isn't a direct dependency.
1544 if (dependency_dict['type'] == 'static_library' and \
1545 not dependency_dict.get('hard_dependency', False)) or \
1546 (dependency_dict['type'] != 'static_library' and \
1547 not dependency in target_dict['dependencies']):
1548 # Take the dependency out of the list, and don't increment index
1549 # because the next dependency to analyze will shift into the index
1550 # formerly occupied by the one being removed.
1551 del dependencies[index]
1552 else:
1553 index = index + 1
1554
1555 # Update the dependencies. If the dependencies list is empty, it's not
1556 # needed, so unhook it.
1557 if len(dependencies) > 0:
1558 target_dict['dependencies'] = dependencies
1559 else:
1560 del target_dict['dependencies']
1561
1562 elif target_type in linkable_types:
1563 # Get a list of dependency targets that should be linked into this
1564 # target. Add them to the dependencies list if they're not already
1565 # present.
1566
1567 link_dependencies = dependency_nodes[target].LinkDependencies(targets)
1568 for dependency in link_dependencies:
1569 if dependency == target:
1570 continue
1571 if not 'dependencies' in target_dict:
1572 target_dict['dependencies'] = []
1573 if not dependency in target_dict['dependencies']:
1574 target_dict['dependencies'].append(dependency)
1575 # Sort the dependencies list in the order from dependents to dependencies.
1576 # e.g. If A and B depend on C and C depends on D, sort them in A, B, C, D.
1577 # Note: flat_list is already sorted in the order from dependencies to
1578 # dependents.
1579 if sort_dependencies and 'dependencies' in target_dict:
1580 target_dict['dependencies'] = [dep for dep in reversed(flat_list)
1581 if dep in target_dict['dependencies']]
1582
1583
1584 # Initialize this here to speed up MakePathRelative.
1585 exception_re = re.compile(r'''["']?[-/$<>]''')
1586
1587
1588 def MakePathRelative(to_file, fro_file, item):
1589 # If item is a relative path, it's relative to the build file dict that it's
1590 # coming from. Fix it up to make it relative to the build file dict that
1591 # it's going into.
1592 # Exception: any |item| that begins with these special characters is
1593 # returned without modification.
1594 # / Used when a path is already absolute (shortcut optimization;
1595 # such paths would be returned as absolute anyway)
1596 # $ Used for build environment variables
1597 # - Used for some build environment flags (such as -lapr-1 in a
1598 # "libraries" section)
1599 # < Used for our own variable and command expansions (see ExpandVariables)
1600 # > Used for our own variable and command expansions (see ExpandVariables)
1601 #
1602 # "/' Used when a value is quoted. If these are present, then we
1603 # check the second character instead.
1604 #
1605 if to_file == fro_file or exception_re.match(item):
1606 return item
1607 else:
1608 # TODO(dglazkov) The backslash/forward-slash replacement at the end is a
1609 # temporary measure. This should really be addressed by keeping all paths
1610 # in POSIX until actual project generation.
1611 ret = os.path.normpath(os.path.join(
1612 gyp.common.RelativePath(os.path.dirname(fro_file),
1613 os.path.dirname(to_file)),
1614 item)).replace('\\', '/')
1615 if item[-1] == '/':
1616 ret += '/'
1617 return ret
1618
1619 def MergeLists(to, fro, to_file, fro_file, is_paths=False, append=True):
1620 def is_hashable(x):
1621 try:
1622 hash(x)
1623 except TypeError:
1624 return False
1625 return True
1626 # If x is hashable, returns whether x is in s. Else returns whether x is in l.
1627 def is_in_set_or_list(x, s, l):
1628 if is_hashable(x):
1629 return x in s
1630 return x in l
1631
1632 prepend_index = 0
1633
1634 # Make membership testing of hashables in |to| (in particular, strings)
1635 # faster.
1636 hashable_to_set = set([x for x in to if is_hashable(x)])
1637
1638 for item in fro:
1639 singleton = False
1640 if isinstance(item, str) or isinstance(item, int):
1641 # The cheap and easy case.
1642 if is_paths:
1643 to_item = MakePathRelative(to_file, fro_file, item)
1644 else:
1645 to_item = item
1646
1647 if not isinstance(item, str) or not item.startswith('-'):
1648 # Any string that doesn't begin with a "-" is a singleton - it can
1649 # only appear once in a list, to be enforced by the list merge append
1650 # or prepend.
1651 singleton = True
1652 elif isinstance(item, dict):
1653 # Make a copy of the dictionary, continuing to look for paths to fix.
1654 # The other intelligent aspects of merge processing won't apply because
1655 # item is being merged into an empty dict.
1656 to_item = {}
1657 MergeDicts(to_item, item, to_file, fro_file)
1658 elif isinstance(item, list):
1659 # Recurse, making a copy of the list. If the list contains any
1660 # descendant dicts, path fixing will occur. Note that here, custom
1661 # values for is_paths and append are dropped; those are only to be
1662 # applied to |to| and |fro|, not sublists of |fro|. append shouldn't
1663 # matter anyway because the new |to_item| list is empty.
1664 to_item = []
1665 MergeLists(to_item, item, to_file, fro_file)
1666 else:
1667 raise TypeError, \
1668 'Attempt to merge list item of unsupported type ' + \
1669 item.__class__.__name__
1670
1671 if append:
1672 # If appending a singleton that's already in the list, don't append.
1673 # This ensures that the earliest occurrence of the item will stay put.
1674 if not singleton or not is_in_set_or_list(to_item, hashable_to_set, to):
1675 to.append(to_item)
1676 if is_hashable(to_item):
1677 hashable_to_set.add(to_item)
1678 else:
1679 # If prepending a singleton that's already in the list, remove the
1680 # existing instance and proceed with the prepend. This ensures that the
1681 # item appears at the earliest possible position in the list.
1682 while singleton and to_item in to:
1683 to.remove(to_item)
1684
1685 # Don't just insert everything at index 0. That would prepend the new
1686 # items to the list in reverse order, which would be an unwelcome
1687 # surprise.
1688 to.insert(prepend_index, to_item)
1689 if is_hashable(to_item):
1690 hashable_to_set.add(to_item)
1691 prepend_index = prepend_index + 1
1692
1693
1694 def MergeDicts(to, fro, to_file, fro_file):
1695 # I wanted to name the parameter "from" but it's a Python keyword...
1696 for k, v in fro.iteritems():
1697 # It would be nice to do "if not k in to: to[k] = v" but that wouldn't give
1698 # copy semantics. Something else may want to merge from the |fro| dict
1699 # later, and having the same dict ref pointed to twice in the tree isn't
1700 # what anyone wants considering that the dicts may subsequently be
1701 # modified.
1702 if k in to:
1703 bad_merge = False
1704 if isinstance(v, str) or isinstance(v, int):
1705 if not (isinstance(to[k], str) or isinstance(to[k], int)):
1706 bad_merge = True
1707 elif v.__class__ != to[k].__class__:
1708 bad_merge = True
1709
1710 if bad_merge:
1711 raise TypeError, \
1712 'Attempt to merge dict value of type ' + v.__class__.__name__ + \
1713 ' into incompatible type ' + to[k].__class__.__name__ + \
1714 ' for key ' + k
1715 if isinstance(v, str) or isinstance(v, int):
1716 # Overwrite the existing value, if any. Cheap and easy.
1717 is_path = IsPathSection(k)
1718 if is_path:
1719 to[k] = MakePathRelative(to_file, fro_file, v)
1720 else:
1721 to[k] = v
1722 elif isinstance(v, dict):
1723 # Recurse, guaranteeing copies will be made of objects that require it.
1724 if not k in to:
1725 to[k] = {}
1726 MergeDicts(to[k], v, to_file, fro_file)
1727 elif isinstance(v, list):
1728 # Lists in dicts can be merged with different policies, depending on
1729 # how the key in the "from" dict (k, the from-key) is written.
1730 #
1731 # If the from-key has ...the to-list will have this action
1732 # this character appended:... applied when receiving the from-list:
1733 # = replace
1734 # + prepend
1735 # ? set, only if to-list does not yet exist
1736 # (none) append
1737 #
1738 # This logic is list-specific, but since it relies on the associated
1739 # dict key, it's checked in this dict-oriented function.
1740 ext = k[-1]
1741 append = True
1742 if ext == '=':
1743 list_base = k[:-1]
1744 lists_incompatible = [list_base, list_base + '?']
1745 to[list_base] = []
1746 elif ext == '+':
1747 list_base = k[:-1]
1748 lists_incompatible = [list_base + '=', list_base + '?']
1749 append = False
1750 elif ext == '?':
1751 list_base = k[:-1]
1752 lists_incompatible = [list_base, list_base + '=', list_base + '+']
1753 else:
1754 list_base = k
1755 lists_incompatible = [list_base + '=', list_base + '?']
1756
1757 # Some combinations of merge policies appearing together are meaningless.
1758 # It's stupid to replace and append simultaneously, for example. Append
1759 # and prepend are the only policies that can coexist.
1760 for list_incompatible in lists_incompatible:
1761 if list_incompatible in fro:
1762 raise KeyError, 'Incompatible list policies ' + k + ' and ' + \
1763 list_incompatible
1764
1765 if list_base in to:
1766 if ext == '?':
1767 # If the key ends in "?", the list will only be merged if it doesn't
1768 # already exist.
1769 continue
1770 if not isinstance(to[list_base], list):
1771 # This may not have been checked above if merging in a list with an
1772 # extension character.
1773 raise TypeError, \
1774 'Attempt to merge dict value of type ' + v.__class__.__name__ + \
1775 ' into incompatible type ' + to[list_base].__class__.__name__ + \
1776 ' for key ' + list_base + '(' + k + ')'
1777 else:
1778 to[list_base] = []
1779
1780 # Call MergeLists, which will make copies of objects that require it.
1781 # MergeLists can recurse back into MergeDicts, although this will be
1782 # to make copies of dicts (with paths fixed), there will be no
1783 # subsequent dict "merging" once entering a list because lists are
1784 # always replaced, appended to, or prepended to.
1785 is_paths = IsPathSection(list_base)
1786 MergeLists(to[list_base], v, to_file, fro_file, is_paths, append)
1787 else:
1788 raise TypeError, \
1789 'Attempt to merge dict value of unsupported type ' + \
1790 v.__class__.__name__ + ' for key ' + k
1791
1792
1793 def MergeConfigWithInheritance(new_configuration_dict, build_file,
1794 target_dict, configuration, visited):
1795 # Skip if previously visted.
1796 if configuration in visited:
1797 return
1798
1799 # Look at this configuration.
1800 configuration_dict = target_dict['configurations'][configuration]
1801
1802 # Merge in parents.
1803 for parent in configuration_dict.get('inherit_from', []):
1804 MergeConfigWithInheritance(new_configuration_dict, build_file,
1805 target_dict, parent, visited + [configuration])
1806
1807 # Merge it into the new config.
1808 MergeDicts(new_configuration_dict, configuration_dict,
1809 build_file, build_file)
1810
1811 # Drop abstract.
1812 if 'abstract' in new_configuration_dict:
1813 del new_configuration_dict['abstract']
1814
1815
1816 def SetUpConfigurations(target, target_dict):
1817 global non_configuration_keys
1818 # key_suffixes is a list of key suffixes that might appear on key names.
1819 # These suffixes are handled in conditional evaluations (for =, +, and ?)
1820 # and rules/exclude processing (for ! and /). Keys with these suffixes
1821 # should be treated the same as keys without.
1822 key_suffixes = ['=', '+', '?', '!', '/']
1823
1824 build_file = gyp.common.BuildFile(target)
1825
1826 # Provide a single configuration by default if none exists.
1827 # TODO(mark): Signal an error if default_configurations exists but
1828 # configurations does not.
1829 if not 'configurations' in target_dict:
1830 target_dict['configurations'] = {'Default': {}}
1831 if not 'default_configuration' in target_dict:
1832 concrete = [i for i in target_dict['configurations'].keys()
1833 if not target_dict['configurations'][i].get('abstract')]
1834 target_dict['default_configuration'] = sorted(concrete)[0]
1835
1836 for configuration in target_dict['configurations'].keys():
1837 old_configuration_dict = target_dict['configurations'][configuration]
1838 # Skip abstract configurations (saves work only).
1839 if old_configuration_dict.get('abstract'):
1840 continue
1841 # Configurations inherit (most) settings from the enclosing target scope.
1842 # Get the inheritance relationship right by making a copy of the target
1843 # dict.
1844 new_configuration_dict = copy.deepcopy(target_dict)
1845
1846 # Take out the bits that don't belong in a "configurations" section.
1847 # Since configuration setup is done before conditional, exclude, and rules
1848 # processing, be careful with handling of the suffix characters used in
1849 # those phases.
1850 delete_keys = []
1851 for key in new_configuration_dict:
1852 key_ext = key[-1:]
1853 if key_ext in key_suffixes:
1854 key_base = key[:-1]
1855 else:
1856 key_base = key
1857 if key_base in non_configuration_keys:
1858 delete_keys.append(key)
1859
1860 for key in delete_keys:
1861 del new_configuration_dict[key]
1862
1863 # Merge in configuration (with all its parents first).
1864 MergeConfigWithInheritance(new_configuration_dict, build_file,
1865 target_dict, configuration, [])
1866
1867 # Put the new result back into the target dict as a configuration.
1868 target_dict['configurations'][configuration] = new_configuration_dict
1869
1870 # Now drop all the abstract ones.
1871 for configuration in target_dict['configurations'].keys():
1872 old_configuration_dict = target_dict['configurations'][configuration]
1873 if old_configuration_dict.get('abstract'):
1874 del target_dict['configurations'][configuration]
1875
1876 # Now that all of the target's configurations have been built, go through
1877 # the target dict's keys and remove everything that's been moved into a
1878 # "configurations" section.
1879 delete_keys = []
1880 for key in target_dict:
1881 key_ext = key[-1:]
1882 if key_ext in key_suffixes:
1883 key_base = key[:-1]
1884 else:
1885 key_base = key
1886 if not key_base in non_configuration_keys:
1887 delete_keys.append(key)
1888 for key in delete_keys:
1889 del target_dict[key]
1890
1891 # Check the configurations to see if they contain invalid keys.
1892 for configuration in target_dict['configurations'].keys():
1893 configuration_dict = target_dict['configurations'][configuration]
1894 for key in configuration_dict.keys():
1895 if key in invalid_configuration_keys:
1896 raise KeyError, ('%s not allowed in the %s configuration, found in '
1897 'target %s' % (key, configuration, target))
1898
1899
1900
1901 def ProcessListFiltersInDict(name, the_dict):
1902 """Process regular expression and exclusion-based filters on lists.
1903
1904 An exclusion list is in a dict key named with a trailing "!", like
1905 "sources!". Every item in such a list is removed from the associated
1906 main list, which in this example, would be "sources". Removed items are
1907 placed into a "sources_excluded" list in the dict.
1908
1909 Regular expression (regex) filters are contained in dict keys named with a
1910 trailing "/", such as "sources/" to operate on the "sources" list. Regex
1911 filters in a dict take the form:
1912 'sources/': [ ['exclude', '_(linux|mac|win)\\.cc$'],
1913 ['include', '_mac\\.cc$'] ],
1914 The first filter says to exclude all files ending in _linux.cc, _mac.cc, and
1915 _win.cc. The second filter then includes all files ending in _mac.cc that
1916 are now or were once in the "sources" list. Items matching an "exclude"
1917 filter are subject to the same processing as would occur if they were listed
1918 by name in an exclusion list (ending in "!"). Items matching an "include"
1919 filter are brought back into the main list if previously excluded by an
1920 exclusion list or exclusion regex filter. Subsequent matching "exclude"
1921 patterns can still cause items to be excluded after matching an "include".
1922 """
1923
1924 # Look through the dictionary for any lists whose keys end in "!" or "/".
1925 # These are lists that will be treated as exclude lists and regular
1926 # expression-based exclude/include lists. Collect the lists that are
1927 # needed first, looking for the lists that they operate on, and assemble
1928 # then into |lists|. This is done in a separate loop up front, because
1929 # the _included and _excluded keys need to be added to the_dict, and that
1930 # can't be done while iterating through it.
1931
1932 lists = []
1933 del_lists = []
1934 for key, value in the_dict.iteritems():
1935 operation = key[-1]
1936 if operation != '!' and operation != '/':
1937 continue
1938
1939 if not isinstance(value, list):
1940 raise ValueError, name + ' key ' + key + ' must be list, not ' + \
1941 value.__class__.__name__
1942
1943 list_key = key[:-1]
1944 if list_key not in the_dict:
1945 # This happens when there's a list like "sources!" but no corresponding
1946 # "sources" list. Since there's nothing for it to operate on, queue up
1947 # the "sources!" list for deletion now.
1948 del_lists.append(key)
1949 continue
1950
1951 if not isinstance(the_dict[list_key], list):
1952 raise ValueError, name + ' key ' + list_key + \
1953 ' must be list, not ' + \
1954 value.__class__.__name__ + ' when applying ' + \
1955 {'!': 'exclusion', '/': 'regex'}[operation]
1956
1957 if not list_key in lists:
1958 lists.append(list_key)
1959
1960 # Delete the lists that are known to be unneeded at this point.
1961 for del_list in del_lists:
1962 del the_dict[del_list]
1963
1964 for list_key in lists:
1965 the_list = the_dict[list_key]
1966
1967 # Initialize the list_actions list, which is parallel to the_list. Each
1968 # item in list_actions identifies whether the corresponding item in
1969 # the_list should be excluded, unconditionally preserved (included), or
1970 # whether no exclusion or inclusion has been applied. Items for which
1971 # no exclusion or inclusion has been applied (yet) have value -1, items
1972 # excluded have value 0, and items included have value 1. Includes and
1973 # excludes override previous actions. All items in list_actions are
1974 # initialized to -1 because no excludes or includes have been processed
1975 # yet.
1976 list_actions = list((-1,) * len(the_list))
1977
1978 exclude_key = list_key + '!'
1979 if exclude_key in the_dict:
1980 for exclude_item in the_dict[exclude_key]:
1981 for index in xrange(0, len(the_list)):
1982 if exclude_item == the_list[index]:
1983 # This item matches the exclude_item, so set its action to 0
1984 # (exclude).
1985 list_actions[index] = 0
1986
1987 # The "whatever!" list is no longer needed, dump it.
1988 del the_dict[exclude_key]
1989
1990 regex_key = list_key + '/'
1991 if regex_key in the_dict:
1992 for regex_item in the_dict[regex_key]:
1993 [action, pattern] = regex_item
1994 pattern_re = re.compile(pattern)
1995
1996 if action == 'exclude':
1997 # This item matches an exclude regex, so set its value to 0 (exclude).
1998 action_value = 0
1999 elif action == 'include':
2000 # This item matches an include regex, so set its value to 1 (include).
2001 action_value = 1
2002 else:
2003 # This is an action that doesn't make any sense.
2004 raise ValueError, 'Unrecognized action ' + action + ' in ' + name + \
2005 ' key ' + key
2006
2007 for index in xrange(0, len(the_list)):
2008 list_item = the_list[index]
2009 if list_actions[index] == action_value:
2010 # Even if the regex matches, nothing will change so continue (regex
2011 # searches are expensive).
2012 continue
2013 if pattern_re.search(list_item):
2014 # Regular expression match.
2015 list_actions[index] = action_value
2016
2017 # The "whatever/" list is no longer needed, dump it.
2018 del the_dict[regex_key]
2019
2020 # Add excluded items to the excluded list.
2021 #
2022 # Note that exclude_key ("sources!") is different from excluded_key
2023 # ("sources_excluded"). The exclude_key list is input and it was already
2024 # processed and deleted; the excluded_key list is output and it's about
2025 # to be created.
2026 excluded_key = list_key + '_excluded'
2027 if excluded_key in the_dict:
2028 raise KeyError, \
2029 name + ' key ' + excluded_key + ' must not be present prior ' + \
2030 ' to applying exclusion/regex filters for ' + list_key
2031
2032 excluded_list = []
2033
2034 # Go backwards through the list_actions list so that as items are deleted,
2035 # the indices of items that haven't been seen yet don't shift. That means
2036 # that things need to be prepended to excluded_list to maintain them in the
2037 # same order that they existed in the_list.
2038 for index in xrange(len(list_actions) - 1, -1, -1):
2039 if list_actions[index] == 0:
2040 # Dump anything with action 0 (exclude). Keep anything with action 1
2041 # (include) or -1 (no include or exclude seen for the item).
2042 excluded_list.insert(0, the_list[index])
2043 del the_list[index]
2044
2045 # If anything was excluded, put the excluded list into the_dict at
2046 # excluded_key.
2047 if len(excluded_list) > 0:
2048 the_dict[excluded_key] = excluded_list
2049
2050 # Now recurse into subdicts and lists that may contain dicts.
2051 for key, value in the_dict.iteritems():
2052 if isinstance(value, dict):
2053 ProcessListFiltersInDict(key, value)
2054 elif isinstance(value, list):
2055 ProcessListFiltersInList(key, value)
2056
2057
2058 def ProcessListFiltersInList(name, the_list):
2059 for item in the_list:
2060 if isinstance(item, dict):
2061 ProcessListFiltersInDict(name, item)
2062 elif isinstance(item, list):
2063 ProcessListFiltersInList(name, item)
2064
2065
2066 def ValidateRulesInTarget(target, target_dict, extra_sources_for_rules):
2067 """Ensures that the rules sections in target_dict are valid and consistent,
2068 and determines which sources they apply to.
2069
2070 Arguments:
2071 target: string, name of target.
2072 target_dict: dict, target spec containing "rules" and "sources" lists.
2073 extra_sources_for_rules: a list of keys to scan for rule matches in
2074 addition to 'sources'.
2075 """
2076
2077 # Dicts to map between values found in rules' 'rule_name' and 'extension'
2078 # keys and the rule dicts themselves.
2079 rule_names = {}
2080 rule_extensions = {}
2081
2082 rules = target_dict.get('rules', [])
2083 for rule in rules:
2084 # Make sure that there's no conflict among rule names and extensions.
2085 rule_name = rule['rule_name']
2086 if rule_name in rule_names:
2087 raise KeyError, 'rule %s exists in duplicate, target %s' % \
2088 (rule_name, target)
2089 rule_names[rule_name] = rule
2090
2091 rule_extension = rule['extension']
2092 if rule_extension in rule_extensions:
2093 raise KeyError, ('extension %s associated with multiple rules, ' +
2094 'target %s rules %s and %s') % \
2095 (rule_extension, target,
2096 rule_extensions[rule_extension]['rule_name'],
2097 rule_name)
2098 rule_extensions[rule_extension] = rule
2099
2100 # Make sure rule_sources isn't already there. It's going to be
2101 # created below if needed.
2102 if 'rule_sources' in rule:
2103 raise KeyError, \
2104 'rule_sources must not exist in input, target %s rule %s' % \
2105 (target, rule_name)
2106 extension = rule['extension']
2107
2108 rule_sources = []
2109 source_keys = ['sources']
2110 source_keys.extend(extra_sources_for_rules)
2111 for source_key in source_keys:
2112 for source in target_dict.get(source_key, []):
2113 (source_root, source_extension) = os.path.splitext(source)
2114 if source_extension.startswith('.'):
2115 source_extension = source_extension[1:]
2116 if source_extension == extension:
2117 rule_sources.append(source)
2118
2119 if len(rule_sources) > 0:
2120 rule['rule_sources'] = rule_sources
2121
2122
2123 def ValidateActionsInTarget(target, target_dict, build_file):
2124 '''Validates the inputs to the actions in a target.'''
2125 target_name = target_dict.get('target_name')
2126 actions = target_dict.get('actions', [])
2127 for action in actions:
2128 action_name = action.get('action_name')
2129 if not action_name:
2130 raise Exception("Anonymous action in target %s. "
2131 "An action must have an 'action_name' field." %
2132 target_name)
2133 inputs = action.get('inputs', [])
2134
2135
2136 def ValidateRunAsInTarget(target, target_dict, build_file):
2137 target_name = target_dict.get('target_name')
2138 run_as = target_dict.get('run_as')
2139 if not run_as:
2140 return
2141 if not isinstance(run_as, dict):
2142 raise Exception("The 'run_as' in target %s from file %s should be a "
2143 "dictionary." %
2144 (target_name, build_file))
2145 action = run_as.get('action')
2146 if not action:
2147 raise Exception("The 'run_as' in target %s from file %s must have an "
2148 "'action' section." %
2149 (target_name, build_file))
2150 if not isinstance(action, list):
2151 raise Exception("The 'action' for 'run_as' in target %s from file %s "
2152 "must be a list." %
2153 (target_name, build_file))
2154 working_directory = run_as.get('working_directory')
2155 if working_directory and not isinstance(working_directory, str):
2156 raise Exception("The 'working_directory' for 'run_as' in target %s "
2157 "in file %s should be a string." %
2158 (target_name, build_file))
2159 environment = run_as.get('environment')
2160 if environment and not isinstance(environment, dict):
2161 raise Exception("The 'environment' for 'run_as' in target %s "
2162 "in file %s should be a dictionary." %
2163 (target_name, build_file))
2164
2165
2166 def TurnIntIntoStrInDict(the_dict):
2167 """Given dict the_dict, recursively converts all integers into strings.
2168 """
2169 # Use items instead of iteritems because there's no need to try to look at
2170 # reinserted keys and their associated values.
2171 for k, v in the_dict.items():
2172 if isinstance(v, int):
2173 v = str(v)
2174 the_dict[k] = v
2175 elif isinstance(v, dict):
2176 TurnIntIntoStrInDict(v)
2177 elif isinstance(v, list):
2178 TurnIntIntoStrInList(v)
2179
2180 if isinstance(k, int):
2181 the_dict[str(k)] = v
2182 del the_dict[k]
2183
2184
2185 def TurnIntIntoStrInList(the_list):
2186 """Given list the_list, recursively converts all integers into strings.
2187 """
2188 for index in xrange(0, len(the_list)):
2189 item = the_list[index]
2190 if isinstance(item, int):
2191 the_list[index] = str(item)
2192 elif isinstance(item, dict):
2193 TurnIntIntoStrInDict(item)
2194 elif isinstance(item, list):
2195 TurnIntIntoStrInList(item)
2196
2197
2198 def VerifyNoCollidingTargets(targets):
2199 """Verify that no two targets in the same directory share the same name.
2200
2201 Arguments:
2202 targets: A list of targets in the form 'path/to/file.gyp:target_name'.
2203 """
2204 # Keep a dict going from 'subdirectory:target_name' to 'foo.gyp'.
2205 used = {}
2206 for target in targets:
2207 # Separate out 'path/to/file.gyp, 'target_name' from
2208 # 'path/to/file.gyp:target_name'.
2209 path, name = target.rsplit(':', 1)
2210 # Separate out 'path/to', 'file.gyp' from 'path/to/file.gyp'.
2211 subdir, gyp = os.path.split(path)
2212 # Use '.' for the current directory '', so that the error messages make
2213 # more sense.
2214 if not subdir:
2215 subdir = '.'
2216 # Prepare a key like 'path/to:target_name'.
2217 key = subdir + ':' + name
2218 if key in used:
2219 # Complain if this target is already used.
2220 raise Exception('Duplicate target name "%s" in directory "%s" used both '
2221 'in "%s" and "%s".' % (name, subdir, gyp, used[key]))
2222 used[key] = gyp
2223
2224
2225 def Load(build_files, variables, includes, depth, generator_input_info, check,
2226 circular_check):
2227 # Set up path_sections and non_configuration_keys with the default data plus
2228 # the generator-specifc data.
2229 global path_sections
2230 path_sections = base_path_sections[:]
2231 path_sections.extend(generator_input_info['path_sections'])
2232
2233 global non_configuration_keys
2234 non_configuration_keys = base_non_configuration_keys[:]
2235 non_configuration_keys.extend(generator_input_info['non_configuration_keys'])
2236
2237 # TODO(mark) handle variants if the generator doesn't want them directly.
2238 generator_handles_variants = \
2239 generator_input_info['generator_handles_variants']
2240
2241 global absolute_build_file_paths
2242 absolute_build_file_paths = \
2243 generator_input_info['generator_wants_absolute_build_file_paths']
2244
2245 global multiple_toolsets
2246 multiple_toolsets = generator_input_info[
2247 'generator_supports_multiple_toolsets']
2248
2249 # A generator can have other lists (in addition to sources) be processed
2250 # for rules.
2251 extra_sources_for_rules = generator_input_info['extra_sources_for_rules']
2252
2253 # Load build files. This loads every target-containing build file into
2254 # the |data| dictionary such that the keys to |data| are build file names,
2255 # and the values are the entire build file contents after "early" or "pre"
2256 # processing has been done and includes have been resolved.
2257 # NOTE: data contains both "target" files (.gyp) and "includes" (.gypi), as
2258 # well as meta-data (e.g. 'included_files' key). 'target_build_files' keeps
2259 # track of the keys corresponding to "target" files.
2260 data = {'target_build_files': set()}
2261 aux_data = {}
2262 for build_file in build_files:
2263 # Normalize paths everywhere. This is important because paths will be
2264 # used as keys to the data dict and for references between input files.
2265 build_file = os.path.normpath(build_file)
2266 try:
2267 LoadTargetBuildFile(build_file, data, aux_data, variables, includes,
2268 depth, check)
2269 except Exception, e:
2270 gyp.common.ExceptionAppend(e, 'while trying to load %s' % build_file)
2271 raise
2272
2273 # Build a dict to access each target's subdict by qualified name.
2274 targets = BuildTargetsDict(data)
2275
2276 # Fully qualify all dependency links.
2277 QualifyDependencies(targets)
2278
2279 # Expand dependencies specified as build_file:*.
2280 ExpandWildcardDependencies(targets, data)
2281
2282 # Apply exclude (!) and regex (/) list filters only for dependency_sections.
2283 for target_name, target_dict in targets.iteritems():
2284 tmp_dict = {}
2285 for key_base in dependency_sections:
2286 for op in ('', '!', '/'):
2287 key = key_base + op
2288 if key in target_dict:
2289 tmp_dict[key] = target_dict[key]
2290 del target_dict[key]
2291 ProcessListFiltersInDict(target_name, tmp_dict)
2292 # Write the results back to |target_dict|.
2293 for key in tmp_dict:
2294 target_dict[key] = tmp_dict[key]
2295
2296 if circular_check:
2297 # Make sure that any targets in a.gyp don't contain dependencies in other
2298 # .gyp files that further depend on a.gyp.
2299 VerifyNoGYPFileCircularDependencies(targets)
2300
2301 [dependency_nodes, flat_list] = BuildDependencyList(targets)
2302
2303 # Check that no two targets in the same directory have the same name.
2304 VerifyNoCollidingTargets(flat_list)
2305
2306 # Handle dependent settings of various types.
2307 for settings_type in ['all_dependent_settings',
2308 'direct_dependent_settings',
2309 'link_settings']:
2310 DoDependentSettings(settings_type, flat_list, targets, dependency_nodes)
2311
2312 # Take out the dependent settings now that they've been published to all
2313 # of the targets that require them.
2314 for target in flat_list:
2315 if settings_type in targets[target]:
2316 del targets[target][settings_type]
2317
2318 # Make sure static libraries don't declare dependencies on other static
2319 # libraries, but that linkables depend on all unlinked static libraries
2320 # that they need so that their link steps will be correct.
2321 gii = generator_input_info
2322 if gii['generator_wants_static_library_dependencies_adjusted']:
2323 AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes,
2324 gii['generator_wants_sorted_dependencies'])
2325
2326 # Apply "post"/"late"/"target" variable expansions and condition evaluations.
2327 for target in flat_list:
2328 target_dict = targets[target]
2329 build_file = gyp.common.BuildFile(target)
2330 ProcessVariablesAndConditionsInDict(target_dict, True, variables,
2331 build_file)
2332
2333 # Move everything that can go into a "configurations" section into one.
2334 for target in flat_list:
2335 target_dict = targets[target]
2336 SetUpConfigurations(target, target_dict)
2337
2338 # Apply exclude (!) and regex (/) list filters.
2339 for target in flat_list:
2340 target_dict = targets[target]
2341 ProcessListFiltersInDict(target, target_dict)
2342
2343 # Make sure that the rules make sense, and build up rule_sources lists as
2344 # needed. Not all generators will need to use the rule_sources lists, but
2345 # some may, and it seems best to build the list in a common spot.
2346 # Also validate actions and run_as elements in targets.
2347 for target in flat_list:
2348 target_dict = targets[target]
2349 build_file = gyp.common.BuildFile(target)
2350 ValidateRulesInTarget(target, target_dict, extra_sources_for_rules)
2351 ValidateRunAsInTarget(target, target_dict, build_file)
2352 ValidateActionsInTarget(target, target_dict, build_file)
2353
2354 # Generators might not expect ints. Turn them into strs.
2355 TurnIntIntoStrInDict(data)
2356
2357 # TODO(mark): Return |data| for now because the generator needs a list of
2358 # build files that came in. In the future, maybe it should just accept
2359 # a list, and not the whole data dict.
2360 return [flat_list, targets, data]
+0
-187
third_party/gyp/pylib/gyp/mac_tool.py less more
0 #!/usr/bin/python
1 # Copyright (c) 2011 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 """Utility functions to perform Xcode-style build steps.
6
7 These functions are executed via gyp-mac-tool when using the Makefile generator.
8 """
9
10 import os
11 import fcntl
12 import plistlib
13 import shutil
14 import string
15 import subprocess
16 import sys
17
18 def main(args):
19 executor = MacTool()
20 executor.Dispatch(args)
21
22 class MacTool(object):
23 """This class performs all the Mac tooling steps. The methods can either be
24 executed directly, or dispatched from an argument list."""
25
26 def Dispatch(self, args):
27 """Dispatches a string command to a method."""
28 if len(args) < 1:
29 raise Exception("Not enough arguments")
30
31 method = "Exec%s" % self._CommandifyName(args[0])
32 getattr(self, method)(*args[1:])
33
34 def _CommandifyName(self, name_string):
35 """Transforms a tool name like copy-info-plist to CopyInfoPlist"""
36 return name_string.title().replace('-', '')
37
38 def ExecFlock(self, lockfile, *cmd_list):
39 """Emulates the most basic behavior of Linux's flock(1)."""
40 # Rely on exception handling to report errors.
41 fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666)
42 fcntl.flock(fd, fcntl.LOCK_EX)
43 return subprocess.call(cmd_list)
44
45 def ExecCopyInfoPlist(self, source, dest):
46 """Copies the |source| Info.plist to the destination directory |dest|."""
47 # Read the source Info.plist into memory.
48 fd = open(source, 'r')
49 lines = fd.read()
50 fd.close()
51
52 # Go through all the environment variables and replace them as variables in
53 # the file.
54 for key in os.environ:
55 if key.startswith('_'):
56 continue
57 evar = '${%s}' % key
58 lines = string.replace(lines, evar, os.environ[key])
59
60 # Write out the file with variables replaced.
61 fd = open(dest, 'w')
62 fd.write(lines)
63 fd.close()
64
65 # Now write out PkgInfo file now that the Info.plist file has been
66 # "compiled".
67 self._WritePkgInfo(dest)
68
69 def _WritePkgInfo(self, info_plist):
70 """This writes the PkgInfo file from the data stored in Info.plist."""
71 plist = plistlib.readPlist(info_plist)
72 if not plist:
73 return
74
75 # The format of PkgInfo is eight characters, representing the bundle type
76 # and bundle signature, each four characters. If either is missing, four
77 # '?' characters are used instead.
78 package_type = plist['CFBundlePackageType']
79 if len(package_type) != 4:
80 package_type = '?' * 4
81 signature_code = plist['CFBundleSignature']
82 if len(signature_code) != 4:
83 signature_code = '?' * 4
84
85 dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo')
86 fp = open(dest, 'w')
87 fp.write('%s%s' % (package_type, signature_code))
88 fp.close()
89
90 def ExecPackageFramework(self, framework, version):
91 """Takes a path to Something.framework and the Current version of that and
92 sets up all the symlinks."""
93 # Find the name of the binary based on the part before the ".framework".
94 binary = os.path.basename(framework).split('.')[0]
95
96 CURRENT = 'Current'
97 RESOURCES = 'Resources'
98 VERSIONS = 'Versions'
99
100 if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)):
101 # Binary-less frameworks don't seem to contain symlinks (see e.g.
102 # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle).
103 return
104
105 # Move into the framework directory to set the symlinks correctly.
106 pwd = os.getcwd()
107 os.chdir(framework)
108
109 # Set up the Current version.
110 self._Relink(version, os.path.join(VERSIONS, CURRENT))
111
112 # Set up the root symlinks.
113 self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary)
114 self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES)
115
116 # Back to where we were before!
117 os.chdir(pwd)
118
119 def _Relink(self, dest, link):
120 """Creates a symlink to |dest| named |link|. If |link| already exists,
121 it is overwritten."""
122 if os.path.lexists(link):
123 os.remove(link)
124 os.symlink(dest, link)
125
126 def ExecCopyBundleResource(self, source, dest):
127 """Copies a resource file to the bundle/Resources directory, performing any
128 necessary compilation on each resource."""
129 extension = os.path.splitext(source)[1].lower()
130 if os.path.isdir(source):
131 # Copy tree.
132 if os.path.exists(dest):
133 shutil.rmtree(dest)
134 shutil.copytree(source, dest)
135 elif extension == '.xib':
136 self._CopyXIBFile(source, dest)
137 elif extension == '.strings':
138 self._CopyStringsFile(source, dest)
139 # TODO: Given that files with arbitrary extensions can be copied to the
140 # bundle, we will want to get rid of this whitelist eventually.
141 elif extension in [
142 '.icns', '.manifest', '.pak', '.pdf', '.png', '.sb', '.sh',
143 '.ttf', '.sdef']:
144 shutil.copyfile(source, dest)
145 else:
146 raise NotImplementedError(
147 "Don't know how to copy bundle resources of type %s while copying "
148 "%s to %s)" % (extension, source, dest))
149
150 def _CopyXIBFile(self, source, dest):
151 """Compiles a XIB file with ibtool into a binary plist in the bundle."""
152 args = ['/Developer/usr/bin/ibtool', '--errors', '--warnings',
153 '--notices', '--output-format', 'human-readable-text', '--compile',
154 dest, source]
155 subprocess.call(args)
156
157 def _CopyStringsFile(self, source, dest):
158 """Copies a .strings file using iconv to reconvert the input into UTF-16."""
159 input_code = self._DetectInputEncoding(source) or "UTF-8"
160 fp = open(dest, 'w')
161 args = ['/usr/bin/iconv', '--from-code', input_code, '--to-code',
162 'UTF-16', source]
163 subprocess.call(args, stdout=fp)
164 fp.close()
165
166 def _DetectInputEncoding(self, file_name):
167 """Reads the first few bytes from file_name and tries to guess the text
168 encoding. Returns None as a guess if it can't detect it."""
169 fp = open(file_name, 'rb')
170 try:
171 header = fp.read(3)
172 except e:
173 fp.close()
174 return None
175 fp.close()
176 if header.startswith("\xFE\xFF"):
177 return "UTF-16BE"
178 elif header.startswith("\xFF\xFE"):
179 return "UTF-16LE"
180 elif header.startswith("\xEF\xBB\xBF"):
181 return "UTF-8"
182 else:
183 return None
184
185 if __name__ == '__main__':
186 sys.exit(main(sys.argv[1:]))
+0
-104
third_party/gyp/pylib/gyp/ninja_syntax.py less more
0 #!/usr/bin/python
1
2 # This file comes from
3 # https://github.com/martine/ninja/blob/master/misc/ninja_syntax.py
4 # Do not edit! Edit the upstream one instead.
5
6 """Python module for generating .ninja files.
7
8 Note that this is emphatically not a required piece of Ninja; it's
9 just a helpful utility for build-file-generation systems that already
10 use Python.
11 """
12
13 import textwrap
14
15 class Writer(object):
16 def __init__(self, output, width=78):
17 self.output = output
18 self.width = width
19
20 def newline(self):
21 self.output.write('\n')
22
23 def comment(self, text):
24 for line in textwrap.wrap(text, self.width - 2):
25 self.output.write('# ' + line + '\n')
26
27 def variable(self, key, value, indent=0):
28 self._line('%s = %s' % (key, value), indent)
29
30 def rule(self, name, command, description=None, depfile=None):
31 self._line('rule %s' % name)
32 self.variable('command', command, indent=1)
33 if description:
34 self.variable('description', description, indent=1)
35 if depfile:
36 self.variable('depfile', depfile, indent=1)
37
38 def build(self, outputs, rule, inputs=None, implicit=None, order_only=None,
39 variables=None):
40 outputs = self._as_list(outputs)
41 all_inputs = self._as_list(inputs)[:]
42
43 if implicit:
44 all_inputs.append('|')
45 all_inputs.extend(self._as_list(implicit))
46 if order_only:
47 all_inputs.append('||')
48 all_inputs.extend(self._as_list(order_only))
49
50 self._line('build %s: %s %s' % (' '.join(outputs),
51 rule,
52 ' '.join(all_inputs)))
53
54 if variables:
55 for key, val in variables:
56 self.variable(key, val, indent=1)
57
58 return outputs
59
60 def include(self, path):
61 self._line('include %s' % path)
62
63 def subninja(self, path):
64 self._line('subninja %s' % path)
65
66 def _line(self, text, indent=0):
67 """Write 'text' word-wrapped at self.width characters."""
68 leading_space = ' ' * indent
69 while len(text) > self.width:
70 # The text is too wide; wrap if possible.
71
72 # Find the rightmost space that would obey our width constraint.
73 available_space = self.width - len(leading_space) - len(' $')
74 space = text.rfind(' ', 0, available_space)
75 if space < 0:
76 # No such space; just use the first space we can find.
77 space = text.find(' ', available_space)
78 if space < 0:
79 # Give up on breaking.
80 break
81
82 self.output.write(leading_space + text[0:space] + ' $\n')
83 text = text[space+1:]
84
85 # Subsequent lines are continuations, so indent them.
86 leading_space = ' ' * (indent+2)
87
88 self.output.write(leading_space + text + '\n')
89
90 def _as_list(self, input):
91 if input is None:
92 return []
93 if isinstance(input, list):
94 return input
95 return [input]
96
97
98 def escape(string):
99 """Escape a string such that it can be embedded into a Ninja file without
100 further interpretation."""
101 assert '\n' not in string, 'Ninja syntax does not allow newlines'
102 # We only have one special metacharacter: '$'.
103 return string.replace('$', '$$')
+0
-77
third_party/gyp/pylib/gyp/system_test.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import os
7 import tempfile
8 import shutil
9 import subprocess
10
11 def TestCommands(commands, files={}, env={}):
12 """Run commands in a temporary directory, returning true if they all succeed.
13 Return false on failures or if any commands produce output.
14
15 Arguments:
16 commands: an array of shell-interpretable commands, e.g. ['ls -l', 'pwd']
17 each will be expanded with Python %-expansion using env first.
18 files: a dictionary mapping filename to contents;
19 files will be created in the temporary directory before running
20 the command.
21 env: a dictionary of strings to expand commands with.
22 """
23 tempdir = tempfile.mkdtemp()
24 try:
25 for name, contents in files.items():
26 f = open(os.path.join(tempdir, name), 'wb')
27 f.write(contents)
28 f.close()
29 for command in commands:
30 proc = subprocess.Popen(command % env, shell=True,
31 stdout=subprocess.PIPE,
32 stderr=subprocess.STDOUT,
33 cwd=tempdir)
34 output = proc.communicate()[0]
35 if proc.returncode != 0 or output:
36 return False
37 return True
38 finally:
39 shutil.rmtree(tempdir)
40 return False
41
42
43 def TestArSupportsT(ar_command='ar', cc_command='cc'):
44 """Test whether 'ar' supports the 'T' flag."""
45 return TestCommands(['%(cc)s -c test.c',
46 '%(ar)s crsT test.a test.o',
47 '%(cc)s test.a'],
48 files={'test.c': 'int main(){}'},
49 env={'ar': ar_command, 'cc': cc_command})
50
51
52 def TestLinkerSupportsThreads(cc_command='cc'):
53 """Test whether the linker supports the --threads flag."""
54 return TestCommands(['%(cc)s -Wl,--threads test.c'],
55 files={'test.c': 'int main(){}'},
56 env={'cc': cc_command})
57
58
59 def TestLinkerSupportsICF(cc_command='cc'):
60 """Test whether the linker supports identical code folding."""
61 return TestCommands(['%(cc)s -Wl,--icf=safe test.c'],
62 files={'test.c': 'int main(){}'},
63 env={'cc': cc_command})
64
65
66 if __name__ == '__main__':
67 # Run the various test functions and print the results.
68 def RunTest(description, function, **kwargs):
69 print "Testing " + description + ':',
70 if function(**kwargs):
71 print 'ok'
72 else:
73 print 'fail'
74 RunTest("ar 'T' flag", TestArSupportsT)
75 RunTest("ar 'T' flag with ccache", TestArSupportsT, cc_command='ccache cc')
76 RunTest("ld --threads", TestLinkerSupportsThreads)
+0
-2840
third_party/gyp/pylib/gyp/xcodeproj_file.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Xcode project file generator.
7
8 This module is both an Xcode project file generator and a documentation of the
9 Xcode project file format. Knowledge of the project file format was gained
10 based on extensive experience with Xcode, and by making changes to projects in
11 Xcode.app and observing the resultant changes in the associated project files.
12
13 XCODE PROJECT FILES
14
15 The generator targets the file format as written by Xcode 3.1 (specifically,
16 3.1.2), but past experience has taught that the format has not changed
17 significantly in the past several years, and future versions of Xcode are able
18 to read older project files.
19
20 Xcode project files are "bundled": the project "file" from an end-user's
21 perspective is actually a directory with an ".xcodeproj" extension. The
22 project file from this module's perspective is actually a file inside this
23 directory, always named "project.pbxproj". This file contains a complete
24 description of the project and is all that is needed to use the xcodeproj.
25 Other files contained in the xcodeproj directory are simply used to store
26 per-user settings, such as the state of various UI elements in the Xcode
27 application.
28
29 The project.pbxproj file is a property list, stored in a format almost
30 identical to the NeXTstep property list format. The file is able to carry
31 Unicode data, and is encoded in UTF-8. The root element in the property list
32 is a dictionary that contains several properties of minimal interest, and two
33 properties of immense interest. The most important property is a dictionary
34 named "objects". The entire structure of the project is represented by the
35 children of this property. The objects dictionary is keyed by unique 96-bit
36 values represented by 24 uppercase hexadecimal characters. Each value in the
37 objects dictionary is itself a dictionary, describing an individual object.
38
39 Each object in the dictionary is a member of a class, which is identified by
40 the "isa" property of each object. A variety of classes are represented in a
41 project file. Objects can refer to other objects by ID, using the 24-character
42 hexadecimal object key. A project's objects form a tree, with a root object
43 of class PBXProject at the root. As an example, the PBXProject object serves
44 as parent to an XCConfigurationList object defining the build configurations
45 used in the project, a PBXGroup object serving as a container for all files
46 referenced in the project, and a list of target objects, each of which defines
47 a target in the project. There are several different types of target object,
48 such as PBXNativeTarget and PBXAggregateTarget. In this module, this
49 relationship is expressed by having each target type derive from an abstract
50 base named XCTarget.
51
52 The project.pbxproj file's root dictionary also contains a property, sibling to
53 the "objects" dictionary, named "rootObject". The value of rootObject is a
54 24-character object key referring to the root PBXProject object in the
55 objects dictionary.
56
57 In Xcode, every file used as input to a target or produced as a final product
58 of a target must appear somewhere in the hierarchy rooted at the PBXGroup
59 object referenced by the PBXProject's mainGroup property. A PBXGroup is
60 generally represented as a folder in the Xcode application. PBXGroups can
61 contain other PBXGroups as well as PBXFileReferences, which are pointers to
62 actual files.
63
64 Each XCTarget contains a list of build phases, represented in this module by
65 the abstract base XCBuildPhase. Examples of concrete XCBuildPhase derivations
66 are PBXSourcesBuildPhase and PBXFrameworksBuildPhase, which correspond to the
67 "Compile Sources" and "Link Binary With Libraries" phases displayed in the
68 Xcode application. Files used as input to these phases (for example, source
69 files in the former case and libraries and frameworks in the latter) are
70 represented by PBXBuildFile objects, referenced by elements of "files" lists
71 in XCTarget objects. Each PBXBuildFile object refers to a PBXBuildFile
72 object as a "weak" reference: it does not "own" the PBXBuildFile, which is
73 owned by the root object's mainGroup or a descendant group. In most cases, the
74 layer of indirection between an XCBuildPhase and a PBXFileReference via a
75 PBXBuildFile appears extraneous, but there's actually one reason for this:
76 file-specific compiler flags are added to the PBXBuildFile object so as to
77 allow a single file to be a member of multiple targets while having distinct
78 compiler flags for each. These flags can be modified in the Xcode applciation
79 in the "Build" tab of a File Info window.
80
81 When a project is open in the Xcode application, Xcode will rewrite it. As
82 such, this module is careful to adhere to the formatting used by Xcode, to
83 avoid insignificant changes appearing in the file when it is used in the
84 Xcode application. This will keep version control repositories happy, and
85 makes it possible to compare a project file used in Xcode to one generated by
86 this module to determine if any significant changes were made in the
87 application.
88
89 Xcode has its own way of assigning 24-character identifiers to each object,
90 which is not duplicated here. Because the identifier only is only generated
91 once, when an object is created, and is then left unchanged, there is no need
92 to attempt to duplicate Xcode's behavior in this area. The generator is free
93 to select any identifier, even at random, to refer to the objects it creates,
94 and Xcode will retain those identifiers and use them when subsequently
95 rewriting the project file. However, the generator would choose new random
96 identifiers each time the project files are generated, leading to difficulties
97 comparing "used" project files to "pristine" ones produced by this module,
98 and causing the appearance of changes as every object identifier is changed
99 when updated projects are checked in to a version control repository. To
100 mitigate this problem, this module chooses identifiers in a more deterministic
101 way, by hashing a description of each object as well as its parent and ancestor
102 objects. This strategy should result in minimal "shift" in IDs as successive
103 generations of project files are produced.
104
105 THIS MODULE
106
107 This module introduces several classes, all derived from the XCObject class.
108 Nearly all of the "brains" are built into the XCObject class, which understands
109 how to create and modify objects, maintain the proper tree structure, compute
110 identifiers, and print objects. For the most part, classes derived from
111 XCObject need only provide a _schema class object, a dictionary that
112 expresses what properties objects of the class may contain.
113
114 Given this structure, it's possible to build a minimal project file by creating
115 objects of the appropriate types and making the proper connections:
116
117 config_list = XCConfigurationList()
118 group = PBXGroup()
119 project = PBXProject({'buildConfigurationList': config_list,
120 'mainGroup': group})
121
122 With the project object set up, it can be added to an XCProjectFile object.
123 XCProjectFile is a pseudo-class in the sense that it is a concrete XCObject
124 subclass that does not actually correspond to a class type found in a project
125 file. Rather, it is used to represent the project file's root dictionary.
126 Printing an XCProjectFile will print the entire project file, including the
127 full "objects" dictionary.
128
129 project_file = XCProjectFile({'rootObject': project})
130 project_file.ComputeIDs()
131 project_file.Print()
132
133 Xcode project files are always encoded in UTF-8. This module will accept
134 strings of either the str class or the unicode class. Strings of class str
135 are assumed to already be encoded in UTF-8. Obviously, if you're just using
136 ASCII, you won't encounter difficulties because ASCII is a UTF-8 subset.
137 Strings of class unicode are handled properly and encoded in UTF-8 when
138 a project file is output.
139 """
140
141 import gyp.common
142 import posixpath
143 import re
144 import struct
145 import sys
146
147 # hashlib is supplied as of Python 2.5 as the replacement interface for sha
148 # and other secure hashes. In 2.6, sha is deprecated. Import hashlib if
149 # available, avoiding a deprecation warning under 2.6. Import sha otherwise,
150 # preserving 2.4 compatibility.
151 try:
152 import hashlib
153 _new_sha1 = hashlib.sha1
154 except ImportError:
155 import sha
156 _new_sha1 = sha.new
157
158
159 # See XCObject._EncodeString. This pattern is used to determine when a string
160 # can be printed unquoted. Strings that match this pattern may be printed
161 # unquoted. Strings that do not match must be quoted and may be further
162 # transformed to be properly encoded. Note that this expression matches the
163 # characters listed with "+", for 1 or more occurrences: if a string is empty,
164 # it must not match this pattern, because it needs to be encoded as "".
165 _unquoted = re.compile('^[A-Za-z0-9$./_]+$')
166
167 # Strings that match this pattern are quoted regardless of what _unquoted says.
168 # Oddly, Xcode will quote any string with a run of three or more underscores.
169 _quoted = re.compile('___')
170
171 # This pattern should match any character that needs to be escaped by
172 # XCObject._EncodeString. See that function.
173 _escaped = re.compile('[\\\\"]|[^ -~]')
174
175
176 # Used by SourceTreeAndPathFromPath
177 _path_leading_variable = re.compile('^\$\((.*?)\)(/(.*))?$')
178
179 def SourceTreeAndPathFromPath(input_path):
180 """Given input_path, returns a tuple with sourceTree and path values.
181
182 Examples:
183 input_path (source_tree, output_path)
184 '$(VAR)/path' ('VAR', 'path')
185 '$(VAR)' ('VAR', None)
186 'path' (None, 'path')
187 """
188
189 source_group_match = _path_leading_variable.match(input_path)
190 if source_group_match:
191 source_tree = source_group_match.group(1)
192 output_path = source_group_match.group(3) # This may be None.
193 else:
194 source_tree = None
195 output_path = input_path
196
197 return (source_tree, output_path)
198
199 def ConvertVariablesToShellSyntax(input_string):
200 return re.sub('\$\((.*?)\)', '${\\1}', input_string)
201
202 class XCObject(object):
203 """The abstract base of all class types used in Xcode project files.
204
205 Class variables:
206 _schema: A dictionary defining the properties of this class. The keys to
207 _schema are string property keys as used in project files. Values
208 are a list of four or five elements:
209 [ is_list, property_type, is_strong, is_required, default ]
210 is_list: True if the property described is a list, as opposed
211 to a single element.
212 property_type: The type to use as the value of the property,
213 or if is_list is True, the type to use for each
214 element of the value's list. property_type must
215 be an XCObject subclass, or one of the built-in
216 types str, int, or dict.
217 is_strong: If property_type is an XCObject subclass, is_strong
218 is True to assert that this class "owns," or serves
219 as parent, to the property value (or, if is_list is
220 True, values). is_strong must be False if
221 property_type is not an XCObject subclass.
222 is_required: True if the property is required for the class.
223 Note that is_required being True does not preclude
224 an empty string ("", in the case of property_type
225 str) or list ([], in the case of is_list True) from
226 being set for the property.
227 default: Optional. If is_requried is True, default may be set
228 to provide a default value for objects that do not supply
229 their own value. If is_required is True and default
230 is not provided, users of the class must supply their own
231 value for the property.
232 Note that although the values of the array are expressed in
233 boolean terms, subclasses provide values as integers to conserve
234 horizontal space.
235 _should_print_single_line: False in XCObject. Subclasses whose objects
236 should be written to the project file in the
237 alternate single-line format, such as
238 PBXFileReference and PBXBuildFile, should
239 set this to True.
240 _encode_transforms: Used by _EncodeString to encode unprintable characters.
241 The index into this list is the ordinal of the
242 character to transform; each value is a string
243 used to represent the character in the output. XCObject
244 provides an _encode_transforms list suitable for most
245 XCObject subclasses.
246 _alternate_encode_transforms: Provided for subclasses that wish to use
247 the alternate encoding rules. Xcode seems
248 to use these rules when printing objects in
249 single-line format. Subclasses that desire
250 this behavior should set _encode_transforms
251 to _alternate_encode_transforms.
252 _hashables: A list of XCObject subclasses that can be hashed by ComputeIDs
253 to construct this object's ID. Most classes that need custom
254 hashing behavior should do it by overriding Hashables,
255 but in some cases an object's parent may wish to push a
256 hashable value into its child, and it can do so by appending
257 to _hashables.
258 Attribues:
259 id: The object's identifier, a 24-character uppercase hexadecimal string.
260 Usually, objects being created should not set id until the entire
261 project file structure is built. At that point, UpdateIDs() should
262 be called on the root object to assign deterministic values for id to
263 each object in the tree.
264 parent: The object's parent. This is set by a parent XCObject when a child
265 object is added to it.
266 _properties: The object's property dictionary. An object's properties are
267 described by its class' _schema variable.
268 """
269
270 _schema = {}
271 _should_print_single_line = False
272
273 # See _EncodeString.
274 _encode_transforms = []
275 i = 0
276 while i < ord(' '):
277 _encode_transforms.append('\\U%04x' % i)
278 i = i + 1
279 _encode_transforms[7] = '\\a'
280 _encode_transforms[8] = '\\b'
281 _encode_transforms[9] = '\\t'
282 _encode_transforms[10] = '\\n'
283 _encode_transforms[11] = '\\v'
284 _encode_transforms[12] = '\\f'
285 _encode_transforms[13] = '\\n'
286
287 _alternate_encode_transforms = list(_encode_transforms)
288 _alternate_encode_transforms[9] = chr(9)
289 _alternate_encode_transforms[10] = chr(10)
290 _alternate_encode_transforms[11] = chr(11)
291
292 def __init__(self, properties=None, id=None, parent=None):
293 self.id = id
294 self.parent = parent
295 self._properties = {}
296 self._hashables = []
297 self._SetDefaultsFromSchema()
298 self.UpdateProperties(properties)
299
300 def __repr__(self):
301 try:
302 name = self.Name()
303 except NotImplementedError:
304 return '<%s at 0x%x>' % (self.__class__.__name__, id(self))
305 return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))
306
307 def Copy(self):
308 """Make a copy of this object.
309
310 The new object will have its own copy of lists and dicts. Any XCObject
311 objects owned by this object (marked "strong") will be copied in the
312 new object, even those found in lists. If this object has any weak
313 references to other XCObjects, the same references are added to the new
314 object without making a copy.
315 """
316
317 that = self.__class__(id=self.id, parent=self.parent)
318 for key, value in self._properties.iteritems():
319 is_strong = self._schema[key][2]
320
321 if isinstance(value, XCObject):
322 if is_strong:
323 new_value = value.Copy()
324 new_value.parent = that
325 that._properties[key] = new_value
326 else:
327 that._properties[key] = value
328 elif isinstance(value, str) or isinstance(value, unicode) or \
329 isinstance(value, int):
330 that._properties[key] = value
331 elif isinstance(value, list):
332 if is_strong:
333 # If is_strong is True, each element is an XCObject, so it's safe to
334 # call Copy.
335 that._properties[key] = []
336 for item in value:
337 new_item = item.Copy()
338 new_item.parent = that
339 that._properties[key].append(new_item)
340 else:
341 that._properties[key] = value[:]
342 elif isinstance(value, dict):
343 # dicts are never strong.
344 if is_strong:
345 raise TypeError, 'Strong dict for key ' + key + ' in ' + \
346 self.__class__.__name__
347 else:
348 that._properties[key] = value.copy()
349 else:
350 raise TypeError, 'Unexpected type ' + value.__class__.__name__ + \
351 ' for key ' + key + ' in ' + self.__class__.__name__
352
353 return that
354
355 def Name(self):
356 """Return the name corresponding to an object.
357
358 Not all objects necessarily need to be nameable, and not all that do have
359 a "name" property. Override as needed.
360 """
361
362 # If the schema indicates that "name" is required, try to access the
363 # property even if it doesn't exist. This will result in a KeyError
364 # being raised for the property that should be present, which seems more
365 # appropriate than NotImplementedError in this case.
366 if 'name' in self._properties or \
367 ('name' in self._schema and self._schema['name'][3]):
368 return self._properties['name']
369
370 raise NotImplementedError, \
371 self.__class__.__name__ + ' must implement Name'
372
373 def Comment(self):
374 """Return a comment string for the object.
375
376 Most objects just use their name as the comment, but PBXProject uses
377 different values.
378
379 The returned comment is not escaped and does not have any comment marker
380 strings applied to it.
381 """
382
383 return self.Name()
384
385 def Hashables(self):
386 hashables = [self.__class__.__name__]
387
388 name = self.Name()
389 if name != None:
390 hashables.append(name)
391
392 hashables.extend(self._hashables)
393
394 return hashables
395
396 def ComputeIDs(self, recursive=True, overwrite=True, hash=None):
397 """Set "id" properties deterministically.
398
399 An object's "id" property is set based on a hash of its class type and
400 name, as well as the class type and name of all ancestor objects. As
401 such, it is only advisable to call ComputeIDs once an entire project file
402 tree is built.
403
404 If recursive is True, recurse into all descendant objects and update their
405 hashes.
406
407 If overwrite is True, any existing value set in the "id" property will be
408 replaced.
409 """
410
411 def _HashUpdate(hash, data):
412 """Update hash with data's length and contents.
413
414 If the hash were updated only with the value of data, it would be
415 possible for clowns to induce collisions by manipulating the names of
416 their objects. By adding the length, it's exceedingly less likely that
417 ID collisions will be encountered, intentionally or not.
418 """
419
420 hash.update(struct.pack('>i', len(data)))
421 hash.update(data)
422
423 if hash == None:
424 hash = _new_sha1()
425
426 hashables = self.Hashables()
427 assert len(hashables) > 0
428 for hashable in hashables:
429 _HashUpdate(hash, hashable)
430
431 if recursive:
432 for child in self.Children():
433 child.ComputeIDs(recursive, overwrite, hash.copy())
434
435 if overwrite or self.id == None:
436 # Xcode IDs are only 96 bits (24 hex characters), but a SHA-1 digest is
437 # is 160 bits. Instead of throwing out 64 bits of the digest, xor them
438 # into the portion that gets used.
439 assert hash.digest_size % 4 == 0
440 digest_int_count = hash.digest_size / 4
441 digest_ints = struct.unpack('>' + 'I' * digest_int_count, hash.digest())
442 id_ints = [0, 0, 0]
443 for index in xrange(0, digest_int_count):
444 id_ints[index % 3] ^= digest_ints[index]
445 self.id = '%08X%08X%08X' % tuple(id_ints)
446
447 def EnsureNoIDCollisions(self):
448 """Verifies that no two objects have the same ID. Checks all descendants.
449 """
450
451 ids = {}
452 descendants = self.Descendants()
453 for descendant in descendants:
454 if descendant.id in ids:
455 other = ids[descendant.id]
456 raise KeyError, \
457 'Duplicate ID %s, objects "%s" and "%s" in "%s"' % \
458 (descendant.id, str(descendant._properties),
459 str(other._properties), self._properties['rootObject'].Name())
460 ids[descendant.id] = descendant
461
462 def Children(self):
463 """Returns a list of all of this object's owned (strong) children."""
464
465 children = []
466 for property, attributes in self._schema.iteritems():
467 (is_list, property_type, is_strong) = attributes[0:3]
468 if is_strong and property in self._properties:
469 if not is_list:
470 children.append(self._properties[property])
471 else:
472 children.extend(self._properties[property])
473 return children
474
475 def Descendants(self):
476 """Returns a list of all of this object's descendants, including this
477 object.
478 """
479
480 children = self.Children()
481 descendants = [self]
482 for child in children:
483 descendants.extend(child.Descendants())
484 return descendants
485
486 def PBXProjectAncestor(self):
487 # The base case for recursion is defined at PBXProject.PBXProjectAncestor.
488 if self.parent:
489 return self.parent.PBXProjectAncestor()
490 return None
491
492 def _EncodeComment(self, comment):
493 """Encodes a comment to be placed in the project file output, mimicing
494 Xcode behavior.
495 """
496
497 # This mimics Xcode behavior by wrapping the comment in "/*" and "*/". If
498 # the string already contains a "*/", it is turned into "(*)/". This keeps
499 # the file writer from outputting something that would be treated as the
500 # end of a comment in the middle of something intended to be entirely a
501 # comment.
502
503 return '/* ' + comment.replace('*/', '(*)/') + ' */'
504
505 def _EncodeTransform(self, match):
506 # This function works closely with _EncodeString. It will only be called
507 # by re.sub with match.group(0) containing a character matched by the
508 # the _escaped expression.
509 char = match.group(0)
510
511 # Backslashes (\) and quotation marks (") are always replaced with a
512 # backslash-escaped version of the same. Everything else gets its
513 # replacement from the class' _encode_transforms array.
514 if char == '\\':
515 return '\\\\'
516 if char == '"':
517 return '\\"'
518 return self._encode_transforms[ord(char)]
519
520 def _EncodeString(self, value):
521 """Encodes a string to be placed in the project file output, mimicing
522 Xcode behavior.
523 """
524
525 # Use quotation marks when any character outside of the range A-Z, a-z, 0-9,
526 # $ (dollar sign), . (period), and _ (underscore) is present. Also use
527 # quotation marks to represent empty strings.
528 #
529 # Escape " (double-quote) and \ (backslash) by preceding them with a
530 # backslash.
531 #
532 # Some characters below the printable ASCII range are encoded specially:
533 # 7 ^G BEL is encoded as "\a"
534 # 8 ^H BS is encoded as "\b"
535 # 11 ^K VT is encoded as "\v"
536 # 12 ^L NP is encoded as "\f"
537 # 127 ^? DEL is passed through as-is without escaping
538 # - In PBXFileReference and PBXBuildFile objects:
539 # 9 ^I HT is passed through as-is without escaping
540 # 10 ^J NL is passed through as-is without escaping
541 # 13 ^M CR is passed through as-is without escaping
542 # - In other objects:
543 # 9 ^I HT is encoded as "\t"
544 # 10 ^J NL is encoded as "\n"
545 # 13 ^M CR is encoded as "\n" rendering it indistinguishable from
546 # 10 ^J NL
547 # All other nonprintable characters within the ASCII range (0 through 127
548 # inclusive) are encoded as "\U001f" referring to the Unicode code point in
549 # hexadecimal. For example, character 14 (^N SO) is encoded as "\U000e".
550 # Characters above the ASCII range are passed through to the output encoded
551 # as UTF-8 without any escaping. These mappings are contained in the
552 # class' _encode_transforms list.
553
554 if _unquoted.search(value) and not _quoted.search(value):
555 return value
556
557 return '"' + _escaped.sub(self._EncodeTransform, value) + '"'
558
559 def _XCPrint(self, file, tabs, line):
560 file.write('\t' * tabs + line)
561
562 def _XCPrintableValue(self, tabs, value, flatten_list=False):
563 """Returns a representation of value that may be printed in a project file,
564 mimicing Xcode's behavior.
565
566 _XCPrintableValue can handle str and int values, XCObjects (which are
567 made printable by returning their id property), and list and dict objects
568 composed of any of the above types. When printing a list or dict, and
569 _should_print_single_line is False, the tabs parameter is used to determine
570 how much to indent the lines corresponding to the items in the list or
571 dict.
572
573 If flatten_list is True, single-element lists will be transformed into
574 strings.
575 """
576
577 printable = ''
578 comment = None
579
580 if self._should_print_single_line:
581 sep = ' '
582 element_tabs = ''
583 end_tabs = ''
584 else:
585 sep = '\n'
586 element_tabs = '\t' * (tabs + 1)
587 end_tabs = '\t' * tabs
588
589 if isinstance(value, XCObject):
590 printable += value.id
591 comment = value.Comment()
592 elif isinstance(value, str):
593 printable += self._EncodeString(value)
594 elif isinstance(value, unicode):
595 printable += self._EncodeString(value.encode('utf-8'))
596 elif isinstance(value, int):
597 printable += str(value)
598 elif isinstance(value, list):
599 if flatten_list and len(value) <= 1:
600 if len(value) == 0:
601 printable += self._EncodeString('')
602 else:
603 printable += self._EncodeString(value[0])
604 else:
605 printable = '(' + sep
606 for item in value:
607 printable += element_tabs + \
608 self._XCPrintableValue(tabs + 1, item, flatten_list) + \
609 ',' + sep
610 printable += end_tabs + ')'
611 elif isinstance(value, dict):
612 printable = '{' + sep
613 for item_key, item_value in sorted(value.iteritems()):
614 printable += element_tabs + \
615 self._XCPrintableValue(tabs + 1, item_key, flatten_list) + ' = ' + \
616 self._XCPrintableValue(tabs + 1, item_value, flatten_list) + ';' + \
617 sep
618 printable += end_tabs + '}'
619 else:
620 raise TypeError, "Can't make " + value.__class__.__name__ + ' printable'
621
622 if comment != None:
623 printable += ' ' + self._EncodeComment(comment)
624
625 return printable
626
627 def _XCKVPrint(self, file, tabs, key, value):
628 """Prints a key and value, members of an XCObject's _properties dictionary,
629 to file.
630
631 tabs is an int identifying the indentation level. If the class'
632 _should_print_single_line variable is True, tabs is ignored and the
633 key-value pair will be followed by a space insead of a newline.
634 """
635
636 if self._should_print_single_line:
637 printable = ''
638 after_kv = ' '
639 else:
640 printable = '\t' * tabs
641 after_kv = '\n'
642
643 # Xcode usually prints remoteGlobalIDString values in PBXContainerItemProxy
644 # objects without comments. Sometimes it prints them with comments, but
645 # the majority of the time, it doesn't. To avoid unnecessary changes to
646 # the project file after Xcode opens it, don't write comments for
647 # remoteGlobalIDString. This is a sucky hack and it would certainly be
648 # cleaner to extend the schema to indicate whether or not a comment should
649 # be printed, but since this is the only case where the problem occurs and
650 # Xcode itself can't seem to make up its mind, the hack will suffice.
651 #
652 # Also see PBXContainerItemProxy._schema['remoteGlobalIDString'].
653 if key == 'remoteGlobalIDString' and isinstance(self,
654 PBXContainerItemProxy):
655 value_to_print = value.id
656 else:
657 value_to_print = value
658
659 # PBXBuildFile's settings property is represented in the output as a dict,
660 # but a hack here has it represented as a string. Arrange to strip off the
661 # quotes so that it shows up in the output as expected.
662 if key == 'settings' and isinstance(self, PBXBuildFile):
663 strip_value_quotes = True
664 else:
665 strip_value_quotes = False
666
667 # In another one-off, let's set flatten_list on buildSettings properties
668 # of XCBuildConfiguration objects, because that's how Xcode treats them.
669 if key == 'buildSettings' and isinstance(self, XCBuildConfiguration):
670 flatten_list = True
671 else:
672 flatten_list = False
673
674 try:
675 printable_key = self._XCPrintableValue(tabs, key, flatten_list)
676 printable_value = self._XCPrintableValue(tabs, value_to_print,
677 flatten_list)
678 if strip_value_quotes and len(printable_value) > 1 and \
679 printable_value[0] == '"' and printable_value[-1] == '"':
680 printable_value = printable_value[1:-1]
681 printable += printable_key + ' = ' + printable_value + ';' + after_kv
682 except TypeError, e:
683 gyp.common.ExceptionAppend(e,
684 'while printing key "%s"' % key)
685 raise
686
687 self._XCPrint(file, 0, printable)
688
689 def Print(self, file=sys.stdout):
690 """Prints a reprentation of this object to file, adhering to Xcode output
691 formatting.
692 """
693
694 self.VerifyHasRequiredProperties()
695
696 if self._should_print_single_line:
697 # When printing an object in a single line, Xcode doesn't put any space
698 # between the beginning of a dictionary (or presumably a list) and the
699 # first contained item, so you wind up with snippets like
700 # ...CDEF = {isa = PBXFileReference; fileRef = 0123...
701 # If it were me, I would have put a space in there after the opening
702 # curly, but I guess this is just another one of those inconsistencies
703 # between how Xcode prints PBXFileReference and PBXBuildFile objects as
704 # compared to other objects. Mimic Xcode's behavior here by using an
705 # empty string for sep.
706 sep = ''
707 end_tabs = 0
708 else:
709 sep = '\n'
710 end_tabs = 2
711
712 # Start the object. For example, '\t\tPBXProject = {\n'.
713 self._XCPrint(file, 2, self._XCPrintableValue(2, self) + ' = {' + sep)
714
715 # "isa" isn't in the _properties dictionary, it's an intrinsic property
716 # of the class which the object belongs to. Xcode always outputs "isa"
717 # as the first element of an object dictionary.
718 self._XCKVPrint(file, 3, 'isa', self.__class__.__name__)
719
720 # The remaining elements of an object dictionary are sorted alphabetically.
721 for property, value in sorted(self._properties.iteritems()):
722 self._XCKVPrint(file, 3, property, value)
723
724 # End the object.
725 self._XCPrint(file, end_tabs, '};\n')
726
727 def UpdateProperties(self, properties, do_copy=False):
728 """Merge the supplied properties into the _properties dictionary.
729
730 The input properties must adhere to the class schema or a KeyError or
731 TypeError exception will be raised. If adding an object of an XCObject
732 subclass and the schema indicates a strong relationship, the object's
733 parent will be set to this object.
734
735 If do_copy is True, then lists, dicts, strong-owned XCObjects, and
736 strong-owned XCObjects in lists will be copied instead of having their
737 references added.
738 """
739
740 if properties == None:
741 return
742
743 for property, value in properties.iteritems():
744 # Make sure the property is in the schema.
745 if not property in self._schema:
746 raise KeyError, property + ' not in ' + self.__class__.__name__
747
748 # Make sure the property conforms to the schema.
749 (is_list, property_type, is_strong) = self._schema[property][0:3]
750 if is_list:
751 if value.__class__ != list:
752 raise TypeError, \
753 property + ' of ' + self.__class__.__name__ + \
754 ' must be list, not ' + value.__class__.__name__
755 for item in value:
756 if not isinstance(item, property_type) and \
757 not (item.__class__ == unicode and property_type == str):
758 # Accept unicode where str is specified. str is treated as
759 # UTF-8-encoded.
760 raise TypeError, \
761 'item of ' + property + ' of ' + self.__class__.__name__ + \
762 ' must be ' + property_type.__name__ + ', not ' + \
763 item.__class__.__name__
764 elif not isinstance(value, property_type) and \
765 not (value.__class__ == unicode and property_type == str):
766 # Accept unicode where str is specified. str is treated as
767 # UTF-8-encoded.
768 raise TypeError, \
769 property + ' of ' + self.__class__.__name__ + ' must be ' + \
770 property_type.__name__ + ', not ' + value.__class__.__name__
771
772 # Checks passed, perform the assignment.
773 if do_copy:
774 if isinstance(value, XCObject):
775 if is_strong:
776 self._properties[property] = value.Copy()
777 else:
778 self._properties[property] = value
779 elif isinstance(value, str) or isinstance(value, unicode) or \
780 isinstance(value, int):
781 self._properties[property] = value
782 elif isinstance(value, list):
783 if is_strong:
784 # If is_strong is True, each element is an XCObject, so it's safe
785 # to call Copy.
786 self._properties[property] = []
787 for item in value:
788 self._properties[property].append(item.Copy())
789 else:
790 self._properties[property] = value[:]
791 elif isinstance(value, dict):
792 self._properties[property] = value.copy()
793 else:
794 raise TypeError, "Don't know how to copy a " + \
795 value.__class__.__name__ + ' object for ' + \
796 property + ' in ' + self.__class__.__name__
797 else:
798 self._properties[property] = value
799
800 # Set up the child's back-reference to this object. Don't use |value|
801 # any more because it may not be right if do_copy is true.
802 if is_strong:
803 if not is_list:
804 self._properties[property].parent = self
805 else:
806 for item in self._properties[property]:
807 item.parent = self
808
809 def HasProperty(self, key):
810 return key in self._properties
811
812 def GetProperty(self, key):
813 return self._properties[key]
814
815 def SetProperty(self, key, value):
816 self.UpdateProperties({key: value})
817
818 def DelProperty(self, key):
819 if key in self._properties:
820 del self._properties[key]
821
822 def AppendProperty(self, key, value):
823 # TODO(mark): Support ExtendProperty too (and make this call that)?
824
825 # Schema validation.
826 if not key in self._schema:
827 raise KeyError, key + ' not in ' + self.__class__.__name__
828
829 (is_list, property_type, is_strong) = self._schema[key][0:3]
830 if not is_list:
831 raise TypeError, key + ' of ' + self.__class__.__name__ + ' must be list'
832 if not isinstance(value, property_type):
833 raise TypeError, 'item of ' + key + ' of ' + self.__class__.__name__ + \
834 ' must be ' + property_type.__name__ + ', not ' + \
835 value.__class__.__name__
836
837 # If the property doesn't exist yet, create a new empty list to receive the
838 # item.
839 if not key in self._properties:
840 self._properties[key] = []
841
842 # Set up the ownership link.
843 if is_strong:
844 value.parent = self
845
846 # Store the item.
847 self._properties[key].append(value)
848
849 def VerifyHasRequiredProperties(self):
850 """Ensure that all properties identified as required by the schema are
851 set.
852 """
853
854 # TODO(mark): A stronger verification mechanism is needed. Some
855 # subclasses need to perform validation beyond what the schema can enforce.
856 for property, attributes in self._schema.iteritems():
857 (is_list, property_type, is_strong, is_required) = attributes[0:4]
858 if is_required and not property in self._properties:
859 raise KeyError, self.__class__.__name__ + ' requires ' + property
860
861 def _SetDefaultsFromSchema(self):
862 """Assign object default values according to the schema. This will not
863 overwrite properties that have already been set."""
864
865 defaults = {}
866 for property, attributes in self._schema.iteritems():
867 (is_list, property_type, is_strong, is_required) = attributes[0:4]
868 if is_required and len(attributes) >= 5 and \
869 not property in self._properties:
870 default = attributes[4]
871
872 defaults[property] = default
873
874 if len(defaults) > 0:
875 # Use do_copy=True so that each new object gets its own copy of strong
876 # objects, lists, and dicts.
877 self.UpdateProperties(defaults, do_copy=True)
878
879
880 class XCHierarchicalElement(XCObject):
881 """Abstract base for PBXGroup and PBXFileReference. Not represented in a
882 project file."""
883
884 # TODO(mark): Do name and path belong here? Probably so.
885 # If path is set and name is not, name may have a default value. Name will
886 # be set to the basename of path, if the basename of path is different from
887 # the full value of path. If path is already just a leaf name, name will
888 # not be set.
889 _schema = XCObject._schema.copy()
890 _schema.update({
891 'comments': [0, str, 0, 0],
892 'fileEncoding': [0, str, 0, 0],
893 'includeInIndex': [0, int, 0, 0],
894 'indentWidth': [0, int, 0, 0],
895 'lineEnding': [0, int, 0, 0],
896 'sourceTree': [0, str, 0, 1, '<group>'],
897 'tabWidth': [0, int, 0, 0],
898 'usesTabs': [0, int, 0, 0],
899 'wrapsLines': [0, int, 0, 0],
900 })
901
902 def __init__(self, properties=None, id=None, parent=None):
903 # super
904 XCObject.__init__(self, properties, id, parent)
905 if 'path' in self._properties and not 'name' in self._properties:
906 path = self._properties['path']
907 name = posixpath.basename(path)
908 if name != '' and path != name:
909 self.SetProperty('name', name)
910
911 if 'path' in self._properties and \
912 (not 'sourceTree' in self._properties or \
913 self._properties['sourceTree'] == '<group>'):
914 # If the pathname begins with an Xcode variable like "$(SDKROOT)/", take
915 # the variable out and make the path be relative to that variable by
916 # assigning the variable name as the sourceTree.
917 (source_tree, path) = SourceTreeAndPathFromPath(self._properties['path'])
918 if source_tree != None:
919 self._properties['sourceTree'] = source_tree
920 if path != None:
921 self._properties['path'] = path
922 if source_tree != None and path == None and \
923 not 'name' in self._properties:
924 # The path was of the form "$(SDKROOT)" with no path following it.
925 # This object is now relative to that variable, so it has no path
926 # attribute of its own. It does, however, keep a name.
927 del self._properties['path']
928 self._properties['name'] = source_tree
929
930 def Name(self):
931 if 'name' in self._properties:
932 return self._properties['name']
933 elif 'path' in self._properties:
934 return self._properties['path']
935 else:
936 # This happens in the case of the root PBXGroup.
937 return None
938
939 def Hashables(self):
940 """Custom hashables for XCHierarchicalElements.
941
942 XCHierarchicalElements are special. Generally, their hashes shouldn't
943 change if the paths don't change. The normal XCObject implementation of
944 Hashables adds a hashable for each object, which means that if
945 the hierarchical structure changes (possibly due to changes caused when
946 TakeOverOnlyChild runs and encounters slight changes in the hierarchy),
947 the hashes will change. For example, if a project file initially contains
948 a/b/f1 and a/b becomes collapsed into a/b, f1 will have a single parent
949 a/b. If someone later adds a/f2 to the project file, a/b can no longer be
950 collapsed, and f1 winds up with parent b and grandparent a. That would
951 be sufficient to change f1's hash.
952
953 To counteract this problem, hashables for all XCHierarchicalElements except
954 for the main group (which has neither a name nor a path) are taken to be
955 just the set of path components. Because hashables are inherited from
956 parents, this provides assurance that a/b/f1 has the same set of hashables
957 whether its parent is b or a/b.
958
959 The main group is a special case. As it is permitted to have no name or
960 path, it is permitted to use the standard XCObject hash mechanism. This
961 is not considered a problem because there can be only one main group.
962 """
963
964 if self == self.PBXProjectAncestor()._properties['mainGroup']:
965 # super
966 return XCObject.Hashables(self)
967
968 hashables = []
969
970 # Put the name in first, ensuring that if TakeOverOnlyChild collapses
971 # children into a top-level group like "Source", the name always goes
972 # into the list of hashables without interfering with path components.
973 if 'name' in self._properties:
974 # Make it less likely for people to manipulate hashes by following the
975 # pattern of always pushing an object type value onto the list first.
976 hashables.append(self.__class__.__name__ + '.name')
977 hashables.append(self._properties['name'])
978
979 # NOTE: This still has the problem that if an absolute path is encountered,
980 # including paths with a sourceTree, they'll still inherit their parents'
981 # hashables, even though the paths aren't relative to their parents. This
982 # is not expected to be much of a problem in practice.
983 path = self.PathFromSourceTreeAndPath()
984 if path != None:
985 components = path.split(posixpath.sep)
986 for component in components:
987 hashables.append(self.__class__.__name__ + '.path')
988 hashables.append(component)
989
990 hashables.extend(self._hashables)
991
992 return hashables
993
994 def Compare(self, other):
995 # Allow comparison of these types. PBXGroup has the highest sort rank;
996 # PBXVariantGroup is treated as equal to PBXFileReference.
997 valid_class_types = {
998 PBXFileReference: 'file',
999 PBXGroup: 'group',
1000 PBXVariantGroup: 'file',
1001 }
1002 self_type = valid_class_types[self.__class__]
1003 other_type = valid_class_types[other.__class__]
1004
1005 if self_type == other_type:
1006 # If the two objects are of the same sort rank, compare their names.
1007 return cmp(self.Name(), other.Name())
1008
1009 # Otherwise, sort groups before everything else.
1010 if self_type == 'group':
1011 return -1
1012 return 1
1013
1014 def CompareRootGroup(self, other):
1015 # This function should be used only to compare direct children of the
1016 # containing PBXProject's mainGroup. These groups should appear in the
1017 # listed order.
1018 # TODO(mark): "Build" is used by gyp.generator.xcode, perhaps the
1019 # generator should have a way of influencing this list rather than having
1020 # to hardcode for the generator here.
1021 order = ['Source', 'Intermediates', 'Projects', 'Frameworks', 'Products',
1022 'Build']
1023
1024 # If the groups aren't in the listed order, do a name comparison.
1025 # Otherwise, groups in the listed order should come before those that
1026 # aren't.
1027 self_name = self.Name()
1028 other_name = other.Name()
1029 self_in = isinstance(self, PBXGroup) and self_name in order
1030 other_in = isinstance(self, PBXGroup) and other_name in order
1031 if not self_in and not other_in:
1032 return self.Compare(other)
1033 if self_name in order and not other_name in order:
1034 return -1
1035 if other_name in order and not self_name in order:
1036 return 1
1037
1038 # If both groups are in the listed order, go by the defined order.
1039 self_index = order.index(self_name)
1040 other_index = order.index(other_name)
1041 if self_index < other_index:
1042 return -1
1043 if self_index > other_index:
1044 return 1
1045 return 0
1046
1047 def PathFromSourceTreeAndPath(self):
1048 # Turn the object's sourceTree and path properties into a single flat
1049 # string of a form comparable to the path parameter. If there's a
1050 # sourceTree property other than "<group>", wrap it in $(...) for the
1051 # comparison.
1052 components = []
1053 if self._properties['sourceTree'] != '<group>':
1054 components.append('$(' + self._properties['sourceTree'] + ')')
1055 if 'path' in self._properties:
1056 components.append(self._properties['path'])
1057
1058 if len(components) > 0:
1059 return posixpath.join(*components)
1060
1061 return None
1062
1063 def FullPath(self):
1064 # Returns a full path to self relative to the project file, or relative
1065 # to some other source tree. Start with self, and walk up the chain of
1066 # parents prepending their paths, if any, until no more parents are
1067 # available (project-relative path) or until a path relative to some
1068 # source tree is found.
1069 xche = self
1070 path = None
1071 while isinstance(xche, XCHierarchicalElement) and \
1072 (path == None or \
1073 (not path.startswith('/') and not path.startswith('$'))):
1074 this_path = xche.PathFromSourceTreeAndPath()
1075 if this_path != None and path != None:
1076 path = posixpath.join(this_path, path)
1077 elif this_path != None:
1078 path = this_path
1079 xche = xche.parent
1080
1081 return path
1082
1083
1084 class PBXGroup(XCHierarchicalElement):
1085 """
1086 Attributes:
1087 _children_by_path: Maps pathnames of children of this PBXGroup to the
1088 actual child XCHierarchicalElement objects.
1089 _variant_children_by_name_and_path: Maps (name, path) tuples of
1090 PBXVariantGroup children to the actual child PBXVariantGroup objects.
1091 """
1092
1093 _schema = XCHierarchicalElement._schema.copy()
1094 _schema.update({
1095 'children': [1, XCHierarchicalElement, 1, 1, []],
1096 'name': [0, str, 0, 0],
1097 'path': [0, str, 0, 0],
1098 })
1099
1100 def __init__(self, properties=None, id=None, parent=None):
1101 # super
1102 XCHierarchicalElement.__init__(self, properties, id, parent)
1103 self._children_by_path = {}
1104 self._variant_children_by_name_and_path = {}
1105 for child in self._properties.get('children', []):
1106 self._AddChildToDicts(child)
1107
1108 def _AddChildToDicts(self, child):
1109 # Sets up this PBXGroup object's dicts to reference the child properly.
1110 child_path = child.PathFromSourceTreeAndPath()
1111 if child_path:
1112 if child_path in self._children_by_path:
1113 raise ValueError, 'Found multiple children with path ' + child_path
1114 self._children_by_path[child_path] = child
1115
1116 if isinstance(child, PBXVariantGroup):
1117 child_name = child._properties.get('name', None)
1118 key = (child_name, child_path)
1119 if key in self._variant_children_by_name_and_path:
1120 raise ValueError, 'Found multiple PBXVariantGroup children with ' + \
1121 'name ' + str(child_name) + ' and path ' + \
1122 str(child_path)
1123 self._variant_children_by_name_and_path[key] = child
1124
1125 def AppendChild(self, child):
1126 # Callers should use this instead of calling
1127 # AppendProperty('children', child) directly because this function
1128 # maintains the group's dicts.
1129 self.AppendProperty('children', child)
1130 self._AddChildToDicts(child)
1131
1132 def GetChildByName(self, name):
1133 # This is not currently optimized with a dict as GetChildByPath is because
1134 # it has few callers. Most callers probably want GetChildByPath. This
1135 # function is only useful to get children that have names but no paths,
1136 # which is rare. The children of the main group ("Source", "Products",
1137 # etc.) is pretty much the only case where this likely to come up.
1138 #
1139 # TODO(mark): Maybe this should raise an error if more than one child is
1140 # present with the same name.
1141 if not 'children' in self._properties:
1142 return None
1143
1144 for child in self._properties['children']:
1145 if child.Name() == name:
1146 return child
1147
1148 return None
1149
1150 def GetChildByPath(self, path):
1151 if not path:
1152 return None
1153
1154 if path in self._children_by_path:
1155 return self._children_by_path[path]
1156
1157 return None
1158
1159 def GetChildByRemoteObject(self, remote_object):
1160 # This method is a little bit esoteric. Given a remote_object, which
1161 # should be a PBXFileReference in another project file, this method will
1162 # return this group's PBXReferenceProxy object serving as a local proxy
1163 # for the remote PBXFileReference.
1164 #
1165 # This function might benefit from a dict optimization as GetChildByPath
1166 # for some workloads, but profiling shows that it's not currently a
1167 # problem.
1168 if not 'children' in self._properties:
1169 return None
1170
1171 for child in self._properties['children']:
1172 if not isinstance(child, PBXReferenceProxy):
1173 continue
1174
1175 container_proxy = child._properties['remoteRef']
1176 if container_proxy._properties['remoteGlobalIDString'] == remote_object:
1177 return child
1178
1179 return None
1180
1181 def AddOrGetFileByPath(self, path, hierarchical):
1182 """Returns an existing or new file reference corresponding to path.
1183
1184 If hierarchical is True, this method will create or use the necessary
1185 hierarchical group structure corresponding to path. Otherwise, it will
1186 look in and create an item in the current group only.
1187
1188 If an existing matching reference is found, it is returned, otherwise, a
1189 new one will be created, added to the correct group, and returned.
1190
1191 If path identifies a directory by virtue of carrying a trailing slash,
1192 this method returns a PBXFileReference of "folder" type. If path
1193 identifies a variant, by virtue of it identifying a file inside a directory
1194 with an ".lproj" extension, this method returns a PBXVariantGroup
1195 containing the variant named by path, and possibly other variants. For
1196 all other paths, a "normal" PBXFileReference will be returned.
1197 """
1198
1199 # Adding or getting a directory? Directories end with a trailing slash.
1200 is_dir = False
1201 if path.endswith('/'):
1202 is_dir = True
1203 normpath = posixpath.normpath(path)
1204 if is_dir:
1205 normpath = path + '/'
1206 else:
1207 normpath = path
1208
1209 # Adding or getting a variant? Variants are files inside directories
1210 # with an ".lproj" extension. Xcode uses variants for localization. For
1211 # a variant path/to/Language.lproj/MainMenu.nib, put a variant group named
1212 # MainMenu.nib inside path/to, and give it a variant named Language. In
1213 # this example, grandparent would be set to path/to and parent_root would
1214 # be set to Language.
1215 variant_name = None
1216 parent = posixpath.dirname(path)
1217 grandparent = posixpath.dirname(parent)
1218 parent_basename = posixpath.basename(parent)
1219 (parent_root, parent_ext) = posixpath.splitext(parent_basename)
1220 if parent_ext == '.lproj':
1221 variant_name = parent_root
1222 if grandparent == '':
1223 grandparent = None
1224
1225 # Putting a directory inside a variant group is not currently supported.
1226 assert not is_dir or variant_name == None
1227
1228 path_split = path.split(posixpath.sep)
1229 if len(path_split) == 1 or \
1230 ((is_dir or variant_name != None) and len(path_split) == 2) or \
1231 not hierarchical:
1232 # The PBXFileReference or PBXVariantGroup will be added to or gotten from
1233 # this PBXGroup, no recursion necessary.
1234 if variant_name == None:
1235 # Add or get a PBXFileReference.
1236 file_ref = self.GetChildByPath(normpath)
1237 if file_ref != None:
1238 assert file_ref.__class__ == PBXFileReference
1239 else:
1240 file_ref = PBXFileReference({'path': path})
1241 self.AppendChild(file_ref)
1242 else:
1243 # Add or get a PBXVariantGroup. The variant group name is the same
1244 # as the basename (MainMenu.nib in the example above). grandparent
1245 # specifies the path to the variant group itself, and path_split[-2:]
1246 # is the path of the specific variant relative to its group.
1247 variant_group_name = posixpath.basename(path)
1248 variant_group_ref = self.AddOrGetVariantGroupByNameAndPath(
1249 variant_group_name, grandparent)
1250 variant_path = posixpath.sep.join(path_split[-2:])
1251 variant_ref = variant_group_ref.GetChildByPath(variant_path)
1252 if variant_ref != None:
1253 assert variant_ref.__class__ == PBXFileReference
1254 else:
1255 variant_ref = PBXFileReference({'name': variant_name,
1256 'path': variant_path})
1257 variant_group_ref.AppendChild(variant_ref)
1258 # The caller is interested in the variant group, not the specific
1259 # variant file.
1260 file_ref = variant_group_ref
1261 return file_ref
1262 else:
1263 # Hierarchical recursion. Add or get a PBXGroup corresponding to the
1264 # outermost path component, and then recurse into it, chopping off that
1265 # path component.
1266 next_dir = path_split[0]
1267 group_ref = self.GetChildByPath(next_dir)
1268 if group_ref != None:
1269 assert group_ref.__class__ == PBXGroup
1270 else:
1271 group_ref = PBXGroup({'path': next_dir})
1272 self.AppendChild(group_ref)
1273 return group_ref.AddOrGetFileByPath(posixpath.sep.join(path_split[1:]),
1274 hierarchical)
1275
1276 def AddOrGetVariantGroupByNameAndPath(self, name, path):
1277 """Returns an existing or new PBXVariantGroup for name and path.
1278
1279 If a PBXVariantGroup identified by the name and path arguments is already
1280 present as a child of this object, it is returned. Otherwise, a new
1281 PBXVariantGroup with the correct properties is created, added as a child,
1282 and returned.
1283
1284 This method will generally be called by AddOrGetFileByPath, which knows
1285 when to create a variant group based on the structure of the pathnames
1286 passed to it.
1287 """
1288
1289 key = (name, path)
1290 if key in self._variant_children_by_name_and_path:
1291 variant_group_ref = self._variant_children_by_name_and_path[key]
1292 assert variant_group_ref.__class__ == PBXVariantGroup
1293 return variant_group_ref
1294
1295 variant_group_properties = {'name': name}
1296 if path != None:
1297 variant_group_properties['path'] = path
1298 variant_group_ref = PBXVariantGroup(variant_group_properties)
1299 self.AppendChild(variant_group_ref)
1300
1301 return variant_group_ref
1302
1303 def TakeOverOnlyChild(self, recurse=False):
1304 """If this PBXGroup has only one child and it's also a PBXGroup, take
1305 it over by making all of its children this object's children.
1306
1307 This function will continue to take over only children when those children
1308 are groups. If there are three PBXGroups representing a, b, and c, with
1309 c inside b and b inside a, and a and b have no other children, this will
1310 result in a taking over both b and c, forming a PBXGroup for a/b/c.
1311
1312 If recurse is True, this function will recurse into children and ask them
1313 to collapse themselves by taking over only children as well. Assuming
1314 an example hierarchy with files at a/b/c/d1, a/b/c/d2, and a/b/c/d3/e/f
1315 (d1, d2, and f are files, the rest are groups), recursion will result in
1316 a group for a/b/c containing a group for d3/e.
1317 """
1318
1319 # At this stage, check that child class types are PBXGroup exactly,
1320 # instead of using isinstance. The only subclass of PBXGroup,
1321 # PBXVariantGroup, should not participate in reparenting in the same way:
1322 # reparenting by merging different object types would be wrong.
1323 while len(self._properties['children']) == 1 and \
1324 self._properties['children'][0].__class__ == PBXGroup:
1325 # Loop to take over the innermost only-child group possible.
1326
1327 child = self._properties['children'][0]
1328
1329 # Assume the child's properties, including its children. Save a copy
1330 # of this object's old properties, because they'll still be needed.
1331 # This object retains its existing id and parent attributes.
1332 old_properties = self._properties
1333 self._properties = child._properties
1334 self._children_by_path = child._children_by_path
1335
1336 if not 'sourceTree' in self._properties or \
1337 self._properties['sourceTree'] == '<group>':
1338 # The child was relative to its parent. Fix up the path. Note that
1339 # children with a sourceTree other than "<group>" are not relative to
1340 # their parents, so no path fix-up is needed in that case.
1341 if 'path' in old_properties:
1342 if 'path' in self._properties:
1343 # Both the original parent and child have paths set.
1344 self._properties['path'] = posixpath.join(old_properties['path'],
1345 self._properties['path'])
1346 else:
1347 # Only the original parent has a path, use it.
1348 self._properties['path'] = old_properties['path']
1349 if 'sourceTree' in old_properties:
1350 # The original parent had a sourceTree set, use it.
1351 self._properties['sourceTree'] = old_properties['sourceTree']
1352
1353 # If the original parent had a name set, keep using it. If the original
1354 # parent didn't have a name but the child did, let the child's name
1355 # live on. If the name attribute seems unnecessary now, get rid of it.
1356 if 'name' in old_properties and old_properties['name'] != None and \
1357 old_properties['name'] != self.Name():
1358 self._properties['name'] = old_properties['name']
1359 if 'name' in self._properties and 'path' in self._properties and \
1360 self._properties['name'] == self._properties['path']:
1361 del self._properties['name']
1362
1363 # Notify all children of their new parent.
1364 for child in self._properties['children']:
1365 child.parent = self
1366
1367 # If asked to recurse, recurse.
1368 if recurse:
1369 for child in self._properties['children']:
1370 if child.__class__ == PBXGroup:
1371 child.TakeOverOnlyChild(recurse)
1372
1373 def SortGroup(self):
1374 self._properties['children'] = \
1375 sorted(self._properties['children'], cmp=lambda x,y: x.Compare(y))
1376
1377 # Recurse.
1378 for child in self._properties['children']:
1379 if isinstance(child, PBXGroup):
1380 child.SortGroup()
1381
1382
1383 class XCFileLikeElement(XCHierarchicalElement):
1384 # Abstract base for objects that can be used as the fileRef property of
1385 # PBXBuildFile.
1386
1387 def PathHashables(self):
1388 # A PBXBuildFile that refers to this object will call this method to
1389 # obtain additional hashables specific to this XCFileLikeElement. Don't
1390 # just use this object's hashables, they're not specific and unique enough
1391 # on their own (without access to the parent hashables.) Instead, provide
1392 # hashables that identify this object by path by getting its hashables as
1393 # well as the hashables of ancestor XCHierarchicalElement objects.
1394
1395 hashables = []
1396 xche = self
1397 while xche != None and isinstance(xche, XCHierarchicalElement):
1398 xche_hashables = xche.Hashables()
1399 for index in xrange(0, len(xche_hashables)):
1400 hashables.insert(index, xche_hashables[index])
1401 xche = xche.parent
1402 return hashables
1403
1404
1405 class XCContainerPortal(XCObject):
1406 # Abstract base for objects that can be used as the containerPortal property
1407 # of PBXContainerItemProxy.
1408 pass
1409
1410
1411 class XCRemoteObject(XCObject):
1412 # Abstract base for objects that can be used as the remoteGlobalIDString
1413 # property of PBXContainerItemProxy.
1414 pass
1415
1416
1417 class PBXFileReference(XCFileLikeElement, XCContainerPortal, XCRemoteObject):
1418 _schema = XCFileLikeElement._schema.copy()
1419 _schema.update({
1420 'explicitFileType': [0, str, 0, 0],
1421 'lastKnownFileType': [0, str, 0, 0],
1422 'name': [0, str, 0, 0],
1423 'path': [0, str, 0, 1],
1424 })
1425
1426 # Weird output rules for PBXFileReference.
1427 _should_print_single_line = True
1428 # super
1429 _encode_transforms = XCFileLikeElement._alternate_encode_transforms
1430
1431 def __init__(self, properties=None, id=None, parent=None):
1432 # super
1433 XCFileLikeElement.__init__(self, properties, id, parent)
1434 if 'path' in self._properties and self._properties['path'].endswith('/'):
1435 self._properties['path'] = self._properties['path'][:-1]
1436 is_dir = True
1437 else:
1438 is_dir = False
1439
1440 if 'path' in self._properties and \
1441 not 'lastKnownFileType' in self._properties and \
1442 not 'explicitFileType' in self._properties:
1443 # TODO(mark): This is the replacement for a replacement for a quick hack.
1444 # It is no longer incredibly sucky, but this list needs to be extended.
1445 extension_map = {
1446 'a': 'archive.ar',
1447 'app': 'wrapper.application',
1448 'bdic': 'file',
1449 'bundle': 'wrapper.cfbundle',
1450 'c': 'sourcecode.c.c',
1451 'cc': 'sourcecode.cpp.cpp',
1452 'cpp': 'sourcecode.cpp.cpp',
1453 'css': 'text.css',
1454 'cxx': 'sourcecode.cpp.cpp',
1455 'dylib': 'compiled.mach-o.dylib',
1456 'framework': 'wrapper.framework',
1457 'h': 'sourcecode.c.h',
1458 'hxx': 'sourcecode.cpp.h',
1459 'icns': 'image.icns',
1460 'java': 'sourcecode.java',
1461 'js': 'sourcecode.javascript',
1462 'm': 'sourcecode.c.objc',
1463 'mm': 'sourcecode.cpp.objcpp',
1464 'nib': 'wrapper.nib',
1465 'o': 'compiled.mach-o.objfile',
1466 'pdf': 'image.pdf',
1467 'pl': 'text.script.perl',
1468 'plist': 'text.plist.xml',
1469 'pm': 'text.script.perl',
1470 'png': 'image.png',
1471 'py': 'text.script.python',
1472 'r': 'sourcecode.rez',
1473 'rez': 'sourcecode.rez',
1474 's': 'sourcecode.asm',
1475 'strings': 'text.plist.strings',
1476 'ttf': 'file',
1477 'xcconfig': 'text.xcconfig',
1478 'xib': 'file.xib',
1479 'y': 'sourcecode.yacc',
1480 }
1481
1482 if is_dir:
1483 file_type = 'folder'
1484 else:
1485 basename = posixpath.basename(self._properties['path'])
1486 (root, ext) = posixpath.splitext(basename)
1487 # Check the map using a lowercase extension.
1488 # TODO(mark): Maybe it should try with the original case first and fall
1489 # back to lowercase, in case there are any instances where case
1490 # matters. There currently aren't.
1491 if ext != '':
1492 ext = ext[1:].lower()
1493
1494 # TODO(mark): "text" is the default value, but "file" is appropriate
1495 # for unrecognized files not containing text. Xcode seems to choose
1496 # based on content.
1497 file_type = extension_map.get(ext, 'text')
1498
1499 self._properties['lastKnownFileType'] = file_type
1500
1501
1502 class PBXVariantGroup(PBXGroup, XCFileLikeElement):
1503 """PBXVariantGroup is used by Xcode to represent localizations."""
1504 # No additions to the schema relative to PBXGroup.
1505 pass
1506
1507
1508 # PBXReferenceProxy is also an XCFileLikeElement subclass. It is defined below
1509 # because it uses PBXContainerItemProxy, defined below.
1510
1511
1512 class XCBuildConfiguration(XCObject):
1513 _schema = XCObject._schema.copy()
1514 _schema.update({
1515 'baseConfigurationReference': [0, PBXFileReference, 0, 0],
1516 'buildSettings': [0, dict, 0, 1, {}],
1517 'name': [0, str, 0, 1],
1518 })
1519
1520 def HasBuildSetting(self, key):
1521 return key in self._properties['buildSettings']
1522
1523 def GetBuildSetting(self, key):
1524 return self._properties['buildSettings'][key]
1525
1526 def SetBuildSetting(self, key, value):
1527 # TODO(mark): If a list, copy?
1528 self._properties['buildSettings'][key] = value
1529
1530 def AppendBuildSetting(self, key, value):
1531 if not key in self._properties['buildSettings']:
1532 self._properties['buildSettings'][key] = []
1533 self._properties['buildSettings'][key].append(value)
1534
1535 def DelBuildSetting(self, key):
1536 if key in self._properties['buildSettings']:
1537 del self._properties['buildSettings'][key]
1538
1539 def SetBaseConfiguration(self, value):
1540 self._properties['baseConfigurationReference'] = value
1541
1542 class XCConfigurationList(XCObject):
1543 # _configs is the default list of configurations.
1544 _configs = [ XCBuildConfiguration({'name': 'Debug'}),
1545 XCBuildConfiguration({'name': 'Release'}) ]
1546
1547 _schema = XCObject._schema.copy()
1548 _schema.update({
1549 'buildConfigurations': [1, XCBuildConfiguration, 1, 1, _configs],
1550 'defaultConfigurationIsVisible': [0, int, 0, 1, 1],
1551 'defaultConfigurationName': [0, str, 0, 1, 'Release'],
1552 })
1553
1554 def Name(self):
1555 return 'Build configuration list for ' + \
1556 self.parent.__class__.__name__ + ' "' + self.parent.Name() + '"'
1557
1558 def ConfigurationNamed(self, name):
1559 """Convenience accessor to obtain an XCBuildConfiguration by name."""
1560 for configuration in self._properties['buildConfigurations']:
1561 if configuration._properties['name'] == name:
1562 return configuration
1563
1564 raise KeyError, name
1565
1566 def DefaultConfiguration(self):
1567 """Convenience accessor to obtain the default XCBuildConfiguration."""
1568 return self.ConfigurationNamed(self._properties['defaultConfigurationName'])
1569
1570 def HasBuildSetting(self, key):
1571 """Determines the state of a build setting in all XCBuildConfiguration
1572 child objects.
1573
1574 If all child objects have key in their build settings, and the value is the
1575 same in all child objects, returns 1.
1576
1577 If no child objects have the key in their build settings, returns 0.
1578
1579 If some, but not all, child objects have the key in their build settings,
1580 or if any children have different values for the key, returns -1.
1581 """
1582
1583 has = None
1584 value = None
1585 for configuration in self._properties['buildConfigurations']:
1586 configuration_has = configuration.HasBuildSetting(key)
1587 if has == None:
1588 has = configuration_has
1589 elif has != configuration_has:
1590 return -1
1591
1592 if configuration_has:
1593 configuration_value = configuration.GetBuildSetting(key)
1594 if value == None:
1595 value = configuration_value
1596 elif value != configuration_value:
1597 return -1
1598
1599 if not has:
1600 return 0
1601
1602 return 1
1603
1604 def GetBuildSetting(self, key):
1605 """Gets the build setting for key.
1606
1607 All child XCConfiguration objects must have the same value set for the
1608 setting, or a ValueError will be raised.
1609 """
1610
1611 # TODO(mark): This is wrong for build settings that are lists. The list
1612 # contents should be compared (and a list copy returned?)
1613
1614 value = None
1615 for configuration in self._properties['buildConfigurations']:
1616 configuration_value = configuration.GetBuildSetting(key)
1617 if value == None:
1618 value = configuration_value
1619 else:
1620 if value != configuration_value:
1621 raise ValueError, 'Variant values for ' + key
1622
1623 return value
1624
1625 def SetBuildSetting(self, key, value):
1626 """Sets the build setting for key to value in all child
1627 XCBuildConfiguration objects.
1628 """
1629
1630 for configuration in self._properties['buildConfigurations']:
1631 configuration.SetBuildSetting(key, value)
1632
1633 def AppendBuildSetting(self, key, value):
1634 """Appends value to the build setting for key, which is treated as a list,
1635 in all child XCBuildConfiguration objects.
1636 """
1637
1638 for configuration in self._properties['buildConfigurations']:
1639 configuration.AppendBuildSetting(key, value)
1640
1641 def DelBuildSetting(self, key):
1642 """Deletes the build setting key from all child XCBuildConfiguration
1643 objects.
1644 """
1645
1646 for configuration in self._properties['buildConfigurations']:
1647 configuration.DelBuildSetting(key)
1648
1649 def SetBaseConfiguration(self, value):
1650 """Sets the build configuration in all child XCBuildConfiguration objects.
1651 """
1652
1653 for configuration in self._properties['buildConfigurations']:
1654 configuration.SetBaseConfiguration(value)
1655
1656
1657 class PBXBuildFile(XCObject):
1658 _schema = XCObject._schema.copy()
1659 _schema.update({
1660 'fileRef': [0, XCFileLikeElement, 0, 1],
1661 'settings': [0, str, 0, 0], # hack, it's a dict
1662 })
1663
1664 # Weird output rules for PBXBuildFile.
1665 _should_print_single_line = True
1666 _encode_transforms = XCObject._alternate_encode_transforms
1667
1668 def Name(self):
1669 # Example: "main.cc in Sources"
1670 return self._properties['fileRef'].Name() + ' in ' + self.parent.Name()
1671
1672 def Hashables(self):
1673 # super
1674 hashables = XCObject.Hashables(self)
1675
1676 # It is not sufficient to just rely on Name() to get the
1677 # XCFileLikeElement's name, because that is not a complete pathname.
1678 # PathHashables returns hashables unique enough that no two
1679 # PBXBuildFiles should wind up with the same set of hashables, unless
1680 # someone adds the same file multiple times to the same target. That
1681 # would be considered invalid anyway.
1682 hashables.extend(self._properties['fileRef'].PathHashables())
1683
1684 return hashables
1685
1686
1687 class XCBuildPhase(XCObject):
1688 """Abstract base for build phase classes. Not represented in a project
1689 file.
1690
1691 Attributes:
1692 _files_by_path: A dict mapping each path of a child in the files list by
1693 path (keys) to the corresponding PBXBuildFile children (values).
1694 _files_by_xcfilelikeelement: A dict mapping each XCFileLikeElement (keys)
1695 to the corresponding PBXBuildFile children (values).
1696 """
1697
1698 # TODO(mark): Some build phase types, like PBXShellScriptBuildPhase, don't
1699 # actually have a "files" list. XCBuildPhase should not have "files" but
1700 # another abstract subclass of it should provide this, and concrete build
1701 # phase types that do have "files" lists should be derived from that new
1702 # abstract subclass. XCBuildPhase should only provide buildActionMask and
1703 # runOnlyForDeploymentPostprocessing, and not files or the various
1704 # file-related methods and attributes.
1705
1706 _schema = XCObject._schema.copy()
1707 _schema.update({
1708 'buildActionMask': [0, int, 0, 1, 0x7fffffff],
1709 'files': [1, PBXBuildFile, 1, 1, []],
1710 'runOnlyForDeploymentPostprocessing': [0, int, 0, 1, 0],
1711 })
1712
1713 def __init__(self, properties=None, id=None, parent=None):
1714 # super
1715 XCObject.__init__(self, properties, id, parent)
1716
1717 self._files_by_path = {}
1718 self._files_by_xcfilelikeelement = {}
1719 for pbxbuildfile in self._properties.get('files', []):
1720 self._AddBuildFileToDicts(pbxbuildfile)
1721
1722 def FileGroup(self, path):
1723 # Subclasses must override this by returning a two-element tuple. The
1724 # first item in the tuple should be the PBXGroup to which "path" should be
1725 # added, either as a child or deeper descendant. The second item should
1726 # be a boolean indicating whether files should be added into hierarchical
1727 # groups or one single flat group.
1728 raise NotImplementedError, \
1729 self.__class__.__name__ + ' must implement FileGroup'
1730
1731 def _AddPathToDict(self, pbxbuildfile, path):
1732 """Adds path to the dict tracking paths belonging to this build phase.
1733
1734 If the path is already a member of this build phase, raises an exception.
1735 """
1736
1737 if path in self._files_by_path:
1738 raise ValueError, 'Found multiple build files with path ' + path
1739 self._files_by_path[path] = pbxbuildfile
1740
1741 def _AddBuildFileToDicts(self, pbxbuildfile, path=None):
1742 """Maintains the _files_by_path and _files_by_xcfilelikeelement dicts.
1743
1744 If path is specified, then it is the path that is being added to the
1745 phase, and pbxbuildfile must contain either a PBXFileReference directly
1746 referencing that path, or it must contain a PBXVariantGroup that itself
1747 contains a PBXFileReference referencing the path.
1748
1749 If path is not specified, either the PBXFileReference's path or the paths
1750 of all children of the PBXVariantGroup are taken as being added to the
1751 phase.
1752
1753 If the path is already present in the phase, raises an exception.
1754
1755 If the PBXFileReference or PBXVariantGroup referenced by pbxbuildfile
1756 are already present in the phase, referenced by a different PBXBuildFile
1757 object, raises an exception. This does not raise an exception when
1758 a PBXFileReference or PBXVariantGroup reappear and are referenced by the
1759 same PBXBuildFile that has already introduced them, because in the case
1760 of PBXVariantGroup objects, they may correspond to multiple paths that are
1761 not all added simultaneously. When this situation occurs, the path needs
1762 to be added to _files_by_path, but nothing needs to change in
1763 _files_by_xcfilelikeelement, and the caller should have avoided adding
1764 the PBXBuildFile if it is already present in the list of children.
1765 """
1766
1767 xcfilelikeelement = pbxbuildfile._properties['fileRef']
1768
1769 paths = []
1770 if path != None:
1771 # It's best when the caller provides the path.
1772 if isinstance(xcfilelikeelement, PBXVariantGroup):
1773 paths.append(path)
1774 else:
1775 # If the caller didn't provide a path, there can be either multiple
1776 # paths (PBXVariantGroup) or one.
1777 if isinstance(xcfilelikeelement, PBXVariantGroup):
1778 for variant in xcfilelikeelement._properties['children']:
1779 paths.append(variant.FullPath())
1780 else:
1781 paths.append(xcfilelikeelement.FullPath())
1782
1783 # Add the paths first, because if something's going to raise, the
1784 # messages provided by _AddPathToDict are more useful owing to its
1785 # having access to a real pathname and not just an object's Name().
1786 for a_path in paths:
1787 self._AddPathToDict(pbxbuildfile, a_path)
1788
1789 # If another PBXBuildFile references this XCFileLikeElement, there's a
1790 # problem.
1791 if xcfilelikeelement in self._files_by_xcfilelikeelement and \
1792 self._files_by_xcfilelikeelement[xcfilelikeelement] != pbxbuildfile:
1793 raise ValueError, 'Found multiple build files for ' + \
1794 xcfilelikeelement.Name()
1795 self._files_by_xcfilelikeelement[xcfilelikeelement] = pbxbuildfile
1796
1797 def AppendBuildFile(self, pbxbuildfile, path=None):
1798 # Callers should use this instead of calling
1799 # AppendProperty('files', pbxbuildfile) directly because this function
1800 # maintains the object's dicts. Better yet, callers can just call AddFile
1801 # with a pathname and not worry about building their own PBXBuildFile
1802 # objects.
1803 self.AppendProperty('files', pbxbuildfile)
1804 self._AddBuildFileToDicts(pbxbuildfile, path)
1805
1806 def AddFile(self, path, settings=None):
1807 (file_group, hierarchical) = self.FileGroup(path)
1808 file_ref = file_group.AddOrGetFileByPath(path, hierarchical)
1809
1810 if file_ref in self._files_by_xcfilelikeelement and \
1811 isinstance(file_ref, PBXVariantGroup):
1812 # There's already a PBXBuildFile in this phase corresponding to the
1813 # PBXVariantGroup. path just provides a new variant that belongs to
1814 # the group. Add the path to the dict.
1815 pbxbuildfile = self._files_by_xcfilelikeelement[file_ref]
1816 self._AddBuildFileToDicts(pbxbuildfile, path)
1817 else:
1818 # Add a new PBXBuildFile to get file_ref into the phase.
1819 if settings is None:
1820 pbxbuildfile = PBXBuildFile({'fileRef': file_ref})
1821 else:
1822 pbxbuildfile = PBXBuildFile({'fileRef': file_ref, 'settings': settings})
1823 self.AppendBuildFile(pbxbuildfile, path)
1824
1825
1826 class PBXHeadersBuildPhase(XCBuildPhase):
1827 # No additions to the schema relative to XCBuildPhase.
1828
1829 def Name(self):
1830 return 'Headers'
1831
1832 def FileGroup(self, path):
1833 return self.PBXProjectAncestor().RootGroupForPath(path)
1834
1835
1836 class PBXResourcesBuildPhase(XCBuildPhase):
1837 # No additions to the schema relative to XCBuildPhase.
1838
1839 def Name(self):
1840 return 'Resources'
1841
1842 def FileGroup(self, path):
1843 return self.PBXProjectAncestor().RootGroupForPath(path)
1844
1845
1846 class PBXSourcesBuildPhase(XCBuildPhase):
1847 # No additions to the schema relative to XCBuildPhase.
1848
1849 def Name(self):
1850 return 'Sources'
1851
1852 def FileGroup(self, path):
1853 return self.PBXProjectAncestor().RootGroupForPath(path)
1854
1855
1856 class PBXFrameworksBuildPhase(XCBuildPhase):
1857 # No additions to the schema relative to XCBuildPhase.
1858
1859 def Name(self):
1860 return 'Frameworks'
1861
1862 def FileGroup(self, path):
1863 (root, ext) = posixpath.splitext(path)
1864 if ext != '':
1865 ext = ext[1:].lower()
1866 if ext == 'o':
1867 # .o files are added to Xcode Frameworks phases, but conceptually aren't
1868 # frameworks, they're more like sources or intermediates. Redirect them
1869 # to show up in one of those other groups.
1870 return self.PBXProjectAncestor().RootGroupForPath(path)
1871 else:
1872 return (self.PBXProjectAncestor().FrameworksGroup(), False)
1873
1874
1875 class PBXShellScriptBuildPhase(XCBuildPhase):
1876 _schema = XCBuildPhase._schema.copy()
1877 _schema.update({
1878 'inputPaths': [1, str, 0, 1, []],
1879 'name': [0, str, 0, 0],
1880 'outputPaths': [1, str, 0, 1, []],
1881 'shellPath': [0, str, 0, 1, '/bin/sh'],
1882 'shellScript': [0, str, 0, 1],
1883 'showEnvVarsInLog': [0, int, 0, 0],
1884 })
1885
1886 def Name(self):
1887 if 'name' in self._properties:
1888 return self._properties['name']
1889
1890 return 'ShellScript'
1891
1892
1893 class PBXCopyFilesBuildPhase(XCBuildPhase):
1894 _schema = XCBuildPhase._schema.copy()
1895 _schema.update({
1896 'dstPath': [0, str, 0, 1],
1897 'dstSubfolderSpec': [0, int, 0, 1],
1898 'name': [0, str, 0, 0],
1899 })
1900
1901 # path_tree_re matches "$(DIR)/path" or just "$(DIR)". Match group 1 is
1902 # "DIR", match group 3 is "path" or None.
1903 path_tree_re = re.compile('^\\$\\((.*)\\)(/(.*)|)$')
1904
1905 # path_tree_to_subfolder maps names of Xcode variables to the associated
1906 # dstSubfolderSpec property value used in a PBXCopyFilesBuildPhase object.
1907 path_tree_to_subfolder = {
1908 'BUILT_PRODUCTS_DIR': 16, # Products Directory
1909 # Other types that can be chosen via the Xcode UI.
1910 # TODO(mark): Map Xcode variable names to these.
1911 # : 1, # Wrapper
1912 # : 6, # Executables: 6
1913 # : 7, # Resources
1914 # : 15, # Java Resources
1915 # : 10, # Frameworks
1916 # : 11, # Shared Frameworks
1917 # : 12, # Shared Support
1918 # : 13, # PlugIns
1919 }
1920
1921 def Name(self):
1922 if 'name' in self._properties:
1923 return self._properties['name']
1924
1925 return 'CopyFiles'
1926
1927 def FileGroup(self, path):
1928 return self.PBXProjectAncestor().RootGroupForPath(path)
1929
1930 def SetDestination(self, path):
1931 """Set the dstSubfolderSpec and dstPath properties from path.
1932
1933 path may be specified in the same notation used for XCHierarchicalElements,
1934 specifically, "$(DIR)/path".
1935 """
1936
1937 path_tree_match = self.path_tree_re.search(path)
1938 if path_tree_match:
1939 # Everything else needs to be relative to an Xcode variable.
1940 path_tree = path_tree_match.group(1)
1941 relative_path = path_tree_match.group(3)
1942
1943 if path_tree in self.path_tree_to_subfolder:
1944 subfolder = self.path_tree_to_subfolder[path_tree]
1945 if relative_path == None:
1946 relative_path = ''
1947 else:
1948 # The path starts with an unrecognized Xcode variable
1949 # name like $(SRCROOT). Xcode will still handle this
1950 # as an "absolute path" that starts with the variable.
1951 subfolder = 0
1952 relative_path = path
1953 elif path.startswith('/'):
1954 # Special case. Absolute paths are in dstSubfolderSpec 0.
1955 subfolder = 0
1956 relative_path = path[1:]
1957 else:
1958 raise ValueError, 'Can\'t use path %s in a %s' % \
1959 (path, self.__class__.__name__)
1960
1961 self._properties['dstPath'] = relative_path
1962 self._properties['dstSubfolderSpec'] = subfolder
1963
1964
1965 class PBXBuildRule(XCObject):
1966 _schema = XCObject._schema.copy()
1967 _schema.update({
1968 'compilerSpec': [0, str, 0, 1],
1969 'filePatterns': [0, str, 0, 0],
1970 'fileType': [0, str, 0, 1],
1971 'isEditable': [0, int, 0, 1, 1],
1972 'outputFiles': [1, str, 0, 1, []],
1973 'script': [0, str, 0, 0],
1974 })
1975
1976 def Name(self):
1977 # Not very inspired, but it's what Xcode uses.
1978 return self.__class__.__name__
1979
1980 def Hashables(self):
1981 # super
1982 hashables = XCObject.Hashables(self)
1983
1984 # Use the hashables of the weak objects that this object refers to.
1985 hashables.append(self._properties['fileType'])
1986 if 'filePatterns' in self._properties:
1987 hashables.append(self._properties['filePatterns'])
1988 return hashables
1989
1990
1991 class PBXContainerItemProxy(XCObject):
1992 # When referencing an item in this project file, containerPortal is the
1993 # PBXProject root object of this project file. When referencing an item in
1994 # another project file, containerPortal is a PBXFileReference identifying
1995 # the other project file.
1996 #
1997 # When serving as a proxy to an XCTarget (in this project file or another),
1998 # proxyType is 1. When serving as a proxy to a PBXFileReference (in another
1999 # project file), proxyType is 2. Type 2 is used for references to the
2000 # producs of the other project file's targets.
2001 #
2002 # Xcode is weird about remoteGlobalIDString. Usually, it's printed without
2003 # a comment, indicating that it's tracked internally simply as a string, but
2004 # sometimes it's printed with a comment (usually when the object is initially
2005 # created), indicating that it's tracked as a project file object at least
2006 # sometimes. This module always tracks it as an object, but contains a hack
2007 # to prevent it from printing the comment in the project file output. See
2008 # _XCKVPrint.
2009 _schema = XCObject._schema.copy()
2010 _schema.update({
2011 'containerPortal': [0, XCContainerPortal, 0, 1],
2012 'proxyType': [0, int, 0, 1],
2013 'remoteGlobalIDString': [0, XCRemoteObject, 0, 1],
2014 'remoteInfo': [0, str, 0, 1],
2015 })
2016
2017 def __repr__(self):
2018 props = self._properties
2019 name = '%s.gyp:%s' % (props['containerPortal'].Name(), props['remoteInfo'])
2020 return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))
2021
2022 def Name(self):
2023 # Admittedly not the best name, but it's what Xcode uses.
2024 return self.__class__.__name__
2025
2026 def Hashables(self):
2027 # super
2028 hashables = XCObject.Hashables(self)
2029
2030 # Use the hashables of the weak objects that this object refers to.
2031 hashables.extend(self._properties['containerPortal'].Hashables())
2032 hashables.extend(self._properties['remoteGlobalIDString'].Hashables())
2033 return hashables
2034
2035
2036 class PBXTargetDependency(XCObject):
2037 # The "target" property accepts an XCTarget object, and obviously not
2038 # NoneType. But XCTarget is defined below, so it can't be put into the
2039 # schema yet. The definition of PBXTargetDependency can't be moved below
2040 # XCTarget because XCTarget's own schema references PBXTargetDependency.
2041 # Python doesn't deal well with this circular relationship, and doesn't have
2042 # a real way to do forward declarations. To work around, the type of
2043 # the "target" property is reset below, after XCTarget is defined.
2044 #
2045 # At least one of "name" and "target" is required.
2046 _schema = XCObject._schema.copy()
2047 _schema.update({
2048 'name': [0, str, 0, 0],
2049 'target': [0, None.__class__, 0, 0],
2050 'targetProxy': [0, PBXContainerItemProxy, 1, 1],
2051 })
2052
2053 def __repr__(self):
2054 name = self._properties.get('name') or self._properties['target'].Name()
2055 return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))
2056
2057 def Name(self):
2058 # Admittedly not the best name, but it's what Xcode uses.
2059 return self.__class__.__name__
2060
2061 def Hashables(self):
2062 # super
2063 hashables = XCObject.Hashables(self)
2064
2065 # Use the hashables of the weak objects that this object refers to.
2066 hashables.extend(self._properties['targetProxy'].Hashables())
2067 return hashables
2068
2069
2070 class PBXReferenceProxy(XCFileLikeElement):
2071 _schema = XCFileLikeElement._schema.copy()
2072 _schema.update({
2073 'fileType': [0, str, 0, 1],
2074 'path': [0, str, 0, 1],
2075 'remoteRef': [0, PBXContainerItemProxy, 1, 1],
2076 })
2077
2078
2079 class XCTarget(XCRemoteObject):
2080 # An XCTarget is really just an XCObject, the XCRemoteObject thing is just
2081 # to allow PBXProject to be used in the remoteGlobalIDString property of
2082 # PBXContainerItemProxy.
2083 #
2084 # Setting a "name" property at instantiation may also affect "productName",
2085 # which may in turn affect the "PRODUCT_NAME" build setting in children of
2086 # "buildConfigurationList". See __init__ below.
2087 _schema = XCRemoteObject._schema.copy()
2088 _schema.update({
2089 'buildConfigurationList': [0, XCConfigurationList, 1, 1,
2090 XCConfigurationList()],
2091 'buildPhases': [1, XCBuildPhase, 1, 1, []],
2092 'dependencies': [1, PBXTargetDependency, 1, 1, []],
2093 'name': [0, str, 0, 1],
2094 'productName': [0, str, 0, 1],
2095 })
2096
2097 def __init__(self, properties=None, id=None, parent=None,
2098 force_outdir=None, force_prefix=None, force_extension=None):
2099 # super
2100 XCRemoteObject.__init__(self, properties, id, parent)
2101
2102 # Set up additional defaults not expressed in the schema. If a "name"
2103 # property was supplied, set "productName" if it is not present. Also set
2104 # the "PRODUCT_NAME" build setting in each configuration, but only if
2105 # the setting is not present in any build configuration.
2106 if 'name' in self._properties:
2107 if not 'productName' in self._properties:
2108 self.SetProperty('productName', self._properties['name'])
2109
2110 if 'productName' in self._properties:
2111 if 'buildConfigurationList' in self._properties:
2112 configs = self._properties['buildConfigurationList']
2113 if configs.HasBuildSetting('PRODUCT_NAME') == 0:
2114 configs.SetBuildSetting('PRODUCT_NAME',
2115 self._properties['productName'])
2116
2117 def AddDependency(self, other):
2118 pbxproject = self.PBXProjectAncestor()
2119 other_pbxproject = other.PBXProjectAncestor()
2120 if pbxproject == other_pbxproject:
2121 # The easy case. Add a dependency to another target in the same
2122 # project file.
2123 container = PBXContainerItemProxy({'containerPortal': pbxproject,
2124 'proxyType': 1,
2125 'remoteGlobalIDString': other,
2126 'remoteInfo': other.Name()})
2127 dependency = PBXTargetDependency({'target': other,
2128 'targetProxy': container})
2129 self.AppendProperty('dependencies', dependency)
2130 else:
2131 # The hard case. Add a dependency to a target in a different project
2132 # file. Actually, this case isn't really so hard.
2133 other_project_ref = \
2134 pbxproject.AddOrGetProjectReference(other_pbxproject)[1]
2135 container = PBXContainerItemProxy({
2136 'containerPortal': other_project_ref,
2137 'proxyType': 1,
2138 'remoteGlobalIDString': other,
2139 'remoteInfo': other.Name(),
2140 })
2141 dependency = PBXTargetDependency({'name': other.Name(),
2142 'targetProxy': container})
2143 self.AppendProperty('dependencies', dependency)
2144
2145 # Proxy all of these through to the build configuration list.
2146
2147 def ConfigurationNamed(self, name):
2148 return self._properties['buildConfigurationList'].ConfigurationNamed(name)
2149
2150 def DefaultConfiguration(self):
2151 return self._properties['buildConfigurationList'].DefaultConfiguration()
2152
2153 def HasBuildSetting(self, key):
2154 return self._properties['buildConfigurationList'].HasBuildSetting(key)
2155
2156 def GetBuildSetting(self, key):
2157 return self._properties['buildConfigurationList'].GetBuildSetting(key)
2158
2159 def SetBuildSetting(self, key, value):
2160 return self._properties['buildConfigurationList'].SetBuildSetting(key, \
2161 value)
2162
2163 def AppendBuildSetting(self, key, value):
2164 return self._properties['buildConfigurationList'].AppendBuildSetting(key, \
2165 value)
2166
2167 def DelBuildSetting(self, key):
2168 return self._properties['buildConfigurationList'].DelBuildSetting(key)
2169
2170
2171 # Redefine the type of the "target" property. See PBXTargetDependency._schema
2172 # above.
2173 PBXTargetDependency._schema['target'][1] = XCTarget
2174
2175
2176 class PBXNativeTarget(XCTarget):
2177 # buildPhases is overridden in the schema to be able to set defaults.
2178 #
2179 # NOTE: Contrary to most objects, it is advisable to set parent when
2180 # constructing PBXNativeTarget. A parent of an XCTarget must be a PBXProject
2181 # object. A parent reference is required for a PBXNativeTarget during
2182 # construction to be able to set up the target defaults for productReference,
2183 # because a PBXBuildFile object must be created for the target and it must
2184 # be added to the PBXProject's mainGroup hierarchy.
2185 _schema = XCTarget._schema.copy()
2186 _schema.update({
2187 'buildPhases': [1, XCBuildPhase, 1, 1,
2188 [PBXSourcesBuildPhase(), PBXFrameworksBuildPhase()]],
2189 'buildRules': [1, PBXBuildRule, 1, 1, []],
2190 'productReference': [0, PBXFileReference, 0, 1],
2191 'productType': [0, str, 0, 1],
2192 })
2193
2194 # Mapping from Xcode product-types to settings. The settings are:
2195 # filetype : used for explicitFileType in the project file
2196 # prefix : the prefix for the file name
2197 # suffix : the suffix for the filen ame
2198 _product_filetypes = {
2199 'com.apple.product-type.application': ['wrapper.application',
2200 '', '.app'],
2201 'com.apple.product-type.bundle': ['wrapper.cfbundle',
2202 '', '.bundle'],
2203 'com.apple.product-type.framework': ['wrapper.framework',
2204 '', '.framework'],
2205 'com.apple.product-type.library.dynamic': ['compiled.mach-o.dylib',
2206 'lib', '.dylib'],
2207 'com.apple.product-type.library.static': ['archive.ar',
2208 'lib', '.a'],
2209 'com.apple.product-type.tool': ['compiled.mach-o.executable',
2210 '', ''],
2211 'com.googlecode.gyp.xcode.bundle': ['compiled.mach-o.dylib',
2212 '', '.so'],
2213 }
2214
2215 def __init__(self, properties=None, id=None, parent=None,
2216 force_outdir=None, force_prefix=None, force_extension=None):
2217 # super
2218 XCTarget.__init__(self, properties, id, parent)
2219
2220 if 'productName' in self._properties and \
2221 'productType' in self._properties and \
2222 not 'productReference' in self._properties and \
2223 self._properties['productType'] in self._product_filetypes:
2224 products_group = None
2225 pbxproject = self.PBXProjectAncestor()
2226 if pbxproject != None:
2227 products_group = pbxproject.ProductsGroup()
2228
2229 if products_group != None:
2230 (filetype, prefix, suffix) = \
2231 self._product_filetypes[self._properties['productType']]
2232 # Xcode does not have a distinct type for loadable modules that are
2233 # pure BSD targets (not in a bundle wrapper). GYP allows such modules
2234 # to be specified by setting a target type to loadable_module without
2235 # having mac_bundle set. These are mapped to the pseudo-product type
2236 # com.googlecode.gyp.xcode.bundle.
2237 #
2238 # By picking up this special type and converting it to a dynamic
2239 # library (com.apple.product-type.library.dynamic) with fix-ups,
2240 # single-file loadable modules can be produced.
2241 #
2242 # MACH_O_TYPE is changed to mh_bundle to produce the proper file type
2243 # (as opposed to mh_dylib). In order for linking to succeed,
2244 # DYLIB_CURRENT_VERSION and DYLIB_COMPATIBILITY_VERSION must be
2245 # cleared. They are meaningless for type mh_bundle.
2246 #
2247 # Finally, the .so extension is forcibly applied over the default
2248 # (.dylib), unless another forced extension is already selected.
2249 # .dylib is plainly wrong, and .bundle is used by loadable_modules in
2250 # bundle wrappers (com.apple.product-type.bundle). .so seems an odd
2251 # choice because it's used as the extension on many other systems that
2252 # don't distinguish between linkable shared libraries and non-linkable
2253 # loadable modules, but there's precedent: Python loadable modules on
2254 # Mac OS X use an .so extension.
2255 if self._properties['productType'] == 'com.googlecode.gyp.xcode.bundle':
2256 self._properties['productType'] = \
2257 'com.apple.product-type.library.dynamic'
2258 self.SetBuildSetting('MACH_O_TYPE', 'mh_bundle')
2259 self.SetBuildSetting('DYLIB_CURRENT_VERSION', '')
2260 self.SetBuildSetting('DYLIB_COMPATIBILITY_VERSION', '')
2261 if force_extension == None:
2262 force_extension = suffix[1:]
2263
2264 if force_extension is not None:
2265 # If it's a wrapper (bundle), set WRAPPER_EXTENSION.
2266 if filetype.startswith('wrapper.'):
2267 self.SetBuildSetting('WRAPPER_EXTENSION', force_extension)
2268 else:
2269 # Extension override.
2270 suffix = '.' + force_extension
2271 self.SetBuildSetting('EXECUTABLE_EXTENSION', force_extension)
2272
2273 if filetype.startswith('compiled.mach-o.executable'):
2274 product_name = self._properties['productName']
2275 product_name += suffix
2276 suffix = ''
2277 self.SetProperty('productName', product_name)
2278 self.SetBuildSetting('PRODUCT_NAME', product_name)
2279
2280 # Xcode handles most prefixes based on the target type, however there
2281 # are exceptions. If a "BSD Dynamic Library" target is added in the
2282 # Xcode UI, Xcode sets EXECUTABLE_PREFIX. This check duplicates that
2283 # behavior.
2284 if force_prefix is not None:
2285 prefix = force_prefix
2286 if filetype.startswith('wrapper.'):
2287 self.SetBuildSetting('WRAPPER_PREFIX', prefix)
2288 else:
2289 self.SetBuildSetting('EXECUTABLE_PREFIX', prefix)
2290
2291 if force_outdir is not None:
2292 self.SetBuildSetting('TARGET_BUILD_DIR', force_outdir)
2293
2294 # TODO(tvl): Remove the below hack.
2295 # http://code.google.com/p/gyp/issues/detail?id=122
2296
2297 # Some targets include the prefix in the target_name. These targets
2298 # really should just add a product_name setting that doesn't include
2299 # the prefix. For example:
2300 # target_name = 'libevent', product_name = 'event'
2301 # This check cleans up for them.
2302 product_name = self._properties['productName']
2303 prefix_len = len(prefix)
2304 if prefix_len and (product_name[:prefix_len] == prefix):
2305 product_name = product_name[prefix_len:]
2306 self.SetProperty('productName', product_name)
2307 self.SetBuildSetting('PRODUCT_NAME', product_name)
2308
2309 ref_props = {
2310 'explicitFileType': filetype,
2311 'includeInIndex': 0,
2312 'path': prefix + product_name + suffix,
2313 'sourceTree': 'BUILT_PRODUCTS_DIR',
2314 }
2315 file_ref = PBXFileReference(ref_props)
2316 products_group.AppendChild(file_ref)
2317 self.SetProperty('productReference', file_ref)
2318
2319 def GetBuildPhaseByType(self, type):
2320 if not 'buildPhases' in self._properties:
2321 return None
2322
2323 the_phase = None
2324 for phase in self._properties['buildPhases']:
2325 if isinstance(phase, type):
2326 # Some phases may be present in multiples in a well-formed project file,
2327 # but phases like PBXSourcesBuildPhase may only be present singly, and
2328 # this function is intended as an aid to GetBuildPhaseByType. Loop
2329 # over the entire list of phases and assert if more than one of the
2330 # desired type is found.
2331 assert the_phase == None
2332 the_phase = phase
2333
2334 return the_phase
2335
2336 def HeadersPhase(self):
2337 headers_phase = self.GetBuildPhaseByType(PBXHeadersBuildPhase)
2338 if headers_phase == None:
2339 headers_phase = PBXHeadersBuildPhase()
2340
2341 # The headers phase should come before the resources, sources, and
2342 # frameworks phases, if any.
2343 insert_at = len(self._properties['buildPhases'])
2344 for index in xrange(0, len(self._properties['buildPhases'])):
2345 phase = self._properties['buildPhases'][index]
2346 if isinstance(phase, PBXResourcesBuildPhase) or \
2347 isinstance(phase, PBXSourcesBuildPhase) or \
2348 isinstance(phase, PBXFrameworksBuildPhase):
2349 insert_at = index
2350 break
2351
2352 self._properties['buildPhases'].insert(insert_at, headers_phase)
2353 headers_phase.parent = self
2354
2355 return headers_phase
2356
2357 def ResourcesPhase(self):
2358 resources_phase = self.GetBuildPhaseByType(PBXResourcesBuildPhase)
2359 if resources_phase == None:
2360 resources_phase = PBXResourcesBuildPhase()
2361
2362 # The resources phase should come before the sources and frameworks
2363 # phases, if any.
2364 insert_at = len(self._properties['buildPhases'])
2365 for index in xrange(0, len(self._properties['buildPhases'])):
2366 phase = self._properties['buildPhases'][index]
2367 if isinstance(phase, PBXSourcesBuildPhase) or \
2368 isinstance(phase, PBXFrameworksBuildPhase):
2369 insert_at = index
2370 break
2371
2372 self._properties['buildPhases'].insert(insert_at, resources_phase)
2373 resources_phase.parent = self
2374
2375 return resources_phase
2376
2377 def SourcesPhase(self):
2378 sources_phase = self.GetBuildPhaseByType(PBXSourcesBuildPhase)
2379 if sources_phase == None:
2380 sources_phase = PBXSourcesBuildPhase()
2381 self.AppendProperty('buildPhases', sources_phase)
2382
2383 return sources_phase
2384
2385 def FrameworksPhase(self):
2386 frameworks_phase = self.GetBuildPhaseByType(PBXFrameworksBuildPhase)
2387 if frameworks_phase == None:
2388 frameworks_phase = PBXFrameworksBuildPhase()
2389 self.AppendProperty('buildPhases', frameworks_phase)
2390
2391 return frameworks_phase
2392
2393 def AddDependency(self, other):
2394 # super
2395 XCTarget.AddDependency(self, other)
2396
2397 static_library_type = 'com.apple.product-type.library.static'
2398 shared_library_type = 'com.apple.product-type.library.dynamic'
2399 framework_type = 'com.apple.product-type.framework'
2400 if isinstance(other, PBXNativeTarget) and \
2401 'productType' in self._properties and \
2402 self._properties['productType'] != static_library_type and \
2403 'productType' in other._properties and \
2404 (other._properties['productType'] == static_library_type or \
2405 ((other._properties['productType'] == shared_library_type or \
2406 other._properties['productType'] == framework_type) and \
2407 ((not other.HasBuildSetting('MACH_O_TYPE')) or
2408 other.GetBuildSetting('MACH_O_TYPE') != 'mh_bundle'))):
2409
2410 file_ref = other.GetProperty('productReference')
2411
2412 pbxproject = self.PBXProjectAncestor()
2413 other_pbxproject = other.PBXProjectAncestor()
2414 if pbxproject != other_pbxproject:
2415 other_project_product_group = \
2416 pbxproject.AddOrGetProjectReference(other_pbxproject)[0]
2417 file_ref = other_project_product_group.GetChildByRemoteObject(file_ref)
2418
2419 self.FrameworksPhase().AppendProperty('files',
2420 PBXBuildFile({'fileRef': file_ref}))
2421
2422
2423 class PBXAggregateTarget(XCTarget):
2424 pass
2425
2426
2427 class PBXProject(XCContainerPortal):
2428 # A PBXProject is really just an XCObject, the XCContainerPortal thing is
2429 # just to allow PBXProject to be used in the containerPortal property of
2430 # PBXContainerItemProxy.
2431 """
2432
2433 Attributes:
2434 path: "sample.xcodeproj". TODO(mark) Document me!
2435 _other_pbxprojects: A dictionary, keyed by other PBXProject objects. Each
2436 value is a reference to the dict in the
2437 projectReferences list associated with the keyed
2438 PBXProject.
2439 """
2440
2441 _schema = XCContainerPortal._schema.copy()
2442 _schema.update({
2443 'attributes': [0, dict, 0, 0],
2444 'buildConfigurationList': [0, XCConfigurationList, 1, 1,
2445 XCConfigurationList()],
2446 'compatibilityVersion': [0, str, 0, 1, 'Xcode 3.1'],
2447 'hasScannedForEncodings': [0, int, 0, 1, 1],
2448 'mainGroup': [0, PBXGroup, 1, 1, PBXGroup()],
2449 'projectDirPath': [0, str, 0, 1, ''],
2450 'projectReferences': [1, dict, 0, 0],
2451 'projectRoot': [0, str, 0, 1, ''],
2452 'targets': [1, XCTarget, 1, 1, []],
2453 })
2454
2455 def __init__(self, properties=None, id=None, parent=None, path=None):
2456 self.path = path
2457 self._other_pbxprojects = {}
2458 # super
2459 return XCContainerPortal.__init__(self, properties, id, parent)
2460
2461 def Name(self):
2462 name = self.path
2463 if name[-10:] == '.xcodeproj':
2464 name = name[:-10]
2465 return posixpath.basename(name)
2466
2467 def Path(self):
2468 return self.path
2469
2470 def Comment(self):
2471 return 'Project object'
2472
2473 def Children(self):
2474 # super
2475 children = XCContainerPortal.Children(self)
2476
2477 # Add children that the schema doesn't know about. Maybe there's a more
2478 # elegant way around this, but this is the only case where we need to own
2479 # objects in a dictionary (that is itself in a list), and three lines for
2480 # a one-off isn't that big a deal.
2481 if 'projectReferences' in self._properties:
2482 for reference in self._properties['projectReferences']:
2483 children.append(reference['ProductGroup'])
2484
2485 return children
2486
2487 def PBXProjectAncestor(self):
2488 return self
2489
2490 def _GroupByName(self, name):
2491 if not 'mainGroup' in self._properties:
2492 self.SetProperty('mainGroup', PBXGroup())
2493
2494 main_group = self._properties['mainGroup']
2495 group = main_group.GetChildByName(name)
2496 if group == None:
2497 group = PBXGroup({'name': name})
2498 main_group.AppendChild(group)
2499
2500 return group
2501
2502 # SourceGroup and ProductsGroup are created by default in Xcode's own
2503 # templates.
2504 def SourceGroup(self):
2505 return self._GroupByName('Source')
2506
2507 def ProductsGroup(self):
2508 return self._GroupByName('Products')
2509
2510 # IntermediatesGroup is used to collect source-like files that are generated
2511 # by rules or script phases and are placed in intermediate directories such
2512 # as DerivedSources.
2513 def IntermediatesGroup(self):
2514 return self._GroupByName('Intermediates')
2515
2516 # FrameworksGroup and ProjectsGroup are top-level groups used to collect
2517 # frameworks and projects.
2518 def FrameworksGroup(self):
2519 return self._GroupByName('Frameworks')
2520
2521 def ProjectsGroup(self):
2522 return self._GroupByName('Projects')
2523
2524 def RootGroupForPath(self, path):
2525 """Returns a PBXGroup child of this object to which path should be added.
2526
2527 This method is intended to choose between SourceGroup and
2528 IntermediatesGroup on the basis of whether path is present in a source
2529 directory or an intermediates directory. For the purposes of this
2530 determination, any path located within a derived file directory such as
2531 PROJECT_DERIVED_FILE_DIR is treated as being in an intermediates
2532 directory.
2533
2534 The returned value is a two-element tuple. The first element is the
2535 PBXGroup, and the second element specifies whether that group should be
2536 organized hierarchically (True) or as a single flat list (False).
2537 """
2538
2539 # TODO(mark): make this a class variable and bind to self on call?
2540 # Also, this list is nowhere near exhaustive.
2541 # INTERMEDIATE_DIR and SHARED_INTERMEDIATE_DIR are used by
2542 # gyp.generator.xcode. There should probably be some way for that module
2543 # to push the names in, rather than having to hard-code them here.
2544 source_tree_groups = {
2545 'DERIVED_FILE_DIR': (self.IntermediatesGroup, True),
2546 'INTERMEDIATE_DIR': (self.IntermediatesGroup, True),
2547 'PROJECT_DERIVED_FILE_DIR': (self.IntermediatesGroup, True),
2548 'SHARED_INTERMEDIATE_DIR': (self.IntermediatesGroup, True),
2549 }
2550
2551 (source_tree, path) = SourceTreeAndPathFromPath(path)
2552 if source_tree != None and source_tree in source_tree_groups:
2553 (group_func, hierarchical) = source_tree_groups[source_tree]
2554 group = group_func()
2555 return (group, hierarchical)
2556
2557 # TODO(mark): make additional choices based on file extension.
2558
2559 return (self.SourceGroup(), True)
2560
2561 def AddOrGetFileInRootGroup(self, path):
2562 """Returns a PBXFileReference corresponding to path in the correct group
2563 according to RootGroupForPath's heuristics.
2564
2565 If an existing PBXFileReference for path exists, it will be returned.
2566 Otherwise, one will be created and returned.
2567 """
2568
2569 (group, hierarchical) = self.RootGroupForPath(path)
2570 return group.AddOrGetFileByPath(path, hierarchical)
2571
2572 def RootGroupsTakeOverOnlyChildren(self, recurse=False):
2573 """Calls TakeOverOnlyChild for all groups in the main group."""
2574
2575 for group in self._properties['mainGroup']._properties['children']:
2576 if isinstance(group, PBXGroup):
2577 group.TakeOverOnlyChild(recurse)
2578
2579 def SortGroups(self):
2580 # Sort the children of the mainGroup (like "Source" and "Products")
2581 # according to their defined order.
2582 self._properties['mainGroup']._properties['children'] = \
2583 sorted(self._properties['mainGroup']._properties['children'],
2584 cmp=lambda x,y: x.CompareRootGroup(y))
2585
2586 # Sort everything else by putting group before files, and going
2587 # alphabetically by name within sections of groups and files. SortGroup
2588 # is recursive.
2589 for group in self._properties['mainGroup']._properties['children']:
2590 if not isinstance(group, PBXGroup):
2591 continue
2592
2593 if group.Name() == 'Products':
2594 # The Products group is a special case. Instead of sorting
2595 # alphabetically, sort things in the order of the targets that
2596 # produce the products. To do this, just build up a new list of
2597 # products based on the targets.
2598 products = []
2599 for target in self._properties['targets']:
2600 if not isinstance(target, PBXNativeTarget):
2601 continue
2602 product = target._properties['productReference']
2603 # Make sure that the product is already in the products group.
2604 assert product in group._properties['children']
2605 products.append(product)
2606
2607 # Make sure that this process doesn't miss anything that was already
2608 # in the products group.
2609 assert len(products) == len(group._properties['children'])
2610 group._properties['children'] = products
2611 else:
2612 group.SortGroup()
2613
2614 def AddOrGetProjectReference(self, other_pbxproject):
2615 """Add a reference to another project file (via PBXProject object) to this
2616 one.
2617
2618 Returns [ProductGroup, ProjectRef]. ProductGroup is a PBXGroup object in
2619 this project file that contains a PBXReferenceProxy object for each
2620 product of each PBXNativeTarget in the other project file. ProjectRef is
2621 a PBXFileReference to the other project file.
2622
2623 If this project file already references the other project file, the
2624 existing ProductGroup and ProjectRef are returned. The ProductGroup will
2625 still be updated if necessary.
2626 """
2627
2628 if not 'projectReferences' in self._properties:
2629 self._properties['projectReferences'] = []
2630
2631 product_group = None
2632 project_ref = None
2633
2634 if not other_pbxproject in self._other_pbxprojects:
2635 # This project file isn't yet linked to the other one. Establish the
2636 # link.
2637 product_group = PBXGroup({'name': 'Products'})
2638
2639 # ProductGroup is strong.
2640 product_group.parent = self
2641
2642 # There's nothing unique about this PBXGroup, and if left alone, it will
2643 # wind up with the same set of hashables as all other PBXGroup objects
2644 # owned by the projectReferences list. Add the hashables of the
2645 # remote PBXProject that it's related to.
2646 product_group._hashables.extend(other_pbxproject.Hashables())
2647
2648 # The other project reports its path as relative to the same directory
2649 # that this project's path is relative to. The other project's path
2650 # is not necessarily already relative to this project. Figure out the
2651 # pathname that this project needs to use to refer to the other one.
2652 this_path = posixpath.dirname(self.Path())
2653 projectDirPath = self.GetProperty('projectDirPath')
2654 if projectDirPath:
2655 if posixpath.isabs(projectDirPath[0]):
2656 this_path = projectDirPath
2657 else:
2658 this_path = posixpath.join(this_path, projectDirPath)
2659 other_path = gyp.common.RelativePath(other_pbxproject.Path(), this_path)
2660
2661 # ProjectRef is weak (it's owned by the mainGroup hierarchy).
2662 project_ref = PBXFileReference({
2663 'lastKnownFileType': 'wrapper.pb-project',
2664 'path': other_path,
2665 'sourceTree': 'SOURCE_ROOT',
2666 })
2667 self.ProjectsGroup().AppendChild(project_ref)
2668
2669 ref_dict = {'ProductGroup': product_group, 'ProjectRef': project_ref}
2670 self._other_pbxprojects[other_pbxproject] = ref_dict
2671 self.AppendProperty('projectReferences', ref_dict)
2672
2673 # Xcode seems to sort this list case-insensitively
2674 self._properties['projectReferences'] = \
2675 sorted(self._properties['projectReferences'], cmp=lambda x,y:
2676 cmp(x['ProjectRef'].Name().lower(),
2677 y['ProjectRef'].Name().lower()))
2678 else:
2679 # The link already exists. Pull out the relevnt data.
2680 project_ref_dict = self._other_pbxprojects[other_pbxproject]
2681 product_group = project_ref_dict['ProductGroup']
2682 project_ref = project_ref_dict['ProjectRef']
2683
2684 self._SetUpProductReferences(other_pbxproject, product_group, project_ref)
2685
2686 return [product_group, project_ref]
2687
2688 def _SetUpProductReferences(self, other_pbxproject, product_group,
2689 project_ref):
2690 # TODO(mark): This only adds references to products in other_pbxproject
2691 # when they don't exist in this pbxproject. Perhaps it should also
2692 # remove references from this pbxproject that are no longer present in
2693 # other_pbxproject. Perhaps it should update various properties if they
2694 # change.
2695 for target in other_pbxproject._properties['targets']:
2696 if not isinstance(target, PBXNativeTarget):
2697 continue
2698
2699 other_fileref = target._properties['productReference']
2700 if product_group.GetChildByRemoteObject(other_fileref) == None:
2701 # Xcode sets remoteInfo to the name of the target and not the name
2702 # of its product, despite this proxy being a reference to the product.
2703 container_item = PBXContainerItemProxy({
2704 'containerPortal': project_ref,
2705 'proxyType': 2,
2706 'remoteGlobalIDString': other_fileref,
2707 'remoteInfo': target.Name()
2708 })
2709 # TODO(mark): Does sourceTree get copied straight over from the other
2710 # project? Can the other project ever have lastKnownFileType here
2711 # instead of explicitFileType? (Use it if so?) Can path ever be
2712 # unset? (I don't think so.) Can other_fileref have name set, and
2713 # does it impact the PBXReferenceProxy if so? These are the questions
2714 # that perhaps will be answered one day.
2715 reference_proxy = PBXReferenceProxy({
2716 'fileType': other_fileref._properties['explicitFileType'],
2717 'path': other_fileref._properties['path'],
2718 'sourceTree': other_fileref._properties['sourceTree'],
2719 'remoteRef': container_item,
2720 })
2721
2722 product_group.AppendChild(reference_proxy)
2723
2724 def SortRemoteProductReferences(self):
2725 # For each remote project file, sort the associated ProductGroup in the
2726 # same order that the targets are sorted in the remote project file. This
2727 # is the sort order used by Xcode.
2728
2729 def CompareProducts(x, y, remote_products):
2730 # x and y are PBXReferenceProxy objects. Go through their associated
2731 # PBXContainerItem to get the remote PBXFileReference, which will be
2732 # present in the remote_products list.
2733 x_remote = x._properties['remoteRef']._properties['remoteGlobalIDString']
2734 y_remote = y._properties['remoteRef']._properties['remoteGlobalIDString']
2735 x_index = remote_products.index(x_remote)
2736 y_index = remote_products.index(y_remote)
2737
2738 # Use the order of each remote PBXFileReference in remote_products to
2739 # determine the sort order.
2740 return cmp(x_index, y_index)
2741
2742 for other_pbxproject, ref_dict in self._other_pbxprojects.iteritems():
2743 # Build up a list of products in the remote project file, ordered the
2744 # same as the targets that produce them.
2745 remote_products = []
2746 for target in other_pbxproject._properties['targets']:
2747 if not isinstance(target, PBXNativeTarget):
2748 continue
2749 remote_products.append(target._properties['productReference'])
2750
2751 # Sort the PBXReferenceProxy children according to the list of remote
2752 # products.
2753 product_group = ref_dict['ProductGroup']
2754 product_group._properties['children'] = sorted(
2755 product_group._properties['children'],
2756 cmp=lambda x, y: CompareProducts(x, y, remote_products))
2757
2758
2759 class XCProjectFile(XCObject):
2760 _schema = XCObject._schema.copy()
2761 _schema.update({
2762 'archiveVersion': [0, int, 0, 1, 1],
2763 'classes': [0, dict, 0, 1, {}],
2764 'objectVersion': [0, int, 0, 1, 45],
2765 'rootObject': [0, PBXProject, 1, 1],
2766 })
2767
2768 def SetXcodeVersion(self, version):
2769 version_to_object_version = {
2770 '2.4': 45,
2771 '3.0': 45,
2772 '3.1': 45,
2773 '3.2': 46,
2774 }
2775 if not version in version_to_object_version:
2776 supported_str = ', '.join(sorted(version_to_object_version.keys()))
2777 raise Exception(
2778 'Unsupported Xcode version %s (supported: %s)' %
2779 ( version, supported_str ) )
2780 compatibility_version = 'Xcode %s' % version
2781 self._properties['rootObject'].SetProperty('compatibilityVersion',
2782 compatibility_version)
2783 self.SetProperty('objectVersion', version_to_object_version[version]);
2784
2785 def ComputeIDs(self, recursive=True, overwrite=True, hash=None):
2786 # Although XCProjectFile is implemented here as an XCObject, it's not a
2787 # proper object in the Xcode sense, and it certainly doesn't have its own
2788 # ID. Pass through an attempt to update IDs to the real root object.
2789 if recursive:
2790 self._properties['rootObject'].ComputeIDs(recursive, overwrite, hash)
2791
2792 def Print(self, file=sys.stdout):
2793 self.VerifyHasRequiredProperties()
2794
2795 # Add the special "objects" property, which will be caught and handled
2796 # separately during printing. This structure allows a fairly standard
2797 # loop do the normal printing.
2798 self._properties['objects'] = {}
2799 self._XCPrint(file, 0, '// !$*UTF8*$!\n')
2800 if self._should_print_single_line:
2801 self._XCPrint(file, 0, '{ ')
2802 else:
2803 self._XCPrint(file, 0, '{\n')
2804 for property, value in sorted(self._properties.iteritems(),
2805 cmp=lambda x, y: cmp(x, y)):
2806 if property == 'objects':
2807 self._PrintObjects(file)
2808 else:
2809 self._XCKVPrint(file, 1, property, value)
2810 self._XCPrint(file, 0, '}\n')
2811 del self._properties['objects']
2812
2813 def _PrintObjects(self, file):
2814 if self._should_print_single_line:
2815 self._XCPrint(file, 0, 'objects = {')
2816 else:
2817 self._XCPrint(file, 1, 'objects = {\n')
2818
2819 objects_by_class = {}
2820 for object in self.Descendants():
2821 if object == self:
2822 continue
2823 class_name = object.__class__.__name__
2824 if not class_name in objects_by_class:
2825 objects_by_class[class_name] = []
2826 objects_by_class[class_name].append(object)
2827
2828 for class_name in sorted(objects_by_class):
2829 self._XCPrint(file, 0, '\n')
2830 self._XCPrint(file, 0, '/* Begin ' + class_name + ' section */\n')
2831 for object in sorted(objects_by_class[class_name],
2832 cmp=lambda x, y: cmp(x.id, y.id)):
2833 object.Print(file)
2834 self._XCPrint(file, 0, '/* End ' + class_name + ' section */\n')
2835
2836 if self._should_print_single_line:
2837 self._XCPrint(file, 0, '}; ')
2838 else:
2839 self._XCPrint(file, 1, '};\n')
+0
-70
third_party/gyp/pylib/gyp/xml_fix.py less more
0 #!/usr/bin/python
1 # Copyright (c) 2011 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 """Applies a fix to CR LF TAB handling in xml.dom.
6
7 Fixes this: http://code.google.com/p/chromium/issues/detail?id=76293
8 Working around this: http://bugs.python.org/issue5752
9 TODO(bradnelson): Consider dropping this when we drop XP support.
10 """
11
12
13 import xml.dom.minidom
14
15
16 def _Replacement_write_data(writer, data, is_attrib=False):
17 """Writes datachars to writer."""
18 data = data.replace("&", "&amp;").replace("<", "&lt;")
19 data = data.replace("\"", "&quot;").replace(">", "&gt;")
20 if is_attrib:
21 data = data.replace(
22 "\r", "&#xD;").replace(
23 "\n", "&#xA;").replace(
24 "\t", "&#x9;")
25 writer.write(data)
26
27
28 def _Replacement_writexml(self, writer, indent="", addindent="", newl=""):
29 # indent = current indentation
30 # addindent = indentation to add to higher levels
31 # newl = newline string
32 writer.write(indent+"<" + self.tagName)
33
34 attrs = self._get_attributes()
35 a_names = attrs.keys()
36 a_names.sort()
37
38 for a_name in a_names:
39 writer.write(" %s=\"" % a_name)
40 _Replacement_write_data(writer, attrs[a_name].value, is_attrib=True)
41 writer.write("\"")
42 if self.childNodes:
43 writer.write(">%s" % newl)
44 for node in self.childNodes:
45 node.writexml(writer, indent + addindent, addindent, newl)
46 writer.write("%s</%s>%s" % (indent, self.tagName, newl))
47 else:
48 writer.write("/>%s" % newl)
49
50
51 class XmlFix(object):
52 """Object to manage temporary patching of xml.dom.minidom."""
53
54 def __init__(self):
55 # Preserve current xml.dom.minidom functions.
56 self.write_data = xml.dom.minidom._write_data
57 self.writexml = xml.dom.minidom.Element.writexml
58 # Inject replacement versions of a function and a method.
59 xml.dom.minidom._write_data = _Replacement_write_data
60 xml.dom.minidom.Element.writexml = _Replacement_writexml
61
62 def Cleanup(self):
63 if self.write_data:
64 xml.dom.minidom._write_data = self.write_data
65 xml.dom.minidom.Element.writexml = self.writexml
66 self.write_data = None
67
68 def __del__(self):
69 self.Cleanup()
+0
-81
third_party/gyp/samples/samples less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import os.path
7 import shutil
8 import sys
9
10
11 gyps = [
12 'app/app.gyp',
13 'base/base.gyp',
14 'build/temp_gyp/googleurl.gyp',
15 'build/all.gyp',
16 'build/common.gypi',
17 'build/external_code.gypi',
18 'chrome/test/security_tests/security_tests.gyp',
19 'chrome/third_party/hunspell/hunspell.gyp',
20 'chrome/chrome.gyp',
21 'media/media.gyp',
22 'net/net.gyp',
23 'printing/printing.gyp',
24 'sdch/sdch.gyp',
25 'skia/skia.gyp',
26 'testing/gmock.gyp',
27 'testing/gtest.gyp',
28 'third_party/bzip2/bzip2.gyp',
29 'third_party/icu38/icu38.gyp',
30 'third_party/libevent/libevent.gyp',
31 'third_party/libjpeg/libjpeg.gyp',
32 'third_party/libpng/libpng.gyp',
33 'third_party/libxml/libxml.gyp',
34 'third_party/libxslt/libxslt.gyp',
35 'third_party/lzma_sdk/lzma_sdk.gyp',
36 'third_party/modp_b64/modp_b64.gyp',
37 'third_party/npapi/npapi.gyp',
38 'third_party/sqlite/sqlite.gyp',
39 'third_party/zlib/zlib.gyp',
40 'v8/tools/gyp/v8.gyp',
41 'webkit/activex_shim/activex_shim.gyp',
42 'webkit/activex_shim_dll/activex_shim_dll.gyp',
43 'webkit/build/action_csspropertynames.py',
44 'webkit/build/action_cssvaluekeywords.py',
45 'webkit/build/action_jsconfig.py',
46 'webkit/build/action_makenames.py',
47 'webkit/build/action_maketokenizer.py',
48 'webkit/build/action_useragentstylesheets.py',
49 'webkit/build/rule_binding.py',
50 'webkit/build/rule_bison.py',
51 'webkit/build/rule_gperf.py',
52 'webkit/tools/test_shell/test_shell.gyp',
53 'webkit/webkit.gyp',
54 ]
55
56
57 def Main(argv):
58 if len(argv) != 3 or argv[1] not in ['push', 'pull']:
59 print 'Usage: %s push/pull PATH_TO_CHROME' % argv[0]
60 return 1
61
62 path_to_chrome = argv[2]
63
64 for g in gyps:
65 chrome_file = os.path.join(path_to_chrome, g)
66 local_file = os.path.join(os.path.dirname(argv[0]), os.path.split(g)[1])
67 if argv[1] == 'push':
68 print 'Copying %s to %s' % (local_file, chrome_file)
69 shutil.copyfile(local_file, chrome_file)
70 elif argv[1] == 'pull':
71 print 'Copying %s to %s' % (chrome_file, local_file)
72 shutil.copyfile(chrome_file, local_file)
73 else:
74 assert False
75
76 return 0
77
78
79 if __name__ == '__main__':
80 sys.exit(Main(sys.argv))
+0
-5
third_party/gyp/samples/samples.bat less more
0 @rem Copyright (c) 2009 Google Inc. All rights reserved.
1 @rem Use of this source code is governed by a BSD-style license that can be
2 @rem found in the LICENSE file.
3
4 @python %~dp0/samples %*
+0
-26
third_party/gyp/setup.py less more
0 #!/usr/bin/env python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 from distutils.core import setup
7 from distutils.command.install import install
8 from distutils.command.install_lib import install_lib
9 from distutils.command.install_scripts import install_scripts
10
11 setup(
12 name='gyp',
13 version='0.1',
14 description='Generate Your Projects',
15 author='Chromium Authors',
16 author_email='chromium-dev@googlegroups.com',
17 url='http://code.google.com/p/gyp',
18 package_dir = {'': 'pylib'},
19 packages=['gyp', 'gyp.generator'],
20
21 scripts = ['gyp'],
22 cmdclass = {'install': install,
23 'install_lib': install_lib,
24 'install_scripts': install_scripts},
25 )
+0
-15
third_party/gyp/tools/README less more
0 pretty_vcproj:
1 Usage: pretty_vcproj.py "c:\path\to\vcproj.vcproj" [key1=value1] [key2=value2]
2
3 They key/value pair are used to resolve vsprops name.
4
5 For example, if I want to diff the base.vcproj project:
6
7 pretty_vcproj.py z:\dev\src-chrome\src\base\build\base.vcproj "$(SolutionDir)=z:\dev\src-chrome\src\chrome\\" "$(CHROMIUM_BUILD)=" "$(CHROME_BUILD_TYPE)=" > orignal.txt
8 pretty_vcproj.py z:\dev\src-chrome\src\base\base_gyp.vcproj "$(SolutionDir)=z:\dev\src-chrome\src\chrome\\" "$(CHROMIUM_BUILD)=" "$(CHROME_BUILD_TYPE)=" > gyp.txt
9
10 And you can use your favorite diff tool to see the changes.
11
12 Note: In the case of base.vcproj, the original vcproj is one level up the generated one.
13 I suggest you do a search and replace for '"..\' and replace it with '"' in original.txt
14 before you perform the diff.
+0
-95
third_party/gyp/tools/graphviz.py less more
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Using the JSON dumped by the dump-dependency-json generator,
7 generate input suitable for graphviz to render a dependency graph of
8 targets."""
9
10 import collections
11 import json
12 import sys
13
14
15 def ParseTarget(target):
16 target, _, suffix = target.partition('#')
17 filename, _, target = target.partition(':')
18 return filename, target, suffix
19
20
21 def LoadEdges(filename, targets):
22 """Load the edges map from the dump file, and filter it to only
23 show targets in |targets| and their depedendents."""
24
25 file = open('dump.json')
26 edges = json.load(file)
27 file.close()
28
29 # Copy out only the edges we're interested in from the full edge list.
30 target_edges = {}
31 to_visit = targets[:]
32 while to_visit:
33 src = to_visit.pop()
34 if src in target_edges:
35 continue
36 target_edges[src] = edges[src]
37 to_visit.extend(edges[src])
38
39 return target_edges
40
41
42 def WriteGraph(edges):
43 """Print a graphviz graph to stdout.
44 |edges| is a map of target to a list of other targets it depends on."""
45
46 # Bucket targets by file.
47 files = collections.defaultdict(list)
48 for src, dst in edges.items():
49 build_file, target_name, toolset = ParseTarget(src)
50 files[build_file].append(src)
51
52 print 'digraph D {'
53 print ' fontsize=8' # Used by subgraphs.
54 print ' node [fontsize=8]'
55
56 # Output nodes by file. We must first write out each node within
57 # its file grouping before writing out any edges that may refer
58 # to those nodes.
59 for filename, targets in files.items():
60 if len(targets) == 1:
61 # If there's only one node for this file, simplify
62 # the display by making it a box without an internal node.
63 target = targets[0]
64 build_file, target_name, toolset = ParseTarget(target)
65 print ' "%s" [shape=box, label="%s\\n%s"]' % (target, filename,
66 target_name)
67 else:
68 # Group multiple nodes together in a subgraph.
69 print ' subgraph "cluster_%s" {' % filename
70 print ' label = "%s"' % filename
71 for target in targets:
72 build_file, target_name, toolset = ParseTarget(target)
73 print ' "%s" [label="%s"]' % (target, target_name)
74 print ' }'
75
76 # Now that we've placed all the nodes within subgraphs, output all
77 # the edges between nodes.
78 for src, dsts in edges.items():
79 for dst in dsts:
80 print ' "%s" -> "%s"' % (src, dst)
81
82 print '}'
83
84
85 if __name__ == '__main__':
86 if len(sys.argv) < 2:
87 print >>sys.stderr, __doc__
88 print >>sys.stderr
89 print >>sys.stderr, 'usage: %s target1 target2...' % (sys.argv[0])
90 sys.exit(1)
91
92 edges = LoadEdges('dump.json', sys.argv[1:])
93
94 WriteGraph(edges)
+0
-142
third_party/gyp/tools/pretty_gyp.py less more
0 #!/usr/bin/env python
1 # Copyright (c) 2009 The Chromium Authors. 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 # This file pretty-prints the contents of a GYP file.
6
7 import sys
8 import re
9
10 input = []
11 if len(sys.argv) > 1:
12 input_file = open(sys.argv[1])
13 input = input_file.read().splitlines()
14 input_file.close()
15 else:
16 input = sys.stdin.read().splitlines()
17
18 # This is used to remove comments when we're counting braces.
19 comment_re = re.compile(r'\s*#.*')
20
21 # This is used to remove quoted strings when we're counting braces.
22 # It takes into account quoted quotes, and makes sure that the quotes
23 # match.
24 # NOTE: It does not handle quotes that span more than one line, or
25 # cases where an escaped quote is preceeded by an escaped backslash.
26 quote_re_str = r'(?P<q>[\'"])(.*?)(?<![^\\][\\])(?P=q)'
27 quote_re = re.compile(quote_re_str)
28
29 def comment_replace(matchobj):
30 return matchobj.group(1) + matchobj.group(2) + '#' * len(matchobj.group(3))
31
32 def mask_comments(input):
33 # This is used to mask the quoted strings so we skip braces inside
34 # quoted strings.
35 search_re = re.compile(r'(.*?)(#)(.*)')
36 return [search_re.sub(comment_replace, line) for line in input]
37
38 def quote_replace(matchobj):
39 return "%s%s%s%s" % (matchobj.group(1),
40 matchobj.group(2),
41 'x'*len(matchobj.group(3)),
42 matchobj.group(2))
43
44 def mask_quotes(input):
45 # This is used to mask the quoted strings so we skip braces inside
46 # quoted strings.
47 search_re = re.compile(r'(.*?)' + quote_re_str)
48 return [search_re.sub(quote_replace, line) for line in input]
49
50 def do_split(input, masked_input, search_re):
51 output = []
52 mask_output = []
53 for (line, masked_line) in zip(input, masked_input):
54 m = search_re.match(masked_line)
55 while m:
56 split = len(m.group(1))
57 line = line[:split] + r'\n' + line[split:]
58 masked_line = masked_line[:split] + r'\n' + masked_line[split:]
59 m = search_re.match(masked_line)
60 output.extend(line.split(r'\n'))
61 mask_output.extend(masked_line.split(r'\n'))
62 return (output, mask_output)
63
64 # This masks out the quotes and comments, and then splits appropriate
65 # lines (lines that matche the double_*_brace re's above) before
66 # indenting them below.
67 def split_double_braces(input):
68 # These are used to split lines which have multiple braces on them, so
69 # that the indentation looks prettier when all laid out (e.g. closing
70 # braces make a nice diagonal line).
71 double_open_brace_re = re.compile(r'(.*?[\[\{\(,])(\s*)([\[\{\(])')
72 double_close_brace_re = re.compile(r'(.*?[\]\}\)],?)(\s*)([\]\}\)])')
73
74 masked_input = mask_quotes(input)
75 masked_input = mask_comments(masked_input)
76
77 (output, mask_output) = do_split(input, masked_input, double_open_brace_re)
78 (output, mask_output) = do_split(output, mask_output, double_close_brace_re)
79
80 return output
81
82 # This keeps track of the number of braces on a given line and returns
83 # the result. It starts at zero and subtracts for closed braces, and
84 # adds for open braces.
85 def count_braces(line):
86 open_braces = ['[', '(', '{']
87 close_braces = [']', ')', '}']
88 closing_prefix_re = re.compile(r'(.*?[^\s\]\}\)]+.*?)([\]\}\)],?)\s*$')
89 cnt = 0
90 stripline = comment_re.sub(r'', line)
91 stripline = quote_re.sub(r"''", stripline)
92 for char in stripline:
93 for brace in open_braces:
94 if char == brace:
95 cnt += 1
96 for brace in close_braces:
97 if char == brace:
98 cnt -= 1
99
100 after = False
101 if cnt > 0:
102 after = True
103
104 # This catches the special case of a closing brace having something
105 # other than just whitespace ahead of it -- we don't want to
106 # unindent that until after this line is printed so it stays with
107 # the previous indentation level.
108 if cnt < 0 and closing_prefix_re.match(stripline):
109 after = True
110 return (cnt, after)
111
112 # This does the main work of indenting the input based on the brace counts.
113 def prettyprint_input(lines):
114 indent = 0
115 basic_offset = 2
116 last_line = ""
117 for line in lines:
118 if comment_re.match(line):
119 print line
120 else:
121 line = line.strip('\r\n\t ') # Otherwise doesn't strip \r on Unix.
122 if len(line) > 0:
123 (brace_diff, after) = count_braces(line)
124 if brace_diff != 0:
125 if after:
126 print " " * (basic_offset * indent) + line
127 indent += brace_diff
128 else:
129 indent += brace_diff
130 print " " * (basic_offset * indent) + line
131 else:
132 print " " * (basic_offset * indent) + line
133 else:
134 print ""
135 last_line = line
136
137 # Split up the double braces.
138 lines = split_double_braces(input)
139
140 # Indent and print the output.
141 prettyprint_input(lines)
+0
-167
third_party/gyp/tools/pretty_sln.py less more
0 #!/usr/bin/python2.5
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Prints the information in a sln file in a diffable way.
7
8 It first outputs each projects in alphabetical order with their
9 dependencies.
10
11 Then it outputs a possible build order.
12 """
13
14 __author__ = 'nsylvain (Nicolas Sylvain)'
15
16 import os
17 import re
18 import sys
19 import pretty_vcproj
20
21 def BuildProject(project, built, projects, deps):
22 # if all dependencies are done, we can build it, otherwise we try to build the
23 # dependency.
24 # This is not infinite-recursion proof.
25 for dep in deps[project]:
26 if dep not in built:
27 BuildProject(dep, built, projects, deps)
28 print project
29 built.append(project)
30
31 def ParseSolution(solution_file):
32 # All projects, their clsid and paths.
33 projects = dict()
34
35 # A list of dependencies associated with a project.
36 dependencies = dict()
37
38 # Regular expressions that matches the SLN format.
39 # The first line of a project definition.
40 begin_project = re.compile(('^Project\("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942'
41 '}"\) = "(.*)", "(.*)", "(.*)"$'))
42 # The last line of a project definition.
43 end_project = re.compile('^EndProject$')
44 # The first line of a dependency list.
45 begin_dep = re.compile('ProjectSection\(ProjectDependencies\) = postProject$')
46 # The last line of a dependency list.
47 end_dep = re.compile('EndProjectSection$')
48 # A line describing a dependency.
49 dep_line = re.compile(' *({.*}) = ({.*})$')
50
51 in_deps = False
52 solution = open(solution_file)
53 for line in solution:
54 results = begin_project.search(line)
55 if results:
56 # Hack to remove icu because the diff is too different.
57 if results.group(1).find('icu') != -1:
58 continue
59 # We remove "_gyp" from the names because it helps to diff them.
60 current_project = results.group(1).replace('_gyp', '')
61 projects[current_project] = [results.group(2).replace('_gyp', ''),
62 results.group(3),
63 results.group(2)]
64 dependencies[current_project] = []
65 continue
66
67 results = end_project.search(line)
68 if results:
69 current_project = None
70 continue
71
72 results = begin_dep.search(line)
73 if results:
74 in_deps = True
75 continue
76
77 results = end_dep.search(line)
78 if results:
79 in_deps = False
80 continue
81
82 results = dep_line.search(line)
83 if results and in_deps and current_project:
84 dependencies[current_project].append(results.group(1))
85 continue
86
87 # Change all dependencies clsid to name instead.
88 for project in dependencies:
89 # For each dependencies in this project
90 new_dep_array = []
91 for dep in dependencies[project]:
92 # Look for the project name matching this cldis
93 for project_info in projects:
94 if projects[project_info][1] == dep:
95 new_dep_array.append(project_info)
96 dependencies[project] = sorted(new_dep_array)
97
98 return (projects, dependencies)
99
100 def PrintDependencies(projects, deps):
101 print "---------------------------------------"
102 print "Dependencies for all projects"
103 print "---------------------------------------"
104 print "-- --"
105
106 for (project, dep_list) in sorted(deps.items()):
107 print "Project : %s" % project
108 print "Path : %s" % projects[project][0]
109 if dep_list:
110 for dep in dep_list:
111 print " - %s" % dep
112 print ""
113
114 print "-- --"
115
116 def PrintBuildOrder(projects, deps):
117 print "---------------------------------------"
118 print "Build order "
119 print "---------------------------------------"
120 print "-- --"
121
122 built = []
123 for (project, dep_list) in sorted(deps.items()):
124 if project not in built:
125 BuildProject(project, built, projects, deps)
126
127 print "-- --"
128
129 def PrintVCProj(projects):
130
131 for project in projects:
132 print "-------------------------------------"
133 print "-------------------------------------"
134 print project
135 print project
136 print project
137 print "-------------------------------------"
138 print "-------------------------------------"
139
140 project_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[1]),
141 projects[project][2]))
142
143 pretty = pretty_vcproj
144 argv = [ '',
145 project_path,
146 '$(SolutionDir)=%s\\' % os.path.dirname(sys.argv[1]),
147 ]
148 argv.extend(sys.argv[3:])
149 pretty.main(argv)
150
151 def main():
152 # check if we have exactly 1 parameter.
153 if len(sys.argv) < 2:
154 print 'Usage: %s "c:\\path\\to\\project.sln"' % sys.argv[0]
155 return
156
157 (projects, deps) = ParseSolution(sys.argv[1])
158 PrintDependencies(projects, deps)
159 PrintBuildOrder(projects, deps)
160
161 if '--recursive' in sys.argv:
162 PrintVCProj(projects)
163
164 if __name__ == '__main__':
165 main()
166
+0
-316
third_party/gyp/tools/pretty_vcproj.py less more
0 #!/usr/bin/python2.5
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Make the format of a vcproj really pretty.
7
8 This script normalize and sort an xml. It also fetches all the properties
9 inside linked vsprops and include them explicitly in the vcproj.
10
11 It outputs the resulting xml to stdout.
12 """
13
14 __author__ = 'nsylvain (Nicolas Sylvain)'
15
16 import os
17 import sys
18
19 from xml.dom.minidom import parse
20 from xml.dom.minidom import Node
21
22 REPLACEMENTS = dict()
23 ARGUMENTS = None
24
25 class CmpTuple:
26 """Compare function between 2 tuple."""
27 def __call__(self, x, y):
28 (key1, value1) = x
29 (key2, value2) = y
30 return cmp(key1, key2)
31
32 class CmpNode:
33 """Compare function between 2 xml nodes."""
34
35 def get_string(self, node):
36 node_string = "node"
37 node_string += node.nodeName
38 if node.nodeValue:
39 node_string += node.nodeValue
40
41 if node.attributes:
42 # We first sort by name, if present.
43 node_string += node.getAttribute("Name")
44
45 all_nodes = []
46 for (name, value) in node.attributes.items():
47 all_nodes.append((name, value))
48
49 all_nodes.sort(CmpTuple())
50 for (name, value) in all_nodes:
51 node_string += name
52 node_string += value
53
54 return node_string
55
56 def __call__(self, x, y):
57 return cmp(self.get_string(x), self.get_string(y))
58
59 def PrettyPrintNode(node, indent=0):
60 if node.nodeType == Node.TEXT_NODE:
61 if node.data.strip():
62 print '%s%s' % (' '*indent, node.data.strip())
63 return
64
65 if node.childNodes:
66 node.normalize()
67 # Get the number of attributes
68 attr_count = 0
69 if node.attributes:
70 attr_count = node.attributes.length
71
72 # Print the main tag
73 if attr_count == 0:
74 print '%s<%s>' % (' '*indent, node.nodeName)
75 else:
76 print '%s<%s' % (' '*indent, node.nodeName)
77
78 all_attributes = []
79 for (name, value) in node.attributes.items():
80 all_attributes.append((name, value))
81 all_attributes.sort(CmpTuple())
82 for (name, value) in all_attributes:
83 print '%s %s="%s"' % (' '*indent, name, value)
84 print '%s>' % (' '*indent)
85 if node.nodeValue:
86 print '%s %s' % (' '*indent, node.nodeValue)
87
88 for sub_node in node.childNodes:
89 PrettyPrintNode(sub_node, indent=indent+2)
90 print '%s</%s>' % (' '*indent, node.nodeName)
91
92 def FlattenFilter(node):
93 """Returns a list of all the node and sub nodes."""
94 node_list = []
95
96 if (node.attributes and
97 node.getAttribute('Name') == '_excluded_files'):
98 # We don't add the "_excluded_files" filter.
99 return []
100
101 for current in node.childNodes:
102 if current.nodeName == 'Filter':
103 node_list.extend(FlattenFilter(current))
104 else:
105 node_list.append(current)
106
107 return node_list
108
109 def FixFilenames(filenames, current_directory):
110 new_list = []
111 for filename in filenames:
112 if filename:
113 for key in REPLACEMENTS:
114 filename = filename.replace(key, REPLACEMENTS[key])
115 os.chdir(current_directory)
116 filename = filename.strip('"\' ')
117 if filename.startswith('$'):
118 new_list.append(filename)
119 else:
120 new_list.append(os.path.abspath(filename))
121 return new_list
122
123 def AbsoluteNode(node):
124 # Make all the properties we know about in this node absolute.
125 if node.attributes:
126 for (name, value) in node.attributes.items():
127 if name in ['InheritedPropertySheets', 'RelativePath',
128 'AdditionalIncludeDirectories',
129 'IntermediateDirectory', 'OutputDirectory',
130 'AdditionalLibraryDirectories']:
131 # We want to fix up these paths
132 path_list = value.split(';')
133 new_list = FixFilenames(path_list, os.path.dirname(ARGUMENTS[1]))
134 node.setAttribute(name, ';'.join(new_list))
135 if not value:
136 node.removeAttribute(name)
137
138 def CleanupVcproj(node):
139 # For each sub node, we call recursively this function.
140 for sub_node in node.childNodes:
141 AbsoluteNode(sub_node)
142 CleanupVcproj(sub_node)
143
144 # Normalize the node, and remove all extranous whitespaces.
145 for sub_node in node.childNodes:
146 if sub_node.nodeType == Node.TEXT_NODE:
147 sub_node.data = sub_node.data.replace("\r", "")
148 sub_node.data = sub_node.data.replace("\n", "")
149 sub_node.data = sub_node.data.rstrip()
150
151 # Fix all the semicolon separated attributes to be sorted, and we also
152 # remove the dups.
153 if node.attributes:
154 for (name, value) in node.attributes.items():
155 sorted_list = sorted(value.split(';'))
156 unique_list = []
157 [unique_list.append(i) for i in sorted_list if not unique_list.count(i)]
158 node.setAttribute(name, ';'.join(unique_list))
159 if not value:
160 node.removeAttribute(name)
161
162 if node.childNodes:
163 node.normalize()
164
165 # For each node, take a copy, and remove it from the list.
166 node_array = []
167 while node.childNodes and node.childNodes[0]:
168 # Take a copy of the node and remove it from the list.
169 current = node.childNodes[0]
170 node.removeChild(current)
171
172 # If the child is a filter, we want to append all its children
173 # to this same list.
174 if current.nodeName == 'Filter':
175 node_array.extend(FlattenFilter(current))
176 else:
177 node_array.append(current)
178
179
180 # Sort the list.
181 node_array.sort(CmpNode())
182
183 # Insert the nodes in the correct order.
184 for new_node in node_array:
185 # But don't append empty tool node.
186 if new_node.nodeName == 'Tool':
187 if new_node.attributes and new_node.attributes.length == 1:
188 # This one was empty.
189 continue
190 if new_node.nodeName == 'UserMacro':
191 continue
192 node.appendChild(new_node)
193
194 def GetConfiguationNodes(vcproj):
195 #TODO(nsylvain): Find a better way to navigate the xml.
196 nodes = []
197 for node in vcproj.childNodes:
198 if node.nodeName == "Configurations":
199 for sub_node in node.childNodes:
200 if sub_node.nodeName == "Configuration":
201 nodes.append(sub_node)
202
203 return nodes
204
205 def GetChildrenVsprops(filename):
206 dom = parse(filename)
207 if dom.documentElement.attributes:
208 vsprops = dom.documentElement.getAttribute('InheritedPropertySheets')
209 return FixFilenames(vsprops.split(';'), os.path.dirname(filename))
210 return []
211
212 def SeekToNode(node1, child2):
213 # A text node does not have properties.
214 if child2.nodeType == Node.TEXT_NODE:
215 return None
216
217 # Get the name of the current node.
218 current_name = child2.getAttribute("Name")
219 if not current_name:
220 # There is no name. We don't know how to merge.
221 return None
222
223 # Look through all the nodes to find a match.
224 for sub_node in node1.childNodes:
225 if sub_node.nodeName == child2.nodeName:
226 name = sub_node.getAttribute("Name")
227 if name == current_name:
228 return sub_node
229
230 # No match. We give up.
231 return None
232
233 def MergeAttributes(node1, node2):
234 # No attributes to merge?
235 if not node2.attributes:
236 return
237
238 for (name, value2) in node2.attributes.items():
239 # Don't merge the 'Name' attribute.
240 if name == 'Name':
241 continue
242 value1 = node1.getAttribute(name)
243 if value1:
244 # The attribute exist in the main node. If it's equal, we leave it
245 # untouched, otherwise we concatenate it.
246 if value1 != value2:
247 node1.setAttribute(name, ';'.join([value1, value2]))
248 else:
249 # The attribute does nto exist in the main node. We append this one.
250 node1.setAttribute(name, value2)
251
252 # If the attribute was a property sheet attributes, we remove it, since
253 # they are useless.
254 if name == 'InheritedPropertySheets':
255 node1.removeAttribute(name)
256
257 def MergeProperties(node1, node2):
258 MergeAttributes(node1, node2)
259 for child2 in node2.childNodes:
260 child1 = SeekToNode(node1, child2)
261 if child1:
262 MergeProperties(child1, child2)
263 else:
264 node1.appendChild(child2.cloneNode(True))
265
266 def main(argv):
267 global REPLACEMENTS
268 global ARGUMENTS
269 ARGUMENTS = argv
270 """Main function of this vcproj prettifier."""
271
272 # check if we have exactly 1 parameter.
273 if len(argv) < 2:
274 print ('Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] '
275 '[key2=value2]' % argv[0])
276 return
277
278 # Parse the keys
279 for i in range(2, len(argv)):
280 (key, value) = argv[i].split('=')
281 REPLACEMENTS[key] = value
282
283 # Open the vcproj and parse the xml.
284 dom = parse(argv[1])
285
286 # First thing we need to do is find the Configuration Node and merge them
287 # with the vsprops they include.
288 for configuration_node in GetConfiguationNodes(dom.documentElement):
289 # Get the property sheets associated with this configuration.
290 vsprops = configuration_node.getAttribute('InheritedPropertySheets')
291
292 # Fix the filenames to be absolute.
293 vsprops_list = FixFilenames(vsprops.strip().split(';'),
294 os.path.dirname(argv[1]))
295
296 # Extend the list of vsprops with all vsprops contained in the current
297 # vsprops.
298 for current_vsprops in vsprops_list:
299 vsprops_list.extend(GetChildrenVsprops(current_vsprops))
300
301 # Now that we have all the vsprops, we need to merge them.
302 for current_vsprops in vsprops_list:
303 MergeProperties(configuration_node,
304 parse(current_vsprops).documentElement)
305
306 # Now that everything is merged, we need to cleanup the xml.
307 CleanupVcproj(dom.documentElement)
308
309 # Finally, we use the prett xml function to print the vcproj back to the
310 # user.
311 #print dom.toprettyxml(newl="\n")
312 PrettyPrintNode(dom.documentElement)
313
314 if __name__ == '__main__':
315 main(sys.argv)
0 あいがん 哀願 * 情にうったえて頼むこと。
1 あいがん 愛玩 * かわいがること。
2 あいしょう 愛唱 * 好んで歌うこと。
0 あいがん 哀願 * 情にうったえる。
1 あいがん 愛玩 * かわいがる。
2 あいしょう 愛唱 * 好んで歌う
33 あいしょう 哀傷 * 悲しみいたむこと。
44 あいしょう 愛称 * 親しみを込めて呼ぶ名称。
5 あいしょう 相性 * 互いの性格、性質の合う程度。「相性が良い」
6 あう 逢う 五段・ワ行促音便 「会う」に同じ。情緒をこめるときに使われる。「恋人に逢う」
5 あいしょう 相性 * 性格、性質が合うこと。
6 あう 逢う 五段・ワ行促音便 人にあう。「恋人に逢う」
77 あう 会う 五段・ワ行促音便 人にあう。「友達と会う」
8 あう 合う 五段・ワ行促音便 ぴったりあう。「息が合う」「答が合う」
9 あう 遭う 五段・ワ行促音便 思いがけず、よくないことに巻き込まれる。「事故に遭う」
10 あおい 青い 形容詞・アウオ段 1. 晴れているときの空や海の色。「空が青い」\n2. 〈「蒼い」とも〉血の気がない。「青い顔をしている」
11 あおい 蒼い 形容詞・アウオ段 〈まれ〉血の気がない。「顔が蒼い」→青い2
12 あおぐ 仰ぐ 五段・ガ行 1. 上を向く。「天を仰ぐ」\n2. 教えなどを求める。「指示を仰ぐ」\n3. 尊敬する。「師と仰ぐ」\n4. 飲む。「毒を仰ぐ」
13 あおぐ 扇ぐ 五段・ガ行 うちわなどを動かし、風を出す。
14 あか 垢 * 皮膚上の脂、汗など老廃物が固まったもの。
15 あがく 足掻く 五段・カ行イ音便 〈かな書きも〉あばれる。もがく。
16 あかし 証 * 証明するもの。証明。「友好の証として自国の動物を寄贈する」
17 あかし 灯 * 〈文語〉 ともしび。
18 あかり 明かり * ともしび。照明。「街に明かりがともる」
19 あがる 挙がる 五段・ラ行 1. (特に手について)上にあげられる。「手が挙がる」\n2. (証拠・犯人が)見つかる。「証拠が挙がる」「犯人が挙がった」\n3. (名前などが)話に出される。「候補として彼女の名前が挙がった」\n4. 〈「上がる」とも〉ひとつひとつ取りざたされる。列挙される。「これら3点が問題点として挙がった」
20 あがる 上がる 五段・ラ行 1. 高い位置、高い水準に移る。「階段を上がる」「中級クラスに上がった」「物価が上がる」\n2. 建物に入る。「靴を脱いでお上がりください」\n3. (水浴びなどを)終える。「シャワーから上がった」\n4. (火・煙が)出る。「煙が上がっている」\n5. (声などが)発せされる。「歓声が上がった」\n6. (費用が)思ったより安く、その中におさまる。「旅行は3万円で上がった」\n7. (電池が)放電して使えなくなる。「車のバッテリーが上がった」\n8. (仕事が)終わる。「仕事が上がって飲みに行った」\n9. 〈ボードゲームで〉ゲームの目的を達成する。「彼女が最初に上がった」\n10. 〈尊敬語〉食べる。「冷めないうちにお上がりください」\n11. (謙譲語)訪れる。「近々お礼に上がります」\n12. (成果・効果などが)あらわれる。「効果が上がる」\n13.(雨などが)止まる。「雨が上がる」\n14. 〈「アガる」とも〉緊張する。「面接で上がってしまった」
21 あがる 揚がる 五段・ラ行 1. 〈「上がる」とも〉空高くあがる。「凧(たこ)が揚がる」\n2. 〈「上がる」とも〉高くかかげられる。「旗が揚がる」\n3. 油であげたものができあがる。「天ぷらが揚がる」
22 あきる 厭きる 一段 →飽きる
23 あきる 飽きる 一段 〈「厭きる」とも〉同じようなことの繰り返しにうんざりする。
24 あく 開く 五段・カ行イ音便 1. (閉まっていたものが)ひらく。「扉が開く」「蓋が開く」⇔閉まる・閉じる。\n2. (店などの)営業が始まる。「新しい店がまだ開かない」\n3. 〈「空く」とも〉(穴が)できる。「壁に穴が開いた」
25 あく 空く 五段・カ行イ音便 1. そこにあったものがなくなり、空間や時間ができる。「隙間が空く」「席が空く」「グラスが空く」「手が空く」(=さしあたってすることがなくなる)\n2. 〈「開く」とも〉(穴が)できる。「壁に穴が空いた」
26 あく 飽く 五段・カ行イ音便 〈文語〉「飽きる」に同じ。
27 あく 明く 五段・カ行イ音便 〈文語〉見えるようになる。「目が明く」
28 あげ 上げ * 〈接尾語〉上げること。「問題を棚上げする」
29 あげ 揚げ * 1. 〈接尾語〉油で揚げること。また、揚げたもの。「さつま揚げ」「から揚げ」\n2. 〈多く「お揚げ」として〉「油揚げ」の略。薄く切った豆腐を揚げたもの。「うどんに揚げがのっている」
30 あける 開ける 一段 1. (閉じていたものを)ひらく。「窓を開ける」\n2. (店などの)営業を始める。また、営業をする。「日曜日にも店を開ける」\n3. (穴を)つくる。「板に穴を開けた」
31 あける 空ける 一段 1. からにする。「グラスを空ける」「家を空ける」\n2. あいだに時間や空白をはさむ。「ある程度の期間を空ける」「行間を空ける」\n3. 空間や時間を埋めないでおく。「後から来る人のために場所を空ける」「来客のためにスケジュールを空ける」\n4. 〈「開ける」とも〉(穴を)つくる。「板に穴を空けた」
32 あける 明ける 一段 ある時期が終わって、別の時期になる。「夜が明ける」「年が明ける」「テストが明ける」
33 あげる 挙げる 一段 1. (特に手について)上にあげる。「手を挙げる」\n2. (証拠・犯人を)見つける。「証拠を挙げる」「犯人を挙げた」\n3. (名前などを)話に出す。「候補として彼女の名前を挙げた」\n4. 〈「上げる」とも〉ひとつひとつ取りざたする。列挙する。「これら3点を問題点として挙げた」
34 あげる 上げる 一段 1. 高い位置、高い水準に移す。「荷物を網棚に上げる」「学生を中級クラスに上げる」「料金を上げる」\n2. 建物に入れる。「客を家に上げる」\n3. (火・煙を)出す。「煙を上げて燃えている」\n4. (声などを)発する。「歓声を上げた」\n5. (費用を)安い範囲におさめる。「旅費を3万円で上げる」\n6. (仕事を)終える。「この仕事を上げてから飲みに行く」\n7. (成果・効果を)あらわす。「効果を上げる」
35 あげる 揚げる 一段 1. 〈「上げる」とも〉空高くあげる。「凧(たこ)を揚げる」\n2. 〈「上げる」とも〉高くかかげる。「旗を揚げる」\n3. 高温の油に浸して調理する。「天ぷらを揚げる」
36 あし 葦 * イネ科の多年草。
37 あし 脚 * 足の付け根から足首までを指すときに、「足」と区別して使う。「すらりとした脚」
38 あし 足 * 1. 人間・動物などが移動のために使う部分の総称。「昆虫には足が六本ある」\n2. 足首から下の部分。「足が大きい」
39 あじ 味 * 1. 舌で感じる、あまい・からい・にがいなどの感覚。\n2.
40 あじ 鰺 * アジ科の魚。
41 あずかる 与る 五段・ラ行 〈かな書きも〉\n1. かかわる。「計画に与る」\n2. (恩恵などを)受ける。もらう。「恩恵に与る」「栄誉に与る」
42 あずかる 預る 五段・ラ行 →預かる
43 あずかる 預かる 五段・ラ行 一時的にまかせられる。「荷物を預かる」
44 あだ 仇 * 1. 〈「仇になる」として〉(かえって)害になる。「自分で解決しようとしたのが仇になった」\n2. かたき。「仇を打つ」
45 あだ 徒 * 〈かな書きも〉無駄。「親切が徒となる」
46 あたたか 温か * 1. (ものなどが)冷たくなくほどよい。「温かな水」\n2. 〈「暖か」とも〉(心・態度などが)やさしく気遣いがある。「温かな心」
47 あたたか 暖か * 1. (気温、気象などが)寒くなくほどよい。「暖かな春」\n2. 〈「温か」とも〉(心・態度などが)やさしく気遣いがある。「暖かな心」
48 あたたかい 温かい 形容詞・アウオ段 1. (ものなどが)冷たくなくほどよい。「水温が温かい」\n2. 〈「暖かい」とも〉(心・態度などが)やさしく気遣いがある。「心が温かい」
49 あたたかい 暖かい 形容詞・アウオ段 1. (気温、気象などが)寒くなくほどよい。「春は暖かい」\n2. 〈「温かい」とも〉(心・態度などが)やさしく気遣いがある。「心が暖かい」
50 あたたまる 温まる 五段・ラ行 1. (ものなどが)温かくなる。「水が温まる」\n2. 〈「暖まる」とも〉(心が)じんわりと和やかになる。「心が温まる」
51 あたたまる 暖まる 五段・ラ行 1. (気温、気象などが)暖かくなる。「部屋が暖まる」\n2. 〈「温まる」とも〉(心が)じんわりと和やかになる。「心が暖まる」
52 あたためる 温める 一段 1. (ものなどを)温かくする。「水を温める」「卵を温める」\n2. 〈「暖める」とも〉(心を)和やかにする。\n3. (考えなどを)外に出さずに自分の中で練る。「数年温めていた計画」\n4. (友情などを)確認し、親しく過ごす。「旧交を温める」
53 あたためる 暖める 一段 1. (気温などを)暖かくする。「部屋を暖める」\n2. 〈「温める」とも〉(心を)和やかにする。
54 あつい 厚い 形容詞・アウオ段 1. 幅がある。「厚い本」\n2. 〈「篤い」とも〉感情の程度が大きい。「情に厚い」「信頼が厚い」
55 あつい 暑い 形容詞・アウオ段 気温が高い。「夏は暑い」⇔寒い
56 あつい 篤い 形容詞・アウオ段 〈文語〉\n1. 重症である。「篤い病」\n2. 〈「厚い」とも〉感情の程度が大きい。「情に篤い」「信頼が篤い」
57 あつい 熱い 形容詞・アウオ段 1. ものなどの温度が高い。「熱いお湯」⇔冷たい 2. 相手を思う気持ちが強い。「熱い仲」
58 あっかん 悪漢 * 悪いことをする男。「悪漢に襲われる」
59 あっかん 圧巻 * 特にすばらしいこと。「圧巻のラストシーン」
8 あう 合う 五段・ワ行促音便 ぴったりあう。「息が合う、答が合う」
9 あう 遭う 五段・ワ行促音便 おもいがけずにあう。「事故に遭う」
10 あおい 青い 形容詞・アウオ段 あおいろに見える。「空が青い」
11 あおい 蒼い 形容詞・アウオ段 血の気のないあお。「顔が蒼い」
12 あおぐ 仰ぐ 五段・ガ行 上を向く。「天を仰ぐ、指示を仰ぐ、師と仰ぐ、毒を仰ぐ」
13 あおぐ 扇ぐ 五段・ガ行 団扇などを動かし、風を出す。
14 あか 垢 * 脂、汗などが
15 あがく 足掻く 五段・カ行イ音便 あばれる、もがく
16 あかし 証 * 証明すること
17 あかし 灯 * ともしび
18 あかり 灯 * ともしび
19 あかり 明かり * 明るいもの。「街に明かりがともる」
20 あがる 挙がる 五段・ラ行 はっきり示される。「手が挙がる」
21 あがる 上がる 五段・ラ行 (一般的)高い位置に移る。「階段を上がる、雨が上がる」
22 あがる 騰がる 五段・ラ行 値段があがる。「物価が騰がる」
23 あがる 揚がる 五段・ラ行 高くあがる。「凧が揚がる、天ぷらが揚がる」
24 あきる 厭きる 一段 あきること(飽きると同じ意味)
25 あきる 飽きる 一段 あきること(厭きると同じ意味)
26 あく 開く 五段・カ行イ音便 ひらく。「扉が開く、蓋が開く」<->閉まる、閉じる。
27 あく 空く 五段・カ行イ音便 そこにあったものがなくなる。「隙間が空く、手が空く、席が空く、グラスが空く」
28 あく 飽く 五段・カ行イ音便 あきる。うんざりする。
29 あく 明く 五段・カ行イ音便 見えるようになる。はっきりする。「目が明く、喪が明く」
30 あげ 上げ * 上に移す。「問題を棚上げする」
31 あげ 揚げ * あぶらであげたもの。「薩摩揚げ、唐揚げ」
32 あける 開ける 一段 ひらく。「窓を開ける」
33 あける 空ける 一段 からにする。「グラスを空ける、家を空ける」
34 あける 明ける 一段 あかるくなる。「夜が明ける」
35 あげる 挙げる 一段 はっきり示す。「手を挙げる」
36 あげる 上げる 一段 (一般的)高い位置に移す。「棚に上げる」
37 あげる 揚げる 一段 高くあげる。「旗を揚げる」
38 あし 葦 * イネ科の多年草
39 あし 脚 * (人、動物などで)支えとなるもの。
40 あし 足 * (一般的)支えとなるもの。
41 あじ 味 * 舌で感じる感覚。
42 あじ 鰺 * アジ科の魚
43 あずかる 与る 五段・ラ行 かかわる。「計画に与る」
44 あずかる 預る 五段・ラ行 まかせられる。「荷物を預る」
45 あずかる 預かる 五段・ラ行 まかせられる。「荷物を預かる」
46 あだ 仇 * (敵)自分に害となるもの。
47 あだ 徒 * (類義:無駄)「親切が徒となる」
48 あたたか 温か * (感触などに対して)冷たくなくほどよい。「温かな水」
49 あたたか 暖か * (気温、気象などに対して)寒くなくほどよい。「暖かな春、暖かな心」
50 あたたかい 温かい 形容詞・アウオ段 (感触などに対して)冷たくなくほどよい。「水温が温かい」
51 あたたかい 暖かい 形容詞・アウオ段 (気温、気象などに対して)寒くなくほどよい。「春は暖かい、心が暖かい」
52 あたたまる 温まる 五段・ラ行 (感触などに対して)温かくなる。「水が温まる」
53 あたたまる 暖まる 五段・ラ行 (気温、気象などに対して)暖かくなる。「部屋が暖まる」
54 あたためる 温める 一段 (感触などに対して)温かくする。「水を温める」
55 あたためる 暖める 一段 (気温、気象などに対して)暖かくする。「部屋を暖める」
56 あつい 厚い 形容詞・アウオ段 幅があるさま。(対:薄い)「厚い本、情に厚い」
57 あつい 暑い 形容詞・アウオ段 気温などが高い。(対:寒い)「夏は暑い」
58 あつい 篤い 形容詞・アウオ段 重症であるさま。「篤い病」
59 あつい 熱い 形容詞・アウオ段 ものなどの温度が高い。(対:冷たい)「熱いお湯、熱い仲」
60 あっかん 悪漢 * わるいことをする男
61 あっかん 圧巻 * 特にすばらしいこと
6062 あてる 宛てる 一段 指名する。「友人に宛てて手紙を書く」
6163 あてる 充てる 一段 充当する。「その一万円を食費に充てる」
62 あてる 当てる 一段 1. 命中させる。「ボールを的に当てる」\n2. 正しい答を言う。「答を当てる」
63 あな 穴 * 1. くぼんだ部分。「落とし穴」「虎の穴」\n2. 〈「孔」とも〉つきぬけた部分。「服の穴」\n3. 行き届いていない部分。「捜査の穴」
64 あな 孔 * つきぬけた部分。「針の孔」→穴2
64 あてる 当てる 一段 命中させる。「ボールを的に当てる、答を当てる」
65 あな 穴 * (一般的)くぼんだ部分。「落とし穴、虎の穴、捜査の穴」
66 あな 孔 * つきぬけた穴。「針の孔」
6567 あぶら 脂 * (常温で固体の)動物、植物の脂質。「脂身」
66 あぶら 油 * (常温で液体の)動物、植物の脂質。「ごま油」
68 あぶら 油 * (常温で液体の)動物、植物の脂質。「胡麻油」
6769 あやまる 誤る 五段・ラ行 まちがえる。「目測を誤る」
6870 あやまる 謝る 五段・ラ行 間違いをわびる。「失礼を謝る」
69 あらい 荒い 形容詞・アウオ段 (性質などが)はげしい。「気性が荒い」「波が荒い」
70 あらい 粗い 形容詞・アウオ段 1. ざらざらしている。「木目が粗い」\n2. いい加減である。「作りが粗い」
71 あらわ 露わ * 外から見えているさま。「肌が露わになる」
72 あらわす 顕す 五段・サ行 広く知らせる。「名を顕す」
73 あらわす 現す 五段・サ行 かくれていたものをあきらかにする。「姿を現す」
71 あらい 荒い 形容詞・アウオ段 (性質などが)はげしい。「気性が荒い、波が荒い」
72 あらい 粗い 形容詞・アウオ段 おおざっぱであるさま。「木目が粗い、作りが粗い」
73 あらわ 露わ * あきらかになるさま。「肌が露わになる」
74 あらわす 顕す 五段・サ行 広く知らせる。「世の中に事実を顕す」
75 あらわす 現す 五段・サ行 かくれていたものがあらわれる。「姿を現す」
7476 あらわす 著す 五段・サ行 書物を書いて世に出す。「書物を著す」
75 あらわす 表す 五段・サ行 はっきりと示す。「感情を表す」「文章に表す」
76 あらわれる 現れる 一段 隠れていたものが明らかになる。「本性が現れる」
77 あらわれる 表れる 一段 はっきりと示される。「感情が表情に表れる」
78 ある 在る 五段・ラ行 〈主にかな書き〉\n1. 物が存在する。「建物がある」\n2. ある状態に置かれている。「苦しい境遇にある」
79 ある 有る 五段・ラ行 〈主にかな書き〉\n所有している。「彼には金がある」
80 いう 謂う 五段・ワ行促音便 →言う
81 いう 云う 五段・ワ行促音便 →言う
82 いう 言う 五段・ワ行促音便 〈「謂う」「云う」とも〉言葉に出す。「御礼を言う」
83 いかす 生かす 五段・サ行 1. 生きているままにする。「生かしておけない」\n2.〈「活かす」とも〉力を発揮させる。「才能を活かす」
84 いかす 活かす 五段・サ行 〈「生かす」とも〉力を発揮させる。「才能を活かす」
85 いき 遺棄 * すてること。「死体を遺棄する」
86 いき 息 * 呼吸。「まだ息をしている」
77 あらわす 表す 五段・サ行 はっきりと示す。「感情を表す、文章に表す」
78 あらわれる 現れる 一段 かくれていたものがあらわれる。「本章が現れる」
79 あらわれる 表れる 一段 表面にでる。「感情が表情に表れる」
80 ある 在る 五段・ラ行 物が存在する。いる。「建物が在る、境遇に在る」
81 ある 有る 五段・ラ行 物事が存在する。所有する。「金が有る、学生で有る」
82 あわす 会わす 五段・サ行 (人と人とを)対面させる。「顔を会わせる」
83 あわす 合わす 五段・サ行 ひとつにする。「答を合わせる、息を合わせる」
84 いう 謂う 五段・ワ行促音便 (「言う、云う」と区別なし)言葉に出す。「御礼を謂う」
85 いう 云う 五段・ワ行促音便 (「謂う、言う」と区別なし)言葉に出す。「御礼を云う」
86 いう 言う 五段・ワ行促音便 (「云う、謂う」と区別なし、一般的)言葉に出す。「御礼を言う」
87 いかす 活かす 五段・サ行 (「生かす」ともいう)力を発揮させる。「才能を活かす」
88 いき 遺棄 * すてる。「死体を遺棄する」
89 いき 息 * 呼吸をする。「まだ息をしている」
8790 いぎ 意義 * 意味。「参加することに意義がある」
8891 いぎ 異義 * 異なる意味。「同音異義語」
8992 いぎ 異議 * 異なる意見。「その提案に異議があります」
9093 いぎょう 偉業 * すばらしい仕事。「歴史に残る偉業」
9194 いぎょう 遺業 * 故人がなしとげた仕事。「遺業を引き継ぐ」
92 いぎょう 医業 * 医者としての仕事。「医業に携わる」
93 いく 行く 五段・カ行促音便 今の場所から移動する。「学校に行く」
95 いぎょう 医業 * 医者としての仕事。
96 いく 行く 五段・カ行促音便 今の場所から出かける。「学校に行く」
9497 いく 逝く 五段・カ行促音便 (人が)死ぬ。「偉大な学者が逝ってしまった」
9598 いしょく 委嘱 * (仕事などを)たのむ。「研究を委嘱する」
96 いしょく 移植 * 他の場所に移して機能させる。「肝臓を移植する」「プログラムを移植する」
97 いたく 依託 * 〈まれ〉他人にまかせること。
98 いたく 委託 * 委ねまかせること。「委託売買」
99 いたむ 傷む 五段・マ行 1. 傷つく。「床が傷む」\n2. 腐る。「野菜が傷む」
100 いたむ 痛む 五段・マ行 痛みを感じる。「傷が痛む」
99 いしょく 移植 * 他の場所に移す。「肝臓を移植する、プログラムを移植する」
100 いたく 依託 * たよりまかすこと。
101 いたく 委託 * 委ねまかすこと。「委託売買」
102 いたむ 傷む 五段・マ行 きずつく、腐る。「床が傷む、野菜が傷む」
103 いたむ 痛む 五段・マ行 いたみを感じる。「傷が痛む」
101104 いたむ 悼む 五段・マ行 (人の死を)悲しく思う。「彼の死を悼む」
102 いためる 傷める 一段 傷つける。「床を傷める」
103 いためる 痛める 一段 痛くする。「腕を痛める」
104 いためる 炒める 一段 少量の油を使って加熱調理する。「豚肉を炒める」
105 いっかつ 一喝 * 大きなひと声でしかりつける。「若者を一喝する」
106 いっかつ 一括 * ひとつにまとめる。「一括して精算する」
105 いためる 傷める 一段 きずつける。「床を傷める」
106 いためる 痛める 一段 いたい思いをさせる。「腕を痛める」
107 いためる 炒める 一段 油を使って加熱調理する。「豚肉を炒める」
108 いっかつ 一喝 * 大きな声でしかりつける。「若者を一喝する」
109 いっかつ 一括 * ひとつにくくる。「一括して精算する」
107110 いっしゅう 一周 * ひとまわりする。「グラウンドを一周する」
108111 いっしゅう 一蹴 * はねつける。「申し出を一蹴する」
109 いどう 異動 * (地位などが)かわること。「異動して部長になった」
110 いどう 移動 * (場所などが)うつること。「場所を移動する。」
111 いりゅう 慰留 * (辞任することを)なだめて思いとどまらせること。「部下を慰留する」
112 いどう 異動 * (地位などが)かわる。「異動して部長になった」
113 いどう 移動 * うつる。「場所を移動する。」
114 いりゅう 慰留 * (辞任することを)なだめて思いとどまらせる。「部下を慰留する」
112115 いりゅう 遺留 * 死後にのこす。「遺留品」
113116 いる 煎る 五段・ラ行 強い火で熱して水分をとる。「ごまを煎る」
114117 いる 入る 五段・ラ行 はいる。「薮に分け入る」
115118 いる 要る 五段・ラ行 必要とする。「人手が要る」
116 いる 居る 一段 〈主にかな書き〉一つの場所に存在する。「学校にいる」
117 いる 射る 一段 矢を放つ。また、矢を放って目的に命中させる。「的を射る」
119 いる 居る 一段 一つの場所に存在する。「学校に居る、本を読んでいる」
120 いる 射る 一段 矢を放つ。「的を射る」
118121 いる 鋳る 一段 鋳造する。「鉄瓶を鋳る」
119122 いんすう 員数 * 人などの数。
120 いんすう 因数 * 整式をいくつかの整式の積として分解したとき、その分解したもの。「因数分解」
123 いんすう 因数 * 数や式において、1、その数以外の整数では割れない因子。「因数分解」
121124 うかがう 窺う 五段・ワ行促音便 様子をみる。「顔色を窺う」
122 うかがう 伺う 五段・ワ行促音便 〈謙譲語〉\n1. 訪問する。「そちらに伺います」\n2. 尋ねる。聞く。「住所を伺ってもよろしいでしょうか」
123 うける 受ける 一段 1. 来るものを手でとめる。受け止める。「ボールを受ける」\n2. もらう。授かる。「恩恵を受ける」「生を受ける」\n3. 〈「承ける」とも〉もとにする。対処する。「事故の結果を受けて態勢を見直す」\n4. 〈文語〉〈「承ける」とも〉(跡を)つぐ。「父の跡を受ける」\n5. 影響をこうむる。(自然現象などに)さらされる。「風雨を受ける」「暴力を受ける」\n6. (検査・審査などの)対象となる。「検査を受ける」\n7. 人気を得る。笑ってもらえる。「このギャグはやたらと受けた」\n8. 〈若者言葉〉〈「ウケる」とも〉おもしろい。笑える。「あの人すごく受ける」
124 うける 承ける 一段 〈まれ〉\n1. もとにする。「事故の結果を承けて態勢を見直す」→受ける3\n2. 〈文語〉(跡を)つぐ。「父の跡を承ける」→受ける4
125 うける 請ける 一段 1. お金をもらって仕事を任される。「公共工事を請ける」\n2. 〈文語〉お金を払って取り戻す。「質草を請ける」
126 うける 享ける 一段 (命などを)授かる。「生を享ける」→受ける2
127 うし 丑 * 干支(えと)の一つ。子(ね)の次、寅(とら)の前。
125 うかがう 伺う 五段・ワ行促音便 (謙譲語)訪問する、尋ねる。「明日に伺います、ご住所を伺ってもよろしいでしょうか」
126 うける 受ける 一段 (一般的)迎え入れる。「ボールを受ける、ダジャレが受ける、恩恵を受ける」
127 うける 承ける 一段 あとをつぐ。「稼業を承ける」
128 うける 請ける 一段 (仕事を)引き受ける。「ダム工事を請ける」
129 うし 丑 * 干支の一つ。
128130 うし 牛 * ウシ目ウシ科の動物の総称。
129 うし 齲歯 * むしば。
130 うたう 唄う 五段・ワ行促音便 →歌う
131 うたう 歌う 五段・ワ行促音便 〈「唄う」「謡う」とも〉歌をくちずさむ。「歌謡曲を歌う」
132 うたう 謡う 五段・ワ行促音便 →歌う
133 うたう 謳う 五段・ワ行促音便 (理念や宣伝文句を)前に押し出す。「戦争放棄が憲法で謳われている」「東洋一と謳われる校舎」
134 うつ 撃つ 五段・タ行 (弾丸などを)発射する。発射して傷つける。「銃を撃つ」「相手を撃つ」
135 うつ 打つ 五段・タ行 (ものを)強くあてる。「ボールを打つ」「釘を打つ」
136 うつ 討つ 五段・タ行 (敵などを)たおす。殺す「敵を討つ」
137 うつす 移す 五段・サ行 移動させる。「場所を移す」「視線を移す」
138 うつす 映す 五段・サ行 1. (光をはねかえすものに)反射させて見る。「自分の姿を鏡に映す」\n2. (スクリーンなどに)映写する。「映画を映す」
139 うつす 写す 五段・サ行 1. 元となるものを見ながら同じものを書く。「ノートを写す」\n2. 写真をとる。
140 うつる 移る 五段・ラ行 移動する。「場所を移る」「視線が移る」
141 うつる 映る 五段・ラ行 1. (光をはねかえすものに)反射されて見える。「水面に映る景色」\n2. (スクリーンなどに)映写する。(テレビなどに画面が)あらわれる。「テレビが映らない」
142 うつる 写る 五段・ラ行 (写真として)撮影される。「写真に写る」
143 うま 午 * 干支(えと)の一つ。巳(み)の次、未(ひつじ)の前。
144 うま 馬 * ウマ目ウマ科の動物の総称。
145 うむ 産む 五段・マ行 (子供、卵などを)体外に出す。出産する。「にわとりが卵を産む」\n※具体的な出産をあらわすときに多く使われる。
146 うむ 生む 五段・マ行 1. 〈一般的〉出産する。「子供を生む」\n※抽象的な表現で多く使われる。\n2. つくりだす。「傑作を生む」
147 うむ 膿む 五段・マ行 化膿する。うみがたまる。「傷口が膿む」
148 うらむ 怨む 五段・マ行 →恨む
149 うらむ 憾む 五段・マ行 〈文語〉残念に思う。「稚拙な攻撃が憾まれる」→恨む2
150 うらむ 恨む 五段・マ行 1. 人から嫌なことをされたと思い、反感を持つ。「彼に恨まれている」\n2. 〈文語では「憾む」とも〉残念に思う。「自分の不勉強を恨む」「稚拙な攻撃が恨まれる」
151 うる 得る 一段・得ル 〈文語〉える。手に入れる。「大金を得る」
131 うし 齲歯 * むしば
132 うたう 唄う 五段・ワ行促音便 (「歌う、謡う」と区別なし)歌をくちずさむ。「歌謡曲を唄う」
133 うたう 歌う 五段・ワ行促音便 (「唄う、謡う」と区別なし、一般的)歌をくちずさむ。「歌謡曲を歌う」
134 うたう 謡う 五段・ワ行促音便 (「歌う、唄う」と区別なし)歌をくちずさむ。「歌謡曲を謡う」
135 うたう 謳う 五段・ワ行促音便 強調されている。「戦争放棄が憲法で謳われている、東洋一と謳われる校舎」
136 うつ 撃つ 五段・タ行 (弾丸などを)発射する。「銃を撃つ、相手を撃つ」
137 うつ 打つ 五段・タ行 (ものを)強くあてる。「ボールを打つ、釘を打つ、芝居を打つ」
138 うつ 討つ 五段・タ行 (敵などを)たおす。「敵を討つ」
139 うつす 移す 五段・サ行 移動させる。「場所を移す、視線を移す」
140 うつす 映す 五段・サ行 (スクリーンなどに)ものの形をあらわす。「映画を映す」
141 うつす 写す 五段・サ行 まねてあらわす。「写真を写す、ノートを写す」
142 うつる 移る 五段・ラ行 移動する。「場所を移る、視線が移る」
143 うつる 映る 五段・ラ行 (スクリーンなどに)あらわれる。「テレビが映る」
144 うつる 写る 五段・ラ行 あらわれる。「写真に写る」
145 うま 午 * 干支の一つ
146 うま 馬 * ウマ目ウマ科の動物の総称
147 うむ 産む 五段・マ行 (子供、卵などを)体外にだす。「にわとりが卵を産む」
148 うむ 生む 五段・マ行 子供が誕生する。「子供を生む、傑作を生む」
149 うむ 膿む 五段・マ行 うみがたまる。「傷口が膿む」
150 うらむ 怨む 五段・マ行 (「恨む」と区別なし)根にもつ。「彼に怨まれている」
151 うらむ 憾む 五段・マ行 残念に思う。「稚拙な攻撃が憾まれる」
152 うらむ 恨む 五段・マ行 (「怨む」と区別なし)根にもつ。「彼に恨まれている」
153 うる 得る 一段・得ル (文語)える。「大金を得る、実現し得る」
152154 うる 売る 五段・ラ行 代金を受けとり品物を渡す。「土地を売る」
153 うれい 愁い * →憂い
154 うれい 憂い * 〈「愁い」とも〉\n1. 心配すること。\n2. 悲しく思うこと。
155 うれう 愁う 五段・ワ行ウ音便 →憂う
156 うれう 憂う 五段・ワ行ウ音便 〈「愁う」とも〉\n1. 心配する。また、悲しく思う。「将来を憂う」「被災地の惨状を憂う」
157 うれえる 愁える 一段 →憂える
158 うれえる 憂える 一段 〈「愁える」とも〉\n1. 心配する。また、悲しく思う。「将来を憂える」「被災地の惨状を憂える」
155 うれい 愁い * 悲しう思うこと。
156 うれい 憂い * 心配すること。
157 うれえる 愁える 一段 悲しく思う。「死を愁える」
158 うれえる 憂える 一段 心配する。「将来を憂える」
159159 うんこう 運航 * (船、航空機が)きまった航路をすすむこと。「飛行機は正常に運航している」
160160 うんこう 運行 * きまった路線をすすむこと。「バスの運行」
161 えいずる 映ずる サ変・−ズル (光などが)うつる。「木々が湖面に映ずる」
161 えいずる 映ずる サ変・−ズル うつる。「木々が湖面に映ずる」
162162 えいずる 詠ずる サ変・−ズル (詩歌を)うたう。「詩を詠ずる」
163 えびす 夷 * 1. 未開の土地の人間に対する古い蔑称。\n2. 〈「恵比寿」が一般的〉七福神の一人。
164 えびす 恵比寿 * 七福神の一人。
165 えびす 恵比須 * 1. 大阪の地名。\n2. 〈「恵比寿」が一般的〉七福神の一人。
166 えびす 戎 * 〈「恵比寿」が一般的〉七福神の一人。
167 えびす 蛭子 * 〈「恵比寿」が一般的〉七福神の一人。
168 える 獲る 一段 (獲物を)とる。「鹿を獲る」
163 えびす 夷 * えぞ、七福神の一人
164 えびす 恵比寿 * 七福神の一人
165 えびす 恵比須 * 地名、七福神の一人
166 えびす 戎 * 七福神の一人
167 えびす 蛭子 * 七福神の一人
168 える 獲る 一段 (獲物を)とる。「鹿を獲る、戦利品を獲る」
169169 える 選る 一段 えらぶ。
170 える 得る 一段 手に入れる。「利益を得る」
170 える 得る 一段 手に入れる。「利益を得る、やむをえない」
171171 えんげい 園芸 * 庭木などの栽培。
172172 えんげい 演芸 * 落語などの芸。
173173 おいこむ 追い込む 五段・マ行 追いつめる。「犯人を追い込む」
174174 おいこむ 老い込む 五段・マ行 年をとる。「彼もすっかり老い込んだ」
175 おう 逐う 五段・ワ行促音便 →追う
176 おう 追う 五段・ワ行促音便 目標をつかまえようとする。「犯人を追う」
177 おう 負う 五段・ワ行促音便 1. 背負う。「荷物を負う」\n2. ひきうける。「責任を負う」
175 おう 逐う 五段・ワ行促音便 (「追う」と区別なし)目標をつかまえようとする。「犯人を逐う」
176 おう 追う 五段・ワ行促音便 (「逐う」と区別なし)目標をつかまえようとする。「犯人を追う」
177 おう 負う 五段・ワ行促音便 ひきうける。「荷物を負う、責任を負う」
178178 おういん 押印 * 判をおすこと。「申請書に押印する」
179179 おういん 押韻 * 韻をふむこと。
180180 おうしゅう 応酬 * やりとりする。「互いに応酬する」
181181 おうしゅう 押収 * (証拠品などを)とりあげる。「証拠品を押収する」
182 おかす 侵す 五段・サ行 1. 侵害する。「領土を侵す」\n2. 〈「冒す」とも〉〈受身で〉(病気に)かかる。「病に侵された少年」
183 おかす 犯す 五段・サ行 1. 規則にそむく。「過ちを犯す」「罪を犯す」\n2. 性的暴行を加える。
184 おかす 冒す 五段・サ行 1. 押し切ってする。「危険を冒す」\n2. 〈「侵す」とも〉〈受身で〉(病気に)かかる。「病に冒された少年」
185 おく 置く 五段・カ行イ音便 1. ものから手を離して、ある位置にとどめる。「グラスを置く」\n2. (機関や部署、役職などを)つくる。設置する。また、設置している。「マイアミに司令部を置く」「監督官を置く」\n3. (抽象的なものを)設定する。「重点を置く」\n4. 仮に割り当てる。「この関数をf(x)と置く」\n5. ある状態にする。ある状態に留める。「国家管理の下に置く」\n6. (時間・空間を)あける。「間を置く」「距離を置く」\n7. (信用などを)与える。「信頼を置く人」\n8. 〈特に執筆に関しては「擱く」とも〉ものから手を離して、それを使った行為をやめる。「筆を置く」「箸を置く」\n9. 〈口語体では「置いておく」とすることが多い。文語体では「措く」とも〉とりあえず考えないことにする。棚上げする。「この問題はとりあえず置いておこう」「この問題はひとまず置くとする」
186 おく 擱く 五段・カ行イ音便 〈「置く」とも〉〈特に執筆に関して〉ものから手を離して、それを使った行為をやめる。「筆を擱く」「ペンを擱く」
187 おく 措く 五段・カ行イ音便 〈文語体〉〈「置く」とも〉とりあえず考えないことにする。棚上げする。「この問題はひとまず措くとする」
188 おくる 送る 五段・ラ行 1. 郵送や電子的な手段でものや情報を他の場所に届ける。「手紙を送る」「メールを送る」\n2. 去る人に途中まで同行する。「客を駅まで送る」
189 おくる 贈る 五段・ラ行 気持ちを示すためにあたえる。「御歳暮を贈る」
190 おくれる 後れる 一段 〈文語〉\n1. あとである。うしろである。「順位が後れるもの」\n2. 〈「遅れる」とも〉ついていけなくなる。取り残される。「時代に後れる」
191 おくれる 遅れる 一段 1. (決まった時間より)遅くなる。「待ち合わせに遅れる」\n2. 速度が遅く、しだいに後ろに行く。「この時計は一日に一分遅れる」\n3. 後ろの位置を保って進む。「この時計は遅れている」「三歩ほど遅れてついていく」\n4. 〈「後れる」とも〉ついていけなくなる。取り残される。「時代に遅れる」
192 おこす 起こす 五段・サ行 1. 持ち上げて縦にする。「体を起こす」\n2. 人を目覚めさせる。「毎朝子供を起こしている」
182 おかす 侵す 五段・サ行 侵害する。「領土を侵す、病に侵される」
183 おかす 犯す 五段・サ行 規則にそむく。「過ちを犯す」
184 おかす 冒す 五段・サ行 押し切ってする。「危険を冒す、病に冒される」
185 おく 置く 五段・カ行イ音便 その位置にとどめる。「グラスを置く、担当者を置く」
186 おくる 送る 五段・ラ行 (物・人を)他の場所に移す。「手紙を送る、駅まで送る」
187 おくる 贈る 五段・ラ行 あたえる。「御歳暮を贈る」
188 おくれる 後れる 一段 とりのこされる。「流行に後れる」
189 おくれる 遅れる 一段 まにあわなくなる。「待ち合わせに遅れる」
190 おこす 起こす 五段・サ行 たたせる。「からだを起こす、毎朝子供を起こしている」
193191 おこす 興す 五段・サ行 さかんにする。「国を興す」
194 おこる 起こる 五段・ラ行 〈「起きる」に同じ〉(現象、気持ちなどが)生まれる。「波が起こる」「地震が起こる」「発作が起こる」「憎しみが起こる」
192 おこる 起こる 五段・ラ行 はじまる。「地震が起こる」
195193 おこる 興る 五段・ラ行 さかんになる。「国が興る」
196 おこる 怒る 五段・ラ行 腹を立てる。また、その気持を相手にぶつける。いかる。「怒ってどなりつける」「部下を怒る」
197 おさえこむ 押え込む 五段・マ行 おさえて動かないようにする。「犯人を押さえ込む」
194 おこる 怒る 五段・ラ行 いかる。「怒ってどなりつける、部下を怒る」
195 おさえこむ 押え込む 五段・マ行 おさえて動かないようにする。「犯人を押さえ込む
198196 おさえこむ 抑え込む 五段・マ行 (柔道の寝技の意で)おさえこむ。
199 おさまる 治まる 五段・ラ行 1. 政治がゆきとどく。「国内が治まる」\n2. 痛み・症状などが静まる。「痛みが治まる」\n3. 〈「収まる」とも〉風雨や騒ぎなどが静まる。「騒ぎが治まる」
200 おさまる 収まる 五段・ラ行 1. 入れ物の中にはいる。「倉庫の中に収まる」\n2. 〈「治まる」とも〉風雨や騒ぎが静まる。「騒ぎが収まる」
197 おさまる 治まる 五段・ラ行 しずまる。「国内が治まる、傷みが治まる」
198 おさまる 収まる 五段・ラ行 入れ物の中にはいる。「倉庫の中に収まった、騒ぎが収まる」
201199 おさまる 修まる 五段・ラ行 言動がととのう。「素行が修まる」
202 おさまる 納まる 五段・ラ行 1. (金品が)きちんとわたされる。「税金が納まる」\n2. ある位置・地位につく。「社長に納まる」
200 おさまる 納まる 五段・ラ行 (金品が)きちんとわたされる。「税金が納まる、社長に納まる」
203201 おさめる 治める 一段 統治する。「国を治める」
204 おさめる 収める 一段 1. しまう。収納する。「倉庫に収める」\n2. のせる。収録する。「辞書に収める」\n3. 手に入れる。成し遂げる。「成功を収める」
205 おさめる 修める 一段 1. (学問・技能などを)修得する。「学問を修める」\n2. 整える。きちんとする。「身を修める」
206 おさめる 納める 一段 (渡すべき金品を)渡す。「税金を納める」
207 おじ 叔父 * 父または母の弟。
208 おじ 小父 * 〈主にかな書き〉(子供から見た)血のつながっていない大人の男性。一般的には「さん」をつける。「近所のおじさん」
209 おじ 伯父 * 父または母の兄。
210 おす 圧す 五段・サ行 →押す5
211 おす 押す 五段・サ行 1. ものに触れて力を入れる。「背中を押す」「上から押す」\n2. 〈「捺す」とも〉(印鑑などに)力を入れることで印字する。「判を押す」\n3. (説得や宣伝、求愛などで)積極的に働きかける。「あんまり押しすぎると引かれるよ」\n4. (勝負などで)積極的に攻める。「いい手が入ったので押すことにした」\n5. 〈「圧す」とも〉圧倒する。「気迫に押される」
212 おす 推す 五段・サ行 推薦する。「彼を議長に推す」
213 おす 捺す 五段・サ行 →押す2
214 おぞましい 鈍ましい 形容詞・アウオ段 〈文語〉にぶい。
215 おぞましい 悍ましい 形容詞・アウオ段 〈主にかな書き〉ぞっとするようないやな感じ。「おぞましい光景」
216 おちる 堕ちる 一段 〈「落ちる」とも〉堕落(だらく)する。落ちぶれる。悪い状態になる。悪い環境に身をおとす。「あいつも堕ちたものだ」「地獄に堕ちる」→落ちる4
217 おちる 墜ちる 一段 〈「落ちる」とも〉引力などにより、上から下に移動する。墜落する。「飛行機が墜ちる」→落ちる1
218 おちる 落ちる 一段 1. 〈「墜ちる」とも〉引力などにより、ものが上から下に移動する。「りんごが落ちる」「飛行機が落ちる」\n2. (状態が)悪くなる。「鮮度が落ちるのが早い」\n3. 〈形容詞的〉(状態が)悪い。「品質が落ちる品」\n4. (試験などに)不合格になる。「予選で落ちる」\n5. 〈「堕ちる」とも〉堕落(だらく)する。落ちぶれる。悪い状態になる。悪い環境に身をおとす。「あいつも落ちたものだ」「地獄に落ちる」\n6. 〈柔道で〉首を絞められて気を失う。「絞め技をかけられて落ちてしまった」\n7. (原稿などが)入稿が遅れて掲載されなくなる。「病気で原稿が落ちた」
219 おどる 躍る 五段・ラ行 1. 躍動する。\n2. わくわくする。「胸が躍る」
220 おどる 踊る 五段・ラ行 (音に合わせて)体や手足を動かす。「日本舞踊を踊る」
221 おば 叔母 * 父または母の妹。
222 おば 小母 * 〈主にかな書き〉(子供から見た)血のつながっていない大人の女性。一般的には「さん」をつける。「近所のおばさん」
223 おば 伯母 * 父または母の姉。
224 おもて 表 * 二つの面があるものに関して、目に見えている側。「コインの表」⇔裏
225 おもて 面 * 〈文語〉顔。「面を上げよ」
226 おりこむ 織り込む 五段・マ行 1. 織ってくみこむ。「模様を織り込む」\n2. 事態を予想して、それに基づいた行動をとる。「相場は悪材料を織り込んで動いている」
227 おりこむ 折り込む 五段・マ行 折りまげて小さくたたむ。「紙を折り込む」
228 おりる 下りる 一段 1. 下に移動する。「山から下りる」\n2. (上の立場のものから、許可や承認が)得られる。「工場建設の許可が下りる」
229 おりる 降りる 一段 乗物から外に出る。「電車から降りる」
230 おる 居る 五段・ラ行 〈古風〉いる。「昔、一休という和尚が居った」
231 おる 織る 五段・ラ行 縦糸と横糸を組み合わせて布をつくる。「布を織る」
232 おる 折る 五段・ラ行 曲げる、また曲げて二つにする。「紙を折る」「釣りざおを折ってしまった」
233 おろす 卸す 五段・サ行 問屋が小売店に商品を売る。「野菜を卸す」
234 おろす 下ろす 五段・サ行 1. 下に移す。「棚から荷物を下ろす」\n2. すりおろす。「大根を下ろす」\n3. 銀行などに預けていたお金を引き出す。「貯金を下ろす」
235 おろす 降ろす 五段・サ行 1. 乗物から出す。「バスから降ろす」\n2. 役から外す。「役者を降ろす」
202 おさめる 収める 一段 しまう。「倉庫に収める、辞書に収める、成功を収める」
203 おさめる 修める 一段 つくろう。「身を修める、学問を修める」
204 おさめる 納める 一段 (金品を)わたす。「税金を納める」
205 おじ 叔父 * 父または母の弟
206 おじ 小父 * (血のつながっていない)おじさん
207 おじ 伯父 * 父または母の兄
208 おす 圧す 五段・サ行 (「押す」も使う)圧迫する。「気迫に圧される」
209 おす 押す 五段・サ行 (一般的)ものに触れて力を入れる。「背中を押す、念を押す」
210 おす 推す 五段・サ行 推進させる。「彼を議長に推す」
211 おす 捺す 五段・サ行 (「押す」も使う)捺印する。「判を捺す」
212 おぞましい 鈍ましい 形容詞・アウオ段 にぶい。
213 おぞましい 悍ましい 形容詞・アウオ段 ぞっとするようないやな感じ。「悍ましい光景」
214 おちる 堕ちる 一段 (堕落した意で)ある状態におちこむ。「深い眠りに堕ちる」
215 おちる 墜ちる 一段 ついらくする。「飛行機が墜ちる」
216 おちる 落ちる 一段 (引力で)ものが上から下に移動する。「りんごが落ちる、試験に落ちる、品質が落ちる」
217 おどる 躍る 五段・ラ行 (躍動、跳躍の意)はねあがる。「胸が躍る」
218 おどる 踊る 五段・ラ行 (音に合わせて)手足をうごかす。「日本舞踊を踊る」
219 おば 叔母 * 父または母の妹
220 おば 小母 * (血のつながっていない)おばさん
221 おば 伯母 * 父または母の姉
222 おもて 表 * 表面。
223 おもて 面 * かお。物の表面。
224 おりこむ 織り込む 五段・マ行 織ってくみこむ。「模様を織り込む」
225 おりこむ 折り込む 五段・マ行 折りまげる。「紙を折り込む」
226 おりる 下りる 一段 下にいく。「幕が下りる、許可が下りる」
227 おりる 降りる 一段 乗物からでる。「車を降りる、梯子を降りる」
228 おる 居る 五段・ラ行 いる。「彼はどこにおられますか、勉強しております」
229 おる 織る 五段・ラ行 布をつくる。「布を織る。」
230 おる 折る 五段・ラ行 まげる。「小枝を折る、骨を折る(苦労する)」
231 おろす 卸す 五段・サ行 卸売をする。「野菜を卸す」
232 おろす 下ろす 五段・サ行 下へいかせる。「のれんを下ろす、大根を下ろす、貯金を下ろす」
233 おろす 降ろす 五段・サ行 乗物から出す。「バスから降ろす、役者を降ろす」
236234 おんし 恩師 * 教えをうけた先生。
237235 おんし 恩賜 * 天皇から賜わること。
238 おんわ 温和 * 1. (気候が)あたたかい。「沖縄は温和な気候だ」\n2. 〈「穏和」とも〉(性格が)おだやかである。「彼は温和な性格だ」
239 おんわ 穏和 * 〈「温和」とも〉(性格が)穏やかである。「彼は穏和な性格だ」
240 かす 化す 五段・サ行 (悪い状態に)変化する。「廃虚と化す」
241 かす 嫁す 五段・サ行 1. (古風)嫁にいく。「豊臣家に嫁した」\n2. 転嫁する。「責任を嫁す」
242 かす 科す 五段・サ行 刑罰を負わせる。「刑罰を科す」
243 かす 課す 五段・サ行 負担させる。「税金を課す」
244 かする 化する サ変・−スル (悪い状態に)変化する。「廃虚と化する」
245 かする 嫁する サ変・−スル 1. (古風)嫁にいく。「豊臣家に嫁した」\n2. 転嫁する。「責任を嫁する」
246 かする 科する サ変・−スル 刑罰を負わせる。「刑罰を科する」
247 かする 架する サ変・−スル かけわたす。「橋を架する」
248 かする 課する サ変・−スル 負担させる。「税金を課する」
249 かい 介する サ変・−スル 1. 間におく。「彼女を介して出会った」\n2. 〈「意に介する」の形で〉気にかける。「意に介さない」
250 かい 会する サ変・−スル 集まる。「一堂に会する」
251 かい 解する サ変・−スル 理解する。「気持を解する」「文意を解する」
252 かいえん 開園 * 動物園・公園などが営業を開始する。「その動物園の開園は10時だ」
236 おんわ 温和 * (気候が)あたたかい。「沖縄は温和である」
237 おんわ 穏和 * おとなしい。「彼は穏和である」
238 かする 化する サ変・−スル 変化する。「廃虚と化する」
239 か 化 * 変化する。「廃虚と化する」
240 か 嫁 * とつぐ。転嫁する。「責任を嫁する」
241 か 科 * 刑罰を負わせる。「刑罰を科する」
242 か 架 * かけわたす。「橋を架する」
243 か 課 * 負担させる。「税金を課する」
244 かい 介 * あいだにおく。「彼女を介して出逢う、意に介さない」
245 かい 会 * よりあう。「一堂に会する」
246 かい 解 * 理解する。「気持を解する、文意を解する」
247 かいえん 開園 * 動物園などが営業を開始する。「その動物園の開園は10時だ」
253248 かいえん 開宴 * うたげを始める。
254249 かいえん 開演 * 演劇などを始める。
255250 かいか 開化 * 文明が開ける。「文明開化」
256 かいか 開花 * 1. 花が開く。「さくらが開花した」\n2. 発揮される。「才能が開花した」
257 がいかん 外患 * 外国から受ける圧力や攻撃、またその憂慮。
258 がいかん 外観 * 外から見た様子。
259 かいてい 改定 * (規則などについて)更新すること。「運賃を改定する」
260 かいてい 改訂 * (書物などを)内容を改め、再び出版すること。「本を改訂する」
261 かいてい 開廷 * 法廷を開くこと。
262 かいふく 回復 * 1. もとの良い状態にもどる、またはもどすこと。「天気が回復する」「体力が少し回復した」「名誉を回復する」\n2. (遅れなどを)解消して追いつく。「遅れを回復する」
263 かいふく 快復 * 病気が完治すること。「病気の快復を祝う」
251 かいか 開花 * はなが開く。「さくらが開花した、才能が開花した」
252 がいかん 外患 * そとから受ける心配事。
253 がいかん 外観 * そとからみた様子。
254 かいてい 改定 * あらためる。「運賃を改定する」
255 かいてい 改訂 * (書物などを)あらためる。「本を改訂する」
256 かいてい 開廷 * 法廷を開く。
257 かいふく 回復 * もとの良い状態にもどること。「天気が回復する、信用を回復する」
258 かいふく 快復 * 病気が治ること。「病気が快復する」
264259 かいへい 開平 * 平方根を求めること。
265260 かいへい 開閉 * 開くことと閉じること。「ドアを開閉する」
266261 かいほう 介抱 * 病人などの世話をする。「怪我人を介抱する」
267 かいほう 解放 * 解き放つ。自由にする「人質を解放する」
268 かいほう 開放 * 1. 開けっぱなしにする。「ドアを開放する」\n2. 自由に使えるようにする。「施設を開放する」
262 かいほう 解放 * 自由にする。「人質を解放する」
263 かいほう 開放 * 開けっぱなしにする。「ドアを開放する、施設を開放する」
269264 かう 飼う 五段・ワ行促音便 動物をやしなう。「猫を飼う」
270 かう 買う 五段・ワ行促音便 1. 代金をはらい、物をもらう。「パソコンを買う」\n2. 他人に何らかの感情を引き起こす。「恨みを買う」\n3. (人物について)高く評価する。「彼の人柄を買う」
265 かう 買う 五段・ワ行促音便 代金をはらい、物をもらう。「パソコンを買う、彼の人柄を買う、うらみを買う」
271266 かえす 帰す 五段・サ行 帰らせる。「生徒を自宅に帰す」
272 かえす 返す 五段・サ行 1. 元の場所・あるべき場所にかえす。「自然に返す」\n2. 借りていたものをかえす。「借金を返す」\n3. 働きかけに対して反応をする。「答えを返す」
273 かえりみる 顧みる 一段 1. ふりかえる。「歴史を顧みる」\n2. 考慮する。「危険を顧みない」
274 かえりみる 省みる 一段 過去の自分や自分の言動について思いを巡らせる。「過去の行動を省みる」
275 かえる 帰る 五段・ラ行 (人が)元の場所・住居に戻る。「家に帰る」
276 かえる 返る 五段・ラ行 1. 元の場所・あるべき場所にもどる。「自然に返る」\n2. 貸していたものがもどってくる。「借金が返る」\n3. 働きかけに対して反応がある。「答えが返る」
277 かえる 換える 一段 〈「替える」とも〉(主に液体・気体について)古いものを出し、新しいものを入れる。「風呂の湯を換える」
278 かえる 替える 一段 〈「換える」とも〉とりかえる。交換する。「二人の席を替える」
279 かえる 代える 一段 代わりをさせる。代替とする。「押印に代えて署名する」
267 かえす 返す 五段・サ行 もとに戻す。「借金を返す、自然に返す、手のひらを返す」
268 かえりみる 顧みる 一段 ふりかえる。「歴史を顧みる、危険を顧みない」
269 かえりみる 省みる 一段 反省する。「過去のことを省みる」
270 かえる 帰る 五段・ラ行 もとの場所に戻る。「家に帰る」
271 かえる 返る 五段・ラ行 もとに戻る。「借金が返る、自然に返る、あきれ返る」
272 かえる 換える 一段 交換する。「商品を入れ換える」
273 かえる 替える 一段 とりかえる。「席を替える」
274 かえる 代える 一段 代りをさせる。「これをもって挨拶と代える」
280275 かえる 変える 一段 異なった状態にする。「顔色を変える」
281 かかる 架かる 五段・ラ行 空中に長いものがかけわたされる。「橋が架かる」
282 かかる 掛かる 五段・ラ行 〈1, 2, 3 以外はかな書きが多い〉\n1. ぶらさがる。「壁に絵が掛かっている」\n2. おおいかぶさる。「体に毛布が掛かっていた」\n3. ひっかかってつかまる。「魚が網に掛かった」\n4. 液体をかぶる。「顔に水が掛かった」\n5. 時間や金などが必要となる。「金が掛かる」\n6. 電話などの着信を受ける。「彼から電話が掛かってきた」\n7. (主に音声を出す)機械のスイッチが入る。また、それによって音が出る。「ラジオが掛かっていた」\n8. (鍵などによって)閉められている。「ドアには鍵が掛かっている」\n9. 診察してもらう。「医者に掛かる」\n10. 〈「罹る」とも〉(病気に)なる。「おたふく風邪に掛かった」
283 かかる 係る 五段・ラ行 (言語において、単語が)修飾する。「この形容詞はこの名詞に係る」
284 かかる 罹る 五段・ラ行 (病気に)なる。「おたふく風邪に罹った」→掛かる10
285 かかる 懸かる 五段・ラ行 1. あることがらの成否によって、ものが得られるかどうか、または別のことがらの成否が決まる。「その競技には賞品が懸かっている」「この事件の解決は君の努力に懸かっている」\n2. 空に浮かんでいる。「夜空に月が懸かる」
286 かかわる 関わる 五段・ラ行 〈「係わる」とも〉関係する。「その仕事に関わる」「命に関わる」
287 かかわる 係わる 五段・ラ行 関係する。→関わる
276 かかる 架かる 五段・ラ行 わたされる。「橋が架かる」
277 かかる 掛かる 五段・ラ行 ぶらさがる。「のれんが掛かる、わなに掛かる、迷惑が掛かる、金が掛かる」
278 かかる 係る 五段・ラ行 かかわる。「人命に係る、彼の腕に係っている」
279 かかる 懸かる 五段・ラ行 ものがうかぶ。「その競技には賞品が懸かっている、夜空に月が懸かる」
280 かかわる 関わる 五段・ラ行 (「係わる」と区別なし)関係する。「命に関わる、その仕事に関わる」
281 かかわる 係わる 五段・ラ行 (「関わる」と区別なし)関係する。「命に係わる、その仕事に係わる」
288282 かかわる 拘る 五段・ラ行 こだわる。「つまらないことに拘る」
289 かきあげる かき揚げる 一段 →かき上げる
290 かきあげる かき上げる 一段 (髪などに手をかけて)ひきあげる。「髪をかき上げる」
291 かきあげる 書き上げる 一段 1. 書き終える。「本を書き上げる」\n2. いくつかのことを残さずひとつひとつ書く。列挙する。「必要なことを書き上げる」
292 かきあげる 掻き上げる 一段 →かき上げる
293 かきあげる 掻き揚げる 一段 →かき上げる
294 かく 欠く 五段・カ行イ音便 1. 不足している。「協調性を欠く」\n2. 物のまわりを一部を壊して落とす。「花瓶の縁を欠く」
295 かく 書く 五段・カ行イ音便 文字をしるす。「文字を書く」「本を書く」
296 かく 掻く 五段・カ行イ音便 1. (爪などで)ものをこする。「頭を掻く」\n2. 手などを水の中で動かす。「水を掻いて泳ぐ」
297 かく 描く 五段・カ行イ音便 絵にえがく。「似顔絵を描く」
283 かきあげる かき揚げる 一段 上にひきあげる。「髪をかき揚げる」
284 かきあげる 書き上げる 一段 ひとつひとつ書く。書き終える。「必要な事を書き上げる、本を書き上げる」
285 かきあげる 掻き上げる 一段 上にひきあげる。「髪を掻き上げる」
286 かきあげる 掻き揚げる 一段 上にひきあげる。「髪を掻き揚げる」
287 かく 欠く 五段・カ行イ音便 こわす。「花瓶を欠く、協調性を欠く」
288 かく 書く 五段・カ行イ音便 文字をしるす。「文字を書く、文章を書く、本を書く」
289 かく 掻く 五段・カ行イ音便 (爪などで)ものをこする。「頭を掻く、水を掻く」
290 かく 描く 五段・カ行イ音便 絵にあらわす。「似顔絵を描く」
298291 かくしゅう 各週 * それぞれの週。
299 かくしゅう 隔週 * 一週間おき(二週間ごと)。
300 かげ 蔭 * →陰
301 かげ 陰 * 〈「蔭」とも〉\n1. 光の当たらない場所。「建物の陰になっている場所で涼む」「建物の陰になっていてここからは見えない」\n2. 表にあらわれないところ。「経済成長の陰で貧困が増加している」\n3. 対象となる人がいないところ。「陰で悪口を言う」\n4. 〈「翳」とも〉人に知らせない内面の暗さ。「陰のある悪役」
302 かげ 影 * 1. 光によってできるものの形。「日が暮れるにつれて影が長くなる」\n2. 人の姿、または印象。「影をひそめる」「影が薄い」「影も形もない」
303 かげ 翳 * 〈「陰」とも〉人に知らせない内面の暗さ。「翳のある悪役」→陰4
304 かける 架ける 一段 空中に長いものをわたす。「橋を架ける」
305 かける 掛ける 一段 〈1, 2, 3 以外はかな書きが多い〉\n1. ぶらさげる。「壁に絵を掛ける」\n2. おおいかぶせる。「体に毛布を掛けてあげた」\n3. ひっかけてつかまえる。「わなに掛ける」\n4. 液体を浴びせる。「怒ってコップの水を相手の顔に掛けた」\n5. 時間や金などをつぎこむ。「金を掛けて作る」\n6. 電話などを発信する。「彼に電話を掛けた」\n7. (主に音声を出す)機械のスイッチを入れる。また、それによって音を出す。「音楽を掛けた」\n8. (鍵などによって)閉める。「ドアに鍵を掛ける」\n9. 道具を使って掃除などをする。「床にぞうきんを掛ける」「部屋に掃除機を掛けた」\n10. 乗算を行う。「底辺と高さを掛ける」
306 かける 駆ける 一段 〈「駈ける」とも〉はしる。「丘を駆ける」
307 かける 駈ける 一段 →駆ける
308 かける 欠ける 一段 1. ものの一部が(壊れて)なくなり、形が完全でない状態になる。「皿が欠ける」「月が欠ける」\n2. 集団の一部がいなくなり、完全でない状態になる。「メンバーが欠ける」
309 かける 懸ける 一段 1. あることがらの成否によって、ものを与えるかどうかを決める。「賞金を懸ける」\n2. 失う覚悟をして取り組む。「命を懸けて戦う」
310 かける 賭ける 一段 勝負して、金品を受け渡す約束をする。「麻雀で金を賭ける」
311 かける 翔ける 一段 (鳥などが)飛ぶ。飛翔する。「天を翔ける」
292 かくしゅう 隔週 * 一週間おき。
293 かげ 蔭 * (「陰」と区別なし)光の当たらない場所。
294 かげ 陰 * (「蔭」と区別なし)光の当たらない場所。「陰で糸を引く」
295 かげ 影 * 光によってできるものの形。「影をひそめる、影も形もない」
296 かげ 翳 * かげり。
297 かける 架ける 一段 わたす。「橋を架ける」
298 かける 掛ける 一段 ぶらさげる。「のれんを掛ける、わなに掛ける、迷惑を掛ける、金を掛ける」
299 かける 駆ける 一段 (「駈ける」と区別なし)はしる。「丘を駆ける」
300 かける 駈ける 一段 (「駆ける」と区別なし)はしる。「丘を駈ける」
301 かける 欠ける 一段 一部がこわれる。「皿が欠ける、メンバーが欠ける」
302 かける 懸ける 一段 失う覚悟でおこなう。「命を懸ける、賞金を懸ける」
303 かける 賭ける 一段 勝負してものをもらえる約束をする。「麻雀で金を賭ける」
304 かける 翔ける 一段 (鳥などが)とぶ。「天を翔ける」
312305 かしぐ 傾ぐ 五段・ガ行 かたむく。「船が傾ぐ」
313 かしぐ 炊ぐ 五段・ガ行 〈文語〉(飯を)炊く。
306 かしぐ 炊ぐ 五段・ガ行 めしを炊く。
314307 かしょう 過小 * ちいさすぎること。「過小評価」
315308 かしょう 過少 * すくなすぎること。
316 かす 化す 五段・サ行 (悪い状態に)変化する。「廃虚と化す」
317 かす 科す 五段・サ行 (刑罰を)負わせる。「刑罰を科す」
318 かす 貸す 五段・サ行 自分のものを一時的に他人に渡す。「金を貸す」
309 かす 化す 五段・サ行 変化する。「廃虚と化す」
310 かす 科す 五段・サ行 刑罰を負わせる。「刑罰を科す」
311 かす 貸す 五段・サ行 自分のものを一時的に他人に渡す。「金を貸す、力を貸す」
319312 かする 科する サ変・−スル 刑罰を負わせる。「刑罰を科する」
320313 かせつ 仮設 * (建物などを)間に合わせでつくること。「仮設住宅」
321314 かせつ 架設 * (橋などを)かけること。「橋の架設工事」
322 かそう 仮想 * 1. かりに想定すること。「仮想敵国」\n2. そうではないものをそう見せること。「仮想ドライブ」
323 かそう 仮装 * 衣装によって外見をかえること。「仮装パーティー」
315 かそう 仮想 * かりに想定すること。「仮想記憶、仮想敵国」
316 かそう 仮装 * かりによそおうこと。「仮装パーティー」
324317 かそう 火葬 * 死体を焼いて葬ること。「祖父を火葬する」
325 かたい 堅い 形容詞・アウオ段 1. 〈「固い」とも〉しっかりしている。堅固、堅実である。「堅い守備」\n2. 〈「固い」とも〉確実性が高い。「堅い投資」\n3. 〈「固い」とも〉間違いがない。動かない。「彼の勝利は堅い」\n4. 〈「固い」とも〉(意志などが)ゆるぎない。「堅い意志」\n5. 〈「固い」「硬い」とも〉まじめだ。ふざけたところがない。「堅い話はこのぐらいにしよう」
326 かたい 固い 形容詞・アウオ段 1. 力を加えても形がなかなか変わらない。「結び目が固い」「固いマット」\n2. 〈「堅い」とも〉融通がきかない。「発想が固い」
327 かたい 硬い 形容詞・アウオ段 1. 力を加えてもまったく形が変わらない。「硬い岩石」\n2. 〈「固い」とも〉筋肉がこわばってなかなか動かない。「体が硬い」\n3. (表情などが)こわばっている。とりつきにくい。「硬い表情」\n4. (水について)カルシウムやマグネシウムのイオン含有量が多い。硬度が高い。硬水である。「硬い水」
328 かたい 難い 形容詞・アウオ段 〈「想像に難くない」として〉容易に想像できる。
318 かたい 堅い 形容詞・アウオ段 (材木など)力を加えても形が変わらない。堅実。「堅い材質、手堅い方法、堅い話、守備が堅い」
319 かたい 固い 形容詞・アウオ段 (一般的)力を加えても(形が)変わらない。「結び目が固い、意志が固い、頭が固い、勝利は固い」
320 かたい 硬い 形容詞・アウオ段 (金属、石など)力を加えても形が変わらない。「硬い岩石、硬い表情」
321 かたい 難い 形容詞・アウオ段 むずかしい。「想像に難くない」
329322 がっしゅうこく 合衆国 * アメリカ合衆国の略。
330323 かなう 叶う 五段・ワ行促音便 思うようになる。「願いが叶う」
331 かなう 敵う 五段・ワ行促音便 〈かな書きも〉匹敵する。「彼には敵わない」
324 かなう 敵う 五段・ワ行促音便 匹敵する。「彼には敵わない」
332325 かなう 適う 五段・ワ行促音便 よく合う。「理に適う」
333326 かねつ 加熱 * 熱を加えること。「なべを加熱する」
334327 かねつ 過熱 * 熱くなりすぎること。「競争が過熱する」
335328 がま 蝦蟇 * ヒキガエル。
336329 がま 蒲 * ガマ科の多年草。
337 かりあげる 刈り上げる 一段 1. 上に向かって切っていく。「髪を刈り上げる」\n2. 全体的に切って短くする。「雑草を刈り上げる」
330 かりあげる 刈り上げる 一段 髪を上に向かって刈る。「髪を刈り上げる、雑草を刈り上げる」
338331 かりあげる 借り上げる 一段 目上のものが目下のものから金品を借りる。「土地を借り上げる」
339 かりいれる 刈り入れる 一段 切って収穫する。「稲を刈り入れる」
340 かりいれる 借り入れる 一段 (金などを)借りる。「銀行から金を借り入れる」
341 かる 刈る 五段・ラ行 生えているものをきりとる。「草を刈る」「髪を刈る」
342 かる 苅る 五段・ラ行 →刈る
343 かる 駆る 五段・ラ行 1. 走らせる。「馬を駆る」\n2. 人をつかう。「雑用に駆られる」\n3. つきうごかす。「衝動に駆られる」
332 かりいれる 刈り入れる 一段 収穫する。「稲を刈り入れる」
333 かりいれる 借り入れる 一段 金などを借りること。「銀行から金を借り入れる」
334 かる 刈る 五段・ラ行 (苅ると区別なし)生えているものをきりとる。「草を刈る、髪を刈る」
335 かる 苅る 五段・ラ行 (刈ると区別なし)生えているものをきりとる。「草を苅る」
336 かる 駆る 五段・ラ行 走らせる。「馬を駆る、雑用に駆られる、衝動に駆られる」
344337 かる 狩る 五段・ラ行 鳥や獣をとる。「鹿を狩る」
345 かれる 枯れる 一段 1. (植物が)生気をなくす。「花が枯れる」「木が枯れた」\n2. 〈「涸れる」とも〉水がなくなる。「井戸が枯れる」\n3. 〈「嗄れる」とも〉声が出なくなる。「歌いすぎて喉が枯れた」\n4. 円熟する。「芸が枯れる」
346 かれる 涸れる 一段 →枯れる2
347 かれる 嗄れる 一段 →枯れる3
348 かわく 渇く 五段・カ行イ音便 1. 〈「喉が渇く」の形で〉生き物の水分が不足し、水分をとりたくなる。「喉が渇く」\n2. 渇望する。「愛に渇く」
349 かわく 乾く 五段・カ行イ音便 ものから水分がなくなる。「洗濯物が乾く」
350 かわる 換わる 五段・ラ行 〈「替わる」とも〉(主に液体・気体について)古いものが出て、新しいものが入る。「空気が換わる」
351 かわる 替わる 五段・ラ行 〈「換わる」とも〉とりかわる。交換される。「二人の席が替わる」
338 かれる 枯れる 一段 水分がなくなる。「花が枯れる、芸が枯れる」
339 かれる 涸れる 一段 (川、池などで)水がなくなる。「井戸が涸れる」
340 かわく 渇く 五段・カ行イ音便 (のどに)水分がなくなる。「のどが渇く」
341 かわく 乾く 五段・カ行イ音便 水分がなくなる。「洗濯物が乾く」
342 かわる 換わる 五段・ラ行 他のものといれかわる。「席を換わる」
343 かわる 替わる 五段・ラ行 新しいものといれかわる。「先生が替わる」
352344 かわる 代わる 五段・ラ行 代理をする。「彼に代わって試合に参加する」
353 かわる 変わる 五段・ラ行 1. 異なる状態になる。「信号が変わる」\n2. 〈「変わっている」「変わった」として〉一般的なものから外れている。「性格が変わっている」「変わった人」
345 かわる 変わる 五段・ラ行 異なる状態になる。「信号が変わる、性格が変わっている」
354346 かんき 喚起 * 呼びおこすこと。「潜在的な需要を喚起する」
355347 かんき 換気 * 空気を入れ換えること。「部屋を換気する」
356348 かんき 歓喜 * よろこぶこと。「一挙手一投足に歓喜する」
364356 かんさ 鑑査 * 調べて優劣を決めること。「骨董品を鑑査する」
365357 かんさつ 監察 * 監督し、とりしまること。「行政を監察する」
366358 かんさつ 観察 * ものごとを注意して見ること。「朝顔を観察する」
367 かんしょう 干渉 * 1. 他人のことに口や手を出すこと。「内政干渉」\n2. (お互いに)影響を与えること。「電波が干渉する」
359 かんしょう 干渉 * 他人のことに口や手を出すこと。「内政干渉、電波が干渉する」
368360 かんしょう 観賞 * 見て楽しむこと。「花を観賞する」
369361 かんしょう 鑑賞 * (芸術などを)たのしむこと。「音楽を鑑賞する」
370 かんしん 歓心 * 気に入る気持ち。「彼の歓心を買う」
362 かんしん 歓心 * 嬉しく思う気持。
371363 かんしん 関心 * 興味を持つこと。「彼女に関心を持つ」
372364 かんすい 冠水 * (洪水などで)水びたしになること。「道路が冠水する」
373365 かんすい 完遂 * 完全にやりとげること。「任務を完遂する」
374366 かんすい 灌水 * 水を注ぐこと。「畑に灌水する」
375 かんずる 感ずる サ変・−ズル 〈文語〉感覚をえる。「喜びを感ずる」
376 かんずる 観ずる サ変・−ズル 〈文語〉さとる。観念する。「因縁を観ずる」
377 かんち 感知 * 感づくこと。「危険性を感知する」
367 かんずる 感ずる サ変・−ズル (文語)感覚をえる。「喜びを感ずる」
368 かんずる 観ずる サ変・−ズル (文語)さとる。観念する。「因縁を観ずる」
369 かんち 感知 * 感づくこと。「危険性を関知する」
378370 かんち 関知 * かかわって知ること。「事件には関知していない」
379 きうん 機運 * なにかをするのにちょうどいい時期。「機運が熟するのを待つ」
380 きうん 気運 * 世の中の雰囲気。「政権交代の気運が高まった」
381 ぎえんきん 義援金 * 災害などを受けた人々のために送るお金。\n※「義捐金」の書き換え。
382 ぎえんきん 義捐金 * 災害などを受けた人々のために送るお金。\n※「義援金」と書き換えられることが多い。
383 ききょう 帰京 * 首都に帰ること。「仕事を終えて帰京する」
371 きうん 機運 * なにかをするのにちょうどいい時期。「機運が高まってきた」
372 きうん 気運 * 世の中のなりゆき。
373 ききょう 帰京 * みやこに帰ること。「仕事を終えて帰京する」
384374 ききょう 帰郷 * 故郷に帰ること。「正月に帰郷した」
385375 きく 効く 五段・カ行イ音便 ききめがある。「麻酔が効く」
386 きく 訊く 五段・カ行イ音便 人にものをたずねる。「道を訊く」→聞く2
387 きく 聴く 五段・カ行イ音便 注意深く聞く。「講演を聴く」「音楽を聴く」→聞く1
388 きく 聞く 五段・カ行イ音便 1. 音を耳で感じる。「話を聞く」「講演を聞く」「音楽を聞く」\n2. 〈「訊く」とも〉人にものをたずねる。「道を聞く」\n3. 味やにおいを判断する。「香を聞く」
389 きく 利く 五段・カ行イ音便 1. じゅうぶんな働きをする。「気が利く」\n2. 〈「口を利く」の形で〉しゃべる。
376 きく 訊く 五段・カ行イ音便 たずねる。「道を訊く」(聞くとも書く)
377 きく 聴く 五段・カ行イ音便 注意深く聞く。「講演を聴く、音楽を聴く」
378 きく 聞く 五段・カ行イ音便 (一般的)音を耳で感じる。「話を聞く、道を聞く、香を聞く」
379 きく 利く 五段・カ行イ音便 じゅうぶんな働らきをする。「気が利く、口を利く」
390380 きぐ 器具 * 道具。「電気器具」
391381 きぐ 機具 * 機械と器具。
392382 きざす 兆す 五段・サ行 ものごとが起ころうとする。「復調が兆す」
393 きざす 萌す 五段・サ行 〈文語〉(芽が)出始める。「木の芽が萌す」
383 きざす 萌す 五段・サ行 芽が出始める。「木の芽が萌す」
394384 ぎし 技師 * 技術者。
395385 ぎし 義肢 * 義手や義足など。
396386 きじく 基軸 * ものごとの基本となるもの。「基軸通貨」
397 きじく 機軸 * 1. 機械の中心となる軸。\n2. 大きな構想。「新しい機軸を打ち出す」
387 きじく 機軸 * 活動の中心。「新しい基軸をだす」
398388 きしつ 基質 * 基盤となる物質。
399389 きしつ 気質 * 生まれつきの性質。「職人気質」
400 ぎしょう 偽称 * 名称を偽ること。
401 ぎしょう 偽証 * いつわりの証言をすること。「裁判で偽証する」
390 ぎしょう 偽称 * 名称を偽る。
391 ぎしょう 偽証 * いつわって証明する。「証拠を偽称する」
402392 きせい 規制 * きまりを決めて制限すること。「交通規制」
403393 きせい 規正 * 悪いことを正しくなおすこと。
404394 きせい 既成 * すでに出来あがっていること。「既成概念」
406396 ぎそう 偽装 * 細工をして欺くこと。「偽装結婚」
407397 ぎそう 擬装 * 外見を変えてごまかすこと。
408398 ぎそう 艤装 * 船に装備を施すこと。
409 きぬ 衣 * 〈文語〉きもの。「歯に衣着せぬ」(ずけずけとものを言う)
410 きぬ 絹 * 蚕の糸からつくった布。
399 きぬ 衣 * きもの。「歯に衣着せぬ」
400 きぬ 絹 * 絹の糸。
411401 きばん 基板 * 集積回路を配線するシリコンの板。
412402 きばん 基盤 * 物事の土台。「情報基盤」
413 きゅう 窮する サ変・-スル 行き詰る。「答えに窮する」
414 きゅう 給する サ変・-スル 〈文語〉あたえる。
403 きゅう 窮 * 行き詰る。「答えに窮する」
404 きゅう 給 * (文語)あたえる。
415405 きゅうはく 急迫 * さしせまること。
416406 きゅうはく 窮迫 * 行き詰まって、どうにもならないこと。
417407 きゅうめい 救命 * 人命を救うこと。「救命胴衣」
418408 きゅうめい 究明 * 真理を追及し、あきらかにすること。「真理を究明する」
419409 きゅうめい 糾明 * 悪いことを問い正して、あきらかにすること。「悪事を糾明する」
420 きょうする 供する サ変・-スル 1. 〈文語〉(飲食物を)与える。提供する。「酒食を供する」\n2. 〈「〜に供する」として〉その目的のために提供する。「公共の利用に供する」
421 きょうする 狂する サ変・-スル 〈文語〉くるう。
422 きょうする 饗する サ変・-スル 〈文語〉ふるまう。
410 きょう 供 * (文語)そなえる。
411 きょう 狂 * (文語)くるう。
412 きょう 饗 * (文語)ふるまう。
423413 きょうえん 競演 * 演技を競うこと。
424414 きょうえん 共演 * 主役が2人出演すること。「二人のスターが共演する」
425 きょうじょう 教場 * 〈文語〉授業をする場所。
426 きょうじょう 教条 * 教義。「教条主義に陥る」
427 きょうせい 共棲 * →共生
428 きょうせい 共生 * 1. 共にくらすこと。\n2. 異種の生物が、お互いに利益を与えて生活すること。
415 きょうじょう 教場 * 授業をする場所。
416 きょうじょう 教条 * 教義を箇条書きにしたもの。
417 きょうせい 共棲 * (「共生」と区別なし)同じところでくらすこと。
418 きょうせい 共生 * (「共棲」と区別なし)同じところでくらすこと。
429419 きょうせい 強制 * むりやりさせること。「強制収容」
430 きょうせい 強請 * 〈文語〉〈「ごうせい」とも読む〉無理に頼むこと。
420 きょうせい 強請 * むりに頼むこと。ごうせい。
431421 きょうどう 共同 * 複数の人でなにかをすること。「共同研究」
432422 きょうどう 協同 * 助けあってなにかをすること。「協同組合」
433 きょうはく 強迫 * 1. むりに要求すること。\n2. 強く定着し、逃れられないこと。「強迫観念」\n3. 〈民法〉「脅迫」の意で使う。
423 きょうはく 強迫 * 相手にむりやりになにかをさせること。「強迫観念」
434424 きょうはく 脅迫 * 相手を脅して、むりやりになにかをさせること。「脅迫罪」
435425 きょうぼう 凶暴 * 凶悪で乱暴なようす。
436426 きょうぼう 狂暴 * くるったように暴れるようす。
437427 きょうわ 共和 * 複数の人が政務などをすること。「共和国」
438 きょうわ 協和 * 1. こころを合わせて仲よくすること。\n2. (音が)うまく合っていること。「協和音」
439 きる 斬る 五段・ラ行 (人などに対して)刃物などで傷つける、または殺す。「人に斬りつける」
440 きる 切る 五段・ラ行 1. くっついているもの、またはひとつのものをはなればなれにする。「ひもを手で切る」「爪を切る」「木を切る」\n2. 鋭いものできずつける。「紙の端で手を切ってしまった」\n3. 機械の動作を止める。「テレビの電源を切る」\n4. 操作して方向をかえる。「ハンドルを切る」
441 きる 伐る 五段・ラ行 (木に対して)刃物などで断つ。「木を伐る」→切る1
442 きわめる 究める 一段 ものごとを追究する。「学問を究める」
443 きわめる 極める 一段 1. 物事をつきつめ、そのすべてを習得する。「剣術を極める」\n2. (困難な場所に)到達する。「山頂を極める」\n3. 程度が極限に達する。「栄華を極める」
444 ぐうする 寓する サ変・-スル 〈文語〉ことよせる。
445 ぐうする 遇する サ変・-スル 〈文語〉もてなす。「自宅で遇する」
428 きょうわ 協和 * こころを合わせて仲よくすること。「協和音」
429 きる 斬る 五段・ラ行 (人などに対して)刃物などで傷つける。「人を斬りつける」
430 きる 切る 五段・ラ行 くっついているものをはなればなれにする。「爪を切る、電話を切る、洗顔料を使い切る、伝票を切る、ハンドルを切る」
431 きる 伐る 五段・ラ行 (木に対して、「切る」とも書く)刃物などで断つ。「木を伐る」
432 きわめる 究める 一段 真理を追究する。「学問を究める」
433 きわめる 極める 一段 物事をつきつめる。「山頂を極める」
434 ぐう 寓 * (文語)ことよせる。
435 ぐう 遇 * (文語)もてなす。「自宅で遇する」
446436 くず 葛 * マメ科の多年草。「葛切り」
447 くず 屑 * ごみ。「紙屑」
448 くだる 下る 五段・ラ行 1. 高いところから低いところに、または中心とされる場所から周辺に移る。「山を下る」「川を下る」\n2. 言い渡される。「判決が下る」\n3. 下痢をする。「腹が下る」
449 くだる 降る 五段・ラ行 降服して所属するようになる。「敵の軍門に降る」
450 くみあげる 汲み上げる 一段 水をくみ、高い場所に上げる。「井戸水を汲み上げる」
451 くみあげる 組み上げる 一段 組み終える。「計画を組み上げる」「足場を組み上げる」
452 くむ 汲む 五段・マ行 1. 水などをすくう。「井戸水を汲む」\n2. おしはかる。「意図を汲む」
453 くむ 酌む 五段・マ行 1. 酒などをつぐ。「酒を酌む」\n2. 考慮する。斟酌(しんしゃく)する。「酌むべき事情がある」
454 くむ 組む 五段・マ行 1. 互い違いに合わせる。また、そうしてものを作る。「腕を組む」「やぐらを組む」\n2. (複数人が、目的のある集団を)集まって構成する。「チームを組む」\n3. 複雑なものをつくりあげる。「プログラムを組む」\n4. 長期間の契約を結ぶ。「ローンを組む」
455 ぐんしゅう 群衆 * 〈「群集」とも〉大勢集まった人々。
456 ぐんしゅう 群集 * 人、動物などの集まり。「群集心理」
457 くんずる 薫ずる サ変・−ズル 〈文語〉かおる、またはにおいを起こす。
458 くんずる 訓ずる サ変・−ズル 〈文語〉訓読する。
459 けいする 慶する サ変・−スル 〈文語〉いわう。
460 けいする 敬する サ変・−スル 〈文語〉うやまう。
461 けいじょう 啓上 * 〈文語〉〈「一筆啓上」として〉書いて申し上げること。
437 くず 屑 * ゴミ。「紙屑」
438 くだる 下る 五段・ラ行 高いとことから低いところに移る。「山を下る、川を下る、判決が下る、腹が下る」
439 くだる 降る 五段・ラ行 おりる。「山を降る、敵の軍門に降る」
440 くみあげる 汲み上げる 一段 水を汲み、高い場所に上げる。「井戸水を汲み上げる」
441 くみあげる 組み上げる 一段 組み終える。「計画を組み上げる、足場を組み上げる」
442 くむ 汲む 五段・マ行 水などをすくう。「井戸水を汲む、意図を汲む」
443 くむ 酌む 五段・マ行 酒などをつぐ。「酒を酌む」
444 くむ 組む 五段・マ行 組になる。「チームを組む、腕を組む、やぐらを組む」
445 ぐんしゅう 群衆 * 大勢の人。
446 ぐんしゅう 群集 * 人、虫などの集まり。「群集心理」
447 くんずる 薫ずる サ変・−ズル かおる。
448 くんずる 訓ずる サ変・−ズル 訓読する。
449 けい 慶 * いわう。
450 けい 敬 * うやまう。
451 けいじょう 啓上 * 申し上げること。
462452 けいじょう 計上 * 計算に加えること。「予算に計上する」
463 けいすう 係数 * 数式において、変数にかかっている数。
453 けいすう 係数 * 数式において変数にかかっている数。
464454 けいすう 計数 * 数を数えること。
465 けっさい 決済 * 支払いを行うこと。「月末に決済する」
455 けっさい 決済 * 支払を行うこと。「月末に決済する」
466456 けっさい 決裁 * 上の立場の人が決定を下すこと。「決裁をあおぐ」
467 げっぽう 月俸 * ひと月の給料。
468 げっぽう 月報 * 月ごとの報告。
469 けんする 検する サ変・−スル とりしらべる。
470 けんする 験する サ変・−スル ためす。
457 げっぽう 月俸 * 月毎の給料。
458 げっぽう 月報 * 月毎の報告。
459 けん 検 * とりしらべる。
460 けん 験 * ためす。
471461 けんあん 懸案 * 問題になっているが、解決されていない問題。「懸案事項」
472462 けんあん 検案 * 形状などを調べること。
473 げんけい 原型 * 1. 基準とする型、また進化する以前の型。「長安を原型として都を建造する」「ウマの原型となる動物」\n2. それを土台に複製を作るような、基本となる型。
474 げんけい 原形 * 変化する前の形。「ゆがんだハンガーを原形に戻す」
475 げんし 原始 * 発展のはじめの段階にあること。「原始宇宙」「原始仏教」
476 げんし 原子 * 単独の化学元素。「原子物理」「原子爆弾」
463 げんけい 原型 * もととなる型。「日本列島の原型」
464 げんけい 原形 * もとのかたち。「原形質」
465 げんし 原始 * はじめ。「原始人」
466 げんし 原子 * 物質の要素。「原子物理、原子爆弾」
477467 げんずる 減ずる サ変・−ズル 減る。
478 げんずる 現ずる サ変・−ズル 〈文語〉あらわれる。
468 げんずる 現ずる サ変・−ズル あらわれる。
479469 けんめい 懸命 * いのちがけ。「懸命に挑戦する」
480470 けんめい 賢明 * 賢く、道理にあっていること。「賢明な対処」
481471 ごい 語意 * ことばの意味。
482472 ごい 語彙 * 語のあつまり。ボキャブラリ。
483 こうする 抗する サ変・−スル 〈文語〉抵抗する。「時代に抗する」
484 こうする 航する サ変・−スル 〈文語〉航海する。「東海岸を航する」
485 こう 乞う 五段・ワ行ウ音便 〈「請う」に同じ〉ねがう、またはものを求める。「許しを乞う」「援助を乞う」
486 こう 請う 五段・ワ行ウ音便 〈「乞う」に同じ〉ねがう、またはものを求める。「許しを請う」「援助を請う」
487 こう 恋う 五段・ワ行ウ音便 なつかしく思う。「故郷を恋う」
473 こう 抗 * (文語)抵抗する。「時代に抗する」
474 こう 航 * (文語)航海する。「東海岸を航する」
475 こう 乞う 五段・ワ行ウ音便 (「請う」と区別なし)ものを求める。「許しを乞う」
476 こう 請う 五段・ワ行促音便 (「乞う」と区別なし)ものを求める。「許しを請う」
477 こう 恋う 五段・ワ行ウ音便 いとしく思う。「故郷を恋う」
488478 こうい 厚意 * 親切な気持。「ご厚意に甘えさせていただきます」
489 こうい 好意 * 好きだという気持。「好意を抱く」「好意を寄せる」
479 こうい 好意 * いいと思う気持。親切な気持。「好意を抱く」
490480 こうえき 公益 * 公共の利益。「公益事業」
491481 こうえき 公役 * 公共団体から任せられた役割。
492 こうかん 交感 * 心や感情が通い合うこと。
493 こうかん 交換 * とりかえること。「交換日記」「ユニフォームを交換する」
494 こうかん 交歓 * 交流して親睦を深めること。「交歓会」
482 こうかん 交感 * 心や感情が通い合うこと。「交感神経」
483 こうかん 交換 * とりかえること。「交換日記、ユニフォームを交換する」
484 こうかん 交歓 * よろこびを分かちあうこと。「交歓会」
495485 こうこう 後攻 * 野球などで、後から攻めること。
496486 こうこう 孝行 * 親に対して行なうよい行い。「親孝行」
497 こうこう 航行 * 船や飛行機で水上や空中を移動すること。「インド洋を航行する」
498 こうこく 公告 * 公共機関が公に知らせること。「政策を公告する」
499 こうこく 広告 * 商業的な目的で広く知らせること。また、それに使われるもの。「新商品の広告を行う」「広告が掲載されている」
487 こうこう 航行 * 船で水上を移動すること。「インド洋を航行する」
488 こうこく 公告 * 公に知らせること。「政策を公告する」
489 こうこく 広告 * 広く世間に知らせること。「新商品を広告する」
500490 こうしゃく 侯爵 * 華族の階級の第二番目。
501491 こうしゃく 公爵 * 華族の階級の第一番目。
502 こうずる 昂ずる サ変・−ズル →高ずる
503 こうずる 嵩ずる サ変・−ズル →高ずる
504 こうずる 講ずる サ変・−ズル 1. (手段・対策などを)実行する。「必要な措置を講ずる」\n2. 〈文語〉講義をする。「数学を講ずる」\n3. 〈「和を講ずる」として〉講和する。
505 こうずる 高ずる サ変・−ズル 〈「昂ずる」「嵩ずる」とも〉たかまる。「病気が高ずる」「趣味が高じて本まで書くようになった」
506 こうせい 更正 * あやまりを正すこと。また、倫理的によい方向に進むこと。「非行少年を更正させる」
507 こうせい 更生 * 立ち直ること。「自力更生」「会社更生法」
492 こうずる 昂ずる サ変・−ズル (「高ずる」と区別なし)たかまる。「病気が昂ずる」
493 こうずる 講ずる サ変・−ズル 講義をする。「数学を講ずる、手段を講ずる」
494 こうずる 高ずる サ変・−ズル (「昂ずる」と区別なし)たかまる。「病気が高ずる」
495 こうせい 更正 * あやまりを正すこと。
496 こうせい 更生 * 生きかえること。「会社更生法」
508497 こうそ 公訴 * 刑事に関する訴訟。
509 こうそ 控訴 * 判決を不服として、上級裁判所に再審を求めること。
498 こうそ 控訴 * 判決を不服として上級裁判所に再審を求めること。
510499 こうちゃく 降着 * 競馬で進路を妨害した馬の順位を下げること。
511 こうちゃく 膠着 * 事態が固定して、変化が起きなくなること。「事件が膠着状態になる」
512 こえる 越える 一段 1. 上を通りすぎる。「山を越える」「橋を越える」\n2. きびしい状況をしのぐ。「冬を越える」\n3. 〈「超える」とも〉うわまわる。「限界を越える」「容量が500MBを越える」
513 こえる 超える 一段 〈「越える」とも〉うわまわる。超過する。「限界を超える」「容量が500MBを超える」
514 こえる 肥える 一段 1. 太る。\n2. (土壌が)ゆたかである。「土地が肥えている」\n3. 鑑識眼がある。「目が肥えている」
515 こおる 凍る 五段・ラ行 水などが冷えて固まる。「湖が凍る」
516 こおる 氷る 五段・ラ行 →凍る
500 こうちゃく 膠着 * 変化が起きないこと。「事件が膠着状態になる」
501 こえる 越える 一段 上を過ぎる。「山を越える、冬を越える」
502 こえる 超える 一段 (「越える」も使う)うわまわる。「限界を超える、容量が500MBを超える」
503 こえる 肥える 一段 ふとる。「目が肥えている、土地が肥えている」
504 こおる 凍る 五段・ラ行 (一般的)水などが冷えて固まる。「湖が凍る」
505 こおる 氷る 五段・ラ行 水などが冷えて固まる。「湖が氷る」
517506 ごかん 語幹 * 動詞・形容詞・形容動詞において変化しない部分。「『こわい』の語幹は『こわ』である」
518 ごかん 語感 * 言葉のあたえる感覚。「語感がよくないので別の言い方を考える」
507 ごかん 語感 * 言葉のあたえる感覚。
519508 ごこうい ご厚意 * 親切な気持。「ご厚意に甘えさせていただきます」
520 ごこうい ご好意 * 好きだという気持。
509 ごこうい ご好意 * いいと思う気持。親切な気持。
521510 ごこうい 御厚意 * 親切な気持。「御厚意に甘えさせていただきます」
522 ごこうい 御好意 * 好きだという気持。
511 ごこうい 御好意 * いいと思う気持。親切な気持。
523512 こじ 固持 * かたく持ちつづけて変えないこと。
524513 こじ 固辞 * かたく辞退すること。「役職を固辞する」
525514 こじ 誇示 * 自慢して示すこと。「力を誇示する」
526515 こじ 古寺 * ふるい寺。
527516 こじ 孤児 * 両親のいない子供。
528 こじ 故事 * 昔あったことがら。
517 こじ 故事 * 昔あった事柄。
529518 ごしん 誤信 * あやまって信じること。
530519 ごしん 誤診 * あやまって診断すること。
531 こす 越す 五段・サ行 1. 通りすぎる。「山を越す」\n2. きびしい状況をしのぐ。「冬を越す」\n3. 住居を移る。引っ越す。「隣町へ越す」\n4. 〈「お越し」の形で〉「来る」の尊敬語。「お客様がお越しです」\n5. 〈「超す」とも〉うわまわる。「3万人を越す」
532 こす 漉す 五段・サ行 →濾す
533 こす 超す 五段・サ行 〈「越す」とも〉うわまわる。「3万人を超す」
534 こす 濾す 五段・サ行 〈「漉す」とも〉目の細かいものなどを通して不純物を取り除く。濾過(ろか)する。「水を濾す」
535 ごぜん 午前 * 24時間制でいうところの0時から12時まで。一日の前半。
520 こす 越す 五段・サ行 通りすぎる。「山を越す、隣町へ越す、冬を越す、お客様がお越しです」
521 こす 漉す 五段・サ行 (「濾す」とも書く)濾過する。「水を漉す」
522 こす 超す 五段・サ行 (「越す」とも書く)ある値よりも上になる。「3万人を超す」
523 こす 濾す 五段・サ行 (「漉す」とも書く)濾過する。「水を濾す」
524 ごぜん 午前 * 0時から12時まで。
536525 ごぜん 御前 * 地位の高い人の前。
537 こちょう 胡蝶 * 昆虫のチョウのこと。
526 こちょう 胡蝶 * (「蝴蝶」と区別なし)蝶のこと。
538527 こちょう 誇張 * おおげさに言うこと。「誇張表現」
539 こちょう 蝴蝶 * →胡蝶
540 こて 小手 * 〈「籠手」とも〉\n1. 剣道で、指先からひじまでを覆う防具。\n2. よろいの中で、肩から腕までを覆う防具。
541 こて 籠手 * 〈「小手」とも〉\n1. よろいの中で、肩から腕までを覆う防具。\n2. 剣道で、指先からひじまでを覆う防具。
542 こて 鏝 * 〈普通かな書き〉漆喰などを塗る道具。
543 こべつ 個別 * ひとつずつ。ひとりずつ。「個別指導」
544 こべつ 戸別 * いえごと。「戸別訪問」
545 こむ 込む 五段・マ行 1. 〈「混む」が一般的〉混雑する。「遊園地が込んでいる」\n2. 巧妙である。「手の込んだ細工」\n3. 〈主に複合語で〉中に入る、または入れる。「入り込む」「中に飛び込む」\n4. とことん行う。「鍛え込む」「教え込む」
546 こむ 混む 五段・マ行 混雑する。「遊園地が混んでいる」
528 こちょう 蝴蝶 * (「胡蝶」と区別なし)蝶のこと。
529 こて 小手 * 肘と手首との間。
530 こて 籠手 * (「小手」とも書く)手から肩を覆う防具。
531 こて 鏝 * 漆喰などを塗る道具。
532 こべつ 個別 * ひとつずつ。「個別指導」
533 こべつ 戸別 * いえごと。
534 こむ 込む 五段・マ行 混雑する。中にはいる。「遊園地が込む、手が込む、入り込む、鍛え込む」
535 こむ 混む 五段・マ行 混雑する。「遊園地が混む」
547536 ごよう 御用 * 用事があること。「御用始め」
548537 ごよう 誤用 * 誤って用いること。「薬を誤用している」
549 こらす 凝らす 五段・サ行 〈かな書きも〉\n1. (意識などを)一つのところに集中させる。「目を凝らす」「視線を凝らす」\n2. 〈「息を凝らす」として〉呼吸を抑える。\n3. (工夫、技巧などを)時間をかけてほどこす。「工夫を凝らした授業」「趣向を凝らした衣装」
550 こらす 懲らす 五段・サ行 〈文語〉こらしめる。「いたずらを懲らす」
538 こらす 凝らす 五段・サ行 一つのところに集中させる。「工夫を凝らす、目を凝らす」
539 こらす 懲らす 五段・サ行 こらしめる。「いたずらを懲らす」
551540 さいかい 再会 * 再び会うこと。「旧友と再会する」
552541 さいかい 再開 * 再び始める。「会議を再開する」
553 さいき 再帰 * 関数などが自分自身を呼び出すこと。「再帰的関数」
554 さいき 再起 * たちなおる。「重症から再起する」「再起不能」
542 さいき 再帰 * 関数などで自分自身を呼び出すこと。「再帰的関数」
543 さいき 再起 * たちなおる。「重症から再起する、再起不能」
555544 さいけつ 採決 * 議案を多数決で決めること。「採決をとる」
556 さいけつ 採血 * 血液を採取すること。「検査のために採血した」
557 さいけつ 裁決 * さばきを行うこと。「裁決を下す」
545 さいけつ 採血 * 血液を採取する。「検査のために採血した」
546 さいけつ 裁決 * さばきを行う。「採決を下す」
558547 さいけん 債券 * 公共機関が発行する有価証券。「債券を発行する」
559548 さいけん 債権 * 金品の返還要求を行う権利。「債権者」
560 さいご 最期 * 〈「最後」とも〉死にぎわ。「祖父の最期に立ち会う」
561 さいご 最後 * 1. いちばんうしろ。\n2. 〈「最期」とも〉死に際。「祖父の最後に立ち会う」
549 さいご 最期 * 死にぎわ。
550 さいご 最後 * いちばんうしろ。
562551 さいしょう 最小 * いちばん小さいこと。
563552 さいしょう 最少 * いちばん少ないこと。
564553 さいしょく 彩色 * 着色。「彩色を施す」
565554 さいしょく 才色 * (女性の)才能と美貌。「才色兼備」
566 さいせい 再生 * 1. 廃物を利用して再び使えるようにすること。リサイクル。「再生紙」\n2. 再び生えてくること。\n3. 機械に記録したものを読み出し、音声や映像を復元すること。「音楽を再生する」
567 さいせい 再製 * 1. 既存のものに再び加工してつくること。「再製茶」\n2. 作り直すこと。「戸籍を再製する」
555 さいせい 再生 * 生きかえること、リサイクル。「再生紙」
556 さいせい 再製 * 製品を作りなおすこと。「再製生糸」
568557 さいせき 採石 * 石を採取すること。「採石場」
569 さいせき 砕石 * 石を砕くこと。「砕石して砂利にする」
558 さいせき 砕石 * 石を砕くこと。「砕石してジャリにする」
570559 さいろく 採録 * 記録すること。「民話を採録する」
571560 さいろく 載録 * 印刷物に載せること。「論文が載録された」
572 さがす 捜す 五段・サ行 見失ったものや人を見つけようとする。「迷子を捜す」「なくした眼鏡を捜す」※この意味でも「探す」が多く使われる。
573 さがす 探す 五段・サ行 目当てのものを見つけようとする。「自分に似合う眼鏡を探す」「他人のあらを探す」
561 さがす 捜す 五段・サ行 なくなったもの見つけようとする。「迷子を捜す」
562 さがす 探す 五段・サ行 欲しいものを見つけようとする。「眼鏡を探す、あらを探す」
574563 さかな 魚 * 魚類。
575 さかな 肴 * 〈かな書きも〉酒のつまみ。
564 さかな 肴 * 酒のつまみ。
576565 さかん 佐官 * 僧侶の役職の一つ。
577566 さかん 左官 * 壁を塗る職人。
578 さく 割く 五段・カ行イ音便 1. 切ってひらく。「魚の腹を割く」\n2. 一部を他にまわす。「時間を割く」
579 さく 咲く 五段・カ行イ音便 花のつぼみが開く。「桜が咲く」
580 さく 裂く 五段・カ行イ音便 1. (手などで)ふたつに切りはなす。「紙を裂く」\n2. 人々を離ればなれにする。「彼女との仲を裂く」
581 さくせい 作成 * (特に書類などの)ものを作ること。「契約書を作成する」
582 さくせい 作製 * 〈「作成」とも〉ものを作ること。
583 さげる 下げる 一段 1. 低くする。「水量を下げる」「値段を下げる」\n2. つるす。「ペンダントを下げる」\n3. 〈「提げる」とも〉手で取っ手を持つ。「カバンを手に下げる」\n4. 回収する。「椅子を下げる」
584 さげる 提げる 一段 手に持ってぶらさげる。「カバンを手に提げる」→下げる3
567 さく 割く 五段・カ行イ音便 一部を他にまわす。「時間を割く、魚の腹を割く」
568 さく 咲く 五段・カ行イ音便 花のつぼみが開く。「さくらが咲く」
569 さく 裂く 五段・カ行イ音便 強引に2つに切りはなす。「紙を裂く、彼女との仲を裂く」
570 さくせい 作成 * 書類などを作ること。「契約書を作成する」
571 さくせい 作製 * ものを作ること。
572 さげる 下げる 一段 下へ移動させる。「水量を下げる、値段を下げる、椅子を下げる」
573 さげる 提げる 一段 手に持ってぶらさげる。「カバンを手に提げる」
585574 さじ 些事 * ささいなこと。
586 さじ 匙 * 液体などをすくうもの。スプーン。「匙を投げる」(あきらめる)
587 さす 差す 五段・サ行 1. 状態が生じる。「いやけが差す」\n2. 光などがかかる。「日が差す」\n3. (傘を)手で支えて体の上にかぶせる。「日傘を差す」\n4. 〈「挿す」とも〉(刀などを)帯に通して持ち運ぶ。
588 さす 鎖す 五段・サ行 〈文語〉錠をおろす。とざす。「戸を鎖す」
589 さす 刺す 五段・サ行 つきとおす。「釘を刺す」「人を刺す」
590 さす 指す 五段・サ行 1. 指を向ける。指し示す。「ある方向を指す」\n2. 言及する。「これは彼のことを指している」\n3. (将棋を)する。「将棋を指す」
591 さす 挿す 五段・サ行 1. 細長いものにつきとおす。「花瓶に花を挿す」\n2. 〈「差す」とも〉(刀などを)帯に通して持ち運ぶ。
592 さばく 裁く 五段・カ行イ音便 善し悪しの判断を下す。「けんかを裁く」
593 さばく 捌く 五段・カ行イ音便 〈かな書きも〉\n1. 効率よく対処する。「大量の仕事を捌く」\n2. (動物、特に魚を)解体する。「魚を捌く」\n3. 売って少なくする。「在庫を捌く」
594 さます 覚ます 五段・サ行 〈「醒ます」とも〉\n1. (眠りなどから)頭が働く状態になる。「目を覚ます」\n2. 酒などの影響がなくなるようにする。「酔いを覚ます」
575 さじ 匙 * 液体などをすくうもの。スプーン。「匙を投げる」
576 さす 差す 五段・サ行 状態が生じる。「いやけが差す、日が差す、かさを差す」
577 さす 鎖す 五段・サ行 とざす。「戸を鎖す」
578 さす 刺す 五段・サ行 つきとおす。「釘を刺す、人を刺す」
579 さす 指す 五段・サ行 ゆびを向ける、示す。「ある方向を指す、これは彼のことを指している、将棋を指す」
580 さす 挿す 五段・サ行 ものをはさむ。「刀を挿す、花を挿す」
581 さばく 裁く 五段・カ行イ音便 善し悪しをはっきりさせる。「けんかを裁く」
582 さばく 捌く 五段・カ行イ音便 上手に対処する。「大量の仕事を捌く、魚を捌く、在庫を捌く」
583 さます 覚ます 五段・サ行 (眠りなどから)頭が働く状態になる。「目を覚ます」
595584 さます 冷ます 五段・サ行 ものを冷たくする。「お湯を冷ます」
596 さます 醒ます 五段・サ行 →覚ます
597 さめる 覚める 一段 1. (眠りなどから)頭が働く状態になる。「目が覚める」\n2. 酒などの影響がなくなる。「酔いが覚める」
598 さめる 醒める 一段 →覚める
599 さめる 冷める 一段 1. 冷たくなる。「お湯が冷める」\n2. (関係が)冷淡になる。「彼女との関係が冷める」\n3. 〈口語〉情熱や恋が失われる。「横柄な態度を見て一気に冷めた」
585 さめる 覚める 一段 (眠りなどから)頭が働く状態になる。「目が覚める」
586 さめる 醒める 一段 酔いがなくなる。「酔いが醒める」
587 さめる 冷める 一段 冷たくなる。「お湯が冷める、彼女との関係が冷める」
600588 さわら 椹 * ヒノキ科の高木。
601589 さわら 鰆 * サバ科の魚。
602 さわる 障る 五段・ラ行 1. 差し支える。悪い影響を及ぼす。「仕事に障る」「体に障る」\n2. 嫌な感情を引き起こす。「気に障る」
603 さわる 触る 五段・ラ行 1. 手でふれる。「物に触る」\n2. 関係する。「その仕事には触っていない」
604 さんする 参する サ変・−スル 〈文語〉たずさわる。「ボランティアに参する」
605 さんする 産する サ変・−スル 1. 〈文語〉産む。「メスだけを産するハチ」\n2. (ものを)生産する。また、生産される。「天然に産する鉱物」
606 さんする 算する サ変・−スル 〈文語〉計算する。「期待値を算する」
607 さんか 傘下 * 支配下。「傘下の企業」
590 さわる 障る 五段・ラ行 障害になる。「気に障る」
591 さわる 触る 五段・ラ行 手でふれる。「物に触る、その仕事には触っていない」
592 さん 参 * (文語)たずさわる。「ボランティアに参する」
593 さん 産 * (文語)産む。「メスだけを産する蜂、天然に産する鉱物」
594 さん 算 * (文語)計算する。「期待値を算する」
595 さんか 傘下 * 支配下。「惨禍の企業」
608596 さんか 惨禍 * 悲惨な災い。「戦争の惨禍」
609 さんか 讃歌 * →賛歌
610 さんか 賛歌 * 〈「讃歌」とも〉ものごとを称賛する歌。
597 さんか 讃歌 * (「賛歌」と区別なし)ものごとを称賛する歌。
598 さんか 賛歌 * (「讃歌」と区別なし)ものごとを称賛する歌。
611599 さんかい 参会 * 会合に参加する。
612600 さんかい 散会 * 会合を終える。
613601 さんざい 散在 * ちらばって存在すること。「支局が散在する」
614 さんざい 散財 * 使うことによって財を失なうこと。「博打で散財した」
602 さんざい 散財 * 財を失なうこと。「博打で散財した」
615603 さんしゅつ 産出 * 産物を産み出すこと。「石油を産出する」
616604 さんしゅつ 算出 * 計算して数字を出すこと。「来場者を算出する」
617 さんずる 参ずる サ変・−ズル 〈文語〉参上する。「明日に参ずる」
618 さんずる 散ずる サ変・−ズル 〈文語〉\n1. (金を)使う。「財を散ずる」\n2. (人が)散らばる。(宴などから)帰る。「客が散ずる」\n3. (気が)散る。(気を)散らす。(気を)晴らす。
605 さんずる 参ずる サ変・−ズル (文語)参上する。「明日に参ずる」
606 さんずる 散ずる サ変・−ズル (文語)なくなる。「財を散ずる」
619607 さんせい 産生 * 生産すること。「自動車を産生する」
620608 さんせい 賛成 * 意見に同意すること。「彼の意見に賛成する」
621609 さんにゅう 参入 * 加わること。「その市場に参入する」
622610 さんにゅう 算入 * 計算に入れること。「診療報酬を収入に算入する」
623 しする 資する サ変・−スル 役立てる。「学問の進歩に資する」
624 しい 四囲 * 〈文語〉まわり。
625 しい 私意 * 〈文語〉自分の考え。
611 し 資 * (文語)役立てる。「学問の進歩に資する」
612 しい 四囲 * まわり。
613 しい 私意 * 自分の考え。
626614 しい 椎 * ブナ科の木。
627 しい 恣意 * 1. 個人の気まぐれ。「恣意的に処罰する」\n2. 意図が入らないこと。何でもよいこと。「記号の恣意性」
628 しく 敷く 五段・カ行イ音便 ものがのるように広げる。「ござを敷く」「布団を敷く」
629 じこう 時候 * 四季それぞれの気候。「時候の挨拶」
630 じこう 時効 * 一定期間後に効力がなくなること。「あの事件はもう時効だ」
615 しい 恣意 * 自分勝手な考え。
616 しく 敷く 五段・カ行イ音便 ものがのるように広げる。「ゴザを敷く、布団を敷く」
617 じこう 時候 * 四季それぞれの気候。
618 じこう 時効 * 一定期間後に、権利を失なったり得たりすること。「あの事件はもう時効だ」
631619 ししん 私信 * 個人的な手紙。
632620 ししん 私心 * 自分の考え。
633 しずまる 静まる 五段・ラ行 1. 静かになる。「場内が静まる」\n2. 〈「鎮まる」とも〉勢いが弱くなる。「傷口の傷みが静まる」「暴動が静まる」
634 しずまる 鎮まる 五段・ラ行 〈「静まる」とも〉勢いが弱くなる、または完全におさまる。「傷口の傷みが鎮まる」「暴動が鎮まる」
635 しずめる 静める 一段 1. 静かにする。「場内を静める」\n2. 〈「鎮める」とも〉勢いを弱くする、または完全になくす。「傷みを静める」「暴動を静める」
636 しずめる 沈める 一段 沈むようにする。「船を沈める」「ソファーに体を沈める」
637 しずめる 鎮める 一段 〈「静める」とも〉勢いを弱くする、または完全になくす。「傷みを鎮める」「暴動を鎮める」
638 じす 辞す 五段・サ行 1. やめる。「職を辞す」\n2. 〈「〜を辞さない」として〉〜することをためらわない。「法的措置も辞さない」
639 じする 侍する サ変・−スル 〈文語〉そばにつかえる。「酒席に侍する」
640 じする 持する サ変・−スル 〈文語〉持つ。たもつ。「名声を持する」
621 しずまる 静まる 五段・ラ行 (音や動きが)落ち着く。「場内が静まる」
622 しずまる 鎮まる 五段・ラ行 (騒ぎや傷みが)おさまる。「傷口の傷みが鎮まる、暴動が鎮まる」
623 しずめる 静める 一段 静かにする。「」
624 しずめる 沈める 一段 しずむようにする。「船を沈める、ソファーに体を沈める」
625 しずめる 鎮める 一段 騒ぎを落ち着かせる。「暴動を鎮める」
626 じする 侍する サ変・−スル つかえる。「酒席に侍する」
627 じする 持する サ変・−スル たもつ。「名声を持する」
641628 じする 辞する サ変・−スル やめる。「職を辞する」
642 じせい 時世 * 現在の世の中。「このご時世では就職も楽ではない」
643 じせい 時制 * 言語において、語形変化などで現在・過去・未来などの時間をあらわすこと。
644 じせい 時勢 * 時代の勢い。「時勢を読む」
629 じせい 時世 * 世の中。
630 じせい 時制 * 英語などで、現在、過去、未来などで動詞の形が変わること。
631 じせい 時勢 * 移り変わる勢い。
645632 じせん 自薦 * 自分を推薦すること。「生徒会長に自薦する」
646633 じせん 自選 * 自分で選ぶこと。「自分の詩のなかで良いものを自選する」
647634 じちょう 自重 * 行動をつつしむこと。「ギャンブルを自重する」
648 じちょう 自嘲 * 自分をあざ笑うこと。「自嘲的な笑い」
635 じちょう 自嘲 * 自分をさげずむこと。「自嘲的な笑い」
649636 しつける 仕付ける 一段 したてる。「服を仕付ける」
650 しつける 躾ける 一段 〈かな書きも〉(子供などに)マナーを覚えさせる。「子供を躾ける」
651 じっけん 実検 * 〈文語〉実物を見て検査すること。「実検状」
652 じっけん 実験 * 理論や考えが正しいかどうか、実際にやって確かめること。「理科の実験」
653 じつじょう 実情 * 〈「実状」に同じ〉実際の事情、実際のようす。「実情を訴える」「実情を把握する」
654 じつじょう 実状 * 〈「実情」に同じ〉実際の事情、実際のようす。「実状を訴える」「実状を把握する」
637 しつける 躾ける 一段 子供にマナーを覚えさせる。「子供を躾ける」
638 じっけん 実検 * 実状を検査すること。「実検状」
639 じっけん 実験 * 理論を実際にやって確かめること。「理科の実験」
640 じつじょう 実情 * 実際の事情。「実情を訴える」
641 じつじょう 実状 * 実際のようす。「実状を把握する」
655642 じっせん 実戦 * 実際の戦闘。「実戦経験」
656643 じっせん 実践 * 実際にものごとを行なうこと。「改革案を実践する」
657 じったい 実体 * 実在する姿。「実体を持たない幽霊」
644 じったい 実体 * 本体。「実体がつかめない」
658645 じったい 実態 * 実際の状態。「実態調査」
659 じてん 事典 * さまざまなことがらを説明する本。「百科事典」
660 じてん 辞典 * ことばの意味を説明する本。辞書。「国語辞典」「英和辞典」
661 じてん 字典 * ひとつひとつの漢字について説明する本。「書道字典」
662 じにん 自任 * そうであると自分で考える。「専門家を自任する」
646 じてん 事典 * さまざまなことを説明した本。「百科事典」
647 じてん 辞典 * 辞書。「国語辞典」
648 じにん 自任 * 自らの任務とすること。「管理者を自任する」
663649 じにん 自認 * 自ら認めること。「過ちを自認する」
664 しのぶ 偲ぶ 五段・バ行 遠く離れたものや亡くなった人のことを思う。「故郷を偲ぶ」「故人を偲ぶ」
665 しのぶ 忍ぶ 五段・バ行 1. こらえる。「恥を忍ぶ」\n2. (人目などを)避ける。目立たないように行動する。「人目を忍ぶ」「忍ぶ恋」「世を忍ぶ仮の姿」(=世間に知られないようにするための仮の姿)\n3. 〈「〜に忍びない」として〉感情的な理由で、〜することができない。「捨てるに忍びない」
666 しぼむ 萎む 五段・マ行 〈かな書きも〉ふくらんでいたものが小さくなる。「つぼみが萎む」
667 しぼりあげる 絞り上げる 一段 1. すっかりしぼる。「雑巾を絞り上げる」\n2. きびしく責める。「遅く帰宅した息子を絞り上げる」\n3. 取り立てる。「金品を絞り上げる」
668 しぼりあげる 搾り上げる 一段 →絞り上げる
669 しぼる 絞る 五段・ラ行 〈1, 2 は「搾る」とも〉\n1. がんばって出す。「知恵を絞る」\n2. 責める。「先生に絞られた」\n3. よく選んで少なくする。「人数を絞る」\n4. 調節して小さくする。「ボリュームを絞る」
670 しぼる 搾る 五段・ラ行 〈「絞る」とも〉ねじって水分を出す。「雑巾を搾る」「乳を搾る」
650 しのぶ 偲ぶ 五段・バ行 昔のことを思う。「故人を偲ぶ」
651 しのぶ 忍ぶ 五段・バ行 こらえる。「恥を忍ぶ、人目を忍ぶ」
652 しぼむ 萎む 五段・マ行 ふくらんでいたものが小さくなる。「つぼみが萎む」
653 しぼりあげる 絞り上げる 一段 強く絞る。「雑巾を絞り上げる」
654 しぼりあげる 搾り上げる 一段 きびしく責める。「金品を搾り上げる」
655 しぼる 絞る 五段・ラ行 ねじって水分を出す。「雑巾を絞る、人数を絞る、ボリュームを絞る」
656 しぼる 搾る 五段・ラ行 力を加えて液を出す。「果物を搾る、税金を搾り取る」
671657 しまる 絞まる 五段・ラ行 (首などに)ものが巻きつけられて力が加わる。「首が絞まる」
672 しまる 締まる 五段・ラ行 1. 固定されて動きにくい状態になる。「ねじが締まる」\n2. 緊張感が出てしっかりする。「顔が締まる」「気持ちが締まる」
658 しまる 締まる 五段・ラ行 ひきしまる。「気持が締まる、ねじが締まる、顔が締まる」
673659 しまる 閉まる 五段・ラ行 (ドアや窓が)とじられる。「ドアが閉まる」
674 しみる 染みる 一段 〈かな書きも〉\n1. (液体、臭いなどが)ものに入りこむ。「服に汗が染みる」\n2. 〈主にかな書き〉刺激物が入って痛くなる。「たばこの煙が目にしみる」「歯に水がしみる」\n3. 深く感じる。「教訓が身に染みてわかった」
675 しみる 凍みる 一段 〈文語〉こおりつく。「寒さで身が凍みる」
676 しむ 染む 五段・マ行 〈文語〉(液体、臭いなどが)ものに入りこむ。染みる。
677 しむ 凍む 五段・マ行 〈文語〉こおりつく。凍みる。
678 しめきる 締め切る 五段・ラ行 受け付けを終える。「受付を締め切る」「論文を締め切る」
660 しみる 染みる 一段 (液体、臭いなどが)ものに入りこむ。「汗が染みる、たばこの煙が目に染みる、教訓が身に染みてわかった」
661 しみる 凍みる 一段 こおりつく。「寒さで身が凍みる」
662 しむ 染む 五段・マ行 (液体、臭いなどが)ものに入りこむ。染みる。
663 しむ 凍む 五段・マ行 こおりつく。凍みる。
664 しめきる 締め切る 五段・ラ行 受け付けを終える。「受付を締め切る、論文を締め切る」
679665 しめきる 閉め切る 五段・ラ行 閉じたままにする。「ドアを閉め切る」
680 しめす 示す 五段・サ行 1. わかるように見せる。「手本を示す」「自分の力を示す」\n2. 考え・反応をあらわす。「興味を示す」
681 しめす 湿す 五段・サ行 しめらせる。「のどを湿す」
666 しめす 示す 五段・サ行 わかるように見せる。「手本を示す、自分の力を示す、興味を示す」
667 しめす 湿す 五段・サ行 しめらす。「のどを湿す」
682668 しめる 絞める 一段 (首などに)ものを巻きつけて力を加える。「首を絞める」
683 しめる 占める 一段 1. ある場所・順位・役割にある。「上位を占める」\n2. (ある割合を)持つ。「大勢を占める」「全体の三割を占める」
684 しめる 締める 一段 固定して動きにくい状態にする。「ネジを締める」
669 しめる 占める 一段 独占する。「上位を占める、大勢を占める」
670 しめる 締める 一段 ひきしめる。「ネジを締める、気持を引き締める」
685671 しめる 閉める 一段 (ドアなどを)閉じる。「ドアを閉める」
686 しもん 試問 * 問題を出して試すこと。「口頭試問」
687 しもん 諮問 * 意見を求めること。「諮問機関」
672 しもん 試問 * 試しに問う。「口頭試問」
673 しもん 諮問 * (目上のものが)意見を求めること。「部下に諮問する、諮問機関」
688674 しゃく 勺 * 容積の単位。約18ml。
689 しゃく 尺 * 長さの単位。約30.3cm。
675 しゃく 尺 * 長さの単位。1mの10/33。
690676 しゃく 杓 * ひしゃく。
691677 しゃく 酌 * 酒を杯にそそぐこと。
692 しゅうがく 就学 * 学校に入り、勉強すること。「就学前の児童」
678 しゅうがく 就学 * 学校に入り、勉強すること。
693679 しゅうがく 修学 * 学問を修めること。
694680 しゅうかん 習慣 * 日常で決まりごとのように行なわれること。
695681 しゅうかん 週刊 * 週ごとに刊行すること。「週刊誌」
696 しゅうかん 週間 * 1週のあいだ。「週間天気予報」
682 しゅうかん 週間 * 7日間。「週間天気予報」
697683 じゅうき 什器 * 日常で使用する家具。
698684 じゅうき 銃器 * 銃の総称。
699685 しゅうぎょう 就業 * 職に就くこと。
700686 しゅうぎょう 修業 * 学業などを修めること。
701687 しゅうぎょう 終業 * 業務を終えること。
702 しゅうし 終始 * 1. 始めと終り。\n2. 始めから終わりまで。「終始笑顔を浮かべていた」\n3. 始めから終わりまで続けること。「試合では防戦に終始した」
688 しゅうし 終始 * 始めから終りまで同じこと。「試合では防戦に終始した」
703689 しゅうし 終止 * おわること。
704690 しゅうしゅう 収拾 * おさめること。「事態を収拾する」
705 しゅうしゅう 収集 * 〈「蒐集」の書き換え〉\n1. 趣味などのために集めること。「コインを収集する」\n※この意味では、現在も「蒐集」と書かれることがある。\n2. 集めること。「ごみの収集」
706 しゅうしゅう 蒐集 * →収集
691 しゅうしゅう 収集 * (「蒐集」と区別なし)あつめること。「コインを収集する」
692 しゅうしゅう 蒐集 * (「収集」と区別なし)あつめること。「コインを蒐集する」
707693 じゅうしょう 重傷 * 重い傷。「刃物で切られて重傷を負う」
708694 じゅうしょう 重症 * 重い症状。「重症患者」
709695 しゅうせい 修整 * ととのえなおすこと。「画像を修整する」
710696 しゅうせい 修正 * なおして正しくすること。「軌道を修正する」
711697 しゅうせい 集成 * あつめてまとめること。集大成。
712698 じゅうそう 重奏 * 同時に奏でること。「四重奏」
713 じゅうそう 重層 * 何層にも重なっていること。
714 しゅうそく 収束 * 1. おさまりがつくこと。「事態が収束する」\n2. (数学で)関数の値がある値に近づいていくこと。「f(x)は0に収束する」
715 しゅうそく 終息 * ものごとが終わること。「反乱は完全に終息した」
699 じゅうそう 重層 * 何層にも重なること。
700 しゅうそく 収束 * おさまりがつくこと。「f(x)は0に収束する」
701 しゅうそく 終息 * ものごとが終わること。「反乱が終息に向かっている」
716702 しゅうそく 集束 * 光が一点に集まること。
717703 しゅうとく 収得 * 自分のものとすること。「収得罪」
718704 しゅうとく 修得 * 学んで身につけること。
719705 しゅうとく 拾得 * 拾うこと。「拾得物」
720706 しゅうとく 習得 * 習って覚えること。「技術を習得する」
721 しゅうよう 収容 * 特定の場所におさめること。「遺体を収容する」「収容所」
722 しゅうよう 収用 * 1. とりあげて用いること。\n2. 国などが補償金を払って強制的に取得すること。「土地を収用する」
707 しゅうよう 収容 * 特定の場所におさめること。「遺体を収容する、収容所」
708 しゅうよう 収用 * とりあげて用いるいこと。「土地を収用する」
723709 しゅうりょう 修了 * 一定の学業をおさめること。「高校の課程を修了する」
724710 しゅうりょう 終了 * おわること。「ゲームを終了する」
725 しゅうろく 収録 * 記録しておさめること。「この曲はこのCDに収録されている」「TV番組を収録する」
726 しゅうろく 集録 * あつめて記録すること。「民話を集録する」
711 しゅうろく 収録 * のせておくこと。「この曲はこのCDに収録されている、TV番組を収録する」
712 しゅうろく 集録 * あつめて記録すること。
727713 しゅかん 主幹 * 仕事の中心となる人。
728 しゅかん 主観 * 自分からみた考え方。「主観的な考え方」
714 しゅかん 主観 * 自分からの考え方。「主観的な考え方」
729715 しゅくせい 粛正 * 厳しくとりしまり、不正をとりのぞくこと。
730716 しゅくせい 粛清 * 厳しくとりしまり、反対するものを排除すること。「政敵を粛清する」
731717 じゅけん 受検 * 検査を受けること。
732718 じゅけん 受験 * 試験を受けること。「地元の大学を受験する」
733719 しゅさい 主催 * 中心となって催すこと。「大会を主催する」
734 しゅさい 主宰 * 中心となってまとめること。「同好会を主宰する」
735 しゅし 主旨 * 主な内容。「文章の主旨」
736 しゅし 趣旨 * 達成しようとする目的、ねらい。また、伝えたい内容。「会議の趣旨」「話の趣旨をつかむ」
737 しゅじ 主事 * 中心となっておこなうこと。また、その人。「教育主事」
720 しゅさい 主宰 * 中心となっておこなうこと。「同好会を主宰する」
721 しゅし 主旨 * 主な意味。「文章の主旨」
722 しゅし 趣旨 * おもむき、ねらい。「会議の趣旨」
723 しゅじ 主事 * 中心となっておこなうこと。「教育主事」
738724 しゅじ 主辞 * 主語。
739725 じゅしょう 受賞 * 賞を受けること。「金賞を受賞する」
740726 じゅしょう 授賞 * 賞を授けること。「授賞式」
741727 しゅせき 主席 * 会議などを代表する人。「会議の主席をつとめる」
742 しゅせき 首席 * トップの順位。また、それを取った人。「首席で卒業する」
743 じゅつご 術語 * 専門用語。
728 しゅせき 首席 * 一番。「首席で卒業する」
729 じゅつご 術語 * 専門的な用語。
744730 じゅつご 述語 * 主語の状態などを述べる単語。「主語と述語」
745731 しゅっせい 出征 * 戦場に行くこと。「友人が出征する」
746 しゅっせい 出生 * 〈「しゅっしょう」とも読む〉うまれること。「出生届」
732 しゅっせい 出生 * うまれること。「出生届」
747733 じゅんか 純化 * 純粋にすること。
748 じゅんか 順化 * 生物が環境に適した性質を持つようになること。
749 じゅんか 馴化 * 生物が環境に適した性質を持つようになること。→順化
750 じゅんこう 巡航 * 1. 航海してまわること。\n2. 推進力をもって空中を移動すること。「巡航ミサイル」
751 じゅんこう 巡行 * 各地をめぐること。
752 じゅんずる 准ずる サ変・−ズル →準ずる
734 じゅんか 順化 * (「馴化」と区別なし)生物が環境に適した性質を持つこと。
735 じゅんか 馴化 * (「順化」と区別なし)生物が環境に適した性質を持つこと。
736 じゅんこう 巡航 * 航海してまわること。「巡航ミサイル」
737 じゅんこう 巡行 * あるきまわること。
738 じゅんずる 准ずる サ変・−ズル (「準ずる」と区別なし)ある基準にならう。「法律に准ずる」
753739 じゅんずる 殉ずる サ変・−ズル あることのために死ぬこと。「職に殉ずる」
754 じゅんずる 準ずる サ変・−ズル ある基準にならう。「法律に準ずる」
755 じゅんりょう 純良 * 〈文語〉純粋で善良である。
756 じゅんりょう 順良 * 〈文語〉従順ですなおである。
757 じょする 序する サ変・−スル 〈文語〉順序を決める。
758 じょする 除する サ変・−スル 〈文語〉除く。
759 しょうする 称する サ変・−スル 1. 名付ける。呼ぶ。「この方法を、ここでは方法Aと称することにする」\n2. 名乗る。「妻の氏を称する」\n3. 自分でそうであると言う。「彼の友人と称する者」\n4. 〈「〜と称して」として〉〜であるという名目で。「しつけと称して虐待を行なっていた」
760 しょうする 証する サ変・−スル 〈文語〉証明する。「無実を証する」
761 しょうする 賞する サ変・−スル 〈文語〉賞賛する。「彼の行動を賞する」
740 じゅんずる 準ずる サ変・−ズル (「准ずる」と区別なし)ある基準にならう。「法律に準ずる」
741 じゅんりょう 純良 * 純粋で善良である。
742 じゅんりょう 順良 * 従順ですなおである。
743 じょ 序 * (文語)順序を決める。
744 じょ 除 * (文語)除く。
745 しょう 称 * (文語)よぶ、たたえる。「彼の友人と称する者」
746 しょう 証 * (文語)証明する。「無実を証する」
747 しょう 賞 * (文語)賞賛する。「彼の行動を賞する」
762748 しょうえん 小宴 * 小さな宴。
763749 しょうえん 招宴 * 宴に招くこと。
764 しょうか 消化 * 1. 食物を胃などで分解すること。「消化酵素」\n2. たまったものをこなすこと。「日程を消化する」
750 しょうか 消化 * 食物を胃などで分解すること。「消化酵素、日程を消化する」
765751 しょうか 消火 * 火を消すこと。「消火器」
766752 しょうがく 奨学 * 学問をすすめること。「奨学金」
767753 しょうがく 小学 * 小学校の略。「小学生」
768 しょうがく 小額 * 小さい額面。「小額紙幣」
769 しょうがく 少額 * 少ない金額。「少額訴訟」
770 しょうきゃく 償却 * 1. (借金などを)返し終わること。「借金を償却する」\n2. 時間にしたがって価値の失われるようなものについて、そのことを計算すること。減価償却。\n3. 金銭化の見込めなくなった資産について、それを失ったものとして処理すること。
771 しょうきゃく 消却 * なくすこと。「株式を消却する」
772 しょうきゃく 焼却 * 燃やして捨てること。「ゴミを焼却する」
773 しょうきん 償金 * 賠償金。
774 しょうきん 賞金 * 賞としての金銭。「賞金王」
775 しょうさん 称賛 * 褒め称えること。
776 しょうさん 賞賛 * →称賛
777 しょうしゅう 召集 * (国会、軍隊などに)人を集めること。「国会を召集する」「召集令状」
778 しょうしゅう 招集 * 招いて人を集めること。「会議を招集する」
754 しょうがく 小額 * (「少額」と区別なし)金額が小さいこと。「小額紙幣」
755 しょうがく 少額 * (「小額」と区別なし)金額が少ないこと。「少額訴訟」
756 しょうきゃく 償却 * (借金などを)返すこと。「借金を償却する」
757 しょうきゃく 消却 * 消しさること。「証拠を消却する」
758 しょうきゃく 焼却 * 焼きすてること。「ゴミを焼却する」
759 しょうきん 償金 * 賠償金のこと。
760 しょうきん 賞金 * 賞としての金銭のこと。「賞金王」
761 しょうさん 称賛 * (「賞賛」と区別なし)
762 しょうさん 賞賛 * (「称賛」と区別なし)
763 しょうしゅう 召集 * (国会、軍隊などに)人を集めること。「国会を召集する、召集令状」
764 しょうしゅう 招集 * 人を集めること。「会議を招集する」
779765 しょうしゅう 消臭 * 臭いを消すこと。「消臭剤」
780 じょうじょう 上々 * 〈「上乗」とも〉この上もなくよいこと。「気分は上々」「上々の出来」
781 じょうじょう 上乗 * 1. 「大乗」に同じ。仏教流派のひとつ。\n2. →上々
766 じょうじょう 上々 * このうえもないこと。「気分は上々」
767 じょうじょう 上乗 * 最もすぐれていること。「上乗の出来」
782768 しょうすう 小数 * 整数でない実数。「小数点」
783769 しょうすう 少数 * 数が少ないこと。「少数派」
784770 じょうすう 乗数 * かけ算での掛ける数。
785 じょうすう 常数 * 「定数」に同じ。
786 しょうずる 招ずる サ変・−ズル 〈文語〉もてなす。「客を招ずる」
787 しょうずる 生ずる サ変・−ズル 発生する。「誤解が生ずる」
771 じょうすう 常数 * 状態変化において、変わらない値のこと。
772 しょうずる 招ずる サ変・−ズル (文語)もてなす。「客を招ずる」
773 しょうずる 生ずる サ変・−ズル (文語)発生する。「誤解が生ずる」
788774 じょうたい 常態 * 通常の状態。
789775 じょうたい 状態 * ものごとの様子。「状態変化」
790776 しょうらん 照覧 * (神などが)ごらんになること。「ご照覧あれ」
791 しょうらん 笑覧 * 笑いながら見ること(人に自分のものを見てもらう時にへりくだって言う)。「ご笑覧ください」
792 しょくする 嘱する サ変・−スル 〈文語〉望みを託す。「将来を嘱されている」
793 しょくする 食する サ変・−スル 食べる。「海の幸を食する」
794 しょくする 属する サ変・−スル 〈文語〉\n1. 属(ぞく)する。\n2. 嘱する。
777 しょうらん 笑覧 * わらいながら見ること。
778 しょく 嘱 * (文語)(「属する」と区別なし)たのむ。「将来を嘱されている」
779 しょく 食 * (文語)たべる。「海の幸を食する」
780 しょく 属 * (文語)(「嘱する」と区別なし)たのむ。「将来を属されている」
795781 しょくぜん 食前 * 食べる前のこと。「食前酒」
796782 しょくぜん 食膳 * 食事を載せた膳。「食膳に上る」
797783 しょくりょう 食料 * 食べ物。「生鮮食料品」
798 しょくりょう 食糧 * 食べ物。特に、主食。「食糧管理法」
799 じょする 叙する サ変・−スル 〈文語〉\n1. 叙述する。\n2. (地位を)授ける。(地位に)つける。「元帥に叙する」
800 じょする 恕する サ変・−スル 〈文語〉許す。
801 じょせい 助勢 * 力を貸すこと。
802 じょせい 助成 * 成功に導くため援助すること。「研究の助成金」
784 しょくりょう 食糧 * 食べ物、主食。「食糧管理法」
785 じょする 叙する サ変・−スル (文語)叙述する。
786 じょする 恕する サ変・−スル (文語)許す。
787 じょせい 助勢 * たすけること。
788 じょせい 助成 * たすけて成功させること。「研究の助成金」
803789 しょとう 初冬 * 冬の初め。
804790 しょとう 初等 * 最初の等級。「初等教育」
805791 しょとう 初頭 * はじめのころ。「80年代初頭に」
806792 しょとう 諸島 * 島々。「小笠原諸島」
807 しょよう 所用 * 用事。「所用のため欠席する」
808 しょよう 所要 * 必要となるものや時間など。「所要時間」
809 しる 知る 五段・ラ行 1. ものごとの意味、内容がわかる。「事実を知る」「知る人ぞ知る逸品」\n2. 経験して身につける。「酒の味を知る」
810 しれい 司令 * (軍隊などで)指揮をとること。また、その人。「司令官」
793 しょよう 所用 * 用事があること。「所用のため欠席する」
794 しょよう 所要 * 必要であるもの、こと。「所要時間」
795 しる 知る 五段・ラ行 ものごとの意味、内容がわかる。「事実を知る、酒の味を知る、知る人ぞ知る逸品」
796 しれい 司令 * (軍隊などで)指揮をとる人。「司令官」
811797 しれい 指令 * 命令。「特攻の指令を出す」
812798 しんい 深意 * 深い意味。
813799 しんい 真意 * 本当の意向。「彼の真意がわからない」
814800 しんか 深化 * 深くなる。「対立が深化する」
815 しんか 進化 * (生物などが)時間とともに変わっていき、発展する。「魚類が進化して両生類となった」「技術が進化する」
816 しんこく 申告 * 申し出ること。「確定申告」
801 しんか 進化 * 進歩する。「猿が進化して人類となる、技術が進化する」
802 しんこく 申告 * 申し告げること。「確定申告」
817803 しんこく 親告 * みずから告げること。「親告罪」
818804 しんしゅつ 侵出 * 境界を越えて進出すること。「他国に侵出する」
819805 しんしゅつ 浸出 * にじみ出ること。「浸出液」
820 しんしゅつ 進出 * 進み出ること。「販路拡大のため海外に進出する」
821 しんしゅつ 滲出 * にじみ出ること。→浸出
822 しんしょく 侵食 * 徐々に侵すこと。
823 しんしょく 侵蝕 * 徐々に侵すこと。→侵食
824 しんしょく 浸食 * 水などが徐々に土を削ること。「海岸が浸食されていく」
825 しんしょく 浸蝕 * 水などが徐々に土を削ること。「海岸が浸蝕されていく」→浸食
806 しんしゅつ 進出 * 進み出ること。「海外に進出する」
807 しんしゅつ 滲出 * しみ出ること。「滲出液」
808 しんしょく 侵食 * (「侵蝕」と区別なし)徐々に侵すこと。
809 しんしょく 侵蝕 * (「侵食」と区別なし)徐々に侵すこと。
810 しんしょく 浸食 * (「浸蝕」と区別なし)水などが徐々に土を削ること。「海岸が浸食されていく」
811 しんしょく 浸蝕 * (「浸食」と区別なし)水などが徐々に土を削ること。「海岸が浸蝕されていく」
826812 しんずい 心髄 * 中心。
827 しんずい 真髄 * 〈「神髄」とも〉本質。「武士道の真髄を究める」
828 しんずい 神髄 * 〈「真髄」とも〉本質。「武士道の神髄を究める」
829 しんずる 信ずる サ変・−ズル 〈文語〉正しいと考える。「神々を信ずる」
830 しんずる 進ずる サ変・−ズル 〈文語〉差し上げる。進上する。
813 しんずい 真髄 * (「神髄」と区別なし)そのことの本質。「武士道の真髄を究める」
814 しんずい 神髄 * (「真髄」と区別なし)そのことの本質。「武士道の神髄を究める」
815 しんずる 信ずる サ変・−ズル (文語)正しいと考える。「神々を信ずる」
816 しんずる 進ずる サ変・−ズル (文語)進上する。
831817 しんそう 深層 * 深い層。「海洋深層水」
832 しんそう 深窓 * 家の奥深い部屋。転じて、上流階級の家庭環境。「深窓の令嬢」
833 しんそう 真相 * 真実のの事情。「事件の真相を知る」
834 しんてん 伸展 * 1. 発達して広がること。「商業が伸展する」\n2. 曲がっていたものをまっすぐにすること。「下肢を伸展する」\n3. 引っ張られて長くなること。「皮膚の伸展」
835 しんてん 進展 * 時間とともに事態が展開していくこと。「状況が進展する」
836 しんどう 振動 * ゆれ動くこと。「振り子の振動」
837 しんどう 震動 * ふるえること。「家が震動する」\n※小さなものに対して「ふるえる」の意味で「振動」を使うことも多い。「携帯電話が振動する」
838 しんにゅう 侵入 * 領域を侵して入ること。「不法侵入」
839 しんにゅう 浸入 * 水などが入ること。「雨水が浸入する」
840 しんにゅう 進入 * 進み入ること。「交差点に進入する」
818 しんそう 深窓 * 家の奥にある居間。
819 しんそう 真相 * 知らなかった真実。「事件の真相を知る」
820 しんてん 伸展 * のばし展開すること。
821 しんてん 進展 * 進歩して発展すること。「状況が進展する」
822 しんどう 振動 * 振り動くこと。「携帯が振動する」
823 しんどう 震動 * ゆれること。「家が震動する」
824 しんにゅう 侵入 * 侵し入ること。「不法侵入」
825 しんにゅう 浸入 * 水などが入ること。
826 しんにゅう 進入 * 進み入ること。
841827 しんり 心理 * 心の状態。「被害者心理」
842 しんり 真理 * 変わらない真実。「真理を探究する」
843 すいか 垂下 * 〈文語〉垂れ下がること。垂れ下げること。
844 すいか 誰何 * 呼び止めて誰であるかを問うこと。「守衛に誰何される」
828 しんり 真理 * まことのこと。「真理を探究する」
829 すいか 垂下 * たれさがること。
830 すいか 誰何 * 自分が誰かを問われること。
845831 すいこう 推考 * 推測して考えること。「原因を推考する」
846 すいこう 推敲 * 時間をかけて文章を練ること。「文章を推敲する」
832 すいこう 推敲 * 文章を練り直すこと。「文章を推敲する」
847833 すいこう 遂行 * なしとげること。「任務を遂行する」
848 すいしょう 推奨 * 良いとして相手にすすめること。「動作環境は以下を推奨する」
849 すいしょう 推賞 * ほめること。「彼の描いた作品を推賞する」
834 すいしょう 推奨 * すすめること。「動作環境は以下を推奨する」
835 すいしょう 推賞 * ほめてすすめること。「彼の描いた作品を推賞する」
850836 すいとう 水稲 * 水田で栽培される稲。
851 すいとう 水筒 * 水などを入れる携帯用の容器。
852 すいほう 水泡 * 水のあわ。転じて、むだになること。「苦労が水泡に帰す」
837 すいとう 水筒 * 水を入れる筒。
838 すいほう 水泡 * 水のあわ。「苦労が水泡に帰す」
853839 すいほう 水疱 * 水ぶくれ。
854 すう 吸う 五段・ワ行促音便 気体や液体、また雑物などを内部に取りこむ。吸引する。「息を吸う」「煙を吸う」「掃除機でゴミを吸う」
855 すき 隙 * 1. 付け入る余地。油断。「隙を見せる」\n2. 〈「〜した隙に」として〉うっかり〜している間に。「目を離した隙に重要な場面を見逃した」
856 すき 鋤 * スコップに似た、人手で土を耕す農具。
840 すう 吸う 五段・ワ行促音便 気体、液体を口または鼻から体内に取りこむ。「息を吸う、煙を吸う、掃除機がゴミを吸い込む」
841 すき 隙 * すきま。「隙を見せる」
842 すき 鋤 * 土を耕す農具。
857843 すき 犁 * 馬、牛などに引かせて土を掘り起こす農具。
858 すく 空く 五段・カ行イ音便 中身が減って空間ができる。「電車が空く」「おなかが空く(=空腹になる)」「手が空く(=することに余裕ができる)」
859 すく 好く 五段・カ行イ音便 〈文語〉好きになる。「ギャンブルは好かない」
860 すく 漉く 五段・カ行イ音便 〈かな書きも〉紙をつくる。「和紙を漉く」
861 すく 透く 五段・カ行イ音便 〈文語〉物と物の間にすきまができる。「壁の間が透いている」
862 すくう 掬う 五段・ワ行促音便 〈かな書きも〉くぼんだもので、液体や粉末・それに含まれるものを取る。「手で水を掬う」「金魚を掬う」
863 すくう 救う 五段・ワ行促音便 危険、困難などから助ける。「窮地を救う」「世を救う」
864 すくう 巣くう 五段・ワ行促音便 〈「巣食う」とも〉よくないものが根を下ろす。「町に巣くう悪者」
865 すくう 巣食う 五段・ワ行促音便 〈「巣くう」とも〉よくないものが根を下ろす「町に巣食う悪者」
866 すず 錫 * 〈カタカナ書きが普通〉元素の一つ。またはその金属。
844 すく 空く 五段・カ行イ音便 ものの中にすきまができる。「おなかが空く、電車が空く、手が空く」
845 すく 好く 五段・カ行イ音便 好きになる。「ギャンブルは好かない」
846 すく 漉く 五段・カ行イ音便 紙をつくる。「和紙を漉く」
847 すく 透く 五段・カ行イ音便 物と物の間にすきまができる。「壁の間が透いている、」
848 すくう 掬う 五段・ワ行促音便 液体をさじなどにとる。「手で水を掬う、金魚を掬う」
849 すくう 救う 五段・ワ行促音便 危険、困難などから助ける。「窮地を救う、世を救う」
850 すくう 巣食う 五段・ワ行促音便 巣を作る。「町に巣食う悪者」
851 すず 錫 * 元素の一つ。またはその金属。
867852 すず 鈴 * 小さい玉を金属などでできた球形のものに入れ、振ると音がなるもの。「ネコの首に鈴を付ける」
868 すすめる 勧める 一段 〈「奨める」とも〉\n1. 物を示し、使う・食べるように促す。「ワインを勧める」\n2. 行動をとるようにさそう。「退社するように勧める」「受診を勧める」\n3. 〈「薦める」とも〉物について、良いとして採用を促す。「新商品を勧める」
869 すすめる 奨める 一段 →勧める
870 すすめる 進める 一段 前に出す。前に動かす。「コマを進める」「交渉を進める」「社内の効率化を進める」
871 すすめる 薦める 一段 (人や物を)良いとして採用を推薦する。「新商品を薦める」「適任者として2人を薦める」\n※物については、多く「勧める」とされる。
853 すすめる 勧める 一段 (「奨める」と区別なし)そうするようにさそう。「退社するように勧める」
854 すすめる 奨める 一段 (「勧める」と区別なし)そうするようにさそう。「退社するように奨める」
855 すすめる 進める 一段 前に出す。「コマを進める、交渉を進める、社内の効率化を進める」
856 すすめる 薦める 一段 推薦する。「新商品を薦める」
872857 すます 済ます 五段・サ行 終わらせる。「仕事を済ませる」
873 すます 澄ます 五段・サ行 (液体などを)すきとおらせる。「泥水を澄ます」「耳を澄ます(=注意深く聞く)」
858 すます 澄ます 五段・サ行 (液体などを)すきとおらせる。「泥水を澄ませる、耳を澄ませる」
874859 すむ 済む 五段・マ行 終わる。「もう仕事は済んだ」
875 すむ 住む 五段・マ行 ある場所で生活する。「彼は東京に住んでいる」「森に住むキツネ」
860 すむ 住む 五段・マ行 ある場所で生活する。「彼は東京に住んでいる」
876861 すむ 澄む 五段・マ行 (液体が)すきとおる。「この湧き水はとても澄んでいる」
877 すむ 棲む 五段・マ行 「住む」に同じ。特に、動物などが巣で生活する。「森に棲むキツネ」「彼は東京に棲んでいる」
878 する 刷る 五段・ラ行 印刷する。「本を刷る」
879 する 擦る 五段・ラ行 1. こすり合わせる。「足を擦って歩く」\n2. 〈主にかな書き〉お金を安易に使ってなくす。「競馬で金をする」
880 する 摺る 五段・ラ行 →刷る
862 すむ 棲む 五段・マ行 (動物などが)巣で生活する。「キツネは森に棲んでいる」
863 する 刷る 五段・ラ行 (「摺る」と区別なし。一般的)印刷する。「本を刷る」
864 する 擦る 五段・ラ行 物と物をこすり合わせる。「足を擦って歩く、競馬で金を擦る」
865 する 摺る 五段・ラ行 (「刷る」と区別なし)印刷する。「本を摺る」
881866 すわる 座る 五段・ラ行 腰をおろす。「いすに座る」
882 すわる 据わる 五段・ラ行 安定する。「赤ん坊の首が据わる」「彼は腹が据わっている」
883 せいする 制する サ変・−スル 1. おさえこむ。「騒ぎを制する」\n2. 支配する。「過半数を制する」\n3. 〈文語〉制定する。「法を制する」
884 せいする 征する サ変・−スル 〈文語〉征伐する。「敵を征する」
885 せいいく 成育 * 育って成長すること。動物が育つこと。「魚が成育する」
886 せいいく 生育 * 生まれ育つこと。植物が生え育つこと。「農作物が生育する」
887 せいかい 正解 * 正しい解答。また、それを言うこと。「クイズに正解した」
888 せいかい 精解 * 〈文語〉詳しく解釈すること。
889 せいけい 成形 * 形をつくること。「粘土を成形する」
890 せいけい 整形 * (特に手術で)形を整えること。「整形手術」
867 すわる 据わる 五段・ラ行 安定する。「赤ん坊の首が据わる、彼は腹が据わっている」
868 せい 制 * おさえこむ。「騒ぎを制する、過半数を制する」
869 せい 征 * (文語)征伐する。「敵を征する」
870 せいいく 成育 * そだつこと。「魚が成育する」
871 せいいく 生育 * 生まれ育つこと。「農作物が生育する」
872 せいかい 正解 * 正しい解答。「クイズに正解した」
873 せいかい 精解 * (文語)詳しく解釈すること。
874 せいけい 成形 * 形をつくること。「ねんどを成形する」
875 せいけい 整形 * 形を整えること。「整形手術」
891876 せいけん 政権 * 政治上の権力。「政権政党」
892877 せいけん 政見 * 政治上の意見。「政見放送」
893 せいさく 制作 * (特に美術品などを)作ること。「絵画を制作する」「映画を制作する」\n※映像作品については「製作」とも。
894 せいさく 製作 * 1. (特に工業品などを)作ること。「機械を製作する」\n2. (映像作品などを)作ること。「映画を製作する」\n※「制作」とも。
895 せいさん 清算 * 1. 金銭の貸し借りを整理すること。「借金を清算する」\n2. けりをつけ、それに対する後始末を行うこと。「事業を清算する」「過去を清算する」
896 せいさん 精算 * 請求金額などを計算すること。また、その金額を払うこと。「運賃を精算する」「経費を精算する」
897 せいし 制止 * おさえて止めること。「暴動を制止する」「制止をふりきる」
898 せいし 静止 * 止まってそのままでいること。「静止衛星」
878 せいさく 制作 * 美術品などを作ること。「絵画を制作する」
879 せいさく 製作 * 工業品などを作ること。「機械を製作する」
880 せいさん 清算 * 金銭の貸し借りを整理すること。「事業を清算する、過去を清算する」
881 せいさん 精算 * 金額などを細かく計算すること。「運賃を精算する」
882 せいし 制止 * おさえて止めること。「暴動を制止する、制止をふりきる」
883 せいし 静止 * 止まって静かにすること。「静止衛星」
899884 せいしょう 清勝 * 手紙などで相手が健康で暮していることを祝う語。
900 せいしょう 清祥 * 手紙などで相手が幸せに暮していることを祝う語。
901 せいすう 整数 * 1に1を複数回足したり引いたりしてできる数。3, -5など。
902 せいすう 正数 * 0よりも大きな数。2.5, 8など。
903 せいねん 成年 * 1. 充分に成熟し、法律行為を単独で行うことができると規定された年齢。日本では満二十歳。また、それに達すること。また、それに達した人。「成年に達する」「今年成年する男女」「成年には選挙権が与えられる」\n2. 充分に成熟したと見なされる年齢。また、それに達すること。また、それに達した人。「成年用の予防接種」
904 せいねん 青年 * 1. 青春期の男性。「一人の青年がたたずんでいた」\n2. 〈主に複合語で〉青春期の男女。「青年海外協力隊」
905 せいひ 成否 * 成功するか否か。「法案の成否がかかっている」
906 せいひ 正否 * 正しいか否か。「解答の正否を確認する」
885 せいしょう 清祥 * 手紙などで相手が元気で暮していることを祝う語。
886 せいすう 整数 * 1,-253など1に1を複数回足したり引いたりしてできる数。
887 せいすう 正数 * 0よりも大きな数。
888 せいねん 成年 * 日本の法律では二十歳。
889 せいねん 青年 * 青年期の男女。「二十歳の青年」
890 せいひ 成否 * 成功するか否か。
891 せいひ 正否 * 正しいか否か。
907892 せいめい 清明 * 清く明らかなこと。
908 せいめい 声明 * 意見などを明らかにすること。「政府が声明を出す」「犯行の声明文」
909 せいやく 制約 * (行動などを)制限すること。「彼の行動を制約する」
893 せいめい 声明 * 意見などを明らかにすること。「政府が声明を出す、犯行の声明文」
894 せいやく 制約 * 約束で行動などを制限すること。「彼の行動を制約する」
910895 せいやく 成約 * 契約が成立すること。「保険が成約する」
911896 せいやく 誓約 * 誓って約束すること。「誓約書」
912 せじ 世事 * 世の中の事。「世事に疎い」
913 せじ 世辞 * 相手を喜ばせるために、心にもないことを言うこと。多く「お世辞」として使う。「世辞を言う」
914 せっしゅ 接種 * 免疫力をつけるために、ウィルス、ワクチンなどを体内に入れること。「予防接種」
915 せっしゅ 摂取 * (体内に)とりいれること。「栄養を摂取する」
916 せってん 接点 * 1. 曲線や曲面、直線などが一点で接するとき、その点。「曲線Aと直線Bとの接点」\n2. かかわり。「犯人との接点」
917 せってん 節点 * 接合されている点。ノード。
897 せじ 世事 * 世の中の事。
898 せじ 世辞 * 相手をよろこばせようとする言葉。「世辞を言う」
899 せっしゅ 接種 * ウィルス、ワクチンなどを体内にとり入れること。「予防接種」
900 せっしゅ 摂取 * とりいれること。「栄養を摂取する」
901 せってん 接点 * 共通する点。「曲線Aと直線Bとの接点、犯人との接点」
902 せってん 節点 * 定常波で振幅が最小になる点。
918903 せめる 攻める 一段 攻撃する。「敵を攻める」
919 せめる 責める 一段 1. 言葉であやまちをとがめる。「彼の無責任さを責める」\n2. 苦しませる。「捕虜を責める」
920 せんする 宣する サ変・−スル 〈文語〉宣言する。
921 せんする 撰する サ変・−スル 〈文語〉編纂する。
922 せんい 線維 * 〈医学・生物学で〉生物を構成するもので糸状のもの。「神経線維」
904 せめる 責める 一段 あやまちをとがめる。「彼の無責任さを責める、捕虜を責める」
905 せん 宣 * (文語)宣言する。
906 せん 撰 * (文語)編纂する。
907 せんい 線維 * 生物を構成するもので糸状のもの。「神経線維」
923908 せんい 繊維 * 細く糸状の物質。「食物の繊維質」
924 せんか 戦果 * 戦いにおける成果。「大きな戦果を得た」
925 せんか 戦火 * 戦争による火災。また、戦争。「戦火がせまる」
909 せんか 戦果 * 戦いで得たもの。「大きな戦果を得た」
910 せんか 戦火 * 戦争による火災。「戦火がせまる」
926911 せんか 戦禍 * 戦争の被害。「戦禍をこうむる」
927912 ぜんかい 全壊 * 全て壊れること。「校舎が全壊した」
928913 ぜんかい 全快 * すっかり治ること。「病気が全快した」
929 ぜんかい 全開 * 1. 全部開いていること。「窓を全開にする」\n2. 〈接尾語〉〈口語〉隠さずさらけ出すこと。丸出し。「本音全開のトーク」
930 ぜんしん 前進 * 前に進むこと。「隊列が前進する」「買収交渉が前進した」
914 ぜんかい 全開 * 全部開くこと。「窓を全開にする」
915 ぜんしん 前進 * 前に進むこと。「隊列が前進する、買収交渉が前進した」
931916 ぜんしん 漸進 * 順を追ってすこしずつ進むこと。「漸進的」
932 せんたん 先端 * 1. とがった端。「鉛筆の先端」\n2. もっとも新しく進んだところ。「先端技術」
933 せんたん 尖端 * →先端
917 せんたん 先端 * ものの一番先。「先端技術」
918 せんたん 尖端 * とがった端。「尖端的」
934919 せんたん 戦端 * 戦争のきっかけ。
935920 せんだん 栴檀 * ビャクダンの総称。
936921 せんだん 船団 * 船の集団。「タンカーの船団」
937922 せんてい 選定 * 選び定める。「請負業者を選定する」
938923 せんてい 剪定 * 枝を切り、果物がよく育つようにすること。「木を剪定する」
939924 せんみん 賎民 * いやしい民。
940 せんみん 選民 * 選ばれた民族。「選民主義」
941 せんもう 繊毛 * 細胞表面の微細な毛。「繊毛運動」
925 せんみん 選民 * 民族を選ぶこと。「選民主義」
926 せんもう 繊毛 * 細かい毛。「繊毛運動」
942927 せんもう 剪毛 * 羊などの毛を刈りとること。
943928 せんもう 譫妄 * 軽い意識障害。
944 せんゆう 占有 * 1. ひとりで持つこと。独占。「生産手段を占有する」\n2. 自分のものとして所持すること。「物件を占有する人」\n3. (割合などを)占めること。「市場占有率」
945 せんゆう 専有 * 共有せず、独立して所有すること。「マンションの個人専有部分」
929 せんゆう 占有 * 自分のものにすること。「トイレを占有する」
930 せんゆう 専有 * 一人で所有すること。「部屋の専有部分」
946931 せんりょ 千慮 * いろいろと考えること。
947932 せんりょ 浅慮 * あさはかな考え。
948 そうする 奏する サ変・−スル 〈文語〉奏上する、演奏する。「お囃子を奏する」
949 そうする 相する サ変・−スル 〈文語〉うらなう。
950 そうする 草する サ変・−スル 〈文語〉草案を作成する。「提言書を草する」
933 そう 奏 * (文語)奏上する、演奏する。「お囃子を奏する」
934 そう 相 * (文語)うらなう。
935 そう 草 * (文語)草案を作成する。「提言書を草する」
951936 そうい 創意 * 新しいものを作る気持ち。「創意工夫」
952937 そうい 創痍 * きず。「満身創痍」
953 そうかい 壮快 * 大胆で快いこと。「壮快な気質」
954 そうかい 爽快 * さわやかで快いこと。「爽快な喉越し」
955 そうかつ 総括 * 1. (情報などを)まとめること。「講演を総括する」\n2. 振り返って評価・反省すること。「近代史を総括する」\n3. 〈「総轄」とも〉(部署などを)管理すること。「事務を総括する」
956 そうかつ 総轄 * (部署などを)管理すること。「事務を総轄する」→総括
938 そうかい 壮快 * 元気で快いこと。
939 そうかい 爽快 * さわやかで快いこと。
940 そうかつ 総括 * 全体をしめくくること。「講演を総括する」
941 そうかつ 総轄 * 全体をとりまとめること。「総轄責任者」
957942 そうかん 創刊 * 雑誌などを新しく出版すること。「週刊誌を創刊する」
958943 そうかん 相姦 * 倫理に反する性交。「近親相姦」
959 そうかん 相関 * 互いに関係しあうこと。「相関関係」
960 そうかん 送還 * (特に、外国人を本国に)送りかえすこと。「強制送還」
944 そうかん 相関 * 互いに関係し合うこと。「相関関係」
945 そうかん 送還 * 送りかえされること。「強制送還」
961946 そうぎょう 創業 * 事業を新しく始めること。「会社の創業者」
962 そうぎょう 操業 * 機械などを操り、仕事をすること。また、一般に業務を行うこと。「操業中の工場」「自転車操業」
963 ぞうけい 造形 * 形を造ること。また、造った形。「金属を造形する」「造形が美しい」
964 ぞうけい 造詣 * ある分野の深い知識や経験。「造詣が深い」
965 そうさ 捜査 * (警察などが)事件について調べること。「犯罪捜査」
966 そうさ 操作 * (機械などを)操って動かすこと。「コンピュータを操作する」
967 そうさ 走査 * テレビなどで、画面を部分的に更新していくこと。「走査線」
947 そうぎょう 操業 * 機械などを操り、仕事をすること。「自転車操業」
948 ぞうけい 造形 * (芸術品などを)かたち造ること。「金属を造形する」
949 ぞうけい 造詣 * 学問、技術などに優れていること。「造詣が深い」
950 そうさ 捜査 * 捜して調べること。「犯罪捜査」
951 そうさ 操作 * 機械などを操って動かすこと。「コンピュータを操作する」
952 そうさ 走査 * テレビなどで画面を部分的に更新していく操作。「走査線」
968953 そうしゃ 掃射 * 機関銃などを敵全体に発射すること。「機銃掃射」
969 そうしゃ 操車 * 列車などを路線に配置すること。「操車場」
970 そうそう 早々 * 1. 急ぐさま。「早々に引き上げる」\n2. すぐ。「転校早々遅刻した」
971 そうそう 草々 * 1. いい加減なようす。「草々に確認を終える」\n2. 手紙の末尾に、簡略であることをわびるために添える語。
972 そうと 壮図 * 〈文語〉壮大な企て。
973 そうと 壮途 * 〈文語〉勇ましくさかんな門出。
954 そうしゃ 操車 * 電車の車両を路線に入れたり出したりすること。「操車場」
955 そうそう 早々 * 急ぐさま。「早々に引き上げる」
956 そうそう 草々 * 忙しいさま。「草々不一」
957 そうと 壮図 * 壮大な企て。
958 そうと 壮途 * 勇ましくさかんな門出。
974959 そくとう 即答 * すぐに答えること。「質問に即答する」
975960 そくとう 速答 * すみやかに答えること。
976 ぞくとう 続投 * 1. 野球などで、投手が続けて投げること。「上原が続投する」\n2. 続けて任にあたること。「幹事長の続投が決まった」
977 ぞくとう 続騰 * 物価、株価などが継続して上がること。「株価が続騰する」
961 ぞくとう 続投 * 続けて投げること。「上原が続投する、幹事長の続投が決まった」
962 ぞくとう 続騰 * 物価、株価などが続けて上がること。「株価が続騰する」
978963 そしゃく 租借 * 他国の領土を借りること。「租借地」
979 そしゃく 咀嚼 * 1. かみくだくこと。「食べ物を咀嚼する」\n2. よく理解すること。「文章の内容をよく咀嚼している」
964 そしゃく 咀嚼 * かみくだくこと。「食べ物を咀嚼する、文章の内容をよく咀嚼している」
980965 そじょう 訴状 * 訴える内容が書かれた文書。
981966 そじょう 俎上 * まないたの上。「俎上の魚」
982967 そなえる 供える 一段 神仏にお供物をさしあげる。
983968 そなえる 備える 一段 準備する。
984 そめる 初める 一段 〈文語、動詞連用形の後で〉…しはじめる。「咲き初める(=咲き始める)」
985 そめる 染める 一段 色をつける。「布を染める」「頬を染める(=頬を赤くする)」
986 そらす 逸らす 五段・サ行 〈かな書きも〉はずす。「目を逸らす」「ボールを逸らす」
987 そらす 反らす 五段・サ行 後ろへそらせる。「胸を反らす」
988 そる 剃る 五段・ラ行 〈かな書きも〉体毛などを、刃物を表面に斜めに当てて根元から切り落とす。「ひげを剃る」
989 そる 反る 五段・ラ行 曲がる。「大きく反っている刀」
990 たいする 体する サ変・−スル 〈文語〉心にとめて守る。「教えを体する」
991 たいする 対する サ変・−スル 1. 〈文語〉面と向かう。「敵に対する」\n2. 〈「~に対する」として、連体形・連用形で〉~を対象とする。~に対応する。「彼に対する評価」「その抗議に対して回答する」
992 たいする 帯する サ変・−スル 〈文語〉身につける。「小刀を帯する」
993 たいしょう 対症 * 症状に対処すること。「対症療法」
994 たいしょう 対称 * 互いに対応して、つりあいがとれていること。「左右対称」
995 たいしょう 対象 * 扱おうとするもの。「対象年齢」「質問の対象」
996 たいしょう 対照 * 1. 照らし合わせること。「原本と複写を対照して確認する」\n2. 複数の異なるものを並べることによって得られる印象。また、異なること。「主人公とライバルの対照が面白い」「対照的な性格」
997 たいせい 体制 * 仕組み。システム。また、社会の中心となる仕組み。「チェック体制」「反体制組織」
998 たいせい 体勢 * 体の姿勢。「相手のキックで体勢を崩した」
999 たいせい 態勢 * 物事に対する身構えや準備。「受け入れ態勢を整える」
1000 たいせい 大勢 * 1. おおよその形勢。「選挙結果の大勢が判明する」\n2. 大きな流れ。「社会の大勢に流される」
1001 たいせき 堆積 * 積み重なること。「土砂が堆積する」
1002 たいせき 滞積 * 〈まれ〉滞り、積もること。「仕事が滞積する」→堆積
1003 たえる 堪える 一段 1. 〈「耐える」とも〉その価値がある。「鑑賞に堪える作品」「見るに堪えない(=見ていられないほどひどい)」\n2. 〈「耐える」とも〉要件を満たす。「実用に堪える」
1004 たえる 絶える 一段 とだえる。続いていた流れなどが止まる。「息が絶える」「血筋が絶える」
1005 たえる 耐える 一段 〈「堪える」とも〉\n1. 我慢する。「痛みを耐える」\n2. もちこたえる。「水圧に耐える製品」
1006 たく 炊く 五段・カ行イ音便 (米などを)煮て食べられるようにする。「ご飯を炊く」
1007 たく 焚く 五段・カ行イ音便 〈かな書きも〉\n1. 火をつけて燃やす。また、それによって熱する。「まきを焚く」「風呂を焚く」\n2. (カメラのフラッシュを)点灯させる。
1008 たこ 凧 * 骨組みに紙などを張りひもをつけ、空気の力で空に飛ばす玩具。
1009 たこ 蛸 * 〈カタカナ書きも〉八本足の軟体動物。「蛸の刺身」
969 そめる 初める 一段 はじまる。「見初める」
970 そめる 染める 一段 色をつける。「布を染める、頬を染める」
971 そらす 逸らす 五段・サ行 はずす。「目を逸らす、ボールを逸らす」
972 そらす 反らす 五段・サ行 後ろへそる。「胸を反らす」
973 そる 剃る 五段・ラ行 体毛などを根元から切る。「髭を剃る」
974 そる 反る 五段・ラ行 のけぞる。「大きく反っている刀」
975 たい 体 * (文語)心にとめて守る。「教えを体する」
976 たい 対 * 面と向かう。「敵に対する、彼に対する態度、その抗議に対する回答」
977 たい 帯 * (文語)身につける。「小刀を帯する」
978 たいしょう 対症 * 症状に対すること。「対症療法」
979 たいしょう 対称 * 互いに対応していること。「左右対称」
980 たいしょう 対象 * 活動などが向けられるもの。「対象年齢、質問の対象」
981 たいせい 体勢 * 姿勢。「体勢をくずす」
982 たいせい 態勢 * 物事に対する身構え。「体勢を整える」
983 たいせい 大勢 * おおよその形勢。「大勢が判明する」
984 たいせき 堆積 * 積み重なること。「土壌が堆積する」
985 たいせき 滞積 * 滞り、積もること。「仕事が滞積する」
986 たえる 堪える 一段 我慢する。「苦痛に堪える、見るに堪えない」
987 たえる 絶える 一段 とだえる。「息が絶える、血筋が絶える」
988 たえる 耐える 一段 もちこたえる。「水圧に耐える、長期の使用に耐えうる。」
989 たき 滝 * (「瀧」と区別なし)
990 たき 瀧 * (「滝」と区別なし)
991 たく 炊く 五段・カ行イ音便 (米などを)煮る。「御飯を炊く」
992 たく 焚く 五段・カ行イ音便 火を燃やす。「たきびを焚く」
993 たこ 凧 * 紐がつき、風で空にあがる玩具。
994 たこ 蛸 * 八本足の軟体動物。「蛸足配線」
1010995 たさい 多彩 * 種類が多く、にぎやかなこと。「多彩な顔ぶれ」
1011996 たさい 多才 * さまざまなことに才能が豊かなこと。「多才な人」
1012 たしょう 他生 * 前世と来世。「他生の縁(=前世までの縁)」〈「多生の縁」とも〉
1013 たしょう 多生 * 何度も生まれ変わること。「多生の縁(=前世までの縁)」〈「他生の縁」とも〉
1014 たしょう 多少 * 1. 多いか少ないかの程度。「多少にかかわらずお持ちください」\n2. 多くない様子。少し。「多少のことには目をつぶります」
997 たしょう 他生 * 他が原因となり発生すること。
998 たしょう 多少 * 多いことと少ないこと。「多少のことには目をつぶります」
1015999 たしょう 多祥 * よろこびの多いこと。
10161000 たずねる 尋ねる 一段 質問する。「道を尋ねる」
10171001 たずねる 訪ねる 一段 おとずれる。「知人の家を訪ねる」
10181002 たたえる 称える 一段 称賛する。「勝利を称える」
1019 たたえる 湛える 一段 〈かな書きも〉\n1. 水などをいっぱいに満たす。「豊かな水を湛える湖」\n2. 表情を顔いっぱいに表す。「満面の笑みを湛える」
1020 たたかう 戦う 五段・ワ行促音便 〈「闘う」とも〉勝とうとして、または自分の要求を通すために、争う。「決勝戦を戦う」「敵国と戦う」「偏見と戦う」「病魔と戦う」
1021 たたかう 闘う 五段・ワ行促音便 「戦う」に同じ。精神的な面を強調するときに好んで使われる。「偏見と闘う」「病魔と闘う」
1022 たたく 叩く 五段・カ行イ音便 1. 手で打つ。「頭を叩く」「肩を叩く」\n2. (くだらないことを)言う。「へらず口を叩く」
1023 ただす 質す 五段・サ行 質問する。「行動の目的を質す」
1024 ただす 正す 五段・サ行 正しくする。「過ちを正す」「えりを正す」
1003 たたえる 湛える 一段 じゅうぶんに満たす。「満面の笑みを湛える、豊かな水を湛える湖」
1004 たたかう 戦う 五段・ワ行促音便 (戦争やスポーツなどにおいて)あらそう。「決勝戦を戦う、敵国と戦う」
1005 たたかう 闘う 五段・ワ行促音便 (困難や対立する人と)あらそう。「重病と闘う」
1006 たたく 叩く 五段・カ行イ音便 なぐる。「頭を叩く、肩を叩く、へらず口を叩く」
1007 ただす 質す 五段・サ行 質問する。「彼を問い質す」
1008 ただす 正す 五段・サ行 正しくする。「不正を正す、襟を正す」
10251009 たたむ 畳む 五段・マ行 折り重ねる。「洗濯物を畳む」
1026 たつ 起つ 五段・タ行 決起する。→立つ4
1010 たつ 起つ 五段・タ行 起き上がる。「髪が起つ」
10271011 たつ 経つ 五段・タ行 (時間が)経過する。「時が経つ」
10281012 たつ 建つ 五段・タ行 (建物が)つくられる。「ビルが建つ」
10291013 たつ 裁つ 五段・タ行 (布などを)裁断する。「布を裁つ」
1030 たつ 絶つ 五段・タ行 1. 続いていた流れなどを止める。「供給を絶つ」「命を絶つ」\n2. (連絡などが)なくなる。「航空機が消息を絶った」\n3. 〈「断つ」とも〉(関係などを)なくす。「関係を絶つ」
1031 たつ 断つ 五段・タ行 1. 切り離す。「糸を断つ」\n2. (道などを)通れなくする。「逃げ道を断つ」\n3. 〈「絶つ」とも〉(関係などを)なくす。「関係を断つ」\n4. 続けてしていたことをやめる。「酒を断つ」
1014 たつ 絶つ 五段・タ行 なくす。「連絡を絶つ、命を絶つ」
1015 たつ 断つ 五段・タ行 切り離す。「ロープを断つ、酒を断つ」
10321016 たつ 発つ 五段・タ行 出発する。「福岡に発つ」
1033 たつ 立つ 五段・タ行 1. 上に向かってまっすぐな状態にある。また、その状態になる。「立っている人」「木が立っている」\n2. 波や煙・ちりなど、またうわさなどが起こる。「波が立つ」「ほこりが立つ」\n3. 身を起こしてその場から去る。「席を立つ」\n4. 決起する。
1034 たつ 辰 * 干支(えと)の一つ。卯(う)の後、巳(み)の前。
1035 たつ 竜 * 蛇をモチーフとした、空を飛ぶ想像上の生物。りゅう。ドラゴン。
1036 たつ 龍 * 「竜」の旧漢字。「竜」と並行して用いられている。
1037 たっとい 貴い 形容詞・アウオ段 高貴・貴重・崇高であるさま。特に、高貴であるさま。とうとい。「貴い身分」
1038 たっとい 尊い 形容詞・アウオ段 高貴・貴重・崇高であるさま。特に、貴重・崇高であるさま。とうとい。「尊い生命」「尊い使命」
1039 たっとぶ 貴ぶ 五段・バ行 →尊ぶ
1040 たっとぶ 尊ぶ 五段・バ行 〈「貴ぶ」とも〉\n1. あがめる。「神を尊ぶ」\n2. 大切にする。「人権を尊ぶ」
1017 たつ 立つ 五段・タ行 身を起こす。「木が立つ、席を立つ、噂が立つ、波が立つ、顔が立つ」
1018 たつ 辰 * 干支の一つ。
1019 たつ 竜 * (「龍」と区別なし)想像上の生物。
1020 たつ 龍 * (「竜」と区別なし)想像上の生物。
1021 たっとい 貴い 形容詞・アウオ段 高貴である様。「貴い身分」
1022 たっとい 尊い 形容詞・アウオ段 尊敬できる様。「尊い神」
1023 たっとぶ 貴ぶ 五段・バ行 大切にする。「人権を貴ぶ」
1024 たっとぶ 尊ぶ 五段・バ行 あがめる。「神を尊ぶ」
10411025 たて 館 * やかた。
1042 たて 楯 * →盾
1043 たて 盾 * 手に持ち攻撃を防ぐ防具。
1026 たて 楯 * (「盾」と区別なし)手に持ち攻撃を防ぐ防具。
1027 たて 盾 * (「楯」と区別なし)手に持ち攻撃を防ぐ防具。
10441028 たてかえる 建て替える 一段 (建物を)つくりなおす。「家を建て替える」
1045 たてかえる 立て替える 一段 他人のかわりにお金を払い、貸しにする。「食事代を立て替える」
1029 たてかえる 立て替える 一段 他人のかわりにお金を払う。「食事代を立て替える」
10461030 たてる 建てる 一段 (建物を)つくる。「ビルを建てる」
1047 たてる 立てる 一段 1. ものを上に向かってまっすぐな状態にする。「看板を立てる」\n2. 波・煙・ちり、またうわさなどを起こす。「波を立てる」「煙を立てる」
1048 たね 胤 * (特に父親の)血筋。また、それを受け継ぐ人。→種
1049 たね 種 * 1. 種子。\n2. 何かを引き起こす原因。「悩みの種」\n3. 題材。ネタ。「うわさの種」\n4. 〈「胤」とも〉(特に父親の)血筋。また、それを受け継ぐ人。
1050 たまう 給う 五段・ワ行促音便 〈「賜う」に同じ〉\n1. 〈文語〉「与える」の尊敬語。「官職を給う」\n2. 〈動詞につく尊敬の助動詞〉なさる。「告げ給う」\n3. 〈動詞につく助動詞〉…なさい。主に命令形で、(時にふざけて)尊大な語気を醸すために使われる。「君の思うことを書きたまえ」
1051 たまう 賜う 五段・ワ行促音便 〈「給う」に同じ〉\n1. 〈文語〉「与える」の尊敬語。「官職を賜う」\n2. (動詞につく尊敬の助動詞)なさる。\n※この用法では「給う」、またはかな書きが多い。
1052 たまご 玉子 * 鶏の卵を料理に使うとき、「卵」の代わりに使われる書き方。「玉子豆腐」(=卵豆腐)
1053 たまご 卵 * 1. さまざまな種類の動物の雌が生む、殻または膜で覆われた球状のもの。適切な環境に置かれると中で子が育ち、殻または膜を破って出てくる。「魚の卵」「卵を産む」\n2. 〈「玉子」とも〉特に、鶏の卵。「卵豆腐」(=玉子豆腐)\n3. 将来、育ってそれになる可能性があるもの。「実業家の卵」
1054 たまる 貯まる 五段・ラ行 金銭的な貯蓄が増える。「貯金が貯まる」
1055 たまる 溜まる 五段・ラ行 〈かな書きも〉排出や消費・解消がされずに残って、一つの場所にものなどが増えていく。「水が溜まる」「不満が溜まる」「ストレスが溜まる」
1056 ためる 矯める 一段 〈文語〉形を直す。矯正する。「弓を矯める」「角を矯めて牛を殺す」(小さいことを直そうとして大きいことをだいなしにする)
1057 ためる 貯める 一段 金銭的な貯蓄を増やす。「お金を貯める」
1058 ためる 溜める 一段 排出や消費・解消をせずに、(意図的または非意図的に)一つの場所にものなどを増やす。「風呂桶にお湯を溜める」「ストレスを溜める」
1031 たてる 立てる 一段 身を起こさせる。「看板を立てる、彼の顔を立てる、煙を立てる」
1032 たね 胤 * 血筋のこと。
1033 たね 種 * 種子。
1034 たまう 給う 五段・ワ行促音便 (動作につく尊敬語。助動詞)なさる。「受け給わりました」
1035 たまう 賜う 五段・ワ行促音便 (「与える」の尊敬語)くださる。「冠を賜う」
1036 たまご 玉子 * にわとりのたまご。
1037 たまご 卵 * 動物(哺乳類を除く)の雌が生み、殻の中に子が入っている。
1038 たまる 貯る 五段・ラ行 財産が増える。「貯金が貯まる」
1039 たまる 溜る 五段・ラ行 ものが集る。「水が溜まる、不満が溜まる」
1040 ためる 矯める 一段 矯正する。「弓を矯める、毒を矯める」
1041 ためる 貯める 一段 (財産を)たくわえる。「お金を貯める」
1042 ためる 溜める 一段 ものを集める。「風呂桶にお湯を溜める」
10591043 たんきゅう 探求 * さがしもとめる。「文化を探求する」
10601044 たんきゅう 探究 * ものごとをさぐり、究めること。「学問を探究する」
10611045 たんこう 炭坑 * 石炭を採掘するためのあな。
1062 たんこう 炭鉱 * 石炭を採掘する鉱山。
1063 たんそ 炭素 * 元素のひとつ。炭の主成分。「炭素繊維」
1064 たんそ 炭疽 * 伝染病のひとつ。「炭疽菌」
1046 たんこう 炭鉱 * 石炭を採掘する場所。
1047 たんそ 炭素 * 元素の一種。「炭素繊維」
1048 たんそ 炭疽 * 伝染病の一種。「炭疽菌」
10651049 ちめい 知名 * 世間的に名前が知られていること。「芸能人の知名度」
10661050 ちめい 知命 * 50歳のこと。
10671051 ちめい 地名 * 土地の名前。
10681052 ちめい 致命 * 命にかかわること。「致命傷」
1069 ちゅうせん 抽選 * くじを引くこと。また、くじを引くなどして意図を加えずに選ぶこと。「抽籤」の書き換え。「抽選で景品を贈る」
1070 ちゅうせん 抽せん * 「抽籤」の書き換え。
1071 ちゅうせん 抽籤 * くじを引くこと。「抽選」「抽せん」と書き換えられることが多い。
10721053 ちょうい 弔意 * 人の死を哀しむこと。「弔意を表わす」
10731054 ちょうい 弔慰 * 人の死を哀しみ、遺族を慰めること。「弔慰金」
1074 ちょうし 調子 * 1. 音程やリズム。「調子の外れた歌」「歌と調子を合わせて踊る」\n2. 言葉の勢い。「きつい調子で非難する」\n3. (良い)状態。コンディション。「調子が出る」「調子が悪い」
1055 ちょうし 調子 * 音程、いきおい。「調子に乗る」
10751056 ちょうし 銚子 * 千葉にある市名。
10761057 ちょうし 長子 * 一番目の子供。
1077 ちょうせい 調整 * 数字や量を変えるなどして、うまくいくように持っていくこと。「日程を調整する」
1078 ちょうせい 調製 * 成分などをきちんと決めてつくること。「調製豆乳」「薬を調製する」
1079 ちょっかん 直感 * 論理的な思考によらない感覚。「自分の直感を信じる」
1080 ちょっかん 直観 * 論理的な思考によらずに理解すること。「直観力がある」
1081 ちょっこう 直交 * 直角に交じわること。「直交する2本の直線」
1082 ちょっこう 直行 * どこにも寄らずに直接行くこと。「直行便」
1083 ついきゅう 追及 * (責任などを)相手に問いただすこと。「責任を追及する」
1058 ちょうせい 調整 * 調子をととのえること。「日程を調整する」
1059 ちょうせい 調製 * 注文に合わせてつくること。
1060 ちょっかん 直感 * すぐに感じたこと。
1061 ちょっかん 直観 * 本質を直接的にとらえること。
1062 ちょっこう 直交 * 直角に交じわること。
1063 ちょっこう 直行 * どこにも寄らずに行くこと。「直行便」
1064 ついきゅう 追及 * (責任などを)強くもとめること。「責任を追及する」
10841065 ついきゅう 追求 * 追いもとめること。「利益を追求する」
1085 ついきゅう 追究 * (学問などを)究めること。「学問を追究する」
1086 つかう 遣う 五段・ワ行促音便 「使う」に同じ。「気を遣う」、また時に「金を遣う」などの形で好んで用いられる。
1087 つかう 使う 五段・ワ行促音便 1. 人やもの・行為を、何かの目的のために役立たせる。「ハサミを使う」「手下を使って嫌がらせをする」「仮病を使って学校を休む」(比喩的に)「気を使う」(=注意を払う)\n2. ついやす。消費する。「ずいぶんと時間を使ってしまった」「金を使いすぎた」
1088 つく 就く 五段・カ行イ音便 〈1 以外は主にかな書き〉\n1. ある立場になる。または、身をおいている。「社長職に就く」\n2. ある状態になる。「眠りにつく」\n3. 〈「着く」とも〉何かをするために、そのための場所に行く。「食卓につく」「床につく」\n4. ある行動を始める。「帰途につく」
1089 つく 衝く 五段・カ行イ音便 「突く」に同じ。「怒髪天を衝く」などの形で好んで用いられる。
1090 つく 着く 五段・カ行イ音便 1. 達する。到着する。「博多に着く」\n2. ある場所を占める。「席に着く」
1091 つく 撞く 五段・カ行イ音便 〈かな書きも〉(鐘などを)棒で叩いて音を鳴らす。「鐘を撞く」
1092 つく 突く 五段・カ行イ音便 1. とがったものの先端を当てる。「剣で敵を突く」\n2. 〈主にかな書き〉支えとなるものを地面に当てる。「杖をつく」\n3. 鋭く指摘する。「意表を突く」\n4. 鋭く刺激する。「鼻を突く」
1093 つく 付く 五段・カ行イ音便 1.離れなくなる。定着する。「汚れが付く」「においが付く」「技術が身に付く」\n2. 近くにいるようになる。「サポートが付く」\n3. 注意をとらえる。「気が付く」「目に付く」
1094 つく 附く 五段・カ行イ音便 →付く
1095 つく 点く 五段・カ行イ音便 〈主にかな書き〉(明かりが)ともる。「電灯がつく」
1096 つく 搗く 五段・カ行イ音便 〈主にかな書き〉やわらかいものを、棒などで強く押す。また、それを繰り返して作る。「米を蒸してつく」「餅をつく」
1066 ついきゅう 追究 * (学問などを)追い、究めること。「学問を追究する」
1067 つかう 遣う 五段・ワ行促音便 こころをはたらかせる。「気を遣う」
1068 つかう 使う 五段・ワ行促音便 役立たせる。「ハサミを使う、随分と時間を使ってしまった」
1069 つく 就く 五段・カ行イ音便 身をおく。「社長職に就く、眠りに就く」
1070 つく 衝く 五段・カ行イ音便 (「突く」も用いる)攻撃する。「意表を衝く、鼻を衝く」
1071 つく 着く 五段・カ行イ音便 到着する。「博多に着く」
1072 つく 撞く 五段・カ行イ音便 (鐘などを)棒で叩いて音を鳴らす。「鐘を撞く」
1073 つく 突く 五段・カ行イ音便 とがったものの先端で叩く。「剣で敵を突く、杖を突く、意表を突く、鼻を突く」
1074 つく 付く 五段・カ行イ音便 (「附く」と区別なし、一般的)はなれなくなる。「汚れが付く、匂いが付く、気が付く、高く付く」
1075 つく 附く 五段・カ行イ音便 (「付く」と区別なし)はなれなくなる。「汚れが附く」
10971076 つぐ 継ぐ 五段・ガ行 継承する。「親の仕事を継ぐ」
1098 つぐ 次ぐ 五段・ガ行 ひとつ下の順位にある。「彼に次いで優秀である」
1099 つぐ 接ぐ 五段・ガ行 くっつけて一体にする。「骨を接ぐ」「枝を接ぐ」
1100 つぐ 注ぐ 五段・ガ行 〈かな書きも〉(一人分の容器に液体や穀類を)入れる。「ビールをコップに注ぐ」「おわんにご飯を注ぐ」
1101 つくる 作る 五段・ラ行 生み出す。こしらえる。製作する。「ホームページを作る」「夕飯を作る」「船を作る」
1102 つくる 造る 五段・ラ行 「作る」に同じ。大きなもの、また酒などを対象とするときに好んで用いられる。「タンカーを造る」
1103 つくる 創る 五段・ラ行 「作る」に同じ。創造的な側面を強調するときに好んで用いられる。「未来を創る」
1077 つぐ 次ぐ 五段・ガ行 次にくる。「彼に次いで優秀である」
1078 つぐ 接ぐ 五段・ガ行 つなぐ。「骨を接ぐ」
1079 つぐ 注ぐ 五段・ガ行 そそぐ。「ビールをコップに注ぐ」
1080 つくる 作る 五段・ラ行 こしらえる。「ホームページを作る、夕飯を作る、嘘を作る」
1081 つくる 造る 五段・ラ行 (工業的なものを)こしらえる。「客船を造る」
11041082 つけこむ 漬け込む 五段・マ行 漬物を仕込む。「大根を漬け込む」
1105 つけこむ 付け込む 五段・マ行 (隙などを)利用する。「弱点に付け込む」
1106 つける 漬ける 一段 液体にひたす。また、そうして保存食を作る。「洗濯物を水に漬ける」「おしんこを漬ける」
1107 つける 点ける 一段 〈主にかな書き〉明かりをともす。「電灯をつける」
1108 つける 付ける 一段 1. はなれないようにする。「バッジを付ける」「印を付ける」\n2. 近くに置く。「サポートを付ける」\n3. 注意を払う。「気を付ける」\n4. 〈かな書きも〉追う。追跡する。「彼の跡を付ける」
1109 つつしむ 謹む 五段・マ行 〈「謹んで」の形で〉うやうやしく。「謹しんでお喜び申し上げます」
1110 つつしむ 慎む 五段・マ行 気をつける。慎重におこなう。少なめにする、またはやめる。「言葉を慎しむ」「飲酒を慎む」「コメントを慎む」
1083 つけこむ 付け込む 五段・マ行 (すきなどを)利用して何かをする。「隙に付け込む」
1084 つける 漬ける 一段 液体にひたす。「洗濯物を水に漬ける、おしんこを漬ける」
1085 つける 点ける 一段 点火、点灯する。「明かりを点ける、火を点ける」
1086 つける 付ける 一段 はなれないようにする。「バッジを付ける、印を付ける、気を付ける、後を付ける」
1087 つつしむ 謹む 五段・マ行 かしこまる。「謹しんで」
1088 つつしむ 慎む 五段・マ行 用心する。「身を慎しむ」
11111089 つとめる 勤める 一段 勤務する。「大学に勤めている」
1112 つとめる 努める 一段 努力する。「学力向上に努める」
1113 つとめる 勉める 一段 →努める
1090 つとめる 努める 一段 (「勉める」と区別なし、一般的)努力する。「学力向上に努める」
1091 つとめる 勉める 一段 (「努める」と区別なし)努力する。「学力向上に勉める」
11141092 つとめる 務める 一段 役目を担う。「大役を務める」
1115 つむ 詰む 五段・マ行 1. 将棋で、王将を動かせる場所がなくなる。「あっけなく詰んでしまった」\n2. 〈口語〉どうしようもない状況に陥る。「ゲームで強い敵に囲まれて、詰んだと思ってリセットした」
1116 つむ 積む 五段・マ行 1. ものを上に重ねる。「まきを積む」\n2. 何かを行なって得た経験などを、自分のものとして身につける。「経験を積む」\n3. 運ぶために、乗り物などに載せる。「トラックに砂利を積む」\n4. 部品としてもつ。搭載する。「最速CPUを積んだパソコン」
1117 つむ 摘む 五段・マ行 (花などを)指先でつまんで、根元から切ってとる。「花を摘む」
1118 つりだす 吊り出す 五段・サ行 1. →釣り出す\n2. (相撲で)相手を持ちあげて外にだす。「相手の力士を吊り出す」
1119 つりだす 釣り出す 五段・サ行 相手のほしがるもので誘い出す。「エサで釣り出す」
1120 つる 攣る 五段・ラ行 〈主にかな書き〉ひきつって動かせなくなる。「海の中で足がつった」
1121 つる 吊る 五段・ラ行 高いところから垂れ下げる。つるす。「ハンモックを吊る」「首を吊る」(=首にひもを回して自分の体を吊るすことで自殺を図る)
1122 つる 釣る 五段・ラ行 1. 魚を針にひっかけてとる。「魚を釣る」\n2. 相手のほしがるもので誘う。「おまけで客を釣る」
1123 ていする 呈する サ変・−スル 1. (状態などを)示す。「惨状を呈している」\n2. 〈「苦言を呈する」の形で〉述べる。\n3. 〈文語〉差し出す。
1124 ていする 挺する サ変・−スル 〈「身を挺する」の形で〉すすんで差し出す。
1125 ていする 訂する サ変・−スル 〈文語〉訂正する。
1126 ていじ 呈示 * 持っているものを相手に見せる。「チケットを呈示する」\n※「提示」が一般的。
1127 ていじ 提示 * 1. 持っているものを相手に見せる。「チケットを提示する」\n※「呈示」とも。\n2. 提案として示す。「条件を提示する」
1128 てっこう 鉄工 * 〈主に複合語で〉鉄を使って工作をすること。「鉄工所」
1093 つむ 詰む 五段・マ行 すきまがなくなる。「将棋で詰む」
1094 つむ 積む 五段・マ行 上に重ねる。「木を積む、金を積む」
1095 つむ 摘む 五段・マ行 (花などを)手でとる。「花を摘む」
1096 つりだす 吊り出す 五段・サ行 そそのかす、(相撲で)相手を持ちあげて外にだす。「相手の力士を吊り出す」
1097 つりだす 釣り出す 五段・サ行 そそのかす。「エサで釣り出す」
1098 つる 吊る 五段・ラ行 つるす。「首を吊る、足が吊る」
1099 つる 釣る 五段・ラ行 魚を針にひっかけてとる。「魚を釣る、値段を釣り上げる」
1100 てい 呈 * (文語)さしだす。「苦言を呈する」
1101 てい 挺 * (文語)先に行なう。「身を挺する」
1102 てい 訂 * (文語)訂正する。
1103 ていじ 呈示 * さしだして見せること。「チケットを呈示する」
1104 ていじ 提示 * 提出して示すこと。「証明書を提示する」
1105 てっこう 鉄工 * 鉄でつくるもの。「鉄工所」
11291106 てっこう 鉄鉱 * 鉄の原料となる鉱石。「鉄鉱石」
1130 てっこう 鉄鋼 * 銑鉄(せんてつ)・鋳鉄・鋼鉄などの総称。「鉄鋼業」
1131 てんい 転位 * 〈主に体内での〉位置が変わること。「骨折部の転位」
1132 てんい 転移 * 〈がんなどが〉他の場所で発生するようになること。「がんが転移する」
1133 てんか 転化 * 移り変わること。変化。「意味が転化する」「憧れが憎しみに転化する」
1107 てっこう 鉄鋼 * 鋼の総称。「鉄鋼業」
1108 てらう 衒う 五段・ワ行促音便 ひけらかす。「奇を衒う」
1109 てらす 照らす 五段・サ行 光をあてる。「暗闇を照らす、解答と照らしあわせる」
1110 てんい 転位 * 位置がかわること。
1111 てんい 転移 * 場所がうつること。「ガンが転移する」
1112 てんか 転化 * 移りかわること。「意味が転化する」
11341113 てんか 転嫁 * (責任などを)なすりつけること。「責任を転嫁する」
1135 てんしん 転身 * 職業などを変えること。「転身して農家になった」
1136 てんしん 転進 * 進路や拠点を変えること。「北に転進する」
1137 てんずる 転ずる サ変・−ズル 1. (状態などを)変える。(状態などが)変わる。「攻勢に転ずる」「好況に転ずる」\n2. (単語の形や意味が)変化する。「あばら肉が転じてバラ肉と呼ばれるようになった」
1138 てんずる 点ずる サ変・−ズル 〈文語〉\n1. (火を)つける。(明かりを)ともす。「香に火を点じる」\n2. (茶を)たてる。
1139 とう 問う 五段・ワ行ウ音便 1. 〈文語的〉人に聞く。質問する。「年齢を問う」\n2. 〈主に受身で〉(人の資質などが)試される。「首相としての資質が問われる」\n3. 〈否定形で〉条件にする。「男女問わず採用する」\n4. 〈主に受身で〉疑問を投げかける。疑う。「実効性を問われる」「罪に問われる」(=犯罪の嫌疑をかけられる)
1140 とうか 投下 * 投げ落とすこと。「爆弾を投下する」
1141 とうか 透過 * 透き通ること。「明かりが透過する」
1114 てんしん 転身 * 職業などをかえること。「転身して農家になった」
1115 てんしん 転進 * 進路をかえること。「北に転進する」
1116 てんずる 転ずる サ変・−ズル (文語)まわる。「攻勢に転ずる」
1117 てんずる 点ずる サ変・−ズル (文語)点をうつ。「目薬を点ずる」
1118 とう 問う 五段・ワ行ウ音便 質問する。「年齢を問う、首相としての資質を問う」
1119 とうか 投下 * 投げおとすこと。「爆弾を投下する」
1120 とうか 透過 * すきとおること。「明かりが透過する」
11421121 とうかい 倒壊 * 倒れ壊れること。「ビルが倒壊する」
1143 とうかい 韜晦 * 自分の地位や本心などを隠すこと。
1122 とうかい 韜晦 * 自己の才能を隠すこと。
11441123 とうき 登記 * 土地などの権利を登記簿に記すこと。「登記簿」
11451124 とうき 投棄 * 投げすてること。「不法投棄」
1146 とうき 騰貴 * (物価などが)上がること。「物価が騰貴する」
1147 とうこう 登校 * 授業を受けるため、または勤務するために学校に行くこと。「大学に登校する」「登校拒否」
1148 とうこう 投稿 * 原稿を募集しているところに、それを送ること。「雑誌に投稿する」「投稿写真」
1149 とうこう 投降 * 戦いつづけることをあきらめ、降参すること。「犯人が説得に応じて投降する」
1150 とうさく 倒錯 * (特に性的な欲求などが)本来の形から外れること。
1151 とうさく 盗作 * 他人の作品を、自分の作品の全部または一部として勝手に使うこと。また、そうして作った作品。「彼の曲を盗作する」「この小説は明らかな盗作だ」
1125 とうき 騰貴 * 物価などが高くなること。「物価が騰貴する」
1126 とうこう 登校 * 学校に行くこと。「大学に登校する、登校拒否」
1127 とうこう 投稿 * 原稿を送ること。「雑誌に投稿する、投稿写真」
1128 とうこう 投降 * 降参すること。「犯人が説得に応じて投降する」
1129 とうさく 倒錯 * 逆になること。
1130 とうさく 盗作 * 他人の作品を自分の作品とすること。「彼の曲を盗作する」
11521131 とうし 凍死 * 凍えて死ぬこと。「雪山で凍死する」
1153 とうし 投資 * 将来の利益のために、事業などに資金を出したり、努力を傾けたりすること。「株に投資する」「自分自身に投資する」
1154 とうし 透視 * さえぎるものの向こう側を、何らかの方法で見ること。「X線による透視」「紙に書かれていることを透視する」
1155 とうし 闘士 * たたかう人。「独立運動の闘士」
1156 とうし 闘志 * たたかう意志。「闘志が湧く」
1157 とうとい 貴い 形容詞・アウオ段 高貴・貴重・崇高であるさま。特に、高貴であるさま。「貴い身分」
1158 とうとい 尊い 形容詞・アウオ段 高貴・貴重・崇高であるさま。特に、貴重・崇高であるさま。「尊い生命」「尊い使命」
1159 とうとぶ 貴ぶ 五段・バ行 →尊ぶ
1160 とうとぶ 尊ぶ 五段・バ行 〈「貴ぶ」とも〉\n1. あがめる。「神を尊ぶ」\n2. 大切にする。「人権を尊ぶ」
1161 とうよう 登用 * 人を採用すること。また、要職につけること。「若者を登用する」
1162 とうよう 当用 * 当面用いること。また、当面の用事。
1163 とかす 融かす 五段・サ行 〈「溶かす」とも。氷・雪などに対しては「解かす」とも〉固体に熱を加えるなどして、液体にする。「鉄を融かす」
1164 とかす 解かす 五段・サ行 1. 〈「融かす」「溶かす」とも〉(氷・雪などを)水にする。「氷を解かす」\n2. くしなどで髪の毛を整える。「髪を解かす」
1165 とかす 溶かす 五段・サ行 1. 粉などを液体に入れ、まぜて一様な液体にする。「小麦粉を水に溶かす」\n2. 液体の性質によって固体を分解する。「金属を塩酸で溶かす」\n3. 〈「融かす」とも。氷・雪などに対しては「解かす」とも〉固体に熱を加えるなどして、液体にする。「鉄を溶かす」
1166 とく 解く 五段・カ行イ音便 1. ほどく。ほどいて開ける。「結び目を解く」「包装を解く」\n2. くしなどで髪の毛を整える。とかす。\n3. 対話などの手段で解消する。「誤解を解く」\n4. (緊張している状態などを)ゆるめ、なくす。「包囲を解く」\n5. 答えを出す。「謎を解く」
1132 とうし 投資 * 事業に資金を出すこと。「株に投資する」
1133 とうし 透視 * すかし見ること。「紙に書かれていることを透視する」
1134 とうし 闘士 * 闘う人。
1135 とうし 闘志 * 闘う意志。「闘志が湧く」
1136 とうとい 貴い 形容詞・アウオ段 高貴である様。「貴い身分」
1137 とうとい 尊い 形容詞・アウオ段 尊敬できる様。「尊い神」
1138 とうとぶ 貴ぶ 五段・バ行 大切にする。「人権を貴ぶ」
1139 とうとぶ 尊ぶ 五段・バ行 あがめる。「神を尊ぶ」
1140 とうよう 登用 * 人を要職で用いること。「若者を登用する」
1141 とうよう 当用 * 当面の用事。
1142 とかす 解かす 五段・サ行 (氷などを)水にする。「氷を解かす」
1143 とかす 溶かす 五段・サ行 粉などを液体に入れ、まぜて一様な液体にする。「小麦粉を水に溶かす」
1144 とく 解く 五段・カ行イ音便 ほどく。「結び目を解く、包囲を解く、問題を解く、誤解を解く」
11671145 とく 説く 五段・カ行イ音便 説明する。「仏教の教えを説く」
1168 とく 溶く 五段・カ行イ音便 粉などを液体に入れ、まぜて一様な液体にする。とかす。「小麦粉を水に溶く」
1169 とくする 得する サ変・−スル もうける。「くじに当たって得をした」
1170 とくする 督する サ変・−スル 〈文語〉監督する。
1146 とく 溶く 五段・カ行イ音便 粉などを液体に入れ、まぜて一様な液体にする。「小麦粉を水に溶く」
1147 とく 得 * もうける。「くじに当たって得をした」
1148 とく 督 * (文語)監督する。
11711149 とくせい 特性 * そのものが持つ特別な性質。「自己相似特性」
11721150 とくせい 特製 * 特別につくること。「特製のケーキ」
11731151 とくちょう 特徴 * 特別に目立つところ。「特徴のある顔立ち」
1174 とくちょう 特長 * 特別にすぐれたこと。「本製品の特長」
1175 とける 融ける 一段 〈「溶ける」とも。氷・雪などに対しては「解ける」とも〉固体に熱が加わるなどして、液体になる。「鉄が融ける」
1176 とける 解ける 一段 1. 〈「融ける」「溶ける」とも〉(氷・雪などが)水になる。「氷が解ける」\n2. ほどける。「結び目が解ける」\n3. (感情的なしこりなどが)解消される。「誤解が解ける」「怒りが解ける」\n4. (緊張している状態などが)ゆるみ、なくなる。「包囲が解ける」\n5. 答えが出る。「謎が解ける」
1177 とける 溶ける 一段 1. 粉などが液体にまざって一様な液体になる。「砂糖が水に溶ける」\n2. 液体の性質によって固体が分解される。「塩酸に溶ける金属」\n3. 〈「融ける」とも。氷・雪などに対しては「解ける」とも〉固体に熱が加わるなどして、液体になる。「鉄が溶ける」
1178 とじる 綴じる 一段 〈かな書きも〉\n1. 紙をひもなどで一つにまとめる。「文集をひもで綴じる」\n2. 〈主にかな書き〉料理の具材に卵をかけ、熱してゆるく固める。「カキフライを卵でとじる」
1179 とじる 閉じる 一段 1. 閉まる。「ドアが閉じる」\n2. 閉める。「店を閉じる」
1180 ととのう 整う 五段・ワ行促音便 1. きちんとした状態になる。「髪型が整う」\n2. 欠けがなく、準備のできた状態になる。「準備が整う」「書類が整う」
1181 ととのう 調う 五段・ワ行促音便 →整う
1182 ととのえる 整える 一段 1. きちんとした状態にする。「髪型を整える」\n2. 欠けのない、準備のできた状態にする。「準備を整える」「書類を整える」\n3. 〈「調える」とも〉(味などを)加減してちょうどいい状態にする。「塩コショウで味を整える」
1183 ととのえる 調える 一段 〈「整える」とも〉(味などを)加減してちょうどいい状態にする。「塩コショウで味を調える」
1184 とぶ 跳ぶ 五段・バ行 地面をけって、はねるように空中に上がる。また、そのようにしてものを乗り越える。「カエルのように跳ぶ」「ハードルを跳ぶ」
1185 とぶ 飛ぶ 五段・バ行 1. 空中を移動する。「飛行機が飛ぶ」\n2. 緊急にある場所にかけつける。「現場に飛ぶ」\n3. 蒸発するようになくなる。消える。「記憶が飛ぶ」「炭酸が飛ぶ」\n4. 抜けがある。「日記の日付が一日飛んでいる」
1186 とまる 止まる 五段・ラ行 1. 動かなくなる。または、流れがなくなる。「車が止まる」「計算機が止まる」「息が止まる」\n2. 飛んでいた虫や鳥などが、身を支える場所につかまってそこにとどまる。「ハエが壁に止まった」
1187 とまる 泊まる 五段・ラ行 夜を過ごす。宿泊する。「友達の家に泊まる」
1188 とまる 留まる 五段・ラ行 〈「止まる」とも〉〈かな書きも〉\n1. 固定される。「画鋲(がびょう)で留まっている」「ボタンがなかなか留まらない」\n2. 〈「目に留まる」として〉注意をよぶ。
1189 とまる 停まる 五段・ラ行 (車などが)動きを止める。→止まる
1190 とめる 止める 一段 動かなくする。または、流れなくする。「車を止める」「計算機を止める」「息を止める」
1191 とめる 停める 一段 1. (車などを)動かなくする。「赤信号で車を停める」→止める\n2. 駐車する。「駐車場に車を停める」
1192 とめる 泊める 一段 夜を過ごさせる。宿泊させる。「友達を自宅に泊める」
1193 とめる 留める 一段 〈「止める」とも〉〈かな書きも〉\n1. 固定する。「貼り紙を画鋲(がびょう)で留める」\n2. 注意を払う。「気を留める」
1194 とら 虎 * ネコ科の大型動物。「虎の威を借る狐」
1195 とら 寅 * 干支(えと)の一つ。丑(うし)の次、卯(う)の前。
1152 とくちょう 特長 * 特別にすぐれたこと。
1153 とける 融ける 一段 融解する。「氷が融ける」
1154 とける 熔ける 一段 (金属などが)溶解する。「鉄塊が熔ける」
1155 とじる 綴じる 一段 紙を紐などで一つにまとめる。「文集を紐で綴じる」
1156 とじる 閉じる 一段 しまる。「ドアが閉じる、店を閉じる」
1157 ととのう 整う 五段・ワ行促音便 整理された状態になる。「部屋が整う」
1158 ととのう 調う 五段・ワ行促音便 そろう。「準備が調う」
1159 ととのえる 整える 一段 整理する。「部屋を整える」
1160 ととのえる 調える 一段 そろえる。「準備を調える」
1161 とぶ 跳ぶ 五段・バ行 足でとびあがる。「ハードルを跳ぶ」
1162 とぶ 飛ぶ 五段・バ行 空に舞う。「飛行機が飛ぶ、現場に飛ぶ、記憶が飛ぶ」
1163 とまる 止まる 五段・ラ行 動かなくなる。「車が止まる、計算機が止まる、息が止まる」
1164 とまる 泊まる 五段・ラ行 宿泊する。「友達の家に泊まる」
1165 とまる 留まる 五段・ラ行 固定される。「画鋲で留まっている、目に留まる」
1166 とめる 止める 一段 (一般的)動かなくする。「車を止める、計算機を止める、息を止める」
1167 とめる 停める 一段 動かなくする。停止、停車。「車を停める」
1168 とめる 泊める 一段 宿泊させる。「友達を自宅に泊める」
1169 とめる 留める 一段 固定する。「貼り紙を画鋲で留める」
1170 とら 虎 * ネコ科の動物。「虎の威を借る狐」
1171 とら 寅 * 干支の一つ。「フーテンの寅さん」
11961172 とり 鳥 * 鳥類の総称。「飛ぶ鳥あとを濁さず」
1197 とり 酉 * 干支(えと)の一つ。申(さる)の次、戌(いぬ)の前。「お酉さま」
1198 とる 採る 五段・ラ行 〈「取る」とも〉\n1. (人を)採用する。「新人を採る」\n2. (方針などを)採択する。選んでそれを実行する。「親米路線を採る」\n3. 採取する。「木の実を採る」
1173 とり 酉 * 干支の一つ。「お酉さま」
1174 とる 採る 五段・ラ行 採取、採択する。「血液を採る、新人を採る」
11991175 とる 撮る 五段・ラ行 撮影する。「写真を撮る」
1200 とる 取る 五段・ラ行 〈採る・摂る・捕る・執るも参照〉\n1. 手でつかむ。「ボールを取る」\n2. 自分のものにする。確保する。「免許を取る」「予約を取る」「人のカバンを取る」\n※「盗む」の意味では「盗る」とも書く。\n3. (離れた店に食べ物を)注文して持ってこさせる。「店屋物を取る」\n4. なくす。取り除く。「水気を取る」\n5. (代価などを)求める。「水を飲むのにも金を取られる」\n6. さまざまな単語と組み合わせて、「調整する」などの意味で使う。「バランスを取る」「機嫌を取る」
1201 とる 摂る 五段・ラ行 〈「取る」とも〉(栄養などを)摂取する。「鉄分を摂る」
1202 とる 盗る 五段・ラ行 〈「取る」とも〉盗む。「人のカバンを盗る」
1203 とる 捕る 五段・ラ行 〈「取る」とも〉つかまえる。「ハエを捕る」
1204 とる 執る 五段・ラ行 〈「取る」とも〉\n1. 手に持つ。「筆を執る」\n2. おこなう。「指揮を執る」
1176 とる 取る 五段・ラ行 つかむ。「ボールを取る、免許を取る、機嫌を取る、予約を取る、取り急ぎ」
1177 とる 盗る 五段・ラ行 ぬすむ。「ハンドバックを盗る」
1178 とる 捕る 五段・ラ行 つかまえる。「ハエを捕る」
12051179 ない 無い 形容詞・アウオ段 存在しない。「お金が無い」
1206 ないしん 内申 * 内申書の略。上級学校を受験する際、その人についての諸情報を当該校に伝えるために出身下級学校が作成する書類。
1207 ないしん 内診 * 婦人科等で、女性器の内部を診察すること。「内診台」
1208 なおす 治す 五段・サ行 (病気やけがなどを)治療する。「風邪を治す」
1209 なおす 直す 五段・サ行 元の状態、または望ましい状態にする。「故障車を直す」「くせを直す」「機嫌を直す」「誤字を直す」
1180 ないしん 内申 * 内々に申すこと。「内申書」
1181 ないしん 内診 * 患者の自宅で診察すること。
1182 なおす 治す 五段・サ行 (病気などを)治療する。「風邪を治す」
1183 なおす 直す 五段・サ行 元通りにする。「故障車を直す、くせを直す、機嫌を直す」
12101184 なおる 治る 五段・ラ行 (病気などから)回復する。「風邪が治る」
1211 なおる 直る 五段・ラ行 元の状態、または望ましい状態になる。「故障車が直る」「くせが直る」「機嫌が直る」「誤字が直っている」
1212 なか 中 * ものの内部や中間、空間の内部、時間の間。また、できごとのさなか。「暗闇の中」「大雨の中駆けつける」「中6日の登板」
1213 なか 仲 * 人などとの関係。「彼との仲」「仲のいい友人」
1214 ながい 永い 形容詞・アウオ段 時間が非常に長い、または永遠であることを示すために、「長い」の代わりに使われる。「永い冬」→長い
1215 ながい 長い 形容詞・アウオ段 (細いものの)幅が大きい。または、時間が長期にわたる。「長い柱」「長い時間」
1185 なおる 直る 五段・ラ行 元通りになる。「故障車が直る、くせが直る、機嫌が直る」
1186 なか 中 * ものの内部。「暗闇の中、中6日の登板」
1187 なか 仲 * 人などとの関係。「彼との仲、仲のいい友人」
1188 ながい 永い 形容詞・アウオ段 (時間が)永遠である。「永い時間」
1189 ながい 長い 形容詞・アウオ段 (距離などが)おおきい。「長い距離」
12161190 なかま 中間 * 福岡県にある市名。
1217 なかま 仲間 * 共になにかをする人の集まり。「飲み仲間」「仲間割れ」
1191 なかま 仲間 * 共になにかをする人の集り。「飲み仲間、仲間割れ」
12181192 なぎ 凪 * 風がない状態。「夕凪」
1219 なぎ 薙 * 〈文語〉山の崩れている場所。
1220 なく 泣く 五段・カ行イ音便 1. 涙を流す。「映画を見て泣く」\n2. 苦労する。「一円を笑うものは一円に泣く」
1221 なく 鳴く 五段・カ行イ音便 1. (動物などが)声をあげる。「にわとりが鳴く」\n2. (麻雀で)ルールに従い、他の参加者から牌(パイ)をもらう。
1222 なく 啼く 五段・カ行イ音便 〈普通「鳴く」〉(特に野鳥が)声をあげる。「ほととぎすが啼く」
1223 なく 哭く 五段・カ行イ音便 〈普通「泣く」〉\n1. 人が大声をあげてなげき悲しむ。\n2. →鳴く2
1193 なぎ 薙 * 山の崩れている場所。
1194 なく 泣く 五段・カ行イ音便 涙を流す。「映画を見て泣く、一円を笑うものは一円に泣く」
1195 なく 鳴く 五段・カ行イ音便 (「啼く」と区別なし、一般的)(動物などが)声をあげる。「にわとりが鳴く」
1196 なく 啼く 五段・カ行イ音便 (「鳴く」と区別なし)(動物などが)声をあげる。「にわとりが啼く」
1197 なぐ 凪ぐ 五段・ガ行 風がやんだ状態。「夕凪」
1198 なぐ 薙ぐ 五段・ガ行 山の崩れた場所。
12241199 なくす 亡くす 五段・サ行 (人に)死なれる。「親を亡くす」
1225 なくす 無くす 五段・サ行 1. うっかりして失う。紛失する。「財布を無くす」\n2. 取り去る。ないようにする。「痛みをなくす」
1226 なくなる 亡くなる 五段・ラ行 〈尊敬語〉死ぬ。「先生が亡くなる」
1227 なくなる 無くなる 五段・ラ行 1. うっかりして失われる。「財布が無くなる」\n2. 消える。ないようになる。「痛みがなくなる」
1228 なす 為す 五段・サ行 〈文語〉〈「成す」とも〉する。「善行を為す」
1229 なす 成す 五段・サ行 〈文語〉\n1. 作り上げる、または成し遂げる。「財を成す」「名を成す」(=有名になる)\n2. 構成する。「根幹を成す」
1230 なめす 鞣す 五段・サ行 〈主にかな書き〉動物の表皮に加工して、柔らかくしたり耐久性をもたせたりする。「皮をなめす」
1231 なめる 嘗める 一段 →舐める
1232 なめる 舐める 一段 〈かな書きも〉\n1. 舌で表面をなでる。また、そのようにして食べる。「アメを舐める」\n2. 軽く見る。「彼を舐めてかかる」
1233 ならす 慣らす 五段・サ行 1. なじませる。「肩を慣らす」\n2. (動物などを)慣れるようにする。かいならす。「シカを慣らす」
1234 ならす 均す 五段・サ行 〈主にかな書き〉均等にする。「土をならす」
1235 ならす 鳴らす 五段・サ行 音をさせる。「笛を鳴らす」
1236 ならぶ 並ぶ 五段・バ行 1. 列をつくる。「ラーメン屋に並ぶ」\n2. 同等になる。「彼に並ぶ記録」
1237 なる 成る 五段・ラ行 1. うまくいく。成就する。「為せば成る」\n2. 〈主にかな書き〉構成される。「三つの要素からなる」\n3. 〈主にかな書き〉かわる。達する。「冬になる」
1238 なる 鳴る 五段・ラ行 音が出る。「鐘が鳴る」
1239 なれる 慣れる 一段 1. 繰り返し、または長期間触れることで普通に、または快適に感じるようになる。なじむ。また、それによって上達する。「日本の生活に慣れる」「目が慣れる」「機器の操作に慣れる」\n2. 〈「馴れる」とも〉動物が、人間を警戒しなくなる。
1240 なれる 熟れる 一段 〈文語〉熟成する。「味噌が熟れる」
1241 なれる 馴れる 一段 〈「慣れる」とも〉動物が、人間を警戒しなくなる。
1242 なれる 狎れる 一段 〈文語〉打ち解けすぎる。
1200 なくす 無くす 五段・サ行 うしなう。「財布を無くす」
1201 なくなる 亡くなる 五段・ラ行 しぬ。「先生が亡くなる」
1202 なくなる 無くなる 五段・ラ行 知らぬまにうしなう。「財布が無くなる」
1203 なす 為す 五段・サ行 (文語)する。「善行を為す」
1204 なす 成す 五段・サ行 (文語)つくりあげる。「名を成す」
1205 なめす 鞣す 五段・サ行 毛皮の毛を除き柔らかくする。「皮を鞣す」
1206 なめる 嘗める 一段 舌先で触れる。「アメを嘗める、彼を嘗めてかかる」
1207 ならす 慣らす 五段・サ行 慣れさせる。「肩を慣らす」
1208 ならす 均す 五段・サ行 均等にする。「土を均す」
1209 ならす 鳴らす 五段・サ行 音をさせる。「フエを鳴らす」
1210 ならぶ 並ぶ 五段・バ行 列をつくる。「ラーメン屋に並ぶ、彼に並ぶ記録」
1211 なる 成る 五段・ラ行 こうせいされる。「三つの要素から成る、しては成らない」
1212 なる 鳴る 五段・ラ行 音がする。「鐘が鳴る、腕が鳴る」
1213 なれる 慣れる 一段 めずらしくなくなる。「日本の生活に慣れる」
1214 なれる 熟れる 一段 熟成する。「味噌が熟れる」
1215 なれる 馴れる 一段 なじみになる。「目が馴れる」
1216 なれる 狎れる 一段 うちとけすぎる。「平和に狎れる」
12431217 におう 臭う 五段・ワ行促音便 悪いにおいがする。「トイレが臭う」
12441218 におう 匂う 五段・ワ行促音便 よいにおいがする。「香水が匂う」
1245 にくい 憎い 形容詞・アウオ段 1. 強く嫌いに思うようす。「憎い犯人」\n2. 好ましい。「憎い心遣い」
1246 にくい 難い 形容詞・アウオ段 〈連用形に続けて〉〈主にかな書き〉困難である。「走りにくい靴」
1247 にくむ 憎む 五段・マ行 強く嫌う。憎悪する。「犯人を憎む」
1219 にくい 憎い 形容詞・アウオ段 腹が立つさま。「憎い犯人」
1220 にくい 難い 形容詞・アウオ段 困難であるさま。「走り難い靴」
1221 にくい 難い 形容詞・アウオ段 困難であるさま。「この靴は走り難い」
1222 にくむ 憎む 五段・マ行 腹がたつ。「犯人が憎い」
12481223 にる 似る 一段 同じように見える。「似ている親子」
12491224 にる 煮る 一段 (食材を)水に入れて熱を通す。「大根を煮る」
1250 ねんとう 年頭 * 年の初め。
1225 ねんとう 年頭 * としはじめ。
12511226 ねんとう 念頭 * 考え。「今言ったことを念頭に置く」
1252 ねんぽう 年俸 * 年ごとの給料。「年俸制」
1227 ねんぽう 年俸 * 年毎の給料。「年俸制」
12531228 ねんぽう 年報 * 年次の報告。
1254 のける 除ける 一段 〈主にかな書き〉\n取り除く。「いらないものをのける」
1255 のける 退ける 一段 〈主にかな書き〉〈複合語で〉\nしりぞける。「人を押しのけて進む」
1256 のせる 載せる 一段 1. 〈「乗せる」とも〉運ぶためにものを乗り物の上や中に置く。「車を船に載せる」\n2. 部品としてもたせる。搭載する。「最新CPUを載せたパソコン」\n3. 出版物などに掲載・記載する。「雑誌に記事を載せる」
1257 のせる 乗せる 一段 1. 人を乗り物に入れて移動させる。「ちょっとそこまで乗せてください」\n2. 移動する媒体や経路に入れる。「流れに乗せる」「軌道に乗せる」\n3. 〈「載せる」とも〉何かのすぐ上に置く。「魚を皿に乗せる」\n4. ほめて調子づかせる。「調子に乗せる」「人を乗せるのがうまい」
1258 のぞく 除く 五段・カ行イ音便 取りのける。取り除く。「嫌いなものを除く」
1259 のぞく 覗く 五段・カ行イ音便 〈かな書きも〉\n1. 見えにくいもの、隠されているものを見る。「節穴から中を覗く」「部屋を覗く」\n2. 見えにくいもの、隠されているものがふと見える。「結い上げた髪からうなじが覗く」\n3. ふと立ち寄る。「講義を覗く」「中古屋を覗く」
1260 のぞむ 望む 五段・マ行 1. 希望する。「転勤を望む」\n2. 遠くに見る。「遠くの山々を望む」
1261 のぞむ 臨む 五段・マ行 1. (ある状況に)当たる。目の前にする。「手術に臨む」「試合に臨む」「毅然たる態度で臨む」\n2. (場所を)目の前にする。「海に臨む家」
1262 のっとる 乗っ取る 五段・ラ行 〈否定的な意味合いで〉支配下に置く。「飛行機を乗っ取る」「コンピュータを乗っ取る」「会社を乗っ取る」
1263 のっとる 則る 五段・ラ行 決められたことに従う。「規則に則って行う」
1264 のばす 延ばす 五段・サ行 1. 時間を遅らせる。延期する。「締め切りを延ばす」「出発を延ばす」\n2. 〈「伸ばす」とも〉既存のものに付け加えて長くする。「路線を延ばす」
1265 のばす 伸ばす 五段・サ行 1. 長くする。「爪を伸ばす」「路線を伸ばす」\n2. まっすぐにする。「背筋を伸ばす」「しわを伸ばす」\n3. 勢いなどを増やす。「勢力を伸ばす」
1266 のびる 延びる 一段 1. 時間が遅れる。延期される。「締め切りが延びる」「出発が延びた」\n2. 〈「伸びる」とも〉既存のものに付け加えられて長くなる。「路線が延びる」
1267 のびる 伸びる 一段 1. 長くなる。「爪が伸びる」「路線が伸びる」\n2. まっすぐになる。「背筋が伸びる」「しわが伸びる」\n3. 勢いなどが増える。「勢力が伸びる」
1268 のべる 延べる 一段 〈文語〉→延ばす。「出発を延べる」
1229 のける 除ける 一段 取り除く。「いらないものを除ける」
1230 のける 退ける 一段 しりぞかす。「通行人を退ける、」
1231 のせる 載せる 一段 上に置く、記載する。「本を机の上に載せる、雑誌に記事を載せる」
1232 のせる 乗せる 一段 乗り物の中に入れる。「子供をバスに乗せる、口車に乗せる、調子に乗せる」
1233 のぞく 除く 五段・カ行イ音便 取り除く。「嫌いなものを除く」
1234 のぞく 覗く 五段・カ行イ音便 すきまから見る。「部屋を覗く、講義を覗く、中古屋を覗く」
1235 のぞむ 望む 五段・マ行 ながめる。「遠くの山々を望む、転勤を望む」
1236 のぞむ 臨む 五段・マ行 目の前にする。「海に臨む家、試験に臨む」
1237 のっとる 乗っ取る 五段・ラ行 占拠する。「飛行機を乗っ取る、コンピュータを乗っ取る」
1238 のっとる 則る 五段・ラ行 ならう。「規則に則って」
1239 のばす 延ばす 五段・サ行 延期、延長する。「締め切りを延ばす、出発を延ばす、路線を延ばす」
1240 のばす 伸ばす 五段・サ行 長くする。「爪を伸ばす、背筋を伸ばす、勢力を伸ばす」
1241 のびる 延びる 一段 延期、延長される。「締め切りが延びた、出発が延びる、路線が延びる」
1242 のびる 伸びる 一段 長くなる。「爪が伸びる、背筋が伸びる、勢力が伸びる」
1243 のべる 延べる 一段 (文語)延期する。「出発を延べる」
12691244 のべる 述べる 一段 言う。「進捗状況について述べる」
1270 のべる 伸べる 一段 〈文語〉\n1. →伸ばす。\n2. 〈「手を伸べる」として〉手をさし出す。「救いの手を伸べる」
1271 のぼる 昇る 五段・ラ行 〈「上る」とも〉まっすぐ上にあがる。上昇する。「日が昇る」「頭に血が昇る」
1272 のぼる 上る 五段・ラ行 1. 低いところから高いところに、または周辺とされる場所から中心に行く。「坂を上る」「川を上る」「日が上る」「頭に血が上る」\n※まっすぐ上がる場合は「昇る」とも書く。\n2. 数量が大きくなる。「予算が3億円に上る」\n3. 話などにとりあげられる。「話題に上る」
1273 のぼる 登る 五段・ラ行 人や動物が、主に手足を使って高い場所に行く。「富士山に登る」「木に登る」
1274 のむ 飲む 五段・マ行 1. 液体を喉から体内に入れる。また、特に酒についてそれを行う。「水を飲む」「酒を飲む」「彼と飲みに行く」\n2. 固形物を喉から体内に入れる。「錠剤を飲む」\n3. (たばこなどを)吸う。「たばこを飲む」「アヘンを飲む」\n4. (相手の条件を)受け入れる。「要求を飲む」\n5. 圧倒する。「雰囲気に飲まれて契約した」\n6. (涙や息を)こらえる。止める。「涙を飲んで撤退する」「その光景に息を飲んだ」\n※1の酒について、また2〜6については「呑む」とも。
1275 のむ 呑む 五段・マ行 →飲む
1276 のる 載る 五段・ラ行 1. 〈「乗る」とも〉何かのすぐ上に置かれる。「魚が皿に載っている」\n2. 〈「乗る」とも〉ものが、運ぶためのものに入る。「荷物がトランクに載らない」\n3. 部品としてもつ。搭載される。「最新CPUが載ったパソコン」\n4. 出版物などに掲載・記載される。「雑誌に記事が載る」
1277 のる 乗る 五段・ラ行 1. 人が乗り物に入って移動する。「電車に乗って行く」\n2. 〈「載る」とも〉何かのすぐ上に置かれる。「魚が皿に乗っている」\n3. 〈「載る」とも〉ものが、運ぶためのものに入る。「荷物がトランクに乗らない」\n4. 移動する媒体や経路に入る。「流れに乗る」「軌道に乗る」\n5. ほめられて調子づく。「すぐ調子に乗る」
1278 はいする 廃する サ変・−スル 〈文語〉用いない。「添加物の使用を廃する」
1279 はいする 拝する サ変・−スル 〈文語〉おがむ。「地蔵を拝する」
1280 はいする 排する サ変・−スル 〈文語〉排除する。「不純物を排する」
1281 はいする 配する サ変・−スル 〈文語〉配分する。「警備を配する」
1245 のべる 伸べる 一段 長くのばす。「救いの手を伸べる」
1246 のぼる 昇る 五段・ラ行 (天体や煙、エレベータなどが)高い場所に行く。「日が昇る、頭に血が昇る」
1247 のぼる 上る 五段・ラ行 (一般的に)高い場所に行く。「坂を上る、川を上る、話題に上る」
1248 のぼる 登る 五段・ラ行 (山、木などで)高い場所に行く。「富士山に登る、木に登る」
1249 のむ 飲む 五段・マ行 噛まずに喉に入れる。「水を飲む、酒を飲む、たばこを飲む」
1250 のむ 呑む 五段・マ行 うけいれる。「犯人の要求を呑む、声を呑む」
1251 のる 載る 五段・ラ行 上に置かれる、記載される。「本が机の上に載っている、雑誌に載る」
1252 のる 乗る 五段・ラ行 乗り物の中に入る。「バスに乗る、相談に乗る、口に乗る、波に乗る」
1253 はい 廃 * (文語)用いない。「添加物の使用を廃する」
1254 はい 拝 * (文語)おがむ。「地蔵を拝する」
1255 はい 排 * (文語)排除する。「不純物を排する、戸を排する」
1256 はい 配 * (文語)配分する。「水を配する、警備を配する」
12821257 ばいしゅん 買春 * 男が金銭で女を買うこと。
12831258 ばいしゅん 売春 * 女が金銭を目当てに体を売ること。
12841259 はいすい 排水 * 水を排泄する。「排水溝」
12851260 はいすい 配水 * 水を配給する。「配水管」
1286 はいふ 配付 * ひとりひとりに配ること。「出席者に資料を配付する」\n※この意味でも「配布」がよく使われる。
1287 はいふ 配布 * 1. 広く配ること。「ビラを配布する」\n2. 〈「配付」とも〉ひとりひとりに配ること。「出席者に資料を配布する」
1288 はえる 映える 一段 1. 光を受けて輝く。「夕日に映える川」\n2. ひきたつ。「青い空に映える白い建物」
1261 はいふ 配付 * 配りつけること。「資料を配付する」
1262 はいふ 配布 * 広く配ること。「ビラを配布する」
1263 はいる 入る 五段・ラ行 閉空間に移動する。「部屋に入る」
1264 はえる 映える 一段 ひきたつ。「夕日に映える、一輪のバラが映える」
12891265 はえる 栄える 一段 立派に見える。「栄えない人」
1290 はえる 生える 一段 (植物、毛などが)出てくる。育つ。伸びる。「草が生える」「毛が生える」
1291 はかる 計る 五段・ラ行 計測する。「血圧を計る」「時間を計る」※長さなどについては「測る」、重さについては「量る」とすることが多い。
1292 はかる 諮る 五段・ラ行 相談する。「理事会に諮る」
1293 はかる 図る 五段・ラ行 しようとする。もくろむ。「対処を図る」「脱走を図る」
1294 はかる 測る 五段・ラ行 (長さなどを)調べる。計測する。「駅までの距離を測る」\n※「計る」とも。
1295 はかる 謀る 五段・ラ行 1. (よくないことを)企てる。「脱走を謀る」→図る\n2. だます。陥れる。「彼に謀られた」
1296 はかる 量る 五段・ラ行 (重さなどを)調べる。計測する。「体重を量る」\n※「計る」、「測る」とも。
1297 はく 穿く 五段・カ行イ音便 〈主にかな書き〉(ズボンなどを)身につける。「ズボンをはく」
1298 はく 掃く 五段・カ行イ音便 (ほこりなどを)払う。「床を掃く」
1299 はく 吐く 五段・カ行イ音便 1. 口から外に出す。特に、吐瀉物(としゃぶつ)を口から外に出す。「つばを吐く」「息を吐く」「飲みすぎて吐いてしまった」\n2. 口のような場所から外に出す。「ばい煙を吐く煙突」\n3. 〈否定的な意味合いで〉言う。「捨てぜりふを吐く」\n4. 追及されて本当のことを言う。白状する。「犯人がついに吐いた」
1266 はえる 生える 一段 (植物などが)根差す。「草が生える、毛が生える」
1267 はかる 計る 五段・ラ行 計算する。「損失を計る、時間を計る」
1268 はかる 諮る 五段・ラ行 相談する。「理事会に諮る、ころあいを諮る」
1269 はかる 図る 五段・ラ行 計画を立てる。「対処を図る」
1270 はかる 測る 五段・ラ行 (長さなどを)調べる。「駅までの距離を測る」
1271 はかる 謀る 五段・ラ行 くわだてる。「脱走を謀る、彼に謀られた」
1272 はかる 量る 五段・ラ行 (重さなどを)調べる。「体重を量る、体積を量る」
1273 はく 穿く 五段・カ行イ音便 (ズボンなどを)身につける。「ズボンを穿く」
1274 はく 掃く 五段・カ行イ音便 (ホコリなどを)払う。「床を掃く」
1275 はく 吐く 五段・カ行イ音便 口の中のものを外に出す。「唾を吐く、真実を吐く、煙を吐く」
13001276 はく 履く 五段・カ行イ音便 (靴などを)足につける。「靴を履く」
13011277 はぐ 矧ぐ 五段・ガ行 矢をつくる。「矢を矧ぐ」
1302 はぐ 剥ぐ 五段・ガ行 むく。はがす。「毛皮を剥ぐ」「身ぐるみ剥ぐ」(=身につけているものを強奪する)
1303 ばくふ 幕府 * 将軍のいる場所。また、将軍の政権。「江戸幕府」
1304 ばくふ 瀑布 * 滝。
1305 はげる 禿げる 一段 1. 毛髪がなくなる。「頭が禿げる」\n2. 山から木がなくなり、地面が露出する。「禿げた山」
1278 はぐ 剥ぐ 五段・ガ行 はがす。「毛皮を剥ぐ、身ぐるみを剥ぐ」
1279 ばくふ 幕府 * 将軍のいる場所。「江戸幕府」
1280 ばくふ 瀑布 * たき。
1281 はげる 禿げる 一段 毛髪がなくなる。「頭が禿げる」
13061282 はげる 剥げる 一段 表面がはがれる。「ペンキが剥げる」
1307 はじめ 始め * 1. 〈主に複合語で〉〈「初め」とも〉はじめること。また、はじめてすぐの時期。「仕事始め」「付き合い始めの時期」\n2. 〈「~を始め」の形で〉〈かな書きも〉主なもの。筆頭。「総理を始め、全閣僚が参加した」
1308 はじめ 初め * 早い時期。「年の初め」
1283 はざま はざ間 * 苗字の一つ。
1284 はざま 狭間 * (「迫間」とも書く)あいだ。「人垣の狭間」
1285 はじめ 一 * 名前のひとつ。
1286 はじめ 初め * (時間的な)はじまり。「年の初め」
1287 はじめる 始める 一段 ものごとのはじまり。「会の始めに、彼を始めとして」
1288 はずす 外す 五段・サ行 のぞく。「レギュラーから外す、ボタンを外す、席を外す」
1289 はずむ 弾む 五段・マ行 はねる。「ボールが弾む、息が弾む、会話が弾む、お年玉を弾む」
1290 はぜ 黄櫨 * ウルシ科の木。
13091291 はぜ 黄櫨 * ウルシ科の木。
13101292 はぜ 鯊 * ハゼ科の魚。
1311 ばち 鉢 * (「はち」の連濁)ふかざら。「すり鉢」
1312 ばち 罰 * 神仏が与える罰(ばつ)。「罰があたる」
1293 ばち 鉢 * (はち)ふかざら。「すり鉢」
1294 ばち 罰 * 神仏があたえるばつ。「罰があたる」
13131295 はな 花 * 植物の生殖にかかわる器官。「花びら」
13141296 はな 華 * 華やかなもの。「彼の演技には華がある」
1315 はなす 放す 五段・サ行 1. つかんでいたのをやめる。「包丁を放す」\n※「手をはなす」は「離す」とすることが多い。\n2. (動物を)自由にする。野生にもどす。「クマに発信機をつけて放す」
1316 はなす 離す 五段・サ行 1. くっついていたもの、または近かったものどうしを分けて遠くする。「受話器を耳から離す」「画面から顔を離す」\n2. 〈「目を離す」の形で〉視線をそらす。「目を離したすきに逃げられた」
1317 はなす 話す 五段・サ行 言葉を使う。言葉で伝える。「日本語を話す」「真実を話す」
1318 はなれる 放れる 一段 →離れる
1319 はなれる 離れる 一段 1. くっついていたもの、または近かったものどうしが分かれて遠くなる。「ガムが床から離れない」\n2. 距離を置く。「危ないから離れなさい」\n3. 去る。「日本を離れる」\n4. 距離がある。「10メートル離れている」
1320 はね 羽 * 〈「羽根」とも〉鳥や昆虫、飛行機などが飛ぶために使うもの。つばさ。※昆虫のものは「翅」とも。
1321 はね 羽根 * 〈「羽」とも〉\n1. 鳥のつばさを構成する、一本一本の羽毛。「羽根ペン」\n2. 小さな玉に鳥の羽毛をつけた遊具。また、それに似せた遊具。「羽根つき」「バドミントンの羽根」
1322 はやい 早い 形容詞・アウオ段 1. 時間があまりたっていない。時間が前である。「まだ晩ご飯には早い」「朝の早い時間」\n2. 短い時間しかかからない。「待つより電話したほうが早い」
1323 はやい 速い 形容詞・アウオ段 すみやかである。速度がある。「進歩が速い」「速い車」
1297 はなす 放す 五段・サ行 自由にする。「犬を放す、包丁を放す」
1298 はなす 離す 五段・サ行 くっついていたものを分ける。「手を離す、3センチ離す」
1299 はなす 話す 五段・サ行 言葉で伝える。「日本語を話す、真実を話す」
1300 はなれる 放れる 一段 自由になる。「犬が放れる」
1301 はなれる 離れる 一段 くっついていたものが分かれる。「手が離れる、10メートル離れている」
1302 はね 羽根 * 鳥のつばさ、羽毛。「羽を伸ばす」
1303 はね 羽根 * 羽を加工したもの。
1304 はやい 早い 形容詞・アウオ段 じかんが短い。「終わるのが早い、早い時間に」
1305 はやい 速い 形容詞・アウオ段 すみやかである様。「仕事が速い、速い車」
13241306 はやまる 早まる 五段・ラ行 時間が早くなる。「出発時刻が早まる」
13251307 はやまる 速まる 五段・ラ行 速度が速くなる。「速度が速まる」
13261308 はやめる 早める 一段 時間を早くする。「出発時刻を早める」
13271309 はやめる 速める 一段 速度を速くする。「足を速める」
1328 はやる 逸る 五段・ラ行 〈主にかな書き〉あせる。「はやる気持を抑えられない」
1329 はやる 流行る 五段・ラ行 流行する。「彼の髪型は流行っている」「風邪が流行る」
1330 はる 張る 五段・ラ行 1. かけわたす。「綱を張る」\n2. 広がる。「根が張る」\n3. ふくらむ。「腹が張る」\n4. 表面にできる。「水面に氷が張る」\n5. (容器に液体を)満たす。「風呂に湯を張る」\n6. 同じ場所にいて観察を続ける、または待ち伏せる。張り込む。「家の前で3時間も張っていた」\n7. (価格などが)高い。「値が張る」\n8. 強くする。「欲を張る」\n9. (体の一部を)高めに持ち上げる。「胸を張る」(胸を反らせる、誇らしげにする)
1331 はる 貼る 五段・ラ行 表面にべたっとくっつける。また、そのように見えるようにする。「切手を貼る」「ウェブページに画像を貼る」
1332 はんざつ 繁雑 * ごちゃごちゃしていること。「繁雑な図」
1333 はんざつ 煩雑 * こみいっていてめんどうなことこと。「煩雑な事務手続き」
1310 はやる 逸る 五段・ラ行 あせる。「逸る気持を抑えられない」
1311 はやる 流行る 五段・ラ行 流行する。「彼の髪型は流行っている、風邪が流行る」
1312 はらす 晴らす 五段・サ行 心のくもりをとりのぞく。「疑いを晴らす」
1313 はらむ 孕む 五段・マ行 妊娠する。「子を孕む」
1314 はる 張る 五段・ラ行 広がる。「根が張る、腹が張る、水面に氷が張る、値が張る、欲を張る」
1315 はる 貼る 五段・ラ行 (糊などで)くっつける。「切手を貼る」
1316 はんざつ 繁雑 * 多くてこみいってること。「繁雑な倉庫内」
1317 はんざつ 煩雑 * わずらわしくてこみいってること。「煩雑な作業」
13341318 はんれい 判例 * 裁判での判決の先例。「最高裁での判例」
13351319 はんれい 反例 * 反証となる例。「命題の反例」
1336 はんれい 凡例 * 1. 主に辞典などの書物において、編集方針や注記法などを掲げたもの。\n2. 図表などで、使用される表記法などを示すためにつけられた解説文。
1337 ひきあげる 引き上げる 一段 1. 引っぱって高い位置に移す。「ファスナーを引き上げる」\n2. つるすなどして、まっすぐ上にあげる。「海に落ちた車を引き上げる」\n3. (値段や数字などを)上げる。「値段を引き上げる」\n4. もとの場所に戻る。「戦場から引き上げる」\n5. (与えたもの・預けたものなどを)回収する。「資金を引き上げる」\n6. (派遣していた人員などを)帰ってこさせる。撤退させる。「軍隊を引き上げる」\n※2, 4, 5, 6では「引き揚げる」とも。4, 6 では、出征先からの帰還の場合によく「引き揚げる」が使われる。
1338 ひきあげる 引き揚げる 一段 〈「引き上げる」とも〉\n1. つるすなどして、まっすぐ上にあげる。「海に落ちた車を引き揚げる」\n2. もとの場所に戻る。「戦場から引き揚げる」\n3. (与えたもの・預けたものなどを)回収する。「資金を引き揚げる」\n4. (派遣していた人員などを)帰ってこさせる。撤退させる。「軍隊を引き揚げる」
1339 ひきのばす 引き延ばす 五段・サ行 〈「引き伸ばす」とも〉\n1. 〈否定的な意味合いで〉遅らせる。「返事を引き延ばす」\n2. 平たいものをのばす。「生地を引き延ばして薄くする」
1340 ひきのばす 引き伸ばす 五段・サ行 1. 引っぱって長くする。「バネを引き伸ばす」\n2. (写真を)拡大して現像する。「写真を引き伸ばす」
1341 ひく 引く 五段・カ行イ音便 1. 端などを持って自分のほうに動かす。「ひもを引く」「弓を引く」\n2. 端などを持って、自分も動きながらそれにつれて動かす。「人力車を引く」「子供の手を引いて歩く」\n3. (一部分を)後ろに動かす。「あごを引く」「顔を引いてよけた」\n4. 減らす。減算する。「5から3を引く」\n5. 〈「惹く」とも〉人の関心などを起こす。「気を引く」「興味を引く」\n6. (線などを)えがく。「地面に白線を引く」\n7. (線状に伝わるものを)通じさせる。「村に電気が引かれる」\n8. (油などを)平らにのばす。「フライパンに油を引く」\n9. もとの場所に戻す。「軍を引く」\n10. 〈「退く」とも〉しりぞく。「身を引く」(=引退する)「手を引く」(=かかわりをやめる)\n11. (辞書などで)求める項目をさがす。「単語を辞書で引く」\n12. 〈若者言葉〉異常とみなし、かかわりたくないと思う。「彼の話を聞いて内心引いてた」
1342 ひく 曳く 五段・カ行イ音便 〈一般的には「引く」〉端などを持って、自分も動きながらそれにつれて動かす。「人力車を曳く」「船を曳く」\n※船について使う場合が多い。
1343 ひく 牽く 五段・カ行イ音便 〈一般的には「引く」〉端などを持って、自分も動きながらそれにつれて動かす。「牛に犁(すき)を牽かせる」\n※家畜などについて使う場合が多い。
1344 ひく 惹く 五段・カ行イ音便 〈「引く」とも〉人の関心などを起こす。「気を惹く」「興味を惹く」
1345 ひく 退く 五段・カ行イ音便 〈一般的には「引く」〉しりぞく。「身を退く」「手を退く」→引く10
1346 ひく 弾く 五段・カ行イ音便 (楽器などを)鳴らす。演奏する。「ピアノを弾く」
1347 ひく 碾く 五段・カ行イ音便 〈主にかな書き〉臼(うす)で食べ物をすりつぶす。「麦をひく」
1348 ひく 轢く 五段・カ行イ音便 〈かな書きも〉(車などで)生物を下じきにする。または、はねとばして死傷させる。「車で人を轢く」
1349 ひじょう 非常 * 1. ただごとではないこと。「非常事態」\n2. 程度が普通ではないこと。「非常な悲しみ」
1350 ひじょう 非情 * 情けがないこと。「非情な男」
1320 はんれい 凡例 * 書物の方針を掲げたもの。「熟語の凡例」
1321 ひきあげる 引き上げる 一段 引いて高い位置に移す。「車を引き上げる、値段を引き上げる」
1322 ひきあげる 引き揚げる 一段 もとの場所にもどる。「戦場から引き揚げる」
1323 ひきのばす 引き延ばす 五段・サ行 おくらせる。「返事を引き延ばす」
1324 ひきのばす 引き伸ばす 五段・サ行 引いて大きくする。「写真を引き伸ばす」
1325 ひく 引く 五段・カ行イ音便 自分の方へ近づける。「紐を引く、村に電気が引かれる、気を引く、手を引く」
1326 ひく 曳く 五段・カ行イ音便 (「引く」とも書く)ひっぱる。「船を曳く」
1327 ひく 牽く 五段・カ行イ音便 (「引く」とも書く)ひっぱる。「車を牽く」
1328 ひく 惹く 五段・カ行イ音便 関心をあたえる。「心を惹く、人目を惹く」
1329 ひく 退く 五段・カ行イ音便 しりぞく。「身を退く、血の気が退く」
1330 ひく 弾く 五段・カ行イ音便 (楽器などを)ならす。「ピアノを弾く」
1331 ひく 碾く 五段・カ行イ音便 臼で食べ物をすりつぶす。「麦を碾く」
1332 ひく 轢く 五段・カ行イ音便 (車などで)生物を下じきにする。「車で人を轢く」
1333 ひじょう 非常 * ただごとではないこと。「非常事態」
1334 ひじょう 非情 * なさけがないこと。「非情な男」
13511335 ひそむ 潜む 五段・マ行 かくれる。「物陰に潜む」
1352 ひそむ 顰む 五段・マ行 〈文語〉(眉を)しかめる。「眉を顰む」
1353 ひそめる 潜める 一段 1. 〈「身を潜める」として〉隠れる。\n2. 〈「声を潜める」として〉小声になる。
1354 ひそめる 顰める 一段 〈かな書きも〉(眉を)しかめる。「眉を顰める」
1355 ひつじ 未 * 干支(えと)の一つ。午(うま)の次、申(さる)の前。
1356 ひつじ 羊 * 主に毛を刈って糸や織物にするために家畜とされる動物。
1357 ひとで 人手 * 1. 働く人の数。「人手が足らない」\n2. 他人の所有。「人手に渡る」\n3. 人の手作業。「人手で注釈をつける」
1336 ひそむ 顰む 五段・マ行 まゆをしかめる。「眉を顰む」
1337 ひそめる 潜める 一段 かくれさせる。「人を潜める、声を潜める」
1338 ひそめる 顰める 一段 まゆをしかめる。「眉を顰める」
1339 ひつじ 未 * 干支の一つ。
1340 ひつじ 羊 * ウシ科の動物。
1341 ひとで 人手 * 他人の手。「人手に渡る、人手が足らない」
13581342 ひとで 人出 * 人が集まること。「花火大会に多くの人出がありました」
1359 ひなん 避難 * 災害などから逃れること。「火災から避難する」
1360 ひなん 非難 * 〈「批難」に同じ〉非があると思う相手を言葉で責めること。「彼の失敗を非難する」
1361 ひなん 批難 * 〈「非難」に同じ〉非があると思う相手を言葉で責めること。「彼の失敗を批難する」
1362 ひょうする 表する サ変・−スル あらわす。「敬意を表する」
1363 ひょうする 評する サ変・−スル 批評する。「この映画を評する」
1364 ひょうき 標記 * 1. 標題として記すこと。また、その内容。「標記の文には矛盾がある」\n2. しるしとしてつけること。また、その内容。「ロゴを標記する」
1365 ひょうき 表記 * 1. 文字などであらわすこと。「英語で表記する」\n2. おもてにしるすこと。「『数学』と表記されたノート」
1343 ひなん 避難 * 災害などから逃れる。「火災から避難する」
1344 ひなん 非難 * せめる。「彼の失敗を非難する」
1345 ひょう 表 * あらわす。「敬意を表する」
1346 ひょう 評 * 批評する。「この映画を評する」
1347 ひょうき 標記 * 標題として記したこと。「交通標記」
1348 ひょうき 表記 * 文字などであらわすこと。「英語で表記する」
13661349 ひょうけつ 票決 * 投票で決めること。「単純多数で票決する」
1367 ひょうけつ 表決 * 議案に対して賛否を示すこと。「起立によって表決する」
1368 ひょうけつ 評決 * 議論して決めること。また、その結論。「陪審員が有罪の評決を告げた」
1369 ひょうしょう 表彰 * 人々の前で功績を誉め、伝えること。「表彰状」
1370 ひょうしょう 表象 * 象徴すること。象徴。
1371 ひょうはく 漂泊 * さまようこと。「各地を漂泊する」
1350 ひょうけつ 表決 * 議案に対して賛否を示すこと。「草案を表決する」
1351 ひょうしょう 表彰 * 功績を誉め、伝えること。「表彰状」
1352 ひょうしょう 表象 * 象徴。
1353 ひょうはく 漂泊 * さまようこと。「海を漂泊する」
13721354 ひょうはく 漂白 * 水などにさらして白くすること。「油汚れを漂白する」
1373 ひょうはく 表白 * 〈文語〉思いを述べること。「自らの苦悩を表白する」
1374 ひんする 瀕する サ変・−スル (危機などが)せまる。「危機に瀕する」
1375 ひんする 貧する サ変・−スル 貧乏な状態になる。また、貧乏な状態にある。「富める者貧する者」
1376 びん 瓶 * 〈「壜」に同じ。一般的〉〈かな書きも〉\nガラスなどの器。「空き瓶」
1377 びん 便 * 交通手段・運送手段について、一度の移動。「午後一番の便で送る」
1378 びん 壜 * →瓶
1379 ふす 付す 五段・サ行 〈「附する」とも〉\n1. 〈文語〉つけたす。「預託金に付す利子」\n2. (審査、評議などに)通す。「審査に付す」\n3. 扱いをする。「一笑に付す」(=笑ってかたづける)「不問に付す」(=問わない)
1380 ふす 賦す 五段・サ行 〈文語〉くばる。
1381 ふす 附す 五段・サ行 →付する
1382 ふする 付する サ変・−スル 〈文語〉〈「附する」とも〉〈普通「付す」〉\n1. つけたす。「預託金に付する利子」\n2. (審査、評議などに)通す。「審査に付する」\n3. 扱いをする。「一笑に付する」(=笑ってかたづける)「不問に付する」(=問わない)
1383 ふする 賦する サ変・−スル 〈文語〉くばる。
1384 ふする 附する サ変・−スル →付する
1385 ふうこう 風光 * 自然の景色。「風光に恵まれた地」「風光明媚」
1355 ひん 瀕 * (危機などが)せまる。「危機に瀕する」
1356 ひん 貧 * 貧乏な状態になる。「富める者貧する者」
1357 びん 瓶 * (「壜」と区別なし、一般的)ガラスなどの器。「空き瓶」
1358 びん 便 * たより。「宅配便」
1359 びん 壜 * (「瓶」と区別なし)ガラスなどの器。「空き壜」
1360 ふ 付 * (文語)(「附する」と区別なし)つけたす。「預託金に付する利子、不問に付す」
1361 ふ 賦 * (文語)くばる。
1362 ふ 附 * (文語)(「付する」と区別なし)つけたす。「預託金に附する利子、不問に附す」
1363 ふうこう 風光 * 自然の景色。「風光明媚な観光地」
13861364 ふうこう 風向 * かざむき。「風向計」
1387 ふえる 殖える 一段 〈「増える」が一般的〉\n(繁殖や利殖によって)数が多くなる。「貯金が殖える」「菌が殖える」
1388 ふえる 増える 一段 数が多くなる。「人数が増える」「貯金が増える」「菌が増える」\n※繁殖や利殖による場合は「殖える」とも。
1365 ふえる 殖える 一段 (財産などが)多くなる。「貯金が殖える」
1366 ふえる 増える 一段 数が多くなる。「人数が増える」
13891367 ふか 付加 * 付け加えること。「おまけを付加する」
1390 ふか 負荷 * (機械などでの)仕事の量。「高負荷」「負荷平均」
1391 ふか 孵化 * 卵からかえること。「ひよこが孵化する」
1368 ふか 負荷 * (計算機などでの)仕事の量。「高負荷、負荷平均」
1369 ふか 孵化 * 卵からかえること。「ヒヨコが孵化する」
13921370 ふかす 更かす 五段・サ行 夜おそくまで起きている。「夜を更かす」
1393 ふかす 吹かす 五段・サ行 1. (タバコを)吸う。\n2. 〈「…風を吹かす」として〉(それに見合わない者が)そのような態度を見せつける。「先輩風を吹かす」
1394 ふかす 蒸かす 五段・サ行 〈主にかな書き〉蒸気で加熱する。むす。「芋をふかす」
1395 ふきゅう 不休 * 〈主に「不眠不休」として〉休むことのないこと。「不眠不休で働く」
1396 ふきゅう 不朽 * 長く価値を保つこと。「不朽の名作」
1397 ふく 拭く 五段・カ行イ音便 布などで表面をこすってきれいにする。ぬぐう。「机を拭く」
1398 ふく 吹く 五段・カ行イ音便 1. 口から息を強く出してものに当てる。「ろうそくを吹いて消す」\n2. 口から息を出して音を立てる。「笛を吹く」\n3. 〈「噴く」とも〉(液体や気体が)中から勢いよく出る。または、勢いよく出す。「血が吹く」「銃が火を吹く」\n4. 中からあらわれる。または、中からあらわす。「芽が吹く」「肌が粉を吹く」\n5. 〈主に「ほらを吹く」として〉うそをつく。\n6. 〈若者言葉〉笑い出す。吹き出す。「画像を見て思わず吹いた」
1399 ふく 葺く 五段・カ行イ音便 (屋根を)瓦やわらなどで覆う。「屋根を葺く」
1400 ふく 噴く 五段・カ行イ音便 〈「吹く」とも〉(液体や気体が)中から勢いよく出る。または、勢いよく出す。「血が噴く」「銃が火を噴く」
1401 ふくす 伏す 五段・サ行 〈文語〉かがむ。
1402 ふくす 復す 五段・サ行 〈文語〉もとにもどす。
1403 ふくす 服す 五段・サ行 したがう。「刑に服す」「喪に服す」
1404 ふくする 伏する サ変・−スル 〈文語〉かがむ。
1405 ふくする 復する サ変・−スル 〈文語〉もとにもどす。
1406 ふくする 服する サ変・−スル したがう。「刑に服する」「喪に服する」
1371 ふかす 蒸かす 五段・サ行 むす。「芋を蒸す」
1372 ふきゅう 不休 * 休むことのないこと。「不眠不休で働く」
1373 ふきゅう 不朽 * 朽ちることのないこと。「不朽の名作」
1374 ふく 拭く 五段・カ行イ音便 ぬぐう。「机を拭く」
1375 ふく 吹く 五段・カ行イ音便 空気が動く。「風が吹く、笛を吹く、粉を吹く」
1376 ふく 葺く 五段・カ行イ音便 瓦や藁などで屋根を覆う。「屋根を葺く」
1377 ふく 噴く 五段・カ行イ音便 (液体、気体などが)勢いよく外にでる。「火を噴く」
1378 ふく 伏 * (文語)かくれる。
1379 ふく 復 * (文語)もとにもどす。
1380 ふく 服 * (文語)したがう。「刑に服する、喪に服する」
14071381 ふくしゅう 復習 * もう一度勉強すること。「英語の授業を復習する」
1408 ふくしゅう 復讐 * しかえし。かたきうち。「親の復讐をする」
1409 ふくす 復す 五段・サ行 〈文語〉もとにもどす。「元の状態に復する」
1410 ふくす 服す 五段・サ行 〈文語〉したがう。「刑に服す」「喪に服す」
1411 ふくすい 腹水 * 腹にたまった水。
1412 ふくすい 覆水 * 〈「覆水盆に返らず」として〉こぼれた水は元に戻らない。取り返しがつかない。
1413 ふくせん 伏線 * あとになって関連してくること。「伏線をはる」「このことはのちに起こる事件の伏線となっている」
1414 ふくせん 複線 * 複数の線。鉄道においては、上下の線路を併設すること。「高速道路の複線化」「複線軌道」
1382 ふくしゅう 復讐 * しかえし。「親の復讐をする」
1383 ふくす 復す 五段・サ行 もとにもどす。「元の状態に復する」
1384 ふくす 服す 五段・サ行 したがう。「刑に服す、喪に服す」
1385 ふくすい 腹水 * 腹に溜まる水。
1386 ふくすい 覆水 * こぼれた水。「覆水盆に返らず」
1387 ふくせん 伏線 * あとのことをほのめかすこと。「伏線をはる」
1388 ふくせん 複線 * 複数の線。「複線軌道」
14151389 ふける 更ける 一段 夜になって時間がたつ。「夜が更ける」
1416 ふける 老ける 一段 年をとる。また、そう見えるようになる。「彼の顔は老けている」「苦労ですっかり老けてしまった」
1417 ふける 耽る 一段 〈かな書きも〉他のことを忘れるほど、そのことだけをする。耽溺(たんでき)する。「物思いに耽る」「豪遊に耽る」
1418 ふこう 不孝 * 孝行でないこと。「親不孝」
1390 ふける 老ける 一段 年をとる。「彼の顔は老けている」
1391 ふこう 不孝 * 孝行でないこと。「親不幸」
14191392 ふこう 不幸 * 幸せでないこと。「不幸な事件」
14201393 ふしん 普請 * 建物の工事。「安普請」
1421 ふしん 腐心 * 目的のためにいろいろ考えること。また、目的のために努力すること。「構造改革に腐心する」
1422 ふしん 不審 * あやしいこと。「不審者」
1423 ふしん 不振 * (成績などが)ふるわないこと。ぱっとしないこと。「打撃不振」
1424 ふじん 夫人 * 他人の妻に対する尊称。「真珠夫人」
1425 ふじん 婦人 * 成人女性。「婦人会」
1426 ふす 臥す 五段・サ行 〈「伏す」とも〉横になる。「床に臥す」
1427 ふす 伏す 五段・サ行 腹ばいになる。また、土下座する。「地に伏す」「伏してお願いする」
1394 ふしん 腐心 * なにかをして心をいためること。「構造改革に腐心する」
1395 ふしん 不審 * あやしいこと。「不審者を見かけたら110番」
1396 ふしん 不振 * ふるわないこと。「打撃不振」
1397 ふじん 夫人 * 他人の妻。「真珠夫人」
1398 ふじん 婦人 * 女性。「婦人会」
1399 ふす 臥す 五段・サ行 (「伏す」と区別なし)うつぶせになる。「床に臥せる、彼には事実を臥せておく」
1400 ふす 伏す 五段・サ行 (「臥す」と区別なし)うつぶせになる。「床に伏せる、彼には事実を伏せておく」
14281401 ふせい 不整 * 整っていないこと。「不整脈」
1429 ふせい 不正 * 正しくないこと。正しくない行為。「不正な利用」「政治の不正を糾弾する」
1430 ふせい 不斉 * 対称でないこと。「不斉炭素原子」
1431 ふせつ 付設 * 〈「附設」とも〉付属して設置すること。「テニスコートを付設する」
1432 ふせつ 附設 * →付設
1433 ふせつ 敷設 * 〈「布設」に同じ。一般的〉広い範囲に設置すること。「鉄道を敷設する」
1434 ふせつ 布設 * 〈「敷設」に同じ〉広い範囲に設置すること。「鉄道を布設する」
1435 ふたく 付託 * 〈「附託」とも〉処置を委ねること。「核問題を安保理に付託する」
1436 ふたく 附託 * →付託
1437 ふたく 負託 * 人に責任を持たせてまかせること。「国民の負託を受ける」
1438 ふっきゅう 復仇 * 1. かたきをうつこと。\n2. やりかえすこと。
1402 ふせい 不正 * ただしくないこと。
1403 ふせい 不斉 * 整っていないこと。「不斉合成」
1404 ふせつ 付設 * 付属して設置すること。「テニスコートを付設する」
1405 ふせつ 敷設 * (設備などを)設置すること。「水道を敷設する」
1406 ふたく 付託 * 依頼すること。「核問題を安保理に付託する」
1407 ふたく 負託 * 人にまかせること。「機能を負託する」
1408 ふっきゅう 復仇 * かたきをうつこと。
14391409 ふっきゅう 復旧 * 元通りにすること。「停電から復旧した」
14401410 ふてい 不貞 * 浮気をすること。「不貞をはたらく」
1441 ふてい 不定 * 定まっていないこと。「不定形」「住所不定無職の男」
1442 ふてき 不敵 * 相手を軽く見るさま。「不敵な笑い」「大胆不敵」
1443 ふてき 不適 * 適さないこと。「飲料水として不適である」
1411 ふてい 不定 * 定まっていないこと。「不定形、住所不定無職の男」
1412 ふてき 不敵 * 敵をあいてにしないさま。「不敵な笑い」
1413 ふてき 不適 * 適さないこと。
14441414 ふとう 不当 * 正当でないこと。「不当な扱いを受ける」
14451415 ふとう 不等 * 等しくないこと。「不等号」
1446 ふどう 不動 * 1. 動かないこと。「直立不動」\n2. 堅固でゆるがないこと。「不動の地位」
1447 ふどう 不同 * (順序について)基準がないこと。「掲載順序は不同です」「順不同」
1448 ふむ 践む 五段・マ行 〈まれ〉「踏む」に同じ。
1449 ふむ 踏む 五段・マ行 1. 足で下じきにする。「エンピツを踏む」「祖国の地を踏む」\n2. やり方に従う。踏襲する。「手順を踏む」\n3. 〈「韻を踏む」として〉押韻する。
1450 ふやす 殖やす 五段・サ行 〈「増やす」が一般的〉(繁殖や利殖によって)数を多くする。「貯金を殖やす」「菌を殖やす」
1451 ふやす 増やす 五段・サ行 数を多くする。「人数を増やす」「貯金を増やす」「菌を増やす」※繁殖や利殖による場合は「殖やす」とも。
1452 ふよう 扶養 * 養うこと。「扶養家族」「三人の家族を扶養している」
1453 ふよう 浮揚 * 1. 〈文語〉浮きあがること。また、浮き上がらせること。「水面に浮揚する」\n2. (景気や人気について)状況を改善する、または改善させること。「景気浮揚策」
1454 ふよう 不用 * 使わないこと。「不用品」\n※「不用品」は「不要品」とも。
1455 ふよう 不要 * 必要でないこと。「手続きは不要です」「不要品」\n※「不要品」は「不用品」とも。
1456 ふりだす 降り出す 五段・サ行 (雨など)が降り始める。「雨が降り出した」
1457 ふりだす 振り出す 五段・サ行 1. 振り始める。「手を振り出した」\n2. (手形・小切手などを)発行する。「小切手を振り出す」
1458 ふる 降る 五段・ラ行 (雨などが)空から落ちる。「雨が降る」「2階から水が降ってきた」
1459 ふる 振る 五段・ラ行 1. ゆり動かす。「バットを振る」\n2. (粉などを)まく。かける。「コショウを振る」\n3. (仕事などを)割り当てる。「仕事を振る」\n4. (話題などを)向ける。「そんな話題を振られても反応に困る」\n5. (交際相手と)交際を断つ。(交際の申し込みを)断る。「彼に振られて泣いていた」「告白したけれど振られた」\n※「フる」「フラれる」とも。
1460 ふるい 旧い 形容詞・アウオ段 →古い
1461 ふるい 古い 形容詞・アウオ段 1. 〈まれに「旧い」とも〉できてから、あるいは起こってから時間がたっている。また、より新しいものに置き換えられている。「古い資料」「古い考え方」\n2. できてから、あるいは起こってから長い時間がたっている。古代のものである。「古い時代の記録」「古い言い伝え」
1462 ふるう 振るう 五段・ワ行促音便 〈「揮う」とも。かな書きも〉\n1. 大きく振り動かす。「指揮棒を振るう」\n2. いかんなく発揮する。「腕を振るう」「熱弁を振るう」\n3. (暴力を)おこなう。「暴力を振るう」\n4. 〈主に否定形で〉勢いがある。「成績が振るわない」
1463 ふるう 揮う 五段・ワ行促音便 →振るう
1464 ふるう 震う 五段・ワ行促音便 〈文語〉震動する。震える。
1465 ふるう 奮う 五段・ワ行促音便 (勇気・気力などを)わきたたせる。ふりしぼる。「勇気を奮う」
1466 ふるう 篩う 五段・ワ行促音便 〈主にかな書き〉ふるいにかける。「小麦粉をふるう」
1467 ぶんか 分化 * 異なるものに変わり、分かれていくこと。「細胞が分化する」
1416 ふどう 不動 * 動かないこと。「不動の地位、目黒不動尊」
1417 ふどう 不同 * 同じでないこと。「順不同」
1418 ふむ 践む 五段・マ行 (「踏む」と区別なし)足で下じきにする。「エンピツを践む、祖国の土を践む、手順を践む、韻を践む」
1419 ふむ 踏む 五段・マ行 (「践む」と区別なし)足で下じきにする。「エンピツを踏む、祖国の土を踏む、手順を踏む、韻を踏む」
1420 ふやす 殖やす 五段・サ行 (財産などを)多くする。「貯金を殖やす」
1421 ふやす 増やす 五段・サ行 多くする。「定員を増やす」
1422 ふよう 扶養 * 養うこと。「扶養家族、三人の家族を扶養している」
1423 ふよう 浮揚 * うきあがること。「景気が浮揚する」
1424 ふよう 不用 * 用のないこと。「不用なもの」
1425 ふよう 不要 * 必要でないこと。「手続きは不要です」
1426 ふりだす 降り出す 五段・サ行 雨などが降り始める。「雨が降り出した」
1427 ふりだす 振り出す 五段・サ行 振り始める。「手を振り出す」
1428 ふる 降る 五段・ラ行 (雨などが)おちる。「雨が降る、災難が降りかかる」
1429 ふる 振る 五段・ラ行 ゆり動かす。「バットを振る、コショウを振る、仕事を振る」
1430 ふるい 旧い 形容詞・アウオ段 (「古い」と区別なし)
1431 ふるい 古い 形容詞・アウオ段 (「旧い」と区別なし)
1432 ふるう 振るう 五段・ワ行促音便 いきおいづく、振る。「成績が振るわない、熱弁を振るう」
1433 ふるう 震う 五段・ワ行促音便 震動する。
1434 ふるう 奮う 五段・ワ行促音便 心をわきたたせる。「勇気を奮う」
1435 ふるう 篩う 五段・ワ行促音便 ふるいで分ける。「参加者を篩う」
1436 ぶんか 分化 * 異質なものに分かれること。「細胞が分化する」
14681437 ぶんか 分科 * 分けられた科目。「分科会」
1469 ぶんか 文化 * 人間の風俗、思考など独自に育んだものの総称。「古代ローマの文化」「重要文化財」「文化系サークル」
1470 ぶんか 文科 * 人文科学・社会科学などの科目。「文科系の大学院」
1438 ぶんか 文化 * 人間の風俗、思考など独自に育んだものの総称。「文化革命、重要文化財」
1439 ぶんか 文科 * 人文系の科目。
14711440 ふんぜん 憤然 * 憤るさま。「彼の発言に憤然とする」
14721441 ふんぜん 奮然 * 奮いたつさま。「奮然といきごむ」
1473 へいこう 平行 * 1. 同一面上の直線がどこまでも交わらないこと。「2本の平行な線」\n2. (移動について)形や傾きをかえないこと。「平行移動」\n3. 〈「並行」「併行」とも〉同時におこなうこと。「学業と平行して執筆する」
1474 へいこう 平衡 * (物や心の)つりあいがとれている状態。バランス。「平衡感覚」
1475 へいこう 並行 * 1. ならんで進むこと。「高速道路と並行する国道」\n2. 〈「平行」「併行」とも〉同時におこなうこと。「学業と並行して執筆する」
1476 へいこう 併行 * 〈「並行」「平行」とも〉同時に行うこと。「学業と併行して執筆する」
1477 へいこう 閉口 * 困ること。「彼のわがままに閉口する」
1442 へいこう 平行 * 同一面上の直線がどこまでも交わらないこと。「平行移動」
1443 へいこう 平衡 * つりあいがとれている状態。「平衡感覚」
1444 へいこう 並行 * 並んで行なうこと。「高速道路と並行する国道」
1445 へいこう 閉口 * ものを言わないこと、あきれること。「彼のわがままに閉口する」
14781446 へいこう 閉校 * 学校が閉鎖されること。
1479 へんけい 変型 * 特殊な型。「変型チラシ」
1480 へんけい 変形 * 形が変わる、または形を変えること。「消しゴムが変形する」「変形ロボット」
1481 へんざい 偏在 * 偏って存在すること。「一部地域に偏在する資源」
1447 へき 僻 * かたよること。「僻地」
1448 へき 壁 * かべ。「絶壁、鉄璧」
1449 へき 癖 * くせ。「性癖、潔癖」
1450 へき 碧 * あおみどり色。「紺碧」
1451 へんけい 変型 * 特殊な型のこと。「変型チラシ」
1452 へんけい 変形 * 形が変わること。「消しゴムが変形する、変形ロボット」
1453 へんざい 偏在 * 偏って存在すること。「偏在する資源」
14821454 へんざい 遍在 * 広く存在すること。「世界に遍在する情報」
1483 へんしゅう 偏執 * 〈「へんしつ」とも読む〉偏ったことに執着すること。「偏執狂」
1484 へんしゅう 編修 * (歴史書などを)まとめること。「日本書紀の編修過程」
1485 へんしゅう 編集 * 1. 元となる資料を整理し、書籍や画像、動画などにまとめること。「雑誌を編集する」「結婚式の動画を編集する」\n2. (パソコンなどでデータを)改変する。「ファイルを編集した後に上書き保存をする」
1486 へんしゅう 編輯 * →編集
1487 べんずる 便ずる サ変・−ズル 〈文語〉用をたす。
1488 べんずる 弁ずる サ変・−ズル 〈文語〉のべる。
1455 へんしゅう 偏執 * 偏ったことに執着すること。「偏執狂」
1456 へんしゅう 編修 * 辞書などの書籍をまとめること。「辞書を編修する」
1457 へんしゅう 編集 * 雑誌などをつくること。「編集者、編集長」
1458 べんずる 便ずる サ変・−ズル (文語)用をたす。
1459 べんずる 弁ずる サ変・−ズル (文語)のべる。
14891460 へんせい 変性 * 性質が変わること。「細胞が変性する」
14901461 へんせい 変声 * 声変わりすること。「変声期」
1491 へんせい 編制 * (決まった規模の)団体を組織すること。「師団を編制する」「学級の編制」
1492 へんせい 編成 * まとめあげること。「チームを編成する」「予算を編成する」
1462 へんせい 編制 * 軍隊などを組織すること。
1463 へんせい 編成 * 組織すること。「チームを編成する」
14931464 へんれい 返戻 * 返しもどすこと。「返戻金」
1494 へんれい 返礼 * 1. 礼・贈り物を受け取り、同等のものを返すこと。また、その行為や品。「返礼を贈る」\n2. いやな仕打ちを受けて、それに対してしかえしをすること。
1495 ほうおう 法王 * 教皇のこと。「ローマ法王」\n※現在は「教皇」が正式。
1465 へんれい 返礼 * 礼をかえすこと。「内祝いとして返礼する」
1466 ほ 保 * (文語)ひきうける。
1467 ほ 補 * (文語)役職をまかせる。
1468 ほうおう 法王 * 教皇のこと。「ローマ法王」
14961469 ほうおう 法皇 * 仏門に入った上皇。
1497 ぼうさつ 忙殺 * 忙しくて他のことができないこと。用事に追われること。「仕事に忙殺される」
1498 ぼうさつ 謀殺 * 計画的に殺人すること。
1499 ほうしょう 報奨 * (行為などに対して)報いることによってすすめること。「若年者雇用に対する報奨金」
1500 ほうしょう 報償 * 報いるため、または償うために支払うこと。「退職に対する報償金」「被害に対する報償金」
1501 ほうしょう 褒賞 * 善行などをほめたたえること。また、それに対して与える賞。「軍功を褒賞する」「功労に対する褒賞金」
1502 ほうずる 報ずる サ変・−ズル 1. 〈文語〉むくいる。\n2. 報道する。「首相の訪朝が報じられた」
1503 ほうずる 奉ずる サ変・−ズル 〈文語〉うけたまわる。
1504 ほうずる 崩ずる サ変・−ズル 〈文語〉亡くなる。崩御する。
1505 ほかん 保管 * 保存・管理すること。「金品を保管する」
1470 ぼうさつ 忙殺 * とても忙がしいこと。「仕事に忙殺される」
1471 ぼうさつ 謀殺 * 計画的な殺人。
1472 ほうしょう 報償 * 損害をつぐなうこと。「事故に対する報償金」
1473 ほうしょう 褒賞 * ほめたたえること。「功労に対する褒賞金」
1474 ほうずる 報ずる サ変・−ズル (文語)むくいる、報道する。「首相の訪朝が報じられた」
1475 ほうずる 奉ずる サ変・−ズル (文語)うけたまわる。
1476 ほうずる 崩ずる サ変・−ズル (文語)くずれる、崩御する。
1477 ほかん 保管 * 大事に保存すること。「金品を保管する」
15061478 ほかん 補完 * 足りないところを補うこと。「言葉を補完する」
15071479 ほけん 保健 * 健康を保つこと。「保健室」
1508 ほけん 保険 * 1. 加入者から掛け金を集め、取り決めたこと(偶然の事故など)があったときに補償金を支払う制度。「保険に加入する」\n2. あてにしていることがうまくいかなかったときのために用意しておくこと。また、それに使うもの。「行きつけの店が休みのときの保険として他の店を見ておく」
1480 ほけん 保険 * 事故などのときに積立金から補償を行う制度。「保険金詐欺」
15091481 ほしょう 保証 * 確かだということに責任を持つこと。「借金の保証人」
1510 ほしょう 保障 * ある状態や水準を守ること。「安全保障」「失業者の生活保障」
1482 ほしょう 保障 * 障害からまもること。「安全保障」
15111483 ほしょう 補償 * 損害などを補うこと。「事故の補償金」
1512 ほしょうきん 保証金 * 債務などの担保として支払う金。「家を借りるのに保証金を払う」
1513 ほしょうきん 補償金 * 損害を補うための金。「事故の被害に対する補償金をもらった」
1514 ほせい 補整 * 補って整えること。「句読点を補整する」\n※まれ。主に「補正」が使われる。
1515 ほせい 補正 * 調整して、正しい、または望ましい状態にすること。「補正予算」「手ぶれを補正する」
1516 ほそく 捕捉 * つかまえること。また、レーダーなどで検知すること。「目標を捕捉する」
1517 ほそく 補足 * 足りないところを補うこと。「彼の説明を補足します」
1484 ほしょうきん 保証金 * 債務の担保として支払う金。
1485 ほしょうきん 補償金 * 損害をおぎなうための金。
1486 ほせい 補整 * 補い整えること。「露出を補整する」
1487 ほせい 補正 * 補い正すこと。「補正予算」
1488 ほそく 捕捉 * とらえること。「目標を捕捉する」
1489 ほそく 補足 * 補い足すこと。「彼の説明を補足します」
15181490 ぼたん 牡丹 * ボタン科の木。
1519 ぼたん 釦 * 〈主にカタカナ〉\n1. 服をとめるもの。「ボタンをかけちがえる」\n2. 押すことによって機械を制御する小さな突起物。また、それを模したコンピュータ画面上の表現。「火災を通報するためのボタン」「ボタンをマウスでクリックする」
1491 ぼたん 釦 * 服をとめるもの。「釦をかけちがえる」
15201492 ほどう 舗道 * 舗装された道路。
1521 ほどう 歩道 * 歩く人のための道。
1522 ほひつ 補弼 * 君主の政治を補佐すること。
1493 ほどう 歩道 * 歩くための道路。
1494 ほひつ 補弼 * 政治を補うこと。
15231495 ほひつ 補筆 * 補って書くこと。
1524 ほる 掘る 五段・ラ行 1. 地面の土を取り除く、または平たいものの一部を削るなどしてくぼみをつくる。「土を掘る」「壁に穴を掘る」\n2. 地面の土を取り除いて、埋まっているものを取り出す。「サツマイモを掘る」
1525 ほる 彫る 五段・ラ行 1. きざみこむ。「板に文字を彫る」\n2. 材料を削ってつくりあげる。「熊の彫刻を彫る」
1526 ほんい 本位 * 〈接尾語〉~を基準とする。「自分本位の勝手な考え」「金本位制度」
1527 ほんい 本意 * 本当の意志。本来意図するところ。「それは私の本意ではない」
1528 ほんい 翻意 * 決めたことを変えること。「説得して翻意を促した」
1496 ほる 掘る 五段・ラ行 穴をあける。「土を掘る」
1497 ほる 彫る 五段・ラ行 彫刻をほどこす。「熊の彫刻を彫る」
1498 ほんい 本位 * 基本となるもの。「自分本位の勝手な考え」
1499 ほんい 本意 * 本当の意志。「本意ではないが」
15291500 ほんだい 本代 * 本の代金。
15301501 ほんだい 本題 * 中心となる題目。「本題に入ります」
15311502 ほんりゅう 奔流 * 激しい流れ。「時代の奔流に流される」
1532 ほんりゅう 本流 * 1. (分岐する河川の)もっとも大きな流れ。「本流に支流が合流する」\n2. (情勢の)もっとも大きな、または伝統のある流れ。「社内の本流」「保守本流」
1533 まかす 委す 五段・サ行 →任す
1534 まかす 任す 五段・サ行 〈「委す」とも〉\nゆだねる。任せる。「仕事を任す」「想像に任す」
1503 ほんりゅう 本流 * もとの流れ。
1504 まかす 委す 五段・サ行 (「任す」と区別なし)ゆだねる。「仕事を委す、想像に委す」
1505 まかす 任す 五段・サ行 (「委す」と区別なし、一般的)ゆだねる。「仕事を任す、想像に任す」
15351506 まかす 負かす 五段・サ行 負けさせる。「試合で相手を負かす」
1536 まかせる 委せる 一段 →任せる
1537 まかせる 任せる 一段 〈「委せる」とも〉\n1. ゆだねる。相手の自由にさせる。「仕事を任せる」「後は想像に任せます」\n2. 〈「意に任せる」として、主に否定形で〉〈文語〉思うようになる。「なかなか意に任せない」
1538 まく 巻く 五段・カ行イ音便 〈「捲く」とも〉\n1. 薄いものや細いものを、その端や別のもののまわりに沿って回し、からみつかせる。また、それをきつくする。また、そのようになる。「糸を巻く」「傷に包帯を巻く」「ぜんまいを巻く」「葉が巻く」\n2. (渦などが)できる。「渦を巻く」\n3. 慣用句の一部として使われる。「煙(けむ)に巻く」(=理解しにくいことを話して相手を混乱させる)「舌を巻く」(=感心する)「管を巻く」(=くどくどと同じようなことを何度もしゃべる)
1539 まく 捲く 五段・カ行イ音便 →巻く
1540 まく 撒く 五段・カ行イ音便 〈かな書きも〉\n1. (粉や液体を)散らばらせる。かける。散布する。「水を撒く」\n2. (紙などを、散布や手渡し・郵送などで)広範囲に行き渡らせる。「ビラを撒く」\n3. 〈「巻く」とも〉(追跡するものの)視野から逃れる。「車の速度を上げて追跡を撒く」
1541 まく 蒔く 五段・カ行イ音便 〈かな書きも〉(成長させる目的で、種を地面に)散らばらせる。または、地中に埋める。「種を蒔く」
1542 まく 幕 * 1. 上から垂らす布。特に、劇場などで舞台の前に垂らす布。「垂幕」「幕を下ろす」\n2. 1によって区切られる一場面。「第二幕」\n3. 1が下りて、出し物が終了すること。また一般に、終了すること。「勝利の場面で幕となった」「この事件は犯人逮捕で幕となった」\n4. 〈「出る幕」として〉かかわる場面。「親の出る幕じゃない」
1543 まく 膜 * 薄い皮。「半透膜」「牛乳が膜を張る」
1544 まざる 交ざる 五段・ラ行 〈「混ざる」が一般的〉違う種類のものが入り込んでまぎれる。「商品に偽物が交ざる」
1545 まざる 混ざる 五段・ラ行 1. 〈「交ざる」とも〉違う種類のものが入り込んでまぎれる。「商品に偽物が混ざる」\n2. 液体や気体に、別のものが入って一体となる。「淡水に海水が混ざる」
1546 まじる 交じる 五段・ラ行 〈「混じる」が一般的〉\n1. 違う種類のものが入り込んでまぎれる。「商品に偽物が交じる」\n2. 違う性質の集団に入る。「若者に交じって勉強する」
1547 まじる 混じる 五段・ラ行 1. 〈「交じる」とも〉違う種類のものが入り込んでまぎれる。「商品に偽物が混ざる」\n2. 液体や気体に、違う種類のものが入って一体となる。「淡水に海水が混じる」\n3. 〈「交じる」とも〉違う性質の集団に入る。「若者に混じって勉強する」
1507 まかせる 委せる 一段 (「任せる」と区別なし)ゆだねる。「仕事を委せる、後は想像に委せます」
1508 まかせる 任せる 一段 (「委せる」と区別なし、一般的)ゆだねる。「仕事を任せる、後は想像に任せます」
1509 まく 巻く 五段・カ行イ音便 (「捲く」と区別なし、一般的)くるくるとたたむ。「包帯を巻く、ぜんまいを巻く、舌を巻く」
1510 まく 捲く 五段・カ行イ音便 (「巻く」と区別なし)くるくるとたたむ。「包帯を捲く、ぜんまいを捲く、舌を捲く」
1511 まく 撒く 五段・カ行イ音便 散らばらせる。「水を撒く、ビラを撒く、追跡を撒く」
1512 まく 蒔く 五段・カ行イ音便 種を植える。「種を蒔く」
1513 まく 幕 * 空間を分けるための布。「垂幕、開幕」
1514 まく 膜 * うすい皮。「半透膜、粘膜、角膜」
1515 まざる 交ざる 五段・ラ行 異種のものが一緒になる。「偽物が交ざる」
1516 まざる 混ざる 五段・ラ行 複数のものがひとつになる。「砂に塩が混ざる」
1517 まじる 交じる 五段・ラ行 異種のものが一緒になる。「偽物が交じる」
1518 まじる 混じる 五段・ラ行 複数のものがひとつになる。「砂に塩が混じる」
15481519 ます 升 * 米などをはかるうつわ。
1549 ます 鱒 * 〈かな書きも〉サケ科の魚。
1550 まぜる 交ぜる 一段 〈「混ぜる」が一般的〉違う種類のものを入れてまぎれさせる、または一体とする。「商品に偽物を交ぜる」
1551 まじる 混ぜる 五段・ラ行 1. 〈「交ぜる」とも〉違う種類のものを入れてまぎれさせる。「商品に偽物を混ぜる」\n2. 液体や気体に、違う種類のものを入れて一体とする。「淡水に海水を混ぜる」
1552 まち 街 * 〈「町」とも〉にぎやかな通り。「街に出る」
1553 まち 町 * 1. 〈「街」とも〉家や商店などが集まっている場所。「町なかに住む」\n2. 地方公共団体のひとつ。町(ちょう)。「町役場」
1554 まつる 祭る 五段・ラ行 →祀る
1555 まつる 奉る 五段・ラ行 〈文語〉さしあげる。「神号を奉られた」
1556 まつる 祀る 五段・ラ行 〈「祭る」とも〉\n1. (死者や神仏を)あがめ、安置する。「死者を祀る場」\n2. (死者や神仏を)あがめ、儀式を行う。「死者を祀る祝日」
1557 まつる 纏る 五段・ラ行 〈主にかな書き〉まつり縫いをする。「スカートの裾をまつる」
1558 まゆ 眉 * 目の少し上に生えている毛。「眉毛」「眉をひそめる」(=不快な気持ちをあらわにする)
1559 まゆ 繭 * 蚕などが、変態にあたってさなぎを保護するために糸を吐いて作るもの。「繭を生産している農家」
1560 まわり 回り * 〈「廻り」とも〉\n1. (さまざまな意味で)回ること。回りぐあい。「換気扇の回りが悪い」「地方回り」「酒の回りが早い」\n2. 〈接尾語〉〈「周り」とも〉…にかかわる部分。「水回りのトラブル」 \n3. 〈助数詞〉回る回数をあらわす。「ひと回りする」\n4. 大きさなどの差について、主観的な一段階ぶんをあらわす。年齢については、干支(えと)のひと回りである12年をあらわす。「普通のものよりふた回りほど小さい」「年齢がひと回り近く離れている」
1561 まわり 廻り * →回り
1562 まわり 周り * 〈「回り」とも〉取り囲むあたり。周囲。周辺。「駅の周りには何もない」「周りの人がじゃまだ」
1563 みえ 見栄 * 他人に自分をよく見せようとすること。虚栄心。「彼女は見栄を張りすぎだ」「見栄のためにブランド品を買う」
1564 みえ 見得 * 1. 〈「見得を切る」として〉役者が一瞬止まりポーズをとること。「役者が見得を切った」\n2. 〈特に「大見得を切る」として〉おおげさに話す。また、大口をたたく。「一人の犠牲者も出さないと大見得を切った」
1565 みことのり 詔 * 天皇のことば。古くは、大事の際の天皇のことばを指した。
1566 みことのり 勅 * 古く、小事の際の天皇のことばを指した。
1567 みだす 見出す 五段・サ行 見はじめる。「しかられているのにテレビを見出した」
1568 みだす 乱す 五段・サ行 乱れさせる。「風紀を乱す」「集中力を乱す」
1520 ます 鱒 * サケ科の魚。
1521 まち 街 * 繁華街などをさす。「繁華街」
1522 まち 町 * 家などが集まっている場所。「町内会」
1523 まつる 祭る 五段・ラ行 祈願する。「月を祭る」
1524 まつる 奉る 五段・ラ行 さしあげる。「讃え奉る」
1525 まま 間々 * 母親の英語表現。
1526 まま 儘 * その状態が保たれること。「その儘でいてくれ、なすが儘」
1527 まゆ 眉 * 目の上に生えている毛。「眉毛、眉をひそめる」
1528 まゆ 繭 * 蚕などが自分を保護するために作るもの。「繭を生産している農家」
1529 まわり 回り * (「廻り」と区別なし、一般的)まわること。「金回りがよい、ひと回りする」
1530 まわり 廻り * (「回り」と区別なし)まわること。「金廻りがよい、ひと廻りする」
1531 まわり 周り * 取り囲むもの、場所。「駅の周りには何もない、周りの人が邪魔だ」
1532 みえ 見栄 * 他人からよく見られようとすること。「彼女は見栄を張りすぎだ」
1533 みえ 見得 * 役者が一瞬止まりポーズをとること。「彼が見得を切った」
1534 みことのり 詔 * 大事の際の天皇のことば。
1535 みことのり 勅 * 小事の際の天皇のことば。
1536 みず 水 * 水素分子が2つと酸素分子が1つ化合したもの。「水を得た魚、水に流す」
1537 みず 瑞 * みずみずしいこと。
1538 みだす 見出す 五段・サ行 見はじめる、見つけ出す。「写真を見出した、彼の才能を見出す」
1539 みだす 乱す 五段・サ行 乱れさせる。「風紀を乱す、集中力を乱す」
15691540 みつりょう 密漁 * 違法に漁を行なう。「禁漁区域で魚を密漁する」
15701541 みつりょう 密猟 * 違法に猟を行なう。「鹿を密猟する」
1571 みとる 看取る 五段・ラ行 臨終に付き添う。「親の臨終を看取る」\n※「見取る」とも。
1572 みとる 見取る 五段・ラ行 見て理解する。見て取る。「彼の本心を見取る」
1573 みにくい 見にくい 形容詞・アウオ段 見ることが難しい。また、見て理解しにくい。「色が多くて地下鉄の路線図が見にくい」
1574 みにくい 醜い 形容詞・アウオ段 見た目がよくない。または、嫌悪をもよおすほど悪い。醜悪である。「醜いアヒルの子」「醜い心根」
1575 みはる 見張る 五段・ラ行 1. あたりを見渡して番をする。「倉庫を見張る」\n2. 〈「瞠る」とも〉(目を)大きく開いて見つめる。「目を見張る」「目を見張るような(=すばらしい)美しさ」
1576 みはる 瞠る 五段・ラ行 →見張る2
1577 みる 看る 一段 →見る5
1578 みる 観る 一段 (出し物などを)観賞する。「映画を観る」「ビデオを観る」→見る2
1579 みる 見る 一段 〈「視る」とも〉\n1. 目でとらえる。「リンゴを見る」\n2. 〈「観る」とも〉(出し物などを)観賞する。「映画を見る」「ビデオを見る」\n3. 目で確認して、批評や訂正をする。「学生の論文を見てやった」\n4. 確かめる。観察して判断する。「様子を見る」「ブレーキの調子を見る」\n5. 〈「看る」とも〉世話をする。「寝たきりの親の面倒を見る」\n6. 推測する。みなす。「殺人と見て捜査する」\n7. 〈「~な目を見る」として〉(いやなことを)経験する。「大変な目を見た」
1580 みる 視る 一段 →見る
1542 みとる 看取る 五段・ラ行 看病する。「寝たきりの親を看取る」
1543 みとる 見取る 五段・ラ行 見てわかる。「彼の本心を見取る」
1544 みにくい 見にくい 形容詞・アウオ段 見るのが難しい。「見にくい形をしている」
1545 みにくい 醜い 形容詞・アウオ段 外見がみっともない。「醜いアヒルの子」
1546 みはる 見張る 五段・ラ行 あたりを見渡して番をする。「倉庫を見張る」
1547 みはる 瞠る 五段・ラ行 目を大きく開いて見つめる。「目を瞠る」
1548 みょうばん 明晩 * 次の日の晩。
1549 みる 看る 一段 看病する。「寝た切りの親の面倒を看る」
1550 みる 観る 一段 観覧する。「芝居を観る」
1551 みる 見る 一段 目で感じる。「リンゴを見る、彼を見る、様子を見る、甘く見すぎていた」
1552 みる 視る 一段 視察する。「被災地を視る」
15811553 みる 診る 一段 診察する。「患者を診る」
1582 みんせい 民政 * 1. 民衆にかかわる政治。「民政局」\n2. 文民による政治。「軍政から民政に移行する」
1554 みんせい 民政 * 民生のための政治。「民政党」
15831555 みんせい 民生 * 民衆の生活。「民生委員」
15841556 みんぞく 民俗 * 民衆の伝統的な文化。「民俗芸能」
1585 みんぞく 民族 * 同じ言語や文化・歴史などを共有し、一体感を持つ人々の集まり。「民族主義」「民族大移動」
1586 むえん 無縁 * 1. 縁がないこと。「汚職とは無縁である」\n2. 縁者がいないこと。「無縁墓地」
1587 むえん 無鉛 * 鉛を含まないこと。「無鉛ガソリン」
1557 みんぞく 民族 * 同じ文化を持つ集り。「民族主義、民族大移動」
1558 むえん 無縁 * 縁がないこと。「汚職とは無縁である、無縁墓地」
1559 むえん 無鉛 * 鉛を含まないこと。
15881560 むえん 無塩 * 塩を含まないこと。「無塩のトマトジュース」
1589 むく 向く 五段・カ行イ音便 1. (ある方向に対して)顔など、主な部分が正面になるように動く。「彼の方を向く」\n2. 適する。ちょうどいい。「この仕事は彼の性格に向いている」\n3. (意識などが、ある対象に)動く。「気が向かない」(=やる気にならない)
1590 むく 剥く 五段・カ行イ音便 〈かな書きも〉\n1. (皮などを)取り去って中身だけにする。「リンゴを剥く」「ミカンの皮をを剥く」\n2. (目や歯を)露出させる。「目を剥いて怒った」「牙を剥く」
1591 むしょう 無償 * 報酬、または代金のないこと。「無償で働く」「無償で貸し出す」
1592 むしょう 無性 * 〈「無性に」として〉(欲求などに関して)やたらに。「無性に食べたくなる」
1593 むじょう 無上 * この上なくよい・大きいこと。「無上の喜び」
1594 むじょう 無常 * 全てのものははかなく滅びるということ。また、はかなさ。「人生の無常を感じる」
1595 むじょう 無情 * 情けをかけないこと。容赦のないこと。「無情にも最後の望みが絶たれた」
1596 むめい 無名 * 1. 名前が広く知られていないこと。「無名の新人」\n2. 名前のついていないこと。「無名の山に名前をつけた」\n3. 名前が記入されていないこと。無記名。「無名の手紙」
1561 むく 向く 五段・カ行イ音便 正面になるように動く。「彼の方を向く、気が向く、彼の性格に向いている」
1562 むく 剥く 五段・カ行イ音便 皮などを取り除く。「リンゴの皮を剥く」
1563 むくろ 骸 * 死体。
1564 むくろ 躯 * 体。
1565 むしょう 無償 * 報いのないこと。「無償で働く」
1566 むしょう 無性 * 心がなくなること。「無性に食べたくなる」
1567 むじょう 無常 * 全てのものははかなく滅びるという真理。「諸行無常の響きあり」
1568 むじょう 無情 * 情けのないこと。「無情にも最後の望みが絶たれた」
1569 むめい 無名 * 名前が知られていないこと。「無名の新人」
15971570 むめい 無銘 * 作者の名前が入ってないこと。
1598 むれる 群れる 一段 1. (動物が)1か所に集まる。「羊が群れる」\n2. (人間が)集団を作る。徒党を組む。「仲良し同士で群れる」
1599 むれる 蒸れる 一段 1. 湿気がこもる。「靴が蒸れる」\n2. 蒸していたものができあがる。「シュウマイが蒸れる」
1600 め 眼 * →目
1601 め 目 * 〈「眼」とも〉\n1. 光を感じる感覚器。「目を見つめる」\n2. 視線。「冷静な目で判断する」\n3. 〈「見た目」として〉外見。「見た目がよくない」\n4. 〈形容詞に続いて〉経験。「ひどい目にあった」\n5. (台風などの)中心。「台風の目」\n6. 穴があいているところ。「目が細かいざる」\n7. (さいころの)数字をあらわすためにつけた点。また、転がして上になったその数。「同じ目が2回連続で出た」\n8. 〈接尾語〉助数詞に付き、はじめからの数ということを示す。「3回目の挑戦」
1602 めいかい 明解 * 1. わかりやすいこと。「明解な文章」\n2. はっきりと解説すること。
1603 めいかい 明快 * すっきりとわかりやすいこと。「明快な返事をした」「単純明快」
1571 むれる 群れる 一段 一つに集まる。「羊が群れている。」
1572 むれる 蒸れる 一段 湿気がこもる。「靴が蒸れる、シュウマイが蒸れる」
1573 め 眼 * 眼球。「」
1574 め 目 * 光を感じる感覚器。「目を見つめる、目が冴える、目が点になる」
1575 めいかい 明解 * はっきりとわかること。
1576 めいかい 明快 * 明らかで快いこと。「単純明快」
16041577 めいき 明記 * はっきりと記すこと。「条件を明記する」
1605 めいき 銘記 * 心に刻んで忘れないこと。「教えを銘記する」
1578 めいき 銘記 * 忘れないこと。「教えを銘記する」
16061579 めいずる 命ずる サ変・−ズル 命令する。「転勤を命ずる」
1607 めいずる 銘ずる サ変・−ズル 1. 〈文語〉きざみつける。「石に名を銘ずる」\n2. 〈「肝に銘ずる」として〉心にしっかりと刻みつける。
1608 もうける 設ける 一段 1. (場などを)用意する。「懇親会を設ける」「給水所を設ける」\n2. (建物・規則・組織などを)新たに作る。設置・設定する。「制限を設ける」「部署を設ける」
1609 もうける 儲ける 一段 1. 金銭的な利益を得る。「株で儲ける」\n2. 〈口語〉意外なことで得をする。「うちのチーム不戦勝だってさ。儲けたな」\n3. 〈主にかな書き〉子供をもつ。「一子をもうけた」
1610 もえる 燃える 一段 1. 炎が立つ。燃焼する。「家が燃える」\n2. 情熱がわきおこる。「心が燃える」「だんだん燃えてきた」
1611 もえる 萌える 一段 1. 芽が出る。「草木が萌える」\n2. 〈若者言葉〉可愛らしいと感じ、愛情や保護欲をかきたてられる。また、そのような感情を起こす。「彼女の上目遣いに萌えた」「萌える絵」
1580 めいずる 銘ずる サ変・−ズル きざみつける。「肝に銘ずる」
1581 もうける 設ける 一段 用意する。「懇親会を設ける、給水所を設ける」
1582 もうける 儲ける 一段 利益を得る。「株で儲ける」
1583 もえる 燃える 一段 炎が立つ。「家が燃える、心が燃える」
1584 もえる 萌える 一段 芽が出る。
16121585 もくする 黙する サ変・−スル 黙る。「黙して語らず」
1613 もくする 目する サ変・−スル 1. そうではないかと推測する。「犯人と目される」\n2. 将来そうなるのではないかと推測する。「次期社長と目される」\n3. 有望視する。嘱望する。「将来を目される小説家」
1614 もっこう 木瓜 * 紋の名。
1615 もっこう 木工 * 1. 木材を使って工作すること。\n2. 〈文語〉大工。
1616 もの 者 * 〈修飾句に続いて〉人。へりくだるとき、責めるときや、文語体の文などで用いられる。「部下の者が失礼をいたしました」「活動を妨害する者がいる」「免許を有する者」
1617 もの 物 * 1. 物体。手に取れるような対象。「部屋に物が多い」「持参する物」\n2. 商品の品質。「物はいいが値段が高い」\n3. 具体的に対象を示さないとき、一部の動詞の目的語として使う。「物を食べる」「物を考える」「物を書く」\n4. 〈主にかな書き〉無生物に対し、形式名詞として使う。「果物を切ったものを皿に載せる」「この靴は彼のものだ」
1618 もも 股 * →腿
1619 もも 腿 * 〈「股」とも〉足の、膝から付け根までの部分。特に、その柔らかい部分。ふともも。「腿をたたいた」
1620 もも 桃 * 夏に、食用となる果実をつけるバラ科の木。また、その果実。「熟した桃」
1621 もる 洩る 五段・ラ行 →漏る
1622 もる 盛る 五段・ラ行 1. 山状に積み上げる。「土を盛る」「丼にご飯を盛る」「果物をざるに盛る」\n2. (食べ物などに、毒を)知られないように入れて飲ませる。「毒を盛る」「一服盛られた」\n3. (文章や条項などに)含める。「計画を報告書に盛る」\n4. 〈若者言葉〉髪を山状に整える。「頭を盛る」\n5. 〈若者言葉〉おおげさに言う。誇張する。「話盛ってるんじゃないの」
1623 もる 漏る 五段・ラ行 〈「洩る」とも〉(水などが)もれる。「天井から水が漏る」
1624 やく 焼く 五段・カ行イ音便 1. 火をつけて燃やす。または、火にかけて加熱する。また、そのようにしてつくる。「紙を焼く」「芋を焼く」「ケーキを焼く」\n2. (肌を)日光などに当てて濃い色にする。「肌を焼く」\n3. (光メディアに、データを)記録する。「ISOイメージを焼く」\n4. 〈「手を焼く」として〉扱いに苦労する。〈「世話を焼く」として〉世話をする。〈「焼き餅を焼く」として〉嫉妬する。→妬く
1625 やく 妬く 五段・カ行イ音便 嫉妬する。「あの人とよく一緒にいるからって妬いてるみたい」
1626 やくしゃ 役者 * 1. 役柄を演じる人。「ひいきの役者」\n2. 演技のうまい人。「お前は役者だな」
1627 やくしゃ 訳者 * 翻訳をした人。翻訳者。「この本の訳者」
1628 やくす 約す 五段・サ行 約束する。「再会を約す」
1586 もくする 目する サ変・−スル 見る。「将来を目される」
1587 もつ 持つ 五段・タ行 手にとる。「箸を持つ、肩を持つ、強い気持を持つ」
1588 もっこう 木瓜 * バイカアマチャという植物。
1589 もっこう 木工 * 大工。
1590 もの 者 * 人をさす。
1591 もの 物 * 生き物以外をさす。
1592 もむ 揉む 五段・マ行 力を加えて柔くする。「土を揉む、肩を揉む、人ごみに揉まれる」
1593 もも 股 * (「腿」と区別なし)足で膝よりも上の部分。
1594 もも 腿 * (「股」と区別なし)足で膝よりも上の部分。
1595 もも 桃 * バラ科の植物。
1596 もる 洩る 五段・ラ行 (「漏る」と区別なし)水などがこぼれる。「天井から水が洩る」
1597 もる 盛る 五段・ラ行 積上げる。「土を盛る、毒を盛る」
1598 もる 漏る 五段・ラ行 (「洩る」と区別なし、一般的)水などがこぼれる。「天井から水が漏る」
1599 やかた 屋形 * 屋根の形をしているもの。「屋形船」
1600 やかた 館 * やしき。
1601 やく 焼く 五段・カ行イ音便 火で燃やす。「紙を焼く、芋を焼く、手を焼く」
1602 やく 妬く 五段・カ行イ音便 嫉妬する。「彼の行動に妬く」
1603 やくしゃ 役者 * 役柄を演じる人。「大根役者」
1604 やくしゃ 訳者 * 翻訳をする人。「この本の訳者」
1605 やくす 約す 五段・サ行 要約する。「説明を約す」
16291606 やくす 訳す 五段・サ行 翻訳する。「英文を日本語文に訳す」
1630 やこう 夜光 * 暗いところで光ること。「夜光虫」「夜光時計」
1631 やこう 夜行 * 1. 夜に行くこと。「夜行バス」\n2. 夜に行動すること。「夜行動物」
1632 やさしい 易しい 形容詞・イ段 〈かな書きも〉わかりやすい、またはやりやすい。簡単、容易である。「この問題は易しい」「易しい手品」
1633 やさしい 優しい 形容詞・イ段 〈かな書きも〉\n1. やわらかく、とげとげしくない。「優しい音楽」\n2. 思いやりや気づかいがある。「優しい子供」
1607 やこう 夜光 * よるのあかり。「夜光虫、夜光時計」
1608 やこう 夜行 * 夜に行くこと。「夜行バス」
1609 やさしい 易しい 形容詞・イ段 簡単である。「この問題は易しい、易しい言葉で話す」
1610 やさしい 優しい 形容詞・イ段 気づかいがある。「彼が優しい言葉をかけてくれた」
16341611 やすい 安い 形容詞・アウオ段 値段が低い。「安い服」
1635 やすい 易い 形容詞・アウオ段 〈動詞の連用形に続いて〉\n1. 簡単である。「解き易い問題」\n2. すぐにそうなる。「壊れ易い品物」
1636 やむ 止む 五段・マ行 (続いていた雨・音などが)とまる。「雨が止む」「電話の音が止む」
1637 やむ 病む 五段・マ行 1. 病気になる。「心身が病む」「気を病む」(=心配する)\n2. 〈若者言葉〉〈「病んでる」として〉精神・行動が正常でない。「そこまで束縛するなんて、その彼絶対病んでるって」
1638 やめる 止める 一段 〈主にかな書き〉していたことをしなくなる、またはする予定だったことをしないことにする。「話すのをやめる」「参加するのをやめる」
1639 やめる 辞める 一段 (職などから)離れる。辞す。「会社を辞める」
1612 やすい 易い 形容詞・アウオ段 簡単である。「解き易い問題」
1613 やむ 止む 五段・マ行 とまる。「雨が止む」
1614 やむ 病む 五段・マ行 病気になる。「心を病む」
1615 やめる 止める 一段 終わらせる。「話すのを止める、参加するのを止める」
1616 やめる 辞める 一段 (仕事などから)はなれる。「会社を辞める」
16401617 やる 遣る 五段・ラ行 行かせる。「おつかいに遣る」
1641 やわらか 柔らか * 1. 〈「軟らか」とも〉力を加えると形をすぐ変えるようす。かたくないようす。「柔らかなクッション」\n2. おだやかであるようす。「柔らかな表情」
1642 やわらか 軟らか * →柔らか1
1643 やわらかい 柔らかい 形容詞・アウオ段 1. 〈汎用的〉力を加えると形をすぐ変える。かたくない。「柔らかいクッション」「体が柔らかい」「柔らかい肉」「野菜を柔らかく煮る」\n2. おだやかである。「柔らかい表情」
1644 やわらかい 軟らかい 形容詞・アウオ段 1. 柔らかい1 に同じ。特に、ぐにゃぐにゃしたものに対して使う。「軟らかい肉」「野菜を軟らかく煮る」\n2. (水について)カルシウムやマグネシウムのイオン含有量が少ない。硬度が低い。軟水である。「軟らかい水」
1645 ゆうせい 優勢 * 勢いが優ること。形勢がよいこと。「こっちのチームが優勢だ」
1646 ゆうせい 優性 * (遺伝子が)対立する遺伝子と組み合わされたときに、相手のものではなくみずからの形質をあらわすこと。「優性遺伝」
1647 ゆうせい 優生 * すぐれているとされる遺伝的形質をもつこと。また、そのようなものを残そうとすること。「優生学」
1618 やわらか 柔らか * ふっくらしている。「柔らかなクッション」
1619 やわらか 軟らか * 硬くない。「軟らかな表情」
1620 やわらかい 柔らかい 形容詞・アウオ段 ふっくらしている。「柔らかいクッション」
1621 やわらかい 軟らかい 形容詞・アウオ段 硬くない。「軟らかい表情」
1622 ゆうせい 優勢 * 勢いが優ること。「こっちのチームが優勢だ」
1623 ゆうせい 優性 * 他の遺伝子とくっついたときに発現する性質。「優勢遺伝」
1624 ゆうせい 優生 * 優秀な生体のこと。「優生学」
16481625 ゆうせい 有性 * 雌雄があること。「有性生殖」
16491626 ゆうせい 遊星 * 惑星のこと。
16501627 ゆうせい 郵政 * 郵便事業のこと。「郵政民営化」
1651 ゆうせい 雄性 * (動植物の)おす。
1652 ゆうわ 宥和 * 敵などに対し、要求を少なくしたり譲歩したりして関係を保とうとすること。「宥和政策」
1653 ゆうわ 融和 * (人が)仲よくまじりあうこと。「民族が融和する」
1654 ゆく 往く 五段・カ行イ音便 →行く
1655 ゆく 行く 五段・カ行促音便ユク 〈「往く」とも〉今の場所から移動する。「海に行く」
1628 ゆうせい 雄性 * おす。
1629 ゆうわ 宥和 * ゆるして仲良くすること。「宥和政策」
1630 ゆうわ 融和 * とけあって、仲良くすること。「民族が融和する」
1631 ゆく 往く 五段・カ行イ音便 (「行く」と区別なし)向かう、移動する。「往く年」
1632 ゆく 行く 五段・カ行促音便ユク (「往く」と区別なし、一般的)向かう、移動する。「海に行く」
16561633 ゆく 逝く 五段・カ行促音便 死ぬ。「父親が逝く」
1657 よい 好い 形容詞・アウオ段 →良い
1658 よい 善い 形容詞・アウオ段 〈まれ〉道徳的に正しい。「善い行ない」→良い2
1659 よい 良い 形容詞・アウオ段 1. 〈「好い」とも〉好ましい。すぐれている。望ましい状態である。「良い商品」「良い天気」「頭が良い」「気持ちが良い」\n2. 〈まれに「善い」とも〉道徳的に正しい。「良い行い」
1634 よい 好い 形容詞・アウオ段 (「良い」と区別なし)好ましい。「好い商品、好い天気」
1635 よい 善い 形容詞・アウオ段 正しい。「善い行ない」
1636 よい 良い 形容詞・アウオ段 (「好い」と区別なし、一般的)好ましい。「良い商品、良い天気、頭が良い、気持ちが良い」
16601637 よういん 要員 * 必要な人員。「作業要員」
16611638 よういん 要因 * おもだった原因。「負けた要因」
1662 ようかい 容喙 * 口出しすること。「容喙を許さない」
1663 ようかい 溶解 * 1. 液体にまざり、均一になること。「食塩を水に溶解させる」\n2. 〈金属の場合は「熔解」とも〉固体が熱により液体になること。「氷河が溶解する」「溶解炉」
1664 ようかい 熔解 * 〈「溶解」とも〉(金属について)固体が熱により液体になること。「熔解炉」
1665 ようけん 用件 * 用事。「用件を伺います」「用件のみにて失礼します」
1666 ようけん 要件 * 1. 必要な条件。「この商品は要件を満たしている」\n2. 〈まれ〉主要な内容。「要件のみにて失礼します」
1667 ようせつ 溶接 * 〈「熔接」とも〉(金属などを)溶かしてくっつけること。「柱を溶接する」
1668 ようせつ 熔接 * →溶接
1639 ようかい 容喙 * 口出しすること。
1640 ようかい 溶解 * とけること。「氷河が溶解する、溶解炉」
1641 ようかい 熔解 * 固体が熱により液体になること。「熔解炉」
1642 ようけん 用件 * 用事。「用件を伺います」
1643 ようけん 要件 * 必要な条件。「この商品は用件を満たしている」
1644 ようせつ 溶接 * (「熔接」と区別なし)金属などを溶かしてくっつけること。「柱を溶接する」
1645 ようせつ 熔接 * (「溶接」と区別なし)金属などを溶かしてくっつけること。「柱を熔接する」
16691646 ようせつ 夭折 * 若いうちに死ぬこと。
16701647 よじょう 余剰 * あまり。「余剰人員」
1671 よじょう 余情 * 残るような味わい。「余情がない」
1672 よす 止す 五段・サ行 〈主にかな書き〉やめる。「いたずらをよす」
1673 よぶ 呼ぶ 五段・バ行 1. 声をかける。「彼の名前を呼ぶ」\n2. 声をかけて、あるいは連絡して来させる。「妹を呼ぶ」「鑑識を呼ぶ」「友達を懇親会に呼ぶ」\n3. 人や物を指すのに、ある名前を使う。名付ける。「彼をあだ名で呼ぶ」「部長と呼ぶ」\n4. (人気などを)集める。「大変な人気を呼んだ」
1648 よじょう 余情 * のこるような味わい。
1649 よす 止す 五段・サ行 やめる。「悪戯を止す」
1650 よぶ 呼ぶ 五段・バ行 名前を叫ぶ。「彼の名前を呼ぶ、懇親会に呼ぶ、彼を仇名で呼ぶ」
16741651 よむ 詠む 五段・マ行 詩歌をつくる。「一句詠む」
1675 よむ 読む 五段・マ行 1. 文字として書かれたものを見て、それを声に出して聞かせる。「子供に絵本を読んでやる」\n2. 文字を見て意味を理解する。「本を読む」\n3. 状況を見てとり、心情や内情や、将来などを予測する。「市場を読む」「表情を読む」「一手先を読む」
1676 よる 依る 五段・ラ行 〈主にかな書き〉\n1. (別のものに)頼る。依存する。「努力によるところが大きい」\n2. (別のものの程度や性質に)従う。応じる。「人によって感じ方が違う」\n3. 手段とする。「血液検査により診断する」\n4. 受身文で、動作主を明示するために使う。…に。「独裁者によって占領された」
1677 よる 因る 五段・ラ行 〈主にかな長き〉(事象について)原因となる。「ウィルスによる障害」
1678 よる 寄る 五段・ラ行 1. 近づく。「そばに寄る」\n2. 集まる。「日本人同士が寄ると日本語を使ってしまう」\n3. 場所が一方向にずれる。「北に少し寄ったところに引っ越す」「画像が少し寄ってしまった」\n4. 一方にかたよる。「弁当を縦に運んだら寄ってしまった」\n5. ついでに行く。立ち寄る。「店に寄る」\n6. (しわが)できる。「服にしわが寄る」
1679 よる 拠る 五段・ラ行 〈主にかな書き〉根拠とする。もとづく。「国連決議による攻撃」「彼女の説明によると」
1680 よる 選る 五段・ラ行 〈文語〉選ぶ。
1681 よる 撚る 五段・ラ行 〈「縒る」とも〉〈かな書きも〉(糸などについて)ねじりあわせる。また、そうして作る。「糸を撚る」「ひもを撚る」
1682 よる 縒る 五段・ラ行 →撚る
1683 よろこぶ 悦ぶ 五段・バ行 →喜ぶ
1684 よろこぶ 歓ぶ 五段・バ行 →喜ぶ
1685 よろこぶ 喜ぶ 五段・バ行 〈「悦ぶ」「歓ぶ」とも〉\n1. うれしく思う。「泣いて喜ぶ」\n2. 〈行為に対して、主に否定形で〉よいと思う。肯定的に見る。「子供が遠出することを喜ばない」\n3. 〈挨拶文で〉〈「慶ぶ」とも〉めでたく思う。(よいことを)願う。「時下ますますご清祥のこととお喜び申し上げます」
1686 よろこぶ 慶ぶ 五段・バ行 〈挨拶文で〉〈「喜ぶ」とも〉めでたく思う。(よいことを)願う。「時下ますますご清祥のこととお慶び申し上げます」
1687 らんちょう 乱丁 * 書物について、ページの順が乱れていること。「乱丁本」
1688 らんちょう 乱調 * 調子が乱れていること。「今日の投手は乱調気味だ」
1689 りっぽう 立方 * 1. 三乗。「立方根」(=三乗根)\n2. 長さの単位の前に付けて、その1単位の縦・横・高さのものが持つ体積の単位をつくる。「1立方メートル」\n3. 長さを示す語の後に付けて、その長さの縦・横・高さの空間をあらわす。「30センチ立方の空間」
1652 よむ 読む 五段・マ行 文字を見て意味を理解する。「本を読む、市場を読む、表情を読む」
1653 よる 依る 五段・ラ行 たよる。「エキスパートに依る」
1654 よる 因る 五段・ラ行 原因となる。「ウィルスによる障害」
1655 よる 寄る 五段・ラ行 ちかづく。「近くに寄る、店に寄る、皺が寄る、寄らば大樹の蔭」
1656 よる 拠る 五段・ラ行 根拠とする。「国連決議に拠る攻撃」
1657 よる 選る 五段・ラ行 えらぶ。「不良品を選り分ける」
1658 よる 撚る 五段・ラ行 (「撚る」と区別なし)ねじりあわせる。「糸を撚る」
1659 よる 縒る 五段・ラ行 (「縒る」と区別なし)ねじりあわせる。「糸を縒る」
1660 よろこぶ 悦ぶ 五段・バ行 (「喜ぶ」と区別なし)うれしく思う。「泣いて悦ぶ」
1661 よろこぶ 喜ぶ 五段・バ行 (「悦ぶ」と区別なし、一般的)うれしく思う。「泣いて喜ぶ」
1662 よろこぶ 慶ぶ 五段・バ行 祝福する。「宿縁を慶ぶ」
1663 らんちょう 乱丁 * 書物でうまく綴じられていないこと。「乱丁本」
1664 らんちょう 乱調 * 調子が乱れていること。「今日の投手は乱調気味」
1665 りっぽう 立方 * 三乗すること。「立方根、立方体」
16901666 りっぽう 立法 * 法律をつくること。「立法院」
1691 りょうする 諒する サ変・−スル 〈文語〉おもいやる。
1692 りょうする 領する サ変・−スル 〈文語〉領有する。
1693 りんかい 臨海 * 海に臨むこと。「臨海都市」
1694 りんかい 臨界 * 1. そこで性質が大きく変わるような境界。「臨界点」(気体または液体として存在できる限界の温度と圧力)「臨界状態」(原子核分裂が一定速度で続くような状態)\n2. 〈比喩的に〉それ以上我慢できないような、感情の限界。「彼の怒りは臨界に達していた」
1667 りょう 諒 * (文語)おもいやる。
1668 りょう 領 * (文語)領有する。
1669 りんかい 臨海 * 海に望む場所。「臨海都市」
1670 りんかい 臨界 * 境界。「臨界点」
16951671 りんどう 竜胆 * リンドウ科の植物。
1696 りんどう 林道 * 林のなかに作られた道。
1672 りんどう 林道 * 林のなかにある道。
16971673 れいじょう 令状 * 命令が書かれた書状。「逮捕令状」
16981674 れいじょう 礼状 * お礼をする書状。
1699 れき 暦 * 〈接尾語〉こよみ。カレンダー。「太陽暦」
1700 れき 歴 * 〈接尾語〉\n1. 過去の記録。「刑事処分歴のある者」\n2. 続けた年数。「記者歴30年のベテラン」
1701 れんけい 連係 * かかわり。つながり。「連係を保つ」
1702 れんけい 連繋 * →連係
1703 れんけい 連携 * 互いに連絡して協力すること。「連携して犯人を逮捕する」
1704 れんぱ 連覇 * 続けて征覇すること。続けて優勝すること。「日本シリーズで連覇する」
1705 れんぱ 連破 * 続けて打ち負かすこと。「二人の大関を連破した」
1675 れき 暦 * こよみ。「太陽暦」
1676 れき 歴 * 通りすぎること。「歴史」
1677 れんけい 連係 * つながりをもつこと。「連係プレー」
1678 れんけい 連携 * 協力すること。「連携して犯人を逮捕する」
1679 れんぱ 連覇 * 続けて征覇する。「日本シリーズで連覇する」
1680 れんぱ 連破 * 続けて破ること。
17061681 れんぽう 連峰 * つらなっている山。「穂高連峰」
1707 れんぽう 連邦 * ある程度の独立性をもった州や国が集まり、ひとつの国家を構成すること。また、そのような国家。「連邦国家」「連邦制」
1682 れんぽう 連邦 * 連邦国家のこと。「連邦国家」
17081683 れんめい 連名 * 名前をつらねること。「連名でサインする」
17091684 れんめい 連盟 * 同一の目的のために集まること。「高校野球連盟」
1710 ろうする 労する サ変・−スル 〈文語〉苦労する。「労せずして手に入れる」
1711 ろうする 弄する サ変・−スル 〈否定的〉(計略などを)使う。あやつる。「術策を弄する」「詭弁(きべん)を弄する」
1712 ろうふ 老夫 * 〈文語〉老いた男。
1685 ろう 労 * (文語)苦労する。
1686 ろう 弄 * (文語)愚弄する。
1687 ろうふ 老夫 * 老いた男。
17131688 ろうふ 老父 * 老いた父親。
1714 ろじ 路地 * 〈「露地」とも〉家などの間の狭い道。
1715 ろじ 露地 * 1. 露出した地面。「露地栽培」\n2. →路地
1716 ろんきゅう 論及 * 論じて言及すること。「その事件について論及している」
1717 ろんきゅう 論究 * つきつめて論じること。「法律の起源について本格的に論究する」
1718 わかれる 分かれる 一段 (ものや意見などが)別々になる。または、別々である。「道が分かれる」「意見が分かれる」「上下巻に分かれた本」
1719 わかれる 別れる 一段 1. (人が)わかれわかれになる。互いから離れる。「駅で友達と別れた」\n2. 恋人・夫婦の関係をたつ。「妻と別れる」
1720 わく 沸く 五段・カ行イ音便 1. お湯になる。または、沸騰する。「風呂が沸く」「ラーメンをゆでる湯が沸いた」\n2. 熱狂する。「会場をおおいに沸かせた」
1721 わく 湧く 五段・カ行イ音便 〈「涌く」とも〉\n1. (水などが)自然と地面から出てくる。「温泉が湧く土地」\n2. (汗や涙が)自然と出てくる。「立っているだけで汗が湧く」\n3. 〈かな書きが多い〉(感情や発想などが)自然と出てくる。「勇気が湧く」「興味が湧く」「イメージが湧かない」\n4. (虫などが)発生する。〈否定的に〉(人が)集まってくる。「米に虫が湧く」「怪しいやつらがどこからか湧いてきた」
1722 わく 涌く 五段・カ行イ音便 →湧く
1723 わざ 技 * 1. 技術。「職人の技が活かされている」\n2. 武術などで相手にしかける動作。「必殺技」
1724 わざ 業 * 〈文語〉行為。〈「~のなせる業」として〉結果。「自信のなせる業」
1725 わずらう 患う 五段・ワ行促音便 病気になる。かかる。「風邪を患う」
1726 わずらう 煩う 五段・ワ行促音便 〈複合語で〉上手くいかずに悩む。苦しむ。「思い煩う」
1727 わたる 渡る 五段・ラ行 1. 間にあるものを越えて移動する。「橋を渡る」「海外に渡る」\n2. つたって移動する。「枝を渡る」\n3. (世の中で)暮らしていく。「世間を渡る」\n4. 〈主にかな書き〉〈「亘る」とも〉ある範囲に及ぶ。「広範囲にわたって調査する」「五十項目にわたる改善案」「三日間にわたる調査」
1728 わたる 亘る 五段・ラ行 →渡る4
1689 ろじ 路地 * 家などの間の狭いみち。
1690 ろじ 露地 * 露出した地面。「露地栽培」
1691 ろんきゅう 論及 * 論じて及ぶこと。
1692 ろんきゅう 論究 * 論じて究めること。
1693 わかれる 分かれる 一段 分裂する。「意見が分かれる」
1694 わかれる 別れる 一段 別々になる。「彼氏と別れる」
1695 わく 沸く 五段・カ行イ音便 お湯になる。「風呂が沸く」
1696 わく 湧く 五段・カ行イ音便 (「涌く」と区別なし)
1697 わく 涌く 五段・カ行イ音便 (「湧く」と区別なし)
1698 わざ 技 * 技術、武術などで相手にしかける動作。「職人の技が活かされている、必殺技」
1699 わざ 業 * 行ない、職業。「人間業ではない」
1700 わずらう 患う 五段・ワ行促音便 病気になる。「風邪を患う」
1701 わずらう 煩う 五段・ワ行促音便 上手くいかずに悩む、苦しむ。「思い煩う」
1702 わたる 渡る 五段・ラ行 移動する。「海外に渡る、職を渡る、橋を渡る」
1703 わたる 亘る 五段・ラ行 長さがおよぶ。「2ヶ月に亘る捜索」
0 mozc (1.3.911.102) lucid; urgency=low
1
2 * Ver. 1.3.911.102 on 2011-11-28
3 * Support new features for IBus.
4 - Support UNDO feature.
5 - Support Reconversion feature for IBus >=1.4.
6 - Add some menus into language bar.
7 - Set ibus-mozc rank as 80.
8 * Fixed some bugs.
9 - Fixed English-number toggle key issue for emacs.(Issue 101)
10 - Fixed crash problem on scim.(Issue 104)
11 * Change dependency name for Ubuntu 11.10.(Issue 106)
12
13 -- Seigo Nonaka <nona> Mon, 28 Nov 2011 15:02:44 +0900
14
15 mozc (1.2.855.102) lucid; urgency=low
16
17 * Ver. 1.2.855.102 on 2011-09-27
18
19 -- Tsuyoshi Horo <horo> Tue, 27 Sep 2011 15:55:43 +0900
20
21 mozc (1.2.831.102) lucid; urgency=low
22
23 * Updated dictionary.
24 * Fixed some bugs.
25
26 -- Tatsuhisa Yamaguchi <yamaguchi> Thu, 01 Sep 2011 15:37:09 +0900
27
28 mozc (1.2.809.102) lucid; urgency=low
29
30 * Ver. 1.2.809.102 on 2011-08-12
31
32 -- Tsuyoshi Horo <horo> Fri, 12 Aug 2011 12:28:58 +0900
33
34 mozc (1.1.773.102) lucid; urgency=low
35
36 * Ver. 1.1.773.102 on 2011-07-07
37
38 -- Hiroshi Sumita <hsumita> Thu, 07 Jul 2011 15:45:12 +0900
39
40 mozc (1.1.758.102) lucid; urgency=low
41
42 * Ver. 1.1.758.102 on 2011-06-23
43
44 -- Hitoshi Yoshida <peria> Thu, 23 Jun 2011 20:22:10 +0900
45
46 mozc (1.1.739.102) lucid; urgency=low
47
48 * Ver. 1.1.739.102 on 2011-06-09
49
50 -- Seigo Nonaka <nona> Thu, 09 Jun 2011 15:36:56 +0900
51
52 mozc (1.1.717.102) lucid; urgency=low
53
54 * Ver. 1.1.717.102 on 2011-05-12
55
56 -- Hiroyuki Komatsu <komatsu> Thu, 12 May 2011 14:33:14 +0900
57
58 mozc (1.1.690.102) lucid; urgency=low
59
60 * Ver. 1.1.690.102 on 2011-04-14
61
62 -- Hiroyuki Komatsu <komatsu> Thu, 14 Apr 2011 17:43:40 +0900
63
64 mozc (1.1.626.102) lucid; urgency=low
65
66 * Ver. 1.1.626.102 on 2011-02-16
67
68 -- Yasuhiro Matsuda <mazda> Wed, 16 Feb 2011 18:44:11 +0900
69
70 mozc (1.0.558.102) lucid; urgency=low
71
72 * Ver. 1.0.558.102 on 2010-12-09
73
74 -- Hiroyuki Komatsu <komatsu> Thu, 09 Dec 2010 11:23:35 +0900
75
76 mozc (0.13.523.102) lucid; urgency=low
77
78 * Ver. 0.13.523.102 on 2010-11-02
79
80 -- Yasuhiro Matsuda <mazda> Tue, 02 Nov 2010 19:45:33 +0900
81
82 mozc (0.13.499.102) lucid; urgency=low
83
84 * Ver. 0.13.499.102 on 2010-10-07
85
86 -- Hiroyuki Komatsu <komatsu> Thu, 07 Oct 2010 14:43:24 +0900
87
88 mozc (0.13.492.102) lucid; urgency=low
89
90 * Ver. 0.13.492.102 on 2010-09-27
91
92 -- Yasuhiro Matsuda <mazda> Mon, 27 Sep 2010 18:26:11 +0900
93
94 mozc (0.13.481.102) lucid; urgency=low
95
96 * Ver. 0.13.481.102 on 2010-09-22
97
98 -- Yasuhiro Matsuda <mazda> Wed, 22 Sep 2010 18:39:14 +0900
99
100 mozc (0.13.464.102) lucid; urgency=low
101
102 * Ver. 0.13.464.102 on 2010-09-02
103
104 -- Hiroyuki Komatsu <komatsu> Fri, 03 Sep 2010 13:14:44 +0900
105
106 mozc (0.12.434.102) lucid; urgency=low
107
108 * Ver. 0.12.434.102 on 2010-08-11
109
110 -- Yasuhiro Matsuda <mazda> Wed, 11 Aug 2010 19:59:17 +0900
111
112 mozc (0.12.422.102) lucid; urgency=low
113
114 * Ver. 0.12.422.102 on 2010-07-23
115
116 -- Yasuhiro Matsuda <mazda> Fri, 23 Jul 2010 14:33:29 +0900
117
118 mozc (0.12.410.102) lucid; urgency=low
119
120 * Ver. 0.12.410.102 on 2010-07-12
121
122 -- Hiroyuki Komatsu <komatsu> Mon, 12 Jul 2010 14:11:04 +0900
123
124 mozc (0.12.402.102) lucid; urgency=low
125
126 * Ver. 0.12.402.102 on 2010-06-30
127
128 -- Yasuhiro Matsuda <mazda> Wed, 30 Jun 2010 13:22:54 +0900
129
130 mozc (0.11.383.102) lucid; urgency=low
131
132 * Ver. 0.11.383.102 on 2010-06-16
133
134 -- Yasuhiro Matsuda <mazda> Wed, 16 Jun 2010 15:39:33 +0900
135
136 mozc (0.11.365.102) lucid; urgency=low
137
138 * Ver. 0.11.365.102 on 2010-05-25
139
140 -- Yasuhiro Matsuda <mazda> Tue, 25 May 2010 16:54:03 +0900
141
142 mozc (0.11.354.100) lucid; urgency=low
143
144 * Ver. 0.11.354.100 on 2010-05-17
145
146 -- Yusuke Sato <yusukes> Mon, 17 May 2010 19:22:54 +0900
147
148 mozc (0.10.288.102) jaunty; urgency=low
149
150 * Ver. 0.10.288.102 on 2010-03-09
151
152 -- Hiroyuki Komatsu <komatsu> Tue, 09 Mar 2010 16:01:11 +0900
0 Source: mozc
1 Section: utils
2 Priority: extra
3 Maintainer: Yusuke Sato <yusukes>
4 Build-Depends: debhelper (>= 4.0.0), libibus-dev | libibus-1.0-dev, libcurl4-openssl-dev, pkg-config, libprotobuf-dev, protobuf-compiler, libgtest-dev, libqt4-dev, scim, libscim-dev, gyp, libzinnia-dev
5 Standards-Version: 3.6.2
6
7 Package: ibus-mozc
8 Architecture: any
9 Depends: ${shlibs:Depends}, ibus, mozc-server (= ${Source-Version})
10 Description: IBus engine module for Mozc.
11
12 Package: scim-mozc
13 Architecture: any
14 Depends: ${shlibs:Depends}, scim, mozc-server (= ${Source-Version})
15 Description: SCIM IMEngine module for Mozc.
16
17 Package: emacs-mozc
18 Architecture: all
19 Depends: emacs | emacs22 | emacs23 | emacs-snapshot, emacs-mozc-bin (= ${Source-Version})
20 Description: Mozc for Emacs.
21
22 Package: emacs-mozc-bin
23 Architecture: any
24 Depends: ${shlibs:Depends}, mozc-server (= ${Source-Version})
25 Description: Helper module for emacs-mozc
26
27 Package: mozc-server
28 Architecture: any
29 Depends: ${shlibs:Depends}
30 Description: Server part of the Mozc input method, used by Mozc clients such as ibus-mozc.
31
32 Package: mozc-utils-gui
33 Architecture: any
34 Depends: ${shlibs:Depends}, mozc-server (= ${Source-Version}), tegaki-zinnia-japanese, libzinnia0
35 Description: Mozc GUI uitilities, such as the configuration dialog, user dictionary tool and about dialog.
0 Copyright 2010, Google Inc.
1 All rights reserved.
2
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions are
5 met:
6
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following disclaimer
11 in the documentation and/or other materials provided with the
12 distribution.
13 * Neither the name of Google Inc. nor the names of its
14 contributors may be used to endorse or promote products derived from
15 this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 #!/usr/bin/make -f
1 # -*- makefile -*-
2 # Sample debian/rules that uses debhelper.
3 #
4 # This file was originally written by Joey Hess and Craig Small.
5 # As a special exception, when this file is copied by dh-make into a
6 # dh-make output file, you may use that output file without restriction.
7 # This special exception was added by Craig Small in version 0.37 of dh-make.
8 #
9 # Modified to make a template file for a multi-binary package with separated
10 # build-arch and build-indep targets by Bill Allombert 2001
11
12 # Uncomment this to turn on verbose mode.
13 #export DH_VERBOSE=1
14
15 # This has to be exported to make some magic below work.
16 export DH_OPTIONS
17
18 BUILD_DIR=./out_linux
19 TARGETS=unix/ibus/ibus.gyp:ibus_mozc unix/scim/scim.gyp:scim_mozc unix/scim/scim.gyp:scim_mozc_setup unix/emacs/emacs.gyp:mozc_emacs_helper server/server.gyp:mozc_server gui/gui.gyp:mozc_tool
20
21 configure: configure-stamp
22 configure-stamp:
23 dh_testdir
24 touch configure-stamp
25
26
27 #Architecture
28 build: build-arch build-indep
29
30 build-arch: build-arch-stamp
31 build-arch-stamp: configure-stamp
32 python build_mozc.py gyp --gypdir=/usr/bin
33 python build_mozc.py build_tools -c Release
34 python build_mozc.py build $(TARGETS) -c Release
35 touch build-arch-stamp
36
37 build-indep: build-indep-stamp
38 build-indep-stamp: configure-stamp
39 touch $@
40
41 clean:
42 dh_testdir
43 dh_testroot
44 rm -f build-arch-stamp build-indep-stamp #CONFIGURE-STAMP#
45 python build_mozc.py clean
46 dh_clean
47
48 install: install-arch install-indep
49
50 install-indep:
51 dh_testdir
52 dh_testroot
53 dh_prep
54 dh_installdirs
55
56 mkdir -p $(CURDIR)/debian/emacs-mozc/usr/share/emacs/site-lisp/emacs-mozc/
57 cp -p unix/emacs/mozc.el $(CURDIR)/debian/emacs-mozc/usr/share/emacs/site-lisp/emacs-mozc/
58
59 install-arch:
60 dh_testdir
61 dh_testroot
62 dh_clean -k -s
63 dh_installdirs -s
64
65 mkdir -p $(CURDIR)/debian/ibus-mozc/usr/lib/ibus-mozc/
66 cp -p $(BUILD_DIR)/Release/ibus_mozc $(CURDIR)/debian/ibus-mozc/usr/lib/ibus-mozc/ibus-engine-mozc
67 mkdir -p $(CURDIR)/debian/ibus-mozc/usr/share/ibus/component/
68 sed 's|/usr/libexec/ibus-engine-mozc|/usr/lib/ibus-mozc/ibus-engine-mozc|' < $(BUILD_DIR)/Release/obj/gen/unix/ibus/mozc.xml > $(CURDIR)/debian/ibus-mozc/usr/share/ibus/component/mozc.xml
69 mkdir -p $(CURDIR)/debian/ibus-mozc/usr/share/ibus-mozc/
70 cp -p data/images/unix/ime_product_icon_opensource-32.png $(CURDIR)/debian/ibus-mozc/usr/share/ibus-mozc/product_icon.png
71 cp -p data/images/unix/ui-tool.png $(CURDIR)/debian/ibus-mozc/usr/share/ibus-mozc/tool.png
72 cp -p data/images/unix/ui-properties.png $(CURDIR)/debian/ibus-mozc/usr/share/ibus-mozc/properties.png
73 cp -p data/images/unix/ui-dictionary.png $(CURDIR)/debian/ibus-mozc/usr/share/ibus-mozc/dictionary.png
74 cp -p data/images/unix/ui-direct.png $(CURDIR)/debian/ibus-mozc/usr/share/ibus-mozc/direct.png
75 cp -p data/images/unix/ui-hiragana.png $(CURDIR)/debian/ibus-mozc/usr/share/ibus-mozc/hiragana.png
76 cp -p data/images/unix/ui-katakana_half.png $(CURDIR)/debian/ibus-mozc/usr/share/ibus-mozc/katakana_half.png
77 cp -p data/images/unix/ui-katakana_full.png $(CURDIR)/debian/ibus-mozc/usr/share/ibus-mozc/katakana_full.png
78 cp -p data/images/unix/ui-alpha_half.png $(CURDIR)/debian/ibus-mozc/usr/share/ibus-mozc/alpha_half.png
79 cp -p data/images/unix/ui-alpha_full.png $(CURDIR)/debian/ibus-mozc/usr/share/ibus-mozc/alpha_full.png
80
81 mkdir -p $(CURDIR)/debian/scim-mozc`pkg-config --variable=moduledir scim`/IMEngine/
82 cp -p $(BUILD_DIR)/Release/lib.target/libscim_mozc.so $(CURDIR)/debian/scim-mozc`pkg-config --variable=moduledir scim`/IMEngine/mozc.so
83 mkdir -p $(CURDIR)/debian/scim-mozc`pkg-config --variable=moduledir scim`/SetupUI/
84 cp -p $(BUILD_DIR)/Release/lib.target/libscim_mozc_setup.so $(CURDIR)/debian/scim-mozc`pkg-config --variable=moduledir scim`/SetupUI/mozc-setup.so
85 mkdir -p $(CURDIR)/debian/scim-mozc`pkg-config --variable=icondir scim`/
86 cp -p data/images/unix/ime_product_icon_opensource-32.png $(CURDIR)/debian/scim-mozc`pkg-config --variable=icondir scim`/scim-mozc.png
87 cp -p data/images/unix/ui-tool.png $(CURDIR)/debian/scim-mozc`pkg-config --variable=icondir scim`/scim-mozc-tool.png
88 cp -p data/images/unix/ui-properties.png $(CURDIR)/debian/scim-mozc`pkg-config --variable=icondir scim`/scim-mozc-properties.png
89 cp -p data/images/unix/ui-dictionary.png $(CURDIR)/debian/scim-mozc`pkg-config --variable=icondir scim`/scim-mozc-dictionary.png
90 cp -p data/images/unix/ui-direct.png $(CURDIR)/debian/scim-mozc`pkg-config --variable=icondir scim`/scim-mozc-direct.png
91 cp -p data/images/unix/ui-hiragana.png $(CURDIR)/debian/scim-mozc`pkg-config --variable=icondir scim`/scim-mozc-hiragana.png
92 cp -p data/images/unix/ui-katakana_half.png $(CURDIR)/debian/scim-mozc`pkg-config --variable=icondir scim`/scim-mozc-katakana_half.png
93 cp -p data/images/unix/ui-katakana_full.png $(CURDIR)/debian/scim-mozc`pkg-config --variable=icondir scim`/scim-mozc-katakana_full.png
94 cp -p data/images/unix/ui-alpha_half.png $(CURDIR)/debian/scim-mozc`pkg-config --variable=icondir scim`/scim-mozc-alpha_half.png
95 cp -p data/images/unix/ui-alpha_full.png $(CURDIR)/debian/scim-mozc`pkg-config --variable=icondir scim`/scim-mozc-alpha_full.png
96
97 mkdir -p $(CURDIR)/debian/emacs-mozc-bin/usr/bin/
98 cp -p $(BUILD_DIR)/Release/mozc_emacs_helper $(CURDIR)/debian/emacs-mozc-bin/usr/bin/
99
100 mkdir -p $(CURDIR)/debian/mozc-server/usr/lib/mozc
101 cp -p $(BUILD_DIR)/Release/mozc_server $(CURDIR)/debian/mozc-server/usr/lib/mozc/
102
103 mkdir -p $(CURDIR)/debian/mozc-utils-gui/usr/lib/mozc
104 cp -p $(BUILD_DIR)/Release/mozc_tool $(CURDIR)/debian/mozc-utils-gui/usr/lib/mozc
105
106 dh_install -s
107
108 # Must not depend on anything. This is to be called by
109 # binary-arch/binary-indep
110 # in another 'make' thread.
111 binary-common:
112 dh_testdir
113 dh_testroot
114 dh_installchangelogs
115 dh_installdocs
116 dh_installexamples
117 # dh_installmenu
118 # dh_installdebconf
119 # dh_installlogrotate
120 dh_installemacsen
121 # dh_installpam
122 # dh_installmime
123 # dh_installinit
124 # dh_installcron
125 # dh_installinfo
126 dh_installman
127 dh_link
128 dh_strip
129 dh_compress
130 dh_fixperms
131 # dh_perl
132 # dh_python
133 dh_makeshlibs
134 dh_installdeb
135 dh_shlibdeps
136 dh_gencontrol
137 dh_md5sums
138 dh_builddeb
139
140 binary-indep: build-indep install-indep
141 $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common
142
143 # Build architecture dependant packages using the common target.
144 binary-arch: build-arch install-arch
145 $(MAKE) -f debian/rules DH_OPTIONS=-a binary-common
146
147 binary: binary-arch binary-indep
148 .PHONY: build clean binary-indep binary-arch binary install install-indep install-arch configure