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 |