diff options
Diffstat (limited to 'cmake_modules/UnityBuild.cmake')
-rw-r--r-- | cmake_modules/UnityBuild.cmake | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/cmake_modules/UnityBuild.cmake b/cmake_modules/UnityBuild.cmake new file mode 100644 index 0000000..7c133f1 --- /dev/null +++ b/cmake_modules/UnityBuild.cmake @@ -0,0 +1,158 @@ +# +# Copyright (c) 2009-2012 Christoph Heindl +# Copyright (c) 2015 Csaba Kertész (csaba.kertesz@gmail.com) +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the <organization> nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +MACRO (COMMIT_UNITY_FILE UNITY_FILE FILE_CONTENT) + SET(DIRTY FALSE) + # Check if the build file exists + SET(OLD_FILE_CONTENT "") + IF (NOT EXISTS ${${UNITY_FILE}} AND NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${${UNITY_FILE}}) + SET(DIRTY TRUE) + ELSE () + # Check the file content + FILE(STRINGS ${${UNITY_FILE}} OLD_FILE_CONTENT) + STRING(REPLACE ";" "" OLD_FILE_CONTENT "${OLD_FILE_CONTENT}") + STRING(REPLACE "\n" "" NEW_CONTENT "${${FILE_CONTENT}}") + STRING(COMPARE EQUAL "${OLD_FILE_CONTENT}" "${NEW_CONTENT}" EQUAL_CHECK) + IF (NOT EQUAL_CHECK EQUAL 1) + SET(DIRTY TRUE) + ENDIF () + ENDIF () + IF (DIRTY MATCHES TRUE) + MESSAGE(STATUS "Write Unity Build file: " ${${UNITY_FILE}}) + FILE(WRITE ${${UNITY_FILE}} "${${FILE_CONTENT}}") + ENDIF () + # Create a dummy copy of the unity file to trigger CMake reconfigure if it is deleted. + SET(UNITY_FILE_PATH "") + SET(UNITY_FILE_NAME "") + GET_FILENAME_COMPONENT(UNITY_FILE_PATH ${${UNITY_FILE}} PATH) + GET_FILENAME_COMPONENT(UNITY_FILE_NAME ${${UNITY_FILE}} NAME) + CONFIGURE_FILE(${${UNITY_FILE}} ${UNITY_FILE_PATH}/CMakeFiles/${UNITY_FILE_NAME}.dummy) +ENDMACRO () + +MACRO (ENABLE_UNITY_BUILD TARGET_NAME SOURCE_VARIABLE_NAME UNIT_SIZE EXTENSION) + # Limit is zero based conversion of unit_size + MATH(EXPR LIMIT ${UNIT_SIZE}-1) + SET(FILES ${SOURCE_VARIABLE_NAME}) + # Effectivly ignore the source files from the build, but keep track them for changes. + SET_SOURCE_FILES_PROPERTIES(${${FILES}} PROPERTIES HEADER_FILE_ONLY true) + # Counts the number of source files up to the threshold + SET(COUNTER ${LIMIT}) + # Have one or more unity build files + SET(FILE_NUMBER 0) + SET(BUILD_FILE "") + SET(BUILD_FILE_CONTENT "") + SET(UNITY_BUILD_FILES "") + SET(_DEPS "") + + FOREACH (SOURCE_FILE ${${FILES}}) + IF (COUNTER EQUAL LIMIT) + SET(_DEPS "") + # Write the actual Unity Build file + IF (NOT ${BUILD_FILE} STREQUAL "" AND NOT ${BUILD_FILE_CONTENT} STREQUAL "") + COMMIT_UNITY_FILE(BUILD_FILE BUILD_FILE_CONTENT) + ENDIF () + SET(UNITY_BUILD_FILES ${UNITY_BUILD_FILES} ${BUILD_FILE}) + # Set the variables for the current Unity Build file + SET(BUILD_FILE ${CMAKE_CURRENT_BINARY_DIR}/unitybuild_${FILE_NUMBER}_${TARGET_NAME}.${EXTENSION}) + SET(BUILD_FILE_CONTENT "// Unity Build file generated by CMake\n") + MATH(EXPR FILE_NUMBER ${FILE_NUMBER}+1) + SET(COUNTER 0) + ENDIF () + # Add source path to the file name if it is not there yet. + SET(FINAL_SOURCE_FILE "") + SET(SOURCE_PATH "") + GET_FILENAME_COMPONENT(SOURCE_PATH ${SOURCE_FILE} PATH) + IF (SOURCE_PATH STREQUAL "" OR NOT EXISTS ${SOURCE_FILE}) + SET(FINAL_SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE}) + ELSE () + SET(FINAL_SOURCE_FILE ${SOURCE_FILE}) + ENDIF () + # Treat only the existing files or moc_*.cpp files + STRING(FIND ${SOURCE_FILE} "moc_" MOC_POS) + IF (EXISTS ${FINAL_SOURCE_FILE} OR MOC_POS GREATER -1) + # Add md5 hash of the source file (except moc files) to the build file content + IF (MOC_POS LESS 0) + SET(MD5_HASH "") + FILE(MD5 ${FINAL_SOURCE_FILE} MD5_HASH) + SET(BUILD_FILE_CONTENT "${BUILD_FILE_CONTENT}// md5: ${MD5_HASH}\n") + ENDIF () + # Add the source file to the build file content + IF (MOC_POS GREATER -1) + SET(BUILD_FILE_CONTENT "${BUILD_FILE_CONTENT}#include <${SOURCE_FILE}>\n") + ELSE () + SET(BUILD_FILE_CONTENT "${BUILD_FILE_CONTENT}#include <${FINAL_SOURCE_FILE}>\n") + ENDIF () + # Add the source dependencies to the Unity Build file + GET_SOURCE_FILE_PROPERTY(_FILE_DEPS ${SOURCE_FILE} OBJECT_DEPENDS) + + IF (_FILE_DEPS) + SET(_DEPS ${_DEPS} ${_FILE_DEPS}) + SET_SOURCE_FILES_PROPERTIES(${BUILD_FILE} PROPERTIES OBJECT_DEPENDS "${_DEPS}") + ENDIF() + # Keep counting up to the threshold. Increment counter. + MATH(EXPR COUNTER ${COUNTER}+1) + ENDIF () + ENDFOREACH () + # Write out the last Unity Build file + IF (NOT ${BUILD_FILE} STREQUAL "" AND NOT ${BUILD_FILE_CONTENT} STREQUAL "") + COMMIT_UNITY_FILE(BUILD_FILE BUILD_FILE_CONTENT) + ENDIF () + SET(UNITY_BUILD_FILES ${UNITY_BUILD_FILES} ${BUILD_FILE}) + SET(${SOURCE_VARIABLE_NAME} ${${SOURCE_VARIABLE_NAME}} ${UNITY_BUILD_FILES}) +ENDMACRO () + +MACRO (UNITY_GENERATE_MOC TARGET_NAME SOURCES HEADERS) + SET(NEW_SOURCES "") + FOREACH (HEADER_FILE ${${HEADERS}}) + IF (NOT EXISTS ${HEADER_FILE}) + MESSAGE(FATAL_ERROR "Header file does not exist (mocing): ${HEADER_FILE}") + ENDIF () + FILE(READ ${HEADER_FILE} FILE_CONTENT) + STRING(FIND "${FILE_CONTENT}" "Q_OBJECT" QOBJECT_POS) + STRING(FIND "${FILE_CONTENT}" "Q_SLOTS" QSLOTS_POS) + STRING(FIND "${FILE_CONTENT}" "Q_SIGNALS" QSIGNALS_POS) + STRING(FIND "${FILE_CONTENT}" "QObject" OBJECT_POS) + STRING(FIND "${FILE_CONTENT}" "slots" SLOTS_POS) + STRING(FIND "${FILE_CONTENT}" "signals" SIGNALS_POS) + IF (QOBJECT_POS GREATER 0 OR OBJECT_POS GREATER 0 OR QSLOTS_POS GREATER 0 OR Q_SIGNALS GREATER 0 OR + SLOTS_POS GREATER 0 OR SIGNALS GREATER 0) + # Generate the moc filename + GET_FILENAME_COMPONENT(HEADER_BASENAME ${HEADER_FILE} NAME_WE) + SET(MOC_FILENAME "moc_${HEADER_BASENAME}.cpp") + SET(NEW_SOURCES ${NEW_SOURCES} ; "${CMAKE_CURRENT_BINARY_DIR}/${MOC_FILENAME}") + ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${MOC_FILENAME}" + DEPENDS ${HEADER_FILE} + COMMAND ${QT_MOC_EXECUTABLE} ${HEADER_FILE} -o "${CMAKE_CURRENT_BINARY_DIR}/${MOC_FILENAME}") + ENDIF () + ENDFOREACH () + IF (NEW_SOURCES) + SET_SOURCE_FILES_PROPERTIES(${NEW_SOURCES} PROPERTIES GENERATED TRUE) + SET(${SOURCES} ${${SOURCES}} ; ${NEW_SOURCES}) + ENDIF () +ENDMACRO () |