blob: 17fb235c08f666f746b735afb7865d2a29bc9324 (
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
|
# Get all subdirectories under ${current_dir} and store them in ${result} variable
macro(subdirlist result current_dir)
file(GLOB children "${current_dir}/*")
set(dirlist "")
foreach(child ${children})
if (IS_DIRECTORY "${child}")
list(APPEND dirlist "${child}")
endif()
endforeach()
set(${result} ${dirlist})
endmacro()
# Prepend ${CMAKE_CURRENT_SOURCE_DIR} to a ${directory} name and save it in PARENT_SCOPE ${variable}
macro(prepend_cur_dir variable directory)
set(${variable} "${CMAKE_CURRENT_SOURCE_DIR}/${directory}")
endmacro()
# Add custom command to print firmware size in Berkeley format
function(firmware_size target)
add_custom_command(TARGET ${target} POST_BUILD
COMMAND ${CMAKE_SIZE_UTIL} -B "$<TARGET_FILE:${target}>"
)
endfunction()
# Add a command to generate firmware in a provided format
function(generate_object target suffix type)
add_custom_command(TARGET ${target} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O ${type} "$<TARGET_FILE:${target}>" "${CMAKE_CURRENT_BINARY_DIR}/${target}${suffix}"
)
endfunction()
# Set linker script for a target
function(target_linker_script target scope script)
target_link_options(${target} "${scope}" "-T${script}")
get_target_property(_cur_link_deps ${target} LINK_DEPENDS)
if (_cur_link_deps STREQUAL "_cur_link_deps-NOTFOUND")
set(_cur_link_deps "")
endif()
string(APPEND _cur_link_deps "${script}")
set_target_properties(${target} PROPERTIES LINK_DEPENDS ${_cur_link_deps})
endfunction()
# Write file only if content has changed
function(write_file_if_changed file content)
if (EXISTS "${file}")
file(READ "${file}" existing_content)
else()
set(existing_content "")
endif()
if (NOT "${existing_content}" STREQUAL "${content}")
file(WRITE "${file}" "${content}")
endif()
endfunction()
# Embed a file into a target
function(embed_file target file symbol)
cmake_path(IS_ABSOLUTE file is_absolute)
if (NOT is_absolute)
set(file "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
endif()
cmake_path(GET file FILENAME filename)
set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
if (NOT EXISTS "${generated_dir}")
file(MAKE_DIRECTORY "${generated_dir}")
endif()
set(generated_objects "${generated_dir}_objects")
if (NOT EXISTS "${generated_objects}")
file(MAKE_DIRECTORY "${generated_objects}")
endif()
set(asm_path "${generated_objects}/${filename}.S")
write_file_if_changed("${asm_path}"
".global ${symbol}_data
.global ${symbol}_size
.section .rodata
.align 4
${symbol}_data:
.incbin \"${file}\"
1:
${symbol}_size:
.int 1b - ${symbol}_data
")
add_custom_command(OUTPUT "${asm_path}"
COMMAND ${CMAKE_COMMAND} -E touch "${asm_path}"
DEPENDS "${file}")
target_sources("${target}" PRIVATE "${asm_path}")
set(header_path "${generated_dir}/${filename}")
write_file_if_changed("${header_path}.h"
"#pragma once
#ifdef __cplusplus
extern \"C\" {
#endif
extern const char ${symbol}_data[];
extern const unsigned int ${symbol}_size;
#ifdef __cplusplus
}
#endif
")
write_file_if_changed("${header_path}.hpp"
"#pragma once
#include \"${header_path}.h\"
#include <span>
inline const std::span<const char> ${symbol}{${symbol}_data, ${symbol}_size};
")
endfunction()
|