| 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) | 
|---|