################################################################################
#
# TNUN unity build helpers
#
# Copyright (c) 2016. Domagoj Saric. All rights reserved.
#
################################################################################

cmake_minimum_required( VERSION 3.1 )


################################################################################
# TNUN_create_unity_build()
#
# Unity builds can be used for static library projects to emulate "plain static
# libs internally built with LTO" until MSVC and Clang offer such functionality
# (i.e. building the project with 'whole program' optimisations w/o leaving the
# IR/'bitcode' in the final libraries).
#
# http://buffered.io/posts/the-magic-of-unity-builds
# https://en.wikipedia.org/wiki/Single_Compilation_Unit
# http://stackoverflow.com/questions/543697/include-all-cpp-files-into-a-single-compilation-unit
# https://engineering-game-dev.com/2009/12/15/the-evils-of-unity-builds
# http://cheind.wordpress.com/2009/12/10/reducing-compilation-time-unity-builds
################################################################################

function( TNUN_create_unity_build )
  # Generate a unique filename for the unity build translation unit.
  set( mother_source_file                  "${CMAKE_CURRENT_BINARY_DIR}/unity_build.cpp"              )
  set( TNUN_unity_build_mother_source_file "${mother_source_file}"                       PARENT_SCOPE )

  file( WRITE ${mother_source_file} "// TNUN Unity Build generated by CMake\n" )
  # Add an include statement for each translation unit:
  set( sources ${ARGN} )
  list( REMOVE_DUPLICATES sources )
  list( SORT              sources )
  foreach( source_file ${sources} )
    get_source_file_property( is_header_only ${source_file} HEADER_FILE_ONLY )
    if ( NOT is_header_only )
      string( FIND ${source_file} ".in"  in_location            )
      string( FIND ${source_file} ".cpp" cpp_extension_location )
      string( FIND ${source_file} ".mm"  mm_extensionLocation   )
      if ( ( cpp_extension_location GREATER -1 OR mm_extension_location GREATER -1 ) AND in_location EQUAL -1 )
        if ( NOT IS_ABSOLUTE ${source_file} )
          set( source_absolute_path "${CMAKE_CURRENT_SOURCE_DIR}/${source_file}" )
        else()
          set( source_absolute_path "${source_file}" )
        endif()
        FILE( APPEND ${mother_source_file} "#include \"${source_absolute_path}\"\n" )
      endif()
    endif()
  endforeach( source_file )

  set_source_files_properties( ${sources}              PROPERTIES HEADER_FILE_ONLY true )
  set_source_files_properties( "${mother_source_file}" PROPERTIES COMPILE_FLAGS "-DTNUN_UNITY_BUILD" )
  if ( APPLE )
    set_source_files_properties( ${mother_source_file} PROPERTIES COMPILE_FLAGS "-x objective-c++" ) # coarse, 'just in case'
  endif()
endfunction()
