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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
|
# This script provides helper functions for FindModules
# Parse and set variables from VERSION dependency file
# On return:
# MODULENAME_ARCHIVE will be set to parent scope
# MODULENAME_VER will be set to parent scope (eg FFMPEG_VER, DAV1D_VER)
# MODULENAME_BASE_URL will be set to parent scope if exists in VERSION file (eg FFMPEG_BASE_URL)
# MODULENAME_HASH will be set if either SHA256 or SHA512 exists in VERSION file
# MODULENAME_BYPRODUCT will be set to parent scope
function(get_versionfile_data)
# Dependency path
set(MODULE_PATH "${PROJECTSOURCE}/tools/depends/${LIB_TYPE}/${MODULE_LC}")
if(NOT EXISTS "${MODULE_PATH}/${MODULE}-VERSION")
MESSAGE(FATAL_ERROR "${MODULE}-VERSION does not exist at ${MODULE_PATH}.")
else()
set(${MODULE}_FILE "${MODULE_PATH}/${MODULE}-VERSION")
endif()
file(STRINGS ${${MODULE}_FILE} ${MODULE}_LNAME REGEX "^[ \t]*LIBNAME=")
file(STRINGS ${${MODULE}_FILE} ${MODULE}_VER REGEX "^[ \t]*VERSION=")
file(STRINGS ${${MODULE}_FILE} ${MODULE}_ARCHIVE REGEX "^[ \t]*ARCHIVE=")
file(STRINGS ${${MODULE}_FILE} ${MODULE}_BASE_URL REGEX "^[ \t]*BASE_URL=")
if(WIN32 OR WINDOWS_STORE)
file(STRINGS ${${MODULE}_FILE} ${MODULE}_BYPRODUCT REGEX "^[ \t]*BYPRODUCT_WIN=")
else()
file(STRINGS ${${MODULE}_FILE} ${MODULE}_BYPRODUCT REGEX "^[ \t]*BYPRODUCT=")
endif()
# Tarball Hash
file(STRINGS ${${MODULE}_FILE} ${MODULE}_HASH_SHA256 REGEX "^[ \t]*SHA256=")
file(STRINGS ${${MODULE}_FILE} ${MODULE}_HASH_SHA512 REGEX "^[ \t]*SHA512=")
string(REGEX REPLACE ".*LIBNAME=([^ \t]*).*" "\\1" ${MODULE}_LNAME "${${MODULE}_LNAME}")
string(REGEX REPLACE ".*VERSION=([^ \t]*).*" "\\1" ${MODULE}_VER "${${MODULE}_VER}")
string(REGEX REPLACE ".*ARCHIVE=([^ \t]*).*" "\\1" ${MODULE}_ARCHIVE "${${MODULE}_ARCHIVE}")
string(REGEX REPLACE ".*BASE_URL=([^ \t]*).*" "\\1" ${MODULE}_BASE_URL "${${MODULE}_BASE_URL}")
if(WIN32 OR WINDOWS_STORE)
string(REGEX REPLACE ".*BYPRODUCT_WIN=([^ \t]*).*" "\\1" ${MODULE}_BYPRODUCT "${${MODULE}_BYPRODUCT}")
else()
string(REGEX REPLACE ".*BYPRODUCT=([^ \t]*).*" "\\1" ${MODULE}_BYPRODUCT "${${MODULE}_BYPRODUCT}")
endif()
string(REGEX REPLACE "\\$\\(LIBNAME\\)" "${${MODULE}_LNAME}" ${MODULE}_ARCHIVE "${${MODULE}_ARCHIVE}")
string(REGEX REPLACE "\\$\\(VERSION\\)" "${${MODULE}_VER}" ${MODULE}_ARCHIVE "${${MODULE}_ARCHIVE}")
set(${MODULE}_ARCHIVE ${${MODULE}_ARCHIVE} PARENT_SCOPE)
set(${MODULE}_VER ${${MODULE}_VER} PARENT_SCOPE)
if (${MODULE}_BASE_URL)
set(${MODULE}_BASE_URL ${${MODULE}_BASE_URL} PARENT_SCOPE)
else()
set(${MODULE}_BASE_URL "http://mirrors.kodi.tv/build-deps/sources" PARENT_SCOPE)
endif()
set(${MODULE}_BYPRODUCT ${${MODULE}_BYPRODUCT} PARENT_SCOPE)
# allow user to override the download URL hash with a local tarball hash
# needed for offline build envs
if (NOT DEFINED ${MODULE}_HASH)
if (${MODULE}_HASH_SHA256)
set(${MODULE}_HASH ${${MODULE}_HASH_SHA256} PARENT_SCOPE)
elseif(${MODULE}_HASH_SHA512)
set(${MODULE}_HASH ${${MODULE}_HASH_SHA512} PARENT_SCOPE)
endif()
endif()
endfunction()
# Parse and set Version from VERSION dependency file
# Used for retrieving version numbers for dependency libs to allow setting
# a required version for find_package call
# On return:
# LIB_MODULENAME_VER will be set to parent scope (eg LIB_FMT_VER)
function(get_libversion_data module libtype)
# Dependency path
set(LIB_MODULE_PATH "${CMAKE_SOURCE_DIR}/tools/depends/${libtype}/${module}")
string(TOUPPER ${module} MOD_UPPER)
if(NOT EXISTS "${LIB_MODULE_PATH}/${MOD_UPPER}-VERSION")
MESSAGE(FATAL_ERROR "${MOD_UPPER}-VERSION does not exist at ${LIB_MODULE_PATH}.")
else()
set(${MOD_UPPER}_FILE "${LIB_MODULE_PATH}/${MOD_UPPER}-VERSION")
endif()
file(STRINGS ${${MOD_UPPER}_FILE} ${MOD_UPPER}_VER REGEX "^[ \t]*VERSION=")
string(REGEX REPLACE ".*VERSION=([^ \t]*).*" "\\1" ${MOD_UPPER}_VER "${${MOD_UPPER}_VER}")
set(LIB_${MOD_UPPER}_VER ${${MOD_UPPER}_VER} PARENT_SCOPE)
endfunction()
# Function to loop through list of patch files (full path)
# Sets to a PATCH_COMMAND variable and set to parent scope (caller)
# Used to test windows line endings and set appropriate patch commands
function(generate_patchcommand _patchlist)
# find the path to the patch executable
find_package(Patch MODULE REQUIRED)
# Loop through patches and add to PATCH_COMMAND
# for windows, check CRLF/LF state
set(_count 0)
foreach(patch ${_patchlist})
if(WIN32 OR WINDOWS_STORE)
PATCH_LF_CHECK(${patch})
endif()
if(${_count} EQUAL "0")
set(_patch_command ${PATCH_EXECUTABLE} -p1 -i ${patch})
else()
list(APPEND _patch_command COMMAND ${PATCH_EXECUTABLE} -p1 -i ${patch})
endif()
math(EXPR _count "${_count}+1")
endforeach()
set(PATCH_COMMAND ${_patch_command} PARENT_SCOPE)
unset(_count)
unset(_patch_command)
endfunction()
# Macro to factor out the repetitive URL setup
macro(SETUP_BUILD_VARS)
string(TOUPPER ${MODULE_LC} MODULE)
# Fall through to target build module dir if not explicitly set
if(NOT DEFINED LIB_TYPE)
set(LIB_TYPE "target")
endif()
# Location for build type, native or target
if(LIB_TYPE STREQUAL "target")
set(DEP_LOCATION "${DEPENDS_PATH}")
else()
set(DEP_LOCATION "${NATIVEPREFIX}")
endif()
# PROJECTSOURCE used in native toolchain to provide core project sourcedir
# to externalproject_add targets that have a different CMAKE_SOURCE_DIR (eg jsonschema/texturepacker in-tree)
if(NOT PROJECTSOURCE)
set(PROJECTSOURCE ${CMAKE_SOURCE_DIR})
endif()
# populate variables of data from VERSION file for MODULE
get_versionfile_data()
# allow user to override the download URL with a local tarball
# needed for offline build envs
if(${MODULE}_URL)
get_filename_component(${MODULE}_URL "${${MODULE}_URL}" ABSOLUTE)
else()
set(${MODULE}_URL ${${MODULE}_BASE_URL}/${${MODULE}_ARCHIVE})
endif()
if(VERBOSE)
message(STATUS "MODULE: ${MODULE}")
message(STATUS "LIB_TYPE: ${LIB_TYPE}")
message(STATUS "DEP_LOCATION: ${DEP_LOCATION}")
message(STATUS "PROJECTSOURCE: ${PROJECTSOURCE}")
message(STATUS "${MODULE}_URL: ${${MODULE}_URL}")
endif()
endmacro()
macro(CLEAR_BUILD_VARS)
# unset all generic variables to insure clean state between macro calls
# Potentially an issue with scope when a macro is used inside a dep that uses a macro
unset(PROJECTSOURCE)
unset(LIB_TYPE)
unset(BUILD_NAME)
unset(INSTALL_DIR)
unset(CMAKE_ARGS)
unset(PATCH_COMMAND)
unset(CONFIGURE_COMMAND)
unset(BUILD_COMMAND)
unset(INSTALL_COMMAND)
unset(BUILD_IN_SOURCE)
unset(BUILD_BYPRODUCTS)
unset(WIN_DISABLE_PROJECT_FLAGS)
# unset all module specific variables to insure clean state between macro calls
# potentially an issue when a native and a target of the same module exists
unset(${MODULE}_LIST_SEPARATOR)
unset(${MODULE}_GENERATOR)
unset(${MODULE}_GENERATOR_PLATFORM)
unset(${MODULE}_INSTALL_PREFIX)
unset(${MODULE}_TOOLCHAIN_FILE)
endmacro()
# Macro to create externalproject_add target
#
# Common usage
#
# CMAKE_ARGS: cmake(required)
# PATCH_COMMAND: ALL(optional)
# CONFIGURE_COMMAND: autoconf(required), meson(required)
# BUILD_COMMAND: autoconf(required), meson(required), cmake(optional)
# INSTALL_COMMAND: autoconf(required), meson(required), cmake(optional)
# BUILD_IN_SOURCE: ALL(optional)
# BUILD_BYPRODUCTS: ALL(optional)
#
# Windows Specific
# WIN_DISABLE_PROJECT_FLAGS - Set to not use core compiler flags for externalproject_add target
# This removes CMAKE_C_FLAGS CMAKE_CXX_FLAGS CMAKE_EXE_LINKER_FLAGS
# from the externalproject_add target. Primarily used for HOST build
# tools that may have different arch/build requirements to the core app
# target (eg flatc)
#
macro(BUILD_DEP_TARGET)
include(ExternalProject)
# Remove cmake warning when Xcode generator used with "New" build system
if(CMAKE_GENERATOR STREQUAL Xcode)
# Policy CMP0114 is not set to NEW. In order to support the Xcode "new build
# system", this project must be updated to set policy CMP0114 to NEW.
if(CMAKE_XCODE_BUILD_SYSTEM STREQUAL 12)
cmake_policy(SET CMP0114 NEW)
else()
cmake_policy(SET CMP0114 OLD)
endif()
endif()
if(CMAKE_ARGS)
set(CMAKE_ARGS CMAKE_ARGS ${CMAKE_ARGS}
-DCMAKE_INSTALL_LIBDIR=lib
-DPROJECTSOURCE=${PROJECTSOURCE}
"-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}")
# We dont have a toolchain for windows, so manually add all the cmake
# build arguments we may want
# We can disable adding them with WIN_DISABLE_PROJECT_FLAGS. This is potentially required
# for host build tools (eg flatc) that may be a different arch to the core app
if(WIN32 OR WINDOWS_STORE)
if(NOT DEFINED WIN_DISABLE_PROJECT_FLAGS)
list(APPEND CMAKE_ARGS "-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} $<$<CONFIG:Debug>:${CMAKE_C_FLAGS_DEBUG}> $<$<CONFIG:Release>:${CMAKE_C_FLAGS_RELEASE}> ${${MODULE}_C_FLAGS}"
"-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} $<$<CONFIG:Debug>:${CMAKE_CXX_FLAGS_DEBUG}> $<$<CONFIG:Release>:${CMAKE_CXX_FLAGS_RELEASE}> ${${MODULE}_CXX_FLAGS}"
"-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS} $<$<CONFIG:Debug>:${CMAKE_EXE_LINKER_FLAGS_DEBUG}> $<$<CONFIG:Release>:${CMAKE_EXE_LINKER_FLAGS_RELEASE}> ${${MODULE}_EXE_LINKER_FLAGS}")
endif()
endif()
if(${MODULE}_INSTALL_PREFIX)
list(APPEND CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${${MODULE}_INSTALL_PREFIX})
else()
list(APPEND CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${DEP_LOCATION})
endif()
if(DEFINED ${MODULE}_TOOLCHAIN_FILE)
list(APPEND CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${${MODULE}_TOOLCHAIN_FILE})
elseif(CMAKE_TOOLCHAIN_FILE)
list(APPEND CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE})
endif()
# Set build type for dep build.
# if MODULE has set a manual build type, use it, otherwise use project build type
if(${MODULE}_BUILD_TYPE)
list(APPEND CMAKE_ARGS "-DCMAKE_BUILD_TYPE=${${MODULE}_BUILD_TYPE}")
# Build_type is forced, so unset the opposite <MODULE>_LIBRARY_<TYPE> to only give
# select_library_configurations one library name to choose from
if(${MODULE}_BUILD_TYPE STREQUAL "Release")
unset(${MODULE}_LIBRARY_DEBUG)
else()
unset(${MODULE}_LIBRARY_RELEASE)
endif()
else()
# single config generator (ie Make, Ninja)
if(CMAKE_BUILD_TYPE)
list(APPEND CMAKE_ARGS "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
else()
# Multi-config generators (eg VS, Xcode, Ninja Multi-Config) will not have CMAKE_BUILD_TYPE
# Use config genex to generate the types
# Potential issue if Build type isnt supported by lib project
# eg lib supports Debug/Release, however users selects RelWithDebInfo in project
list(APPEND CMAKE_ARGS "-DCMAKE_BUILD_TYPE=$<CONFIG>")
endif()
endif()
# Xcode - Default sub projects to makefile builds. More consistent
# Windows - Default to same generator version used in parent
if(CMAKE_GENERATOR STREQUAL Xcode)
if(NOT ${MODULE}_GENERATOR)
set(${MODULE}_GENERATOR CMAKE_GENERATOR "Unix Makefiles")
endif()
elseif(MSVC)
if(NOT ${MODULE}_GENERATOR)
set(${MODULE}_GENERATOR CMAKE_GENERATOR "${CMAKE_GENERATOR}")
endif()
if(NOT ${MODULE}_GENERATOR_PLATFORM)
set(${MODULE}_GENERATOR_PLATFORM CMAKE_GENERATOR_PLATFORM ${CMAKE_GENERATOR_PLATFORM})
endif()
endif()
endif()
if(PATCH_COMMAND)
set(PATCH_COMMAND PATCH_COMMAND ${PATCH_COMMAND})
endif()
if(CONFIGURE_COMMAND)
if(NOT CMAKE_ARGS AND DEP_BUILDENV)
# DEP_BUILDENV only used for non cmake externalproject_add builds
# iterate through CONFIGURE_COMMAND looking for multiple COMMAND, we need to
# add DEP_BUILDENV for each distinct COMMAND
set(tmp_config_command ${DEP_BUILDENV})
foreach(item ${CONFIGURE_COMMAND})
list(APPEND tmp_config_command ${item})
if(item STREQUAL "COMMAND")
list(APPEND tmp_config_command ${DEP_BUILDENV})
endif()
endforeach()
set(CONFIGURE_COMMAND CONFIGURE_COMMAND ${tmp_config_command})
unset(tmp_config_command)
else()
set(CONFIGURE_COMMAND CONFIGURE_COMMAND ${CONFIGURE_COMMAND})
endif()
endif()
if(BUILD_COMMAND)
set(BUILD_COMMAND BUILD_COMMAND ${BUILD_COMMAND})
endif()
if(INSTALL_COMMAND)
set(INSTALL_COMMAND INSTALL_COMMAND ${INSTALL_COMMAND})
endif()
if(BUILD_IN_SOURCE)
set(BUILD_IN_SOURCE BUILD_IN_SOURCE ${BUILD_IN_SOURCE})
endif()
# Set Library names.
if(DEFINED ${MODULE}_DEBUG_POSTFIX)
set(_POSTFIX ${${MODULE}_DEBUG_POSTFIX})
string(REGEX REPLACE "\\.[^.]*$" "" _LIBNAME ${${MODULE}_BYPRODUCT})
string(REGEX REPLACE "^.*\\." "" _LIBEXT ${${MODULE}_BYPRODUCT})
set(${MODULE}_LIBRARY_DEBUG ${DEP_LOCATION}/lib/${_LIBNAME}${${MODULE}_DEBUG_POSTFIX}.${_LIBEXT})
endif()
# set <MODULE>_LIBRARY_RELEASE for use of select_library_configurations
# any modules that dont use select_library_configurations, we set <MODULE>_LIBRARY
# No harm in having either set for both potential paths
set(${MODULE}_LIBRARY_RELEASE ${DEP_LOCATION}/lib/${${MODULE}_BYPRODUCT})
set(${MODULE}_LIBRARY ${${MODULE}_LIBRARY_RELEASE})
if(NOT ${MODULE}_INCLUDE_DIR)
set(${MODULE}_INCLUDE_DIR ${DEP_LOCATION}/include)
endif()
if(BUILD_BYPRODUCTS)
set(BUILD_BYPRODUCTS BUILD_BYPRODUCTS ${BUILD_BYPRODUCTS})
else()
if(DEFINED ${MODULE}_LIBRARY_DEBUG)
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.20")
set(BUILD_BYPRODUCTS BUILD_BYPRODUCTS "$<IF:$<CONFIG:Debug,RelWithDebInfo>,${${MODULE}_LIBRARY_DEBUG},${${MODULE}_LIBRARY_RELEASE}>")
else()
if(DEFINED CMAKE_BUILD_TYPE)
if(NOT CMAKE_BUILD_TYPE STREQUAL "Release" AND DEFINED ${MODULE}_LIBRARY_DEBUG)
set(BUILD_BYPRODUCTS BUILD_BYPRODUCTS "${${MODULE}_LIBRARY_DEBUG}")
else()
set(BUILD_BYPRODUCTS BUILD_BYPRODUCTS "${${MODULE}_LIBRARY}")
endif()
else()
message(FATAL_ERROR "MultiConfig Generator usage requires CMake >= 3.20.0 - Generator Expressions in BYPRODUCT option")
endif()
endif()
else()
set(BUILD_BYPRODUCTS BUILD_BYPRODUCTS "${${MODULE}_LIBRARY}")
endif()
endif()
if(NOT BUILD_NAME)
set(BUILD_NAME ${MODULE_LC})
endif()
if(NOT INSTALL_DIR)
set(INSTALL_DIR ${DEP_LOCATION})
endif()
# Allow a target to supply in-tree source location. eg TexturePacker, JsonSchemaBuilder
if(${MODULE}_SOURCE_DIR)
set(BUILD_DOWNLOAD_STEPS SOURCE_DIR "${${MODULE}_SOURCE_DIR}")
else()
set(BUILD_DOWNLOAD_STEPS URL ${${MODULE}_URL}
URL_HASH ${${MODULE}_HASH}
DOWNLOAD_DIR ${TARBALL_DIR}
DOWNLOAD_NAME ${${MODULE}_ARCHIVE})
endif()
externalproject_add(${BUILD_NAME}
${BUILD_DOWNLOAD_STEPS}
PREFIX ${CORE_BUILD_DIR}/${BUILD_NAME}
INSTALL_DIR ${INSTALL_DIR}
${${MODULE}_LIST_SEPARATOR}
${CMAKE_ARGS}
${${MODULE}_GENERATOR}
${${MODULE}_GENERATOR_PLATFORM}
${PATCH_COMMAND}
${CONFIGURE_COMMAND}
${BUILD_COMMAND}
${INSTALL_COMMAND}
${BUILD_BYPRODUCTS}
${BUILD_IN_SOURCE})
set_target_properties(${BUILD_NAME} PROPERTIES FOLDER "External Projects")
CLEAR_BUILD_VARS()
endmacro()
# Macro to test format of line endings of a patch
# Windows Specific
macro(PATCH_LF_CHECK patch)
if(CMAKE_HOST_WIN32)
# On Windows "patch.exe" can only handle CR-LF line-endings.
# Our patches have LF-only line endings - except when they
# have been checked out as part of a dependency hosted on Git
# and core.autocrlf=true.
file(READ ${ARGV0} patch_content_hex HEX)
# Force handle LF-only line endings
if(NOT patch_content_hex MATCHES "0d0a")
if (NOT "--binary" IN_LIST PATCH_EXECUTABLE)
list(APPEND PATCH_EXECUTABLE --binary)
endif()
else()
if ("--binary" IN_LIST PATCH_EXECUTABLE)
list(REMOVE_ITEM PATCH_EXECUTABLE --binary)
endif()
endif()
endif()
unset(patch_content_hex)
endmacro()
|