blob: 35b0d432be53a6d365de75f4b3b6545e75b449ec [file] [log] [blame]
yang.lid6fe6242022-01-13 14:44:24 +08001# Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
2
3# SPDX-License-Identifier: MIT
4
bin.chen1a426d32021-10-13 10:52:36 +08005# SPDX-License-Identifier: Apache-2.0
6
7########################################################
8# Table of contents
9########################################################
10# 1. Amlogic-aware extensions
11# 1.1. aml_*
12# 1.2. aml_library_*
13# 1.2.1 aml_interface_library_*
14# 1.3. generate_inc_*
15# 1.4. board_*
16# 1.5. Misc.
17# 2. Kconfig-aware extensions
18# 2.1 *_if_kconfig
19# 2.2 Misc
20# 3. CMake-generic extensions
21# 3.1. *_ifdef
22# 3.2. *_ifndef
23# 3.3. *_option compiler compatibility checks
24# 3.4. Debugging CMake
25# 3.5. File system management
26
27########################################################
28# 1. Amlogic-aware extensions
29########################################################
30# 1.1. aml_*
31#
32# The following methods are for modifying the CMake library[0] called
33# "aml". aml is a catch-all CMake library for source files that
34# can be built purely with the include paths, defines, and other
35# compiler flags that all aml source files use.
36# [0] https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html
37#
38# Example usage:
39# aml_sources(
40# random_esp32.c
41# utils.c
42# )
43#
44# Is short for:
45# target_sources(aml PRIVATE
46# ${CMAKE_CURRENT_SOURCE_DIR}/random_esp32.c
47# ${CMAKE_CURRENT_SOURCE_DIR}/utils.c
48# )
49
50# https://cmake.org/cmake/help/latest/command/target_sources.html
51function(aml_sources)
52 foreach(arg ${ARGV})
53 if(IS_ABSOLUTE ${arg})
54 set(path ${arg})
55 else()
56 set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
57 endif()
58
59 if(IS_DIRECTORY ${path})
60 message(FATAL_ERROR "aml_sources() was called on a directory")
61 endif()
62
63 target_sources(${TARGET_NAME} PRIVATE ${path})
64 endforeach()
65endfunction()
66
67# https://cmake.org/cmake/help/latest/command/target_include_directories.html
68function(aml_include_directories)
69 foreach(arg ${ARGV})
70 if(IS_ABSOLUTE ${arg})
71 set(path ${arg})
72 else()
73 set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
74 endif()
75 target_include_directories(aml_interface INTERFACE ${path})
76 endforeach()
77endfunction()
78
79# https://cmake.org/cmake/help/latest/command/target_include_directories.html
80function(aml_system_include_directories)
81 foreach(arg ${ARGV})
82 if(IS_ABSOLUTE ${arg})
83 set(path ${arg})
84 else()
85 set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
86 endif()
87 target_include_directories(aml_interface SYSTEM INTERFACE ${path})
88 endforeach()
89endfunction()
90
91# https://cmake.org/cmake/help/latest/command/target_compile_definitions.html
92function(aml_compile_definitions)
93 target_compile_definitions(aml_interface INTERFACE ${ARGV})
94endfunction()
95
96# https://cmake.org/cmake/help/latest/command/target_compile_options.html
97function(aml_compile_options)
98 target_compile_options(aml_interface INTERFACE ${ARGV})
99endfunction()
100
101# https://cmake.org/cmake/help/latest/command/target_link_libraries.html
102function(aml_link_libraries)
xiaohu.huang50acd142022-05-16 13:52:56 +0800103 set(COLLECT_LINK_LIBRARIES ${CURRENT_LIBRARY} ${COLLECT_LINK_LIBRARIES} CACHE INTERNAL "")
104# target_link_libraries(${TARGET_NAME} ${CURRENT_LIBRARY})
105endfunction()
106
107function(aml_link_libraries_with_name lib_name)
108 set(COLLECT_LINK_LIBRARIES ${lib_name} ${COLLECT_LINK_LIBRARIES} CACHE INTERNAL "")
109# target_link_libraries(${TARGET_NAME} ${CURRENT_LIBRARY})
bin.chen1a426d32021-10-13 10:52:36 +0800110endfunction()
111
xiaohu.huang0c43a622022-11-15 17:48:56 +0800112function(aml_link_cpp_libraries_with_name lib_name)
113 set(COLLECT_LINK_LIBRARIES ${lib_name} ${COLLECT_LINK_LIBRARIES} CACHE INTERNAL "")
114 set(COLLECT_IS_CPP_LIBRARIES "1" CACHE INTERNAL "")
115endfunction()
116
bin.chen1a426d32021-10-13 10:52:36 +0800117function(aml_link_interfaces)
118 target_link_libraries(${TARGET_NAME} ${CURRENT_INTERFACE})
119endfunction()
120
121# See this file section 3.1. target_cc_option
122function(aml_cc_option)
123 foreach(arg ${ARGV})
124 target_cc_option(aml_interface INTERFACE ${arg})
125 endforeach()
126endfunction()
127
128function(aml_cc_option_fallback option1 option2)
129 target_cc_option_fallback(aml_interface INTERFACE ${option1} ${option2})
130endfunction()
131
132function(aml_ld_options)
133 target_ld_options(aml_interface INTERFACE ${ARGV})
134endfunction()
135
136# Getter functions for extracting build information from
137# aml_interface. Returning lists, and strings is supported, as is
138# requesting specific categories of build information (defines,
139# includes, options).
140#
141# The naming convention follows:
142# aml_get_${build_information}_for_lang${format}(lang x [SKIP_PREFIX])
143# Where
144# the argument 'x' is written with the result
145# and
146# ${build_information} can be one of
147# - include_directories # -I directories
148# - system_include_directories # -isystem directories
149# - compile_definitions # -D'efines
150# - compile_options # misc. compiler flags
151# and
152# ${format} can be
153# - the empty string '', signifying that it should be returned as a list
154# - _as_string signifying that it should be returned as a string
155# and
156# ${lang} can be one of
157# - C
158# - CXX
159# - ASM
160#
161# SKIP_PREFIX
162#
163# By default the result will be returned ready to be passed directly
164# to a compiler, e.g. prefixed with -D, or -I, but it is possible to
165# omit this prefix by specifying 'SKIP_PREFIX' . This option has no
166# effect for 'compile_options'.
167#
168# e.g.
169# aml_get_include_directories_for_lang(ASM x)
170# writes "-Isome_dir;-Isome/other/dir" to x
171
172function(aml_get_include_directories_for_lang_as_string lang i)
173 aml_get_include_directories_for_lang(${lang} list_of_flags ${ARGN})
174
175 convert_list_of_flags_to_string_of_flags(list_of_flags str_of_flags)
176
177 set(${i} ${str_of_flags} PARENT_SCOPE)
178endfunction()
179
180function(aml_get_system_include_directories_for_lang_as_string lang i)
181 aml_get_system_include_directories_for_lang(${lang} list_of_flags ${ARGN})
182
183 convert_list_of_flags_to_string_of_flags(list_of_flags str_of_flags)
184
185 set(${i} ${str_of_flags} PARENT_SCOPE)
186endfunction()
187
188function(aml_get_compile_definitions_for_lang_as_string lang i)
189 aml_get_compile_definitions_for_lang(${lang} list_of_flags ${ARGN})
190
191 convert_list_of_flags_to_string_of_flags(list_of_flags str_of_flags)
192
193 set(${i} ${str_of_flags} PARENT_SCOPE)
194endfunction()
195
196function(aml_get_compile_options_for_lang_as_string lang i)
197 aml_get_compile_options_for_lang(${lang} list_of_flags)
198
199 convert_list_of_flags_to_string_of_flags(list_of_flags str_of_flags)
200
201 set(${i} ${str_of_flags} PARENT_SCOPE)
202endfunction()
203
204function(aml_get_include_directories_for_lang lang i)
205 get_property_and_add_prefix(flags aml_interface INTERFACE_INCLUDE_DIRECTORIES
206 "-I"
207 ${ARGN}
208 )
209
210 process_flags(${lang} flags output_list)
211
212 set(${i} ${output_list} PARENT_SCOPE)
213endfunction()
214
215function(aml_get_system_include_directories_for_lang lang i)
216 get_property_and_add_prefix(flags aml_interface INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
217 "-isystem"
218 ${ARGN}
219 )
220
221 process_flags(${lang} flags output_list)
222
223 set(${i} ${output_list} PARENT_SCOPE)
224endfunction()
225
226function(aml_get_compile_definitions_for_lang lang i)
227 get_property_and_add_prefix(flags aml_interface INTERFACE_COMPILE_DEFINITIONS
228 "-D"
229 ${ARGN}
230 )
231
232 process_flags(${lang} flags output_list)
233
234 set(${i} ${output_list} PARENT_SCOPE)
235endfunction()
236
237function(aml_get_compile_options_for_lang lang i)
238 get_property(flags TARGET aml_interface PROPERTY INTERFACE_COMPILE_OPTIONS)
239
240 process_flags(${lang} flags output_list)
241
242 set(${i} ${output_list} PARENT_SCOPE)
243endfunction()
244
245# This function writes a dict to it's output parameter
246# 'return_dict'. The dict has information about the parsed arguments,
247#
248# Usage:
249# aml_get_parse_args(foo ${ARGN})
250# print(foo_STRIP_PREFIX) # foo_STRIP_PREFIX might be set to 1
251function(aml_get_parse_args return_dict)
252 foreach(x ${ARGN})
253 if(x STREQUAL STRIP_PREFIX)
254 set(${return_dict}_STRIP_PREFIX 1 PARENT_SCOPE)
255 endif()
256 endforeach()
257endfunction()
258
259function(process_flags lang input output)
260 # The flags might contains compile language generator expressions that
261 # look like this:
262 # $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
263 #
264 # Flags that don't specify a language like this apply to all
265 # languages.
266 #
267 # See COMPILE_LANGUAGE in
268 # https://cmake.org/cmake/help/v3.3/manual/cmake-generator-expressions.7.html
269 #
270 # To deal with this, we apply a regex to extract the flag and also
271 # to find out if the language matches.
272 #
273 # If this doesn't work out we might need to ban the use of
274 # COMPILE_LANGUAGE and instead partition C, CXX, and ASM into
275 # different libraries
276 set(languages C CXX ASM)
277
278 set(tmp_list "")
279
280 foreach(flag ${${input}})
281 set(is_compile_lang_generator_expression 0)
282 foreach(l ${languages})
283 if(flag MATCHES "<COMPILE_LANGUAGE:${l}>:([^>]+)>")
284 set(is_compile_lang_generator_expression 1)
285 if(${l} STREQUAL ${lang})
286 list(APPEND tmp_list ${CMAKE_MATCH_1})
287 break()
288 endif()
289 endif()
290 endforeach()
291
292 if(NOT is_compile_lang_generator_expression)
293 list(APPEND tmp_list ${flag})
294 endif()
295 endforeach()
296
297 set(${output} ${tmp_list} PARENT_SCOPE)
298endfunction()
299
300function(convert_list_of_flags_to_string_of_flags ptr_list_of_flags string_of_flags)
301 # Convert the list to a string so we can do string replace
302 # operations on it and replace the ";" list separators with a
303 # whitespace so the flags are spaced out
304 string(REPLACE ";" " " locally_scoped_string_of_flags "${${ptr_list_of_flags}}")
305
306 # Set the output variable in the parent scope
307 set(${string_of_flags} ${locally_scoped_string_of_flags} PARENT_SCOPE)
308endfunction()
309
310macro(get_property_and_add_prefix result target property prefix)
311 aml_get_parse_args(args ${ARGN})
312
313 if(args_STRIP_PREFIX)
314 set(maybe_prefix "")
315 else()
316 set(maybe_prefix ${prefix})
317 endif()
318
319 get_property(target_property TARGET ${target} PROPERTY ${property})
320 foreach(x ${target_property})
321 list(APPEND ${result} ${maybe_prefix}${x})
322 endforeach()
323endmacro()
324
325# 1.2 aml_library_*
326#
327# Amlogic libraries use CMake's library concept and a set of
328# assumptions about how aml code is organized to cut down on
329# boilerplate code.
330#
331# A Amlogic library can be constructed by the function aml_library
332# or aml_library_named. The constructors create a CMake library
333# with a name accessible through the variable CURRENT_LIBRARY.
334#
335# The variable CURRENT_LIBRARY should seldomly be needed since
336# the aml libraries have methods that modify the libraries. These
337# methods have the signature: aml_library_<target-function>
338#
339# The methods are wrappers around the CMake target_* functions. See
340# https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html for
341# documentation on the underlying target_* functions.
342#
343# The methods modify the CMake target_* API to reduce boilerplate;
344# PRIVATE is assumed
345# The target is assumed to be CURRENT_LIBRARY
346#
347# When a flag that is given through the aml_* API conflicts with
348# the aml_library_* API then precedence will be given to the
349# aml_library_* API. In other words, local configuration overrides
350# global configuration.
351
352# Constructor with a directory-inferred name
353macro(aml_library)
354 aml_library_get_current_dir_lib_name(lib_name)
355 aml_library_named(${lib_name})
356endmacro()
357
bin.chen1a426d32021-10-13 10:52:36 +0800358# Constructor with an explicitly given name.
359macro(aml_library_named name)
360 # This is a macro because we need add_library() to be executed
361 # within the scope of the caller.
362 set(CURRENT_LIBRARY ${name})
363 add_library(${name} STATIC "")
364
365 aml_append_cmake_library(${name})
366
367 target_link_libraries(${name} PUBLIC aml_interface)
368endmacro()
369
bin.chen6427c932024-01-17 19:20:30 +0800370macro(redefine_file_macro)
371 get_target_property(source_files "${CURRENT_LIBRARY}" SOURCES)
372 foreach(sourcefile ${source_files})
373 get_property(defs SOURCE "${sourcefile}" PROPERTY COMPILE_DEFINITIONS)
374 get_filename_component(filepath "${sourcefile}" ABSOLUTE)
375 string(REPLACE ${PROJECT_SOURCE_DIR}/ "" relpath ${filepath})
376 list(APPEND defs "__FILE__=\"${relpath}\"")
377 set_property(SOURCE "${sourcefile}" PROPERTY COMPILE_DEFINITIONS ${defs})
378 endforeach()
379endmacro()
380
bin.chen1a426d32021-10-13 10:52:36 +0800381macro(aml_add_library)
382 STRING( REGEX REPLACE ".*/(.*)/.*" "\\1" LAYER ${CMAKE_CURRENT_SOURCE_DIR} )
383 STRING( REGEX REPLACE ".*/(.*)" "\\1" MODULE ${CMAKE_CURRENT_SOURCE_DIR} )
384
shijie.xiongf00d0fe2024-01-11 17:18:58 +0800385 if(LAYER STREQUAL ARCH AND MODULE STREQUAL SPLIT_ARCH_DIR)
386 STRING( REGEX REPLACE ".*/(.*)/.*/.*" "\\1" LAYER ${CMAKE_CURRENT_SOURCE_DIR} )
387 STRING( REGEX REPLACE ".*/(.*)/.*" "\\1" MODULE ${CMAKE_CURRENT_SOURCE_DIR} )
388 endif()
389
Kelvin Zhang9bcad3d2021-12-29 17:22:42 +0800390 set(CURRENT_LIBRARY_TYPE STATIC)
bin.chen1a426d32021-10-13 10:52:36 +0800391 set(CURRENT_LIBRARY ${LAYER}__${MODULE})
Kelvin Zhang9bcad3d2021-12-29 17:22:42 +0800392 message(STATUS "@@${CURRENT_LIBRARY_TYPE}: ${CURRENT_LIBRARY}")
393 add_library(${CURRENT_LIBRARY} ${CURRENT_LIBRARY_TYPE} "")
xiaohu.huang50acd142022-05-16 13:52:56 +0800394
395 set_target_properties(${CURRENT_LIBRARY} PROPERTIES LIBRARY_BASE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
396endmacro()
397
398macro(aml_add_library_spec CURRENT_LIBRARY CURRENT_LIBRARY_TYPE)
399 add_library(${CURRENT_LIBRARY} ${CURRENT_LIBRARY_TYPE} "")
400 set_target_properties(${CURRENT_LIBRARY} PROPERTIES LIBRARY_BASE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
bin.chen1a426d32021-10-13 10:52:36 +0800401endmacro()
402
403macro(aml_add_interface)
404 STRING( REGEX REPLACE ".*/(.*)/.*" "\\1" LAYER ${CMAKE_CURRENT_SOURCE_DIR} )
405 STRING( REGEX REPLACE ".*/(.*)" "\\1" MODULE ${CMAKE_CURRENT_SOURCE_DIR} )
406
Kelvin Zhang9bcad3d2021-12-29 17:22:42 +0800407 set(CURRENT_INTERFACE_TYPE INTERFACE)
bin.chen1a426d32021-10-13 10:52:36 +0800408 set(CURRENT_INTERFACE ${LAYER}__${MODULE})
Kelvin Zhang9bcad3d2021-12-29 17:22:42 +0800409 message(STATUS "@@${CURRENT_INTERFACE_TYPE}: ${CURRENT_INTERFACE}")
410 add_library(${CURRENT_INTERFACE} ${CURRENT_INTERFACE_TYPE})
bin.chen1a426d32021-10-13 10:52:36 +0800411endmacro()
412
413function(aml_link_interface interface)
414 target_link_libraries(${interface} INTERFACE aml_interface)
415endfunction()
416
417#
418# aml_library versions of normal CMake target_<func> functions
419#
420function(aml_library_sources source)
xiaohu.huang50acd142022-05-16 13:52:56 +0800421 #remove the base dir if the source is a full path
422 string(REPLACE "${CMAKE_CURRENT_LIST_DIR}/" "" source ${source})
423 #calculate the obj output full path
424 set(FILE_NAME "${source}.obj")
425 get_target_property(LIBRARY_BASE_PATH ${CURRENT_LIBRARY} LIBRARY_BASE_PATH)
426 string(REPLACE ${LIBRARY_BASE_PATH} "${LIBRARY_BASE_PATH}/CMakeFiles/${CURRENT_LIBRARY}.dir"
427 OBJ_OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
428 string(REPLACE ${PROJECT_SOURCE_DIR} "${PROJECT_SOURCE_DIR}/output/$ENV{ARCH}-$ENV{BOARD}-$ENV{PRODUCT}/$ENV{KERNEL}/obj"
429 OBJ_OUTPUT_DIR ${OBJ_OUTPUT_DIR})
430 set(OBJ_OUTPUT_PATH "${OBJ_OUTPUT_DIR}/${FILE_NAME}")
431 #collect the obj output full path to COLLECT_LINK_OBJS
432 set(COLLECT_LINK_OBJS ${OBJ_OUTPUT_PATH} ${COLLECT_LINK_OBJS} CACHE INTERNAL "")
433
434 FOREACH(PART_PATH ${ARGN})
435 string(REPLACE "${CMAKE_CURRENT_LIST_DIR}/" "" PART_PATH ${PART_PATH})
436 set(FILE_NAME "${PART_PATH}.obj")
437 set(OBJ_OUTPUT_PATH "${OBJ_OUTPUT_DIR}/${FILE_NAME}")
xiaohu.huang33a5ff52022-11-03 11:30:02 +0800438 #if the obj is exist in collection,ignore it
439 string(FIND "${COLLECT_LINK_OBJS}" "${OBJ_OUTPUT_PATH}" ret)
440 if(${ret} STREQUAL "-1")
441 set(COLLECT_LINK_OBJS ${OBJ_OUTPUT_PATH} ${COLLECT_LINK_OBJS} CACHE INTERNAL "")
442 endif()
xiaohu.huang50acd142022-05-16 13:52:56 +0800443 ENDFOREACH(PART_PATH)
444
445 target_sources(${CURRENT_LIBRARY} PRIVATE ${source} ${ARGN})
bin.chen1a426d32021-10-13 10:52:36 +0800446endfunction()
447
448function(aml_library_include_directories)
449 target_include_directories(${CURRENT_LIBRARY} PUBLIC ${ARGN})
450endfunction()
451
xiaohu.huange74966d2022-09-16 23:32:07 +0800452function(aml_library_include_directories_ifdef feature_toggle)
453if(${${feature_toggle}})
454 target_include_directories(${CURRENT_LIBRARY} PUBLIC ${ARGN})
455endif()
456endfunction()
457
bin.chen1a426d32021-10-13 10:52:36 +0800458function(aml_interface_include_directories)
459 target_include_directories(${CURRENT_INTERFACE} INTERFACE ${ARGN})
460endfunction()
461
462function(aml_library_link_libraries item)
463 target_link_libraries(${CURRENT_LIBRARY} PUBLIC ${item} ${ARGN})
464endfunction()
465
466function(aml_interface_link_interfaces item)
467 target_link_libraries(${CURRENT_INTERFACE} INTERFACE ${item} ${ARGN})
468endfunction()
469
470function(aml_library_compile_definitions item)
471 target_compile_definitions(${CURRENT_LIBRARY} PRIVATE ${item} ${ARGN})
472endfunction()
473
474function(aml_library_compile_options item)
475 # The compiler is relied upon for sane behaviour when flags are in
476 # conflict. Compilers generally give precedence to flags given late
477 # on the command line. So to ensure that aml_library_* flags are
478 # placed late on the command line we create a dummy interface
479 # library and link with it to obtain the flags.
480 #
481 # Linking with a dummy interface library will place flags later on
482 # the command line than the the flags from aml_interface because
483 # aml_interface will be the first interface library that flags
484 # are taken from.
485
486 string(MD5 uniqueness ${item})
487 set(lib_name options_interface_lib_${uniqueness})
488
489 if (TARGET ${lib_name})
490 # ${item} already added, ignoring duplicate just like CMake does
491 return()
492 endif()
493
494 add_library( ${lib_name} INTERFACE)
495 target_compile_options(${lib_name} INTERFACE ${item} ${ARGN})
496
497 target_link_libraries(${CURRENT_LIBRARY} PRIVATE ${lib_name})
498endfunction()
499
500function(aml_library_cc_option)
501 foreach(option ${ARGV})
502 string(MAKE_C_IDENTIFIER check${option} check)
503 aml_check_compiler_flag(C ${option} ${check})
504
505 if(${check})
506 aml_library_compile_options(${option})
507 endif()
508 endforeach()
509endfunction()
510
bin.chen1a426d32021-10-13 10:52:36 +0800511# 1.2.1 aml_interface_library_*
bin.chen1a426d32021-10-13 10:52:36 +0800512
513# 1.3 generate_inc_*
514
bin.chen1a426d32021-10-13 10:52:36 +0800515# 1.4. board_*
516
517# 1.5. Misc.
518
bin.chen1a426d32021-10-13 10:52:36 +0800519########################################################
520# 2. Kconfig-aware extensions
521########################################################
522#
523# Kconfig is a configuration language developed for the Linux
524# kernel. The below functions integrate CMake with Kconfig.
525#
526# 2.1 *_if_kconfig
527#
528# Functions for conditionally including directories and source files
529# that have matching KConfig values.
530#
531# aml_library_sources_if_kconfig(fft.c)
532# is the same as
533# aml_library_sources_ifdef(CONFIG_FFT fft.c)
534#
535# add_subdirectory_if_kconfig(serial)
536# is the same as
537# add_subdirectory_ifdef(CONFIG_SERIAL serial)
538function(add_subdirectory_if_kconfig dir)
539 string(TOUPPER config_${dir} UPPER_CASE_CONFIG)
540 add_subdirectory_ifdef(${UPPER_CASE_CONFIG} ${dir})
541endfunction()
542
543function(target_sources_if_kconfig target scope item)
544 get_filename_component(item_basename ${item} NAME_WE)
545 string(TOUPPER CONFIG_${item_basename} UPPER_CASE_CONFIG)
546 target_sources_ifdef(${UPPER_CASE_CONFIG} ${target} ${scope} ${item})
547endfunction()
548
549function(aml_library_sources_if_kconfig item)
550 get_filename_component(item_basename ${item} NAME_WE)
551 string(TOUPPER CONFIG_${item_basename} UPPER_CASE_CONFIG)
552 aml_library_sources_ifdef(${UPPER_CASE_CONFIG} ${item})
553endfunction()
554
555function(aml_sources_if_kconfig item)
556 get_filename_component(item_basename ${item} NAME_WE)
557 string(TOUPPER CONFIG_${item_basename} UPPER_CASE_CONFIG)
558 aml_sources_ifdef(${UPPER_CASE_CONFIG} ${item})
559endfunction()
560
561# 2.2 Misc
562#
563# Parse a KConfig fragment (typically with extension .config) and
564# introduce all the symbols that are prefixed with 'prefix' into the
565# CMake namespace
566function(import_kconfig prefix kconfig_fragment)
567 # Parse the lines prefixed with 'prefix' in ${kconfig_fragment}
568 file(
569 STRINGS
570 ${kconfig_fragment}
571 DOT_CONFIG_LIST
572 REGEX "^${prefix}"
573 ENCODING "UTF-8"
574 )
575
576 foreach (CONFIG ${DOT_CONFIG_LIST})
577 # CONFIG could look like: CONFIG_NET_BUF=y
578
579 # Match the first part, the variable name
580 string(REGEX MATCH "[^=]+" CONF_VARIABLE_NAME ${CONFIG})
581
582 # Match the second part, variable value
583 string(REGEX MATCH "=(.+$)" CONF_VARIABLE_VALUE ${CONFIG})
584 # The variable name match we just did included the '=' symbol. To just get the
585 # part on the RHS we use match group 1
586 set(CONF_VARIABLE_VALUE ${CMAKE_MATCH_1})
587
588 if("${CONF_VARIABLE_VALUE}" MATCHES "^\"(.*)\"$") # Is surrounded by quotes
589 set(CONF_VARIABLE_VALUE ${CMAKE_MATCH_1})
590 endif()
591
592 set("${CONF_VARIABLE_NAME}" "${CONF_VARIABLE_VALUE}" PARENT_SCOPE)
593 endforeach()
594endfunction()
595
596########################################################
597# 3. CMake-generic extensions
598########################################################
599#
600# These functions extend the CMake API in a way that is not particular
601# to Amlogic. Primarily they work around limitations in the CMake
602# language to allow cleaner build scripts.
603
604# 3.1. *_ifdef
605#
606# Functions for conditionally executing CMake functions with oneliners
607# e.g.
608#
609# if(CONFIG_FFT)
610# aml_library_source(
611# fft_32.c
612# fft_utils.c
613# )
614# endif()
615#
616# Becomes
617#
618# aml_source_ifdef(
619# CONFIG_FFT
620# fft_32.c
621# fft_utils.c
622# )
623#
624# More Generally
625# "<function-name>_ifdef(CONDITION args)"
626# Becomes
627# """
628# if(CONDITION)
629# <function-name>(args)
630# endif()
631# """
632#
633# ifdef functions are added on an as-need basis. See
634# https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html for
635# a list of available functions.
636function(add_subdirectory_ifdef feature_toggle dir)
637 if(${${feature_toggle}})
638 add_subdirectory(${dir})
639 endif()
640endfunction()
641
642function(target_sources_ifdef feature_toggle target scope item)
643 if(${${feature_toggle}})
644 target_sources(${target} ${scope} ${item} ${ARGN})
645 endif()
646endfunction()
647
648function(target_compile_definitions_ifdef feature_toggle target scope item)
649 if(${${feature_toggle}})
650 target_compile_definitions(${target} ${scope} ${item} ${ARGN})
651 endif()
652endfunction()
653
654function(target_include_directories_ifdef feature_toggle target scope item)
655 if(${${feature_toggle}})
656 target_include_directories(${target} ${scope} ${item} ${ARGN})
657 endif()
658endfunction()
659
660function(target_link_libraries_ifdef feature_toggle target item)
661 if(${${feature_toggle}})
662 target_link_libraries(${target} ${item} ${ARGN})
663 endif()
664endfunction()
665
666function(add_compile_option_ifdef feature_toggle option)
667 if(${${feature_toggle}})
668 add_compile_options(${option})
669 endif()
670endfunction()
671
672function(target_compile_option_ifdef feature_toggle target scope option)
673 if(${feature_toggle})
674 target_compile_options(${target} ${scope} ${option})
675 endif()
676endfunction()
677
678function(target_cc_option_ifdef feature_toggle target scope option)
679 if(${feature_toggle})
680 target_cc_option(${target} ${scope} ${option})
681 endif()
682endfunction()
683
684function(aml_library_sources_ifdef feature_toggle source)
685 if(${${feature_toggle}})
686 aml_library_sources(${source} ${ARGN})
687 endif()
688endfunction()
689
Dongjin Kim04002a32025-04-01 12:45:15 +0900690function(aml_library_sources_ifndef feature_toggle source)
691 if(NOT ${feature_toggle})
692 aml_library_sources(${source} ${ARGN})
693 endif()
694endfunction()
695
bin.chen1a426d32021-10-13 10:52:36 +0800696function(aml_sources_ifdef feature_toggle)
697 if(${${feature_toggle}})
698 aml_sources(${ARGN})
699 endif()
700endfunction()
701
702function(aml_sources_ifndef feature_toggle)
703 if(NOT ${feature_toggle})
704 aml_sources(${ARGN})
705 endif()
706endfunction()
707
708function(aml_cc_option_ifdef feature_toggle)
709 if(${${feature_toggle}})
710 aml_cc_option(${ARGN})
711 endif()
712endfunction()
713
714function(aml_ld_option_ifdef feature_toggle)
715 if(${${feature_toggle}})
716 aml_ld_options(${ARGN})
717 endif()
718endfunction()
719
720function(aml_link_libraries_ifdef feature_toggle)
721 if(${${feature_toggle}})
722 aml_link_libraries(${ARGN})
723 endif()
724endfunction()
725
726function(aml_compile_options_ifdef feature_toggle)
727 if(${${feature_toggle}})
728 aml_compile_options(${ARGN})
729 endif()
730endfunction()
731
732function(aml_compile_definitions_ifdef feature_toggle)
733 if(${${feature_toggle}})
734 aml_compile_definitions(${ARGN})
735 endif()
736endfunction()
737
738function(aml_include_directories_ifdef feature_toggle)
739 if(${${feature_toggle}})
740 aml_include_directories(${ARGN})
741 endif()
742endfunction()
743
744function(aml_library_compile_definitions_ifdef feature_toggle item)
745 if(${${feature_toggle}})
746 aml_library_compile_definitions(${item} ${ARGN})
747 endif()
748endfunction()
749
750function(aml_library_compile_options_ifdef feature_toggle item)
751 if(${${feature_toggle}})
752 aml_library_compile_options(${item} ${ARGN})
753 endif()
754endfunction()
755
756function(aml_link_interface_ifdef feature_toggle interface)
757 if(${${feature_toggle}})
758 target_link_libraries(${interface} INTERFACE aml_interface)
759 endif()
760endfunction()
761
762function(aml_library_link_libraries_ifdef feature_toggle item)
763 if(${${feature_toggle}})
764 aml_library_link_libraries(${item})
765 endif()
766endfunction()
767
768macro(list_append_ifdef feature_toggle list)
769 if(${${feature_toggle}})
770 list(APPEND ${list} ${ARGN})
771 endif()
772endmacro()
773
bin.chen1a426d32021-10-13 10:52:36 +0800774# 3.4. Debugging CMake
775
776# Usage:
777# print(BOARD)
778#
779# will print: "BOARD: nrf52_pca10040"
780function(print arg)
781 message(STATUS "${arg}: ${${arg}}")
782endfunction()
783
bin.chen1a426d32021-10-13 10:52:36 +0800784# will cause a FATAL_ERROR and print an error message if the first
785# expression is false
786macro(assert test comment)
787 if(NOT ${test})
788 message(FATAL_ERROR "Assertion failed: ${comment}")
789 endif()
790endmacro()
791
792# Usage:
793# assert_not(FLASH_SCRIPT "FLASH_SCRIPT has been removed; use BOARD_FLASH_RUNNER")
794#
795# will cause a FATAL_ERROR and print an errorm essage if the first
796# espression is true
797macro(assert_not test comment)
798 if(${test})
799 message(FATAL_ERROR "Assertion failed: ${comment}")
800 endif()
801endmacro()
802
803# Usage:
804# assert_exists(CMAKE_READELF)
805#
806# will cause a FATAL_ERROR if there is no file or directory behind the
807# variable
808macro(assert_exists var)
809 if(NOT EXISTS ${${var}})
810 message(FATAL_ERROR "No such file or directory: ${var}: '${${var}}'")
811 endif()
812endmacro()
813
xiaohu.huang616e6992024-06-26 15:45:49 +0800814# 3.5. extend files management
bin.chen1a426d32021-10-13 10:52:36 +0800815function(compiler_generate_binary_output TARGET)
816 add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_OBJCOPY_COMPILER} ARGS -O binary $<TARGET_FILE:${TARGET}> $<TARGET_FILE_DIR:${TARGET}>/$ENV{KERNEL}.bin)
817endfunction()
818
xiaohu.huang616e6992024-06-26 15:45:49 +0800819function(compiler_generate_lst_output TARGET)
820 #Generate disassembly file intermix source code
821 #llvm-objdump -S will warning can't find source file which in the prebuilt library,
822 #then use 2>/dev/null to ignore standard error output
823 add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_OBJDUMP_COMPILER} ARGS -S $<TARGET_FILE:${TARGET}> > $<TARGET_FILE_DIR:${TARGET}>/$ENV{KERNEL}.lst 2>/dev/null)
bin.chen1a426d32021-10-13 10:52:36 +0800824endfunction()
xiaohu.huang50acd142022-05-16 13:52:56 +0800825
xiaohu.huang8619de92022-11-01 18:02:58 +0800826function(generate_module_info_output TARGET)
bin.chenfe62a522024-03-05 16:19:25 +0800827 set(map_file_path ${PROJECT_SOURCE_DIR}/output/$ENV{ARCH}-$ENV{BOARD}-$ENV{PRODUCT}/$ENV{KERNEL}/${TARGET_NAME}.map)
xiaohu.huang616e6992024-06-26 15:45:49 +0800828 add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND COMPILER=$ENV{COMPILER} ARCH=$ENV{ARCH} ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/map_analyzer_$ENV{COMPILER}.py --combine ${map_file_path} > $<TARGET_FILE_DIR:${TARGET}>/$ENV{KERNEL}_module_info.txt)
xiaohu.huang8619de92022-11-01 18:02:58 +0800829endfunction()
830