Index: pylib/gyp/generator/cmake.py |
diff --git a/pylib/gyp/generator/cmake.py b/pylib/gyp/generator/cmake.py |
index 8f5feddee1cb353147cb9df51ddb2c81684a0975..cd6f46260f92867a7c5c17dd6bab02227aed709d 100644 |
--- a/pylib/gyp/generator/cmake.py |
+++ b/pylib/gyp/generator/cmake.py |
@@ -150,20 +150,17 @@ def SetFileProperty(output, source_name, property_name, values, sep): |
output.write('")\n') |
-def SetFilesProperty(output, source_names, property_name, values, sep): |
+def SetFilesProperty(output, variable, property_name, values, sep): |
"""Given a set of source files, sets the given property on them.""" |
- output.write('set_source_files_properties(\n') |
- for source_name in source_names: |
- output.write(' ') |
- output.write(source_name) |
- output.write('\n') |
- output.write(' PROPERTIES\n ') |
+ output.write('set_source_files_properties(') |
+ WriteVariable(output, variable) |
+ output.write(' PROPERTIES ') |
output.write(property_name) |
output.write(' "') |
for value in values: |
output.write(CMakeStringEscape(value)) |
output.write(sep) |
- output.write('"\n)\n') |
+ output.write('")\n') |
def SetTargetProperty(output, target_name, property_name, values, sep=''): |
@@ -236,11 +233,11 @@ def StringToCMakeTargetName(a): |
"""Converts the given string 'a' to a valid CMake target name. |
All invalid characters are replaced by '_'. |
- Invalid for cmake: ' ', '/', '(', ')' |
+ Invalid for cmake: ' ', '/', '(', ')', '"' |
Invalid for make: ':' |
Invalid for unknown reasons but cause failures: '.' |
""" |
- return a.translate(string.maketrans(' /():.', '______')) |
+ return a.translate(string.maketrans(' /():."', '_______')) |
def WriteActions(target_name, actions, extra_sources, extra_deps, |
@@ -640,6 +637,12 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, |
target_type = spec.get('type', '<missing target type>') |
target_toolset = spec.get('toolset') |
+ cmake_target_type = cmake_target_type_from_gyp_target_type.get(target_type) |
+ if cmake_target_type is None: |
+ print ('Target %s has unknown target type %s, skipping.' % |
+ ( target_name, target_type ) ) |
+ return |
+ |
SetVariable(output, 'TARGET', target_name) |
SetVariable(output, 'TOOLSET', target_toolset) |
@@ -667,27 +670,78 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, |
srcs = spec.get('sources', []) |
# Gyp separates the sheep from the goats based on file extensions. |
- def partition(l, p): |
- return reduce(lambda x, e: x[not p(e)].append(e) or x, l, ([], [])) |
- compilable_srcs, other_srcs = partition(srcs, Compilable) |
+ # A full separation is done here because of flag handing (see below). |
+ s_sources = [] |
+ c_sources = [] |
+ cxx_sources = [] |
+ other_sources = [] |
+ for src in srcs: |
+ _, ext = os.path.splitext(src) |
+ src_type = COMPILABLE_EXTENSIONS.get(ext, None) |
+ src_norm_path = NormjoinPath(path_from_cmakelists_to_gyp, src); |
- # CMake gets upset when executable targets provide no sources. |
- if target_type == 'executable' and not compilable_srcs and not extra_sources: |
- print ('Executable %s has no complilable sources, treating as "none".' % |
- target_name ) |
- target_type = 'none' |
+ if src_type == 's': |
+ s_sources.append(src_norm_path) |
+ elif src_type == 'cc': |
+ c_sources.append(src_norm_path) |
+ elif src_type == 'cxx': |
+ cxx_sources.append(src_norm_path) |
+ else: |
+ other_sources.append(src_norm_path) |
- cmake_target_type = cmake_target_type_from_gyp_target_type.get(target_type) |
- if cmake_target_type is None: |
- print ('Target %s has unknown target type %s, skipping.' % |
- ( target_name, target_type ) ) |
- return |
+ for extra_source in extra_sources: |
+ src, real_source = extra_source |
+ _, ext = os.path.splitext(real_source) |
+ src_type = COMPILABLE_EXTENSIONS.get(ext, None) |
+ |
+ if src_type == 's': |
+ s_sources.append(src) |
+ elif src_type == 'cc': |
+ c_sources.append(src) |
+ elif src_type == 'cxx': |
+ cxx_sources.append(src) |
+ else: |
+ other_sources.append(src) |
+ |
+ s_sources_name = None |
+ if s_sources: |
+ s_sources_name = cmake_target_name + '__asm_srcs' |
+ SetVariableList(output, s_sources_name, s_sources) |
+ |
+ c_sources_name = None |
+ if c_sources: |
+ c_sources_name = cmake_target_name + '__c_srcs' |
+ SetVariableList(output, c_sources_name, c_sources) |
+ |
+ cxx_sources_name = None |
+ if cxx_sources: |
+ cxx_sources_name = cmake_target_name + '__cxx_srcs' |
+ SetVariableList(output, cxx_sources_name, cxx_sources) |
+ |
+ other_sources_name = None |
+ if other_sources: |
+ other_sources_name = cmake_target_name + '__other_srcs' |
+ SetVariableList(output, other_sources_name, other_sources) |
+ |
+ # CMake gets upset when executable targets provide no sources. |
+ # http://www.cmake.org/pipermail/cmake/2010-July/038461.html |
+ dummy_sources_name = None |
+ has_sources = (s_sources_name or |
+ c_sources_name or |
+ cxx_sources_name or |
+ other_sources_name) |
+ if target_type == 'executable' and not has_sources: |
Nico
2015/05/27 20:11:49
Does this ever happen? I'd expect other generators
|
+ dummy_sources_name = cmake_target_name + '__dummy_srcs' |
+ SetVariable(output, dummy_sources_name, |
+ "${obj}.${TOOLSET}/${TARGET}/genc/dummy.c") |
+ output.write('if(NOT EXISTS "') |
+ WriteVariable(output, dummy_sources_name) |
+ output.write('")\n') |
+ output.write(' file(WRITE "') |
+ WriteVariable(output, dummy_sources_name) |
+ output.write('" "")\n') |
+ output.write("endif()\n") |
- other_srcs_name = None |
- if other_srcs: |
- other_srcs_name = cmake_target_name + '__other_srcs' |
- SetVariableList(output, other_srcs_name, |
- [NormjoinPath(path_from_cmakelists_to_gyp, src) for src in other_srcs]) |
# CMake is opposed to setting linker directories and considers the practice |
# of setting linker directories dangerous. Instead, it favors the use of |
@@ -713,29 +767,25 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, |
output.write(' ') |
output.write(cmake_target_type.modifier) |
- if other_srcs_name: |
- WriteVariable(output, other_srcs_name, ' ') |
- |
- output.write('\n') |
- |
- for src in compilable_srcs: |
- output.write(' ') |
- output.write(NormjoinPath(path_from_cmakelists_to_gyp, src)) |
- output.write('\n') |
- for extra_source in extra_sources: |
- output.write(' ') |
- src, _ = extra_source |
- output.write(NormjoinPath(path_from_cmakelists_to_gyp, src)) |
- output.write('\n') |
+ if s_sources_name: |
+ WriteVariable(output, s_sources_name, ' ') |
+ if c_sources_name: |
+ WriteVariable(output, c_sources_name, ' ') |
+ if cxx_sources_name: |
+ WriteVariable(output, cxx_sources_name, ' ') |
+ if other_sources_name: |
+ WriteVariable(output, other_sources_name, ' ') |
+ if dummy_sources_name: |
+ WriteVariable(output, dummy_sources_name, ' ') |
output.write(')\n') |
# Output name and location. |
if target_type != 'none': |
# Mark uncompiled sources as uncompiled. |
- if other_srcs_name: |
+ if other_sources_name: |
output.write('set_source_files_properties(') |
- WriteVariable(output, other_srcs_name, '') |
+ WriteVariable(output, other_sources_name, '') |
output.write(' PROPERTIES HEADER_FILE_ONLY "TRUE")\n') |
# Output directory |
@@ -851,40 +901,13 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, |
# 'CXX_COMPILE_FLAGS', cflags_cc, ' ') |
# Instead we must... |
- s_sources = [] |
- c_sources = [] |
- cxx_sources = [] |
- for src in srcs: |
- _, ext = os.path.splitext(src) |
- src_type = COMPILABLE_EXTENSIONS.get(ext, None) |
- |
- if src_type == 's': |
- s_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) |
- |
- if src_type == 'cc': |
- c_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) |
- |
- if src_type == 'cxx': |
- cxx_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) |
- |
- for extra_source in extra_sources: |
- src, real_source = extra_source |
- _, ext = os.path.splitext(real_source) |
- src_type = COMPILABLE_EXTENSIONS.get(ext, None) |
- |
- if src_type == 's': |
- s_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) |
- |
- if src_type == 'cc': |
- c_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) |
- |
- if src_type == 'cxx': |
- cxx_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) |
- |
cflags = config.get('cflags', []) |
cflags_c = config.get('cflags_c', []) |
cflags_cxx = config.get('cflags_cc', []) |
- if c_sources and not (s_sources or cxx_sources): |
+ if (not cflags_c or not c_sources) and (not cflags_cxx or not cxx_sources): |
+ SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', cflags, ' ') |
+ |
+ elif c_sources and not (s_sources or cxx_sources): |
flags = [] |
flags.extend(cflags) |
flags.extend(cflags_c) |
@@ -898,22 +921,22 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, |
else: |
if s_sources and cflags: |
- SetFilesProperty(output, s_sources, 'COMPILE_FLAGS', cflags, ' ') |
+ SetFilesProperty(output, s_sources_name, 'COMPILE_FLAGS', cflags, ' ') |
if c_sources and (cflags or cflags_c): |
flags = [] |
flags.extend(cflags) |
flags.extend(cflags_c) |
- SetFilesProperty(output, c_sources, 'COMPILE_FLAGS', flags, ' ') |
+ SetFilesProperty(output, c_sources_name, 'COMPILE_FLAGS', flags, ' ') |
if cxx_sources and (cflags or cflags_cxx): |
flags = [] |
flags.extend(cflags) |
flags.extend(cflags_cxx) |
- SetFilesProperty(output, cxx_sources, 'COMPILE_FLAGS', flags, ' ') |
+ SetFilesProperty(output, cxx_sources_name, 'COMPILE_FLAGS', flags, ' ') |
- # Have assembly link as c if there are no other files |
- if not c_sources and not cxx_sources and s_sources: |
+ # Link as 'C' if there are no other files |
+ if not c_sources and not cxx_sources: |
SetTargetProperty(output, cmake_target_name, 'LINKER_LANGUAGE', ['C']) |
# Linker flags |
@@ -1047,12 +1070,32 @@ def GenerateOutputForConfig(target_list, target_dicts, data, |
SetVariable(output, 'configuration', config_to_use) |
+ cc = None |
+ cxx = None |
+ ar = None |
+ |
+ #TODO: support make_global_settings |
+ |
+ cc = gyp.common.GetEnvironFallback(['CC_target', 'CC'], cc) |
+ cxx = gyp.common.GetEnvironFallback(['CXX_target', 'CXX'], cxx) |
+ ar = gyp.common.GetEnvironFallback(['AR_target', 'AR'], ar) |
+ |
+ if cc: |
+ SetVariable(output, 'CMAKE_C_COMPILER', cc) |
+ if cxx: |
+ SetVariable(output, 'CMAKE_CXX_COMPILER', cxx) |
+ if ar: |
+ SetVariable(output, 'CMAKE_AR', ar) |
+ |
# The following appears to be as-yet undocumented. |
# http://public.kitware.com/Bug/view.php?id=8392 |
output.write('enable_language(ASM)\n') |
# ASM-ATT does not support .S files. |
# output.write('enable_language(ASM-ATT)\n') |
+ if cc: |
+ SetVariable(output, 'CMAKE_ASM_COMPILER', cc) |
+ |
SetVariable(output, 'builddir', '${CMAKE_BINARY_DIR}') |
SetVariable(output, 'obj', '${builddir}/obj') |
output.write('\n') |