# Add the following code before all include to avoid compilation failure. set(UNITY_CC_BEFORE_CODE [[ #ifndef NOMINMAX #define NOMINMAX #endif #ifndef _USE_MATH_DEFINES #define _USE_MATH_DEFINES #endif]]) set(UNITY_CU_BEFORE_CODE [[ #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) 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}) endif() # 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) # 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") # 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() # 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}) endif() 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() math(EXPR unity_group_index "${unity_group_index} + 1") set_property(GLOBAL PROPERTY ${UNITY_TARGET}_${TYPE}_group_index ${unity_group_index}) endfunction() # 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) # 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() endif() 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() endif() endforeach() endif() # Use original source file. if("${unity_file}" STREQUAL "") set(unity_target_sources ${unity_target_sources} ${src}) endif() endforeach() set(unity_target_${TYPE}_sources ${unity_target_sources} PARENT_SCOPE) endfunction() # 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) # 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") 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() endfunction()