cmake: use assembly language support
This commit moves the asm libraries to object libraries through CMake's
ASM and ASM_NASM support. It brings the following benefits:
- we no longer need to duplicate between static and shared libraries
- Nasm objects can now be fully compiled in parallel (as they're not
custom targets anymore)
- there's no longer the need for dummy C files to determine the linker
The ASM language support is currently unused, but it's been added since
AS_EXECUTABLE was used for both Nasm and GAS files.
For Xcode, the existing approach has to be preserved due to the
following issues:
- the Xcode generator does not recognise ASM_NASM as a valid language,
so it does not output build rules
- even if this was fixed (with explicitFileType set to
"sourcecode.nasm"), the default build rule in Xcode does not carry
any of the ASM_NASM flags, nor the selected object format
These issues were already detected in [1], and I asked about them in
the CMake Discourse forum [2], to no avail yet.
Since this change relies on CMake's CheckLanguage module and ASM_NASM
language support, the minimum version has been increased to 3.9.
[1]: https://cmake.org/pipermail/cmake/2018-October/068332.html
[2]: https://discourse.cmake.org/t/building-nasm-files-with-xcode/7934
Related: aomedia:3401
Change-Id: Id0d4c8208afa403df30c0b8ab9b0809e6d67d6d8
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2e38010..50c4efd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,7 +11,7 @@
if(CONFIG_TFLITE)
cmake_minimum_required(VERSION 3.11)
else()
- cmake_minimum_required(VERSION 3.7)
+ cmake_minimum_required(VERSION 3.9)
endif()
set(AOM_ROOT "${CMAKE_CURRENT_SOURCE_DIR}")
diff --git a/aom_ports/aom_ports.cmake b/aom_ports/aom_ports.cmake
index 92d3030..e3b67e4 100644
--- a/aom_ports/aom_ports.cmake
+++ b/aom_ports/aom_ports.cmake
@@ -49,9 +49,13 @@
#
# * The libaom target must exist before this function is called.
function(setup_aom_ports_targets)
- if(WIN32 AND "${AOM_TARGET_CPU}" STREQUAL "x86_64")
+ if(XCODE AND "${AOM_TARGET_CPU}" STREQUAL "x86_64")
add_asm_library("aom_ports" "AOM_PORTS_ASM_X86")
- set(aom_ports_asm_lib 1)
+ # Xcode is the only one
+ set(aom_ports_is_embedded 1)
+ set(aom_ports_has_symbols 1)
+ elseif(WIN32 AND "${AOM_TARGET_CPU}" STREQUAL "x86_64")
+ add_asm_library("aom_ports" "AOM_PORTS_ASM_X86")
set(aom_ports_has_symbols 1)
elseif("${AOM_TARGET_CPU}" MATCHES "arm")
add_library(aom_ports OBJECT ${AOM_PORTS_SOURCES_ARM})
@@ -74,14 +78,7 @@
# libaom_srcs.*; if it becomes necessary for a particular generator another
# method should be used.
if(aom_ports_has_symbols)
- if(aom_ports_asm_lib)
- # When aom_ports is an asm library its name changes based on build
- # configuration. This handles adding sources to the correct target(s).
- target_sources(aom_ports_static PRIVATE ${AOM_PORTS_INCLUDES})
- if(BUILD_SHARED_LIBS)
- target_sources(aom_ports_shared PRIVATE ${AOM_PORTS_INCLUDES})
- endif()
- else()
+ if(NOT aom_ports_is_embedded)
target_sources(aom_ports PRIVATE ${AOM_PORTS_INCLUDES})
endif()
set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} PARENT_SCOPE)
diff --git a/build/cmake/aom_configure.cmake b/build/cmake/aom_configure.cmake
index d5fa169..33def6c 100644
--- a/build/cmake/aom_configure.cmake
+++ b/build/cmake/aom_configure.cmake
@@ -155,49 +155,61 @@
endif()
if(AOM_TARGET_CPU STREQUAL "x86" OR AOM_TARGET_CPU STREQUAL "x86_64")
- find_program(AS_EXECUTABLE yasm $ENV{YASM_PATH})
- if(NOT AS_EXECUTABLE OR ENABLE_NASM)
- unset(AS_EXECUTABLE CACHE)
- find_program(AS_EXECUTABLE nasm $ENV{NASM_PATH})
- if(AS_EXECUTABLE)
- test_nasm()
- endif()
+ find_program(CMAKE_ASM_NASM_COMPILER yasm $ENV{YASM_PATH})
+ if(NOT CMAKE_ASM_NASM_COMPILER OR ENABLE_NASM)
+ unset(CMAKE_ASM_NASM_COMPILER CACHE)
+ find_program(CMAKE_ASM_NASM_COMPILER nasm $ENV{NASM_PATH})
endif()
- if(NOT AS_EXECUTABLE)
+ include(CheckLanguage)
+ check_language(ASM_NASM)
+ if(CMAKE_ASM_NASM_COMPILER)
+ get_asm_obj_format("objformat")
+ unset(CMAKE_ASM_NASM_OBJECT_FORMAT)
+ set(CMAKE_ASM_NASM_OBJECT_FORMAT ${objformat})
+ enable_language(ASM_NASM)
+ if(CMAKE_ASM_NASM_COMPILER_ID STREQUAL "NASM")
+ test_nasm()
+ endif()
+ # Xcode requires building the objects manually, so pass the object format
+ # flag.
+ if(XCODE)
+ set(AOM_AS_FLAGS -f ${objformat} ${AOM_AS_FLAGS})
+ endif()
+ else()
message(
FATAL_ERROR
"Unable to find assembler. Install 'yasm' or 'nasm.' "
"To build without optimizations, add -DAOM_TARGET_CPU=generic to "
"your cmake command line.")
endif()
- get_asm_obj_format("objformat")
- set(AOM_AS_FLAGS -f ${objformat} ${AOM_AS_FLAGS})
string(STRIP "${AOM_AS_FLAGS}" AOM_AS_FLAGS)
elseif(AOM_TARGET_CPU MATCHES "arm")
if(AOM_TARGET_SYSTEM STREQUAL "Darwin")
- set(AS_EXECUTABLE as)
+ set(CMAKE_ASM_COMPILER as)
set(AOM_AS_FLAGS -arch ${AOM_TARGET_CPU} -isysroot ${CMAKE_OSX_SYSROOT})
elseif(AOM_TARGET_SYSTEM STREQUAL "Windows")
- if(NOT AS_EXECUTABLE)
- set(AS_EXECUTABLE ${CMAKE_C_COMPILER} -c -mimplicit-it=always)
+ if(NOT CMAKE_ASM_COMPILER)
+ set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER} -c -mimplicit-it=always)
endif()
else()
- if(NOT AS_EXECUTABLE)
- set(AS_EXECUTABLE as)
+ if(NOT CMAKE_ASM_COMPILER)
+ set(CMAKE_ASM_COMPILER as)
endif()
endif()
- find_program(as_executable_found ${AS_EXECUTABLE})
- if(NOT as_executable_found)
+ include(CheckLanguage)
+ check_language(ASM)
+ if(NOT CMAKE_ASM_COMPILER)
message(
FATAL_ERROR
"Unable to find assembler and optimizations are enabled."
- "Searched for ${AS_EXECUTABLE}. Install it, add it to your path, or "
- "set the assembler directly by adding -DAS_EXECUTABLE=<assembler path> "
- "to your CMake command line."
+ "Searched for ${CMAKE_ASM_COMPILER}. Install it, add it to your path,"
+ "or set the assembler directly by adding "
+ "-DCMAKE_ASM_COMPILER=<assembler path> to your CMake command line."
"To build without optimizations, add -DAOM_TARGET_CPU=generic to your "
"cmake command line.")
endif()
+ enable_language(ASM)
string(STRIP "${AOM_AS_FLAGS}" AOM_AS_FLAGS)
endif()
diff --git a/build/cmake/aom_optimization.cmake b/build/cmake/aom_optimization.cmake
index ff0193a..f8eeb82 100644
--- a/build/cmake/aom_optimization.cmake
+++ b/build/cmake/aom_optimization.cmake
@@ -133,7 +133,7 @@
# language, and that build tools don't complain that an object exposes no
# symbols.
#
-# In shared library configs every step described above happens twice, and
+# In Xcode-based builds every step described above happens twice, and
# directory/target/object names are updated to include _shared and _static
# suffixes.
function(add_asm_library lib_name asm_sources)
@@ -141,49 +141,66 @@
return()
endif()
- list(APPEND asm_configs "static")
- if(BUILD_SHARED_LIBS)
- list(APPEND asm_configs "shared")
- endif()
-
- foreach(asm_config ${asm_configs})
- set(asm_lib_name ${lib_name}_${asm_config})
- set(asm_lib_obj_dir "${AOM_CONFIG_DIR}/asm_objects/${asm_lib_name}")
- if(NOT EXISTS "${asm_lib_obj_dir}")
- file(MAKE_DIRECTORY "${asm_lib_obj_dir}")
+ if(XCODE)
+ # CMake's generator does not output a build rule for Nasm files. Moreover,
+ # it makes Xcode believe Nasm files are of type "sourcecode" instead of
+ # "sourcecode.nasm", which prevents even the default rule from applying.
+ # This default rule is broken, though, because it doesn't apply any of the
+ # flags specified for ASM_NASM. See https://discourse.cmake.org/t/building-
+ # nasm-files-with-xcode/7934
+ list(APPEND asm_configs "static")
+ if(BUILD_SHARED_LIBS)
+ list(APPEND asm_configs "shared")
endif()
- add_library(${asm_lib_name} STATIC ${${asm_sources}})
- set_property(TARGET ${asm_lib_name} PROPERTY FOLDER ${AOM_TARGET_CPU})
+ set(as_executable "${CMAKE_ASM_NASM_COMPILER}")
+ if(NOT as_executable)
+ set(as_executable "${CMAKE_ASM_COMPILER}")
+ endif()
- foreach(asm_source ${${asm_sources}})
- get_filename_component(asm_source_name "${asm_source}" NAME)
- set(asm_object "${asm_lib_obj_dir}/${asm_source_name}.o")
- add_custom_command(OUTPUT "${asm_object}"
- COMMAND ${AS_EXECUTABLE} ARGS ${AOM_AS_FLAGS}
- -I${AOM_ROOT}/ -I${AOM_CONFIG_DIR}/ -o
- "${asm_object}" "${asm_source}"
- DEPENDS "${asm_source}"
- COMMENT "Building ASM object ${asm_object}"
- WORKING_DIRECTORY "${AOM_CONFIG_DIR}"
- VERBATIM)
- if(BUILD_SHARED_LIBS AND "${asm_config}" STREQUAL "static")
- target_sources(aom_static PRIVATE "${asm_object}")
- else()
- target_sources(aom PRIVATE "${asm_object}")
+ foreach(asm_config ${asm_configs})
+ set(asm_lib_name ${lib_name}_${asm_config})
+ set(asm_lib_obj_dir "${AOM_CONFIG_DIR}/asm_objects/${asm_lib_name}")
+ if(NOT EXISTS "${asm_lib_obj_dir}")
+ file(MAKE_DIRECTORY "${asm_lib_obj_dir}")
endif()
- endforeach()
- # The above created a target containing only ASM sources. CMake needs help
- # here to determine the linker language. Add a C file with an unused no-op
- # function to force the linker language to C. We don't bother with setting
- # the LINKER_LANGUAGE property on the library target because not all
- # generators obey it (looking at you, Xcode generator).
- add_no_op_source_file_to_target("${asm_lib_name}" "c")
+ foreach(asm_source ${${asm_sources}})
+ get_filename_component(asm_source_name "${asm_source}" NAME)
+ set(asm_object "${asm_lib_obj_dir}/${asm_source_name}.o")
+ add_custom_command(OUTPUT "${asm_object}"
+ COMMAND ${as_executable} ARGS ${AOM_AS_FLAGS}
+ -I${AOM_ROOT}/ -I${AOM_CONFIG_DIR}/ -o
+ "${asm_object}" "${asm_source}"
+ DEPENDS "${asm_source}"
+ COMMENT "Building ASM object ${asm_object}"
+ WORKING_DIRECTORY "${AOM_CONFIG_DIR}"
+ VERBATIM)
+ if(BUILD_SHARED_LIBS AND "${asm_config}" STREQUAL "static")
+ target_sources(aom_static PRIVATE "${asm_object}")
+ else()
+ target_sources(aom PRIVATE "${asm_object}")
+ endif()
+ endforeach()
+ endforeach()
+ else()
+ # For non-Xcode generators, CMake does not need extra help. The language
+ # support takes care of it.
+ set(asm_lib_name ${lib_name})
+
+ add_library(${asm_lib_name} OBJECT ${${asm_sources}})
+ target_include_directories(${asm_lib_name}
+ PRIVATE ${AOM_ROOT} ${AOM_CONFIG_DIR})
+ target_compile_options(${asm_lib_name} PRIVATE ${AOM_AS_FLAGS})
+ set_property(TARGET ${asm_lib_name} PROPERTY FOLDER ${AOM_TARGET_CPU})
+ if(BUILD_SHARED_LIBS)
+ target_sources(aom_static PRIVATE "$<TARGET_OBJECTS:${asm_lib_name}>")
+ endif()
+ target_sources(aom PRIVATE "$<TARGET_OBJECTS:${asm_lib_name}>")
# Add the new lib target to the global list of aom library targets.
list(APPEND AOM_LIB_TARGETS ${asm_lib_name})
- endforeach()
+ endif()
set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} PARENT_SCOPE)
endfunction()
@@ -192,7 +209,8 @@
# Currently checks only for presence of required object formats and support for
# the -Ox argument (multipass optimization).
function(test_nasm)
- execute_process(COMMAND ${AS_EXECUTABLE} -hf OUTPUT_VARIABLE nasm_helptext)
+ execute_process(COMMAND ${CMAKE_ASM_NASM_COMPILER} -hf
+ OUTPUT_VARIABLE nasm_helptext)
if(NOT "${nasm_helptext}" MATCHES "-Ox")
message(
diff --git a/build/cmake/toolchains/android.cmake b/build/cmake/toolchains/android.cmake
index f0b9fab..4d38c9a 100644
--- a/build/cmake/toolchains/android.cmake
+++ b/build/cmake/toolchains/android.cmake
@@ -45,11 +45,11 @@
endif()
if(ANDROID_ABI MATCHES "^arm")
- set(AS_EXECUTABLE as)
+ set(CMAKE_ASM_COMPILER as)
# No runtime cpu detect for arm targets.
set(CONFIG_RUNTIME_CPU_DETECT 0 CACHE STRING "")
elseif(ANDROID_ABI MATCHES "^x86")
- set(AS_EXECUTABLE yasm)
+ set(CMAKE_ASM_NASM_COMPILER yasm)
endif()
set(CMAKE_SYSTEM_NAME "Android")
diff --git a/build/cmake/toolchains/arm64-linux-gcc.cmake b/build/cmake/toolchains/arm64-linux-gcc.cmake
index 64e460b..a510524 100644
--- a/build/cmake/toolchains/arm64-linux-gcc.cmake
+++ b/build/cmake/toolchains/arm64-linux-gcc.cmake
@@ -27,8 +27,8 @@
if(NOT CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER ${CROSS}g++)
endif()
-if(NOT AS_EXECUTABLE)
- set(AS_EXECUTABLE ${CROSS}as)
+if(NOT CMAKE_ASM_COMPILER)
+ set(CMAKE_ASM_COMPILER ${CROSS}as)
endif()
set(CMAKE_C_FLAGS_INIT "-march=armv8-a")
set(CMAKE_CXX_FLAGS_INIT "-march=armv8-a")
diff --git a/build/cmake/toolchains/armv7-linux-gcc.cmake b/build/cmake/toolchains/armv7-linux-gcc.cmake
index 1201538..7ce1dd8 100644
--- a/build/cmake/toolchains/armv7-linux-gcc.cmake
+++ b/build/cmake/toolchains/armv7-linux-gcc.cmake
@@ -31,8 +31,8 @@
if(NOT CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER ${CROSS}g++)
endif()
-if(NOT AS_EXECUTABLE)
- set(AS_EXECUTABLE ${CROSS}as)
+if(NOT CMAKE_ASM_COMPILER)
+ set(CMAKE_ASM_COMPILER ${CROSS}as)
endif()
set(CMAKE_C_FLAGS_INIT "-march=armv7-a -mfpu=vfpv3 \
${AOM_EXTRA_TOOLCHAIN_FLAGS}")
diff --git a/build/cmake/toolchains/ppc-linux-gcc.cmake b/build/cmake/toolchains/ppc-linux-gcc.cmake
index ab0efea..aeb2420 100644
--- a/build/cmake/toolchains/ppc-linux-gcc.cmake
+++ b/build/cmake/toolchains/ppc-linux-gcc.cmake
@@ -27,8 +27,8 @@
if(NOT CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER ${CROSS}g++)
endif()
-if(NOT AS_EXECUTABLE)
- set(AS_EXECUTABLE ${CROSS}as)
+if(NOT CMAKE_ASM_COMPILER)
+ set(CMAKE_ASM_COMPILER ${CROSS}as)
endif()
set(CMAKE_SYSTEM_PROCESSOR "ppc")
diff --git a/build/cmake/toolchains/riscv-linux-gcc.cmake b/build/cmake/toolchains/riscv-linux-gcc.cmake
index 21e7370..65b7c59 100644
--- a/build/cmake/toolchains/riscv-linux-gcc.cmake
+++ b/build/cmake/toolchains/riscv-linux-gcc.cmake
@@ -27,8 +27,8 @@
if(NOT CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER ${CROSS}g++)
endif()
-if(NOT AS_EXECUTABLE)
- set(AS_EXECUTABLE ${CROSS}as)
+if(NOT CMAKE_ASM_COMPILER)
+ set(CMAKE_ASM_COMPILER ${CROSS}as)
endif()
set(CMAKE_SYSTEM_PROCESSOR "riscv")