Skip to content
This repository was archived by the owner on Apr 17, 2023. It is now read-only.

Commit 67307b6

Browse files
authored
Merge pull request #38 from arduino-cmake/feature/lib-refactor
Applied library-centric refactoring
2 parents ed09635 + f4ab16c commit 67307b6

19 files changed

+578
-242
lines changed

cmake/Platform/Arduino.cmake

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,20 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/Other)
66
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/Properties)
77
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/Sketches)
88
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/Sources)
9+
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/Libraries)
910
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/Targets)
1011

11-
include(MathUtils)
12-
include(ListUtils)
13-
include(StringUtils)
14-
include(PropertyUtils)
15-
include(PlatformLibraryUtils)
12+
include(Utilities)
1613

1714
include(BoardManager)
1815
include(RecipeParser)
1916
include(TargetFlagsManager)
2017
include(SourcesManager)
2118
include(SketchManager)
2219
include(DefaultsManager)
20+
include(ArchitectureSupportQuery)
21+
22+
include(Libraries)
2323

2424
include(BuildSystemInitializer)
2525

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
include(LibraryArchitectureParser)
2+
include(LibrarySourcesArchitectureResolver)
3+
include(LibraryFlagsManager)
4+
include(LibrariesFinder)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#=============================================================================#
2+
# Finds an Arduino library with the given library name and creates a library target from it
3+
# with the given target name.
4+
# The search process also resolves library's architecture to check if it even can be built
5+
# using the current platform architecture.
6+
# _target_name - Name of the library target to be created. Usually library's real name.
7+
# _library_name - Name of the Arduino library to find.
8+
# _board_id - Board ID associated with the linked Core Lib.
9+
# [3RD_PARTY] - Whether library should be treated as a 3rd Party library.
10+
#=============================================================================#
11+
function(find_arduino_library _target_name _library_name _board_id)
12+
13+
set(argument_options "3RD_PARTY" "HEADER_ONLY")
14+
cmake_parse_arguments(parsed_args "${argument_options}" "" "" ${ARGN})
15+
16+
if (NOT parsed_args_3RD_PARTY)
17+
convert_string_to_pascal_case(${_library_name} _library_name)
18+
endif ()
19+
20+
find_file(library_properties_file library.properties
21+
PATHS ${ARDUINO_SDK_LIBRARIES_PATH} ${ARDUINO_CMAKE_SKETCHBOOK_PATH}/libraries
22+
PATH_SUFFIXES ${_library_name}
23+
NO_DEFAULT_PATH
24+
NO_CMAKE_FIND_ROOT_PATH)
25+
26+
if (${library_properties_file} MATCHES "NOTFOUND")
27+
message(SEND_ERROR "Couldn't find library named ${_library_name}")
28+
else () # Library is found
29+
30+
get_filename_component(library_path ${library_properties_file} DIRECTORY)
31+
32+
find_library_header_files("${library_path}" library_headers)
33+
34+
if (NOT library_headers)
35+
message(SEND_ERROR "Couldn't find any header files for the ${_library_name} library")
36+
else ()
37+
38+
if (parsed_args_HEADER_ONLY)
39+
add_arduino_header_only_library(${_target_name} ${_board_id} ${library_headers})
40+
41+
else ()
42+
43+
find_library_source_files("${library_path}" library_sources)
44+
45+
if (NOT library_sources)
46+
message(SEND_ERROR "Couldn't find any source files for the "
47+
"${_library_name} library - Is it a header-only library?"
48+
"If so, please pass the HEADER_ONLY option "
49+
"as an argument to the function")
50+
else ()
51+
set(sources ${library_headers} ${library_sources})
52+
53+
add_arduino_library(${_target_name} ${_board_id}
54+
LIB_PROPS_FILE ${library_properties_file}
55+
${sources})
56+
endif ()
57+
58+
endif ()
59+
endif ()
60+
endif ()
61+
62+
unset(library_properties_file CACHE)
63+
64+
endfunction()
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#=============================================================================#
2+
# Gets a list of architectures supported by a library.
3+
# The list is read from the given properties file, which includes metadata about the library.
4+
# _library_properties_file - Full path to a library's properties file
5+
# (usually named 'library,propertie').
6+
# _return_var - Name of variable in parent-scope holding the return value.
7+
# Returns - List of architectures supported by the library or '*'
8+
# if it's architecture-agnostic (Supports all arhcitectures).
9+
#=============================================================================#
10+
function(get_arduino_library_supported_architectures _library_properties_file _return_var)
11+
12+
file(STRINGS ${_library_properties_file} library_properties)
13+
14+
list(FILTER library_properties INCLUDE REGEX "arch")
15+
16+
_get_property_value("${library_properties}" _library_arch_list)
17+
18+
string(REPLACE "," ";" _library_arch_list ${_library_arch_list}) # Turn into a valid list
19+
20+
set(${_return_var} ${_library_arch_list} PARENT_SCOPE)
21+
22+
endfunction()
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#=============================================================================#
2+
# Sets compiler and linker flags on the given library target.
3+
# Changes are kept even outside the scope of the function since they apply on a target.
4+
# _library_target - Name of the library target.
5+
# _board_id - Board ID associated with the library. Some flags require it.
6+
#=============================================================================#
7+
function(set_library_flags _library_target _board_id)
8+
9+
parse_scope_argument(scope "${ARGN}"
10+
DEFAULT_SCOPE PUBLIC)
11+
12+
# Set C++ compiler flags
13+
get_cmake_compliant_language_name(cpp flags_language)
14+
set_compiler_target_flags(${_library_target} "${_board_id}" ${scope} LANGUAGE ${flags_language})
15+
16+
# Set linker flags
17+
set_linker_flags(${_library_target} "${_board_id}")
18+
19+
endfunction()
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#=============================================================================#
2+
# Filters sources that relate to an architecture from the given list of unsupported architectures.
3+
# _unsupported_archs_regex - List of unsupported architectures as a regex-pattern string.
4+
# _sources - List of sources to check and potentially filter.
5+
# _return_var - Name of variable in parent-scope holding the return value.
6+
# Returns - Filtered list of sources containing only those that don't relate to
7+
# any unsupported architecture.
8+
#=============================================================================#
9+
function(_filter_unsupported_arch_sources _unsupported_archs_regex _sources _return_var)
10+
11+
if (NOT "${_unsupported_archs_regex}" STREQUAL "") # Not all architectures are supported
12+
# Filter sources dependant on unsupported architectures
13+
list(FILTER _sources EXCLUDE REGEX ${_unsupported_archs_regex})
14+
endif ()
15+
16+
set(${_return_var} ${_sources} PARENT_SCOPE)
17+
18+
endfunction()
19+
20+
#=============================================================================#
21+
# Resolves library's architecture-related elements by doing several things:
22+
# 1. Checking whether the platform's architecture is supported by the library
23+
# 2. Filtering out any library sources that relate to unsupported architectures, i.e
24+
# architectures other than the platform's.
25+
# If the platform's architecture isn't supported by the library, CMake generates an error and stops.
26+
# _library_sources - List of library's sources to check and potentially filter.
27+
# [LIB_PROPS_FILE] - Full path to the library's properties file. Optional.
28+
# _return_var - Name of variable in parent-scope holding the return value.
29+
# Returns - Filtered list of sources containing only those that don't relate to
30+
# any unsupported architecture.
31+
#=============================================================================#
32+
function(resolve_library_architecture _library_sources _return_var)
33+
34+
cmake_parse_arguments(parsed_args "" "LIB_PROPS_FILE" "" ${ARGN})
35+
36+
if (parsed_args_LIB_PROPS_FILE) # Library properties file is given
37+
set(lib_props_file ${parsed_args_LIB_PROPS_FILE})
38+
else ()
39+
40+
# Warn user and assume library is arch-agnostic
41+
message(STATUS "Library's properties file can't be found "
42+
"under its' root directory - Assuming the library "
43+
"is architecture-agnostic (supports all architectures)")
44+
set(${_return_var} "${_library_sources}" PARENT_SCOPE)
45+
return()
46+
47+
endif ()
48+
49+
get_arduino_library_supported_architectures("${lib_props_file}" lib_archs)
50+
51+
# Check if the platform's architecture is supported by the library
52+
is_platform_architecture_supported(${lib_archs} arch_supported_by_lib)
53+
54+
if (NOT ${arch_supported_by_lib})
55+
message(SEND_ERROR "The platform's architecture, ${ARDUINO_CMAKE_PLATFORM_ARCHITECTURE}, "
56+
"isn't supported by the ${_library_name} library")
57+
endif ()
58+
59+
get_unsupported_architectures("${lib_archs}" unsupported_archs REGEX)
60+
61+
# Filter any sources that aren't supported by the platform's architecture
62+
_filter_unsupported_arch_sources("${unsupported_archs}" "${_library_sources}" valid_sources)
63+
64+
set(${_return_var} "${valid_sources}" PARENT_SCOPE)
65+
66+
endfunction()
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#=============================================================================#
2+
# Checks whether the platform's architecture is supported in the context of the given list
3+
# of architectures, i.e If the list contains the platform's architecture.
4+
# _arch_list - List of architectures supported by the library,
5+
# inferred from its' 'library.properties' file.
6+
# _return_var - Name of variable in parent-scope holding the return value.
7+
# Returns - True if supported, false otherwise.
8+
#=============================================================================#
9+
function(is_platform_architecture_supported _arch_list _return_var)
10+
11+
if ("${_arch_list}" MATCHES "\\*") # Any architecture is supported
12+
set(result TRUE)
13+
else ()
14+
if (${ARDUINO_CMAKE_PLATFORM_ARCHITECTURE} IN_LIST _arch_list)
15+
set(result TRUE) # Our platform's arch is supported
16+
else ()
17+
set(result FALSE) # Our arch isn't supported
18+
endif ()
19+
endif ()
20+
21+
set(${_return_var} ${result} PARENT_SCOPE)
22+
23+
endfunction()
24+
25+
#=============================================================================#
26+
# Gets a filtered list of architectures that aren't compliant with the platform's architecture.
27+
# e.g If a list contains 'avr' and 'nrf52', while our arch is 'avr', 'nrf52' will be returned.
28+
# _arch_list - List of all architectures probably read from a library's properties file
29+
# [REGEX] - Returns list in a regex-compatible mode, allowing caller to
30+
# use result in search patterns. This is currently the only supported mode.
31+
# _return_var - Name of variable in parent-scope holding the return value.
32+
# Returns - Filtered list of architectures.
33+
#=============================================================================#
34+
function(get_unsupported_architectures _arch_list _return_var)
35+
36+
cmake_parse_arguments(parsed_args "REGEX" "" "" ${ARGN})
37+
38+
if ("${_arch_list}" MATCHES "\\*") # All architectures are supported, return nothing
39+
return()
40+
endif ()
41+
42+
list(FILTER _arch_list EXCLUDE REGEX ${ARDUINO_CMAKE_PLATFORM_ARCHITECTURE})
43+
set(unsupported_arch_list ${_arch_list}) # Just for better readability
44+
45+
if (parsed_args_REGEX) # Return in regex format
46+
47+
foreach (arch ${unsupported_arch_list})
48+
# Append every unsupported-architecture and "|" to represent "or" in regex-fomart
49+
string(APPEND unsupported_archs_regex "${arch}" "|")
50+
endforeach ()
51+
52+
# Remove last "|" as it's unnecessary - There's no element after it
53+
string(LENGTH ${unsupported_archs_regex} str_len)
54+
decrement_integer(str_len 1) # Decrement string's length by 1 to trim last char ('|')
55+
string(SUBSTRING ${unsupported_archs_regex} 0 ${str_len} unsupported_archs_regex)
56+
57+
# prepare for generalized function return
58+
set(unsupported_arch_list ${unsupported_archs_regex})
59+
60+
endif ()
61+
62+
set(${_return_var} ${unsupported_arch_list} PARENT_SCOPE)
63+
64+
endfunction()

cmake/Platform/Other/TargetFlagsManager.cmake

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,24 @@
55
#=============================================================================#
66
function(set_compiler_target_flags _target_name _board_id)
77

8-
set(option_args PRIVATE PUBLIC INTERFACE)
9-
set(single_args LANGUAGE)
10-
cmake_parse_arguments(compiler "${option_args}" "${single_args}" "" ${ARGN})
11-
12-
if (compiler_LANGUAGE)
13-
if (compiler_PRIVATE)
14-
set(scope PRIVATE)
15-
elseif (compiler_INTERFACE)
16-
set(scope INTERFACE)
17-
else ()
18-
set(scope PUBLIC)
19-
endif ()
8+
cmake_parse_arguments(parsed_args "" "LANGUAGE" "" ${ARGN})
9+
parse_scope_argument(scope "${ARGN}"
10+
DEFAULT_SCOPE PUBLIC)
11+
12+
if (parsed_args_LANGUAGE)
13+
2014
parse_compiler_recipe_flags("${_board_id}" compiler_recipe_flags
21-
LANGUAGE "${compiler_LANGUAGE}")
15+
LANGUAGE "${parsed_args_LANGUAGE}")
16+
2217
target_compile_options(${_target_name} ${scope}
23-
$<$<COMPILE_LANGUAGE:${compiler_LANGUAGE}>:${compiler_recipe_flags}>)
18+
$<$<COMPILE_LANGUAGE:${parsed_args_LANGUAGE}>:${compiler_recipe_flags}>)
19+
2420
else ()
21+
2522
parse_compiler_recipe_flags("${_board_id}" compiler_recipe_flags)
26-
target_compile_options(${_target_name} PUBLIC ${compiler_recipe_flags})
23+
24+
target_compile_options(${_target_name} ${scope} ${compiler_recipe_flags})
25+
2726
endif ()
2827

2928
endfunction()
@@ -36,7 +35,9 @@ endfunction()
3635
function(set_linker_flags _target_name _board_id)
3736

3837
parse_linker_recpie_pattern("${_board_id}" linker_recipe_flags)
38+
3939
string(REPLACE ";" " " cmake_compliant_linker_flags "${linker_recipe_flags}")
40+
4041
set(CMAKE_EXE_LINKER_FLAGS "${cmake_compliant_linker_flags}" CACHE STRING "" FORCE)
4142

4243
endfunction()
@@ -81,3 +82,18 @@ function(set_upload_target_flags _target_name _board_id _upload_port _return_var
8182

8283
endfunction()
8384

85+
#=============================================================================#
86+
# Adds a compiler definition (#define) for the given architecture to the target.
87+
# The affecting scope of the definition is controlled by the _scope argument.
88+
# _target - Name of the target (Executable) to set flags on.
89+
# _scope - PUBLIC|INTERFACE|PRIVATE. Affects outer scope - How other targets see it.
90+
# _architecture - Architecture to define, e.g. 'avr'
91+
#=============================================================================#
92+
function(set_target_architecture_definition _target _scope _architecture)
93+
94+
string(TOUPPER ${_architecture} upper_arch)
95+
set(arch_definition "ARDUINO_ARCH_${upper_arch}")
96+
97+
target_compile_definitions(${_target} ${_scope} ${arch_definition})
98+
99+
endfunction()

cmake/Platform/System/DefaultsManager.cmake

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ function(set_default_arduino_cmake_options)
5757

5858
endfunction()
5959

60+
function(set_default_paths)
61+
62+
set(ARDUINO_CMAKE_LIBRARY_PROPERTIES_FILE_NAME "library.properties" CACHE STRING
63+
"Name of the libraries' properties file")
64+
65+
endfunction()
66+
6067
#=============================================================================#
6168
# Sets various defaults used throughout the platform.
6269
#=============================================================================#
@@ -65,5 +72,6 @@ function(set_arduino_cmake_defaults)
6572
set_internal_search_patterns()
6673
set_source_files_patterns()
6774
set_default_arduino_cmake_options()
75+
set_default_paths()
6876

6977
endfunction()

0 commit comments

Comments
 (0)