blob: 61121b006144eb5c805e3cc9da847978e729542f [file] [log] [blame]
Chris Brand19bf2742022-07-05 11:15:17 -07001#-------------------------------------------------------------------------------
Anton Komlev1e775502025-04-25 16:37:55 +01002# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors#
Chris Brand19bf2742022-07-05 11:15:17 -07003#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
8include(FetchContent)
9set(FETCHCONTENT_QUIET FALSE)
10
11find_package(Git)
12
Chris Brand19bf2742022-07-05 11:15:17 -070013# This function helps to handle options with an empty string values.
14# There is a feature/bug in CMake that result in problem with the empty string arguments.
15# See https://gitlab.kitware.com/cmake/cmake/-/issues/16341 for details
16#
17# Arguments:
18# [in] KEY - option name
19# [out] KEY_VAR - name of variable that is set to ${KEY} on exit if value is not
20# an empty string otherwise to the empty string.
21# [out] VALUE_VAR - name of variable that is set to option value for ${KEY}.
22# [in/out] ARG_LIST_VAR - name of variable that holds list of key/value pairs - arguments.
23# Function looks for key/value pair specified by ${KEY} variable in
24# this list. Function removes key/value pair specified by ${KEY} on
25# exit.
26#
27# Example #1:
28# # We have following key/options:
29# # GIT_SUBMODULES ""
30# # BOO "abc"
31# # HEY "hi"
32# set(ARGS GIT_SUBMODULES "" BOO "abc" HEY "hi")
33# # Extract key/value for option "GIT_SUBMODULES"
34# extract_key_value(GIT_SUBMODULES GIT_SUBMODULES_VAR GIT_SUBMODULES_VALUE_VAR ARGS)
35# # ${GIT_SUBMODULES_VAR} is equal to ""
36# # ${GIT_SUBMODULES_VALUE_VAR} is equal to ""
37#
38# Example #2:
39# # We have following key/options:
40# # GIT_SUBMODULES "name"
41# # BOO "abc"
42# # HEY "hi"
43# set(ARGS GIT_SUBMODULES "name" BOO "abc" HEY "hi")
44# # Extract key/value for option "GIT_SUBMODULES"
45# extract_key_value(GIT_SUBMODULES GIT_SUBMODULES_VAR GIT_SUBMODULES_VALUE_VAR ARGS)
46# # ${GIT_SUBMODULES_VAR} is equal to "GIT_SUBMODULES"
47# # ${GIT_SUBMODULES_VALUE_VAR} is equal to "name"
48function(extract_key_value KEY KEY_VAR VALUE_VAR ARG_LIST_VAR)
49 list(FIND ${ARG_LIST_VAR} ${KEY} KEY_INDEX)
50 if(${KEY_INDEX} GREATER_EQUAL 0)
51 # Variable has been set, remove KEY
52 list(REMOVE_AT ${ARG_LIST_VAR} ${KEY_INDEX})
53
54 # Validate that there is an option value in the list of arguments
55 list(LENGTH ${ARG_LIST_VAR} ARG_LIST_LENGTH)
56 if(${KEY_INDEX} GREATER_EQUAL ${ARG_LIST_LENGTH})
57 message(FATAL_ERROR "Missing option value for ${KEY}")
58 endif()
59
60 # Get value
61 list(GET ${ARG_LIST_VAR} ${KEY_INDEX} VALUE)
62
63 # Remove value in the list
64 list(REMOVE_AT ${ARG_LIST_VAR} ${KEY_INDEX})
65
66 # Update argument list
67 set(${ARG_LIST_VAR} ${${ARG_LIST_VAR}} PARENT_SCOPE)
68
69 # Set KEY_VAR & VALUE_VAR
70 set(${KEY_VAR} ${KEY} PARENT_SCOPE)
71 set(${VALUE_VAR} ${VALUE} PARENT_SCOPE)
72 else()
73 # Variable is not defined, set KEY_VAR & VALUE_VAR to empty strings
74 set(${KEY_VAR} "" PARENT_SCOPE)
75 set(${VALUE_VAR} "" PARENT_SCOPE)
76 endif()
77endfunction()
78
79
80# This function allows to fetch library from a remote repository or use a local
81# library copy.
82#
83# You can specify location of directory with patches. Patches are applied in
84# alphabetical order.
85#
86# Arguments:
87# [in] LIB_NAME <name> - library name
88# [in/out] LIB_SOURCE_PATH_VAR <var> - name of variable which holds path to library source
89# or "DOWNLOAD" if sources should be fetched from the remote repository. This
90# variable is updated in case if library is downloaded. It will point
91# to the path where FetchContent_Populate will locate local library copy.
92# [out] LIB_BINARY_PATH_VAR <var> - optional name of variable which is updated to
93# directory intended for use as a corresponding build directory if
94# library is fetched from the remote repository.
95# [in] LIB_BASE_DIR <path> - is used to set FETCHCONTENT_BASE_DIR.
96# [in] LIB_PATCH_DIR <path> - optional path to local folder which contains patches
97# that should be applied.
Joakim Andersson083ebe42023-01-18 12:00:36 +010098# [in] LIB_FORCE_PATCH - optional argument to force applying patches when the path
99# is a local folder instead of fetching from the remote repository.
Chris Brand19bf2742022-07-05 11:15:17 -0700100# [in] GIT_REPOSITORY, GIT_TAG, ... - see https://cmake.org/cmake/help/latest/module/ExternalProject.html
101# for more details
102#
103# This function set CMP0097 to NEW if CMAKE_VERSION is greater or equal than 3.18.0.
104# Because of https://gitlab.kitware.com/cmake/cmake/-/issues/20579 CMP0097 is
105# non-functional until cmake 3.18.0.
106# See https://cmake.org/cmake/help/latest/policy/CMP0097.html for more info.
107function(fetch_remote_library)
108 # Parse arguments
109 set(options "")
Joakim Andersson083ebe42023-01-18 12:00:36 +0100110 set(oneValueArgs LIB_NAME LIB_SOURCE_PATH_VAR LIB_BINARY_PATH_VAR LIB_BASE_DIR LIB_PATCH_DIR LIB_FORCE_PATCH)
Chris Brand19bf2742022-07-05 11:15:17 -0700111 set(multiValueArgs FETCH_CONTENT_ARGS)
112 cmake_parse_arguments(PARSE_ARGV 0 ARG "${options}" "${oneValueArgs}" "${multiValueArgs}")
113
114 if(ARG_LIB_BASE_DIR)
115 set(FETCHCONTENT_BASE_DIR "${ARG_LIB_BASE_DIR}")
116 endif()
117
Chris Brand19bf2742022-07-05 11:15:17 -0700118 if ("${${ARG_LIB_SOURCE_PATH_VAR}}" STREQUAL "DOWNLOAD")
119 # Process arguments which can be an empty string
120 # There is a feature/bug in CMake that result in problem with empty string arguments
121 # See https://gitlab.kitware.com/cmake/cmake/-/issues/16341 for details
122 extract_key_value(GIT_SUBMODULES GIT_SUBMODULES GIT_SUBMODULES_VALUE ARG_FETCH_CONTENT_ARGS)
123
124 # Validate that there is no empty arguments to FetchContent_Declare
125 LIST(FIND ARG_FETCH_CONTENT_ARGS "" EMPTY_VALUE_INDEX)
126 if(${EMPTY_VALUE_INDEX} GREATER_EQUAL 0)
127 # There is an unsupported empty string argument, FATAL ERROR!
128 math(EXPR EMPTY_KEY_INDEX "${EMPTY_VALUE_INDEX} - 1")
129 list(GET ARG_FETCH_CONTENT_ARGS ${EMPTY_KEY_INDEX} EMPTY_KEY)
130 # TODO: Use extract_key_value if you have argument with empty value (see GIT_SUBMODULES above)
131 message(FATAL_ERROR "fetch_remote_library: Unexpected empty string value for ${EMPTY_KEY}. "
132 "Please, validate arguments or update fetch_remote_library to support empty value for ${EMPTY_KEY}!!!")
133 endif()
Anton Komlev1e775502025-04-25 16:37:55 +0100134 else()
135 string(TOUPPER ${ARG_LIB_NAME} ARG_LIB_NAME_UPCASE)
136 set(FETCHCONTENT_SOURCE_DIR_${ARG_LIB_NAME_UPCASE} ${${ARG_LIB_SOURCE_PATH_VAR}})
Chris Brand19bf2742022-07-05 11:15:17 -0700137 endif()
138
Anton Komlev1e775502025-04-25 16:37:55 +0100139 # list all available patches in absolute names
140 file(GLOB PATCH_FILES ${ARG_LIB_PATCH_DIR}/*.patch LIST_DIRECTORIES true)
141
142 if(PATCH_FILES)
143 set(PATCH_COMMAND PATCH_COMMAND ${GIT_EXECUTABLE} am --ignore-date ${PATCH_FILES})
Joakim Anderssonae84acf2023-02-16 17:06:31 +0100144 endif()
145
Anton Komlev1e775502025-04-25 16:37:55 +0100146 # Content fetching
147 FetchContent_Declare(${ARG_LIB_NAME}
148 ${ARG_FETCH_CONTENT_ARGS}
149 "${GIT_SUBMODULES}" "${GIT_SUBMODULES_VALUE}"
150 ${PATCH_COMMAND}
151 )
152 FetchContent_MakeAvailable(${ARG_LIB_NAME})
153 set(${ARG_LIB_SOURCE_PATH_VAR} ${${ARG_LIB_NAME}_SOURCE_DIR} CACHE PATH "Library has been downloaded from ${REPO_URL_VAR}, tag ${TAG_VAR}" FORCE)
Chris Brand19bf2742022-07-05 11:15:17 -0700154endfunction()