#
# Brisk
#
# Cross-platform application framework
# --------------------------------------------------------------
#
# Copyright (C) 2025 Brisk Developers
#
# This file is part of the Brisk library.
#
# Brisk is dual-licensed under the GNU General Public License, version 2 (GPL-2.0+), and a commercial license. You may
# use, modify, and distribute this software under the terms of the GPL-2.0+ license if you comply with its conditions.
#
# You should have received a copy of the GNU General Public License along with this program. If not, see
# .
#
# If you do not wish to be bound by the GPL-2.0+ license, you must purchase a commercial license. For commercial
# licensing options, please visit: https://brisklib.com
#
cmake_minimum_required(VERSION 3.22)
set(_RESOURCES_DATA_DIR
${CMAKE_BINARY_DIR}/resources
CACHE PATH "")
file(MAKE_DIRECTORY ${_RESOURCES_DATA_DIR})
set(BRISK_SCRIPTS_DIR
${CMAKE_CURRENT_LIST_DIR}
CACHE INTERNAL "Brisk script dir")
find_program(PACK_RESOURCE_TOOL NAMES pack_resource REQUIRED)
define_property(
TARGET
PROPERTY "BRISK_RESOURCES"
INHERITED
BRIEF_DOCS "List of Brisk resources per target"
FULL_DOCS "List of Brisk resources per target")
function (strip_build_interface input_string output_var)
string(REGEX REPLACE "\\$]*)>" "\\1" stripped_string "${input_string}")
set(${output_var}
"${stripped_string}"
PARENT_SCOPE)
endfunction ()
function (get_linked_libraries_recursive result target)
list(APPEND visited_targets ${target})
get_target_property(interface_libs ${target} INTERFACE_LINK_LIBRARIES)
get_target_property(link_libs ${target} LINK_LIBRARIES)
strip_build_interface("${interface_libs}" interface_libs)
strip_build_interface("${link_libs}" link_libs)
list(APPEND link_libs ${interface_libs})
set(result_list "")
foreach (lib ${link_libs})
if (TARGET ${lib})
list(FIND visited_targets ${lib} is_visited)
if (${is_visited} EQUAL -1)
get_linked_libraries_recursive(recursive_libs ${lib})
list(APPEND result_list ${recursive_libs} ${lib})
endif ()
endif ()
endforeach ()
set(visited_targets
${visited_targets}
PARENT_SCOPE)
set(${result}
${result_list}
PARENT_SCOPE)
endfunction ()
function (brisk_target_resources target)
set(absolute_path_list)
foreach (entry ${ARGN})
string(REGEX MATCH "^([^=]*)=([^\|]*)(\|.*)?$" match "${entry}")
set(key "${CMAKE_MATCH_1}")
set(value "${CMAKE_MATCH_2}")
set(filters "${CMAKE_MATCH_3}")
string(REPLACE "\"" "" value "${value}")
get_filename_component(full_path ${value} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_LIST_DIR})
list(APPEND absolute_path_list ${key}=${full_path}${filters})
endforeach ()
set_property(
TARGET ${target}
APPEND
PROPERTY BRISK_RESOURCES "${absolute_path_list}")
endfunction ()
function (brisk_target_resource target key)
cmake_parse_arguments("R" "BROTLI;GZIP;LZ4" "INPUT" "" ${ARGN})
set(filters "")
if (R_GZIP)
set(filters "|GZIP")
elseif (R_LZ4)
set(filters "|LZ4")
elseif (R_BROTLI)
set(filters "|BROTLI")
endif ()
brisk_target_resources(${target} ${key}=${R_INPUT}${filters})
endfunction ()
function (brisk_target_link_resource target mode key)
cmake_parse_arguments("R" "BROTLI;GZIP;LZ4" "INPUT" "" ${ARGN})
set(filters "")
if (R_GZIP)
set(filters "|GZIP")
elseif (R_LZ4)
set(filters "|LZ4")
elseif (R_BROTLI)
set(filters "|BROTLI")
endif ()
brisk_target_resources(${target} ${key}=${R_INPUT}${filters})
endfunction ()
if (CMAKE_GENERATOR MATCHES "^Visual Studio")
set(GEN_VS
TRUE
CACHE INTERNAL "")
endif ()
function (brisk_bundle_resources target)
get_linked_libraries_recursive(dependent_targets ${target})
list(APPEND dependent_targets ${target})
set(resource_list "")
foreach (dep ${dependent_targets})
get_target_property(resources ${dep} BRISK_RESOURCES)
list(APPEND resource_list ${resources})
endforeach ()
set(resource_keys "")
foreach (entry ${resource_list})
string(REGEX MATCH "^([^=]*)=(.*)$" match "${entry}")
set(key "${CMAKE_MATCH_1}")
set(value "${CMAKE_MATCH_2}")
set("resource_map__${key}" ${value})
list(APPEND resource_keys ${key})
endforeach ()
list(REMOVE_DUPLICATES resource_keys)
list(SORT resource_keys)
string(MAKE_C_IDENTIFIER ${target} target_id)
if (GEN_VS)
set(resource_dir ${_RESOURCES_DATA_DIR}/${target_id})
file(MAKE_DIRECTORY "${_RESOURCES_DATA_DIR}/${target_id}")
else ()
set(resource_dir ${_RESOURCES_DATA_DIR})
endif ()
set(resource_entries_c "${resource_dir}/entries__${target_id}.c")
file(
WRITE ${resource_entries_c}-tmp
[=[
#include
]=])
set(entries "")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(IS_MSVC TRUE)
endif ()
foreach (key ${resource_keys})
string(REGEX MATCH "^([^\\|]*)(\\|(.*))?$" match "${resource_map__${key}}")
set(full_path "${CMAKE_MATCH_1}")
file(TO_CMAKE_PATH "${full_path}" cm_full_path)
set(filters "${CMAKE_MATCH_3}")
string(TOUPPER "${filters}" filters)
string(MAKE_C_IDENTIFIER "${key}" ckey)
string(SHA256 hash ${cm_full_path})
string(SUBSTRING "${hash}" 0 8 hash)
set(full_key ${ckey}_${hash})
set(resource_key_c "${resource_dir}/${full_key}${filters}.c")
get_filename_component(dir_path "${resource_key_c}" DIRECTORY)
file(MAKE_DIRECTORY "${dir_path}")
set(rsrc_flags "ResourceCompression_None")
if ((NOT "${filters}" STREQUAL "") OR IS_MSVC)
set(flags "")
if ("${filters}" STREQUAL "BROTLI")
set(rsrc_flags "ResourceCompression_Brotli")
set(flags "--br")
elseif ("${filters}" STREQUAL "LZ4")
set(rsrc_flags "ResourceCompression_LZ4")
set(flags "--lz4")
elseif ("${filters}" STREQUAL "GZIP")
set(rsrc_flags "ResourceCompression_GZip")
set(flags "--gz")
elseif ("${filters}" STREQUAL "ZLIB")
set(rsrc_flags "ResourceCompression_ZLib")
set(flags "--zlib")
else ()
if (NOT "${filters}" STREQUAL "")
message(FATAL_ERROR "Unrocognized option in brisk_target_resource: ${filters}")
endif ()
endif ()
if (IS_MSVC)
list(APPEND flags "--c" "${full_key}")
endif ()
if (IS_MSVC)
set(output_file ${resource_key_c})
else ()
set(output_file ${resource_dir}/${full_key}${filters}.bin)
endif ()
set(_BRISK_GENERATED_RESOURCES ${BRISK_GENERATED_RESOURCES})
if (NOT "${output_file}" IN_LIST _BRISK_GENERATED_RESOURCES)
list(APPEND _BRISK_GENERATED_RESOURCES "${output_file}")
set(BRISK_GENERATED_RESOURCES
"${_BRISK_GENERATED_RESOURCES}"
CACHE INTERNAL "Resources generated by Brisk")
set(CMD ${PACK_RESOURCE_TOOL} ${flags} ${output_file} ${full_path})
add_custom_command(
OUTPUT ${output_file}
COMMAND ${CMAKE_COMMAND} "-DIN=${full_path}" "-DOUT=${output_file}" "-DCMD=${CMD}" -P
${BRISK_SCRIPTS_DIR}/pack_resource.cmake
# COMMAND ${PACK_RESOURCE_TOOL} ${flags} ${output_file} ${full_path}
DEPENDS ${full_path}
VERBATIM)
endif ()
if (IS_MSVC)
else ()
file(WRITE ${resource_key_c}-tmp
"#include \n\nINCBIN(${full_key}, \"${output_file}\");\n")
endif ()
else ()
# no filters and not MSVC
file(WRITE ${resource_key_c}-tmp
"#include \n\nINCBIN(${full_key}, \"${full_path}\");\n")
endif ()
if (NOT IS_MSVC)
file(COPY_FILE ${resource_key_c}-tmp ${resource_key_c} ONLY_IF_DIFFERENT)
file(REMOVE ${resource_key_c}-tmp)
endif ()
if ((NOT "${filters}" STREQUAL "") OR IS_MSVC)
if (IS_MSVC)
set_source_files_properties(${resource_key_c} PROPERTIES GENERATED TRUE)
else ()
set_source_files_properties(${resource_key_c} OBJECT_DEPENDS ${output_file})
endif ()
else ()
set_source_files_properties(${resource_key_c} OBJECT_DEPENDS ${full_path})
endif ()
set(entries "${entries} {\"${key}\", rsrc__${full_key}_data, &rsrc__${full_key}_size, ${rsrc_flags}}, \n")
file(APPEND ${resource_entries_c}-tmp "INCBIN_EXTERN(${full_key});\n")
target_sources(${target} PRIVATE ${resource_key_c})
endforeach ()
list(LENGTH resource_keys resource_count)
if ("${entries}" STREQUAL "")
set(entries " {0}\n")
endif ()
file(APPEND ${resource_entries_c}-tmp "const struct ResourceEntry resourceEntries[] = {\n${entries}};\n")
file(APPEND ${resource_entries_c}-tmp "const uint32_t resourceEntriesSize = ${resource_count};\n")
file(COPY_FILE ${resource_entries_c}-tmp ${resource_entries_c} ONLY_IF_DIFFERENT)
file(REMOVE ${resource_entries_c}-tmp)
target_sources(${target} PRIVATE ${resource_entries_c})
endfunction ()
set(BRISK_EMPTY_FILE ${CMAKE_CURRENT_BINARY_DIR}/empty-file)
file(TOUCH "${BRISK_EMPTY_FILE}")
function (brisk_target_remove_resources target)
set(resources "${ARGN}")
list(TRANSFORM resources APPEND "=${BRISK_EMPTY_FILE}")
brisk_target_resources(${target} ${resources})
endfunction ()