Add shared library support to the CMake build.

This is enabled via:
$ cmake path/to/aom -DBUILD_SHARED_LIBS=1

Currently supports only Linux and MacOS targets. Symbol visibility
is handled by exports.cmake and its helpers exports_sources.cmake
and generate_exports.cmake.

Some sweeping changes were required to properly support shared libs
and control symbol visibility:

- Object libraries are always linked privately into static
  libraries.
- Static libraries are always linked privately into eachother
  in the many cases where the CMake build merges multiple library
  targets.
- aom_dsp.cmake now links all its targets into the aom_dsp static
  library target, and privately links aom_dsp into the aom target.
- av1.cmake now links all its targets into the aom_av1 static library
  target, and privately links in aom_dsp and aom_scale as well. It
  then privately links aom_av1 into the aom target.
- The aom_mem, aom_ports, aom_scale, and aom_util targets are now
  static libs that are privately linked into the aom target.
- In CMakeLists.txt libyuv and libwebm are now privately linked into
  app targets.
- The ASM and intrinsic library functions in aom_optimization.cmake
  now both require a dependent target argument. This facilitates the
  changes noted above regarding new privately linked static library
  targets for ASM and intrinsics sources.

BUG=aomedia:76,aomedia:556

Change-Id: I4892059880c5de0f479da2e9c21d8ba2fa7390c3
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f20ebd2..59d03fd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,6 +23,9 @@
 option(ENABLE_IDE_TEST_HOSTING
        "Enables running tests within IDEs like Visual Studio and Xcode." OFF)
 
+# $BUILD_SHARED_LIBS is a CMake built-in-- it's listed here for visibility.
+option(BUILD_SHARED_LIBS "CMake should generate a shared library build." OFF)
+
 project(AOM C CXX)
 
 set(AOM_ROOT "${CMAKE_CURRENT_SOURCE_DIR}")
@@ -36,7 +39,6 @@
 endif ()
 
 include("${AOM_ROOT}/build/cmake/aom_configure.cmake")
-include("${AOM_ROOT}/build/cmake/aom_optimization.cmake")
 include("${AOM_ROOT}/aom_dsp/aom_dsp.cmake")
 include("${AOM_ROOT}/aom_mem/aom_mem.cmake")
 include("${AOM_ROOT}/aom_ports/aom_ports.cmake")
@@ -44,6 +46,7 @@
 include("${AOM_ROOT}/aom_util/aom_util.cmake")
 include("${AOM_ROOT}/av1/av1.cmake")
 include("${AOM_ROOT}/test/test.cmake")
+include("${AOM_ROOT}/build/cmake/util.cmake")
 
 set(AOM_RTCD_SOURCES
     "${AOM_CONFIG_DIR}/aom_dsp_rtcd.h"
@@ -214,9 +217,9 @@
 if (CONFIG_AV1_DECODER)
   add_library(aom_decoder_app_util OBJECT ${AOM_DECODER_APP_UTIL_SOURCES})
   add_executable(aomdec
-               "${AOM_ROOT}/aomdec.c"
-               $<TARGET_OBJECTS:aom_common_app_util>
-               $<TARGET_OBJECTS:aom_decoder_app_util>)
+                 "${AOM_ROOT}/aomdec.c"
+                 $<TARGET_OBJECTS:aom_common_app_util>
+                 $<TARGET_OBJECTS:aom_decoder_app_util>)
 
   if (CONFIG_ANALYZER)
     add_executable(analyzer
@@ -326,7 +329,7 @@
 
   # Add to existing targets.
   foreach (aom_app ${AOM_APP_TARGETS})
-    target_sources(${aom_app} PUBLIC $<TARGET_OBJECTS:yuv>)
+    target_sources(${aom_app} PRIVATE $<TARGET_OBJECTS:yuv>)
     set_property(TARGET ${aom_app} PROPERTY LINKER_LANGUAGE CXX)
   endforeach ()
 endif ()
@@ -341,15 +344,15 @@
 
   # Add to existing targets.
   if (CONFIG_AV1_DECODER)
-    target_sources(aom_decoder_app_util PUBLIC ${AOM_WEBM_DECODER_SOURCES})
+    target_sources(aom_decoder_app_util PRIVATE ${AOM_WEBM_DECODER_SOURCES})
   endif ()
 
   if (CONFIG_AV1_ENCODER)
-    target_sources(aom_encoder_app_util PUBLIC ${AOM_WEBM_ENCODER_SOURCES})
+    target_sources(aom_encoder_app_util PRIVATE ${AOM_WEBM_ENCODER_SOURCES})
   endif ()
 
   foreach (aom_app ${AOM_APP_TARGETS})
-    target_sources(${aom_app} PUBLIC $<TARGET_OBJECTS:webm>)
+    target_sources(${aom_app} PRIVATE $<TARGET_OBJECTS:webm>)
     set_property(TARGET ${aom_app} PROPERTY LINKER_LANGUAGE CXX)
    endforeach ()
 endif ()
@@ -376,11 +379,8 @@
     # Note: LINKER_LANGUAGE is explicitly set to C++ for all targets touched
     # here, it really is the Xcode generator's fault, or just a deficiency in
     # Xcode itself.
-    set(XCODE_DUMMY_CXX_FILE "${AOM_CONFIG_DIR}/dummy.cc")
-    file(WRITE "${XCODE_DUMMY_CXX_FILE}"
-         "// Xcode needs a C++ file to link, ignore this file.")
     foreach (aom_app ${AOM_APP_TARGETS})
-      target_sources(${aom_app} PUBLIC "${XCODE_DUMMY_CXX_FILE}")
+      add_dummy_source_file_to_target("${aom_app}" "cc")
     endforeach ()
   endif ()
 endif ()
@@ -393,6 +393,11 @@
                         RUNTIME_OUTPUT_DIRECTORY "${AOM_CONFIG_DIR}/examples")
 endif ()
 
+if (BUILD_SHARED_LIBS)
+  include("${AOM_ROOT}/build/cmake/exports.cmake")
+  setup_exports_target()
+endif ()
+
 # Aomedia documentation rule.
 if (ENABLE_DOCS)
   include(FindDoxygen)
diff --git a/README.md b/README.md
index 1fc764d..69b7f88 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,16 @@
 in the root of the AV1 repository, and AV1 codec configuration options can
 currently be found in the file `build/cmake/aom_config_defaults.cmake`.
 
+### Dylib builds
+
+A dylib (shared object) build of the AV1 codec library can be enabled via the
+CMake built in variable BUILD\_SHARED\_LIBS:
+
+    $ cmake path/to/aom -D BUILD_SHARED_LIBS=1
+    $ make
+
+This is currently only supported on non-Windows targets.
+
 ### Cross compiling
 
 For the purposes of building the AV1 codec and applications and relative to the
diff --git a/aom_dsp/aom_dsp.cmake b/aom_dsp/aom_dsp.cmake
index a8bd85a..f39da7c 100644
--- a/aom_dsp/aom_dsp.cmake
+++ b/aom_dsp/aom_dsp.cmake
@@ -414,111 +414,123 @@
 # has been created.
 function (setup_aom_dsp_targets)
   add_library(aom_dsp_common OBJECT ${AOM_DSP_COMMON_SOURCES})
-  set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} aom_dsp_common)
-  target_sources(aom PUBLIC $<TARGET_OBJECTS:aom_dsp_common>)
+  list(APPEND AOM_LIB_TARGETS aom_dsp_common)
+  add_library(aom_dsp STATIC $<TARGET_OBJECTS:aom_dsp_common>)
+  list(APPEND AOM_LIB_TARGETS aom_dsp)
+
+  # Not all generators support libraries consisting only of object files. Add a
+  # dummy source file to the aom_dsp target.
+  add_dummy_source_file_to_target("aom_dsp" "c")
 
   if (CONFIG_AV1_DECODER)
     add_library(aom_dsp_decoder OBJECT ${AOM_DSP_DECODER_SOURCES})
     set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} aom_dsp_decoder)
-    target_sources(aom PUBLIC $<TARGET_OBJECTS:aom_dsp_decoder>)
+    target_sources(aom_dsp PRIVATE $<TARGET_OBJECTS:aom_dsp_decoder>)
   endif ()
 
   if (CONFIG_AV1_ENCODER)
     add_library(aom_dsp_encoder OBJECT ${AOM_DSP_ENCODER_SOURCES})
     set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} aom_dsp_encoder)
-    target_sources(aom PUBLIC $<TARGET_OBJECTS:aom_dsp_encoder>)
+    target_sources(aom_dsp PRIVATE $<TARGET_OBJECTS:aom_dsp_encoder>)
   endif ()
 
   if (HAVE_SSE2)
-    add_asm_library("aom_dsp_common_sse2" "AOM_DSP_COMMON_ASM_SSE2" "aom")
+    add_asm_library("aom_dsp_common_sse2" "AOM_DSP_COMMON_ASM_SSE2" "aom_dsp")
     add_intrinsics_object_library("-msse2" "sse2" "aom_dsp_common"
-                                  "AOM_DSP_COMMON_INTRIN_SSE2")
+                                   "AOM_DSP_COMMON_INTRIN_SSE2" "aom_dsp")
+
     if (CONFIG_AV1_ENCODER)
-      add_asm_library("aom_dsp_encoder_sse2" "AOM_DSP_ENCODER_ASM_SSE2" "aom")
+      add_asm_library("aom_dsp_encoder_sse2" "AOM_DSP_ENCODER_ASM_SSE2"
+                      "aom_dsp")
       add_intrinsics_object_library("-msse2" "sse2" "aom_dsp_encoder"
-                                    "AOM_DSP_ENCODER_INTRIN_SSE2")
+                                    "AOM_DSP_ENCODER_INTRIN_SSE2" "aom_dsp")
     endif()
   endif ()
 
   if (HAVE_SSE3 AND CONFIG_AV1_ENCODER)
-    add_asm_library("aom_dsp_encoder_sse3" "AOM_DSP_ENCODER_INTRIN_SSE3" "aom")
+    add_asm_library("aom_dsp_encoder_sse3" "AOM_DSP_ENCODER_INTRIN_SSE3"
+                    "aom_dsp")
   endif ()
 
   if (HAVE_SSSE3)
-    add_asm_library("aom_dsp_common_ssse3" "AOM_DSP_COMMON_ASM_SSSE3" "aom")
+    add_asm_library("aom_dsp_common_ssse3" "AOM_DSP_COMMON_ASM_SSSE3" "aom_dsp")
     add_intrinsics_object_library("-mssse3" "ssse3" "aom_dsp_common"
-                                  "AOM_DSP_COMMON_INTRIN_SSSE3")
+                                  "AOM_DSP_COMMON_INTRIN_SSSE3" "aom_dsp")
 
     if (CONFIG_AV1_ENCODER)
       if ("${AOM_TARGET_CPU}" STREQUAL "x86_64")
         list(APPEND AOM_DSP_ENCODER_ASM_SSSE3
              ${AOM_DSP_ENCODER_ASM_SSSE3_X86_64})
       endif ()
-      add_asm_library("aom_dsp_encoder_ssse3" "AOM_DSP_ENCODER_ASM_SSSE3" "aom")
-
+      add_asm_library("aom_dsp_encoder_ssse3" "AOM_DSP_ENCODER_ASM_SSSE3"
+                      "aom_dsp")
       if (AOM_DSP_ENCODER_INTRIN_SSSE3)
         add_intrinsics_object_library("-mssse3" "ssse3" "aom_dsp_encoder"
-                                      "AOM_DSP_ENCODER_INTRIN_SSSE3")
+                                      "AOM_DSP_ENCODER_INTRIN_SSSE3" "aom_dsp")
       endif ()
     endif ()
   endif ()
 
   if (HAVE_SSE4_1)
     add_intrinsics_object_library("-msse4.1" "sse4_1" "aom_dsp_common"
-                                  "AOM_DSP_COMMON_INTRIN_SSE4_1")
+                                  "AOM_DSP_COMMON_INTRIN_SSE4_1" "aom_dsp")
     if (CONFIG_AV1_ENCODER)
       if (AOM_DSP_ENCODER_INTRIN_SSE4_1)
         add_intrinsics_object_library("-msse4.1" "sse4_1" "aom_dsp_encoder"
-                                      "AOM_DSP_ENCODER_INTRIN_SSE4_1")
+                                      "AOM_DSP_ENCODER_INTRIN_SSE4_1" "aom_dsp")
       endif ()
       add_asm_library("aom_dsp_encoder_sse4_1" "AOM_DSP_ENCODER_ASM_SSE4_1"
-                      "aom")
+                      "aom_dsp")
     endif ()
   endif ()
 
   if (HAVE_AVX AND "${AOM_TARGET_CPU}" STREQUAL "x86_64")
     if (CONFIG_AV1_ENCODER)
       add_asm_library("aom_dsp_encoder_avx" "AOM_DSP_ENCODER_AVX_ASM_X86_64"
-                      "aom")
+                      "aom_dsp")
     endif ()
   endif ()
 
   if (HAVE_AVX2)
     add_intrinsics_object_library("-mavx2" "avx2" "aom_dsp_common"
-                                  "AOM_DSP_COMMON_INTRIN_AVX2")
+                                  "AOM_DSP_COMMON_INTRIN_AVX2" "aom_dsp")
     if (CONFIG_AV1_ENCODER)
       add_intrinsics_object_library("-mavx2" "avx2" "aom_dsp_encoder"
-                                    "AOM_DSP_ENCODER_INTRIN_AVX2")
+                                    "AOM_DSP_ENCODER_INTRIN_AVX2" "aom_dsp")
     endif ()
   endif ()
 
   if (HAVE_NEON_ASM)
     if (AOM_ADS2GAS_REQUIRED)
-      add_gas_asm_library("aom_dsp_common_neon" "AOM_DSP_COMMON_ASM_NEON" "aom")
+      add_gas_asm_library("aom_dsp_common_neon" "AOM_DSP_COMMON_ASM_NEON"
+                          "aom_dsp")
     else ()
-      add_asm_library("aom_dsp_common_neon" "AOM_DSP_COMMON_ASM_NEON" "aom")
+      add_asm_library("aom_dsp_common_neon" "AOM_DSP_COMMON_ASM_NEON" "aom_dsp")
     endif ()
   endif ()
 
   if (HAVE_NEON)
     add_intrinsics_object_library("${AOM_NEON_INTRIN_FLAG}" "neon"
-                                  "aom_dsp_common" "AOM_DSP_COMMON_INTRIN_NEON")
+                                  "aom_dsp_common" "AOM_DSP_COMMON_INTRIN_NEON"
+                                  "aom_dsp")
   endif ()
 
   if (HAVE_DSPR2)
     add_intrinsics_object_library("" "dspr2" "aom_dsp_common"
-                                  "AOM_DSP_COMMON_INTRIN_DSPR2")
+                                  "AOM_DSP_COMMON_INTRIN_DSPR2" "aom_dsp")
   endif ()
 
   if (HAVE_MSA)
     add_intrinsics_object_library("" "msa" "aom_dsp_common"
-                                  "AOM_DSP_COMMON_INTRIN_MSA")
+                                  "AOM_DSP_COMMON_INTRIN_MSA" "aom_dsp")
     if (CONFIG_AV1_ENCODER)
       add_intrinsics_object_library("" "msa" "aom_dsp_encoder"
-                                    "AOM_DSP_ENCODER_INTRIN_MSA")
+                                    "AOM_DSP_ENCODER_INTRIN_MSA" "aom_dsp")
     endif ()
   endif ()
 
+  target_link_libraries(aom PRIVATE aom_dsp)
+
   # Pass the new lib targets up to the parent scope instance of
   # $AOM_LIB_TARGETS.
   set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} PARENT_SCOPE)
diff --git a/aom_mem/aom_mem.cmake b/aom_mem/aom_mem.cmake
index 6ea5ae0..a064a9d 100644
--- a/aom_mem/aom_mem.cmake
+++ b/aom_mem/aom_mem.cmake
@@ -19,9 +19,9 @@
 # Creates the aom_mem build target and makes libaom depend on it. The libaom
 # target must exist before this function is called.
 function (setup_aom_mem_targets)
-  add_library(aom_mem OBJECT ${AOM_MEM_SOURCES})
+  add_library(aom_mem STATIC ${AOM_MEM_SOURCES})
   set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} aom_mem PARENT_SCOPE)
-  target_sources(aom PUBLIC $<TARGET_OBJECTS:aom_mem>)
+  target_link_libraries(aom PRIVATE aom_mem)
 endfunction ()
 
 endif ()  # AOM_AOM_MEM_AOM_MEM_CMAKE_
diff --git a/aom_ports/aom_ports.cmake b/aom_ports/aom_ports.cmake
index 00ec28c..b9063b1 100644
--- a/aom_ports/aom_ports.cmake
+++ b/aom_ports/aom_ports.cmake
@@ -43,27 +43,26 @@
     add_asm_library("aom_ports" "AOM_PORTS_ASM_MMX" "aom")
     set(aom_ports_has_symbols 1)
   elseif ("${AOM_TARGET_CPU}" MATCHES "arm")
-    add_library(aom_ports OBJECT ${AOM_PORTS_SOURCES_ARM})
+    add_library(aom_ports STATIC ${AOM_PORTS_SOURCES_ARM})
     set(aom_ports_has_symbols 1)
-    list(APPEND AOM_LIB_TARGETS aom_ports)
-    target_sources(aom PRIVATE $<TARGET_OBJECTS:aom_ports>)
+    target_link_libraries(aom PRIVATE aom_ports)
   endif ()
 
   if (aom_ports_has_symbols)
-    target_sources(aom_ports PUBLIC ${AOM_PORTS_INCLUDES})
+    target_sources(aom_ports PRIVATE ${AOM_PORTS_INCLUDES})
 
     if ("${AOM_TARGET_CPU}" STREQUAL "x86" OR
         "${AOM_TARGET_CPU}" STREQUAL "x86_64")
-      target_sources(aom_ports PUBLIC ${AOM_PORTS_INCLUDES_X86})
+      target_sources(aom_ports PRIVATE ${AOM_PORTS_INCLUDES_X86})
     endif ()
 
     set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} PARENT_SCOPE)
   else ()
-    target_sources(aom PUBLIC ${AOM_PORTS_INCLUDES})
+    target_sources(aom PRIVATE ${AOM_PORTS_INCLUDES})
 
     if ("${AOM_TARGET_CPU}" STREQUAL "x86" OR
         "${AOM_TARGET_CPU}" STREQUAL "x86_64")
-      target_sources(aom PUBLIC ${AOM_PORTS_INCLUDES_X86})
+      target_sources(aom PRIVATE ${AOM_PORTS_INCLUDES_X86})
     endif ()
   endif ()
 endfunction ()
diff --git a/aom_scale/aom_scale.cmake b/aom_scale/aom_scale.cmake
index e1e3f6c..58d9a5f 100644
--- a/aom_scale/aom_scale.cmake
+++ b/aom_scale/aom_scale.cmake
@@ -25,12 +25,12 @@
 # Creates the aom_scale build target and makes libaom depend on it. The libaom
 # target must exist before this function is called.
 function (setup_aom_scale_targets)
-  add_library(aom_scale OBJECT ${AOM_SCALE_SOURCES})
-  target_sources(aom PUBLIC $<TARGET_OBJECTS:aom_scale>)
+  add_library(aom_scale STATIC ${AOM_SCALE_SOURCES})
+  target_link_libraries(aom PRIVATE aom_scale)
 
   if (HAVE_DSPR2)
     add_intrinsics_object_library("" "dspr2" "aom_scale"
-                                  "AOM_SCALE_INTRIN_DSPR2")
+                                  "AOM_SCALE_INTRIN_DSPR2" "aom_scale")
   endif ()
 
   set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} aom_scale PARENT_SCOPE)
diff --git a/aom_util/aom_util.cmake b/aom_util/aom_util.cmake
index 68f5253..8ffbd51 100644
--- a/aom_util/aom_util.cmake
+++ b/aom_util/aom_util.cmake
@@ -26,9 +26,9 @@
 # Creates the aom_util build target and makes libaom depend on it. The libaom
 # target must exist before this function is called.
 function (setup_aom_util_targets)
-  add_library(aom_util OBJECT ${AOM_UTIL_SOURCES})
+  add_library(aom_util STATIC ${AOM_UTIL_SOURCES})
   set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} aom_util PARENT_SCOPE)
-  target_sources(aom PUBLIC $<TARGET_OBJECTS:aom_util>)
+  target_link_libraries(aom PRIVATE aom_util)
 endfunction ()
 
 endif ()  # AOM_AOM_UTIL_AOM_UTIL_CMAKE_
diff --git a/av1/av1.cmake b/av1/av1.cmake
index 84f141e..a4001e5 100644
--- a/av1/av1.cmake
+++ b/av1/av1.cmake
@@ -442,75 +442,82 @@
 # this function is called.
 function (setup_av1_targets)
   add_library(aom_av1_common OBJECT ${AOM_AV1_COMMON_SOURCES})
-  set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} aom_av1_common)
-  target_sources(aom PUBLIC $<TARGET_OBJECTS:aom_av1_common>)
+  list(APPEND AOM_LIB_TARGETS aom_av1_common)
+  add_library(aom_av1 STATIC $<TARGET_OBJECTS:aom_av1_common>)
+  list(APPEND AOM_LIB_TARGETS aom_av1)
+
+  # Not all generators support libraries consisting only of object files. Add a
+  # dummy source file to the aom_av1 target.
+  add_dummy_source_file_to_target("aom_av1" "c")
 
   if (CONFIG_AV1_DECODER)
     add_library(aom_av1_decoder OBJECT ${AOM_AV1_DECODER_SOURCES})
     set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} aom_av1_decoder)
-    target_sources(aom PUBLIC $<TARGET_OBJECTS:aom_av1_decoder>)
+    target_sources(aom PRIVATE $<TARGET_OBJECTS:aom_av1_decoder>)
   endif ()
 
   if (CONFIG_AV1_ENCODER)
     add_library(aom_av1_encoder OBJECT ${AOM_AV1_ENCODER_SOURCES})
     set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} aom_av1_encoder)
-    target_sources(aom PUBLIC $<TARGET_OBJECTS:aom_av1_encoder>)
+    target_sources(aom PRIVATE $<TARGET_OBJECTS:aom_av1_encoder>)
   endif ()
 
   if (HAVE_SSE2)
     require_flag_nomsvc("-msse2" NO)
     add_intrinsics_object_library("-msse2" "sse2" "aom_av1_common"
-                                  "AOM_AV1_COMMON_INTRIN_SSE2")
+                                  "AOM_AV1_COMMON_INTRIN_SSE2" "aom_av1")
     if (CONFIG_AV1_DECODER)
       if (AOM_AV1_DECODER_ASM_SSE2)
-        add_asm_library("aom_av1_decoder_sse2" "AOM_AV1_DECODER_ASM_SSE2" "aom")
+        add_asm_library("aom_av1_decoder_sse2" "AOM_AV1_DECODER_ASM_SSE2"
+                        "aom_av1")
       endif ()
 
       if (AOM_AV1_DECODER_INTRIN_SSE2)
         add_intrinsics_object_library("-msse2" "sse2" "aom_av1_decoder"
-                                      "AOM_AV1_DECODER_INTRIN_SSE2")
+                                      "AOM_AV1_DECODER_INTRIN_SSE2" "aom_av1")
       endif ()
     endif ()
 
     if (CONFIG_AV1_ENCODER)
-      add_asm_library("aom_av1_encoder_sse2" "AOM_AV1_ENCODER_ASM_SSE2" "aom")
+      add_asm_library("aom_av1_encoder_sse2" "AOM_AV1_ENCODER_ASM_SSE2"
+                      "aom_av1")
       add_intrinsics_object_library("-msse2" "sse2" "aom_av1_encoder"
-                                    "AOM_AV1_ENCODER_INTRIN_SSE2")
+                                    "AOM_AV1_ENCODER_INTRIN_SSE2" "aom_av1")
     endif ()
   endif ()
 
   if (HAVE_SSSE3)
     require_flag_nomsvc("-mssse3" NO)
     add_intrinsics_object_library("-mssse3" "ssse3" "aom_av1_common"
-                                  "AOM_AV1_COMMON_INTRIN_SSSE3")
+                                  "AOM_AV1_COMMON_INTRIN_SSSE3" "aom_av1")
 
     if (CONFIG_AV1_DECODER)
       if (AOM_AV1_DECODER_INTRIN_SSSE3)
         add_intrinsics_object_library("-mssse3" "ssse3" "aom_av1_decoder"
-                                      "AOM_AV1_DECODER_INTRIN_SSSE3")
+                                      "AOM_AV1_DECODER_INTRIN_SSSE3" "aom_av1")
       endif ()
     endif ()
 
     if (CONFIG_AV1_ENCODER)
       add_intrinsics_object_library("-mssse3" "ssse3" "aom_av1_encoder"
-                                    "AOM_AV1_ENCODER_INTRIN_SSSE3")
+                                    "AOM_AV1_ENCODER_INTRIN_SSSE3" "aom_av1")
     endif ()
   endif ()
 
   if (HAVE_SSE4_1)
     require_flag_nomsvc("-msse4.1" NO)
     add_intrinsics_object_library("-msse4.1" "sse4" "aom_av1_common"
-                                  "AOM_AV1_COMMON_INTRIN_SSE4_1")
+                                  "AOM_AV1_COMMON_INTRIN_SSE4_1" "aom_av1")
 
     if (CONFIG_AV1_ENCODER)
       if ("${AOM_TARGET_CPU}" STREQUAL "x86_64")
         add_asm_library("aom_av1_encoder_ssse3"
-                        "AOM_AV1_ENCODER_ASM_SSSE3_X86_64" "aom")
+                        "AOM_AV1_ENCODER_ASM_SSSE3_X86_64" "aom_av1")
       endif ()
 
       if (AOM_AV1_ENCODER_INTRIN_SSE4_1)
         add_intrinsics_object_library("-msse4.1" "sse4" "aom_av1_encoder"
-                                      "AOM_AV1_ENCODER_INTRIN_SSE4_1")
+                                      "AOM_AV1_ENCODER_INTRIN_SSE4_1" "aom_av1")
       endif ()
     endif ()
   endif ()
@@ -518,11 +525,11 @@
   if (HAVE_AVX2)
     require_flag_nomsvc("-mavx2" NO)
     add_intrinsics_object_library("-mavx2" "avx2" "aom_av1_common"
-                                  "AOM_AV1_COMMON_INTRIN_AVX2")
+                                  "AOM_AV1_COMMON_INTRIN_AVX2" "aom_av1")
 
     if (CONFIG_AV1_ENCODER)
       add_intrinsics_object_library("-mavx2" "avx2" "aom_av1_encoder"
-                                    "AOM_AV1_ENCODER_INTRIN_AVX2")
+                                    "AOM_AV1_ENCODER_INTRIN_AVX2" "aom_av1")
     endif ()
   endif ()
 
@@ -531,29 +538,32 @@
       add_intrinsics_object_library("${AOM_INTRIN_NEON_FLAG}"
                                     "neon"
                                     "aom_av1_common"
-                                    "AOM_AV1_COMMON_INTRIN_NEON")
+                                    "AOM_AV1_COMMON_INTRIN_NEON" "aom_av1")
     endif ()
 
     if (AOM_AV1_ENCODER_INTRIN_NEON)
       add_intrinsics_object_library("${AOM_INTRIN_NEON_FLAG}"
                                     "neon"
                                     "aom_av1_encoder"
-                                    "AOM_AV1_ENCODER_INTRIN_NEON")
+                                    "AOM_AV1_ENCODER_INTRIN_NEON" "aom_av1")
     endif ()
   endif ()
 
   if (HAVE_DSPR2)
     add_intrinsics_object_library("" "dspr2" "aom_av1_common"
-                                  "AOM_AV1_COMMON_INTRIN_DSPR2")
+                                  "AOM_AV1_COMMON_INTRIN_DSPR2" "aom_av1")
   endif ()
 
   if (HAVE_MSA)
     add_intrinsics_object_library("" "msa" "aom_av1_common"
-                                  "AOM_AV1_COMMON_INTRIN_MSA")
+                                  "AOM_AV1_COMMON_INTRIN_MSA" "aom_av1")
     add_intrinsics_object_library("" "msa" "aom_av1_encoder"
-                                  "AOM_AV1_ENCODER_INTRIN_MSA")
+                                  "AOM_AV1_ENCODER_INTRIN_MSA" "aom_av1")
   endif ()
 
+  target_link_libraries(aom_av1 PRIVATE aom_dsp aom_scale)
+  target_link_libraries(aom PRIVATE aom_av1)
+
   # Pass the new lib targets up to the parent scope instance of
   # $AOM_LIB_TARGETS.
   set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} PARENT_SCOPE)
diff --git a/build/cmake/aom_configure.cmake b/build/cmake/aom_configure.cmake
index 8c749d3..75e58ea 100644
--- a/build/cmake/aom_configure.cmake
+++ b/build/cmake/aom_configure.cmake
@@ -83,6 +83,19 @@
 message("--- aom_configure: Detected CPU: ${AOM_TARGET_CPU}")
 set(AOM_TARGET_SYSTEM ${CMAKE_SYSTEM_NAME})
 
+if (BUILD_SHARED_LIBS)
+  set(CONFIG_PIC 1)
+  set(CONFIG_SHARED 1)
+  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+  if ("${AOM_TARGET_SYSTEM}" STREQUAL "Linux" AND
+      "${AOM_TARGET_CPU}" MATCHES "^armv7")
+    set(AOM_AS_FLAGS ${AOM_AS_FLAGS} --defsym PIC=1)
+  else ()
+    set(AOM_AS_FLAGS ${AOM_AS_FLAGS} -DPIC)
+  endif ()
+endif ()
+
 if (NOT "${AOM_SUPPORTED_CPU_TARGETS}" MATCHES "${AOM_TARGET_CPU}")
   message(FATAL_ERROR "No RTCD support for ${AOM_TARGET_CPU}. Create it, or "
           "add -DAOM_TARGET_CPU=generic to your cmake command line for a "
diff --git a/build/cmake/aom_optimization.cmake b/build/cmake/aom_optimization.cmake
index 8110760..18cbed2 100644
--- a/build/cmake/aom_optimization.cmake
+++ b/build/cmake/aom_optimization.cmake
@@ -11,6 +11,8 @@
 if (NOT AOM_BUILD_CMAKE_AOM_OPTIMIZATION_CMAKE_)
 set(AOM_BUILD_CMAKE_AOM_OPTIMIZATION_CMAKE_ 1)
 
+include("${AOM_ROOT}/build/cmake/util.cmake")
+
 # Translate $flag to one which MSVC understands, and write the new flag to the
 # variable named by $translated_flag (or unset it, when MSVC needs no flag).
 function (get_msvc_intrinsic_flag flag translated_flag)
@@ -33,7 +35,8 @@
 # Note: the libaom target is always updated because OBJECT libraries have rules
 # that disallow the direct addition of .o files to them as dependencies. Static
 # libraries do not have this limitation.
-function (add_intrinsics_object_library flag opt_name target_to_update sources)
+function (add_intrinsics_object_library flag opt_name target_to_update sources
+          dependent_target)
   set(target_name ${target_to_update}_${opt_name}_intrinsics)
   add_library(${target_name} OBJECT ${${sources}})
 
@@ -45,7 +48,7 @@
     target_compile_options(${target_name} PUBLIC ${flag})
   endif ()
 
-  target_sources(aom PUBLIC $<TARGET_OBJECTS:${target_name}>)
+  target_sources(${dependent_target} PRIVATE $<TARGET_OBJECTS:${target_name}>)
 
   # Add the new lib target to the global list of aom library targets.
   list(APPEND AOM_LIB_TARGETS ${target_name})
@@ -55,7 +58,7 @@
 # Adds sources in list named by $sources to $target and adds $flag to the
 # compile flags for each source file.
 function (add_intrinsics_source_to_target flag target sources)
-  target_sources(${target} PUBLIC ${${sources}})
+  target_sources(${target} PRIVATE ${${sources}})
   if (MSVC)
     get_msvc_intrinsic_flag(${flag} "flag")
   endif ()
@@ -136,14 +139,9 @@
   # 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).
-  set(dummy_c_file "${AOM_CONFIG_DIR}/${lib_name}_dummy.c")
-  file(WRITE "${dummy_c_file}"
-       "// Generated file. DO NOT EDIT!\n"
-       "// ${lib_name} needs C file to force link language, ignore me.\n"
-       "void ${lib_name}_dummy_function(void) {}\n")
-  target_sources(${lib_name} PUBLIC ${dummy_c_file})
+  add_dummy_source_file_to_target("${lib_name}" "c")
 
-  target_link_libraries(${dependent_target} ${AOM_LIB_LINK_TYPE} ${lib_name})
+  target_link_libraries(${dependent_target} PRIVATE ${lib_name})
 
   # Add the new lib target to the global list of aom library targets.
   list(APPEND AOM_LIB_TARGETS ${lib_name})
diff --git a/build/cmake/exports.cmake b/build/cmake/exports.cmake
new file mode 100644
index 0000000..8153aad
--- /dev/null
+++ b/build/cmake/exports.cmake
@@ -0,0 +1,65 @@
+##
+## Copyright (c) 2017, Alliance for Open Media. All rights reserved
+##
+## This source code is subject to the terms of the BSD 2 Clause License and
+## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+## was not distributed with this source code in the LICENSE file, you can
+## obtain it at www.aomedia.org/license/software. If the Alliance for Open
+## Media Patent License 1.0 was not distributed with this source code in the
+## PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+##
+if (NOT AOM_BUILD_CMAKE_EXPORTS_CMAKE_)
+set(AOM_BUILD_CMAKE_EXPORTS_CMAKE_ 1)
+
+include("${AOM_ROOT}/build/cmake/exports_sources.cmake")
+
+# Creates the custom target which handles generation of the symbol export lists.
+function (setup_exports_target)
+  if ("${AOM_TARGET_SYSTEM}" STREQUAL "Darwin")
+    set(symbol_file_ext "syms")
+  elseif ("${AOM_TARGET_SYSTEM}" MATCHES "Windows\|MSYS" AND MSVC)
+    set(symbol_file_ext "def")
+  else ()
+    set(symbol_file_ext "ver")
+  endif ()
+
+  set(aom_sym_file "${AOM_CONFIG_DIR}/libaom.${symbol_file_ext}")
+
+  add_custom_target(generate_exports
+                    COMMAND ${CMAKE_COMMAND}
+                      -DAOM_ROOT="${AOM_ROOT}"
+                      -DAOM_CONFIG_DIR="${AOM_CONFIG_DIR}"
+                      -DAOM_TARGET_SYSTEM=${AOM_TARGET_SYSTEM}
+                      -DAOM_SYM_FILE="${aom_sym_file}"
+                      -DAOM_MSVC=${MSVC}
+                      -DAOM_XCODE=${XCODE}
+                      -DCONFIG_NAME=$<CONFIG>
+                      -DCONFIG_AV1_DECODER=${CONFIG_AV1_DECODER}
+                      -DCONFIG_AV1_ENCODER=${CONFIG_AV1_ENCODER}
+                      -P "${AOM_ROOT}/build/cmake/generate_exports.cmake"
+                    SOURCES ${AOM_EXPORTS_SOURCES}
+                    DEPENDS ${AOM_EXPORTS_SOURCES})
+
+  # Make libaom depend on the exports file, and set flags to pick it up when
+  # creating the dylib.
+  add_dependencies(aom generate_exports)
+
+  if (APPLE)
+    set_property(TARGET aom APPEND_STRING PROPERTY LINK_FLAGS
+                 "-exported_symbols_list ${aom_sym_file}")
+  elseif (WIN32)
+    message(FATAL_ERROR "Windows DLL builds not supported yet.")
+    if (NOT MSVC)
+      set_property(TARGET aom APPEND_STRING PROPERTY LINK_FLAGS
+                   "-Wl,--version-script ${aom_sym_file}")
+    endif ()
+
+    # TODO(tomfinegan): Sort out the import lib situation and flags for MSVC.
+
+  else ()
+    set_property(TARGET aom APPEND_STRING PROPERTY LINK_FLAGS
+                 "-Wl,--version-script,${aom_sym_file}")
+  endif ()
+endfunction ()
+
+endif ()  # AOM_BUILD_CMAKE_EXPORTS_CMAKE_
diff --git a/build/cmake/exports_sources.cmake b/build/cmake/exports_sources.cmake
new file mode 100644
index 0000000..36f79ee
--- /dev/null
+++ b/build/cmake/exports_sources.cmake
@@ -0,0 +1,30 @@
+##
+## Copyright (c) 2017, Alliance for Open Media. All rights reserved
+##
+## This source code is subject to the terms of the BSD 2 Clause License and
+## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+## was not distributed with this source code in the LICENSE file, you can
+## obtain it at www.aomedia.org/license/software. If the Alliance for Open
+## Media Patent License 1.0 was not distributed with this source code in the
+## PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+##
+if (NOT AOM_BUILD_CMAKE_EXPORTS_SOURCES_CMAKE_)
+set(AOM_BUILD_CMAKE_EXPORTS_SOURCES_CMAKE_ 1)
+
+set(AOM_EXPORTS_SOURCES "${AOM_ROOT}/aom/exports_com")
+
+if (CONFIG_AV1_DECODER)
+  set(AOM_EXPORTS_SOURCES
+      ${AOM_EXPORTS_SOURCES}
+      "${AOM_ROOT}/aom/exports_dec"
+      "${AOM_ROOT}/av1/exports_dec")
+endif ()
+
+if (CONFIG_AV1_ENCODER)
+  set(AOM_EXPORTS_SOURCES
+      ${AOM_EXPORTS_SOURCES}
+      "${AOM_ROOT}/aom/exports_enc"
+      "${AOM_ROOT}/av1/exports_enc")
+endif ()
+
+endif ()  # AOM_BUILD_CMAKE_EXPORTS_SOURCES_CMAKE_
diff --git a/build/cmake/generate_exports.cmake b/build/cmake/generate_exports.cmake
new file mode 100644
index 0000000..baa2982
--- /dev/null
+++ b/build/cmake/generate_exports.cmake
@@ -0,0 +1,64 @@
+##
+## Copyright (c) 2017, Alliance for Open Media. All rights reserved
+##
+## This source code is subject to the terms of the BSD 2 Clause License and
+## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+## was not distributed with this source code in the LICENSE file, you can
+## obtain it at www.aomedia.org/license/software. If the Alliance for Open
+## Media Patent License 1.0 was not distributed with this source code in the
+## PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+##
+cmake_minimum_required(VERSION 3.5)
+
+set(REQUIRED_ARGS "AOM_ROOT" "AOM_CONFIG_DIR" "AOM_TARGET_SYSTEM" "AOM_SYM_FILE"
+    "CONFIG_AV1_DECODER" "CONFIG_AV1_ENCODER")
+
+foreach (arg ${REQUIRED_ARGS})
+  if ("${${arg}}" STREQUAL "")
+    message(FATAL_ERROR "${arg} must not be empty.")
+  endif ()
+endforeach ()
+
+include("${AOM_ROOT}/build/cmake/exports_sources.cmake")
+
+if ("${AOM_TARGET_SYSTEM}" STREQUAL "Darwin")
+  set(symbol_prefix "_")
+elseif ("${AOM_TARGET_SYSTEM}" MATCHES "Windows\|MSYS" AND AOM_MSVC)
+  set(symbol_prefix "_")
+  file(WRITE "${AOM_SYM_FILE}"
+       "LIBRARY libaom INITINSTANCE TERMINSTANCE\n"
+       "DATA MULTIPLE NONSHARED\n"
+       "EXPORTS\n")
+else ()
+  set(symbol_suffix ";")
+endif ()
+
+set(aom_sym_file "${AOM_SYM_FILE}")
+
+if ("${AOM_TARGET_SYSTEM}" STREQUAL "Darwin")
+  file(REMOVE "${aom_sym_file}")
+elseif ("${AOM_TARGET_SYSTEM}" MATCHES "Windows\|MSYS")
+  file(WRITE "${aom_sym_file}"
+       "LIBRARY libaom INITINSTANCE TERMINSTANCE\n"
+       "DATA MULTIPLE NONSHARED\n"
+       "EXPORTS\n")
+else ()
+  file(WRITE "${aom_sym_file}" "{ global:\n")
+endif ()
+
+foreach (export_file ${AOM_EXPORTS_SOURCES})
+  file(STRINGS "${export_file}" exported_file_data)
+  set(exported_symbols "${exported_symbols} ${exported_file_data};")
+  string(STRIP "${exported_symbols}" exported_symbols)
+endforeach ()
+
+foreach (exported_symbol ${exported_symbols})
+  string(STRIP "${exported_symbol}" exported_symbol)
+  string(REGEX REPLACE "text \|data " "" "exported_symbol" "${exported_symbol}")
+  set(exported_symbol "${symbol_prefix}${exported_symbol}${symbol_suffix}")
+  file(APPEND "${aom_sym_file}" "${exported_symbol}\n")
+endforeach ()
+
+if ("${aom_sym_file}" MATCHES "ver$")
+  file(APPEND "${aom_sym_file}" " };")
+endif ()
diff --git a/build/cmake/util.cmake b/build/cmake/util.cmake
new file mode 100644
index 0000000..9aad172
--- /dev/null
+++ b/build/cmake/util.cmake
@@ -0,0 +1,25 @@
+##
+## Copyright (c) 2017, Alliance for Open Media. All rights reserved
+##
+## This source code is subject to the terms of the BSD 2 Clause License and
+## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+## was not distributed with this source code in the LICENSE file, you can
+## obtain it at www.aomedia.org/license/software. If the Alliance for Open
+## Media Patent License 1.0 was not distributed with this source code in the
+## PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+##
+if (NOT AOM_BUILD_CMAKE_UTIL_CMAKE_)
+set(AOM_BUILD_CMAKE_UTIL_CMAKE_ 1)
+
+function (add_dummy_source_file_to_target target_name extension)
+  set(dummy_source_file "${AOM_CONFIG_DIR}/${target_name}_dummy.${extension}")
+  file(WRITE "${dummy_source_file}"
+       "// Generated file. DO NOT EDIT!\n"
+       "// ${target_name} needs a ${extension} file to force link language, \n"
+       "// ignore me.\n"
+       "void ${target_name}_dummy_function(void) {}\n")
+  target_sources(${target_name} PRIVATE ${dummy_source_file})
+endfunction ()
+
+endif()  # AOM_BUILD_CMAKE_UTIL_CMAKE_
+
diff --git a/test/test.cmake b/test/test.cmake
index a5abb19..b7566b7 100644
--- a/test/test.cmake
+++ b/test/test.cmake
@@ -301,6 +301,11 @@
   include_directories(
     "${AOM_ROOT}/third_party/googletest/src/googletest/src"
     "${AOM_ROOT}/third_party/googletest/src/googletest/include")
+
+  if (BUILD_SHARED_LIBS AND APPLE)
+    # Silence an RPATH warning.
+    set(CMAKE_MACOSX_RPATH 1)
+  endif ()
   add_subdirectory("${AOM_ROOT}/third_party/googletest/src/googletest"
                    EXCLUDE_FROM_ALL)
 
@@ -324,30 +329,27 @@
     add_library(test_aom_encoder OBJECT ${AOM_UNIT_TEST_ENCODER_SOURCES})
   endif ()
 
-  set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} test_aom_common test_aom_decoder
-      test_aom_encoder PARENT_SCOPE)
-
   add_executable(test_libaom ${AOM_UNIT_TEST_WRAPPER_SOURCES}
                  $<TARGET_OBJECTS:aom_common_app_util>
                  $<TARGET_OBJECTS:test_aom_common>)
 
   if (CONFIG_AV1_DECODER)
-    target_sources(test_libaom PUBLIC
+    target_sources(test_libaom PRIVATE
                    $<TARGET_OBJECTS:aom_decoder_app_util>
                    $<TARGET_OBJECTS:test_aom_decoder>)
 
     if (CONFIG_DECODE_PERF_TESTS AND CONFIG_WEBM_IO)
-      target_sources(test_libaom PUBLIC ${AOM_DECODE_PERF_TEST_SOURCES})
+      target_sources(test_libaom PRIVATE ${AOM_DECODE_PERF_TEST_SOURCES})
     endif ()
   endif ()
 
   if (CONFIG_AV1_ENCODER)
-    target_sources(test_libaom PUBLIC
+    target_sources(test_libaom PRIVATE
                    $<TARGET_OBJECTS:test_aom_encoder>
                    $<TARGET_OBJECTS:aom_encoder_app_util>)
 
     if (CONFIG_ENCODE_PERF_TESTS)
-      target_sources(test_libaom PUBLIC ${AOM_ENCODE_PERF_TEST_SOURCES})
+      target_sources(test_libaom PRIVATE ${AOM_ENCODE_PERF_TEST_SOURCES})
     endif ()
 
     if (NOT BUILD_SHARED_LIBS)
@@ -362,11 +364,10 @@
   target_link_libraries(test_libaom ${AOM_LIB_LINK_TYPE} aom gtest)
 
   if (CONFIG_LIBYUV)
-    target_sources(test_libaom PUBLIC $<TARGET_OBJECTS:yuv>)
+    target_sources(test_libaom PRIVATE $<TARGET_OBJECTS:yuv>)
   endif ()
   if (CONFIG_WEBM_IO)
-    target_sources(test_libaom PUBLIC ${AOM_UNIT_TEST_WEBM_SOURCES}
-                   $<TARGET_OBJECTS:webm>)
+    target_sources(test_libaom PRIVATE $<TARGET_OBJECTS:webm>)
   endif ()
   if (HAVE_SSE2)
     add_intrinsics_source_to_target("-msse2" "test_libaom"
@@ -386,6 +387,10 @@
       endif ()
     endif ()
   endif ()
+  if (HAVE_AVX2)
+    add_intrinsics_source_to_target("-mavx2" "test_libaom"
+                                    "AOM_UNIT_TEST_COMMON_INTRIN_AVX2")
+  endif ()
   if (HAVE_NEON)
     add_intrinsics_source_to_target("${AOM_NEON_INTRIN_FLAG}" "test_libaom"
                                     "AOM_UNIT_TEST_COMMON_INTRIN_NEON")