[ASan] CMake support for building ASan runtime as a universal binary on Mac

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@161665 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d8985c2..a7d9a89 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -48,6 +48,18 @@
             COMPILE_DEFINITIONS "${TARGET_I386_CFLAGS}"
             CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${TARGET_I386_CFLAGS}")
 
+function(filter_available_targets out_var)
+  set(archs)
+  foreach(arch ${ARGN})
+    if(${arch} STREQUAL "x86_64" AND CAN_TARGET_X86_64)
+      list(APPEND archs ${arch})
+    elseif (${arch} STREQUAL "i386" AND CAN_TARGET_I386)
+      list(APPEND archs ${arch})
+    endif()
+  endforeach()
+  set(${out_var} ${archs} PARENT_SCOPE)
+endfunction()
+
 # Because compiler-rt spends a lot of time setting up custom compile flags,
 # define a handy helper function for it. The compile flags setting in CMake
 # has serious issues that make its syntax challenging at best.
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 6701965..c39bb0c 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -15,8 +15,8 @@
   set(CLANG_RUNTIME_LIB_DIR
       ${LLVM_BINARY_DIR}/lib/clang/${CLANG_VERSION}/lib/linux)
 endif()
-function(add_clang_runtime_static_library target_name)
-  set_target_properties(${target_name} PROPERTIES
+function(add_clang_runtime_static_library target_names)
+  set_target_properties(${target_names} PROPERTIES
                         ARCHIVE_OUTPUT_DIRECTORY ${CLANG_RUNTIME_LIB_DIR})
 endfunction()
 
@@ -26,9 +26,9 @@
 add_subdirectory(interception)
 add_subdirectory(sanitizer_common)
 
+# FIXME: Add support for tsan library.
 # FIXME: Add support for the profile library.
 
-
 # The top-level lib directory contains a large amount of C code which provides
 # generic implementations of the core runtime library along with optimized
 # architecture-specific code in various subdirectories.
diff --git a/lib/asan/CMakeLists.txt b/lib/asan/CMakeLists.txt
index 111f80e..9d81ca5 100644
--- a/lib/asan/CMakeLists.txt
+++ b/lib/asan/CMakeLists.txt
@@ -46,37 +46,48 @@
   ASAN_NEEDS_SEGV=1
   )
 
-# FIXME: We need to build universal binaries on OS X instead of
-# two arch-specific binaries.
+set(ASAN_RUNTIME_LIBRARIES)
+if(APPLE)
+  # Build universal binary on APPLE.
+  add_library(clang_rt.asan_osx STATIC
+    ${ASAN_SOURCES}
+    $<TARGET_OBJECTS:RTInterception.osx>
+    $<TARGET_OBJECTS:RTSanitizerCommon.osx>
+    )
+  set_target_compile_flags(clang_rt.asan_osx ${ASAN_CFLAGS})
+  filter_available_targets(ASAN_TARGETS x86_64 i386)
+  set_target_properties(clang_rt.asan_osx PROPERTIES
+    OSX_ARCHITECTURES "${ASAN_TARGETS}")
+  list(APPEND ASAN_RUNTIME_LIBRARIES clang_rt.asan_osx)
+else()
+  # Otherwise, build separate libraries for each target.
+  if(CAN_TARGET_X86_64)
+    add_library(clang_rt.asan-x86_64 STATIC
+      ${ASAN_SOURCES}
+      $<TARGET_OBJECTS:RTInterception.x86_64>
+      $<TARGET_OBJECTS:RTSanitizerCommon.x86_64>
+      )
+    set_target_compile_flags(clang_rt.asan-x86_64
+      ${ASAN_CFLAGS} ${TARGET_X86_64_CFLAGS}
+      )
+    list(APPEND ASAN_RUNTIME_LIBRARIES clang_rt.asan-x86_64)
+  endif()
+  if(CAN_TARGET_I386)
+    add_library(clang_rt.asan-i386 STATIC
+      ${ASAN_SOURCES}
+      $<TARGET_OBJECTS:RTInterception.i386>
+      $<TARGET_OBJECTS:RTSanitizerCommon.i386>
+      )
+    set_target_compile_flags(clang_rt.asan-i386
+      ${ASAN_CFLAGS} ${TARGET_I386_CFLAGS}
+      )
+    list(APPEND ASAN_RUNTIME_LIBRARIES clang_rt.asan-i386)
+  endif()
+endif()
 
-if(CAN_TARGET_X86_64)
-  add_library(clang_rt.asan-x86_64 STATIC
-    ${ASAN_SOURCES}
-    $<TARGET_OBJECTS:RTInterception.x86_64>
-    $<TARGET_OBJECTS:RTSanitizerCommon.x86_64>
-    )
-  set_target_compile_flags(clang_rt.asan-x86_64
-    ${ASAN_CFLAGS}
-    ${TARGET_X86_64_CFLAGS}
-    )
-  set_property(TARGET clang_rt.asan-x86_64 APPEND PROPERTY COMPILE_DEFINITIONS
-    ${ASAN_COMMON_DEFINITIONS})
-  add_clang_runtime_static_library(clang_rt.asan-x86_64)
-endif()
-if(CAN_TARGET_I386)
-  add_library(clang_rt.asan-i386 STATIC
-    ${ASAN_SOURCES}
-    $<TARGET_OBJECTS:RTInterception.i386>
-    $<TARGET_OBJECTS:RTSanitizerCommon.i386>
-    )
-  set_target_compile_flags(clang_rt.asan-i386
-    ${ASAN_CFLAGS}
-    ${TARGET_I386_CFLAGS}
-    )
-  set_property(TARGET clang_rt.asan-i386 APPEND PROPERTY COMPILE_DEFINITIONS
-    ${ASAN_COMMON_DEFINITIONS})
-  add_clang_runtime_static_library(clang_rt.asan-i386)
-endif()
+set_property(TARGET ${ASAN_RUNTIME_LIBRARIES} APPEND PROPERTY
+  COMPILE_DEFINITIONS ${ASAN_COMMON_DEFINITIONS})
+add_clang_runtime_static_library(${ASAN_RUNTIME_LIBRARIES})
 
 if(LLVM_INCLUDE_TESTS)
   add_subdirectory(tests)
diff --git a/lib/asan/lit_tests/CMakeLists.txt b/lib/asan/lit_tests/CMakeLists.txt
index c754074..3f3bf44 100644
--- a/lib/asan/lit_tests/CMakeLists.txt
+++ b/lib/asan/lit_tests/CMakeLists.txt
@@ -16,7 +16,7 @@
   # and can be sure that clang would produce working binaries.
   set(ASAN_TEST_DEPS
     clang clang-headers FileCheck count not
-    clang-rt.asan-x86_64 clang-rt.asan-i386
+    ${ASAN_RUNTIME_LIBRARIES}
     )
   if(LLVM_INCLUDE_TESTS)
     list(APPEND ASAN_TEST_DEPS AsanUnitTests)
diff --git a/lib/asan/tests/CMakeLists.txt b/lib/asan/tests/CMakeLists.txt
index a17b811..07f540e 100644
--- a/lib/asan/tests/CMakeLists.txt
+++ b/lib/asan/tests/CMakeLists.txt
@@ -51,19 +51,20 @@
 set_target_properties(AsanUnitTests PROPERTIES FOLDER "ASan unit tests")
 function(add_asan_test testname)
   add_unittest(AsanUnitTests ${testname} ${ARGN})
-  if(LLVM_BUILD_32_BITS)
-    target_link_libraries(${testname} clang_rt.asan-i386)
-  else()
-    target_link_libraries(${testname} clang_rt.asan-x86_64)
-  endif()
   if (APPLE)
     # Darwin-specific linker flags.
     set_property(TARGET ${testname} APPEND PROPERTY
                  LINK_FLAGS "-framework Foundation")
+    target_link_libraries(${testname} clang_rt.asan_osx)
   elseif (UNIX)
     # Linux-specific linker flags.
     set_property(TARGET ${testname} APPEND PROPERTY
                  LINK_FLAGS "-lpthread -ldl -export-dynamic")
+    if(LLVM_BUILD_32_BITS)
+      target_link_libraries(${testname} clang_rt.asan-i386)
+    else()
+      target_link_libraries(${testname} clang_rt.asan-x86_64)
+    endif()
   endif()
   set(add_compile_flags "")
   get_property(compile_flags TARGET ${testname} PROPERTY COMPILE_FLAGS)
@@ -99,7 +100,7 @@
               -c -o "${output_obj}"
               ${CMAKE_CURRENT_SOURCE_DIR}/${source}
       MAIN_DEPENDENCY ${source}
-      DEPENDS clang clang_rt.asan-i386 clang_rt.asan-x86_64 ${ARGN}
+      DEPENDS clang ${ASAN_RUNTIME_LIBRARIES} ${ARGN}
       )
   endfunction()
 
diff --git a/lib/interception/CMakeLists.txt b/lib/interception/CMakeLists.txt
index 3ebeb61..aacecf9 100644
--- a/lib/interception/CMakeLists.txt
+++ b/lib/interception/CMakeLists.txt
@@ -24,19 +24,23 @@
   list(APPEND INTERCEPTION_CFLAGS -Wno-variadic-macros)
 endif()
 
-set(INTERCEPTION_COMMON_DEFINITIONS)
-
-if(CAN_TARGET_X86_64)
-  add_library(RTInterception.x86_64 OBJECT ${INTERCEPTION_SOURCES})
-  set_target_compile_flags(RTInterception.x86_64
-    ${INTERCEPTION_CFLAGS} ${TARGET_X86_64_CFLAGS})
-  set_property(TARGET RTInterception.x86_64 APPEND PROPERTY
-    COMPILE_DEFINITIONS ${INTERCEPTION_COMMON_DEFINITIONS})
-endif()
-if(CAN_TARGET_I386)
-  add_library(RTInterception.i386 OBJECT ${INTERCEPTION_SOURCES})
-  set_target_compile_flags(RTInterception.i386
-    ${INTERCEPTION_CFLAGS} ${TARGET_I386_CFLAGS})
-  set_property(TARGET RTInterception.i386 APPEND PROPERTY
-    COMPILE_DEFINITIONS ${INTERCEPTION_COMMON_DEFINITIONS})
+if(APPLE)
+  # Build universal binary on APPLE.
+  add_library(RTInterception.osx OBJECT ${INTERCEPTION_SOURCES})
+  set_target_compile_flags(RTInterception.osx ${INTERCEPTION_CFLAGS})
+  filter_available_targets(INTERCEPTION_TARGETS x86_64 i386)
+  set_target_properties(RTInterception.osx PROPERTIES
+    OSX_ARCHITECTURES "${INTERCEPTION_TARGETS}")
+else()
+  # Otherwise, build separate libraries for each target.
+  if(CAN_TARGET_X86_64)
+    add_library(RTInterception.x86_64 OBJECT ${INTERCEPTION_SOURCES})
+    set_target_compile_flags(RTInterception.x86_64
+      ${INTERCEPTION_CFLAGS} ${TARGET_X86_64_CFLAGS})
+  endif()
+  if(CAN_TARGET_I386)
+    add_library(RTInterception.i386 OBJECT ${INTERCEPTION_SOURCES})
+    set_target_compile_flags(RTInterception.i386
+      ${INTERCEPTION_CFLAGS} ${TARGET_I386_CFLAGS})
+  endif()
 endif()
diff --git a/lib/sanitizer_common/CMakeLists.txt b/lib/sanitizer_common/CMakeLists.txt
index 7780f0b..d3f3f24 100644
--- a/lib/sanitizer_common/CMakeLists.txt
+++ b/lib/sanitizer_common/CMakeLists.txt
@@ -23,19 +23,25 @@
   -fvisibility=hidden
   )
 
-set(SANITIZER_COMMON_DEFINITIONS)
+if(APPLE)
+  # Build universal binary on APPLE.
+  add_library(RTSanitizerCommon.osx OBJECT ${SANITIZER_SOURCES})
+  set_target_compile_flags(RTSanitizerCommon.osx ${SANITIZER_CFLAGS})
+  filter_available_targets(SANITIZER_TARGETS x86_64 i386)
+  set_target_properties(RTSanitizerCommon.osx PROPERTIES
+    OSX_ARCHITECTURES "${SANITIZER_TARGETS}")
+else()
+  # Otherwise, build separate libraries for each target.
+  if(CAN_TARGET_X86_64)
+    add_library(RTSanitizerCommon.x86_64 OBJECT ${SANITIZER_SOURCES})
+    set_target_compile_flags(RTSanitizerCommon.x86_64
+      ${SANITIZER_CFLAGS} ${TARGET_X86_64_CFLAGS})
+  endif()
+  if(CAN_TARGET_I386)
+    add_library(RTSanitizerCommon.i386 OBJECT ${SANITIZER_SOURCES})
+    set_target_compile_flags(RTSanitizerCommon.i386
+      ${SANITIZER_CFLAGS} ${TARGET_I386_CFLAGS})
+  endif()
+endif()
 
-if(CAN_TARGET_X86_64)
-  add_library(RTSanitizerCommon.x86_64 OBJECT ${SANITIZER_SOURCES})
-  set_target_compile_flags(RTSanitizerCommon.x86_64
-    ${SANITIZER_CFLAGS} ${TARGET_X86_64_CFLAGS})
-  set_property(TARGET RTSanitizerCommon.x86_64 APPEND PROPERTY
-    COMPILE_DEFINITIONS ${SANITIZER_COMMON_DEFINITIONS})
-endif()
-if(CAN_TARGET_I386)
-  add_library(RTSanitizerCommon.i386 OBJECT ${SANITIZER_SOURCES})
-  set_target_compile_flags(RTSanitizerCommon.i386
-    ${SANITIZER_CFLAGS} ${TARGET_I386_CFLAGS})
-  set_property(TARGET RTSanitizerCommon.i386 APPEND PROPERTY
-    COMPILE_DEFINITIONS ${SANITIZER_COMMON_DEFINITIONS})
-endif()
+# FIXME: Add support for running sanitizer_common unit tests.