1#-------------------------------------------------------------------
2# This file is part of the CMake build system for OGRE
3#     (Object-oriented Graphics Rendering Engine)
4# For the latest info, see http://www.ogre3d.org/
5#
6# The contents of this file are placed in the public domain. Feel
7# free to make use of it in any way you like.
8#-------------------------------------------------------------------
9
10# check the contents of a given source file. If they differ from the
11# expected content, or the file does not exist, rewrite it with the
12# provided content.
13# This function is used in order to update Unity build files only when
14# necessary. If we rewrote them unconditionally, it might trigger an
15# unnecessary rebuild of the file.
16function(check_and_update_file FILENAME CONTENT)
17  # read current file contents
18  if (EXISTS ${FILENAME})
19    file(READ ${FILENAME} _CUR)
20  else ()
21    # create empty file
22    file(WRITE ${FILENAME} "")
23    set(_CUR "")
24  endif ()
25  if (NOT _CUR STREQUAL CONTENT)
26    # rewrite file with new contents
27    message(STATUS "  Updating ${FILENAME}...")
28    file(WRITE ${FILENAME} ${CONTENT})
29  else ()
30    message(STATUS "  ${FILENAME} is up to date.")
31  endif ()
32endfunction()
33
34
35# generate unity build files for the given target.
36# If in the list of source files the key word SEPARATE is specified, then
37# any source file after that will be compiled separately.
38macro(create_unity_build_files TARGETNAME)
39  # first step: build the primary and separate lists
40  set(_PRIMARY "")
41  set(_EXCLUDES "")
42  set(_SEP FALSE)
43  foreach(_FILE ${ARGN})
44    if (_FILE STREQUAL "SEPARATE")
45      set(_SEP TRUE)
46    else ()
47      if (_SEP)
48        list(APPEND _EXCLUDES ${_FILE})
49      else ()
50        list(APPEND _PRIMARY ${_FILE})
51      endif ()
52    endif()
53  endforeach()
54  set(_SOURCES ${_PRIMARY} ${_EXCLUDES})
55  list(REMOVE_DUPLICATES _SOURCES)
56
57  if (OGRE_UNITY_BUILD)
58    include_directories(${CMAKE_CURRENT_SOURCE_DIR})
59    # create Unity compilation units
60    # all source files given will be put into a certain number of
61    # compilation units.
62    # if certain source files should be excluded from the unity build
63    # and built separately, they need to also be named in the SEPARATE
64    # list.
65    set(_FILE_NUM 0)
66    set(_FILE_CNT 0)
67    set(_FILE_CONTENTS "")
68    message(STATUS "Creating Unity build files for target ${TARGETNAME}")
69    foreach(_FILE ${_PRIMARY})
70      # test if file is more than just a header
71      get_filename_component(_EXT ${_FILE} EXT)
72      list(FIND _EXCLUDES ${_FILE} _EXCLUDED)
73      if ((_EXT STREQUAL ".cpp") AND (_EXCLUDED EQUAL "-1"))
74        set(_FILE_CONTENTS "${_FILE_CONTENTS}\#include \"${_FILE}\"\n")
75        math(EXPR _FILE_CNT "${_FILE_CNT}+1")
76        if(_FILE_CNT EQUAL OGRE_UNITY_FILES_PER_UNIT)
77          set(_FILENAME "${OGRE_BINARY_DIR}/${TARGETNAME}/compile_${TARGETNAME}_${_FILE_NUM}.cpp")
78          check_and_update_file(${_FILENAME} ${_FILE_CONTENTS})
79          math(EXPR _FILE_NUM "${_FILE_NUM}+1")
80          set(_FILE_CNT 0)
81          set (_FILE_CONTENTS "")
82          list(APPEND _SOURCES ${_FILENAME})
83        endif()
84        # exclude the original source file from the compilation
85        set_source_files_properties(${_FILE} PROPERTIES LANGUAGE "" HEADER_FILE_ONLY TRUE)
86      endif()
87    endforeach()
88    # don't forget the last set of files
89    set(_FILENAME "${OGRE_BINARY_DIR}/${TARGETNAME}/compile_${TARGETNAME}_${_FILE_NUM}.cpp")
90    check_and_update_file(${_FILENAME} ${_FILE_CONTENTS})
91    list(APPEND _SOURCES ${_FILENAME})
92  endif ()
93endmacro()
94
95
96# add a new library target
97# usage: ogre_add_library(TARGETNAME LIBTYPE SOURCE_FILES [SEPARATE SOURCE_FILES])
98function(ogre_add_library TARGETNAME LIBTYPE)
99  create_unity_build_files(${TARGETNAME} ${ARGN})
100  add_library(${TARGETNAME} ${LIBTYPE} ${_SOURCES})
101endfunction(ogre_add_library)
102
103
104# add a new executable target
105# usage: ogre_add_executable(TARGETNAME [WIN32] [MACOSX_BUNDLE] SOURCE_FILES [SEPARATE SOURCE_FILES])
106function(ogre_add_executable TARGETNAME)
107  # test if WIN32 or MACOSX_BUNDLE options were provided
108  set(_WIN32 "")
109  set(_OSX "")
110  list(FIND ARGN "WIN32" _W32_IDX)
111  if (_W32_IDX GREATER "-1")
112    set(_WIN32 "WIN32")
113    list(REMOVE_AT ARGN ${_W32_IDX})
114  endif ()
115  list(FIND ARGN "MACOSX_BUNDLE" _OSX_IDX)
116  if (_OSX_IDX GREATER "-1")
117    set(_OSX "MACOSX_BUNDLE")
118    list(REMOVE_AT ARGN ${_OSX_IDX})
119  endif ()
120  create_unity_build_files(${TARGETNAME} ${ARGN})
121  add_executable(${TARGETNAME} ${_WIN32} ${_OSX} ${_SOURCES})
122endfunction()
123