aboutsummaryrefslogtreecommitdiff
path: root/scripts/cmake/vcpkg_execute_build_process.cmake
blob: 914c07e0d3054a24252f2773eac8932ce8495c64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
80
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
106
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#[===[.md:
# vcpkg_execute_build_process

Execute a required build process

## Usage
```cmake
vcpkg_execute_build_process(
    COMMAND <cmd> [<args>...]
    [NO_PARALLEL_COMMAND <cmd> [<args>...]]
    WORKING_DIRECTORY </path/to/dir>
    LOGNAME <log_name>
)
```
## Parameters
### COMMAND
The command to be executed, along with its arguments.

### NO_PARALLEL_COMMAND
Optional parameter which specifies a non-parallel command to attempt if a
failure potentially due to parallelism is detected.

### WORKING_DIRECTORY
The directory to execute the command in.

### LOGNAME
The prefix to use for the log files.

This should be a unique name for different triplets so that the logs don't
conflict when building multiple at once.

## Examples

* [icu](https://github.com/Microsoft/vcpkg/blob/master/ports/icu/portfile.cmake)
#]===]

set(Z_VCPKG_EXECUTE_BUILD_PROCESS_RETRY_ERROR_MESSAGES
    "LINK : fatal error LNK1102:"
    " fatal error C1060: "
    # The linker ran out of memory during execution. We will try continuing once more, with parallelism disabled.
    "LINK : fatal error LNK1318:"
    "LINK : fatal error LNK1104:"
    "LINK : fatal error LNK1201:"
    # Multiple threads using the same directory at the same time cause conflicts, will try again.
    "Cannot create parent directory"
    "Cannot write file"
    # Multiple threads caused the wrong order of creating folders and creating files in folders
    "Can't open"
)
list(JOIN Z_VCPKG_EXECUTE_BUILD_PROCESS_RETRY_ERROR_MESSAGES "|" Z_VCPKG_EXECUTE_BUILD_PROCESS_RETRY_ERROR_MESSAGES)

function(vcpkg_execute_build_process)
    cmake_parse_arguments(PARSE_ARGV 0 arg "" "WORKING_DIRECTORY;LOGNAME" "COMMAND;NO_PARALLEL_COMMAND")

    if(DEFINED arg_UNPARSED_ARGUMENTS)
        message(WARNING "${CMAKE_CURRENT_FUNCTION} was passed extra arguments: ${arg_UNPARSED_ARGUMENTS}")
    endif()
    foreach(required_arg IN ITEMS WORKING_DIRECTORY COMMAND)
        if(NOT DEFINED arg_${required_arg})
            message(FATAL_ERROR "${required_arg} must be specified.")
        endif()
    endforeach()

    if(NOT DEFINED arg_LOGNAME)
        message(WARNING "LOGNAME should be specified.")
        set(arg_LOGNAME "build")
    endif()

    set(log_prefix "${CURRENT_BUILDTREES_DIR}/${arg_LOGNAME}")
    set(log_out "${log_prefix}-out.log")
    set(log_err "${log_prefix}-err.log")
    set(all_logs "${log_out}" "${log_err}")

    execute_process(
        COMMAND ${arg_COMMAND}
        WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}"
        OUTPUT_FILE "${log_out}"
        ERROR_FILE "${log_err}"
        RESULT_VARIABLE error_code
    )

    if(NOT error_code EQUAL "0")
        file(READ "${log_out}" out_contents)
        file(READ "${log_err}" err_contents)
        set(all_contents "${out_contents}${err_contents}")
        if(all_contents MATCHES "${Z_VCPKG_EXECUTE_BUILD_PROCESS_RETRY_ERROR_MESSAGES}")
            message(STATUS "Restarting Build without parallelism because memory exceeded")
            set(log_out "${log_prefix}-out-1.log")
            set(log_err "${log_prefix}-err-1.log")
            list(APPEND all_logs "${log_out}" "${log_err}")

            if(DEFINED arg_NO_PARALLEL_COMMAND)
                execute_process(
                    COMMAND ${arg_NO_PARALLEL_COMMAND}
                    WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}"
                    OUTPUT_FILE "${log_out}"
                    ERROR_FILE "${log_err}"
                    RESULT_VARIABLE error_code
                )
            else()
                execute_process(
                    COMMAND ${arg_COMMAND}
                    WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}"
                    OUTPUT_FILE "${log_out}"
                    ERROR_FILE "${log_err}"
                    RESULT_VARIABLE error_code
                )
            endif()
        elseif(all_contents MATCHES "mt : general error c101008d: ")
            # Antivirus workaround - occasionally files are locked and cause mt.exe to fail
            message(STATUS "mt.exe has failed. This may be the result of anti-virus. Disabling anti-virus on the buildtree folder may improve build speed")
            foreach(iteration RANGE 1 3)
                message(STATUS "Restarting Build ${TARGET_TRIPLET}-${SHORT_BUILDTYPE} because of mt.exe file locking issue. Iteration: ${iteration}")

                set(log_out "${log_prefix}-out-${iteration}.log")
                set(log_err "${log_prefix}-err-${iteration}.log")
                list(APPEND all_logs "${log_out}" "${log_err}")
                execute_process(
                    COMMAND ${arg_COMMAND}
                    WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}"
                    OUTPUT_FILE "${log_out}"
                    ERROR_FILE "${log_err}"
                    RESULT_VARIABLE error_code
                )

                if(error_code EQUAL "0")
                    break()
                endif()

                file(READ "${log_out}" out_contents)
                file(READ "${log_err}" err_contents)
                set(all_contents "${out_contents}${err_contents}")
                if(NOT all_contents MATCHES "mt : general error c101008d: ")
                    break()
                endif()
            endforeach()
        elseif(all_contents MATCHES "fatal error: ld terminated with signal 9 [Killed]")
            message(WARNING "ld was terminated with signal 9 [killed], please ensure your system has sufficient hard disk space and memory.")
        endif()
    endif()

    if(NOT error_code EQUAL "0")
        set(stringified_logs "")
        foreach(log IN LISTS all_logs)
            if(NOT EXISTS "${log}")
                continue()
            endif()
            file(SIZE "${log}" log_size)
            if(NOT log_size EQUAL "0")
                file(TO_NATIVE_PATH "${log}" native_log)
                string(APPEND stringified_logs "    ${native_log}\n")
            endif()
        endforeach()
        z_vcpkg_prettify_command_line(pretty_command ${arg_COMMAND})
        message(FATAL_ERROR
            "  Command failed: ${pretty_command}\n"
            "  Working Directory: ${arg_WORKING_DIRECTORY}\n"
            "  See logs for more information:\n"
            "${stringified_logs}"
        )
    endif()
endfunction()