1d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org# Copyright (c) 2013 Google Inc. All rights reserved.
2d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org# Use of this source code is governed by a BSD-style license that can be
3d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org# found in the LICENSE file.
4d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
5d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org"""cmake output module
6d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
7d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgThis module is under development and should be considered experimental.
8d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
9d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgThis module produces cmake (2.8.8+) input as its output. One CMakeLists.txt is
10d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgcreated for each configuration.
11d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
12d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgThis module's original purpose was to support editing in IDEs like KDevelop
13d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgwhich use CMake for project management. It is also possible to use CMake to
14d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orggenerate projects for other IDEs such as eclipse cdt and code::blocks. QtCreator
15d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgwill convert the CMakeLists.txt to a code::blocks cbp for the editor to read,
16d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgbut build using CMake. As a result QtCreator editor is unaware of compiler
17d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdefines. The generated CMakeLists.txt can also be used to build on Linux. There
18d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgis currently no support for building on platforms other than Linux.
19d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
20d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgThe generated CMakeLists.txt should properly compile all projects. However,
21d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgthere is a mismatch between gyp and cmake with regard to linking. All attempts
22d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgare made to work around this, but CMake sometimes sees -Wl,--start-group as a
23d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orglibrary and incorrectly repeats it. As a result the output of this generator
24d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgshould not be relied on for building.
25d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
26d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgWhen using with kdevelop, use version 4.4+. Previous versions of kdevelop will
27d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgnot be able to find the header file directories described in the generated
28d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgCMakeLists.txt file.
29d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org"""
30d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
31d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgimport multiprocessing
32d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgimport os
33d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgimport signal
34d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgimport string
35d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgimport subprocess
36d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgimport gyp.common
37d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
38d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orggenerator_default_variables = {
39d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'EXECUTABLE_PREFIX': '',
40d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'EXECUTABLE_SUFFIX': '',
41d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'STATIC_LIB_PREFIX': 'lib',
42d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'STATIC_LIB_SUFFIX': '.a',
43d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'SHARED_LIB_PREFIX': 'lib',
44d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'SHARED_LIB_SUFFIX': '.so',
45d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'SHARED_LIB_DIR': '${builddir}/lib.${TOOLSET}',
46d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'LIB_DIR': '${obj}.${TOOLSET}',
47d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'INTERMEDIATE_DIR': '${obj}.${TOOLSET}/${TARGET}/geni',
48d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'SHARED_INTERMEDIATE_DIR': '${obj}/gen',
49d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'PRODUCT_DIR': '${builddir}',
50d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'RULE_INPUT_PATH': '${RULE_INPUT_PATH}',
51d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'RULE_INPUT_DIRNAME': '${RULE_INPUT_DIRNAME}',
52d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'RULE_INPUT_NAME': '${RULE_INPUT_NAME}',
53d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'RULE_INPUT_ROOT': '${RULE_INPUT_ROOT}',
54d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'RULE_INPUT_EXT': '${RULE_INPUT_EXT}',
55d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'CONFIGURATION_NAME': '${configuration}',
56d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org}
57d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
58d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgFULL_PATH_VARS = ('${CMAKE_SOURCE_DIR}', '${builddir}', '${obj}')
59d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
60d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orggenerator_supports_multiple_toolsets = True
61d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orggenerator_wants_static_library_dependencies_adjusted = True
62d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
63d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgCOMPILABLE_EXTENSIONS = {
64d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  '.c': 'cc',
65d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  '.cc': 'cxx',
66d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  '.cpp': 'cxx',
67d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  '.cxx': 'cxx',
68d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  '.s': 's', # cc
69d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  '.S': 's', # cc
70d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org}
71d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
72d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
73d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef RemovePrefix(a, prefix):
74d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Returns 'a' without 'prefix' if it starts with 'prefix'."""
75d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  return a[len(prefix):] if a.startswith(prefix) else a
76d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
77d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
78d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef CalculateVariables(default_variables, params):
79d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Calculate additional variables for use in the build (called by gyp)."""
80d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  default_variables.setdefault('OS', gyp.common.GetFlavor(params))
81d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
82d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
83d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef Compilable(filename):
84d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Return true if the file is compilable (should be in OBJS)."""
85d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  return any(filename.endswith(e) for e in COMPILABLE_EXTENSIONS)
86d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
87d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
88d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef Linkable(filename):
89d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Return true if the file is linkable (should be on the link line)."""
90d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  return filename.endswith('.o')
91d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
92d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
93d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef NormjoinPathForceCMakeSource(base_path, rel_path):
94d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Resolves rel_path against base_path and returns the result.
95d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
96d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  If rel_path is an absolute path it is returned unchanged.
97d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  Otherwise it is resolved against base_path and normalized.
98d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  If the result is a relative path, it is forced to be relative to the
99d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  CMakeLists.txt.
100d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """
101d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if os.path.isabs(rel_path):
102d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    return rel_path
103d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if any([rel_path.startswith(var) for var in FULL_PATH_VARS]):
104d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    return rel_path
105d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # TODO: do we need to check base_path for absolute variables as well?
106d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  return os.path.join('${CMAKE_SOURCE_DIR}',
107d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                      os.path.normpath(os.path.join(base_path, rel_path)))
108d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
109d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
110d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef NormjoinPath(base_path, rel_path):
111d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Resolves rel_path against base_path and returns the result.
112d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  TODO: what is this really used for?
113d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  If rel_path begins with '$' it is returned unchanged.
114d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  Otherwise it is resolved against base_path if relative, then normalized.
115d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """
116d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if rel_path.startswith('$') and not rel_path.startswith('${configuration}'):
117d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    return rel_path
118d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  return os.path.normpath(os.path.join(base_path, rel_path))
119d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
120d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
121d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef CMakeStringEscape(a):
122d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Escapes the string 'a' for use inside a CMake string.
123d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
124d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  This means escaping
125d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  '\' otherwise it may be seen as modifying the next character
126d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  '"' otherwise it will end the string
127d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  ';' otherwise the string becomes a list
128d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
129d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  The following do not need to be escaped
130d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  '#' when the lexer is in string state, this does not start a comment
131d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
132d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  The following are yet unknown
133d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  '$' generator variables (like ${obj}) must not be escaped,
134d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      but text $ should be escaped
135d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      what is wanted is to know which $ come from generator variables
136d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """
137d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  return a.replace('\\', '\\\\').replace(';', '\\;').replace('"', '\\"')
138d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
139d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
140d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef SetFileProperty(output, source_name, property_name, values, sep):
141d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Given a set of source file, sets the given property on them."""
142d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('set_source_files_properties(')
143d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(source_name)
144d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(' PROPERTIES ')
145d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(property_name)
146d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(' "')
147d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for value in values:
148d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(CMakeStringEscape(value))
149d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(sep)
150d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('")\n')
151d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
152d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
153d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef SetFilesProperty(output, source_names, property_name, values, sep):
154d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Given a set of source files, sets the given property on them."""
155d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('set_source_files_properties(\n')
156d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for source_name in source_names:
157d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('  ')
158d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(source_name)
159d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n')
160d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(' PROPERTIES\n  ')
161d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(property_name)
162d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(' "')
163d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for value in values:
164d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(CMakeStringEscape(value))
165d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(sep)
166d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('"\n)\n')
167d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
168d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
169d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef SetTargetProperty(output, target_name, property_name, values, sep=''):
170d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Given a target, sets the given property."""
171d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('set_target_properties(')
172d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(target_name)
173d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(' PROPERTIES ')
174d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(property_name)
175d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(' "')
176d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for value in values:
177d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(CMakeStringEscape(value))
178d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(sep)
179d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('")\n')
180d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
181d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
182d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef SetVariable(output, variable_name, value):
183d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Sets a CMake variable."""
184d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('set(')
185d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(variable_name)
186d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(' "')
187d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(CMakeStringEscape(value))
188d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('")\n')
189d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
190d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
191d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef SetVariableList(output, variable_name, values):
192d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Sets a CMake variable to a list."""
193d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if not values:
194d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    return SetVariable(output, variable_name, "")
195d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if len(values) == 1:
196d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    return SetVariable(output, variable_name, values[0])
197d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('list(APPEND ')
198d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(variable_name)
199d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('\n  "')
200d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('"\n  "'.join([CMakeStringEscape(value) for value in values]))
201d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('")\n')
202d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
203d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
204d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef UnsetVariable(output, variable_name):
205d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Unsets a CMake variable."""
206d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('unset(')
207d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(variable_name)
208d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(')\n')
209d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
210d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
211d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef WriteVariable(output, variable_name, prepend=None):
212d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if prepend:
213d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(prepend)
214d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('${')
215d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(variable_name)
216d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('}')
217d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
218d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
219d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgclass CMakeTargetType:
220d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  def __init__(self, command, modifier, property_modifier):
221d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    self.command = command
222d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    self.modifier = modifier
223d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    self.property_modifier = property_modifier
224d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
225d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
226d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgcmake_target_type_from_gyp_target_type = {
227d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'executable': CMakeTargetType('add_executable', None, 'RUNTIME'),
228d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'static_library': CMakeTargetType('add_library', 'STATIC', 'ARCHIVE'),
229d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'shared_library': CMakeTargetType('add_library', 'SHARED', 'LIBRARY'),
230d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'loadable_module': CMakeTargetType('add_library', 'MODULE', 'LIBRARY'),
231d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  'none': CMakeTargetType('add_custom_target', 'SOURCES', None),
232d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org}
233d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
234d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
235d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef StringToCMakeTargetName(a):
236d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Converts the given string 'a' to a valid CMake target name.
237d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
238d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  All invalid characters are replaced by '_'.
239d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  Invalid for cmake: ' ', '/', '(', ')'
240d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  Invalid for make: ':'
241d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  Invalid for unknown reasons but cause failures: '.'
242d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """
243d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  return a.translate(string.maketrans(' /():.', '______'))
244d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
245d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
246d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef WriteActions(target_name, actions, extra_sources, extra_deps,
247d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                 path_to_gyp, output):
248d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Write CMake for the 'actions' in the target.
249d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
250d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  Args:
251d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    target_name: the name of the CMake target being generated.
252d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    actions: the Gyp 'actions' dict for this target.
253d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    extra_sources: [(<cmake_src>, <src>)] to append with generated source files.
254d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    extra_deps: [<cmake_taget>] to append with generated targets.
255d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    path_to_gyp: relative path from CMakeLists.txt being generated to
256d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        the Gyp file in which the target being generated is defined.
257d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """
258d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for action in actions:
259d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    action_name = StringToCMakeTargetName(action['action_name'])
260d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    action_target_name = '%s__%s' % (target_name, action_name)
261d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
262d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    inputs = action['inputs']
263d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    inputs_name = action_target_name + '__input'
264d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetVariableList(output, inputs_name,
265d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        [NormjoinPathForceCMakeSource(path_to_gyp, dep) for dep in inputs])
266d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
267d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    outputs = action['outputs']
268d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    cmake_outputs = [NormjoinPathForceCMakeSource(path_to_gyp, out)
269d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                     for out in outputs]
270d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    outputs_name = action_target_name + '__output'
271d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetVariableList(output, outputs_name, cmake_outputs)
272d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
273d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    # Build up a list of outputs.
274d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    # Collect the output dirs we'll need.
275d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    dirs = set(dir for dir in (os.path.dirname(o) for o in outputs) if dir)
276d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
277d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if int(action.get('process_outputs_as_sources', False)):
278d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      extra_sources.extend(zip(cmake_outputs, outputs))
279d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
280d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    # add_custom_command
281d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('add_custom_command(OUTPUT ')
282d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    WriteVariable(output, outputs_name)
283d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n')
284d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
285d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if len(dirs) > 0:
286d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      for directory in dirs:
287d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        output.write('  COMMAND ${CMAKE_COMMAND} -E make_directory ')
288d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        output.write(directory)
289d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        output.write('\n')
290d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
291d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('  COMMAND ')
292d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(gyp.common.EncodePOSIXShellList(action['action']))
293d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n')
294d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
295d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('  DEPENDS ')
296d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    WriteVariable(output, inputs_name)
297d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n')
298d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
299d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/')
300d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(path_to_gyp)
301d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n')
302d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
303d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('  COMMENT ')
304d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if 'message' in action:
305d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(action['message'])
306d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    else:
307d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(action_target_name)
308d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n')
309d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
310d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('  VERBATIM\n')
311d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(')\n')
312d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
313d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    # add_custom_target
314d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('add_custom_target(')
315d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(action_target_name)
316d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n  DEPENDS ')
317d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    WriteVariable(output, outputs_name)
318d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n  SOURCES ')
319d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    WriteVariable(output, inputs_name)
320d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n)\n')
321d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
322d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    extra_deps.append(action_target_name)
323d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
324d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
325d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef NormjoinRulePathForceCMakeSource(base_path, rel_path, rule_source):
326d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if rel_path.startswith(("${RULE_INPUT_PATH}","${RULE_INPUT_DIRNAME}")):
327d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if any([rule_source.startswith(var) for var in FULL_PATH_VARS]):
328d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      return rel_path
329d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  return NormjoinPathForceCMakeSource(base_path, rel_path)
330d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
331d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
332d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef WriteRules(target_name, rules, extra_sources, extra_deps,
333d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org               path_to_gyp, output):
334d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Write CMake for the 'rules' in the target.
335d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
336d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  Args:
337d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    target_name: the name of the CMake target being generated.
338d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    actions: the Gyp 'actions' dict for this target.
339d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    extra_sources: [(<cmake_src>, <src>)] to append with generated source files.
340d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    extra_deps: [<cmake_taget>] to append with generated targets.
341d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    path_to_gyp: relative path from CMakeLists.txt being generated to
342d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        the Gyp file in which the target being generated is defined.
343d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """
344d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for rule in rules:
345d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    rule_name = StringToCMakeTargetName(target_name + '__' + rule['rule_name'])
346d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
347d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    inputs = rule.get('inputs', [])
348d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    inputs_name = rule_name + '__input'
349d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetVariableList(output, inputs_name,
350d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        [NormjoinPathForceCMakeSource(path_to_gyp, dep) for dep in inputs])
351d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    outputs = rule['outputs']
352d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    var_outputs = []
353d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
354d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    for count, rule_source in enumerate(rule.get('rule_sources', [])):
355d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      action_name = rule_name + '_' + str(count)
356d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
357d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      rule_source_dirname, rule_source_basename = os.path.split(rule_source)
358d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      rule_source_root, rule_source_ext = os.path.splitext(rule_source_basename)
359d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
360d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      SetVariable(output, 'RULE_INPUT_PATH', rule_source)
361d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      SetVariable(output, 'RULE_INPUT_DIRNAME', rule_source_dirname)
362d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      SetVariable(output, 'RULE_INPUT_NAME', rule_source_basename)
363d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      SetVariable(output, 'RULE_INPUT_ROOT', rule_source_root)
364d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      SetVariable(output, 'RULE_INPUT_EXT', rule_source_ext)
365d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
366d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      # Build up a list of outputs.
367d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      # Collect the output dirs we'll need.
368d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      dirs = set(dir for dir in (os.path.dirname(o) for o in outputs) if dir)
369d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
370d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      # Create variables for the output, as 'local' variable will be unset.
371d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      these_outputs = []
372d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      for output_index, out in enumerate(outputs):
373d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        output_name = action_name + '_' + str(output_index)
374d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        SetVariable(output, output_name,
375d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                     NormjoinRulePathForceCMakeSource(path_to_gyp, out,
376d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                                      rule_source))
377d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        if int(rule.get('process_outputs_as_sources', False)):
378d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          extra_sources.append(('${' + output_name + '}', out))
379d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        these_outputs.append('${' + output_name + '}')
380d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        var_outputs.append('${' + output_name + '}')
381d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
382d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      # add_custom_command
383d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('add_custom_command(OUTPUT\n')
384d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      for out in these_outputs:
385d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        output.write('  ')
386d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        output.write(out)
387d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        output.write('\n')
388d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
389d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      for directory in dirs:
390d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        output.write('  COMMAND ${CMAKE_COMMAND} -E make_directory ')
391d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        output.write(directory)
392d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        output.write('\n')
393d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
394d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('  COMMAND ')
395d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(gyp.common.EncodePOSIXShellList(rule['action']))
396d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('\n')
397d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
398d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('  DEPENDS ')
399d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      WriteVariable(output, inputs_name)
400d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(' ')
401d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(NormjoinPath(path_to_gyp, rule_source))
402d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('\n')
403d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
404d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      # CMAKE_SOURCE_DIR is where the CMakeLists.txt lives.
405d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      # The cwd is the current build directory.
406d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/')
407d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(path_to_gyp)
408d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('\n')
409d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
410d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('  COMMENT ')
411d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      if 'message' in rule:
412d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        output.write(rule['message'])
413d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      else:
414d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        output.write(action_name)
415d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('\n')
416d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
417d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('  VERBATIM\n')
418d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(')\n')
419d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
420d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      UnsetVariable(output, 'RULE_INPUT_PATH')
421d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      UnsetVariable(output, 'RULE_INPUT_DIRNAME')
422d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      UnsetVariable(output, 'RULE_INPUT_NAME')
423d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      UnsetVariable(output, 'RULE_INPUT_ROOT')
424d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      UnsetVariable(output, 'RULE_INPUT_EXT')
425d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
426d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    # add_custom_target
427d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('add_custom_target(')
428d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(rule_name)
429d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(' DEPENDS\n')
430d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    for out in var_outputs:
431d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('  ')
432d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(out)
433d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('\n')
434d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('SOURCES ')
435d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    WriteVariable(output, inputs_name)
436d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n')
437d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    for rule_source in rule.get('rule_sources', []):
438d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('  ')
439d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(NormjoinPath(path_to_gyp, rule_source))
440d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('\n')
441d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(')\n')
442d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
443d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    extra_deps.append(rule_name)
444d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
445d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
446d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef WriteCopies(target_name, copies, extra_deps, path_to_gyp, output):
447d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Write CMake for the 'copies' in the target.
448d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
449d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  Args:
450d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    target_name: the name of the CMake target being generated.
451d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    actions: the Gyp 'actions' dict for this target.
452d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    extra_deps: [<cmake_taget>] to append with generated targets.
453d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    path_to_gyp: relative path from CMakeLists.txt being generated to
454d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        the Gyp file in which the target being generated is defined.
455d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """
456d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  copy_name = target_name + '__copies'
457d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
458d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # CMake gets upset with custom targets with OUTPUT which specify no output.
459d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  have_copies = any(copy['files'] for copy in copies)
460d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if not have_copies:
461d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('add_custom_target(')
462d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(copy_name)
463d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(')\n')
464d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    extra_deps.append(copy_name)
465d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    return
466d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
467d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  class Copy:
468d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    def __init__(self, ext, command):
469d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      self.cmake_inputs = []
470d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      self.cmake_outputs = []
471d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      self.gyp_inputs = []
472d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      self.gyp_outputs = []
473d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      self.ext = ext
474d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      self.inputs_name = None
475d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      self.outputs_name = None
476d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      self.command = command
477d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
478d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  file_copy = Copy('', 'copy')
479d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  dir_copy = Copy('_dirs', 'copy_directory')
480d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
481d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for copy in copies:
482d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    files = copy['files']
483d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    destination = copy['destination']
484d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    for src in files:
485d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      path = os.path.normpath(src)
486d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      basename = os.path.split(path)[1]
487d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      dst = os.path.join(destination, basename)
488d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
489d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      copy = file_copy if os.path.basename(src) else dir_copy
490d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
491d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      copy.cmake_inputs.append(NormjoinPath(path_to_gyp, src))
492d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      copy.cmake_outputs.append(NormjoinPathForceCMakeSource(path_to_gyp, dst))
493d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      copy.gyp_inputs.append(src)
494d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      copy.gyp_outputs.append(dst)
495d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
496d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for copy in (file_copy, dir_copy):
497d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if copy.cmake_inputs:
498d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      copy.inputs_name = copy_name + '__input' + copy.ext
499d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      SetVariableList(output, copy.inputs_name, copy.cmake_inputs)
500d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
501d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      copy.outputs_name = copy_name + '__output' + copy.ext
502d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      SetVariableList(output, copy.outputs_name, copy.cmake_outputs)
503d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
504d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # add_custom_command
505d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('add_custom_command(\n')
506d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
507d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('OUTPUT')
508d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for copy in (file_copy, dir_copy):
509d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if copy.outputs_name:
510d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      WriteVariable(output, copy.outputs_name, ' ')
511d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('\n')
512d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
513d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for copy in (file_copy, dir_copy):
514d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    for src, dst in zip(copy.gyp_inputs, copy.gyp_outputs):
515d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      # 'cmake -E copy src dst' will create the 'dst' directory if needed.
516d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('COMMAND ${CMAKE_COMMAND} -E %s ' % copy.command)
517d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(src)
518d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(' ')
519d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(dst)
520d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write("\n")
521d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
522d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('DEPENDS')
523d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for copy in (file_copy, dir_copy):
524d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if copy.inputs_name:
525d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      WriteVariable(output, copy.inputs_name, ' ')
526d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('\n')
527d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
528d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/')
529d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(path_to_gyp)
530d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('\n')
531d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
532d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('COMMENT Copying for ')
533d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(target_name)
534d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('\n')
535d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
536d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('VERBATIM\n')
537d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(')\n')
538d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
539d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # add_custom_target
540d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('add_custom_target(')
541d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(copy_name)
542d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('\n  DEPENDS')
543d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for copy in (file_copy, dir_copy):
544d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if copy.outputs_name:
545d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      WriteVariable(output, copy.outputs_name, ' ')
546d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('\n  SOURCES')
547d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if file_copy.inputs_name:
548d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    WriteVariable(output, file_copy.inputs_name, ' ')
549d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('\n)\n')
550d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
551d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  extra_deps.append(copy_name)
552d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
553d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
554d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef CreateCMakeTargetBaseName(qualified_target):
555d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """This is the name we would like the target to have."""
556d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  _, gyp_target_name, gyp_target_toolset = (
557d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      gyp.common.ParseQualifiedTarget(qualified_target))
558d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  cmake_target_base_name = gyp_target_name
559d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if gyp_target_toolset and gyp_target_toolset != 'target':
560d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    cmake_target_base_name += '_' + gyp_target_toolset
561d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  return StringToCMakeTargetName(cmake_target_base_name)
562d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
563d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
564d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef CreateCMakeTargetFullName(qualified_target):
565d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """An unambiguous name for the target."""
566d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  gyp_file, gyp_target_name, gyp_target_toolset = (
567d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      gyp.common.ParseQualifiedTarget(qualified_target))
568d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  cmake_target_full_name = gyp_file + ':' + gyp_target_name
569d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if gyp_target_toolset and gyp_target_toolset != 'target':
570d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    cmake_target_full_name += '_' + gyp_target_toolset
571d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  return StringToCMakeTargetName(cmake_target_full_name)
572d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
573d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
574d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgclass CMakeNamer(object):
575d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """Converts Gyp target names into CMake target names.
576d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
577d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  CMake requires that target names be globally unique. One way to ensure
578d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  this is to fully qualify the names of the targets. Unfortunatly, this
579d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  ends up with all targets looking like "chrome_chrome_gyp_chrome" instead
580d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  of just "chrome". If this generator were only interested in building, it
581d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  would be possible to fully qualify all target names, then create
582d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  unqualified target names which depend on all qualified targets which
583d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  should have had that name. This is more or less what the 'make' generator
584d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  does with aliases. However, one goal of this generator is to create CMake
585d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  files for use with IDEs, and fully qualified names are not as user
586d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  friendly.
587d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
588d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  Since target name collision is rare, we do the above only when required.
589d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
590d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  Toolset variants are always qualified from the base, as this is required for
591d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  building. However, it also makes sense for an IDE, as it is possible for
592d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  defines to be different.
593d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  """
594d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  def __init__(self, target_list):
595d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    self.cmake_target_base_names_conficting = set()
596d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
597d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    cmake_target_base_names_seen = set()
598d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    for qualified_target in target_list:
599d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      cmake_target_base_name = CreateCMakeTargetBaseName(qualified_target)
600d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
601d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      if cmake_target_base_name not in cmake_target_base_names_seen:
602d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        cmake_target_base_names_seen.add(cmake_target_base_name)
603d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      else:
604d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        self.cmake_target_base_names_conficting.add(cmake_target_base_name)
605d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
606d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  def CreateCMakeTargetName(self, qualified_target):
607d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    base_name = CreateCMakeTargetBaseName(qualified_target)
608d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if base_name in self.cmake_target_base_names_conficting:
609d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      return CreateCMakeTargetFullName(qualified_target)
610d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    return base_name
611d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
612d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
613d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use,
614d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                options, generator_flags, all_qualified_targets, output):
615d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
616d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # The make generator does this always.
617d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # TODO: It would be nice to be able to tell CMake all dependencies.
618d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  circular_libs = generator_flags.get('circular', True)
619d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
620d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if not generator_flags.get('standalone', False):
621d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n#')
622d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(qualified_target)
623d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n')
624d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
625d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  gyp_file, _, _ = gyp.common.ParseQualifiedTarget(qualified_target)
626d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  rel_gyp_file = gyp.common.RelativePath(gyp_file, options.toplevel_dir)
627d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  rel_gyp_dir = os.path.dirname(rel_gyp_file)
628d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
629d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Relative path from build dir to top dir.
630d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  build_to_top = gyp.common.InvertRelativePath(build_dir, options.toplevel_dir)
631d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Relative path from build dir to gyp dir.
632d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  build_to_gyp = os.path.join(build_to_top, rel_gyp_dir)
633d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
634d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  path_from_cmakelists_to_gyp = build_to_gyp
635d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
636d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  spec = target_dicts.get(qualified_target, {})
637d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  config = spec.get('configurations', {}).get(config_to_use, {})
638d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
639d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  target_name = spec.get('target_name', '<missing target name>')
640d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  target_type = spec.get('type', '<missing target type>')
641d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  target_toolset = spec.get('toolset')
642d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
643d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  SetVariable(output, 'TARGET', target_name)
644d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  SetVariable(output, 'TOOLSET', target_toolset)
645d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
646d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  cmake_target_name = namer.CreateCMakeTargetName(qualified_target)
647d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
648d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  extra_sources = []
649d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  extra_deps = []
650d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
651d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Actions must come first, since they can generate more OBJs for use below.
652d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if 'actions' in spec:
653d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    WriteActions(cmake_target_name, spec['actions'], extra_sources, extra_deps,
654d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                 path_from_cmakelists_to_gyp, output)
655d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
656d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Rules must be early like actions.
657d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if 'rules' in spec:
658d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    WriteRules(cmake_target_name, spec['rules'], extra_sources, extra_deps,
659d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org               path_from_cmakelists_to_gyp, output)
660d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
661d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Copies
662d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if 'copies' in spec:
663d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    WriteCopies(cmake_target_name, spec['copies'], extra_deps,
664d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                path_from_cmakelists_to_gyp, output)
665d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
666d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Target and sources
667d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  srcs = spec.get('sources', [])
668d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
669d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Gyp separates the sheep from the goats based on file extensions.
670d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  def partition(l, p):
671d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    return reduce(lambda x, e: x[not p(e)].append(e) or x, l, ([], []))
672d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  compilable_srcs, other_srcs = partition(srcs, Compilable)
673d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
674d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # CMake gets upset when executable targets provide no sources.
675d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if target_type == 'executable' and not compilable_srcs and not extra_sources:
676d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    print ('Executable %s has no complilable sources, treating as "none".' %
677d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                       target_name                                         )
678d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    target_type = 'none'
679d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
680d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  cmake_target_type = cmake_target_type_from_gyp_target_type.get(target_type)
681d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if cmake_target_type is None:
682d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    print ('Target %s has unknown target type %s, skipping.' %
683d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          (        target_name,               target_type  ) )
684d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    return
685d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
686d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  other_srcs_name = None
687d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if other_srcs:
688d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    other_srcs_name = cmake_target_name + '__other_srcs'
689d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetVariableList(output, other_srcs_name,
690d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        [NormjoinPath(path_from_cmakelists_to_gyp, src) for src in other_srcs])
691d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
692d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # CMake is opposed to setting linker directories and considers the practice
693d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # of setting linker directories dangerous. Instead, it favors the use of
694d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # find_library and passing absolute paths to target_link_libraries.
695d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # However, CMake does provide the command link_directories, which adds
696d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # link directories to targets defined after it is called.
697d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # As a result, link_directories must come before the target definition.
698d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # CMake unfortunately has no means of removing entries from LINK_DIRECTORIES.
699d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  library_dirs = config.get('library_dirs')
700d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if library_dirs is not None:
701d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('link_directories(')
702d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    for library_dir in library_dirs:
703d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(' ')
704d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(NormjoinPath(path_from_cmakelists_to_gyp, library_dir))
705d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('\n')
706d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(')\n')
707d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
708d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(cmake_target_type.command)
709d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('(')
710d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(cmake_target_name)
711d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
712d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if cmake_target_type.modifier is not None:
713d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(' ')
714d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(cmake_target_type.modifier)
715d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
716d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if other_srcs_name:
717d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    WriteVariable(output, other_srcs_name, ' ')
718d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
719d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('\n')
720d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
721d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for src in compilable_srcs:
722d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('  ')
723d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(NormjoinPath(path_from_cmakelists_to_gyp, src))
724d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n')
725d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for extra_source in extra_sources:
726d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('  ')
727d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    src, _ = extra_source
728d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(NormjoinPath(path_from_cmakelists_to_gyp, src))
729d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n')
730d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
731d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(')\n')
732d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
733d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Output name and location.
734d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if target_type != 'none':
735d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    # Mark uncompiled sources as uncompiled.
736d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if other_srcs_name:
737d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('set_source_files_properties(')
738d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      WriteVariable(output, other_srcs_name, '')
739d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(' PROPERTIES HEADER_FILE_ONLY "TRUE")\n')
740d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
741d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    # Output directory
742d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    target_output_directory = spec.get('product_dir')
743d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if target_output_directory is None:
744d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      if target_type in ('executable', 'loadable_module'):
745d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        target_output_directory = generator_default_variables['PRODUCT_DIR']
746d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      elif target_type in ('shared_library'):
747d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        target_output_directory = '${builddir}/lib.${TOOLSET}'
748d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      elif spec.get('standalone_static_library', False):
749d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        target_output_directory = generator_default_variables['PRODUCT_DIR']
750d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      else:
751d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        base_path = gyp.common.RelativePath(os.path.dirname(gyp_file),
752d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                            options.toplevel_dir)
753d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        target_output_directory = '${obj}.${TOOLSET}'
754d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        target_output_directory = (
755d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org            os.path.join(target_output_directory, base_path))
756d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
757d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    cmake_target_output_directory = NormjoinPathForceCMakeSource(
758d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                        path_from_cmakelists_to_gyp,
759d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                        target_output_directory)
760d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetTargetProperty(output,
761d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        cmake_target_name,
762d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        cmake_target_type.property_modifier + '_OUTPUT_DIRECTORY',
763d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        cmake_target_output_directory)
764d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
765d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    # Output name
766d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    default_product_prefix = ''
767d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    default_product_name = target_name
768d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    default_product_ext = ''
769d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if target_type == 'static_library':
770d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      static_library_prefix = generator_default_variables['STATIC_LIB_PREFIX']
771d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      default_product_name = RemovePrefix(default_product_name,
772d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                          static_library_prefix)
773d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      default_product_prefix = static_library_prefix
774d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      default_product_ext = generator_default_variables['STATIC_LIB_SUFFIX']
775d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
776d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    elif target_type in ('loadable_module', 'shared_library'):
777d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      shared_library_prefix = generator_default_variables['SHARED_LIB_PREFIX']
778d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      default_product_name = RemovePrefix(default_product_name,
779d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                          shared_library_prefix)
780d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      default_product_prefix = shared_library_prefix
781d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      default_product_ext = generator_default_variables['SHARED_LIB_SUFFIX']
782d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
783d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    elif target_type != 'executable':
784d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      print ('ERROR: What output file should be generated?',
785d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org              'type', target_type, 'target', target_name)
786d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
787d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    product_prefix = spec.get('product_prefix', default_product_prefix)
788d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    product_name = spec.get('product_name', default_product_name)
789d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    product_ext = spec.get('product_extension')
790d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if product_ext:
791d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      product_ext = '.' + product_ext
792d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    else:
793d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      product_ext = default_product_ext
794d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
795d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetTargetProperty(output, cmake_target_name, 'PREFIX', product_prefix)
796d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetTargetProperty(output, cmake_target_name,
797d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                        cmake_target_type.property_modifier + '_OUTPUT_NAME',
798d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                        product_name)
799d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetTargetProperty(output, cmake_target_name, 'SUFFIX', product_ext)
800d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
801d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    # Make the output of this target referenceable as a source.
802d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    cmake_target_output_basename = product_prefix + product_name + product_ext
803d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    cmake_target_output = os.path.join(cmake_target_output_directory,
804d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                       cmake_target_output_basename)
805d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetFileProperty(output, cmake_target_output, 'GENERATED', ['TRUE'], '')
806d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
807d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Let CMake know if the 'all' target should depend on this target.
808d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  exclude_from_all = ('TRUE' if qualified_target not in all_qualified_targets
809d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                             else 'FALSE')
810d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  SetTargetProperty(output, cmake_target_name,
811d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                      'EXCLUDE_FROM_ALL', exclude_from_all)
812d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for extra_target_name in extra_deps:
813d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetTargetProperty(output, extra_target_name,
814d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                        'EXCLUDE_FROM_ALL', exclude_from_all)
815d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
816d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Includes
817d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  includes = config.get('include_dirs')
818d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if includes:
819d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    # This (target include directories) is what requires CMake 2.8.8
820d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    includes_name = cmake_target_name + '__include_dirs'
821d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetVariableList(output, includes_name,
822d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        [NormjoinPathForceCMakeSource(path_from_cmakelists_to_gyp, include)
823d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org         for include in includes])
824d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('set_property(TARGET ')
825d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(cmake_target_name)
826d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(' APPEND PROPERTY INCLUDE_DIRECTORIES ')
827d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    WriteVariable(output, includes_name, '')
828d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(')\n')
829d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
830d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Defines
831d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  defines = config.get('defines')
832d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if defines is not None:
833d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetTargetProperty(output,
834d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                        cmake_target_name,
835d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                        'COMPILE_DEFINITIONS',
836d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                        defines,
837d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                        ';')
838d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
839d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Compile Flags - http://www.cmake.org/Bug/view.php?id=6493
840d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # CMake currently does not have target C and CXX flags.
841d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # So, instead of doing...
842d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
843d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # cflags_c = config.get('cflags_c')
844d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # if cflags_c is not None:
845d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  #   SetTargetProperty(output, cmake_target_name,
846d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  #                       'C_COMPILE_FLAGS', cflags_c, ' ')
847d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
848d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # cflags_cc = config.get('cflags_cc')
849d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # if cflags_cc is not None:
850d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  #   SetTargetProperty(output, cmake_target_name,
851d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  #                       'CXX_COMPILE_FLAGS', cflags_cc, ' ')
852d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
853d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Instead we must...
854d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  s_sources = []
855d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  c_sources = []
856d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  cxx_sources = []
857d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for src in srcs:
858d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    _, ext = os.path.splitext(src)
859d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    src_type = COMPILABLE_EXTENSIONS.get(ext, None)
860d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
861d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if src_type == 's':
862d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      s_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src))
863d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
864d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if src_type == 'cc':
865d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      c_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src))
866d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
867d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if src_type == 'cxx':
868d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      cxx_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src))
869d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
870d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for extra_source in extra_sources:
871d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    src, real_source = extra_source
872d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    _, ext = os.path.splitext(real_source)
873d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    src_type = COMPILABLE_EXTENSIONS.get(ext, None)
874d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
875d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if src_type == 's':
876d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      s_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src))
877d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
878d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if src_type == 'cc':
879d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      c_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src))
880d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
881d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if src_type == 'cxx':
882d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      cxx_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src))
883d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
884d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  cflags = config.get('cflags', [])
885d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  cflags_c = config.get('cflags_c', [])
886d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  cflags_cxx = config.get('cflags_cc', [])
887d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if c_sources and not (s_sources or cxx_sources):
888d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    flags = []
889d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    flags.extend(cflags)
890d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    flags.extend(cflags_c)
891d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', flags, ' ')
892d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
893d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  elif cxx_sources and not (s_sources or c_sources):
894d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    flags = []
895d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    flags.extend(cflags)
896d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    flags.extend(cflags_cxx)
897d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', flags, ' ')
898d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
899d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  else:
900d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if s_sources and cflags:
901d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      SetFilesProperty(output, s_sources, 'COMPILE_FLAGS', cflags, ' ')
902d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
903d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if c_sources and (cflags or cflags_c):
904d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      flags = []
905d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      flags.extend(cflags)
906d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      flags.extend(cflags_c)
907d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      SetFilesProperty(output, c_sources, 'COMPILE_FLAGS', flags, ' ')
908d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
909d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if cxx_sources and (cflags or cflags_cxx):
910d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      flags = []
911d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      flags.extend(cflags)
912d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      flags.extend(cflags_cxx)
913d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      SetFilesProperty(output, cxx_sources, 'COMPILE_FLAGS', flags, ' ')
914d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
915d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Have assembly link as c if there are no other files
916d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if not c_sources and not cxx_sources and s_sources:
917d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetTargetProperty(output, cmake_target_name, 'LINKER_LANGUAGE', ['C'])
918d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
919d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Linker flags
920d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  ldflags = config.get('ldflags')
921d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if ldflags is not None:
922d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    SetTargetProperty(output, cmake_target_name, 'LINK_FLAGS', ldflags, ' ')
923d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
924d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Note on Dependencies and Libraries:
925d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # CMake wants to handle link order, resolving the link line up front.
926d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Gyp does not retain or enforce specifying enough information to do so.
927d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # So do as other gyp generators and use --start-group and --end-group.
928d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Give CMake as little information as possible so that it doesn't mess it up.
929d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
930d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Dependencies
931d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  rawDeps = spec.get('dependencies', [])
932d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
933d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  static_deps = []
934d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  shared_deps = []
935d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  other_deps = []
936d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for rawDep in rawDeps:
937d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    dep_cmake_name = namer.CreateCMakeTargetName(rawDep)
938d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    dep_spec = target_dicts.get(rawDep, {})
939d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    dep_target_type = dep_spec.get('type', None)
940d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
941d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if dep_target_type == 'static_library':
942d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      static_deps.append(dep_cmake_name)
943d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    elif dep_target_type ==  'shared_library':
944d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      shared_deps.append(dep_cmake_name)
945d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    else:
946d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      other_deps.append(dep_cmake_name)
947d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
948d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # ensure all external dependencies are complete before internal dependencies
949d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # extra_deps currently only depend on their own deps, so otherwise run early
950d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if static_deps or shared_deps or other_deps:
951d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    for extra_dep in extra_deps:
952d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('add_dependencies(')
953d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(extra_dep)
954d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('\n')
955d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      for deps in (static_deps, shared_deps, other_deps):
956d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        for dep in gyp.common.uniquer(deps):
957d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write('  ')
958d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write(dep)
959d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write('\n')
960d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(')\n')
961d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
962d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  linkable = target_type in ('executable', 'loadable_module', 'shared_library')
963d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  other_deps.extend(extra_deps)
964d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if other_deps or (not linkable and (static_deps or shared_deps)):
965d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('add_dependencies(')
966d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(cmake_target_name)
967d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write('\n')
968d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    for dep in gyp.common.uniquer(other_deps):
969d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('  ')
970d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(dep)
971d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('\n')
972d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if not linkable:
973d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      for deps in (static_deps, shared_deps):
974d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        for lib_dep in gyp.common.uniquer(deps):
975d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write('  ')
976d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write(lib_dep)
977d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write('\n')
978d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    output.write(')\n')
979d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
980d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Libraries
981d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if linkable:
982d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    external_libs = [lib for lib in spec.get('libraries', []) if len(lib) > 0]
983d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if external_libs or static_deps or shared_deps:
984d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('target_link_libraries(')
985d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(cmake_target_name)
986d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write('\n')
987d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      if static_deps:
988d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        write_group = circular_libs and len(static_deps) > 1
989d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        if write_group:
990d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write('-Wl,--start-group\n')
991d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        for dep in gyp.common.uniquer(static_deps):
992d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write('  ')
993d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write(dep)
994d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write('\n')
995d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        if write_group:
996d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write('-Wl,--end-group\n')
997d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      if shared_deps:
998d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        for dep in gyp.common.uniquer(shared_deps):
999d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write('  ')
1000d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write(dep)
1001d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write('\n')
1002d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      if external_libs:
1003d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        for lib in gyp.common.uniquer(external_libs):
1004d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write('  ')
1005d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write(lib)
1006d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          output.write('\n')
1007d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1008d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      output.write(')\n')
1009d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1010d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  UnsetVariable(output, 'TOOLSET')
1011d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  UnsetVariable(output, 'TARGET')
1012d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1013d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1014d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef GenerateOutputForConfig(target_list, target_dicts, data,
1015d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                            params, config_to_use):
1016d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  options = params['options']
1017d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  generator_flags = params['generator_flags']
1018d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1019d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # generator_dir: relative path from pwd to where make puts build files.
1020d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Makes migrating from make to cmake easier, cmake doesn't put anything here.
1021d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Each Gyp configuration creates a different CMakeLists.txt file
1022d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # to avoid incompatibilities between Gyp and CMake configurations.
1023d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  generator_dir = os.path.relpath(options.generator_output or '.')
1024d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1025d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # output_dir: relative path from generator_dir to the build directory.
1026d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output_dir = generator_flags.get('output_dir', 'out')
1027d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1028d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # build_dir: relative path from source root to our output files.
1029d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # e.g. "out/Debug"
1030d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  build_dir = os.path.normpath(os.path.join(generator_dir,
1031d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                            output_dir,
1032d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                            config_to_use))
1033d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1034d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  toplevel_build = os.path.join(options.toplevel_dir, build_dir)
1035d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1036d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output_file = os.path.join(toplevel_build, 'CMakeLists.txt')
1037b5a494899379867f5445f29db21fb2b8e5e8e03ethakis@chromium.org  gyp.common.EnsureDirExists(output_file)
1038d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1039d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output = open(output_file, 'w')
1040d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR)\n')
1041d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('cmake_policy(VERSION 2.8.8)\n')
1042d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1043d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  _, project_target, _ = gyp.common.ParseQualifiedTarget(target_list[-1])
1044d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('project(')
1045d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(project_target)
1046d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write(')\n')
1047d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1048d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  SetVariable(output, 'configuration', config_to_use)
1049d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1050d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # The following appears to be as-yet undocumented.
1051d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # http://public.kitware.com/Bug/view.php?id=8392
1052d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('enable_language(ASM)\n')
1053d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # ASM-ATT does not support .S files.
1054d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # output.write('enable_language(ASM-ATT)\n')
1055d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1056d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  SetVariable(output, 'builddir', '${CMAKE_BINARY_DIR}')
1057d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  SetVariable(output, 'obj', '${builddir}/obj')
1058d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('\n')
1059d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1060d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # TODO: Undocumented/unsupported (the CMake Java generator depends on it).
1061d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # CMake by default names the object resulting from foo.c to be foo.c.o.
1062d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Gyp traditionally names the object resulting from foo.c foo.o.
1063d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # This should be irrelevant, but some targets extract .o files from .a
1064d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # and depend on the name of the extracted .o files.
1065d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1)\n')
1066d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)\n')
1067d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.write('\n')
1068d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1069d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  namer = CMakeNamer(target_list)
1070d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1071d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # The list of targets upon which the 'all' target should depend.
1072d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # CMake has it's own implicit 'all' target, one is not created explicitly.
1073d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  all_qualified_targets = set()
1074d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for build_file in params['build_files']:
1075d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    for qualified_target in gyp.common.AllTargets(target_list,
1076d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                                  target_dicts,
1077d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                                  os.path.normpath(build_file)):
1078d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      all_qualified_targets.add(qualified_target)
1079d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1080d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for qualified_target in target_list:
1081d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use,
1082d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                options, generator_flags, all_qualified_targets, output)
1083d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1084d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output.close()
1085d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1086d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1087d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef PerformBuild(data, configurations, params):
1088d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  options = params['options']
1089d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  generator_flags = params['generator_flags']
1090d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1091d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # generator_dir: relative path from pwd to where make puts build files.
1092d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Makes migrating from make to cmake easier, cmake doesn't put anything here.
1093d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  generator_dir = os.path.relpath(options.generator_output or '.')
1094d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1095d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # output_dir: relative path from generator_dir to the build directory.
1096d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  output_dir = generator_flags.get('output_dir', 'out')
1097d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1098d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  for config_name in configurations:
1099d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    # build_dir: relative path from source root to our output files.
1100d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    # e.g. "out/Debug"
1101d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    build_dir = os.path.normpath(os.path.join(generator_dir,
1102d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                              output_dir,
1103d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                              config_name))
1104d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    arguments = ['cmake', '-G', 'Ninja']
1105d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    print 'Generating [%s]: %s' % (config_name, arguments)
1106d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    subprocess.check_call(arguments, cwd=build_dir)
1107d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1108d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    arguments = ['ninja', '-C', build_dir]
1109d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    print 'Building [%s]: %s' % (config_name, arguments)
1110d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    subprocess.check_call(arguments)
1111d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1112d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1113d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef CallGenerateOutputForConfig(arglist):
1114d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # Ignore the interrupt signal so that the parent process catches it and
1115d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  # kills all multiprocessing children.
1116d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  signal.signal(signal.SIGINT, signal.SIG_IGN)
1117d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1118d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  target_list, target_dicts, data, params, config_name = arglist
1119d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  GenerateOutputForConfig(target_list, target_dicts, data, params, config_name)
1120d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1121d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org
1122d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.orgdef GenerateOutput(target_list, target_dicts, data, params):
1123d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  user_config = params.get('generator_flags', {}).get('config', None)
1124d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  if user_config:
1125d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    GenerateOutputForConfig(target_list, target_dicts, data,
1126d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                            params, user_config)
1127d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org  else:
1128d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    config_names = target_dicts[target_list[0]]['configurations'].keys()
1129d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    if params['parallel']:
1130d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      try:
1131d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        pool = multiprocessing.Pool(len(config_names))
1132d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        arglists = []
1133d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        for config_name in config_names:
1134d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          arglists.append((target_list, target_dicts, data,
1135d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                           params, config_name))
1136d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org          pool.map(CallGenerateOutputForConfig, arglists)
1137d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      except KeyboardInterrupt, e:
1138d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        pool.terminate()
1139d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        raise e
1140d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org    else:
1141d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org      for config_name in config_names:
1142d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org        GenerateOutputForConfig(target_list, target_dicts, data,
1143d0176c0a2a9e558662905c328c3aa93fd25bbf12bungeman@chromium.org                                params, config_name)
1144