| 1 | # | 
|---|
| 2 | #             ORXONOX - the hottest 3D action shooter ever to exist | 
|---|
| 3 | #                             > www.orxonox.net < | 
|---|
| 4 | # | 
|---|
| 5 | #        This program is free software; you can redistribute it and/or | 
|---|
| 6 | #         modify it under the terms of the GNU General Public License | 
|---|
| 7 | #        as published by the Free Software Foundation; either version 2 | 
|---|
| 8 | #            of the License, or (at your option) any later version. | 
|---|
| 9 | # | 
|---|
| 10 | #       This program is distributed in the hope that it will be useful, | 
|---|
| 11 | #        but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 12 | #        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
| 13 | #                 GNU General Public License for more details. | 
|---|
| 14 | # | 
|---|
| 15 | #   You should have received a copy of the GNU General Public License along | 
|---|
| 16 | #      with this program; if not, write to the Free Software Foundation, | 
|---|
| 17 | #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. | 
|---|
| 18 | # | 
|---|
| 19 | # | 
|---|
| 20 | #  Author: | 
|---|
| 21 | #    Reto Grieder | 
|---|
| 22 | # | 
|---|
| 23 |  | 
|---|
| 24 | FUNCTION(GENERATE_BUILD_UNITS _target_name _all_files_var) | 
|---|
| 25 | SET(_source_files) | 
|---|
| 26 | SET(_total_file_count 0) | 
|---|
| 27 |  | 
|---|
| 28 | # Count the number of actual C++ source files | 
|---|
| 29 | FOREACH(_file ${${_all_files_var}}) | 
|---|
| 30 | # Only look at C++ source files | 
|---|
| 31 | IF(_file MATCHES "\\.(cpp|cc|cxx)$") | 
|---|
| 32 | # Some files might be marked as not to compile at all | 
|---|
| 33 | GET_SOURCE_FILE_PROPERTY(_skip1 ${_file} HEADER_FILE_ONLY) | 
|---|
| 34 | GET_SOURCE_FILE_PROPERTY(_skip2 ${_file} EXCLUDE_FROM_BUILD_UNITS) | 
|---|
| 35 | IF(NOT _skip1 AND NOT _skip2) | 
|---|
| 36 | GET_SOURCE_FILE_PROPERTY(_size ${_file} BUILD_UNIT_SIZE) | 
|---|
| 37 | IF(NOT _size) | 
|---|
| 38 | SET(_size 1) | 
|---|
| 39 | ENDIF() | 
|---|
| 40 | # Append file AND size to the list (like storing an std::pair) | 
|---|
| 41 | LIST(APPEND _source_files ${_file} ${_size}) | 
|---|
| 42 | MATH(EXPR _total_file_count "${_total_file_count} + ${_size}") | 
|---|
| 43 | # Don't compile | 
|---|
| 44 | SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES HEADER_FILE_ONLY TRUE) | 
|---|
| 45 | ENDIF() | 
|---|
| 46 | ENDIF() | 
|---|
| 47 | ENDFOREACH(_file) | 
|---|
| 48 |  | 
|---|
| 49 | # Get number of build units we have to make. The default is NR_OF_BUILD_UNITS | 
|---|
| 50 | # However we can specify different values in a config file | 
|---|
| 51 | SET(_config ${BUILD_UNITS_CONFIG_${NR_OF_BUILD_UNITS}_THREADS}) | 
|---|
| 52 | SET(_nr_of_units) | 
|---|
| 53 | IF(_config) | 
|---|
| 54 | LIST(FIND _config ${_target_name} _index) | 
|---|
| 55 | IF(NOT _index EQUAL -1) | 
|---|
| 56 | # Nr of build units is the next element in the list (we assume it exists) | 
|---|
| 57 | MATH(EXPR _index "${_index} + 1") | 
|---|
| 58 | LIST(GET _config ${_index} _nr_of_units) | 
|---|
| 59 | ENDIF() | 
|---|
| 60 | ENDIF() | 
|---|
| 61 | IF(NOT _nr_of_units) | 
|---|
| 62 | # Use default as specified (e.g. "full4" --> 4) or 1 for externals | 
|---|
| 63 | IF(_arg_ORXONOX_EXTERNAL) | 
|---|
| 64 | SET(_nr_of_units 1) | 
|---|
| 65 | ELSE() | 
|---|
| 66 | SET(_nr_of_units ${NR_OF_BUILD_UNITS}) | 
|---|
| 67 | ENDIF() | 
|---|
| 68 | ENDIF() | 
|---|
| 69 |  | 
|---|
| 70 | # Disable precompiled header files for targets with two or less build units | 
|---|
| 71 | IF(_nr_of_units LESS 3) | 
|---|
| 72 | SET(PCH_DISABLE_${_target_name} TRUE PARENT_SCOPE) | 
|---|
| 73 | ENDIF() | 
|---|
| 74 |  | 
|---|
| 75 | SET(_remaining_files ${_total_file_count}) | 
|---|
| 76 | SET(_remaining_units ${_nr_of_units}) | 
|---|
| 77 | SET(_unit_nr 1) | 
|---|
| 78 | # Loop counts back from ${_nr_of_units} to 1 | 
|---|
| 79 | FOREACH(_remaining_units RANGE ${_nr_of_units} 1 -1) | 
|---|
| 80 | # Use integer division to get the current build unit size | 
|---|
| 81 | MATH(EXPR _aimed_size "${_remaining_files} / ${_remaining_units}") | 
|---|
| 82 |  | 
|---|
| 83 | SET(_current_size 0) | 
|---|
| 84 | SET(_current_unit) | 
|---|
| 85 |  | 
|---|
| 86 | SET(_file_index 0) | 
|---|
| 87 | LIST(LENGTH _source_files _list_size) | 
|---|
| 88 | WHILE(${_file_index} LESS ${_list_size} AND NOT ${_current_size} EQUAL ${_aimed_size}) | 
|---|
| 89 | # _source_files stores pairs of values (file followed by its size) | 
|---|
| 90 | MATH(EXPR _size_index "${_file_index} + 1") | 
|---|
| 91 | LIST(GET _source_files ${_file_index} _file) | 
|---|
| 92 | LIST(GET _source_files ${_size_index} _size) | 
|---|
| 93 |  | 
|---|
| 94 | MATH(EXPR _new_size "${_current_size} + ${_size}") | 
|---|
| 95 | IF(${_new_size} GREATER ${_aimed_size}) | 
|---|
| 96 | # Try next file in list (jump 2 because pairs are stored) | 
|---|
| 97 | MATH(EXPR _file_index "${_file_index} + 2") | 
|---|
| 98 | ELSE() | 
|---|
| 99 | SET(_current_size ${_new_size}) | 
|---|
| 100 | LIST(APPEND _current_unit ${_file}) | 
|---|
| 101 | # Remove from _source_files list | 
|---|
| 102 | LIST(REMOVE_AT _source_files ${_file_index} ${_size_index}) | 
|---|
| 103 | MATH(EXPR _list_size "${_list_size} - 2") | 
|---|
| 104 | ENDIF() | 
|---|
| 105 | ENDWHILE() | 
|---|
| 106 |  | 
|---|
| 107 | # Finalise | 
|---|
| 108 | LIST(LENGTH _current_unit _nr_of_included_files) | 
|---|
| 109 | IF(_nr_of_included_files EQUAL 1) | 
|---|
| 110 | # If unit consists of one file, we can compile it the old fashioned way | 
|---|
| 111 | SET_SOURCE_FILES_PROPERTIES(${_current_unit} PROPERTIES HEADER_FILE_ONLY FALSE) | 
|---|
| 112 | ELSEIF(_nr_of_included_files GREATER 1) | 
|---|
| 113 | # Assemble unit by writing some #include statements | 
|---|
| 114 | SET(_include_string) | 
|---|
| 115 | FOREACH(_file ${_current_unit}) | 
|---|
| 116 | SET(_include_string "${_include_string}#include \"${_file}\"\n") | 
|---|
| 117 | ENDFOREACH(_file) | 
|---|
| 118 |  | 
|---|
| 119 | # Generate the filename | 
|---|
| 120 | IF(NOT _nr_of_units EQUAL 1) | 
|---|
| 121 | SET(_suffix ${_unit_nr}) | 
|---|
| 122 | ENDIF() | 
|---|
| 123 | SET(_unit_file ${CMAKE_CURRENT_BINARY_DIR}/${_target_name}BuildUnit${_suffix}.cc) | 
|---|
| 124 | # Only write if content has changed (avoids recompile) | 
|---|
| 125 | IF(EXISTS ${_unit_file}) | 
|---|
| 126 | FILE(READ ${_unit_file} _file_include_string) | 
|---|
| 127 | ENDIF() | 
|---|
| 128 | IF(NOT _include_string STREQUAL "${_file_include_string}") | 
|---|
| 129 | FILE(WRITE ${_unit_file} "${_include_string}") | 
|---|
| 130 | ENDIF() | 
|---|
| 131 |  | 
|---|
| 132 | LIST(APPEND _build_units ${_unit_file}) | 
|---|
| 133 |  | 
|---|
| 134 | # Increase file name counter | 
|---|
| 135 | MATH(EXPR _unit_nr "${_unit_nr} + 1") | 
|---|
| 136 | ENDIF() | 
|---|
| 137 |  | 
|---|
| 138 | # Compute remaining files | 
|---|
| 139 | MATH(EXPR _remaining_files "${_remaining_files} - ${_current_size}") | 
|---|
| 140 | ENDFOREACH(_remaining_units) | 
|---|
| 141 |  | 
|---|
| 142 | # Add units to list of source files (function, not macro --> parent scope) | 
|---|
| 143 | # Do this ONCE because parent scope changes will NOT be visible here | 
|---|
| 144 | SET(${_all_files_var} ${${_all_files_var}} ${_build_units} PARENT_SCOPE) | 
|---|
| 145 |  | 
|---|
| 146 | ENDFUNCTION(GENERATE_BUILD_UNITS) | 
|---|