Files
UnrealEngine/Engine/Source/ThirdParty/openexr/openexr-3.3.2/cmake/OpenEXRSetup.cmake
2025-05-18 13:04:45 +08:00

364 lines
15 KiB
CMake

# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) Contributors to the OpenEXR Project.
include(GNUInstallDirs)
if(NOT "${CMAKE_PROJECT_NAME}" STREQUAL "${PROJECT_NAME}")
set(OPENEXR_IS_SUBPROJECT ON)
message(STATUS "OpenEXR is configuring as a cmake subproject")
endif()
########################
## Target configuration
# What C++ standard to compile for
# VFX Platform 21 is c++17, so 21, 22, 23, 24 gives us 4+ years of 17
set(tmp 17)
if(CMAKE_CXX_STANDARD GREATER tmp)
set(tmp ${CMAKE_CXX_STANDARD})
endif()
set(OPENEXR_CXX_STANDARD "${tmp}" CACHE STRING "C++ standard to compile against")
set(tmp)
message(STATUS "Building against C++ Standard: ${OPENEXR_CXX_STANDARD}")
set(OPENEXR_NAMESPACE_CUSTOM "0" CACHE STRING "Whether the namespace has been customized (so external users know)")
set(OPENEXR_INTERNAL_IMF_NAMESPACE "Imf_${OPENEXR_VERSION_API}" CACHE STRING "Real namespace for OpenEXR that will end up in compiled symbols")
set(OPENEXR_IMF_NAMESPACE "Imf" CACHE STRING "Public namespace alias for OpenEXR")
set(OPENEXR_PACKAGE_NAME "OpenEXR ${OPENEXR_VERSION}${OPENEXR_VERSION_RELEASE_TYPE}" CACHE STRING "Public string / label for displaying package")
# Namespace-related settings, allows one to customize the
# namespace generated, and to version the namespaces
set(ILMTHREAD_NAMESPACE_CUSTOM "0" CACHE STRING "Whether the namespace has been customized (so external users know)")
set(ILMTHREAD_INTERNAL_NAMESPACE "IlmThread_${OPENEXR_VERSION_API}" CACHE STRING "Real namespace for IlmThread that will end up in compiled symbols")
set(ILMTHREAD_NAMESPACE "IlmThread" CACHE STRING "Public namespace alias for IlmThread")
set(IEX_NAMESPACE_CUSTOM "0" CACHE STRING "Whether the namespace has been customized (so external users know)")
set(IEX_INTERNAL_NAMESPACE "Iex_${OPENEXR_VERSION_API}" CACHE STRING "Real namespace for Iex that will end up in compiled symbols")
set(IEX_NAMESPACE "Iex" CACHE STRING "Public namespace alias for Iex")
# Whether to generate and install a pkg-config file OpenEXR.pc
option(OPENEXR_INSTALL_PKG_CONFIG "Install OpenEXR.pc file" ON)
# Whether to enable threading. This can be disabled, although thread pool and tasks
# are still used, just processed immediately
option(OPENEXR_ENABLE_THREADING "Enables threaded processing of requests" ON)
option(OPENEXR_USE_DEFAULT_VISIBILITY "Makes the compile use default visibility (by default compiles tidy, hidden-by-default)" OFF)
# This is primarily for the auto array that enables a stack
# object (if you enable this) that contains member to avoid double allocations
option(OPENEXR_ENABLE_LARGE_STACK "Enables code to take advantage of large stack support" OFF)
########################
## Build related options
option(OPENEXR_INSTALL "Install OpenEXR libraries/binaries/bindings" ON)
# Whether to build & install the main libraries
option(OPENEXR_BUILD_LIBS "Enables building of main libraries" ON)
# Whether to build the various command line utility programs
option(OPENEXR_BUILD_TOOLS "Enables building of utility programs" ON)
option(OPENEXR_INSTALL_TOOLS "Install OpenEXR tools" ON)
option(OPENEXR_BUILD_EXAMPLES "Build and install OpenEXR examples" ON)
option(OPENEXR_BUILD_PYTHON "Build python bindings" OFF)
option(OPENEXR_TEST_LIBRARIES "Run library tests" ON)
option(OPENEXR_TEST_TOOLS "Run tool tests" ON)
option(OPENEXR_TEST_PYTHON "Run python binding tests" ON)
# This is a variable here for use in controlling where include files are
# installed. Care must be taken when changing this, as many things
# probably assume this is OpenEXR
set(OPENEXR_OUTPUT_SUBDIR OpenEXR CACHE STRING "Destination sub-folder of the include path for install")
# This does not seem to be available as a per-target property,
# but is pretty harmless to set globally
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Suffix for debug configuration libraries
# (if you should choose to install those)
set(CMAKE_DEBUG_POSTFIX "_d" CACHE STRING "Suffix for debug builds")
if(NOT OPENEXR_IS_SUBPROJECT)
# Usual cmake option to build shared libraries or not, only overridden if OpenEXR is a top level project,
# in general this setting should be explicitly configured by the end user
option(BUILD_SHARED_LIBS "Build shared library" ON)
endif()
# Suffix to append to root name, this helps with version management
# but can be turned off if you don't care, or otherwise customized
set(OPENEXR_LIB_SUFFIX "-${OPENEXR_VERSION_API}" CACHE STRING "string added to the end of all the libraries")
# when building both dynamic and static, the additional string to
# add to the library name, such that to get static linkage, you
# would use -lOpenEXR_static (or target_link_libraries(xxx OpenEXR::OpenEXR_static))
set(OPENEXR_STATIC_LIB_SUFFIX "_static" CACHE STRING "When building both static and shared, name to append to static library (in addition to normal suffix)")
# rpath related setup
# make sure we force an rpath to the rpath we're compiling
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
# adds the automatically determined parts of the rpath
# which point to directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
if(APPLE)
set(CMAKE_MACOSX_RPATH ON)
endif()
# if the user sets an install rpath
# then just use that, or otherwise set one for them
if(NOT CMAKE_INSTALL_RPATH)
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
if("${CMAKE_SYSTEM}" MATCHES "Linux")
get_filename_component(tmpSysPath "${CMAKE_INSTALL_FULL_LIBDIR}" NAME)
if(NOT tmpSysPath)
set(tmpSysPath "lib")
endif()
set(CMAKE_INSTALL_RPATH "\\\$ORIGIN/../${tmpSysPath};${CMAKE_INSTALL_FULL_LIBDIR}")
set(tmpSysPath)
elseif(APPLE)
set(CMAKE_INSTALL_RPATH "@loader_path/../lib;@executable_path/../lib;${CMAKE_INSTALL_FULL_LIBDIR}")
else()
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}")
endif()
endif()
set(isSystemDir)
endif()
########################
# set a default build type if not set
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
# Code check related features
option(OPENEXR_USE_CLANG_TIDY "Check if clang-tidy is available, and enable that" OFF)
if(OPENEXR_USE_CLANG_TIDY)
find_program(OPENEXR_CLANG_TIDY_BIN clang-tidy)
if(OPENEXR_CLANG_TIDY_BIN-NOTFOUND)
message(FATAL_ERROR "clang-tidy processing requested, but no clang-tidy found")
endif()
# TODO: Need to define the list of valid checks and add a file with said list
set(CMAKE_CXX_CLANG_TIDY
${OPENEXR_CLANG_TIDY_BIN};
-header-filter=.;
-checks=*;
)
endif()
if (NOT OPENEXR_BUILD_LIBS)
return()
endif()
###############################
# Dependent libraries
# so we know how to add the thread stuff to the pkg-config package
# which is the only (but good) reason.
if(OPENEXR_ENABLE_THREADING)
if(NOT TARGET Threads::Threads)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
if(NOT Threads_FOUND)
message(FATAL_ERROR "Unable to find a threading library, disable with OPENEXR_ENABLE_THREADING=OFF")
endif()
endif()
endif()
option(OPENEXR_FORCE_INTERNAL_DEFLATE "Force using an internal libdeflate" OFF)
set(OPENEXR_DEFLATE_REPO "https://github.com/ebiggers/libdeflate.git" CACHE STRING "Repo path for libdeflate source")
set(OPENEXR_DEFLATE_TAG "v1.18" CACHE STRING "Tag to use for libdeflate source repo (defaults to primary if empty)")
if(NOT OPENEXR_FORCE_INTERNAL_DEFLATE)
#TODO: ^^ Release should not clone from main, this is a place holder
set(CMAKE_IGNORE_PATH "${CMAKE_CURRENT_BINARY_DIR}/_deps/deflate-src/config;${CMAKE_CURRENT_BINARY_DIR}/_deps/deflate-build/config")
# First try cmake config
find_package(libdeflate CONFIG QUIET)
if(libdeflate_FOUND)
if(TARGET libdeflate::libdeflate_shared)
set(EXR_DEFLATE_LIB libdeflate::libdeflate_shared)
else()
set(EXR_DEFLATE_LIB libdeflate::libdeflate_static)
endif()
set(EXR_DEFLATE_VERSION ${libdeflate_VERSION})
message(STATUS "Using libdeflate from ${libdeflate_DIR}")
else()
# If not found, try pkgconfig
find_package(PkgConfig)
if(PKG_CONFIG_FOUND)
include(FindPkgConfig)
pkg_check_modules(deflate IMPORTED_TARGET GLOBAL libdeflate)
if(deflate_FOUND)
set(EXR_DEFLATE_LIB PkgConfig::deflate)
set(EXR_DEFLATE_VERSION ${deflate_VERSION})
message(STATUS "Using libdeflate from ${deflate_LINK_LIBRARIES}")
endif()
endif()
endif()
set(CMAKE_IGNORE_PATH)
endif()
if(EXR_DEFLATE_LIB)
# Using external library
set(EXR_DEFLATE_SOURCES)
set(EXR_DEFLATE_INCLUDE_DIR)
# For OpenEXR.pc.in for static build
set(EXR_DEFLATE_PKGCONFIG_REQUIRES "libdeflate >= ${EXR_DEFLATE_VERSION}")
else()
# Using internal deflate
if(OPENEXR_FORCE_INTERNAL_DEFLATE)
message(STATUS "libdeflate forced internal, installing from ${OPENEXR_DEFLATE_REPO} (${OPENEXR_DEFLATE_TAG})")
else()
message(STATUS "libdeflate was not found, installing from ${OPENEXR_DEFLATE_REPO} (${OPENEXR_DEFLATE_TAG})")
endif()
include(FetchContent)
# Fetch deflate but exclude it from the "all" target.
# This prevents the library from being built.
FetchContent_Declare(Deflate
GIT_REPOSITORY "${OPENEXR_DEFLATE_REPO}"
GIT_TAG "${OPENEXR_DEFLATE_TAG}"
GIT_SHALLOW ON
EXCLUDE_FROM_ALL
)
FetchContent_GetProperties(Deflate)
if(NOT deflate_POPULATED)
if(CMAKE_VERSION VERSION_LESS "3.30")
# CMake 3.30 deprecated this single argument version of
# FetchContent_Populate():
# https://cmake.org/cmake/help/latest/policy/CMP0169.html
# Prior to CMake 3.28, passing the EXCLUDE_FROM_ALL option to
# FetchContent_Declare() does *not* have the desired effect of
# excluding the fetched content from the build when
# FetchContent_MakeAvailable() is called.
# Ideally we could "manually" set the EXCLUDE_FROM_ALL property on the
# deflate SOURCE_DIR and BINARY_DIR, but a bug that was only fixed as of
# CMake 3.20.3 prevents that from properly excluding the directories:
# https://gitlab.kitware.com/cmake/cmake/-/issues/22234
# To support the full range of CMake versions without overly
# complicating the logic here with workarounds, we continue to use
# Populate for CMake versions before 3.30, and switch to MakeAvailable
# for CMake 3.30 and later.
FetchContent_Populate(Deflate)
else()
FetchContent_MakeAvailable(Deflate)
endif()
endif()
# Rather than actually compile something, just embed the sources
# into exrcore. This could in theory cause issues when compiling as
# a static library into another application which also uses
# libdeflate but we switch the export symbol to hidden which should
# hide the symbols when linking...
set(EXR_DEFLATE_SOURCES
lib/arm/cpu_features.c
lib/x86/cpu_features.c
lib/utils.c
lib/deflate_compress.c
lib/deflate_decompress.c
lib/adler32.c
lib/zlib_compress.c
lib/zlib_decompress.c)
# don't need these
# lib/crc32.c
# lib/gzip_compress.c
# lib/gzip_decompress.c
file(READ ${deflate_SOURCE_DIR}/lib/lib_common.h DEFLATE_HIDE)
string(REPLACE "visibility(\"default\")" "visibility(\"hidden\")" DEFLATE_HIDE "${DEFLATE_HIDE}")
string(REPLACE "__declspec(dllexport)" "/**/" DEFLATE_HIDE "${DEFLATE_HIDE}")
file(WRITE ${deflate_SOURCE_DIR}/lib/lib_common.h "${DEFLATE_HIDE}")
# cmake makes fetch content name lowercase for the properties (to deflate)
list(TRANSFORM EXR_DEFLATE_SOURCES PREPEND ${deflate_SOURCE_DIR}/)
set(EXR_DEFLATE_INCLUDE_DIR ${deflate_SOURCE_DIR})
set(EXR_DEFLATE_LIB)
endif()
#######################################
# Find or install Imath
#######################################
option(OPENEXR_FORCE_INTERNAL_IMATH "Force using an internal imath" OFF)
# Check to see if Imath is installed outside of the current build directory.
set(OPENEXR_IMATH_REPO "https://github.com/AcademySoftwareFoundation/Imath.git" CACHE STRING "Repo for auto-build of Imath")
set(OPENEXR_IMATH_TAG "v3.1.12" CACHE STRING "Tag for auto-build of Imath (branch, tag, or SHA)")
if(NOT OPENEXR_FORCE_INTERNAL_IMATH)
#TODO: ^^ Release should not clone from main, this is a place holder
set(CMAKE_IGNORE_PATH "${CMAKE_CURRENT_BINARY_DIR}/_deps/imath-src/config;${CMAKE_CURRENT_BINARY_DIR}/_deps/imath-build/config")
find_package(Imath 3.1)
set(CMAKE_IGNORE_PATH)
endif()
if(NOT TARGET Imath::Imath AND NOT Imath_FOUND)
if(OPENEXR_FORCE_INTERNAL_IMATH)
message(STATUS "Imath forced internal, installing from ${OPENEXR_IMATH_REPO} (${OPENEXR_IMATH_TAG})")
else()
message(STATUS "Imath was not found, installing from ${OPENEXR_IMATH_REPO} (${OPENEXR_IMATH_TAG})")
endif()
include(FetchContent)
FetchContent_Declare(Imath
GIT_REPOSITORY "${OPENEXR_IMATH_REPO}"
GIT_TAG "${OPENEXR_IMATH_TAG}"
GIT_SHALLOW ON
)
FetchContent_GetProperties(Imath)
if(NOT Imath_POPULATED)
FetchContent_MakeAvailable(Imath)
# Propagate OpenEXR's install setting to Imath
set(IMATH_INSTALL ${OPENEXR_INSTALL})
# Propagate OpenEXR's setting for pkg-config generation to Imath:
# If OpenEXR is generating it, the internal Imath should, too.
set(IMATH_INSTALL_PKG_CONFIG ${OPENEXR_INSTALL_PKG_CONFIG})
endif()
# the install creates this but if we're using the library locally we
# haven't installed the header files yet, so need to extract those
# and make a variable for header only usage
if(NOT TARGET Imath::ImathConfig)
get_target_property(imathinc Imath INTERFACE_INCLUDE_DIRECTORIES)
get_target_property(imathconfinc ImathConfig INTERFACE_INCLUDE_DIRECTORIES)
list(APPEND imathinc ${imathconfinc})
set(IMATH_HEADER_ONLY_INCLUDE_DIRS ${imathinc})
message(STATUS "Imath interface dirs ${IMATH_HEADER_ONLY_INCLUDE_DIRS}")
endif()
else()
message(STATUS "Using Imath from ${Imath_DIR}")
# local build
# add_subdirectory(${IMATH_ROOT} Imath)
# add_subdirectory(${OPENEXR_ROOT} OpenEXR)
if(NOT TARGET Imath::ImathConfig AND TARGET Imath AND TARGET ImathConfig)
get_target_property(imathinc Imath INTERFACE_INCLUDE_DIRECTORIES)
get_target_property(imathconfinc ImathConfig INTERFACE_INCLUDE_DIRECTORIES)
list(APPEND imathinc ${imathconfinc})
set(IMATH_HEADER_ONLY_INCLUDE_DIRS ${imathinc})
message(STATUS "Imath interface dirs ${IMATH_HEADER_ONLY_INCLUDE_DIRS}")
endif()
endif()
###########################################
# Check if we need to emulate vld1q_f32_x2
###########################################
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
include(CheckCSourceCompiles)
check_c_source_compiles("#include <arm_neon.h>
int main() {
float a[] = {1.0, 1.0};
vld1q_f32_x2(a);
return 0;
}" HAS_VLD1)
if(NOT HAS_VLD1)
set(OPENEXR_MISSING_ARM_VLD1 TRUE)
endif()
endif()