diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index cbda0ca65..0d25fe930 100755 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -930,6 +930,30 @@ endif() configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in" "${PROJECT_BINARY_DIR}/x265_config.h") +# Declared before the multilib logic below, which reads it to decide whether +# the 10/12-bit archives should be merged into the static library. +option(ENABLE_SHARED "Build shared library" ON) + +# Build a single library containing the 8-bit, 10-bit and 12-bit encoders, +# switching bit depths at runtime (see build/linux/multilib.sh). Toolchain +# settings that CMake cannot infer (e.g. a packaging toolchain's target +# triplet) can be passed through MULTILIB_CMAKE_ARGS. +option(ENABLE_MULTILIB "Build a single library containing all supported bit depths" OFF) +set(MULTILIB_CMAKE_ARGS "" CACHE STRING "Extra CMake arguments for the multilib sub-builds") +set(MULTILIB_ARCHIVER "" CACHE STRING "Archiver used to merge the multilib static libraries") +if(ENABLE_MULTILIB) + include(cmake/multilib.cmake) +elseif(X265_MULTILIB_CACHE_OWNED) + # ENABLE_MULTILIB was switched back OFF in an existing build tree; drop the + # cache entries that the ON configuration force-wrote so the 8-bit library + # stops trying to link the (now stale) multilib archives. + unset(EXTRA_LIB CACHE) + unset(EXTRA_LIB) + unset(LINKED_10BIT CACHE) + unset(LINKED_12BIT CACHE) + unset(X265_MULTILIB_CACHE_OWNED CACHE) +endif() + add_subdirectory(encoder) add_subdirectory(common) @@ -1088,6 +1112,36 @@ endif() if(EXTRA_LIB) target_link_libraries(x265-static ${EXTRA_LIB}) endif() +if(ENABLE_MULTILIB) + # Statically merge the 10/12-bit archives into the 8-bit API archive so + # that consumers only need to link against a single library. This runs + # for shared builds as well: the static library is built and installed + # either way, and without the merge it would lack the 10/12-bit objects + # (multilib.sh merges them in this case too) + add_custom_command(TARGET x265-static POST_BUILD + COMMAND "${CMAKE_COMMAND}" + "-DOUTPUT=$" + "-DINPUT1=$" + "-DINPUT2=${CMAKE_CURRENT_BINARY_DIR}/multilib/10bit/${_multilib_archive_name}" + "-DINPUT3=${CMAKE_CURRENT_BINARY_DIR}/multilib/12bit/${_multilib_archive_name}" + "-DARCHIVER=${_multilib_archiver}" + -P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/x265-merge.cmake" + VERBATIM) +endif() +if(ENABLE_MULTILIB) + # Make sure the 10/12-bit sub-builds are done before this library is + # archived and merged + add_dependencies(x265-static x265-multilib-10bit x265-multilib-12bit) + # Run the sub-builds after the 8-bit objects have been compiled (the + # bit-depth libraries are also built one after another), like + # multilib.sh does: a parallel parent build would otherwise interleave + # the nested build logs with the main compile output + foreach(_multilib_objects IN ITEMS encoder common dynamicHDR10 x265-asm) + if(TARGET ${_multilib_objects}) + add_dependencies(x265-multilib-10bit ${_multilib_objects}) + endif() + endforeach() +endif() if(ENABLE_LIBVMAF) target_link_libraries(x265-static ${VMAF}) endif() @@ -1155,7 +1209,6 @@ endif() if(NOT (MSVC_IDE OR XCODE)) add_custom_target(clean-generated COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/clean-generated.cmake) endif() -option(ENABLE_SHARED "Build shared library" ON) if(ENABLE_SHARED) if(ENABLE_HDR10_PLUS) add_library(x265-shared SHARED "${PROJECT_BINARY_DIR}/x265.def" ${ASM_OBJS} @@ -1176,6 +1229,11 @@ if(ENABLE_SHARED) endif() if(EXTRA_LIB) target_link_libraries(x265-shared ${EXTRA_LIB}) + endif() + if(ENABLE_MULTILIB) + # Make sure the 10/12-bit sub-builds are done before linking this + # shared library + add_dependencies(x265-shared x265-multilib-10bit x265-multilib-12bit) endif() target_link_libraries(x265-shared ${PLATFORM_LIBS}) if(SVTHEVC_FOUND) diff --git a/source/cmake/multilib.cmake b/source/cmake/multilib.cmake new file mode 100644 index 000000000..a0954c08a --- /dev/null +++ b/source/cmake/multilib.cmake @@ -0,0 +1,270 @@ +# multilib.cmake - Build the 10-bit and 12-bit static libraries as nested +# sub-builds and link them into the 8-bit API library so that a single library +# can switch bit depths at runtime, following the upstream +# build/linux/multilib.sh recipe. +# +# Included from the top-level CMakeLists.txt when ENABLE_MULTILIB is ON. The +# sub-builds are defined as regular build targets so that they are only built +# when the library is built; the resulting archives are then merged into the +# 8-bit API library by a POST_BUILD step (see CMakeLists.txt). +# +# The nested builds inherit the generator, the toolchain and this project's +# build options, plus the common Android/OHOS target-selection variables. Any +# other toolchain-specific setting that CMake cannot infer (e.g. a packaging +# toolchain's triplet) can be passed through MULTILIB_CMAKE_ARGS. + +set(_multilib_root "${CMAKE_CURRENT_BINARY_DIR}/multilib") +set(_multilib_source "${CMAKE_CURRENT_SOURCE_DIR}") + +# The nested builds need `file(GLOB_RECURSE ... CONFIGURE_DEPENDS)` and the +# -j option of `cmake --build`, both introduced in CMake 3.12; plain x265 +# builds keep supporting older CMake versions +if(CMAKE_VERSION VERSION_LESS 3.12) + message(FATAL_ERROR "ENABLE_MULTILIB requires CMake 3.12 or later. " + "Use build/linux/multilib.sh or the build/vc*-x86_64/multilib.bat " + "scripts to build the multi-bit-depth library with older CMake.") +endif() + +# Append "-D=" to the argument list, escaping the list separator. +# Semicolons cannot be stored in list elements, so a value containing a list +# (e.g. CMAKE_OSX_ARCHITECTURES=arm64;x86_64 or ANDROID_ABI with several ABIs) +# is escaped to "\;" here and arrives at the nested configure as a single +# argument with the semicolons restored. +function(x265_multilib_append_d list_var var) + if(DEFINED ${var} AND NOT "${${var}}" STREQUAL "") + string(REPLACE ";" "\\;" _value "${${var}}") + list(APPEND ${list_var} "-D${var}=${_value}") + set(${list_var} "${${list_var}}" PARENT_SCOPE) + endif() +endfunction() + +# Inherit the generator, toolchain and platform settings from this build +set(_multilib_common_args + "-DCMAKE_GENERATOR=${CMAKE_GENERATOR}" + "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" + "-DENABLE_SHARED=OFF" + "-DENABLE_CLI=OFF" + "-DEXPORT_C_API=OFF" +) +if(DEFINED CMAKE_GENERATOR_PLATFORM) + list(APPEND _multilib_common_args "-DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}") +endif() +if(DEFINED CMAKE_GENERATOR_TOOLSET AND NOT CMAKE_GENERATOR_TOOLSET STREQUAL "") + list(APPEND _multilib_common_args "-T${CMAKE_GENERATOR_TOOLSET}") +endif() +if(DEFINED CMAKE_MAKE_PROGRAM) + list(APPEND _multilib_common_args "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}") +endif() +# Inherit the compilers (and any launcher such as ccache/sccache) so the nested +# builds use the same toolchain as the parent instead of whatever CMake happens +# to detect in the build environment +if(DEFINED CMAKE_C_COMPILER) + list(APPEND _multilib_common_args "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}") +endif() +if(DEFINED CMAKE_CXX_COMPILER) + list(APPEND _multilib_common_args "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") +endif() +if(DEFINED CMAKE_C_COMPILER_LAUNCHER AND NOT CMAKE_C_COMPILER_LAUNCHER STREQUAL "") + list(APPEND _multilib_common_args "-DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER}") +endif() +if(DEFINED CMAKE_CXX_COMPILER_LAUNCHER AND NOT CMAKE_CXX_COMPILER_LAUNCHER STREQUAL "") + list(APPEND _multilib_common_args "-DCMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER}") +endif() +if(DEFINED CMAKE_BUILD_TYPE) + list(APPEND _multilib_common_args "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") +endif() +if(DEFINED CMAKE_SYSTEM_VERSION) + list(APPEND _multilib_common_args "-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}") +endif() +if(CMAKE_CROSSCOMPILING AND DEFINED CMAKE_SYSTEM_NAME) + # Required for cross-compilation; not propagated for native builds, where + # an explicit CMAKE_SYSTEM_NAME would wrongly put the nested builds into + # cross-compiling mode + list(APPEND _multilib_common_args "-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}") +endif() +# Inherit this project's build options (STATIC_LINK_CRT matters: mixing /MT +# and /MD objects fails with LNK2038 on MSVC) +foreach(_option IN ITEMS ENABLE_ASSEMBLY ENABLE_PIC ENABLE_LIBNUMA + STATIC_LINK_CRT ENABLE_HDR10_PLUS ENABLE_SVT_HEVC + ENABLE_LIBVMAF ENABLE_ALPHA ENABLE_MULTIVIEW + ENABLE_SCC_EXT) + if(DEFINED ${_option}) + list(APPEND _multilib_common_args "-D${_option}=${${_option}}") + endif() +endforeach() +# Inherit user-provided compiler flags so the sub-builds are compiled with +# the same settings as the parent +x265_multilib_append_d(_multilib_common_args CMAKE_C_FLAGS) +x265_multilib_append_d(_multilib_common_args CMAKE_CXX_FLAGS) +# The MSVC runtime selection must match the parent's (LNK2038 otherwise) +if(MSVC) + x265_multilib_append_d(_multilib_common_args CMAKE_MSVC_RUNTIME_LIBRARY) +endif() +# Universal macOS builds (e.g. -DCMAKE_OSX_ARCHITECTURES=arm64;x86_64) must +# produce universal sub-libraries as well +if(APPLE) + x265_multilib_append_d(_multilib_common_args CMAKE_OSX_ARCHITECTURES) +endif() +if(DEFINED CMAKE_DISABLE_FIND_PACKAGE_VLD) + list(APPEND _multilib_common_args "-DCMAKE_DISABLE_FIND_PACKAGE_VLD=${CMAKE_DISABLE_FIND_PACKAGE_VLD}") +endif() +# These are often provided on the configure command line rather than by the +# toolchain file, so forward them explicitly when present +if(DEFINED VERSION) + list(APPEND _multilib_common_args "-DVERSION=${VERSION}") +endif() +if(DEFINED NASM_EXECUTABLE) + list(APPEND _multilib_common_args "-DNASM_EXECUTABLE=${NASM_EXECUTABLE}") +endif() +# Toolchain target selection (e.g. the Android NDK ABI) is passed on the +# command line and lives in plain cache variables, not in the toolchain file; +# forward the common ones so the nested builds target the same ABI. The +# values may themselves be lists (several ANDROID_ABI entries, +# ANDROID_CPP_FEATURES=rtti;exceptions), hence the escaped append. +foreach(_var IN ITEMS ANDROID_ABI ANDROID_ARM_NEON ANDROID_ARM_MODE + ANDROID_PLATFORM ANDROID_STL ANDROID_NDK + ANDROID_TOOLCHAIN ANDROID_CPP_FEATURES + OHOS_ARCH CMAKE_PLATFORM_NO_VERSIONED_SONAME) + x265_multilib_append_d(_multilib_common_args ${_var}) +endforeach() +# Packager hook: extra CMake arguments for the nested builds (e.g. the +# toolchain's target selection such as ANDROID_ABI) +if(DEFINED MULTILIB_CMAKE_ARGS AND NOT MULTILIB_CMAKE_ARGS STREQUAL "") + separate_arguments(_multilib_extra_args NATIVE_COMMAND "${MULTILIB_CMAKE_ARGS}") + list(APPEND _multilib_common_args ${_multilib_extra_args}) +endif() +# Forward the parallelism of the parent build so the nested builds do not fall +# back to -j1. Prefer CMAKE_BUILD_PARALLEL_LEVEL and otherwise fall back to the +# machine's processor count; the two bit-depth sub-builds are chained +# sequentially, so each may safely use all cores. The level is passed as a +# separate argument: `cmake --build` rejects the combined "-jN" form before +# CMake 3.14. +set(_multilib_parallel_args "") +if(DEFINED ENV{CMAKE_BUILD_PARALLEL_LEVEL} AND NOT "$ENV{CMAKE_BUILD_PARALLEL_LEVEL}" STREQUAL "") + set(_multilib_parallel_args -j "$ENV{CMAKE_BUILD_PARALLEL_LEVEL}") +else() + include(ProcessorCount) + ProcessorCount(_multilib_ncpu) + if(_multilib_ncpu GREATER 0) + set(_multilib_parallel_args -j "${_multilib_ncpu}") + endif() +endif() + +# Track the x265 sources so that the nested builds re-run when they change; +# without this the produced archive would be considered up to date forever. +# The build tree is excluded from the tracking: it can be located inside +# source/ (CLion and VS Code do this when they open source/ as the project +# root), and its generated files would make the sub-builds depend on their +# own outputs (circular dependency). +file(GLOB_RECURSE _multilib_depends CONFIGURE_DEPENDS "${_multilib_source}/*") +set(_multilib_build_prefix "${CMAKE_CURRENT_BINARY_DIR}/") +set(_multilib_sources "") +foreach(_dep IN LISTS _multilib_depends) + string(FIND "${_dep}" "${_multilib_build_prefix}" _multilib_dep_pos) + if(NOT _multilib_dep_pos EQUAL 0) + list(APPEND _multilib_sources "${_dep}") + endif() +endforeach() +set(_multilib_depends "${_multilib_sources}") + +# The nested builds produce the static archive of the x265-static target +# (libx265.a on non-MSVC, x265-static.lib on MSVC) +if(MSVC) + set(_multilib_archive_name "x265-static.lib") +else() + set(_multilib_archive_name "libx265.a") +endif() + +# Archiver used by the static merge. x265-merge.cmake runs in `cmake -P` +# script mode, where WIN32/APPLE/MINGW describe the *host* rather than the +# target, so it cannot be left to auto-detect the tool whenever host and +# target can differ; pass the target toolchain's archiver instead (llvm-ar +# for the Android NDK, GNU ar for MinGW, ...). Apple targets (macOS and +# iOS/tvOS cross-builds) keep the script default: libtool merges Mach-O +# archives for every Apple platform, while Apple's ar does not support the +# MRI scripts used for ELF/COFF archives. Native MSVC and Linux builds also +# keep the default (lib.exe / ar). +if(MULTILIB_ARCHIVER) + set(_multilib_archiver "${MULTILIB_ARCHIVER}") +elseif(MINGW OR (CMAKE_CROSSCOMPILING AND NOT APPLE)) + set(_multilib_archiver "${CMAKE_AR}") +else() + set(_multilib_archiver "") +endif() + +# Define the bit-depth sub-builds as regular targets that declare their +# produced archive as an output, so that the build system knows how to build +# the archives the main library links against; the main library targets depend +# on them (see CMakeLists.txt). +# +# CMAKE_ARCHIVE_OUTPUT_DIRECTORY is forced so that the produced archive always +# lands directly in the sub-build directory. Multi-config generators such as +# Visual Studio additionally need the per-configuration variants, otherwise +# they append a per-configuration subdirectory to the archive path. +function(x265_define_multilib_variant name dir archive) + set(_archive_dir_args "-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=${dir}") + if(CMAKE_CONFIGURATION_TYPES) + # Multi-config generators (Visual Studio, Xcode) append a per-config + # subdirectory to the generic path unless the per-config path is set + foreach(_config IN ITEMS DEBUG RELEASE MINSIZEREL RELWITHDEBINFO) + list(APPEND _archive_dir_args "-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_${_config}=${dir}") + endforeach() + endif() + add_custom_command( + OUTPUT "${archive}" + # The nested configure is driven through the documented `cmake -E + # make_directory`/`-E chdir` tools with the source given as a + # positional argument instead of `cmake -S/-B`, which needs CMake 3.13; + # `cmake -E chdir` does not create the build directory, hence the + # explicit make_directory + COMMAND "${CMAKE_COMMAND}" -E make_directory "${dir}" + COMMAND "${CMAKE_COMMAND}" -E chdir "${dir}" "${CMAKE_COMMAND}" + ${_multilib_common_args} ${ARGN} + ${_archive_dir_args} + "${_multilib_source}" + # Run the nested build with an empty MAKEFLAGS so the nested make does + # not try to join the parent's jobserver ("resetting jobserver mode" + # warnings); the explicit -j above gives it its own parallelism + COMMAND "${CMAKE_COMMAND}" -E env MAKEFLAGS= "${CMAKE_COMMAND}" + --build "${dir}" --config "$" + ${_multilib_parallel_args} + DEPENDS ${_multilib_depends} + COMMENT "Building the ${name} x265 sub-library" + VERBATIM) + add_custom_target(${name} DEPENDS "${archive}") +endfunction() + +x265_define_multilib_variant(x265-multilib-10bit "${_multilib_root}/10bit" + "${_multilib_root}/10bit/${_multilib_archive_name}" "-DHIGH_BIT_DEPTH=ON") +x265_define_multilib_variant(x265-multilib-12bit "${_multilib_root}/12bit" + "${_multilib_root}/12bit/${_multilib_archive_name}" "-DHIGH_BIT_DEPTH=ON" "-DMAIN12=ON") +# Build the bit-depth sub-libraries sequentially (like build/linux/multilib.sh) +# so that a parallel parent build does not run two nested builds at once +add_dependencies(x265-multilib-12bit x265-multilib-10bit) + +# Link the 10/12-bit archives into this build; the LINKED_* options enable the +# bit-depth dispatch in the exported C API (see encoder/api.cpp). A user +# provided EXTRA_LIB is respected (with a warning) instead of being silently +# discarded; the cache entries are marked as owned so they can be cleared when +# ENABLE_MULTILIB is turned back OFF in the same build tree. +set(_multilib_extra_lib + "${_multilib_root}/10bit/${_multilib_archive_name};${_multilib_root}/12bit/${_multilib_archive_name}") +if(EXTRA_LIB AND NOT "${EXTRA_LIB}" STREQUAL "${_multilib_extra_lib}") + message(WARNING "ENABLE_MULTILIB is enabled but EXTRA_LIB is already set; the multilib archives will not be linked automatically") + if(X265_MULTILIB_CACHE_OWNED) + # A previous ENABLE_MULTILIB configuration force-set these entries; + # the user's own EXTRA_LIB takes over now, so restore the LINKED_* + # defaults (they referred to the multilib archives, which are no + # longer linked) and release the ownership so that turning + # ENABLE_MULTILIB back OFF will not delete the user's value + unset(LINKED_10BIT CACHE) + unset(LINKED_12BIT CACHE) + unset(X265_MULTILIB_CACHE_OWNED CACHE) + endif() +else() + set(EXTRA_LIB "${_multilib_extra_lib}" + CACHE STRING "Extra libraries to link against" FORCE) + set(LINKED_10BIT ON CACHE BOOL "10bit libx265 is being linked with this library" FORCE) + set(LINKED_12BIT ON CACHE BOOL "12bit libx265 is being linked with this library" FORCE) + set(X265_MULTILIB_CACHE_OWNED ON CACHE INTERNAL "x265 multilib force-set EXTRA_LIB/LINKED_10BIT/LINKED_12BIT") +endif() diff --git a/source/cmake/x265-merge.cmake b/source/cmake/x265-merge.cmake new file mode 100644 index 000000000..3aff35b12 --- /dev/null +++ b/source/cmake/x265-merge.cmake @@ -0,0 +1,118 @@ +# x265-merge.cmake - Merge several static archives into one. +# +# Usage: +# cmake -DOUTPUT= [-DINPUT1=] [-DINPUT2=] ... +# [-DARCHIVER=] -P x265-merge.cmake +# +# The merge is performed with GNU ar (MRI script) on Linux/MinGW, libtool on +# macOS and lib.exe/llvm-lib on MSVC. When ARCHIVER is not given, the tool is +# looked up on the system. + +if(NOT DEFINED OUTPUT) + message(FATAL_ERROR "OUTPUT is required") +endif() + +get_filename_component(_out_name "${OUTPUT}" NAME) +get_filename_component(_out_dir "${OUTPUT}" DIRECTORY) +set(_work "${_out_dir}/.x265-merge") +file(REMOVE_RECURSE "${_work}") +file(MAKE_DIRECTORY "${_work}") + +set(_inputs) +set(_index 1) +while(DEFINED INPUT${_index}) + set(_input "${INPUT${_index}}") + if(NOT EXISTS "${_input}") + message(FATAL_ERROR "Input archive does not exist: ${_input}") + endif() + get_filename_component(_input_name "${_input}" NAME) + get_filename_component(_input_ext "${_input}" EXT) + file(COPY "${_input}" DESTINATION "${_work}") + file(RENAME "${_work}/${_input_name}" "${_work}/in${_index}${_input_ext}") + list(APPEND _inputs "in${_index}${_input_ext}") + math(EXPR _index "${_index} + 1") +endwhile() +if(NOT _inputs) + message(FATAL_ERROR "At least one INPUT argument is required") +endif() + +if(DEFINED ARCHIVER AND ARCHIVER) + get_filename_component(_ar_name "${ARCHIVER}" NAME) + if(_ar_name MATCHES "^(lib|llvm-lib)(\\.exe)?$") + set(_mode "msvc") + elseif(_ar_name MATCHES "^(libtool|llvm-libtool)(\\.exe)?$") + set(_mode "libtool") + elseif(_ar_name MATCHES "^(ar|llvm-ar)(\\.exe)?$") + set(_mode "mri") + else() + # Prefixed cross archivers such as x86_64-w64-mingw32-ar or + # aarch64-linux-android-ar speak the GNU ar MRI syntax + set(_mode "mri") + endif() + set(_archiver "${ARCHIVER}") +else() + if(WIN32 AND NOT MINGW) + find_program(_archiver NAMES lib.exe llvm-lib) + set(_mode "msvc") + elseif(APPLE) + find_program(_archiver NAMES libtool) + set(_mode "libtool") + else() + find_program(_archiver NAMES ar) + set(_mode "mri") + endif() + if(NOT _archiver) + message(FATAL_ERROR "Unable to find an archiver to merge the x265 multilib libraries") + endif() +endif() + +if(_mode STREQUAL "mri") + set(_script_contents "CREATE ${_out_name}\n") + foreach(_input IN LISTS _inputs) + string(APPEND _script_contents "ADDLIB ${_input}\n") + endforeach() + string(APPEND _script_contents "SAVE\nEND\n") + file(WRITE "${_work}/merge.script" "${_script_contents}") + execute_process( + COMMAND "${_archiver}" -M + WORKING_DIRECTORY "${_work}" + INPUT_FILE "${_work}/merge.script" + RESULT_VARIABLE _result) + if(NOT _result EQUAL 0) + message(FATAL_ERROR "Failed to merge static archives with ${_archiver}: ${_result}") + endif() +elseif(_mode STREQUAL "msvc") + set(_command "/NOLOGO" "/OUT:${_work}/${_out_name}") + foreach(_input IN LISTS _inputs) + list(APPEND _command "${_work}/${_input}") + endforeach() + execute_process(COMMAND "${_archiver}" ${_command} WORKING_DIRECTORY "${_work}" RESULT_VARIABLE _result) + if(NOT _result EQUAL 0) + message(FATAL_ERROR "Failed to merge static archives with ${_archiver}: ${_result}") + endif() +else() + set(_command libtool -static -o "${_work}/${_out_name}") + foreach(_input IN LISTS _inputs) + list(APPEND _command "${_work}/${_input}") + endforeach() + execute_process(COMMAND ${_command} WORKING_DIRECTORY "${_work}" + OUTPUT_VARIABLE _out ERROR_VARIABLE _err RESULT_VARIABLE _result) + if(NOT _result EQUAL 0) + message(FATAL_ERROR "Failed to merge static archives with libtool: ${_result}\n${_out}${_err}") + endif() + # libtool warns about the identically-named object members that the three + # bit-depth builds produce; harmless, filter them from the output + if(_err) + string(REGEX REPLACE "[^\n]*member name[^\n]*\n?" "" _err "${_err}") + string(STRIP "${_err}" _err) + if(NOT _err STREQUAL "") + message(STATUS "${_err}") + endif() + endif() +endif() + +if(EXISTS "${OUTPUT}") + file(REMOVE "${OUTPUT}") +endif() +file(RENAME "${_work}/${_out_name}" "${OUTPUT}") +file(REMOVE_RECURSE "${_work}") diff --git a/source/encoder/CMakeLists.txt b/source/encoder/CMakeLists.txt index 8c8090786..c83804427 100644 --- a/source/encoder/CMakeLists.txt +++ b/source/encoder/CMakeLists.txt @@ -22,7 +22,12 @@ if(EXTRA_LIB) list(APPEND APIFLAGS "-DLINKED_12BIT=1") endif(LINKED_12BIT) string(REPLACE ";" " " APIFLAGSTR "${APIFLAGS}") - set_source_files_properties(api.cpp PROPERTIES COMPILE_FLAGS ${APIFLAGSTR}) + if(APIFLAGSTR) + # Guard against an empty flag list: EXTRA_LIB may be set without any + # of the LINKED_* options, and COMPILE_FLAGS without a value is a + # configure error + set_source_files_properties(api.cpp PROPERTIES COMPILE_FLAGS ${APIFLAGSTR}) + endif() endif(EXTRA_LIB) add_library(encoder OBJECT ../x265.h