| OLD | NEW |
| 1 # Copyright (c) 2013 Google Inc. All rights reserved. | 1 # Copyright (c) 2013 Google Inc. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """cmake output module | 5 """cmake output module |
| 6 | 6 |
| 7 This module is under development and should be considered experimental. | 7 This module is under development and should be considered experimental. |
| 8 | 8 |
| 9 This module produces cmake (2.8.8+) input as its output. One CMakeLists.txt is | 9 This module produces cmake (2.8.8+) input as its output. One CMakeLists.txt is |
| 10 created for each configuration. | 10 created for each configuration. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 output.write(source_name) | 143 output.write(source_name) |
| 144 output.write(' PROPERTIES ') | 144 output.write(' PROPERTIES ') |
| 145 output.write(property_name) | 145 output.write(property_name) |
| 146 output.write(' "') | 146 output.write(' "') |
| 147 for value in values: | 147 for value in values: |
| 148 output.write(CMakeStringEscape(value)) | 148 output.write(CMakeStringEscape(value)) |
| 149 output.write(sep) | 149 output.write(sep) |
| 150 output.write('")\n') | 150 output.write('")\n') |
| 151 | 151 |
| 152 | 152 |
| 153 def SetFilesProperty(output, source_names, property_name, values, sep): | 153 def SetFilesProperty(output, variable, property_name, values, sep): |
| 154 """Given a set of source files, sets the given property on them.""" | 154 """Given a set of source files, sets the given property on them.""" |
| 155 output.write('set_source_files_properties(\n') | 155 output.write('set_source_files_properties(') |
| 156 for source_name in source_names: | 156 WriteVariable(output, variable) |
| 157 output.write(' ') | 157 output.write(' PROPERTIES ') |
| 158 output.write(source_name) | |
| 159 output.write('\n') | |
| 160 output.write(' PROPERTIES\n ') | |
| 161 output.write(property_name) | 158 output.write(property_name) |
| 162 output.write(' "') | 159 output.write(' "') |
| 163 for value in values: | 160 for value in values: |
| 164 output.write(CMakeStringEscape(value)) | 161 output.write(CMakeStringEscape(value)) |
| 165 output.write(sep) | 162 output.write(sep) |
| 166 output.write('"\n)\n') | 163 output.write('")\n') |
| 167 | 164 |
| 168 | 165 |
| 169 def SetTargetProperty(output, target_name, property_name, values, sep=''): | 166 def SetTargetProperty(output, target_name, property_name, values, sep=''): |
| 170 """Given a target, sets the given property.""" | 167 """Given a target, sets the given property.""" |
| 171 output.write('set_target_properties(') | 168 output.write('set_target_properties(') |
| 172 output.write(target_name) | 169 output.write(target_name) |
| 173 output.write(' PROPERTIES ') | 170 output.write(' PROPERTIES ') |
| 174 output.write(property_name) | 171 output.write(property_name) |
| 175 output.write(' "') | 172 output.write(' "') |
| 176 for value in values: | 173 for value in values: |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 'shared_library': CMakeTargetType('add_library', 'SHARED', 'LIBRARY'), | 226 'shared_library': CMakeTargetType('add_library', 'SHARED', 'LIBRARY'), |
| 230 'loadable_module': CMakeTargetType('add_library', 'MODULE', 'LIBRARY'), | 227 'loadable_module': CMakeTargetType('add_library', 'MODULE', 'LIBRARY'), |
| 231 'none': CMakeTargetType('add_custom_target', 'SOURCES', None), | 228 'none': CMakeTargetType('add_custom_target', 'SOURCES', None), |
| 232 } | 229 } |
| 233 | 230 |
| 234 | 231 |
| 235 def StringToCMakeTargetName(a): | 232 def StringToCMakeTargetName(a): |
| 236 """Converts the given string 'a' to a valid CMake target name. | 233 """Converts the given string 'a' to a valid CMake target name. |
| 237 | 234 |
| 238 All invalid characters are replaced by '_'. | 235 All invalid characters are replaced by '_'. |
| 239 Invalid for cmake: ' ', '/', '(', ')' | 236 Invalid for cmake: ' ', '/', '(', ')', '"' |
| 240 Invalid for make: ':' | 237 Invalid for make: ':' |
| 241 Invalid for unknown reasons but cause failures: '.' | 238 Invalid for unknown reasons but cause failures: '.' |
| 242 """ | 239 """ |
| 243 return a.translate(string.maketrans(' /():.', '______')) | 240 return a.translate(string.maketrans(' /():."', '_______')) |
| 244 | 241 |
| 245 | 242 |
| 246 def WriteActions(target_name, actions, extra_sources, extra_deps, | 243 def WriteActions(target_name, actions, extra_sources, extra_deps, |
| 247 path_to_gyp, output): | 244 path_to_gyp, output): |
| 248 """Write CMake for the 'actions' in the target. | 245 """Write CMake for the 'actions' in the target. |
| 249 | 246 |
| 250 Args: | 247 Args: |
| 251 target_name: the name of the CMake target being generated. | 248 target_name: the name of the CMake target being generated. |
| 252 actions: the Gyp 'actions' dict for this target. | 249 actions: the Gyp 'actions' dict for this target. |
| 253 extra_sources: [(<cmake_src>, <src>)] to append with generated source files. | 250 extra_sources: [(<cmake_src>, <src>)] to append with generated source files. |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 for copy in copies: | 478 for copy in copies: |
| 482 files = copy['files'] | 479 files = copy['files'] |
| 483 destination = copy['destination'] | 480 destination = copy['destination'] |
| 484 for src in files: | 481 for src in files: |
| 485 path = os.path.normpath(src) | 482 path = os.path.normpath(src) |
| 486 basename = os.path.split(path)[1] | 483 basename = os.path.split(path)[1] |
| 487 dst = os.path.join(destination, basename) | 484 dst = os.path.join(destination, basename) |
| 488 | 485 |
| 489 copy = file_copy if os.path.basename(src) else dir_copy | 486 copy = file_copy if os.path.basename(src) else dir_copy |
| 490 | 487 |
| 491 copy.cmake_inputs.append(NormjoinPath(path_to_gyp, src)) | 488 copy.cmake_inputs.append(NormjoinPathForceCMakeSource(path_to_gyp, src)) |
| 492 copy.cmake_outputs.append(NormjoinPathForceCMakeSource(path_to_gyp, dst)) | 489 copy.cmake_outputs.append(NormjoinPathForceCMakeSource(path_to_gyp, dst)) |
| 493 copy.gyp_inputs.append(src) | 490 copy.gyp_inputs.append(src) |
| 494 copy.gyp_outputs.append(dst) | 491 copy.gyp_outputs.append(dst) |
| 495 | 492 |
| 496 for copy in (file_copy, dir_copy): | 493 for copy in (file_copy, dir_copy): |
| 497 if copy.cmake_inputs: | 494 if copy.cmake_inputs: |
| 498 copy.inputs_name = copy_name + '__input' + copy.ext | 495 copy.inputs_name = copy_name + '__input' + copy.ext |
| 499 SetVariableList(output, copy.inputs_name, copy.cmake_inputs) | 496 SetVariableList(output, copy.inputs_name, copy.cmake_inputs) |
| 500 | 497 |
| 501 copy.outputs_name = copy_name + '__output' + copy.ext | 498 copy.outputs_name = copy_name + '__output' + copy.ext |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 | 630 |
| 634 path_from_cmakelists_to_gyp = build_to_gyp | 631 path_from_cmakelists_to_gyp = build_to_gyp |
| 635 | 632 |
| 636 spec = target_dicts.get(qualified_target, {}) | 633 spec = target_dicts.get(qualified_target, {}) |
| 637 config = spec.get('configurations', {}).get(config_to_use, {}) | 634 config = spec.get('configurations', {}).get(config_to_use, {}) |
| 638 | 635 |
| 639 target_name = spec.get('target_name', '<missing target name>') | 636 target_name = spec.get('target_name', '<missing target name>') |
| 640 target_type = spec.get('type', '<missing target type>') | 637 target_type = spec.get('type', '<missing target type>') |
| 641 target_toolset = spec.get('toolset') | 638 target_toolset = spec.get('toolset') |
| 642 | 639 |
| 640 cmake_target_type = cmake_target_type_from_gyp_target_type.get(target_type) |
| 641 if cmake_target_type is None: |
| 642 print ('Target %s has unknown target type %s, skipping.' % |
| 643 ( target_name, target_type ) ) |
| 644 return |
| 645 |
| 643 SetVariable(output, 'TARGET', target_name) | 646 SetVariable(output, 'TARGET', target_name) |
| 644 SetVariable(output, 'TOOLSET', target_toolset) | 647 SetVariable(output, 'TOOLSET', target_toolset) |
| 645 | 648 |
| 646 cmake_target_name = namer.CreateCMakeTargetName(qualified_target) | 649 cmake_target_name = namer.CreateCMakeTargetName(qualified_target) |
| 647 | 650 |
| 648 extra_sources = [] | 651 extra_sources = [] |
| 649 extra_deps = [] | 652 extra_deps = [] |
| 650 | 653 |
| 651 # Actions must come first, since they can generate more OBJs for use below. | 654 # Actions must come first, since they can generate more OBJs for use below. |
| 652 if 'actions' in spec: | 655 if 'actions' in spec: |
| 653 WriteActions(cmake_target_name, spec['actions'], extra_sources, extra_deps, | 656 WriteActions(cmake_target_name, spec['actions'], extra_sources, extra_deps, |
| 654 path_from_cmakelists_to_gyp, output) | 657 path_from_cmakelists_to_gyp, output) |
| 655 | 658 |
| 656 # Rules must be early like actions. | 659 # Rules must be early like actions. |
| 657 if 'rules' in spec: | 660 if 'rules' in spec: |
| 658 WriteRules(cmake_target_name, spec['rules'], extra_sources, extra_deps, | 661 WriteRules(cmake_target_name, spec['rules'], extra_sources, extra_deps, |
| 659 path_from_cmakelists_to_gyp, output) | 662 path_from_cmakelists_to_gyp, output) |
| 660 | 663 |
| 661 # Copies | 664 # Copies |
| 662 if 'copies' in spec: | 665 if 'copies' in spec: |
| 663 WriteCopies(cmake_target_name, spec['copies'], extra_deps, | 666 WriteCopies(cmake_target_name, spec['copies'], extra_deps, |
| 664 path_from_cmakelists_to_gyp, output) | 667 path_from_cmakelists_to_gyp, output) |
| 665 | 668 |
| 666 # Target and sources | 669 # Target and sources |
| 667 srcs = spec.get('sources', []) | 670 srcs = spec.get('sources', []) |
| 668 | 671 |
| 669 # Gyp separates the sheep from the goats based on file extensions. | 672 # Gyp separates the sheep from the goats based on file extensions. |
| 670 def partition(l, p): | 673 # A full separation is done here because of flag handing (see below). |
| 671 return reduce(lambda x, e: x[not p(e)].append(e) or x, l, ([], [])) | 674 s_sources = [] |
| 672 compilable_srcs, other_srcs = partition(srcs, Compilable) | 675 c_sources = [] |
| 676 cxx_sources = [] |
| 677 linkable_sources = [] |
| 678 other_sources = [] |
| 679 for src in srcs: |
| 680 _, ext = os.path.splitext(src) |
| 681 src_type = COMPILABLE_EXTENSIONS.get(ext, None) |
| 682 src_norm_path = NormjoinPath(path_from_cmakelists_to_gyp, src); |
| 683 |
| 684 if src_type == 's': |
| 685 s_sources.append(src_norm_path) |
| 686 elif src_type == 'cc': |
| 687 c_sources.append(src_norm_path) |
| 688 elif src_type == 'cxx': |
| 689 cxx_sources.append(src_norm_path) |
| 690 elif Linkable(ext): |
| 691 linkable_sources.append(src_norm_path) |
| 692 else: |
| 693 other_sources.append(src_norm_path) |
| 694 |
| 695 for extra_source in extra_sources: |
| 696 src, real_source = extra_source |
| 697 _, ext = os.path.splitext(real_source) |
| 698 src_type = COMPILABLE_EXTENSIONS.get(ext, None) |
| 699 |
| 700 if src_type == 's': |
| 701 s_sources.append(src) |
| 702 elif src_type == 'cc': |
| 703 c_sources.append(src) |
| 704 elif src_type == 'cxx': |
| 705 cxx_sources.append(src) |
| 706 elif Linkable(ext): |
| 707 linkable_sources.append(src) |
| 708 else: |
| 709 other_sources.append(src) |
| 710 |
| 711 s_sources_name = None |
| 712 if s_sources: |
| 713 s_sources_name = cmake_target_name + '__asm_srcs' |
| 714 SetVariableList(output, s_sources_name, s_sources) |
| 715 |
| 716 c_sources_name = None |
| 717 if c_sources: |
| 718 c_sources_name = cmake_target_name + '__c_srcs' |
| 719 SetVariableList(output, c_sources_name, c_sources) |
| 720 |
| 721 cxx_sources_name = None |
| 722 if cxx_sources: |
| 723 cxx_sources_name = cmake_target_name + '__cxx_srcs' |
| 724 SetVariableList(output, cxx_sources_name, cxx_sources) |
| 725 |
| 726 linkable_sources_name = None |
| 727 if linkable_sources: |
| 728 linkable_sources_name = cmake_target_name + '__linkable_srcs' |
| 729 SetVariableList(output, linkable_sources_name, linkable_sources) |
| 730 |
| 731 other_sources_name = None |
| 732 if other_sources: |
| 733 other_sources_name = cmake_target_name + '__other_srcs' |
| 734 SetVariableList(output, other_sources_name, other_sources) |
| 673 | 735 |
| 674 # CMake gets upset when executable targets provide no sources. | 736 # CMake gets upset when executable targets provide no sources. |
| 675 if target_type == 'executable' and not compilable_srcs and not extra_sources: | 737 # http://www.cmake.org/pipermail/cmake/2010-July/038461.html |
| 676 print ('Executable %s has no complilable sources, treating as "none".' % | 738 dummy_sources_name = None |
| 677 target_name ) | 739 has_sources = (s_sources_name or |
| 678 target_type = 'none' | 740 c_sources_name or |
| 741 cxx_sources_name or |
| 742 linkable_sources_name or |
| 743 other_sources_name) |
| 744 if target_type == 'executable' and not has_sources: |
| 745 dummy_sources_name = cmake_target_name + '__dummy_srcs' |
| 746 SetVariable(output, dummy_sources_name, |
| 747 "${obj}.${TOOLSET}/${TARGET}/genc/dummy.c") |
| 748 output.write('if(NOT EXISTS "') |
| 749 WriteVariable(output, dummy_sources_name) |
| 750 output.write('")\n') |
| 751 output.write(' file(WRITE "') |
| 752 WriteVariable(output, dummy_sources_name) |
| 753 output.write('" "")\n') |
| 754 output.write("endif()\n") |
| 679 | 755 |
| 680 cmake_target_type = cmake_target_type_from_gyp_target_type.get(target_type) | |
| 681 if cmake_target_type is None: | |
| 682 print ('Target %s has unknown target type %s, skipping.' % | |
| 683 ( target_name, target_type ) ) | |
| 684 return | |
| 685 | |
| 686 other_srcs_name = None | |
| 687 if other_srcs: | |
| 688 other_srcs_name = cmake_target_name + '__other_srcs' | |
| 689 SetVariableList(output, other_srcs_name, | |
| 690 [NormjoinPath(path_from_cmakelists_to_gyp, src) for src in other_srcs]) | |
| 691 | 756 |
| 692 # CMake is opposed to setting linker directories and considers the practice | 757 # CMake is opposed to setting linker directories and considers the practice |
| 693 # of setting linker directories dangerous. Instead, it favors the use of | 758 # of setting linker directories dangerous. Instead, it favors the use of |
| 694 # find_library and passing absolute paths to target_link_libraries. | 759 # find_library and passing absolute paths to target_link_libraries. |
| 695 # However, CMake does provide the command link_directories, which adds | 760 # However, CMake does provide the command link_directories, which adds |
| 696 # link directories to targets defined after it is called. | 761 # link directories to targets defined after it is called. |
| 697 # As a result, link_directories must come before the target definition. | 762 # As a result, link_directories must come before the target definition. |
| 698 # CMake unfortunately has no means of removing entries from LINK_DIRECTORIES. | 763 # CMake unfortunately has no means of removing entries from LINK_DIRECTORIES. |
| 699 library_dirs = config.get('library_dirs') | 764 library_dirs = config.get('library_dirs') |
| 700 if library_dirs is not None: | 765 if library_dirs is not None: |
| 701 output.write('link_directories(') | 766 output.write('link_directories(') |
| 702 for library_dir in library_dirs: | 767 for library_dir in library_dirs: |
| 703 output.write(' ') | 768 output.write(' ') |
| 704 output.write(NormjoinPath(path_from_cmakelists_to_gyp, library_dir)) | 769 output.write(NormjoinPath(path_from_cmakelists_to_gyp, library_dir)) |
| 705 output.write('\n') | 770 output.write('\n') |
| 706 output.write(')\n') | 771 output.write(')\n') |
| 707 | 772 |
| 708 output.write(cmake_target_type.command) | 773 output.write(cmake_target_type.command) |
| 709 output.write('(') | 774 output.write('(') |
| 710 output.write(cmake_target_name) | 775 output.write(cmake_target_name) |
| 711 | 776 |
| 712 if cmake_target_type.modifier is not None: | 777 if cmake_target_type.modifier is not None: |
| 713 output.write(' ') | 778 output.write(' ') |
| 714 output.write(cmake_target_type.modifier) | 779 output.write(cmake_target_type.modifier) |
| 715 | 780 |
| 716 if other_srcs_name: | 781 if s_sources_name: |
| 717 WriteVariable(output, other_srcs_name, ' ') | 782 WriteVariable(output, s_sources_name, ' ') |
| 718 | 783 if c_sources_name: |
| 719 output.write('\n') | 784 WriteVariable(output, c_sources_name, ' ') |
| 720 | 785 if cxx_sources_name: |
| 721 for src in compilable_srcs: | 786 WriteVariable(output, cxx_sources_name, ' ') |
| 722 output.write(' ') | 787 if linkable_sources_name: |
| 723 output.write(NormjoinPath(path_from_cmakelists_to_gyp, src)) | 788 WriteVariable(output, linkable_sources_name, ' ') |
| 724 output.write('\n') | 789 if other_sources_name: |
| 725 for extra_source in extra_sources: | 790 WriteVariable(output, other_sources_name, ' ') |
| 726 output.write(' ') | 791 if dummy_sources_name: |
| 727 src, _ = extra_source | 792 WriteVariable(output, dummy_sources_name, ' ') |
| 728 output.write(NormjoinPath(path_from_cmakelists_to_gyp, src)) | |
| 729 output.write('\n') | |
| 730 | 793 |
| 731 output.write(')\n') | 794 output.write(')\n') |
| 732 | 795 |
| 796 # Let CMake know if the 'all' target should depend on this target. |
| 797 exclude_from_all = ('TRUE' if qualified_target not in all_qualified_targets |
| 798 else 'FALSE') |
| 799 SetTargetProperty(output, cmake_target_name, |
| 800 'EXCLUDE_FROM_ALL', exclude_from_all) |
| 801 for extra_target_name in extra_deps: |
| 802 SetTargetProperty(output, extra_target_name, |
| 803 'EXCLUDE_FROM_ALL', exclude_from_all) |
| 804 |
| 733 # Output name and location. | 805 # Output name and location. |
| 734 if target_type != 'none': | 806 if target_type != 'none': |
| 807 # Link as 'C' if there are no other files |
| 808 if not c_sources and not cxx_sources: |
| 809 SetTargetProperty(output, cmake_target_name, 'LINKER_LANGUAGE', ['C']) |
| 810 |
| 735 # Mark uncompiled sources as uncompiled. | 811 # Mark uncompiled sources as uncompiled. |
| 736 if other_srcs_name: | 812 if other_sources_name: |
| 737 output.write('set_source_files_properties(') | 813 output.write('set_source_files_properties(') |
| 738 WriteVariable(output, other_srcs_name, '') | 814 WriteVariable(output, other_sources_name, '') |
| 739 output.write(' PROPERTIES HEADER_FILE_ONLY "TRUE")\n') | 815 output.write(' PROPERTIES HEADER_FILE_ONLY "TRUE")\n') |
| 740 | 816 |
| 817 # Mark object sources as linkable. |
| 818 if linkable_sources_name: |
| 819 output.write('set_source_files_properties(') |
| 820 WriteVariable(output, other_sources_name, '') |
| 821 output.write(' PROPERTIES EXTERNAL_OBJECT "TRUE")\n') |
| 822 |
| 741 # Output directory | 823 # Output directory |
| 742 target_output_directory = spec.get('product_dir') | 824 target_output_directory = spec.get('product_dir') |
| 743 if target_output_directory is None: | 825 if target_output_directory is None: |
| 744 if target_type in ('executable', 'loadable_module'): | 826 if target_type in ('executable', 'loadable_module'): |
| 745 target_output_directory = generator_default_variables['PRODUCT_DIR'] | 827 target_output_directory = generator_default_variables['PRODUCT_DIR'] |
| 746 elif target_type == 'shared_library': | 828 elif target_type == 'shared_library': |
| 747 target_output_directory = '${builddir}/lib.${TOOLSET}' | 829 target_output_directory = '${builddir}/lib.${TOOLSET}' |
| 748 elif spec.get('standalone_static_library', False): | 830 elif spec.get('standalone_static_library', False): |
| 749 target_output_directory = generator_default_variables['PRODUCT_DIR'] | 831 target_output_directory = generator_default_variables['PRODUCT_DIR'] |
| 750 else: | 832 else: |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 cmake_target_type.property_modifier + '_OUTPUT_NAME', | 879 cmake_target_type.property_modifier + '_OUTPUT_NAME', |
| 798 product_name) | 880 product_name) |
| 799 SetTargetProperty(output, cmake_target_name, 'SUFFIX', product_ext) | 881 SetTargetProperty(output, cmake_target_name, 'SUFFIX', product_ext) |
| 800 | 882 |
| 801 # Make the output of this target referenceable as a source. | 883 # Make the output of this target referenceable as a source. |
| 802 cmake_target_output_basename = product_prefix + product_name + product_ext | 884 cmake_target_output_basename = product_prefix + product_name + product_ext |
| 803 cmake_target_output = os.path.join(cmake_target_output_directory, | 885 cmake_target_output = os.path.join(cmake_target_output_directory, |
| 804 cmake_target_output_basename) | 886 cmake_target_output_basename) |
| 805 SetFileProperty(output, cmake_target_output, 'GENERATED', ['TRUE'], '') | 887 SetFileProperty(output, cmake_target_output, 'GENERATED', ['TRUE'], '') |
| 806 | 888 |
| 807 # Let CMake know if the 'all' target should depend on this target. | 889 # Includes |
| 808 exclude_from_all = ('TRUE' if qualified_target not in all_qualified_targets | 890 includes = config.get('include_dirs') |
| 809 else 'FALSE') | 891 if includes: |
| 810 SetTargetProperty(output, cmake_target_name, | 892 # This (target include directories) is what requires CMake 2.8.8 |
| 811 'EXCLUDE_FROM_ALL', exclude_from_all) | 893 includes_name = cmake_target_name + '__include_dirs' |
| 812 for extra_target_name in extra_deps: | 894 SetVariableList(output, includes_name, |
| 813 SetTargetProperty(output, extra_target_name, | 895 [NormjoinPathForceCMakeSource(path_from_cmakelists_to_gyp, include) |
| 814 'EXCLUDE_FROM_ALL', exclude_from_all) | 896 for include in includes]) |
| 897 output.write('set_property(TARGET ') |
| 898 output.write(cmake_target_name) |
| 899 output.write(' APPEND PROPERTY INCLUDE_DIRECTORIES ') |
| 900 WriteVariable(output, includes_name, '') |
| 901 output.write(')\n') |
| 815 | 902 |
| 816 # Includes | 903 # Defines |
| 817 includes = config.get('include_dirs') | 904 defines = config.get('defines') |
| 818 if includes: | 905 if defines is not None: |
| 819 # This (target include directories) is what requires CMake 2.8.8 | 906 SetTargetProperty(output, |
| 820 includes_name = cmake_target_name + '__include_dirs' | 907 cmake_target_name, |
| 821 SetVariableList(output, includes_name, | 908 'COMPILE_DEFINITIONS', |
| 822 [NormjoinPathForceCMakeSource(path_from_cmakelists_to_gyp, include) | 909 defines, |
| 823 for include in includes]) | 910 ';') |
| 824 output.write('set_property(TARGET ') | |
| 825 output.write(cmake_target_name) | |
| 826 output.write(' APPEND PROPERTY INCLUDE_DIRECTORIES ') | |
| 827 WriteVariable(output, includes_name, '') | |
| 828 output.write(')\n') | |
| 829 | 911 |
| 830 # Defines | 912 # Compile Flags - http://www.cmake.org/Bug/view.php?id=6493 |
| 831 defines = config.get('defines') | 913 # CMake currently does not have target C and CXX flags. |
| 832 if defines is not None: | 914 # So, instead of doing... |
| 833 SetTargetProperty(output, | |
| 834 cmake_target_name, | |
| 835 'COMPILE_DEFINITIONS', | |
| 836 defines, | |
| 837 ';') | |
| 838 | 915 |
| 839 # Compile Flags - http://www.cmake.org/Bug/view.php?id=6493 | 916 # cflags_c = config.get('cflags_c') |
| 840 # CMake currently does not have target C and CXX flags. | 917 # if cflags_c is not None: |
| 841 # So, instead of doing... | 918 # SetTargetProperty(output, cmake_target_name, |
| 919 # 'C_COMPILE_FLAGS', cflags_c, ' ') |
| 842 | 920 |
| 843 # cflags_c = config.get('cflags_c') | 921 # cflags_cc = config.get('cflags_cc') |
| 844 # if cflags_c is not None: | 922 # if cflags_cc is not None: |
| 845 # SetTargetProperty(output, cmake_target_name, | 923 # SetTargetProperty(output, cmake_target_name, |
| 846 # 'C_COMPILE_FLAGS', cflags_c, ' ') | 924 # 'CXX_COMPILE_FLAGS', cflags_cc, ' ') |
| 847 | 925 |
| 848 # cflags_cc = config.get('cflags_cc') | 926 # Instead we must... |
| 849 # if cflags_cc is not None: | 927 cflags = config.get('cflags', []) |
| 850 # SetTargetProperty(output, cmake_target_name, | 928 cflags_c = config.get('cflags_c', []) |
| 851 # 'CXX_COMPILE_FLAGS', cflags_cc, ' ') | 929 cflags_cxx = config.get('cflags_cc', []) |
| 930 if (not cflags_c or not c_sources) and (not cflags_cxx or not cxx_sources): |
| 931 SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', cflags, ' ') |
| 852 | 932 |
| 853 # Instead we must... | 933 elif c_sources and not (s_sources or cxx_sources): |
| 854 s_sources = [] | |
| 855 c_sources = [] | |
| 856 cxx_sources = [] | |
| 857 for src in srcs: | |
| 858 _, ext = os.path.splitext(src) | |
| 859 src_type = COMPILABLE_EXTENSIONS.get(ext, None) | |
| 860 | |
| 861 if src_type == 's': | |
| 862 s_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) | |
| 863 | |
| 864 if src_type == 'cc': | |
| 865 c_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) | |
| 866 | |
| 867 if src_type == 'cxx': | |
| 868 cxx_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) | |
| 869 | |
| 870 for extra_source in extra_sources: | |
| 871 src, real_source = extra_source | |
| 872 _, ext = os.path.splitext(real_source) | |
| 873 src_type = COMPILABLE_EXTENSIONS.get(ext, None) | |
| 874 | |
| 875 if src_type == 's': | |
| 876 s_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) | |
| 877 | |
| 878 if src_type == 'cc': | |
| 879 c_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) | |
| 880 | |
| 881 if src_type == 'cxx': | |
| 882 cxx_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) | |
| 883 | |
| 884 cflags = config.get('cflags', []) | |
| 885 cflags_c = config.get('cflags_c', []) | |
| 886 cflags_cxx = config.get('cflags_cc', []) | |
| 887 if c_sources and not (s_sources or cxx_sources): | |
| 888 flags = [] | |
| 889 flags.extend(cflags) | |
| 890 flags.extend(cflags_c) | |
| 891 SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', flags, ' ') | |
| 892 | |
| 893 elif cxx_sources and not (s_sources or c_sources): | |
| 894 flags = [] | |
| 895 flags.extend(cflags) | |
| 896 flags.extend(cflags_cxx) | |
| 897 SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', flags, ' ') | |
| 898 | |
| 899 else: | |
| 900 if s_sources and cflags: | |
| 901 SetFilesProperty(output, s_sources, 'COMPILE_FLAGS', cflags, ' ') | |
| 902 | |
| 903 if c_sources and (cflags or cflags_c): | |
| 904 flags = [] | 934 flags = [] |
| 905 flags.extend(cflags) | 935 flags.extend(cflags) |
| 906 flags.extend(cflags_c) | 936 flags.extend(cflags_c) |
| 907 SetFilesProperty(output, c_sources, 'COMPILE_FLAGS', flags, ' ') | 937 SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', flags, ' ') |
| 908 | 938 |
| 909 if cxx_sources and (cflags or cflags_cxx): | 939 elif cxx_sources and not (s_sources or c_sources): |
| 910 flags = [] | 940 flags = [] |
| 911 flags.extend(cflags) | 941 flags.extend(cflags) |
| 912 flags.extend(cflags_cxx) | 942 flags.extend(cflags_cxx) |
| 913 SetFilesProperty(output, cxx_sources, 'COMPILE_FLAGS', flags, ' ') | 943 SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', flags, ' ') |
| 914 | 944 |
| 915 # Have assembly link as c if there are no other files | 945 else: |
| 916 if not c_sources and not cxx_sources and s_sources: | 946 # TODO: This is broken, one cannot generally set properties on files, |
| 917 SetTargetProperty(output, cmake_target_name, 'LINKER_LANGUAGE', ['C']) | 947 # as other targets may require different properties on the same files. |
| 948 if s_sources and cflags: |
| 949 SetFilesProperty(output, s_sources_name, 'COMPILE_FLAGS', cflags, ' ') |
| 918 | 950 |
| 919 # Linker flags | 951 if c_sources and (cflags or cflags_c): |
| 920 ldflags = config.get('ldflags') | 952 flags = [] |
| 921 if ldflags is not None: | 953 flags.extend(cflags) |
| 922 SetTargetProperty(output, cmake_target_name, 'LINK_FLAGS', ldflags, ' ') | 954 flags.extend(cflags_c) |
| 955 SetFilesProperty(output, c_sources_name, 'COMPILE_FLAGS', flags, ' ') |
| 956 |
| 957 if cxx_sources and (cflags or cflags_cxx): |
| 958 flags = [] |
| 959 flags.extend(cflags) |
| 960 flags.extend(cflags_cxx) |
| 961 SetFilesProperty(output, cxx_sources_name, 'COMPILE_FLAGS', flags, ' ') |
| 962 |
| 963 # Linker flags |
| 964 ldflags = config.get('ldflags') |
| 965 if ldflags is not None: |
| 966 SetTargetProperty(output, cmake_target_name, 'LINK_FLAGS', ldflags, ' ') |
| 923 | 967 |
| 924 # Note on Dependencies and Libraries: | 968 # Note on Dependencies and Libraries: |
| 925 # CMake wants to handle link order, resolving the link line up front. | 969 # CMake wants to handle link order, resolving the link line up front. |
| 926 # Gyp does not retain or enforce specifying enough information to do so. | 970 # Gyp does not retain or enforce specifying enough information to do so. |
| 927 # So do as other gyp generators and use --start-group and --end-group. | 971 # So do as other gyp generators and use --start-group and --end-group. |
| 928 # Give CMake as little information as possible so that it doesn't mess it up. | 972 # Give CMake as little information as possible so that it doesn't mess it up. |
| 929 | 973 |
| 930 # Dependencies | 974 # Dependencies |
| 931 rawDeps = spec.get('dependencies', []) | 975 rawDeps = spec.get('dependencies', []) |
| 932 | 976 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 | 1077 |
| 1034 toplevel_build = os.path.join(options.toplevel_dir, build_dir) | 1078 toplevel_build = os.path.join(options.toplevel_dir, build_dir) |
| 1035 | 1079 |
| 1036 output_file = os.path.join(toplevel_build, 'CMakeLists.txt') | 1080 output_file = os.path.join(toplevel_build, 'CMakeLists.txt') |
| 1037 gyp.common.EnsureDirExists(output_file) | 1081 gyp.common.EnsureDirExists(output_file) |
| 1038 | 1082 |
| 1039 output = open(output_file, 'w') | 1083 output = open(output_file, 'w') |
| 1040 output.write('cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR)\n') | 1084 output.write('cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR)\n') |
| 1041 output.write('cmake_policy(VERSION 2.8.8)\n') | 1085 output.write('cmake_policy(VERSION 2.8.8)\n') |
| 1042 | 1086 |
| 1043 _, project_target, _ = gyp.common.ParseQualifiedTarget(target_list[-1]) | 1087 gyp_file, project_target, _ = gyp.common.ParseQualifiedTarget(target_list[-1]) |
| 1044 output.write('project(') | 1088 output.write('project(') |
| 1045 output.write(project_target) | 1089 output.write(project_target) |
| 1046 output.write(')\n') | 1090 output.write(')\n') |
| 1047 | 1091 |
| 1048 SetVariable(output, 'configuration', config_to_use) | 1092 SetVariable(output, 'configuration', config_to_use) |
| 1049 | 1093 |
| 1094 ar = None |
| 1095 cc = None |
| 1096 cxx = None |
| 1097 |
| 1098 make_global_settings = data[gyp_file].get('make_global_settings', []) |
| 1099 build_to_top = gyp.common.InvertRelativePath(build_dir, |
| 1100 options.toplevel_dir) |
| 1101 for key, value in make_global_settings: |
| 1102 if key == 'AR': |
| 1103 ar = os.path.join(build_to_top, value) |
| 1104 if key == 'CC': |
| 1105 cc = os.path.join(build_to_top, value) |
| 1106 if key == 'CXX': |
| 1107 cxx = os.path.join(build_to_top, value) |
| 1108 |
| 1109 ar = gyp.common.GetEnvironFallback(['AR_target', 'AR'], ar) |
| 1110 cc = gyp.common.GetEnvironFallback(['CC_target', 'CC'], cc) |
| 1111 cxx = gyp.common.GetEnvironFallback(['CXX_target', 'CXX'], cxx) |
| 1112 |
| 1113 if ar: |
| 1114 SetVariable(output, 'CMAKE_AR', ar) |
| 1115 if cc: |
| 1116 SetVariable(output, 'CMAKE_C_COMPILER', cc) |
| 1117 if cxx: |
| 1118 SetVariable(output, 'CMAKE_CXX_COMPILER', cxx) |
| 1119 |
| 1050 # The following appears to be as-yet undocumented. | 1120 # The following appears to be as-yet undocumented. |
| 1051 # http://public.kitware.com/Bug/view.php?id=8392 | 1121 # http://public.kitware.com/Bug/view.php?id=8392 |
| 1052 output.write('enable_language(ASM)\n') | 1122 output.write('enable_language(ASM)\n') |
| 1053 # ASM-ATT does not support .S files. | 1123 # ASM-ATT does not support .S files. |
| 1054 # output.write('enable_language(ASM-ATT)\n') | 1124 # output.write('enable_language(ASM-ATT)\n') |
| 1055 | 1125 |
| 1126 if cc: |
| 1127 SetVariable(output, 'CMAKE_ASM_COMPILER', cc) |
| 1128 |
| 1056 SetVariable(output, 'builddir', '${CMAKE_BINARY_DIR}') | 1129 SetVariable(output, 'builddir', '${CMAKE_BINARY_DIR}') |
| 1057 SetVariable(output, 'obj', '${builddir}/obj') | 1130 SetVariable(output, 'obj', '${builddir}/obj') |
| 1058 output.write('\n') | 1131 output.write('\n') |
| 1059 | 1132 |
| 1060 # TODO: Undocumented/unsupported (the CMake Java generator depends on it). | 1133 # TODO: Undocumented/unsupported (the CMake Java generator depends on it). |
| 1061 # CMake by default names the object resulting from foo.c to be foo.c.o. | 1134 # CMake by default names the object resulting from foo.c to be foo.c.o. |
| 1062 # Gyp traditionally names the object resulting from foo.c foo.o. | 1135 # Gyp traditionally names the object resulting from foo.c foo.o. |
| 1063 # This should be irrelevant, but some targets extract .o files from .a | 1136 # This should be irrelevant, but some targets extract .o files from .a |
| 1064 # and depend on the name of the extracted .o files. | 1137 # and depend on the name of the extracted .o files. |
| 1065 output.write('set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1)\n') | 1138 output.write('set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1)\n') |
| 1066 output.write('set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)\n') | 1139 output.write('set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)\n') |
| 1067 output.write('\n') | 1140 output.write('\n') |
| 1068 | 1141 |
| 1142 # Force ninja to use rsp files. Otherwise link and ar lines can get too long, |
| 1143 # resulting in 'Argument list too long' errors. |
| 1144 output.write('set(CMAKE_NINJA_FORCE_RESPONSE_FILE 1)\n') |
| 1145 output.write('\n') |
| 1146 |
| 1069 namer = CMakeNamer(target_list) | 1147 namer = CMakeNamer(target_list) |
| 1070 | 1148 |
| 1071 # The list of targets upon which the 'all' target should depend. | 1149 # The list of targets upon which the 'all' target should depend. |
| 1072 # CMake has it's own implicit 'all' target, one is not created explicitly. | 1150 # CMake has it's own implicit 'all' target, one is not created explicitly. |
| 1073 all_qualified_targets = set() | 1151 all_qualified_targets = set() |
| 1074 for build_file in params['build_files']: | 1152 for build_file in params['build_files']: |
| 1075 for qualified_target in gyp.common.AllTargets(target_list, | 1153 for qualified_target in gyp.common.AllTargets(target_list, |
| 1076 target_dicts, | 1154 target_dicts, |
| 1077 os.path.normpath(build_file)): | 1155 os.path.normpath(build_file)): |
| 1078 all_qualified_targets.add(qualified_target) | 1156 all_qualified_targets.add(qualified_target) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1134 arglists.append((target_list, target_dicts, data, | 1212 arglists.append((target_list, target_dicts, data, |
| 1135 params, config_name)) | 1213 params, config_name)) |
| 1136 pool.map(CallGenerateOutputForConfig, arglists) | 1214 pool.map(CallGenerateOutputForConfig, arglists) |
| 1137 except KeyboardInterrupt, e: | 1215 except KeyboardInterrupt, e: |
| 1138 pool.terminate() | 1216 pool.terminate() |
| 1139 raise e | 1217 raise e |
| 1140 else: | 1218 else: |
| 1141 for config_name in config_names: | 1219 for config_name in config_names: |
| 1142 GenerateOutputForConfig(target_list, target_dicts, data, | 1220 GenerateOutputForConfig(target_list, target_dicts, data, |
| 1143 params, config_name) | 1221 params, config_name) |
| OLD | NEW |