unity_build.cmake 7.5 KB
Newer Older
1
# Add the following code before all include to avoid compilation failure.
2
set(UNITY_CC_BEFORE_CODE [[
3 4 5 6 7 8
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif]])
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
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()
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79

# 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(register_unity_group)

# 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 "")
80 81
        # Note(zhouwei25): UB use the path releative to CMAKE_SOURCE_DIR.
        # If use absolute path, sccache/ccache hit rate will be reduced.
82 83
        if(IS_ABSOLUTE ${src})
            set(src_absolute_path ${src})
84
            file(RELATIVE_PATH src_relative_path ${CMAKE_SOURCE_DIR} ${src})
85 86
        else()
            set(src_absolute_path ${CMAKE_CURRENT_SOURCE_DIR}/${src})
87
            file(RELATIVE_PATH src_relative_path ${CMAKE_SOURCE_DIR} ${src_absolute_path})
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
        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")
107 108 109 110
                        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()
111
                    endif()
112
                    set_property(GLOBAL APPEND PROPERTY ${unity_file_sources} "#include \"${src_relative_path}\"")
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
                    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(compose_unity_target_sources)

# 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(finish_unity_target)