diff --git a/CMake/FindBacktrace.cmake b/CMake/FindBacktrace.cmake new file mode 100644 index 0000000000..0b19a8538c --- /dev/null +++ b/CMake/FindBacktrace.cmake @@ -0,0 +1,106 @@ +# This is cloned from +# https://github.com/Kitware/CMake/blob/master/Modules/ +# The module is already included in CMake since 3.0. Until we +# require CMake 3.0 this module works as a backport. + +# Find provider for backtrace(3). +# +# Checks if OS supports backtrace(3) via either libc or custom library. +# This module defines the following variables: +# +# ``Backtrace_HEADER`` +# The header file needed for backtrace(3). Cached. +# Could be forcibly set by user. +# ``Backtrace_INCLUDE_DIRS`` +# The include directories needed to use backtrace(3) header. +# ``Backtrace_LIBRARIES`` +# The libraries (linker flags) needed to use backtrace(3), if any. +# ``Backtrace_FOUND`` +# Is set if and only if backtrace(3) support detected. +# +# The following cache variables are also available to set or use: +# +# ``Backtrace_LIBRARY`` +# The external library providing backtrace, if any. +# ``Backtrace_INCLUDE_DIR`` +# The directory holding the backtrace(3) header. +# +# Typical usage is to generate of header file using configure_file() with the +# contents like the following:: +# +# #cmakedefine01 Backtrace_FOUND +# #if Backtrace_FOUND +# # include <${Backtrace_HEADER}> +# #endif +# +# And then reference that generated header file in actual source. + +#============================================================================= +# Copyright 2013 Vadim Zhukov +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + + +include(CMakePushCheckState) +include(CheckSymbolExists) +include(FindPackageHandleStandardArgs) + +# List of variables to be provided to find_package_handle_standard_args() +set(_Backtrace_STD_ARGS Backtrace_INCLUDE_DIR) + +if(Backtrace_HEADER) + set(_Backtrace_HEADER_TRY "${Backtrace_HEADER}") +else(Backtrace_HEADER) + set(_Backtrace_HEADER_TRY "execinfo.h") +endif(Backtrace_HEADER) + +find_path(Backtrace_INCLUDE_DIR "${_Backtrace_HEADER_TRY}") +set(Backtrace_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR}) + +if (NOT DEFINED Backtrace_LIBRARY) + # First, check if we already have backtrace(), e.g., in libc + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_INCLUDES ${Backtrace_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_QUIET ${Backtrace_FIND_QUIETLY}) + check_symbol_exists("backtrace" "${_Backtrace_HEADER_TRY}" + _Backtrace_SYM_FOUND) + cmake_pop_check_state() +endif() + +if(_Backtrace_SYM_FOUND) + # Avoid repeating the message() call below each time CMake is run. + if(NOT Backtrace_FIND_QUIETLY AND NOT DEFINED Backtrace_LIBRARY) + message(STATUS "backtrace facility detected in default set of libraries") + endif() + set(Backtrace_LIBRARY "" CACHE FILEPATH "Library providing backtrace(3), + empty for default set of libraries") +else() + # Check for external library, for non-glibc systems + if(Backtrace_INCLUDE_DIR) + # OpenBSD has libbacktrace renamed to libexecinfo + find_library(Backtrace_LIBRARY "execinfo") + elseif() # respect user wishes + set(_Backtrace_HEADER_TRY "backtrace.h") + find_path(Backtrace_INCLUDE_DIR ${_Backtrace_HEADER_TRY}) + find_library(Backtrace_LIBRARY "backtrace") + endif() + + # Prepend list with library path as it's more common practice + set(_Backtrace_STD_ARGS Backtrace_LIBRARY ${_Backtrace_STD_ARGS}) +endif() + +set(Backtrace_LIBRARIES ${Backtrace_LIBRARY}) +set(Backtrace_HEADER "${_Backtrace_HEADER_TRY}" CACHE STRING "Header + providing backtrace(3) facility") + +find_package_handle_standard_args(Backtrace FOUND_VAR Backtrace_FOUND + REQUIRED_VARS ${_Backtrace_STD_ARGS}) +mark_as_advanced(Backtrace_HEADER Backtrace_INCLUDE_DIR Backtrace_LIBRARY) \ No newline at end of file diff --git a/CMake/backtrace.h.in b/CMake/backtrace.h.in new file mode 100644 index 0000000000..c26f0c68ee --- /dev/null +++ b/CMake/backtrace.h.in @@ -0,0 +1,13 @@ +#ifndef __MLPACK_CORE_UTIL_BACKTRACE_HPP +#define __MLPACK_CORE_UTIL_BACKTRACE_HPP + +namespace mlpack { + +#cmakedefine01 Backtrace_FOUND +#if Backtrace_FOUND + #include <@Backtrace_HEADER@> +#endif + +}; //namespace mlpack + +#endif diff --git a/CMakeLists.txt b/CMakeLists.txt index b9d2816f36..ae5d17893a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,9 @@ option(ARMA_EXTRA_DEBUG "Compile with extra Armadillo debugging symbols." OFF) option(MATLAB_BINDINGS "Compile MATLAB bindings if MATLAB is found." OFF) option(TEST_VERBOSE "Run test cases with verbose output." OFF) +# Include modules in the CMake directory. +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake") + # This is as of yet unused. #option(PGO "Use profile-guided optimization if not a debug build" ON) @@ -56,6 +59,20 @@ if(CMAKE_COMPILER_IS_GNUCC AND PROFILE) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") endif(CMAKE_COMPILER_IS_GNUCC AND PROFILE) +# mlpack uses backtrace() facilities. On some systems (e.g., GNU/Linux), it +# resides in libc itself and requires ; on other (e.g., OpenBSD) +# it's provided by a separate library. +find_package(Backtrace) +if(Backtrace_FOUND) + include_directories(${Backtrace_INCLUDE_DIRS}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Backtrace_LIBRARIES}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${Backtrace_LIBRARIES}") +endif(Backtrace_FOUND) + +# Generate the backtrace header file. +configure_file(${CMAKE_MODULE_PATH}/backtrace.h.in + ${CMAKE_SOURCE_DIR}/src/mlpack/core/util/backtrace.hpp) + # If the user asked for running test cases with verbose output, turn that on. if(TEST_VERBOSE) add_definitions(-DTEST_VERBOSE) @@ -78,9 +95,6 @@ endif(ARMA_EXTRA_DEBUG) # BOOST_INCLUDEDIR - include directory for Boost # BOOST_LIBRARYDIR - library directory for Boost -# Include modules in the CMake directory. -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake") - find_package(Armadillo 3.6.0 REQUIRED) # If Armadillo was compiled without ARMA_64BIT_WORD and we are on a 64-bit diff --git a/src/mlpack/core/util/log.cpp b/src/mlpack/core/util/log.cpp index 8b566c0636..6d95d3a72b 100644 --- a/src/mlpack/core/util/log.cpp +++ b/src/mlpack/core/util/log.cpp @@ -7,10 +7,10 @@ #ifndef _WIN32 #include #include - #include #endif #include "log.hpp" +#include "backtrace.hpp" // Color code escape sequences -- but not on Windows. #ifndef _WIN32 @@ -53,7 +53,7 @@ void Log::Assert(bool condition, const std::string& message) { if (!condition) { -#ifndef _WIN32 +#if Backtrace_FOUND void* array[25]; size_t size = backtrace(array, sizeof(array) / sizeof(void*)); char** messages = backtrace_symbols(array, size); @@ -118,7 +118,7 @@ void Log::Assert(bool condition, const std::string& message) #endif Log::Debug << message << std::endl; -#ifndef _WIN32 +#if Backtrace_FOUND free(messages); #endif