-
Notifications
You must be signed in to change notification settings - Fork 1
/
assets_include.cmake
105 lines (87 loc) · 4.39 KB
/
assets_include.cmake
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
# credit goes to https://github.com/Lauriethefish for this
# Directory where our arbitrary asset files are stored
set(ASSETS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/assets)
# Directory to save the object files generated by llvm-objcopy
set(ASSET_BINARIES_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/binaryAssets)
# Directory to save the prepended files to
set(PREPENDED_ASSETS_DIR ${CMAKE_CURRENT_BINARY_DIR}/prependedAssets)
set(ASSET_HEADER_PATH "${CMAKE_CURRENT_SOURCE_DIR}/include/assets.hpp")
# Define a macro which we will use for defining the symbols to access our asset files below
set(ASSET_HEADER_DATA
"#pragma once
struct IncludedAsset {
IncludedAsset(uint8_t* start, uint8_t* end) : array(reinterpret_cast<Array<uint8_t>*>(start)) {
array->klass = nullptr;
array->monitor = nullptr;
array->bounds = nullptr;
array->max_length = end - start - 32;
}
operator ArrayW<uint8_t>() const {
init();
return array;
}
operator std::string_view() const {
return { reinterpret_cast<char*>(array->_values), array->get_Length() };
}
operator std::span<uint8_t>() const {
return { array->_values, array->get_Length() };
}
void init() const {
if(!array->klass)
array->klass = classof(Array<uint8_t>*);
}
private:
Array<uint8_t>* array;
};
#define DECLARE_FILE(name) \\
extern \"C\" uint8_t _binary_##name##_start[]; \\
extern \"C\" uint8_t _binary_##name##_end[]; \\
const IncludedAsset name { _binary_##name##_start, _binary_##name##_end};
namespace IncludedAssets {
\n")
if (EXISTS ${ASSETS_DIRECTORY})
file(MAKE_DIRECTORY ${ASSET_BINARIES_DIRECTORY})
file(MAKE_DIRECTORY ${PREPENDED_ASSETS_DIR})
file(GLOB ASSETS LIST_DIRECTORIES false ${ASSETS_DIRECTORY}/*)
# Iterate through each file in the assets directory. TODO: This could be recursive
foreach(FILE IN LISTS ASSETS)
message("-- Including asset: ${FILE}")
get_filename_component(ASSET ${FILE} NAME) # Find the asset's file name
# make a copy of the file with 32 bytes added in the build dir
add_custom_command(
OUTPUT ${PREPENDED_ASSETS_DIR}/${ASSET}
COMMAND ${CMAKE_COMMAND} -E echo_append " " > ${PREPENDED_ASSETS_DIR}/${ASSET}
COMMAND ${CMAKE_COMMAND} -E cat ${ASSETS_DIRECTORY}/${ASSET} >> ${PREPENDED_ASSETS_DIR}/${ASSET}
DEPENDS ${ASSETS_DIRECTORY}/${ASSET}
)
set(OUTPUT_FILE "${ASSET_BINARIES_DIRECTORY}/${ASSET}.o") # Save our asset in the asset binaries directory
# Use llvm-objcopy to create an object file that stores our binary asset
# The resulting file contains 3 symbols: _binary_<file_name>_start, _binary_<file_name>_size and _binary_<file_name>_end
# We only use the first two
add_custom_command(
OUTPUT ${OUTPUT_FILE}
COMMAND ${CMAKE_OBJCOPY} ${ASSET} ${OUTPUT_FILE} --input-target binary --output-target elf64-aarch64 --set-section-flags binary=strings
DEPENDS ${PREPENDED_ASSETS_DIR}/${ASSET}
WORKING_DIRECTORY ${PREPENDED_ASSETS_DIR}
)
list(APPEND BINARY_ASSET_FILES ${OUTPUT_FILE})
# Find the correct objcopy symbol name, this is always the file name with any non-alphanumeric characters replaced with _
string(REGEX REPLACE "[^a-zA-Z0-9]" "_" FIXED_ASSET ${ASSET})
# Add to our assets header
set(ASSET_HEADER_DATA "${ASSET_HEADER_DATA}\tDECLARE_FILE(${FIXED_ASSET})\n")
endforeach()
set(ASSET_HEADER_DATA "${ASSET_HEADER_DATA}\n}\n")
# check if at least 1 asset file, otherwise ignore
list(LENGTH BINARY_ASSET_FILES COUNT)
if (${COUNT} GREATER 0)
# Generate the assets header file
file(GENERATE OUTPUT ${ASSET_HEADER_PATH} CONTENT "${ASSET_HEADER_DATA}")
# Add our assets files to the final SO
add_library(asset_files OBJECT ${BINARY_ASSET_FILES})
set_target_properties(asset_files PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(${COMPILE_ID} PRIVATE asset_files ${BINARY_ASSET_FILES})
endif()
else()
message("-- Removing '${ASSET_HEADER_PATH}' as no assets have been found in '${ASSETS_DIRECTORY}'")
file(REMOVE ${ASSET_HEADER_PATH})
endif()