unity_build.cmake 7.4 KB
Newer Older
1
# Add the following code before all include to avoid compilation failure.
2 3
set(UNITY_CC_BEFORE_CODE
    [[
4 5 6 7 8 9
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif]])
10 11
set(UNITY_CU_BEFORE_CODE
    [[
12 13 14 15 16 17 18
#ifndef __CUDACC_VER_MAJOR__
#define __CUDACC_VER_MAJOR__ CUDA_COMPILER_MAJOR_VERSION
#endif
#ifndef __CUDACC_VER_MINOR__
#define __CUDACC_VER_MINOR__ CUDA_COMPILER_MINOR_VERSION
#endif]])
if(WITH_GPU)
19 20 21 22 23 24 25
  string(REPLACE "." ";" CUDA_COMPILER_VERSION ${CMAKE_CUDA_COMPILER_VERSION})
  list(GET CUDA_COMPILER_VERSION 0 CUDA_COMPILER_MAJOR_VERSION)
  list(GET CUDA_COMPILER_VERSION 1 CUDA_COMPILER_MINOR_VERSION)
  string(REPLACE "CUDA_COMPILER_MAJOR_VERSION" ${CUDA_COMPILER_MAJOR_VERSION}
                 UNITY_CU_BEFORE_CODE ${UNITY_CU_BEFORE_CODE})
  string(REPLACE "CUDA_COMPILER_MINOR_VERSION" ${CUDA_COMPILER_MINOR_VERSION}
                 UNITY_CU_BEFORE_CODE ${UNITY_CU_BEFORE_CODE})
26
endif()
27 28 29 30 31 32

# Group a list of source files that can be included together.
# This combination is just a guiding rule, and the source file of group
# do not have to exist.
# Here you need to specify the source type which belongs to cc or cu.
function(register_unity_group TYPE)
33 34 35 36 37
  # Get UNITY_TARGET from CMAKE_CURRENT_SOURCE_DIR.
  string(REPLACE "${PADDLE_SOURCE_DIR}/paddle/fluid/" "" UNITY_TARGET
                 ${CMAKE_CURRENT_SOURCE_DIR})
  string(REPLACE "/" "_" UNITY_TARGET ${UNITY_TARGET})
  set(UNITY_TARGET "paddle_${UNITY_TARGET}_unity")
38

39 40 41 42 43 44
  # Variable unity_group_index is used to record the number of UNITY_TARGET groups.
  get_property(unity_group_index GLOBAL
               PROPERTY ${UNITY_TARGET}_${TYPE}_group_index)
  if("${unity_group_index}" STREQUAL "")
    set(unity_group_index 0)
  endif()
45

46 47 48 49 50 51 52 53
  # Variable unity_group_sources is used to record the sources of one group.
  set(unity_group_sources
      ${UNITY_TARGET}_${TYPE}_group_${unity_group_index}_sources)
  set_property(GLOBAL PROPERTY ${unity_group_sources} "")
  foreach(src ${ARGN})
    # UB use absolute path of source.
    if(NOT IS_ABSOLUTE ${src})
      set(src ${CMAKE_CURRENT_SOURCE_DIR}/${src})
54
    endif()
55 56 57 58 59 60 61 62 63 64 65
    set_property(GLOBAL APPEND PROPERTY ${unity_group_sources} ${src})
  endforeach()

  # If unity_file does not exists, nv_library or cc_library will use
  # dummy_file. Touch unity_file to avoid to use dummy file.
  set(unity_file
      ${CMAKE_CURRENT_BINARY_DIR}/${UNITY_TARGET}_${unity_group_index}_${TYPE}.${TYPE}
  )
  if(NOT EXISTS ${unity_file})
    file(TOUCH ${unity_file})
  endif()
66

67 68 69
  math(EXPR unity_group_index "${unity_group_index} + 1")
  set_property(GLOBAL PROPERTY ${UNITY_TARGET}_${TYPE}_group_index
                               ${unity_group_index})
70
endfunction()
71 72 73 74 75 76 77 78 79 80

# Combine the original source files used by `TARGET`, then use
# `unity_target_${TYPE}_sources` to get the combined source files.
# If the source file does not hit any registed groups, use itself.
# This function put the actual combination relationship in variables instead of
# writing the unity source file. The reason is that writing unity source file
# will change the timestampe and affect the effect of retaining the build
# directory on Windows.
# Here you need to specify the source type which belongs to cc or cu.
function(compose_unity_target_sources TARGET TYPE)
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
  # Variable unity_target_sources represents the source file used in TARGET
  set(unity_target_sources "")
  get_property(unity_group_index_max GLOBAL
               PROPERTY ${TARGET}_${TYPE}_group_index)
  foreach(src ${ARGN})
    set(unity_file "")
    # Note(zhouwei25): UB use the path releative to CMAKE_SOURCE_DIR.
    # If use absolute path, sccache/ccache hit rate will be reduced.
    if(IS_ABSOLUTE ${src})
      set(src_absolute_path ${src})
      file(RELATIVE_PATH src_relative_path ${CMAKE_SOURCE_DIR} ${src})
    else()
      set(src_absolute_path ${CMAKE_CURRENT_SOURCE_DIR}/${src})
      file(RELATIVE_PATH src_relative_path ${CMAKE_SOURCE_DIR}
           ${src_absolute_path})
    endif()
    # If `unity_group_index_max` is empty, there is no combination
    # relationship.
    # TODO(Avin0323): Whether use target property `UNITY_BUILD` of CMAKE to
    # combine source files.
    if(NOT "${unity_group_index_max}" STREQUAL "")
      # Search in each registed group.
      foreach(unity_group_index RANGE ${unity_group_index_max})
        if(${unity_group_index} GREATER_EQUAL ${unity_group_index_max})
          break()
106
        endif()
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
        get_property(
          unity_group_sources GLOBAL
          PROPERTY ${TARGET}_${TYPE}_group_${unity_group_index}_sources)
        if(${src_absolute_path} IN_LIST unity_group_sources)
          set(unity_file
              ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_${unity_group_index}_${TYPE}.${TYPE}
          )
          set(unity_file_sources
              ${TARGET}_${TYPE}_file_${unity_group_index}_sources)
          get_property(
            set_unity_file_sources GLOBAL
            PROPERTY ${unity_file_sources}
            SET)
          if(NOT ${set_unity_file_sources})
            # Add macro before include source files.
            set_property(GLOBAL PROPERTY ${unity_file_sources}
                                         "// Generate by Unity Build")
            set_property(GLOBAL APPEND PROPERTY ${unity_file_sources}
                                                ${UNITY_CC_BEFORE_CODE})
            if(WITH_GPU AND "${TYPE}" STREQUAL "cu")
              set_property(GLOBAL APPEND PROPERTY ${unity_file_sources}
                                                  ${UNITY_CU_BEFORE_CODE})
            endif()
          endif()
          set_property(
            GLOBAL APPEND PROPERTY ${unity_file_sources}
                                   "#include \"${src_relative_path}\"")
          set(unity_target_sources ${unity_target_sources} ${unity_file})
          break()
136
        endif()
137 138 139 140 141 142 143
      endforeach()
    endif()
    # Use original source file.
    if("${unity_file}" STREQUAL "")
      set(unity_target_sources ${unity_target_sources} ${src})
    endif()
  endforeach()
144

145 146 147
  set(unity_target_${TYPE}_sources
      ${unity_target_sources}
      PARENT_SCOPE)
148
endfunction()
149 150 151 152 153

# Write the unity files used by `UNITY_TARGET`.
# Write dependent on whether the contents of the unity file have changed, which
# protects incremental compilation speed.
function(finish_unity_target TYPE)
154 155 156 157 158
  # Get UNITY_TARGET from CMAKE_CURRENT_SOURCE_DIR.
  string(REPLACE "${PADDLE_SOURCE_DIR}/paddle/fluid/" "" UNITY_TARGET
                 ${CMAKE_CURRENT_SOURCE_DIR})
  string(REPLACE "/" "_" UNITY_TARGET ${UNITY_TARGET})
  set(UNITY_TARGET "paddle_${UNITY_TARGET}_unity")
159

160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
  get_property(unity_group_index_max GLOBAL
               PROPERTY ${UNITY_TARGET}_${TYPE}_group_index)
  if(NOT "${unity_group_index_max}" STREQUAL "")
    foreach(unity_group_index RANGE ${unity_group_index_max})
      if(${unity_group_index} GREATER_EQUAL ${unity_group_index_max})
        break()
      endif()
      get_property(
        unity_file_sources GLOBAL
        PROPERTY ${UNITY_TARGET}_${TYPE}_file_${unity_group_index}_sources)
      set(unity_file_read_content "")
      string(JOIN "\n" unity_file_write_content ${unity_file_sources})
      set(unity_file
          ${CMAKE_CURRENT_BINARY_DIR}/${UNITY_TARGET}_${unity_group_index}_${TYPE}.${TYPE}
      )
      file(READ ${unity_file} unity_file_read_content)
      if(NOT "${unity_file_read_content}" STREQUAL
         "${unity_file_write_content}")
        file(WRITE ${unity_file} ${unity_file_write_content})
      endif()
    endforeach()
  endif()
182
endfunction()