1# 2# Copyright (c) 2017, Alliance for Open Media. All rights reserved. 3# 4# This source code is subject to the terms of the BSD 2 Clause License and the 5# Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License was 6# not distributed with this source code in the LICENSE file, you can obtain it 7# at www.aomedia.org/license/software. If the Alliance for Open Media Patent 8# License 1.0 was not distributed with this source code in the PATENTS file, you 9# can obtain it at www.aomedia.org/license/patent. 10# 11if(AOM_BUILD_CMAKE_AOM_OPTIMIZATION_CMAKE_) 12 return() 13endif() # AOM_BUILD_CMAKE_AOM_OPTIMIZATION_CMAKE_ 14set(AOM_BUILD_CMAKE_AOM_OPTIMIZATION_CMAKE_ 1) 15 16include("${AOM_ROOT}/build/cmake/util.cmake") 17 18# Translate $flag to one which MSVC understands, and write the new flag to the 19# variable named by $translated_flag (or unset it, when MSVC needs no flag). 20function(get_msvc_intrinsic_flag flag translated_flag) 21 if("${flag}" STREQUAL "-mavx") 22 set(${translated_flag} "/arch:AVX" PARENT_SCOPE) 23 elseif("${flag}" STREQUAL "-mavx2") 24 set(${translated_flag} "/arch:AVX2" PARENT_SCOPE) 25 else() 26 27 # MSVC does not need flags for intrinsics flavors other than AVX/AVX2. 28 unset(${translated_flag} PARENT_SCOPE) 29 endif() 30endfunction() 31 32# Adds an object library target. Terminates generation if $flag is not supported 33# by the current compiler. $flag is the intrinsics flag required by the current 34# compiler, and is added to the compile flags for all sources in $sources. 35# $opt_name is used to name the target. $target_to_update is made dependent upon 36# the created target. 37# 38# Note: this function always updates the aom, and aom_static targets because 39# OBJECT libraries have rules that disallow the direct addition of .o files to 40# them as dependencies. Static and shared libraries do not have this limitation. 41function(add_intrinsics_object_library flag opt_name target_to_update sources) 42 if("${${sources}}" STREQUAL "") 43 return() 44 endif() 45 set(target_name ${target_to_update}_${opt_name}_intrinsics) 46 add_library(${target_name} OBJECT ${${sources}}) 47 set_property(TARGET ${target_name} PROPERTY FOLDER ${AOM_TARGET_CPU}) 48 49 # MSVC does not need flags for intrinsics flavors other than AVX/AVX2. 50 # However, for clang-cl, the default is SSE2, and the MSVC frontend does not 51 # provide any flags to enable SSE3 up to SSE4.1. So we need to restrict the 52 # usage of MSVC-style flags to only the real MSVC. 53 if(CMAKE_C_COMPILER_ID STREQUAL "MSVC") 54 get_msvc_intrinsic_flag("${flag}" "flag") 55 endif() 56 57 if("${flag}" STREQUAL "-mavx2") 58 unset(FLAG_SUPPORTED) 59 check_c_compiler_flag("-mno-avx256-split-unaligned-load" FLAG_SUPPORTED) 60 if(${FLAG_SUPPORTED}) 61 set(flag "${flag} -mno-avx256-split-unaligned-load") 62 endif() 63 64 unset(FLAG_SUPPORTED) 65 check_c_compiler_flag("-mno-avx256-split-unaligned-store" FLAG_SUPPORTED) 66 if(${FLAG_SUPPORTED}) 67 set(flag "${flag} -mno-avx256-split-unaligned-store") 68 endif() 69 endif() 70 71 if(flag) 72 separate_arguments(flag) 73 target_compile_options(${target_name} PUBLIC ${flag}) 74 endif() 75 76 target_sources(aom PRIVATE $<TARGET_OBJECTS:${target_name}>) 77 if(BUILD_SHARED_LIBS) 78 target_sources(aom_static PRIVATE $<TARGET_OBJECTS:${target_name}>) 79 endif() 80 81 # Add the new lib target to the global list of aom library targets. 82 list(APPEND AOM_LIB_TARGETS ${target_name}) 83 set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} PARENT_SCOPE) 84endfunction() 85 86# Adds sources in list named by $sources to $target and adds $flag to the 87# compile flags for each source file. 88function(add_intrinsics_source_to_target flag target sources) 89 target_sources(${target} PRIVATE ${${sources}}) 90 if(MSVC) 91 get_msvc_intrinsic_flag("${flag}" "flag") 92 endif() 93 if(flag) 94 foreach(source ${${sources}}) 95 set_property(SOURCE ${source} APPEND PROPERTY COMPILE_FLAGS ${flag}) 96 endforeach() 97 endif() 98endfunction() 99 100# Writes object format for the current target to the var named by $out_format, 101# or terminates the build when the object format for the current target is 102# unknown. 103function(get_asm_obj_format out_format) 104 if("${AOM_TARGET_CPU}" STREQUAL "x86_64") 105 if("${AOM_TARGET_SYSTEM}" STREQUAL "Darwin") 106 set(objformat "macho64") 107 elseif("${AOM_TARGET_SYSTEM}" STREQUAL "MSYS" 108 OR "${AOM_TARGET_SYSTEM}" STREQUAL "CYGWIN" 109 OR "${AOM_TARGET_SYSTEM}" STREQUAL "Windows") 110 set(objformat "win64") 111 else() 112 set(objformat "elf64") 113 endif() 114 elseif("${AOM_TARGET_CPU}" STREQUAL "x86") 115 if("${AOM_TARGET_SYSTEM}" STREQUAL "Darwin") 116 set(objformat "macho32") 117 elseif("${AOM_TARGET_SYSTEM}" STREQUAL "MSYS" 118 OR "${AOM_TARGET_SYSTEM}" STREQUAL "CYGWIN" 119 OR "${AOM_TARGET_SYSTEM}" STREQUAL "Windows") 120 set(objformat "win32") 121 else() 122 set(objformat "elf32") 123 endif() 124 else() 125 message( 126 FATAL_ERROR "Unknown obj format: ${AOM_TARGET_CPU}-${AOM_TARGET_SYSTEM}") 127 endif() 128 129 set(${out_format} ${objformat} PARENT_SCOPE) 130endfunction() 131 132# Adds library target named $lib_name for ASM files in variable named by 133# $asm_sources. Builds an output directory path from $lib_name. Links $lib_name 134# into the aom library target(s). Generates a C file with an unused no-op 135# function to ensure that all cmake generators can determine the linker 136# language, and that build tools don't complain that an object exposes no 137# symbols. 138# 139# In Xcode-based builds every step described above happens twice, and 140# directory/target/object names are updated to include _shared and _static 141# suffixes. 142function(add_asm_library lib_name asm_sources) 143 if("${${asm_sources}}" STREQUAL "") 144 return() 145 endif() 146 147 if(XCODE) 148 # CMake's generator does not output a build rule for Nasm files. Moreover, 149 # it makes Xcode believe Nasm files are of type "sourcecode" instead of 150 # "sourcecode.nasm", which prevents even the default rule from applying. 151 # This default rule is broken, though, because it doesn't apply any of the 152 # flags specified for ASM_NASM. See https://discourse.cmake.org/t/building- 153 # nasm-files-with-xcode/7934 154 list(APPEND asm_configs "static") 155 if(BUILD_SHARED_LIBS) 156 list(APPEND asm_configs "shared") 157 endif() 158 159 set(as_executable "${CMAKE_ASM_NASM_COMPILER}") 160 if(NOT as_executable) 161 set(as_executable "${CMAKE_ASM_COMPILER}") 162 endif() 163 164 foreach(asm_config ${asm_configs}) 165 set(asm_lib_name ${lib_name}_${asm_config}) 166 set(asm_lib_obj_dir "${AOM_CONFIG_DIR}/asm_objects/${asm_lib_name}") 167 if(NOT EXISTS "${asm_lib_obj_dir}") 168 file(MAKE_DIRECTORY "${asm_lib_obj_dir}") 169 endif() 170 171 foreach(asm_source ${${asm_sources}}) 172 get_filename_component(asm_source_name "${asm_source}" NAME) 173 set(asm_object "${asm_lib_obj_dir}/${asm_source_name}.o") 174 add_custom_command(OUTPUT "${asm_object}" 175 COMMAND ${as_executable} ARGS ${AOM_AS_FLAGS} 176 -I${AOM_ROOT}/ -I${AOM_CONFIG_DIR}/ -o 177 "${asm_object}" "${asm_source}" 178 DEPENDS "${asm_source}" 179 COMMENT "Building ASM object ${asm_object}" 180 WORKING_DIRECTORY "${AOM_CONFIG_DIR}" 181 VERBATIM) 182 if(BUILD_SHARED_LIBS AND "${asm_config}" STREQUAL "static") 183 target_sources(aom_static PRIVATE "${asm_object}") 184 else() 185 target_sources(aom PRIVATE "${asm_object}") 186 endif() 187 endforeach() 188 endforeach() 189 else() 190 # For non-Xcode generators, CMake does not need extra help. The language 191 # support takes care of it. 192 set(asm_lib_name ${lib_name}) 193 194 add_library(${asm_lib_name} OBJECT ${${asm_sources}}) 195 target_include_directories(${asm_lib_name} 196 PRIVATE ${AOM_ROOT} ${AOM_CONFIG_DIR}) 197 target_compile_options(${asm_lib_name} PRIVATE ${AOM_AS_FLAGS}) 198 set_property(TARGET ${asm_lib_name} PROPERTY FOLDER ${AOM_TARGET_CPU}) 199 if(BUILD_SHARED_LIBS) 200 target_sources(aom_static PRIVATE "$<TARGET_OBJECTS:${asm_lib_name}>") 201 endif() 202 target_sources(aom PRIVATE "$<TARGET_OBJECTS:${asm_lib_name}>") 203 204 # Add the new lib target to the global list of aom library targets. 205 list(APPEND AOM_LIB_TARGETS ${asm_lib_name}) 206 endif() 207 208 set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} PARENT_SCOPE) 209endfunction() 210 211# Terminates generation if nasm found in PATH does not meet requirements. 212# Currently checks only for presence of required object formats and support for 213# the -Ox argument (multipass optimization). 214function(test_nasm) 215 execute_process(COMMAND ${CMAKE_ASM_NASM_COMPILER} -hf 216 OUTPUT_VARIABLE nasm_helptext) 217 218 if(NOT "${nasm_helptext}" MATCHES "-Ox") 219 message( 220 FATAL_ERROR "Unsupported nasm: multipass optimization not supported.") 221 endif() 222 223 if("${AOM_TARGET_CPU}" STREQUAL "x86") 224 if("${AOM_TARGET_SYSTEM}" STREQUAL "Darwin") 225 if(NOT "${nasm_helptext}" MATCHES "macho32") 226 message( 227 FATAL_ERROR "Unsupported nasm: macho32 object format not supported.") 228 endif() 229 elseif("${AOM_TARGET_SYSTEM}" STREQUAL "MSYS" 230 OR "${AOM_TARGET_SYSTEM}" STREQUAL "Windows") 231 if(NOT "${nasm_helptext}" MATCHES "win32") 232 message( 233 FATAL_ERROR "Unsupported nasm: win32 object format not supported.") 234 endif() 235 else() 236 if(NOT "${nasm_helptext}" MATCHES "elf32") 237 message( 238 FATAL_ERROR "Unsupported nasm: elf32 object format not supported.") 239 endif() 240 endif() 241 else() 242 if("${AOM_TARGET_SYSTEM}" STREQUAL "Darwin") 243 if(NOT "${nasm_helptext}" MATCHES "macho64") 244 message( 245 FATAL_ERROR "Unsupported nasm: macho64 object format not supported.") 246 endif() 247 elseif("${AOM_TARGET_SYSTEM}" STREQUAL "MSYS" 248 OR "${AOM_TARGET_SYSTEM}" STREQUAL "Windows") 249 if(NOT "${nasm_helptext}" MATCHES "win64") 250 message( 251 FATAL_ERROR "Unsupported nasm: win64 object format not supported.") 252 endif() 253 else() 254 if(NOT "${nasm_helptext}" MATCHES "elf64") 255 message( 256 FATAL_ERROR "Unsupported nasm: elf64 object format not supported.") 257 endif() 258 endif() 259 endif() 260endfunction() 261 262# Adds build command for generation of rtcd C source files using 263# build/cmake/rtcd.pl. $config is the input perl file, $output is the output C 264# include file, $source is the C source file, and $symbol is used for the symbol 265# argument passed to rtcd.pl. 266function(add_rtcd_build_step config output source symbol) 267 add_custom_command( 268 OUTPUT ${output} 269 COMMAND ${PERL_EXECUTABLE} ARGS "${AOM_ROOT}/build/cmake/rtcd.pl" 270 --arch=${AOM_TARGET_CPU} 271 --sym=${symbol} ${AOM_RTCD_FLAGS} 272 --config=${AOM_CONFIG_DIR}/config/aom_config.h ${config} > ${output} 273 DEPENDS "${AOM_ROOT}/build/cmake/rtcd.pl" ${config} 274 COMMENT "Generating ${output}" 275 WORKING_DIRECTORY ${AOM_CONFIG_DIR} 276 VERBATIM) 277 set_property(SOURCE ${source} PROPERTY OBJECT_DEPENDS ${output}) 278 set_property(SOURCE ${output} PROPERTY GENERATED TRUE) 279endfunction() 280