Files
2026-07-07 15:39:46 +08:00

299 lines
10 KiB
CMake

include_guard(GLOBAL)
macro(wdk_fatal CONTEXT SUMMARY)
set(_wdk_fatal_details "details:")
set(_args ${ARGN})
foreach(_detail IN LISTS _args)
string(APPEND _wdk_fatal_details "\n ${_detail}")
endforeach()
message(FATAL_ERROR
"WDK fatal error\n"
" context: ${CONTEXT}\n"
" summary: ${SUMMARY}\n"
"${_wdk_fatal_details}"
)
endmacro()
function(wdk_get_raw_target_property_or_empty OUT_VAR TGT PROP)
get_property(_is_set TARGET "${TGT}" PROPERTY "${PROP}" SET)
if(NOT _is_set)
set(_value "")
else()
get_property(_value TARGET "${TGT}" PROPERTY "${PROP}")
if("${_value}" MATCHES "-NOTFOUND$")
set(_value "")
endif()
endif()
set(${OUT_VAR} "${_value}" PARENT_SCOPE)
endfunction()
function(wdk_get_target_property_or_empty OUT_VAR TGT NAME)
wdk_get_raw_target_property_or_empty(_value "${TGT}" "${NAME}")
set(${OUT_VAR} "${_value}" PARENT_SCOPE)
endfunction()
function(wdk_require_target_state_name CONTEXT NAME)
if("${NAME}" STREQUAL "")
wdk_fatal("${CONTEXT}" "state name is empty")
endif()
if(NOT "${NAME}" MATCHES "^[a-z][a-z0-9_]*$")
wdk_fatal("${CONTEXT}" "state name must be lower_snake_case" "name=${NAME}")
endif()
endfunction()
function(wdk_set_target_state TARGET_NAME NAME)
wdk_require_target("wdk_set_target_state" "${TARGET_NAME}")
wdk_require_target_state_name("wdk_set_target_state" "${NAME}")
set_property(TARGET "${TARGET_NAME}" PROPERTY "${NAME}" "${ARGN}")
if("${NAME}" STREQUAL "folder_name")
set_property(TARGET "${TARGET_NAME}" PROPERTY FOLDER "${ARGN}")
endif()
endfunction()
function(wdk_init_target_state TARGET_NAME NAME)
wdk_require_target("wdk_init_target_state" "${TARGET_NAME}")
wdk_require_target_state_name("wdk_init_target_state" "${NAME}")
get_property(_is_set TARGET "${TARGET_NAME}" PROPERTY "${NAME}" SET)
if(NOT _is_set)
set_property(TARGET "${TARGET_NAME}" PROPERTY "${NAME}" "${ARGN}")
if("${NAME}" STREQUAL "folder_name")
set_property(TARGET "${TARGET_NAME}" PROPERTY FOLDER "${ARGN}")
endif()
endif()
endfunction()
function(wdk_get_target_state OUT_VAR TARGET_NAME)
wdk_require_target("wdk_get_target_state" "${TARGET_NAME}")
if("${OUT_VAR}" STREQUAL "")
wdk_fatal("wdk_get_target_state" "output variable is empty" "target=${TARGET_NAME}")
endif()
wdk_require_target_state_name("wdk_get_target_state" "${OUT_VAR}")
wdk_get_target_property_or_empty(_value "${TARGET_NAME}" "${OUT_VAR}")
if("${OUT_VAR}" STREQUAL "folder_name" AND "${_value}" STREQUAL "")
wdk_get_target_property_or_empty(_value "${TARGET_NAME}" FOLDER)
endif()
set(${OUT_VAR} "${_value}" PARENT_SCOPE)
endfunction()
function(wdk_has_target_state OUT_VAR TARGET_NAME NAME)
wdk_require_target("wdk_has_target_state" "${TARGET_NAME}")
wdk_require_target_state_name("wdk_has_target_state" "${NAME}")
get_property(_is_set TARGET "${TARGET_NAME}" PROPERTY "${NAME}" SET)
set(${OUT_VAR} "${_is_set}" PARENT_SCOPE)
endfunction()
function(wdk_begin_target_state_init_once OUT_VAR TARGET_NAME NAME)
wdk_require_target("wdk_begin_target_state_init_once" "${TARGET_NAME}")
wdk_require_target_state_name("wdk_begin_target_state_init_once" "${NAME}")
set(_prop "${NAME}_initialized")
get_property(_is_set TARGET "${TARGET_NAME}" PROPERTY "${_prop}" SET)
if(_is_set)
set(${OUT_VAR} FALSE PARENT_SCOPE)
else()
set_property(TARGET "${TARGET_NAME}" PROPERTY "${_prop}" TRUE)
set(${OUT_VAR} TRUE PARENT_SCOPE)
endif()
endfunction()
function(wdk_require_target CONTEXT TARGET_NAME)
if("${TARGET_NAME}" STREQUAL "" OR NOT TARGET "${TARGET_NAME}")
wdk_fatal("${CONTEXT}" "target not found" "target=${TARGET_NAME}")
endif()
endfunction()
function(wdk_require_no_extra_args CONTEXT)
if(ARGN)
wdk_fatal("${CONTEXT}" "unexpected extra arguments" "args=${ARGN}")
endif()
endfunction()
function(wdk_require_non_empty CONTEXT VALUE_NAME VALUE)
if("${VALUE}" STREQUAL "")
wdk_fatal("${CONTEXT}" "required value is empty" "name=${VALUE_NAME}")
endif()
endfunction()
function(wdk_require_value_in_list CONTEXT VALUE LIST_VAR)
if(NOT DEFINED ${LIST_VAR})
wdk_fatal("${CONTEXT}" "list variable is not defined" "listVar=${LIST_VAR}" "value=${VALUE}")
endif()
list(FIND ${LIST_VAR} "${VALUE}" _index)
if(_index EQUAL -1)
wdk_fatal("${CONTEXT}" "unsupported value" "value=${VALUE}" "listVar=${LIST_VAR}" "supported=${${LIST_VAR}}")
endif()
endfunction()
function(wdk_print_list HEADER LIST_VAR)
message(STATUS "${HEADER}")
foreach(_item IN LISTS ${LIST_VAR})
message(STATUS " ${_item}")
endforeach()
endfunction()
macro(check_exist_fail_fast)
foreach(var_name ${ARGN})
if("${var_name}" STREQUAL "")
wdk_fatal("check_exist_fail_fast" "empty variable name" "args=${ARGN}")
endif()
if(NOT DEFINED ${var_name})
wdk_fatal("check_exist_fail_fast" "variable is not defined" "variable=${var_name}" "args=${ARGN}")
endif()
if("${${var_name}}" STREQUAL "")
wdk_fatal("check_exist_fail_fast" "variable is empty" "variable=${var_name}")
endif()
if(NOT EXISTS "${${var_name}}")
wdk_fatal("check_exist_fail_fast"
"path does not exist"
"variable=${var_name}"
"value=${${var_name}}"
"cwd=${CMAKE_CURRENT_BINARY_DIR}"
)
endif()
endforeach()
endmacro()
function(wdk_make_cmd_script_content OUT_VAR)
set(_content "@echo off\r\n")
string(APPEND _content "setlocal EnableExtensions\r\n")
foreach(_line IN LISTS ARGN)
string(APPEND _content "${_line}\r\n")
endforeach()
string(APPEND _content "endlocal\r\n")
string(APPEND _content "exit /b 0\r\n")
set(${OUT_VAR} "${_content}" PARENT_SCOPE)
endfunction()
function(wdk_write_cmd_script SCRIPT_FILE SCRIPT_CONTENT)
get_filename_component(_script_dir "${SCRIPT_FILE}" DIRECTORY)
file(MAKE_DIRECTORY "${_script_dir}")
file(WRITE "${SCRIPT_FILE}" "${SCRIPT_CONTENT}")
endfunction()
function(wdk_command_line_from_list OUT_VAR)
set(_line "")
foreach(_arg IN LISTS ARGN)
if("${_line}" STREQUAL "")
set(_line "\"${_arg}\"")
else()
string(APPEND _line " \"${_arg}\"")
endif()
endforeach()
set(${OUT_VAR} "${_line}" PARENT_SCOPE)
endfunction()
function(wdk_generate_cmd_script SCRIPT_FILE SCRIPT_CONTENT)
get_filename_component(_script_dir "${SCRIPT_FILE}" DIRECTORY)
file(MAKE_DIRECTORY "${_script_dir}")
file(GENERATE OUTPUT "${SCRIPT_FILE}" CONTENT "${SCRIPT_CONTENT}")
endfunction()
function(wdk_add_cmd_script_target TARGET_NAME SCRIPT_FILE WORKING_DIRECTORY COMMENT)
add_custom_target("${TARGET_NAME}"
COMMAND "${CMAKE_COMMAND}" -E chdir "${WORKING_DIRECTORY}" cmd.exe /D /C call "${SCRIPT_FILE}"
DEPENDS ${ARGN}
USES_TERMINAL
VERBATIM
COMMENT "${COMMENT}"
)
endfunction()
function(wdk_add_generated_cmd_script_target TARGET_NAME SCRIPT_FILE WORKING_DIRECTORY COMMENT SCRIPT_CONTENT)
wdk_generate_cmd_script("${SCRIPT_FILE}" "${SCRIPT_CONTENT}")
wdk_add_cmd_script_target(
"${TARGET_NAME}"
"${SCRIPT_FILE}"
"${WORKING_DIRECTORY}"
"${COMMENT}"
${ARGN}
)
endfunction()
function(wdk_add_written_cmd_script_target TARGET_NAME SCRIPT_FILE WORKING_DIRECTORY COMMENT SCRIPT_CONTENT)
wdk_write_cmd_script("${SCRIPT_FILE}" "${SCRIPT_CONTENT}")
wdk_add_cmd_script_target(
"${TARGET_NAME}"
"${SCRIPT_FILE}"
"${WORKING_DIRECTORY}"
"${COMMENT}"
${ARGN}
)
endfunction()
function(wdk_add_post_build_cmd_script TARGET_NAME SCRIPT_FILE COMMENT)
add_custom_command(TARGET "${TARGET_NAME}"
POST_BUILD
COMMAND cmd.exe /D /C call "${SCRIPT_FILE}"
VERBATIM
COMMENT "${COMMENT}"
)
endfunction()
function(wdk_add_generated_post_build_cmd_script TARGET_NAME SCRIPT_FILE COMMENT SCRIPT_CONTENT)
wdk_generate_cmd_script("${SCRIPT_FILE}" "${SCRIPT_CONTENT}")
wdk_add_post_build_cmd_script("${TARGET_NAME}" "${SCRIPT_FILE}" "${COMMENT}")
endfunction()
function(add_serial_build_target serial_target)
set(_targets ${ARGN})
list(LENGTH _targets _count)
if(_count EQUAL 0)
wdk_fatal("add_serial_build_target" "no targets provided" "serialTarget=${serial_target}")
endif()
if(TARGET "${serial_target}")
wdk_fatal("add_serial_build_target" "target already exists" "serialTarget=${serial_target}")
endif()
foreach(_target IN LISTS _targets)
if(NOT TARGET "${_target}")
wdk_fatal("add_serial_build_target" "target not found" "serialTarget=${serial_target}" "missingTarget=${_target}" "allTargets=${_targets}")
endif()
endforeach()
if(CMAKE_CONFIGURATION_TYPES)
set(_config_args --config "$<CONFIG>")
else()
set(_config_args)
endif()
set(_script_lines "")
foreach(_target IN LISTS _targets)
wdk_command_line_from_list(_build_line
"${CMAKE_COMMAND}"
--build "${CMAKE_BINARY_DIR}"
--target "${_target}"
${_config_args}
)
list(APPEND _script_lines
"${_build_line}"
"if errorlevel 1 exit /b 1"
)
endforeach()
set(_script_file "${CMAKE_BINARY_DIR}/windows_driver/_global/wdk_scripts/${serial_target}_$<CONFIG>.bat")
if("${serial_target}" MATCHES "^(.+)_static_tools_logo$")
set(_driver_target "${CMAKE_MATCH_1}")
if(TARGET "${_driver_target}")
wdk_get_target_state(script_dir "${_driver_target}")
set(_script_file "${script_dir}/${serial_target}_$<CONFIG>.bat")
endif()
endif()
wdk_make_cmd_script_content(_script_content ${_script_lines})
wdk_add_generated_cmd_script_target(
"${serial_target}"
"${_script_file}"
"${CMAKE_BINARY_DIR}"
"Running targets sequentially: ${_targets}"
"${_script_content}"
)
endfunction()