[libcxxabi] Rework CMakeLists.txt into modules
authorMartell Malone <martellmalone@gmail.com>
Thu, 1 Jun 2017 00:09:20 +0000 (00:09 +0000)
committerMartell Malone <martellmalone@gmail.com>
Thu, 1 Jun 2017 00:09:20 +0000 (00:09 +0000)
Refactor cmake to remove dependence on LLVM's cmake modules.
This improves handling of cmake checks when cross compiling and brings
libcxxabi in line with libcxx and other project modules.

Differential revision: https://reviews.llvm.org/D33635

llvm-svn: 304374

libcxxabi/CMakeLists.txt
libcxxabi/cmake/Modules/HandleLibcxxabiFlags.cmake [new file with mode: 0644]
libcxxabi/cmake/Modules/HandleOutOfTreeLLVM.cmake [new file with mode: 0644]
libcxxabi/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake [new file with mode: 0644]
libcxxabi/src/CMakeLists.txt

index 07ad0c6..b7363dd 100644 (file)
@@ -1,3 +1,5 @@
+# See www/CMake.html for instructions on how to build libcxxabi with CMake.
+
 #===============================================================================
 # Setup Project
 #===============================================================================
@@ -16,121 +18,28 @@ set(CMAKE_MODULE_PATH
   )
 
 if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
-  project(libcxxabi)
-
-  # Rely on llvm-config.
-  set(CONFIG_OUTPUT)
-  if (NOT LLVM_CONFIG_PATH)
-    find_program(LLVM_CONFIG_PATH "llvm-config")
-  endif()
-  if(DEFINED LLVM_PATH)
-    set(LLVM_INCLUDE_DIR ${LLVM_INCLUDE_DIR} CACHE PATH "Path to llvm/include")
-    set(LLVM_PATH ${LLVM_PATH} CACHE PATH "Path to LLVM source tree")
-    set(LLVM_MAIN_SRC_DIR ${LLVM_PATH})
-    set(LLVM_CMAKE_PATH "${LLVM_PATH}/cmake/modules")
-  elseif(LLVM_CONFIG_PATH)
-    message(STATUS "Found LLVM_CONFIG_PATH as ${LLVM_CONFIG_PATH}")
-    set(CONFIG_COMMAND ${LLVM_CONFIG_PATH}
-      "--includedir"
-      "--prefix"
-      "--src-root")
-    execute_process(
-      COMMAND ${CONFIG_COMMAND}
-      RESULT_VARIABLE HAD_ERROR
-      OUTPUT_VARIABLE CONFIG_OUTPUT
-    )
-    if(NOT HAD_ERROR)
-      string(REGEX REPLACE
-        "[ \t]*[\r\n]+[ \t]*" ";"
-        CONFIG_OUTPUT ${CONFIG_OUTPUT})
-    else()
-      string(REPLACE ";" " " CONFIG_COMMAND_STR "${CONFIG_COMMAND}")
-      message(STATUS "${CONFIG_COMMAND_STR}")
-      message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}")
-    endif()
-
-    list(GET CONFIG_OUTPUT 0 INCLUDE_DIR)
-    list(GET CONFIG_OUTPUT 1 LLVM_OBJ_ROOT)
-    list(GET CONFIG_OUTPUT 2 MAIN_SRC_DIR)
-
-    set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Path to llvm/include")
-    set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree")
-    set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree")
-    set(LLVM_LIT_PATH "${LLVM_PATH}/utils/lit/lit.py")
-
-    # --cmakedir is supported since llvm r291218 (4.0 release)
-    execute_process(
-      COMMAND ${LLVM_CONFIG_PATH} --cmakedir
-      RESULT_VARIABLE HAD_ERROR
-      OUTPUT_VARIABLE CONFIG_OUTPUT
-      ERROR_QUIET)
-    if(NOT HAD_ERROR)
-      string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH)
-    else()
-      set(LLVM_CMAKE_PATH
-          "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
-    endif()
-  else()
-    message(FATAL_ERROR "llvm-config not found and LLVM_MAIN_SRC_DIR not defined. "
-                        "Reconfigure with -DLLVM_CONFIG_PATH=path/to/llvm-config "
-                        "or -DLLVM_PATH=path/to/llvm-source-root.")
-  endif()
-
-  if(EXISTS ${LLVM_CMAKE_PATH})
-    list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
-    include("${LLVM_CMAKE_PATH}/AddLLVM.cmake")
-    include("${LLVM_CMAKE_PATH}/HandleLLVMOptions.cmake")
-  else()
-    message(FATAL_ERROR "Not found: ${LLVM_CMAKE_PATH}")
-  endif()
+  project(libcxxabi CXX C)
 
   set(PACKAGE_NAME libcxxabi)
   set(PACKAGE_VERSION 5.0.0svn)
   set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
   set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org")
 
-  if (NOT DEFINED LLVM_INCLUDE_TESTS)
-    set(LLVM_INCLUDE_TESTS ON)
-  endif()
-
-  if(EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
-    set(LLVM_LIT ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
-  else()
-    # Seek installed Lit.
-    find_program(LLVM_LIT "lit.py" ${LLVM_MAIN_SRC_DIR}/utils/lit
-      DOC "Path to lit.py")
-  endif()
-
-  if(LLVM_LIT)
-    # Define the default arguments to use with 'lit', and an option for the user
-    # to override.
-    set(LIT_ARGS_DEFAULT "-sv")
-    if (MSVC OR XCODE)
-      set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar")
-    endif()
-    set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
-
-    # On Win32 hosts, provide an option to specify the path to the GnuWin32 tools.
-    if( WIN32 AND NOT CYGWIN )
-      set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools")
-    endif()
-  else()
-    set(LLVM_INCLUDE_TESTS OFF)
-  endif()
-
-  set(LIBCXXABI_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING
-      "Define suffix of library directory name (32/64)")
-
-  set(LIBCXXABI_STANDALONE_BUILD 1)
-else()
-  set(LLVM_MAIN_SRC_DIR "${CMAKE_SOURCE_DIR}" CACHE PATH "Path to LLVM source tree")
-  set(LLVM_LIT "${CMAKE_SOURCE_DIR}/utils/lit/lit.py")
-  set(LIBCXXABI_LIBDIR_SUFFIX ${LLVM_LIBDIR_SUFFIX})
+  # Find the LLVM sources and simulate LLVM CMake options.
+  include(HandleOutOfTreeLLVM)
 endif()
 
+# Require out of source build.
+include(MacroEnsureOutOfSourceBuild)
+MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
+ "${PROJECT_NAME} requires an out of source build. Please create a separate
+ build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there."
+ )
+
 #===============================================================================
 # Setup CMake Options
 #===============================================================================
+include(CMakeDependentOption)
 include(HandleCompilerRT)
 
 # Define options.
@@ -247,6 +156,7 @@ endif()
 
 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR})
 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR})
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR})
 
 # By default, for non-standalone builds, libcxx and libcxxabi share a library
 # directory.
@@ -264,30 +174,26 @@ elseif(LIBCXXABI_BUILD_32_BITS)
   message(FATAL_ERROR "LIBCXXABI_BUILD_32_BITS=ON is not supported on this platform.")
 endif()
 
-#===============================================================================
-# Setup Compiler Flags
-#===============================================================================
-
-# Get required flags.
-macro(append_if list condition var)
-  if (${condition})
-    list(APPEND ${list} ${var})
-  endif()
-endmacro()
-
-macro(add_target_flags_if condition var)
-  if (${condition})
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${var}")
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${var}")
-    list(APPEND LIBCXXABI_COMPILE_FLAGS ${var})
-    list(APPEND LIBCXXABI_LINK_FLAGS ${var})
-  endif()
-endmacro()
+# Declare libc++abi configuration variables.
+# They are intended for use as follows:
+# LIBCXXABI_C_FLAGS: General flags for both the c++ compiler and linker.
+# LIBCXXABI_CXX_FLAGS: General flags for both the c++ compiler and linker.
+# LIBCXXABI_COMPILE_FLAGS: Compile only flags.
+# LIBCXXABI_LINK_FLAGS: Linker only flags.
+# LIBCXXABI_LIBRARIES: libraries libc++abi is linked to.
 
 set(LIBCXXABI_C_FLAGS "")
 set(LIBCXXABI_CXX_FLAGS "")
 set(LIBCXXABI_COMPILE_FLAGS "")
 set(LIBCXXABI_LINK_FLAGS "")
+set(LIBCXXABI_LIBRARIES "")
+
+# Include macros for adding and removing libc++abi flags.
+include(HandleLibcxxabiFlags)
+
+#===============================================================================
+# Setup Compiler Flags
+#===============================================================================
 
 # Configure target flags
 add_target_flags_if(LIBCXXABI_BUILD_32_BITS "-m32")
@@ -325,53 +231,54 @@ if (WIN32 AND LIBCXXABI_ENABLE_STATIC AND NOT LIBCXXABI_ENABLE_SHARED)
   add_definitions(-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS)
 endif()
 
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WERROR_FLAG -Werror=return-type)
+add_compile_flags_if_supported(-Werror=return-type)
 
 # Get warning flags
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_W_FLAG -W)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WALL_FLAG -Wall)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WCHAR_SUBSCRIPTS_FLAG -Wchar-subscripts)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WCONVERSION_FLAG -Wconversion)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WMISMATCHED_TAGS_FLAG -Wmismatched-tags)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WMISSING_BRACES_FLAG -Wmissing-braces)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WNEWLINE_EOF_FLAG -Wnewline-eof)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WUNUSED_FUNCTION_FLAG -Wunused-function)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WSHADOW_FLAG -Wshadow)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WSHORTEN_64_TO_32_FLAG -Wshorten-64-to-32)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WSIGN_COMPARE_FLAG -Wsign-compare)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WSIGN_CONVERSION_FLAG -Wsign-conversion)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WSTRICT_ALIASING_FLAG -Wstrict-aliasing=2)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WSTRICT_OVERFLOW_FLAG -Wstrict-overflow=4)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WUNUSED_PARAMETER_FLAG -Wunused-parameter)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WUNUSED_VARIABLE_FLAG -Wunused-variable)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WWRITE_STRINGS_FLAG -Wwrite-strings)
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WUNDEF_FLAG -Wundef)
+add_compile_flags_if_supported(-W)
+add_compile_flags_if_supported(-Wall)
+add_compile_flags_if_supported(-Wchar-subscripts)
+add_compile_flags_if_supported(-Wconversion)
+add_compile_flags_if_supported(-Wmismatched-tags)
+add_compile_flags_if_supported(-Wmissing-braces)
+add_compile_flags_if_supported(-Wnewline-eof)
+add_compile_flags_if_supported(-Wunused-function)
+add_compile_flags_if_supported(-Wshadow)
+add_compile_flags_if_supported(-Wshorten-64-to-32)
+add_compile_flags_if_supported(-Wsign-compare)
+add_compile_flags_if_supported(-Wsign-conversion)
+add_compile_flags_if_supported(-Wstrict-aliasing=2)
+add_compile_flags_if_supported(-Wstrict-overflow=4)
+add_compile_flags_if_supported(-Wunused-parameter)
+add_compile_flags_if_supported(-Wunused-variable)
+add_compile_flags_if_supported(-Wwrite-strings)
+add_compile_flags_if_supported(-Wundef)
 
 if (LIBCXXABI_ENABLE_WERROR)
-  append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WERROR_FLAG -Werror)
-  append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WX_FLAG -WX)
+  add_compile_flags_if_supported(-Werror)
+  add_compile_flags_if_supported(-WX)
 else()
-  append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WNO_ERROR_FLAG -Wno-error)
-  append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_NO_WX_FLAG -WX-)
+  add_compile_flags_if_supported(-Wno-error)
+  add_compile_flags_if_supported(-WX-)
 endif()
 if (LIBCXXABI_ENABLE_PEDANTIC)
-  append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_PEDANTIC_FLAG -pedantic)
+  add_compile_flags_if_supported(-pedantic)
 endif()
 
 # Get feature flags.
-append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_FSTRICT_ALIASING_FLAG -fstrict-aliasing)
+add_compile_flags_if_supported(-fstrict-aliasing)
 
 # Exceptions
 if (LIBCXXABI_ENABLE_EXCEPTIONS)
   # Catches C++ exceptions only and tells the compiler to assume that extern C
   # functions never throw a C++ exception.
-  append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_EHSC_FLAG -EHsc)
-  append_if(LIBCXXABI_C_FLAGS LIBCXXABI_HAS_FUNWIND_TABLES -funwind-tables)
+  add_compile_flags_if_supported(-EHsc)
+  # Do we really need to be run through the C compiler ?
+  add_c_compile_flags_if_supported(-funwind-tables)
 else()
   add_definitions(-D_LIBCXXABI_NO_EXCEPTIONS)
-  append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_NO_EXCEPTIONS_FLAG -fno-exceptions)
-  append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_NO_EHS_FLAG -EHs-)
-  append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_NO_EHA_FLAG -EHa-)
+  add_compile_flags_if_supported(-fno-exceptions)
+  add_compile_flags_if_supported(-EHs-)
+  add_compile_flags_if_supported(-EHa-)
 endif()
 
 # Assert
diff --git a/libcxxabi/cmake/Modules/HandleLibcxxabiFlags.cmake b/libcxxabi/cmake/Modules/HandleLibcxxabiFlags.cmake
new file mode 100644 (file)
index 0000000..3eddd7b
--- /dev/null
@@ -0,0 +1,208 @@
+# HandleLibcxxFlags - A set of macros used to setup the flags used to compile
+# and link libc++abi. These macros add flags to the following CMake variables.
+# - LIBCXXABI_COMPILE_FLAGS: flags used to compile libc++abi
+# - LIBCXXABI_LINK_FLAGS: flags used to link libc++abi
+# - LIBCXXABI_LIBRARIES: libraries to link libc++abi to.
+
+include(CheckCXXCompilerFlag)
+
+unset(add_flag_if_supported)
+
+# Mangle the name of a compiler flag into a valid CMake identifier.
+# Ex: --std=c++11 -> STD_EQ_CXX11
+macro(mangle_name str output)
+  string(STRIP "${str}" strippedStr)
+  string(REGEX REPLACE "^/" "" strippedStr "${strippedStr}")
+  string(REGEX REPLACE "^-+" "" strippedStr "${strippedStr}")
+  string(REGEX REPLACE "-+$" "" strippedStr "${strippedStr}")
+  string(REPLACE "-" "_" strippedStr "${strippedStr}")
+  string(REPLACE "=" "_EQ_" strippedStr "${strippedStr}")
+  string(REPLACE "+" "X" strippedStr "${strippedStr}")
+  string(TOUPPER "${strippedStr}" ${output})
+endmacro()
+
+# Remove a list of flags from all CMake variables that affect compile flags.
+# This can be used to remove unwanted flags specified on the command line
+# or added in other parts of LLVM's cmake configuration.
+macro(remove_flags)
+  foreach(var ${ARGN})
+    string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
+    string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}")
+    string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
+    string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
+    string(REPLACE "${var}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+    string(REPLACE "${var}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+    string(REPLACE "${var}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
+    string(REPLACE "${var}" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+    string(REPLACE "${var}" "" CMAKE_SHARED_MODULE_FLAGS "${CMAKE_SHARED_MODULE_FLAGS}")
+    remove_definitions(${var})
+  endforeach()
+endmacro(remove_flags)
+
+macro(check_flag_supported flag)
+    mangle_name("${flag}" flagname)
+    check_cxx_compiler_flag("${flag}" "LIBCXXABI_SUPPORTS_${flagname}_FLAG")
+endmacro()
+
+# Add a macro definition if condition is true.
+macro(define_if condition def)
+  if (${condition})
+    add_definitions(${def})
+  endif()
+endmacro()
+
+# Add a macro definition if condition is not true.
+macro(define_if_not condition def)
+  if (NOT ${condition})
+    add_definitions(${def})
+  endif()
+endmacro()
+
+# Add a macro definition to the __config_site file if the specified condition
+# is 'true'. Note that '-D${def}' is not added. Instead it is expected that
+# the build include the '__config_site' header.
+macro(config_define_if condition def)
+  if (${condition})
+    set(${def} ON)
+    set(LIBCXXABI_NEEDS_SITE_CONFIG ON)
+  endif()
+endmacro()
+
+macro(config_define_if_not condition def)
+  if (NOT ${condition})
+    set(${def} ON)
+    set(LIBCXXABI_NEEDS_SITE_CONFIG ON)
+  endif()
+endmacro()
+
+macro(config_define value def)
+  set(${def} ${value})
+  set(LIBCXXABI_NEEDS_SITE_CONFIG ON)
+endmacro()
+
+# Add a list of flags to all of 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS',
+# 'LIBCXXABI_COMPILE_FLAGS' and 'LIBCXXABI_LINK_FLAGS'.
+macro(add_target_flags)
+  foreach(value ${ARGN})
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${value}")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${value}")
+    list(APPEND LIBCXXABI_COMPILE_FLAGS ${value})
+    list(APPEND LIBCXXABI_LINK_FLAGS ${value})
+  endforeach()
+endmacro()
+
+# If the specified 'condition' is true then add a list of flags to
+# all of 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', 'LIBCXXABI_COMPILE_FLAGS'
+# and 'LIBCXXABI_LINK_FLAGS'.
+macro(add_target_flags_if condition)
+  if (${condition})
+    add_target_flags(${ARGN})
+  endif()
+endmacro()
+
+# Add a specified list of flags to both 'LIBCXXABI_COMPILE_FLAGS' and
+# 'LIBCXXABI_LINK_FLAGS'.
+macro(add_flags)
+  foreach(value ${ARGN})
+    list(APPEND LIBCXXABI_COMPILE_FLAGS ${value})
+    list(APPEND LIBCXXABI_LINK_FLAGS ${value})
+  endforeach()
+endmacro()
+
+# If the specified 'condition' is true then add a list of flags to both
+# 'LIBCXXABI_COMPILE_FLAGS' and 'LIBCXXABI_LINK_FLAGS'.
+macro(add_flags_if condition)
+  if (${condition})
+    add_flags(${ARGN})
+  endif()
+endmacro()
+
+# Add each flag in the list to LIBCXXABI_COMPILE_FLAGS and LIBCXXABI_LINK_FLAGS
+# if that flag is supported by the current compiler.
+macro(add_flags_if_supported)
+  foreach(flag ${ARGN})
+      mangle_name("${flag}" flagname)
+      check_cxx_compiler_flag("${flag}" "LIBCXXABI_SUPPORTS_${flagname}_FLAG")
+      add_flags_if(LIBCXXABI_SUPPORTS_${flagname}_FLAG ${flag})
+  endforeach()
+endmacro()
+
+# Add a list of flags to 'LIBCXXABI_COMPILE_FLAGS'.
+macro(add_compile_flags)
+  foreach(f ${ARGN})
+    list(APPEND LIBCXXABI_COMPILE_FLAGS ${f})
+  endforeach()
+endmacro()
+
+# If 'condition' is true then add the specified list of flags to
+# 'LIBCXXABI_COMPILE_FLAGS'
+macro(add_compile_flags_if condition)
+  if (${condition})
+    add_compile_flags(${ARGN})
+  endif()
+endmacro()
+
+# For each specified flag, add that flag to 'LIBCXXABI_COMPILE_FLAGS' if the
+# flag is supported by the C++ compiler.
+macro(add_compile_flags_if_supported)
+  foreach(flag ${ARGN})
+      mangle_name("${flag}" flagname)
+      check_cxx_compiler_flag("${flag}" "LIBCXXABI_SUPPORTS_${flagname}_FLAG")
+      add_compile_flags_if(LIBCXXABI_SUPPORTS_${flagname}_FLAG ${flag})
+  endforeach()
+endmacro()
+
+# For each specified flag, add that flag to 'LIBCXXABI_COMPILE_FLAGS' if the
+# flag is supported by the C compiler.
+macro(add_c_compile_flags_if_supported)
+  foreach(flag ${ARGN})
+      mangle_name("${flag}" flagname)
+      check_c_compiler_flag("${flag}" "LIBCXXABI_SUPPORTS_${flagname}_FLAG")
+      add_compile_flags_if(LIBCXXABI_SUPPORTS_${flagname}_FLAG ${flag})
+  endforeach()
+endmacro()
+
+# Add a list of flags to 'LIBCXXABI_LINK_FLAGS'.
+macro(add_link_flags)
+  foreach(f ${ARGN})
+    list(APPEND LIBCXXABI_LINK_FLAGS ${f})
+  endforeach()
+endmacro()
+
+# If 'condition' is true then add the specified list of flags to
+# 'LIBCXXABI_LINK_FLAGS'
+macro(add_link_flags_if condition)
+  if (${condition})
+    add_link_flags(${ARGN})
+  endif()
+endmacro()
+
+# For each specified flag, add that flag to 'LIBCXXABI_LINK_FLAGS' if the
+# flag is supported by the C++ compiler.
+macro(add_link_flags_if_supported)
+  foreach(flag ${ARGN})
+    mangle_name("${flag}" flagname)
+    check_cxx_compiler_flag("${flag}" "LIBCXXABI_SUPPORTS_${flagname}_FLAG")
+    add_link_flags_if(LIBCXXABI_SUPPORTS_${flagname}_FLAG ${flag})
+  endforeach()
+endmacro()
+
+# Add a list of libraries or link flags to 'LIBCXXABI_LIBRARIES'.
+macro(add_library_flags)
+  foreach(lib ${ARGN})
+    list(APPEND LIBCXXABI_LIBRARIES ${lib})
+  endforeach()
+endmacro()
+
+# if 'condition' is true then add the specified list of libraries and flags
+# to 'LIBCXXABI_LIBRARIES'.
+macro(add_library_flags_if condition)
+  if(${condition})
+    add_library_flags(${ARGN})
+  endif()
+endmacro()
+
+# Turn a comma separated CMake list into a space separated string.
+macro(split_list listname)
+  string(REPLACE ";" " " ${listname} "${${listname}}")
+endmacro()
diff --git a/libcxxabi/cmake/Modules/HandleOutOfTreeLLVM.cmake b/libcxxabi/cmake/Modules/HandleOutOfTreeLLVM.cmake
new file mode 100644 (file)
index 0000000..1dcaf90
--- /dev/null
@@ -0,0 +1,130 @@
+macro(find_llvm_parts)
+# Rely on llvm-config.
+  set(CONFIG_OUTPUT)
+  if(NOT LLVM_CONFIG_PATH)
+    find_program(LLVM_CONFIG_PATH "llvm-config")
+  endif()
+  if(DEFINED LLVM_PATH)
+    set(LLVM_INCLUDE_DIR ${LLVM_INCLUDE_DIR} CACHE PATH "Path to llvm/include")
+    set(LLVM_PATH ${LLVM_PATH} CACHE PATH "Path to LLVM source tree")
+    set(LLVM_MAIN_SRC_DIR ${LLVM_PATH})
+    set(LLVM_CMAKE_PATH "${LLVM_PATH}/cmake/modules")
+  elseif(LLVM_CONFIG_PATH)
+    message(STATUS "Found LLVM_CONFIG_PATH as ${LLVM_CONFIG_PATH}")
+    set(LIBCXXABI_USING_INSTALLED_LLVM 1)
+    set(CONFIG_COMMAND ${LLVM_CONFIG_PATH}
+      "--includedir"
+      "--prefix"
+      "--src-root")
+    execute_process(
+      COMMAND ${CONFIG_COMMAND}
+      RESULT_VARIABLE HAD_ERROR
+      OUTPUT_VARIABLE CONFIG_OUTPUT
+    )
+    if(NOT HAD_ERROR)
+      string(REGEX REPLACE
+        "[ \t]*[\r\n]+[ \t]*" ";"
+        CONFIG_OUTPUT ${CONFIG_OUTPUT})
+    else()
+      string(REPLACE ";" " " CONFIG_COMMAND_STR "${CONFIG_COMMAND}")
+      message(STATUS "${CONFIG_COMMAND_STR}")
+      message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}")
+    endif()
+
+    list(GET CONFIG_OUTPUT 0 INCLUDE_DIR)
+    list(GET CONFIG_OUTPUT 1 LLVM_OBJ_ROOT)
+    list(GET CONFIG_OUTPUT 2 MAIN_SRC_DIR)
+
+    set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Path to llvm/include")
+    set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree")
+    set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree")
+
+    # --cmakedir is supported since llvm r291218 (4.0 release)
+    execute_process(
+      COMMAND ${LLVM_CONFIG_PATH} --cmakedir
+      RESULT_VARIABLE HAD_ERROR
+      OUTPUT_VARIABLE CONFIG_OUTPUT
+      ERROR_QUIET)
+    if(NOT HAD_ERROR)
+      string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH)
+    else()
+      set(LLVM_CMAKE_PATH
+          "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
+    endif()
+  else()
+    set(LLVM_FOUND OFF)
+    message(WARNING "UNSUPPORTED LIBCXXABI CONFIGURATION DETECTED: "
+                    "llvm-config not found and LLVM_PATH not defined.\n"
+                    "Reconfigure with -DLLVM_CONFIG_PATH=path/to/llvm-config "
+                    "or -DLLVM_PATH=path/to/llvm-source-root.")
+    return()
+  endif()
+
+  if (EXISTS "${LLVM_CMAKE_PATH}")
+    list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
+  elseif (EXISTS "${LLVM_MAIN_SRC_DIR}/cmake/modules")
+    list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules")
+  else()
+    set(LLVM_FOUND OFF)
+    message(WARNING "Neither ${LLVM_CMAKE_PATH} nor ${LLVM_MAIN_SRC_DIR}/cmake/modules found")
+    return()
+  endif()
+
+  set(LLVM_FOUND ON)
+endmacro(find_llvm_parts)
+
+macro(configure_out_of_tree_llvm)
+  message(STATUS "Configuring for standalone build.")
+  set(LIBCXXABI_STANDALONE_BUILD 1)
+
+  find_llvm_parts()
+
+  # Add LLVM Functions --------------------------------------------------------
+  if (LLVM_FOUND AND LIBCXXABI_USING_INSTALLED_LLVM)
+    include(LLVMConfig) # For TARGET_TRIPLE
+  else()
+    if (WIN32)
+      set(LLVM_ON_UNIX 0)
+      set(LLVM_ON_WIN32 1)
+    else()
+      set(LLVM_ON_UNIX 1)
+      set(LLVM_ON_WIN32 0)
+    endif()
+  endif()
+  if (LLVM_FOUND)
+    include(AddLLVM OPTIONAL)
+  endif()
+
+  # LLVM Options --------------------------------------------------------------
+  if (NOT DEFINED LLVM_INCLUDE_TESTS)
+    set(LLVM_INCLUDE_TESTS ${LLVM_FOUND})
+  endif()
+  if (NOT DEFINED LLVM_INCLUDE_DOCS)
+    set(LLVM_INCLUDE_DOCS ${LLVM_FOUND})
+  endif()
+  if (NOT DEFINED LLVM_ENABLE_SPHINX)
+    set(LLVM_ENABLE_SPHINX OFF)
+  endif()
+
+  # Required LIT Configuration ------------------------------------------------
+  # Define the default arguments to use with 'lit', and an option for the user
+  # to override.
+  set(LIT_ARGS_DEFAULT "-sv --show-xfail --show-unsupported")
+  if (MSVC OR XCODE)
+    set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar")
+  endif()
+  set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
+
+  # Required doc configuration
+  if (LLVM_ENABLE_SPHINX)
+    find_package(Sphinx REQUIRED)
+  endif()
+
+  if (LLVM_ON_UNIX AND NOT APPLE)
+    set(LLVM_HAVE_LINK_VERSION_SCRIPT 1)
+  else()
+    set(LLVM_HAVE_LINK_VERSION_SCRIPT 0)
+  endif()
+endmacro(configure_out_of_tree_llvm)
+
+configure_out_of_tree_llvm()
diff --git a/libcxxabi/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake b/libcxxabi/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake
new file mode 100644 (file)
index 0000000..e75002b
--- /dev/null
@@ -0,0 +1,18 @@
+# MACRO_ENSURE_OUT_OF_SOURCE_BUILD(<errorMessage>)
+
+macro( MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage )
+
+string( COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource )
+if( _insource )
+ message( SEND_ERROR "${_errorMessage}" )
+ message( FATAL_ERROR
+ "In-source builds are not allowed.
+ CMake would overwrite the makefiles distributed with libcxxabi.
+ Please create a directory and run cmake from there, passing the path
+ to this source directory as the last argument.
+ This process created the file `CMakeCache.txt' and the directory `CMakeFiles'.
+ Please delete them."
+ )
+endif( _insource )
+
+endmacro( MACRO_ENSURE_OUT_OF_SOURCE_BUILD )
index d844b7f..ac2c3a6 100644 (file)
@@ -52,36 +52,33 @@ if (LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
   add_definitions(-DHAVE___CXA_THREAD_ATEXIT_IMPL)
 endif()
 
-# Generate library list
-set(libraries ${LIBCXXABI_CXX_ABI_LIBRARIES})
-
 if (LIBCXXABI_ENABLE_THREADS)
-  append_if(libraries LIBCXXABI_HAS_PTHREAD_LIB pthread)
+  add_library_flags_if(LIBCXXABI_HAS_PTHREAD_LIB pthread)
 endif()
 
-append_if(libraries LIBCXXABI_HAS_C_LIB c)
+add_library_flags_if(LIBCXXABI_HAS_C_LIB c)
 if (LIBCXXABI_USE_LLVM_UNWINDER)
   # Prefer using the in-tree version of libunwind, either shared or static. If
   # none are found fall back to using -lunwind.
   # FIXME: Is it correct to prefer the static version of libunwind?
   if (NOT LIBCXXABI_ENABLE_STATIC_UNWINDER AND (TARGET unwind_shared OR HAVE_LIBUNWIND))
-    list(APPEND libraries unwind_shared)
+    list(APPEND LIBCXXABI_LIBRARIES unwind_shared)
   elseif (LIBCXXABI_ENABLE_STATIC_UNWINDER AND (TARGET unwind_static OR HAVE_LIBUNWIND))
-    list(APPEND libraries unwind_static)
+    list(APPEND LIBCXXABI_LIBRARIES unwind_static)
   else()
-    list(APPEND libraries unwind)
+    list(APPEND LIBCXXABI_LIBRARIES unwind)
   endif()
 else()
-  append_if(libraries LIBCXXABI_HAS_GCC_S_LIB gcc_s)
+  add_library_flags_if(LIBCXXABI_HAS_GCC_S_LIB gcc_s)
 endif()
 if (MINGW)
   # MINGW_LIBRARIES is defined in config-ix.cmake
-  list(APPEND libraries ${MINGW_LIBRARIES})
+  list(APPEND LIBCXXABI_LIBRARIES ${MINGW_LIBRARIES})
 endif()
 
 # Setup flags.
-append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_FPIC_FLAG -fPIC)
-append_if(LIBCXXABI_LINK_FLAGS LIBCXXABI_HAS_NODEFAULTLIBS_FLAG -nodefaultlibs)
+add_compile_flags_if_supported(-fPIC)
+add_link_flags_if_supported(-nodefaultlibs)
 
 set(LIBCXXABI_SHARED_LINK_FLAGS)
 
@@ -101,9 +98,9 @@ if ( APPLE )
   endif()
 endif()
 
-string(REPLACE ";" " " LIBCXXABI_COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}")
-string(REPLACE ";" " " LIBCXXABI_LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}")
-string(REPLACE ";" " " LIBCXXABI_SHARED_LINK_FLAGS "${LIBCXXABI_SHARED_LINK_FLAGS}")
+split_list(LIBCXXABI_COMPILE_FLAGS)
+split_list(LIBCXXABI_LINK_FLAGS)
+split_list(LIBCXXABI_SHARED_LINK_FLAGS)
 
 # FIXME: libc++abi.so will not link when modules are enabled because it depends
 # on symbols defined in libc++.so which has not yet been built.
@@ -124,7 +121,7 @@ set(LIBCXXABI_TARGETS)
 # Build the shared library.
 if (LIBCXXABI_ENABLE_SHARED)
   add_library(cxxabi_shared SHARED $<TARGET_OBJECTS:cxxabi_objects>)
-  target_link_libraries(cxxabi_shared ${libraries})
+  target_link_libraries(cxxabi_shared ${LIBCXXABI_LIBRARIES})
   set_target_properties(cxxabi_shared
     PROPERTIES
       LINK_FLAGS    "${LIBCXXABI_LINK_FLAGS} ${LIBCXXABI_SHARED_LINK_FLAGS}"
@@ -138,7 +135,7 @@ endif()
 # Build the static library.
 if (LIBCXXABI_ENABLE_STATIC)
   add_library(cxxabi_static STATIC $<TARGET_OBJECTS:cxxabi_objects>)
-  target_link_libraries(cxxabi_static ${libraries})
+  target_link_libraries(cxxabi_static ${LIBCXXABI_LIBRARIES})
   set_target_properties(cxxabi_static
     PROPERTIES
       LINK_FLAGS    "${LIBCXXABI_LINK_FLAGS}"