Squashed 'third_party/glog/' content from commit 9ef754a3023

git-subtree-dir: third_party/glog
git-subtree-split: 9ef754a3023e6fd10f20fe53dfca96dd898182e3
This commit is contained in:
Vincent Ambo 2020-05-27 01:26:30 +01:00
commit afe04691ac
133 changed files with 23455 additions and 0 deletions

25
.bazelci/presubmit.yml Normal file
View file

@ -0,0 +1,25 @@
---
platforms:
ubuntu1604:
build_targets:
- "..."
test_targets:
- "..."
ubuntu1804:
build_targets:
- "..."
test_targets:
- "..."
macos:
build_targets:
- "..."
test_targets:
- "..."
windows:
# Optional: use VS 2017 instead of 2015.
environment:
BAZEL_VC: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC"
build_targets:
- "..."
test_targets:
- "..."

12
.gitignore vendored Normal file
View file

@ -0,0 +1,12 @@
/*.cmake
/*.filters
/*.sln
/*.vcxproj
autom4te.cache
bazel-*
CMakeCache.txt
CMakeFiles/
config.h
glog-*.tar.gz
packages/debian-*
packages/rpm-unknown

18
.travis.ubuntu.sh Executable file
View file

@ -0,0 +1,18 @@
#!/bin/bash
set -e
set -x
uname -a
cmake -H. -B_build_${TOOLCHAIN} -DCMAKE_TOOLCHAIN_FILE="${PWD}/toolchains/${TOOLCHAIN}.cmake"
cmake --build _build_${TOOLCHAIN} -- -j4
if [ "$RUN_TESTS" = true ]; then
case "$TOOLCHAIN" in linux-mingw*)
echo "copy runtime libraries needed for tests into build directory"
cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll /usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/{libstdc++-6.dll,libgcc_s_seh-1.dll} _build_${TOOLCHAIN}
esac
CTEST_OUTPUT_ON_FAILURE=1 cmake --build _build_${TOOLCHAIN} --target test
fi

119
.travis.yml Normal file
View file

@ -0,0 +1,119 @@
sudo: required
language: bash
services:
- docker
# define the build matrix
env:
global:
- PROJECT_DIR: .
- TOOLCHAIN: gcc-cxx11
- BUILD_PACKAGES: cmake
- RUN_TESTS: true
matrix:
include:
# Linux {
# Ubuntu 14.04
- os: linux
env: >
BUILD_FLAVOR=ubuntu
BUILD_RELEASE=trusty
BUILD_ARCH=amd64
BUILD_PACKAGES=cmake3
- os: linux
env: >
BUILD_FLAVOR=ubuntu
BUILD_RELEASE=trusty
BUILD_ARCH=i386
BUILD_PACKAGES=cmake3
# Ubuntu 16.04
- os: linux
env: >
BUILD_FLAVOR=ubuntu
BUILD_RELEASE=xenial
BUILD_ARCH=amd64
- os: linux
env: >
BUILD_FLAVOR=ubuntu
BUILD_RELEASE=xenial
BUILD_ARCH=i386
# Ubuntu 18.04
- os: linux
env: >
BUILD_FLAVOR=ubuntu
BUILD_RELEASE=bionic
BUILD_ARCH=amd64
TOOLCHAIN=gcc-cxx98
- os: linux
env: >
BUILD_FLAVOR=ubuntu
BUILD_RELEASE=bionic
BUILD_ARCH=amd64
- os: linux
env: >
BUILD_FLAVOR=ubuntu
BUILD_RELEASE=bionic
BUILD_ARCH=amd64
TOOLCHAIN=gcc-gnuxx11
- os: linux
env: >
BUILD_FLAVOR=ubuntu
BUILD_RELEASE=bionic
BUILD_ARCH=amd64
TOOLCHAIN=gcc-cxx17
- os: linux
env: >
BUILD_FLAVOR=ubuntu
BUILD_RELEASE=bionic
BUILD_ARCH=amd64
TOOLCHAIN=clang-cxx17
BUILD_PACKAGES="cmake clang"
# } // end Linux
# Windows build with mingw-w64 on Ubuntu 18.04
- os: linux
env: >
BUILD_FLAVOR=ubuntu
BUILD_RELEASE=bionic
BUILD_ARCH=amd64
TOOLCHAIN=linux-mingw-w64-cxx11
BUILD_PACKAGES="cmake mingw-w64 wine-stable"
- os: linux
env: >
BUILD_FLAVOR=ubuntu
BUILD_RELEASE=bionic
BUILD_ARCH=amd64
TOOLCHAIN=linux-mingw-w64-gnuxx11
BUILD_PACKAGES="cmake mingw-w64 wine-stable"
- os: linux
env: >
BUILD_FLAVOR=ubuntu
BUILD_RELEASE=bionic
BUILD_ARCH=amd64
TOOLCHAIN=linux-mingw-w64-cxx17
BUILD_PACKAGES="cmake mingw-w64 wine-stable"
before_install:
# use the Dockerfile.<distro>.template file for building the image with sed magic
- |
sed \
-e "s/@BUILD_FLAVOR@/${BUILD_FLAVOR}/g" \
-e "s/@BUILD_RELEASE@/${BUILD_RELEASE}/g" \
-e "s/@BUILD_ARCH@/${BUILD_ARCH}/g" \
-e "s/@BUILD_PACKAGES@/${BUILD_PACKAGES}/g" \
Dockerfile.$BUILD_FLAVOR.template | tee Dockerfile.$BUILD_FLAVOR.$BUILD_RELEASE.$BUILD_ARCH
- docker build -f Dockerfile.$BUILD_FLAVOR.$BUILD_RELEASE.$BUILD_ARCH -t glog-devel .
script: |
# run the respective .travis.<distro>.sh script
docker run \
-e BUILD_FLAVOR="$BUILD_FLAVOR" \
-e BUILD_RELEASE="$BUILD_RELEASE" \
-e BUILD_ARCH="$BUILD_ARCH" \
-e PROJECT_DIR="$PROJECT_DIR" \
-e TOOLCHAIN="$TOOLCHAIN" \
-e RUN_TESTS="$RUN_TESTS" \
-it glog-devel ./.travis.$BUILD_FLAVOR.sh

26
AUTHORS Normal file
View file

@ -0,0 +1,26 @@
# This is the official list of glog authors for copyright purposes.
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.
#
# Names should be added to this file as:
# Name or Organization <email address>
# The email address is not required for organizations.
#
# Please keep the list sorted.
Abhishek Dasgupta <abhi2743@gmail.com>
Abhishek Parmar <abhishek@orng.net>
Andrew Schwartzmeyer <andrew@schwartzmeyer.com>
Andy Ying <andy@trailofbits.com>
Brian Silverman <bsilver16384@gmail.com>
Google Inc.
Guillaume Dumont <dumont.guillaume@gmail.com>
Marco Wang <m.aesophor@gmail.com>
Michael Tanner <michael@tannertaxpro.com>
MiniLight <MiniLightAR@Gmail.com>
romange <romange@users.noreply.github.com>
Roman Perepelitsa <roman.perepelitsa@gmail.com>
Sergiu Deitsch <sergiu.deitsch@gmail.com>
tbennun <tbennun@gmail.com>
Teddy Reed <teddy@prosauce.org>
Zhongming Qu <qzmfranklin@gmail.com>

5
BUILD Normal file
View file

@ -0,0 +1,5 @@
licenses(['notice'])
load(':bazel/glog.bzl', 'glog_library')
glog_library()

848
CMakeLists.txt Normal file
View file

@ -0,0 +1,848 @@
cmake_minimum_required (VERSION 3.0)
if (POLICY CMP0042)
cmake_policy (SET CMP0042 NEW)
endif (POLICY CMP0042)
if (POLICY CMP0063)
cmake_policy (SET CMP0063 NEW)
endif (POLICY CMP0063)
project(glog VERSION 0.4.0 LANGUAGES C CXX)
set (CPACK_PACKAGE_NAME glog)
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "")
set (CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set (CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set (CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
set (CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
option (WITH_GFLAGS "Use gflags" ON)
option (WITH_THREADS "Enable multithreading support" ON)
option (WITH_TLS "Enable Thread Local Storage (TLS) support" ON)
option (BUILD_SHARED_LIBS "Build shared libraries" OFF)
option (PRINT_UNSYMBOLIZED_STACK_TRACES
"Print file offsets in traces instead of symbolizing" OFF)
option (WITH_PKGCONFIG "Enable pkg-config support" ON)
option (WITH_UNWIND "Enable libunwind support" ON)
option (WITH_SYMBOLIZE "Enable symbolize module" ON)
if (NOT WITH_UNWIND)
set (CMAKE_DISABLE_FIND_PACKAGE_Unwind ON)
endif (NOT WITH_UNWIND)
if (NOT WITH_THREADS)
set (CMAKE_DISABLE_FIND_PACKAGE_Threads ON)
endif (NOT WITH_THREADS)
list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include (CheckCSourceCompiles)
include (CheckCXXCompilerFlag)
include (CheckCXXSourceCompiles)
include (CheckCXXSourceRuns)
include (CheckFunctionExists)
include (CheckIncludeFile)
include (CheckIncludeFileCXX)
include (CheckLibraryExists)
include (CheckStructHasMember)
include (CheckSymbolExists)
include (CheckTypeSize)
include (CMakePackageConfigHelpers)
include (CMakePushCheckState)
include (CPack)
include (CTest)
include (DetermineGflagsNamespace)
include (GetCacheVariables)
include (GNUInstallDirs)
set (CMAKE_DEBUG_POSTFIX d)
set (CMAKE_THREAD_PREFER_PTHREAD 1)
if (WITH_GFLAGS)
find_package (gflags 2.2.0)
if (gflags_FOUND)
set (HAVE_LIB_GFLAGS 1)
determine_gflags_namespace (gflags_NAMESPACE)
endif (gflags_FOUND)
endif (WITH_GFLAGS)
find_package (Threads)
find_package (Unwind)
if (Unwind_FOUND)
set (HAVE_LIB_UNWIND 1)
set (HAVE_UNWIND_H 1)
endif (Unwind_FOUND)
check_include_file (dlfcn.h HAVE_DLFCN_H)
check_include_file (execinfo.h HAVE_EXECINFO_H)
check_include_file (glob.h HAVE_GLOB_H)
check_include_file (inttypes.h HAVE_INTTYPES_H)
check_include_file (memory.h HAVE_MEMORY_H)
check_include_file (pwd.h HAVE_PWD_H)
check_include_file (stdint.h HAVE_STDINT_H)
check_include_file (stdlib.h HAVE_STDLIB_H)
check_include_file (string.h HAVE_STRING_H)
check_include_file (strings.h HAVE_STRINGS_H)
check_include_file (sys/stat.h HAVE_SYS_STAT_H)
check_include_file (sys/syscall.h HAVE_SYS_SYSCALL_H)
check_include_file (sys/time.h HAVE_SYS_TIME_H)
check_include_file (sys/types.h HAVE_SYS_TYPES_H)
check_include_file (sys/utsname.h HAVE_SYS_UTSNAME_H)
check_include_file (sys/wait.h HAVE_SYS_WAIT_H)
check_include_file (syscall.h HAVE_SYSCALL_H)
check_include_file (syslog.h HAVE_SYSLOG_H)
check_include_file (ucontext.h HAVE_UCONTEXT_H)
check_include_file (unistd.h HAVE_UNISTD_H)
check_include_file (pwd.h HAVE_PWD_H)
check_include_file_cxx ("ext/hash_map" HAVE_EXT_HASH_MAP)
check_include_file_cxx ("ext/hash_set" HAVE_EXT_HASH_SET)
check_include_file_cxx ("ext/slist" HAVE_EXT_SLIST)
check_include_file_cxx ("tr1/unordered_map" HAVE_TR1_UNORDERED_MAP)
check_include_file_cxx ("tr1/unordered_set" HAVE_TR1_UNORDERED_SET)
check_include_file_cxx ("unordered_map" HAVE_UNORDERED_MAP)
check_include_file_cxx ("unordered_set" HAVE_UNORDERED_SET)
check_type_size ("unsigned __int16" HAVE___UINT16)
check_type_size (u_int16_t HAVE_U_INT16_T)
check_type_size (uint16_t HAVE_UINT16_T)
check_function_exists (dladdr HAVE_DLADDR)
check_function_exists (fcntl HAVE_FCNTL)
check_function_exists (pread HAVE_PREAD)
check_function_exists (pwrite HAVE_PWRITE)
check_function_exists (sigaction HAVE_SIGACTION)
check_function_exists (sigaltstack HAVE_SIGALSTACK)
# NOTE gcc does not fail if you pass a non-existent -Wno-* option as an
# argument. However, it will happily fail if you pass the corresponding -W*
# option. So, we check whether options that disable warnings exist by testing
# the availability of the corresponding option that enables the warning. This
# eliminates the need to check for compiler for several (mainly Clang) options.
check_cxx_compiler_flag (-Wdeprecated HAVE_NO_DEPRECATED)
check_cxx_compiler_flag (-Wunnamed-type-template-args
HAVE_NO_UNNAMED_TYPE_TEMPLATE_ARGS)
# NOTE: Cannot use check_function_exists here since >=vc-14.0 can define
# snprintf as an inline function
check_symbol_exists (snprintf stdio.h HAVE_SNPRINTF)
check_library_exists (dbghelp UnDecorateSymbolName "" HAVE_DBGHELP)
check_c_source_compiles ("
#include <stdlib.h>
static void foo(void) __attribute__ ((unused));
int main(void) { return 0; }
" HAVE___ATTRIBUTE__)
check_c_source_compiles ("
#include <stdlib.h>
static void foo(void) __attribute__ ((visibility(\"default\")));
int main(void) { return 0; }
" HAVE___ATTRIBUTE__VISIBILITY_DEFAULT)
check_c_source_compiles ("
#include <stdlib.h>
static void foo(void) __attribute__ ((visibility(\"hidden\")));
int main(void) { return 0; }
" HAVE___ATTRIBUTE__VISIBILITY_HIDDEN)
check_c_source_compiles ("
int main(void) { if (__builtin_expect(0, 0)) return 1; return 0; }
" HAVE___BUILTIN_EXPECT)
check_c_source_compiles ("
int main(void)
{
int a; if (__sync_val_compare_and_swap(&a, 0, 1)) return 1; return 0;
}
" HAVE___SYNC_VAL_COMPARE_AND_SWAP)
check_c_source_compiles ("
#define _XOPEN_SOURCE 500
#include <pthread.h>
int main(void)
{
pthread_rwlock_t l;
pthread_rwlock_init(&l, NULL);
pthread_rwlock_rdlock(&l);
return 0;
}
" HAVE_RWLOCK)
check_c_source_compiles ("
__declspec(selectany) int a;
int main(void) { return 0; }
" HAVE___DECLSPEC)
check_cxx_source_compiles ("
#include <vector>
vector<int> t; int main() { }
" STL_NO_NAMESPACE)
check_cxx_source_compiles ("
#include <vector>
std::vector<int> t; int main() { }
" STL_STD_NAMESPACE)
check_cxx_source_compiles ("
#include <iostream>
std::ostream& operator<<(std::ostream&, struct s);
using ::operator<<;
int main() { }
" HAVE_USING_OPERATOR)
check_cxx_source_compiles ("
namespace Outer { namespace Inner { int i = 0; }}
using namespace Outer::Inner;;
int main() { return i; }
" HAVE_NAMESPACES)
check_cxx_source_compiles ("
__thread int tls;
int main() { }
" HAVE_GCC_TLS)
check_cxx_source_compiles ("
__declspec(thread) int tls;
int main() { }
" HAVE_MSVC_TLS)
check_cxx_source_compiles ("
thread_local int tls;
int main() { }
" HAVE_CXX11_TLS)
check_cxx_source_compiles ("
#include <type_traits>
std::aligned_storage<sizeof(char), alignof(char)>::type data;
int main() { }
" HAVE_ALIGNED_STORAGE)
if (WITH_TLS)
# Cygwin does not support the thread attribute. Don't bother.
if (HAVE_GCC_TLS)
set (GLOG_THREAD_LOCAL_STORAGE "__thread")
elseif (HAVE_MSVC_TLS)
set (GLOG_THREAD_LOCAL_STORAGE "__declspec(thread)")
elseif (HAVE_CXX11_TLS)
set (GLOG_THREAD_LOCAL_STORAGE thread_local)
endif (HAVE_GCC_TLS)
endif (WITH_TLS)
set (_PC_FIELDS
"gregs[REG_PC]"
"gregs[REG_EIP]"
"gregs[REG_RIP]"
"sc_ip"
"uc_regs->gregs[PT_NIP]"
"gregs[R15]"
"arm_pc"
"mc_eip"
"mc_rip"
"__gregs[REG_EIP]"
"__gregs[REG_RIP]"
"ss.eip"
"__ss.__eip"
"ss.rip"
"__ss.__rip"
"ss.srr0"
"__ss.__srr0"
)
set (_PC_HEADERS ucontext.h signal.h)
if (HAVE_UCONTEXT_H AND NOT PC_FROM_UCONTEXT)
foreach (_PC_FIELD ${_PC_FIELDS})
foreach (_PC_HEADER ${_PC_HEADERS})
set (_TMP
${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/uctfield.c)
file (WRITE ${_TMP} "
#define _GNU_SOURCE 1
#include <${_PC_HEADER}>
int main(void)
{
ucontext_t u;
return u.${_PC_FIELD} == 0;
}
")
try_compile (HAVE_PC_FROM_UCONTEXT ${CMAKE_CURRENT_BINARY_DIR} ${_TMP}
COMPILE_DEFINITIONS _GNU_SOURCE=1)
if (HAVE_PC_FROM_UCONTEXT)
set (PC_FROM_UCONTEXT ${_PC_FIELD} CACHE)
endif (HAVE_PC_FROM_UCONTEXT)
endforeach (_PC_HEADER)
endforeach (_PC_FIELD)
endif (HAVE_UCONTEXT_H AND NOT PC_FROM_UCONTEXT)
if (STL_STD_NAMESPACE)
set (STL_NAMESPACE std)
else (STL_STD_NAMESPACE)
set (STL_NAMESPACE "")
endif (STL_STD_NAMESPACE)
set (GOOGLE_NAMESPACE google)
set (_START_GOOGLE_NAMESPACE_ "namespace ${GOOGLE_NAMESPACE} {")
set (_END_GOOGLE_NAMESPACE_ "}")
if (HAVE___UINT16)
set (ac_cv_have___uint16 1)
else (HAVE___UINT16)
set (ac_cv_have___uint16 0)
endif (HAVE___UINT16)
if (HAVE_INTTYPES_H)
set (ac_cv_have_inttypes_h 1)
else (HAVE_INTTYPES_H)
set (ac_cv_have_inttypes_h 0)
endif (HAVE_INTTYPES_H)
if (HAVE_LIB_GFLAGS)
set (ac_cv_have_libgflags 1)
else (HAVE_LIB_GFLAGS)
set (ac_cv_have_libgflags 0)
endif (HAVE_LIB_GFLAGS)
if (HAVE_STDINT_H)
set (ac_cv_have_stdint_h 1)
else (HAVE_STDINT_H)
set (ac_cv_have_stdint_h 0)
endif (HAVE_STDINT_H)
if (HAVE_SYS_TYPES_H)
set (ac_cv_have_systypes_h 1)
else (HAVE_SYS_TYPES_H)
set (ac_cv_have_systypes_h 0)
endif (HAVE_SYS_TYPES_H)
if (HAVE_U_INT16_T)
set (ac_cv_have_u_int16_t 1)
else (HAVE_U_INT16_T)
set (ac_cv_have_u_int16_t 0)
endif (HAVE_U_INT16_T)
if (HAVE_UINT16_T)
set (ac_cv_have_uint16_t 1)
else (HAVE_UINT16_T)
set (ac_cv_have_uint16_t 0)
endif (HAVE_UINT16_T)
if (HAVE_UNISTD_H)
set (ac_cv_have_unistd_h 1)
else (HAVE_UNISTD_H)
set (ac_cv_have_unistd_h 0)
endif (HAVE_UNISTD_H)
set (ac_google_namespace ${GOOGLE_NAMESPACE})
set (ac_google_end_namespace ${_END_GOOGLE_NAMESPACE_})
set (ac_google_start_namespace ${_START_GOOGLE_NAMESPACE_})
if (HAVE___ATTRIBUTE__)
set (ac_cv___attribute___noreturn "__attribute__((noreturn))")
set (ac_cv___attribute___noinline "__attribute__((noinline))")
elseif (HAVE___DECLSPEC)
set (ac_cv___attribute___noreturn "__declspec(noreturn)")
#set (ac_cv___attribute___noinline "__declspec(noinline)")
endif (HAVE___ATTRIBUTE__)
if (HAVE___BUILTIN_EXPECT)
set (ac_cv_have___builtin_expect 1)
else (HAVE___BUILTIN_EXPECT)
set (ac_cv_have___builtin_expect 0)
endif (HAVE___BUILTIN_EXPECT)
if (HAVE_USING_OPERATOR)
set (ac_cv_cxx_using_operator 1)
else (HAVE_USING_OPERATOR)
set (ac_cv_cxx_using_operator 0)
endif (HAVE_USING_OPERATOR)
if (HAVE_EXECINFO_H)
set (HAVE_STACKTRACE 1)
endif (HAVE_EXECINFO_H)
if (WITH_SYMBOLIZE)
if (WIN32 OR CYGWIN)
cmake_push_check_state (RESET)
set (CMAKE_REQUIRED_LIBRARIES DbgHelp)
check_cxx_source_runs ([=[
#include <windows.h>
#include <dbghelp.h>
#include <cstdlib>
void foobar() { }
int main()
{
HANDLE process = GetCurrentProcess();
if (!SymInitialize(process, NULL, TRUE))
return EXIT_FAILURE;
char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
SYMBOL_INFO *symbol = reinterpret_cast<SYMBOL_INFO *>(buf);
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = MAX_SYM_NAME;
void* const pc = reinterpret_cast<void*>(&foobar);
BOOL ret = SymFromAddr(process, reinterpret_cast<DWORD64>(pc), 0, symbol);
return ret ? EXIT_SUCCESS : EXIT_FAILURE;
}
]=] HAVE_SYMBOLIZE)
cmake_pop_check_state ()
if (HAVE_SYMBOLIZE)
set (HAVE_STACKTRACE 1)
endif (HAVE_SYMBOLIZE)
elseif (UNIX OR (APPLE AND HAVE_DLADDR))
set (HAVE_SYMBOLIZE 1)
endif (WIN32 OR CYGWIN)
endif (WITH_SYMBOLIZE)
check_cxx_source_compiles ("
#include <cstdlib>
#include <time.h>
int main()
{
time_t timep;
struct tm result;
localtime_r(&timep, &result);
return EXIT_SUCCESS;
}
" HAVE_LOCALTIME_R)
set (SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
if (WITH_THREADS AND Threads_FOUND)
if (CMAKE_USE_PTHREADS_INIT)
set (HAVE_PTHREAD 1)
endif (CMAKE_USE_PTHREADS_INIT)
else (WITH_THREADS AND Threads_FOUND)
set (NO_THREADS 1)
endif (WITH_THREADS AND Threads_FOUND)
set (TEST_SRC_DIR \"${CMAKE_CURRENT_SOURCE_DIR}\")
configure_file (src/config.h.cmake.in config.h)
configure_file (src/glog/logging.h.in glog/logging.h @ONLY)
configure_file (src/glog/raw_logging.h.in glog/raw_logging.h @ONLY)
configure_file (src/glog/stl_logging.h.in glog/stl_logging.h @ONLY)
configure_file (src/glog/vlog_is_on.h.in glog/vlog_is_on.h @ONLY)
if (WITH_PKGCONFIG)
set (VERSION ${PROJECT_VERSION})
set (prefix ${CMAKE_INSTALL_PREFIX})
set (exec_prefix ${CMAKE_INSTALL_FULL_BINDIR})
set (libdir ${CMAKE_INSTALL_FULL_LIBDIR})
set (includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR})
configure_file (
"${PROJECT_SOURCE_DIR}/libglog.pc.in"
"${PROJECT_BINARY_DIR}/libglog.pc"
@ONLY
)
unset (VERSION)
unset (prefix)
unset (exec_prefix)
unset (libdir)
unset (includedir)
endif (WITH_PKGCONFIG)
set (CMAKE_CXX_VISIBILITY_PRESET default)
set (CMAKE_VISIBILITY_INLINES_HIDDEN 1)
set (GLOG_PUBLIC_H
${CMAKE_CURRENT_BINARY_DIR}/glog/logging.h
${CMAKE_CURRENT_BINARY_DIR}/glog/raw_logging.h
${CMAKE_CURRENT_BINARY_DIR}/glog/stl_logging.h
${CMAKE_CURRENT_BINARY_DIR}/glog/vlog_is_on.h
src/glog/log_severity.h
)
set (GLOG_SRCS
${GLOG_PUBLIC_H}
src/base/commandlineflags.h
src/base/googleinit.h
src/base/mutex.h
src/demangle.cc
src/demangle.h
src/logging.cc
src/raw_logging.cc
src/symbolize.cc
src/symbolize.h
src/utilities.cc
src/utilities.h
src/vlog_is_on.cc
)
if (HAVE_PTHREAD OR WIN32)
list (APPEND GLOG_SRCS src/signalhandler.cc)
endif (HAVE_PTHREAD OR WIN32)
if (WIN32)
list (APPEND GLOG_SRCS
src/windows/port.cc
src/windows/port.h
)
endif (WIN32)
add_compile_options ($<$<AND:$<BOOL:${HAVE_NO_UNNAMED_TYPE_TEMPLATE_ARGS}>,$<NOT:$<CXX_COMPILER_ID:GNU>>>:-Wno-unnamed-type-template-args>)
set (_glog_CMake_BINDIR ${CMAKE_INSTALL_BINDIR})
set (_glog_CMake_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR})
set (_glog_CMake_LIBDIR ${CMAKE_INSTALL_LIBDIR})
set (_glog_CMake_INSTALLDIR ${_glog_CMake_LIBDIR}/cmake/glog)
set (_glog_CMake_DIR glog/cmake)
set (_glog_CMake_DATADIR ${CMAKE_INSTALL_DATAROOTDIR}/${_glog_CMake_DIR})
set (_glog_BINARY_CMake_DATADIR
${CMAKE_CURRENT_BINARY_DIR}/${_glog_CMake_DATADIR})
# Add additional CMake find modules here.
set (_glog_CMake_MODULES)
if (Unwind_FOUND)
# Copy the module only if libunwind is actually used.
list (APPEND _glog_CMake_MODULES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindUnwind.cmake)
endif (Unwind_FOUND)
# Generate file name for each module in the binary directory
foreach (_file ${_glog_CMake_MODULES})
get_filename_component (_module "${_file}" NAME)
list (APPEND _glog_BINARY_CMake_MODULES
${_glog_BINARY_CMake_DATADIR}/${_module})
endforeach (_file)
if (_glog_CMake_MODULES)
# Copy modules to binary directory during the build
add_custom_command (OUTPUT ${_glog_BINARY_CMake_MODULES}
COMMAND ${CMAKE_COMMAND} -E make_directory
${_glog_BINARY_CMake_DATADIR}
COMMAND ${CMAKE_COMMAND} -E copy ${_glog_CMake_MODULES}
${_glog_BINARY_CMake_DATADIR}
DEPENDS ${_glog_CMake_MODULES}
COMMENT "Copying find modules..."
)
endif (_glog_CMake_MODULES)
add_library (glog
${GLOG_SRCS}
${_glog_BINARY_CMake_MODULES}
)
add_library(glog::glog ALIAS glog)
set_target_properties (glog PROPERTIES POSITION_INDEPENDENT_CODE ON)
if (Unwind_FOUND)
target_link_libraries (glog PUBLIC unwind::unwind)
set (Unwind_DEPENDENCY "find_dependency (Unwind ${Unwind_VERSION})")
endif (Unwind_FOUND)
if (HAVE_DBGHELP)
target_link_libraries (glog PUBLIC dbghelp)
endif (HAVE_DBGHELP)
if (HAVE_PTHREAD)
target_link_libraries (glog PUBLIC ${CMAKE_THREAD_LIBS_INIT})
endif (HAVE_PTHREAD)
if (WIN32 AND HAVE_SNPRINTF)
set_property (SOURCE src/windows/port.cc APPEND PROPERTY COMPILE_DEFINITIONS
HAVE_SNPRINTF)
endif (WIN32 AND HAVE_SNPRINTF)
if (gflags_FOUND)
target_link_libraries (glog PUBLIC gflags)
if (NOT BUILD_SHARED_LIBS)
# Don't use __declspec(dllexport|dllimport) if this is a static build
targeT_compile_definitions (glog PUBLIC GFLAGS_DLL_DECLARE_FLAG= GFLAGS_DLL_DEFINE_FLAG=)
endif (NOT BUILD_SHARED_LIBS)
endif (gflags_FOUND)
set_target_properties (glog PROPERTIES VERSION ${PROJECT_VERSION})
set_target_properties (glog PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR})
if (WIN32)
target_compile_definitions (glog PUBLIC GLOG_NO_ABBREVIATED_SEVERITIES)
endif (WIN32)
set_target_properties (glog PROPERTIES PUBLIC_HEADER "${GLOG_PUBLIC_H}")
target_include_directories (glog BEFORE PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>"
"$<INSTALL_INTERFACE:${_glog_CMake_INCLUDE_DIR}>"
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
if (WIN32)
target_include_directories (glog PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/windows>"
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/windows)
endif (WIN32)
set_target_properties (glog PROPERTIES DEFINE_SYMBOL LIBGLOG_EXPORTS)
if (NOT BUILD_SHARED_LIBS)
target_compile_definitions (glog PUBLIC GOOGLE_GLOG_DLL_DECL=)
else (NOT BUILD_SHARED_LIBS)
target_compile_definitions (glog PRIVATE GOOGLE_GLOG_IS_A_DLL=1)
if (HAVE___DECLSPEC)
set (_EXPORT "__declspec(dllexport)")
set (_IMPORT "__declspec(dllimport)")
elseif (HAVE___ATTRIBUTE__VISIBILITY_DEFAULT)
set (_EXPORT "__attribute__((visibility(\"default\")))")
set (_IMPORT "")
endif (HAVE___DECLSPEC)
target_compile_definitions (glog PRIVATE
"GOOGLE_GLOG_DLL_DECL=${_EXPORT}")
target_compile_definitions (glog INTERFACE
"GOOGLE_GLOG_DLL_DECL=${_IMPORT}")
target_compile_definitions (glog INTERFACE
"GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS=${_IMPORT}")
endif (NOT BUILD_SHARED_LIBS)
# Unit testing
if (BUILD_TESTING)
add_executable (logging_unittest
src/logging_unittest.cc
)
target_link_libraries (logging_unittest PRIVATE glog)
add_executable (stl_logging_unittest
src/stl_logging_unittest.cc
)
target_link_libraries (stl_logging_unittest PRIVATE glog)
if (HAVE_NO_DEPRECATED)
set_property (TARGET stl_logging_unittest APPEND PROPERTY COMPILE_OPTIONS
-Wno-deprecated)
endif (HAVE_NO_DEPRECATED)
if (HAVE_UNORDERED_MAP AND HAVE_UNORDERED_SET)
target_compile_definitions (stl_logging_unittest PRIVATE
GLOG_STL_LOGGING_FOR_UNORDERED)
endif (HAVE_UNORDERED_MAP AND HAVE_UNORDERED_SET)
if (HAVE_TR1_UNORDERED_MAP AND HAVE_TR1_UNORDERED_SET)
target_compile_definitions (stl_logging_unittest PRIVATE
GLOG_STL_LOGGING_FOR_TR1_UNORDERED)
endif (HAVE_TR1_UNORDERED_MAP AND HAVE_TR1_UNORDERED_SET)
if (HAVE_EXT_HASH_MAP AND HAVE_EXT_HASH_SET)
target_compile_definitions (stl_logging_unittest PRIVATE
GLOG_STL_LOGGING_FOR_EXT_HASH)
endif (HAVE_EXT_HASH_MAP AND HAVE_EXT_HASH_SET)
if (HAVE_EXT_SLIST)
target_compile_definitions (stl_logging_unittest PRIVATE
GLOG_STL_LOGGING_FOR_EXT_SLIST)
endif (HAVE_EXT_SLIST)
if (HAVE_SYMBOLIZE)
add_executable (symbolize_unittest
src/symbolize_unittest.cc
)
target_link_libraries (symbolize_unittest PRIVATE glog)
endif (HAVE_SYMBOLIZE)
add_executable (demangle_unittest
src/demangle_unittest.cc
)
target_link_libraries (demangle_unittest PRIVATE glog)
if (HAVE_STACKTRACE)
add_executable (stacktrace_unittest
src/stacktrace_unittest.cc
)
target_link_libraries (stacktrace_unittest PRIVATE glog)
endif (HAVE_STACKTRACE)
add_executable (utilities_unittest
src/utilities_unittest.cc
)
target_link_libraries (utilities_unittest PRIVATE glog)
if (HAVE_STACKTRACE AND HAVE_SYMBOLIZE)
add_executable (signalhandler_unittest
src/signalhandler_unittest.cc
)
target_link_libraries (signalhandler_unittest PRIVATE glog)
endif (HAVE_STACKTRACE AND HAVE_SYMBOLIZE)
add_test (NAME demangle COMMAND demangle_unittest)
add_test (NAME logging COMMAND logging_unittest)
if (TARGET signalhandler_unittest)
add_test (NAME signalhandler COMMAND signalhandler_unittest)
endif (TARGET signalhandler_unittest)
if (TARGET stacktrace_unittest)
add_test (NAME stacktrace COMMAND stacktrace_unittest)
set_tests_properties(stacktrace PROPERTIES TIMEOUT 30)
endif (TARGET stacktrace_unittest)
add_test (NAME stl_logging COMMAND stl_logging_unittest)
if (TARGET symbolize_unittest)
add_test (NAME symbolize COMMAND symbolize_unittest)
endif (TARGET symbolize_unittest)
# Generate an initial cache
get_cache_variables (_CACHEVARS EXCLUDE CMAKE_MAKE_PROGRAM)
set (_INITIAL_CACHE
${CMAKE_CURRENT_BINARY_DIR}/test_package_config/glog_package_config_initial_cache.cmake)
# Package config test
add_test (NAME cmake_package_config_init COMMAND ${CMAKE_COMMAND}
-DTEST_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}/test_package_config
-DINITIAL_CACHE=${_INITIAL_CACHE}
-DCACHEVARS=${_CACHEVARS}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestInitPackageConfig.cmake
)
add_test (NAME cmake_package_config_generate COMMAND ${CMAKE_COMMAND}
-DPATH=$ENV{PATH}
-DINITIAL_CACHE=${_INITIAL_CACHE}
-DTEST_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}/test_package_config/working_config
-DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}/src/package_config_unittest/working_config
-DPACKAGE_DIR=${CMAKE_CURRENT_BINARY_DIR}
-DGENERATOR=${CMAKE_GENERATOR}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestPackageConfig.cmake
)
add_test (NAME cmake_package_config_build COMMAND
${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/test_package_config/working_config
)
add_test (NAME cmake_package_config_cleanup COMMAND ${CMAKE_COMMAND} -E
remove_directory
${CMAKE_CURRENT_BINARY_DIR}/test_package_config
)
# Fixtures setup
set_tests_properties (cmake_package_config_init PROPERTIES FIXTURES_SETUP
cmake_package_config)
set_tests_properties (cmake_package_config_generate PROPERTIES FIXTURES_SETUP
cmake_package_config_working)
# Fixtures cleanup
set_tests_properties (cmake_package_config_cleanup PROPERTIES FIXTURES_CLEANUP
cmake_package_config)
# Fixture requirements
set_tests_properties (cmake_package_config_generate PROPERTIES
FIXTURES_REQUIRED cmake_package_config)
set_tests_properties (cmake_package_config_build PROPERTIES
FIXTURES_REQUIRED "cmake_package_config;cmake_package_config_working")
endif (BUILD_TESTING)
install (TARGETS glog
EXPORT glog-targets
RUNTIME DESTINATION ${_glog_CMake_BINDIR}
PUBLIC_HEADER DESTINATION ${_glog_CMake_INCLUDE_DIR}/glog
LIBRARY DESTINATION ${_glog_CMake_LIBDIR}
ARCHIVE DESTINATION ${_glog_CMake_LIBDIR})
if (WITH_PKGCONFIG)
install (
FILES "${PROJECT_BINARY_DIR}/libglog.pc"
DESTINATION "${_glog_CMake_LIBDIR}/pkgconfig"
)
endif (WITH_PKGCONFIG)
set (glog_CMake_VERSION 3.0)
if (gflags_FOUND)
# Ensure clients locate only the package config and not third party find
# modules having the same name. This avoid cmake_policy PUSH/POP errors.
if (CMAKE_VERSION VERSION_LESS 3.9)
set (gflags_DEPENDENCY "find_dependency (gflags ${gflags_VERSION})")
else (CMAKE_VERSION VERSION_LESS 3.9)
# Passing additional find_package arguments to find_dependency is possible
# starting with CMake 3.9.
set (glog_CMake_VERSION 3.9)
set (gflags_DEPENDENCY "find_dependency (gflags ${gflags_VERSION} NO_MODULE)")
endif (CMAKE_VERSION VERSION_LESS 3.9)
endif (gflags_FOUND)
configure_package_config_file (glog-config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/glog-config.cmake
INSTALL_DESTINATION ${_glog_CMake_INSTALLDIR}
NO_CHECK_REQUIRED_COMPONENTS_MACRO)
write_basic_package_version_file (glog-config-version.cmake VERSION
${PROJECT_VERSION} COMPATIBILITY SameMajorVersion)
export (TARGETS glog NAMESPACE glog:: FILE glog-targets.cmake)
export (PACKAGE glog)
get_filename_component (_PREFIX "${CMAKE_INSTALL_PREFIX}" ABSOLUTE)
# Directory containing the find modules relative to the config install
# directory.
file (RELATIVE_PATH glog_REL_CMake_MODULES
${_PREFIX}/${_glog_CMake_INSTALLDIR}
${_PREFIX}/${_glog_CMake_DATADIR}/glog-modules.cmake)
get_filename_component (glog_REL_CMake_DATADIR ${glog_REL_CMake_MODULES}
DIRECTORY)
set (glog_FULL_CMake_DATADIR
${CMAKE_CURRENT_BINARY_DIR}/${_glog_CMake_DATADIR})
configure_file (glog-modules.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/glog-modules.cmake @ONLY)
install (CODE
"
set (glog_FULL_CMake_DATADIR \"\\\${CMAKE_CURRENT_LIST_DIR}/${glog_REL_CMake_DATADIR}\")
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/glog-modules.cmake.in
\"${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/glog-modules.cmake\" @ONLY)
file (INSTALL
\"${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/glog-modules.cmake\"
DESTINATION
\"\${CMAKE_INSTALL_PREFIX}/${_glog_CMake_INSTALLDIR}\")
"
COMPONENT Development
)
install (FILES
${CMAKE_CURRENT_BINARY_DIR}/glog-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/glog-config-version.cmake
${CMAKE_CURRENT_BINARY_DIR}/glog-modules.cmake
DESTINATION ${_glog_CMake_INSTALLDIR})
# Find modules in share/glog/cmake
install (DIRECTORY ${_glog_BINARY_CMake_DATADIR}
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/glog
COMPONENT Development
FILES_MATCHING PATTERN "*.cmake"
)
install (EXPORT glog-targets NAMESPACE glog:: DESTINATION
${_glog_CMake_INSTALLDIR})

58
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,58 @@
# How to contribute #
We'd love to accept your patches and contributions to this project. There are
a just a few small guidelines you need to follow.
## Contributor License Agreement ##
Contributions to any Google project must be accompanied by a Contributor
License Agreement. This is not a copyright **assignment**, it simply gives
Google permission to use and redistribute your contributions as part of the
project.
* If you are an individual writing original source code and you're sure you
own the intellectual property, then you'll need to sign an [individual
CLA][].
* If you work for a company that wants to allow you to contribute your work,
then you'll need to sign a [corporate CLA][].
You generally only need to submit a CLA once, so if you've already submitted
one (even if it was for a different project), you probably don't need to do it
again.
[individual CLA]: https://developers.google.com/open-source/cla/individual
[corporate CLA]: https://developers.google.com/open-source/cla/corporate
Once your CLA is submitted (or if you already submitted one for
another Google project), make a commit adding yourself to the
[AUTHORS][] and [CONTRIBUTORS][] files. This commit can be part
of your first [pull request][].
[AUTHORS]: AUTHORS
[CONTRIBUTORS]: CONTRIBUTORS
## Submitting a patch ##
1. It's generally best to start by opening a new issue describing the bug or
feature you're intending to fix. Even if you think it's relatively minor,
it's helpful to know what people are working on. Mention in the initial
issue that you are planning to work on that bug or feature so that it can
be assigned to you.
1. Follow the normal process of [forking][] the project, and setup a new
branch to work in. It's important that each group of changes be done in
separate branches in order to ensure that a pull request only includes the
commits related to that bug or feature.
1. Do your best to have [well-formed commit messages][] for each change.
This provides consistency throughout the project, and ensures that commit
messages are able to be formatted properly by various git tools.
1. Finally, push the commits to your fork and submit a [pull request][].
[forking]: https://help.github.com/articles/fork-a-repo
[well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
[pull request]: https://help.github.com/articles/creating-a-pull-request

48
CONTRIBUTORS Normal file
View file

@ -0,0 +1,48 @@
# People who have agreed to one of the CLAs and can contribute patches.
# The AUTHORS file lists the copyright holders; this file
# lists people. For example, Google employees are listed here
# but not in AUTHORS, because Google holds the copyright.
#
# Names should be added to this file only after verifying that
# the individual or the individual's organization has agreed to
# the appropriate Contributor License Agreement, found here:
#
# https://developers.google.com/open-source/cla/individual
# https://developers.google.com/open-source/cla/corporate
#
# The agreement for individuals can be filled out on the web.
#
# When adding J Random Contributor's name to this file,
# either J's name or J's organization's name should be
# added to the AUTHORS file, depending on whether the
# individual or corporate CLA was used.
#
# Names should be added to this file as:
# Name <email address>
#
# Please keep the list sorted.
Abhishek Dasgupta <abhi2743@gmail.com>
Abhishek Parmar <abhishek@orng.net>
Andrew Schwartzmeyer <andrew@schwartzmeyer.com>
Andy Ying <andy@trailofbits.com>
Brian Silverman <bsilver16384@gmail.com>
Fumitoshi Ukai <ukai@google.com>
Guillaume Dumont <dumont.guillaume@gmail.com>
Håkan L. S. Younes <hyounes@google.com>
Ivan Penkov <ivanpe@google.com>
Jacob Trimble <modmaker@google.com>
Jim Ray <jimray@google.com>
Marco Wang <m.aesophor@gmail.com>
Michael Darr <mdarr@matician.com>
Michael Tanner <michael@tannertaxpro.com>
MiniLight <MiniLightAR@Gmail.com>
Peter Collingbourne <pcc@google.com>
Rodrigo Queiro <rodrigoq@google.com>
romange <romange@users.noreply.github.com>
Roman Perepelitsa <roman.perepelitsa@gmail.com>
Sergiu Deitsch <sergiu.deitsch@gmail.com>
Shinichiro Hamaji <hamaji@google.com>
tbennun <tbennun@gmail.com>
Teddy Reed <teddy@prosauce.org>
Zhongming Qu <qzmfranklin@gmail.com>

65
COPYING Normal file
View file

@ -0,0 +1,65 @@
Copyright (c) 2008, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
A function gettimeofday in utilities.cc is based on
http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/COPYING&q=GetSystemTimeAsFileTime%20license:bsd
The license of this code is:
Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name(s) of the above-listed copyright holder(s) nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

99
ChangeLog Normal file
View file

@ -0,0 +1,99 @@
2019-01-22 Google Inc. <opensource@google.com>
* google-glog: version 0.4.0.
* See git log for the details.
2017-05-09 Google Inc. <opensource@google.com>
* google-glog: version 0.3.5
* See git log for the details.
2015-03-09 Google Inc. <opensource@google.com>
* google-glog: version 0.3.4
* See git log for the details.
2013-02-01 Google Inc. <opensource@google.com>
* google-glog: version 0.3.3
* Add --disable-rtti option for configure.
* Visual Studio build and test fix.
* QNX build fix (thanks vanuan).
* Reduce warnings.
* Fixed LOG_SYSRESULT (thanks ukai).
* FreeBSD build fix (thanks yyanagisawa).
* Clang build fix.
* Now users can re-initialize glog after ShutdownGoogleLogging.
* Color output support by GLOG_colorlogtostderr (thanks alexs).
* Now glog's ABI around flags are compatible with gflags.
* Document mentions how to modify flags from user programs.
2012-01-12 Google Inc. <opensource@google.com>
* google-glog: version 0.3.2
* Clang support.
* Demangler and stacktrace improvement for newer GCCs.
* Now fork(2) doesn't mess up log files.
* Make valgrind happier.
* Reduce warnings for more -W options.
* Provide a workaround for ERROR defined by windows.h.
2010-06-15 Google Inc. <opensource@google.com>
* google-glog: version 0.3.1
* GLOG_* environment variables now work even when gflags is installed.
* Snow leopard support.
* Now we can build and test from out side tree.
* Add DCHECK_NOTNULL.
* Add ShutdownGoogleLogging to close syslog (thanks DGunchev)
* Fix --enable-frame-pointers option (thanks kazuki.ohta)
* Fix libunwind detection (thanks giantchen)
2009-07-30 Google Inc. <opensource@google.com>
* google-glog: version 0.3.0
* Fix a deadlock happened when user uses glog with recent gflags.
* Suppress several unnecessary warnings (thanks keir).
* NetBSD and OpenBSD support.
* Use Win32API GetComputeNameA properly (thanks magila).
* Fix user name detection for Windows (thanks ademin).
* Fix several minor bugs.
2009-04-10 Google Inc. <opensource@google.com>
* google-glog: version 0.2.1
* Fix timestamps of VC++ version.
* Add pkg-config support (thanks Tomasz)
* Fix build problem when building with gtest (thanks Michael)
* Add --with-gflags option for configure (thanks Michael)
* Fixes for GCC 4.4 (thanks John)
2009-01-23 Google Inc. <opensource@google.com>
* google-glog: version 0.2
* Add initial Windows VC++ support.
* Google testing/mocking frameworks integration.
* Link pthread library automatically.
* Flush logs in signal handlers.
* Add macros LOG_TO_STRING, LOG_AT_LEVEL, DVLOG, and LOG_TO_SINK_ONLY.
* Log microseconds.
* Add --log_backtrace_at option.
* Fix some minor bugs.
2008-11-18 Google Inc. <opensource@google.com>
* google-glog: version 0.1.2
* Add InstallFailureSignalHandler(). (satorux)
* Re-organize the way to produce stacktraces.
* Don't define unnecessary macro DISALLOW_EVIL_CONSTRUCTORS.
2008-10-15 Google Inc. <opensource@google.com>
* google-glog: version 0.1.1
* Support symbolize for MacOSX 10.5.
* BUG FIX: --vmodule didn't work with gflags.
* BUG FIX: symbolize_unittest failed with GCC 4.3.
* Several fixes on the document.
2008-10-07 Google Inc. <opensource@google.com>
* google-glog: initial release:
The glog package contains a library that implements application-level
logging. This library provides logging APIs based on C++-style
streams and various helper macros.

View file

@ -0,0 +1,14 @@
# Build Ubuntu image
FROM @BUILD_ARCH@/@BUILD_FLAVOR@:@BUILD_RELEASE@
# see https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#/run
RUN apt-get update && \
apt-get install -y --no-install-recommends \
@BUILD_PACKAGES@ \
build-essential \
g++
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY . /usr/src/app

313
INSTALL Normal file
View file

@ -0,0 +1,313 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006, 2007 Free Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Glog-Specific Install Notes
================================
*** NOTE FOR 64-BIT LINUX SYSTEMS
The glibc built-in stack-unwinder on 64-bit systems has some problems
with the glog libraries. (In particular, if you are using
InstallFailureSignalHandler(), the signal may be raised in the middle
of malloc, holding some malloc-related locks when they invoke the
stack unwinder. The built-in stack unwinder may call malloc
recursively, which may require the thread to acquire a lock it already
holds: deadlock.)
For that reason, if you use a 64-bit system and you need
InstallFailureSignalHandler(), we strongly recommend you install
libunwind before trying to configure or install google glog.
libunwind can be found at
http://download.savannah.nongnu.org/releases/libunwind/libunwind-snap-070410.tar.gz
Even if you already have libunwind installed, you will probably still
need to install from the snapshot to get the latest version.
CAUTION: if you install libunwind from the URL above, be aware that
you may have trouble if you try to statically link your binary with
glog: that is, if you link with 'gcc -static -lgcc_eh ...'. This
is because both libunwind and libgcc implement the same C++ exception
handling APIs, but they implement them differently on some platforms.
This is not likely to be a problem on ia64, but may be on x86-64.
Also, if you link binaries statically, make sure that you add
-Wl,--eh-frame-hdr to your linker options. This is required so that
libunwind can find the information generated by the compiler required
for stack unwinding.
Using -static is rare, though, so unless you know this will affect you
it probably won't.
If you cannot or do not wish to install libunwind, you can still try
to use two kinds of stack-unwinder: 1. glibc built-in stack-unwinder
and 2. frame pointer based stack-unwinder.
1. As we already mentioned, glibc's unwinder has a deadlock issue.
However, if you don't use InstallFailureSignalHandler() or you don't
worry about the rare possibilities of deadlocks, you can use this
stack-unwinder. If you specify no options and libunwind isn't
detected on your system, the configure script chooses this unwinder by
default.
2. The frame pointer based stack unwinder requires that your
application, the glog library, and system libraries like libc, all be
compiled with a frame pointer. This is *not* the default for x86-64.
If you are on x86-64 system, know that you have a set of system
libraries with frame-pointers enabled, and compile all your
applications with -fno-omit-frame-pointer, then you can enable the
frame pointer based stack unwinder by passing the
--enable-frame-pointers flag to configure.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README.md' file for
instructions specific to this package.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README.md' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
6. Often, you can also type `make uninstall' to remove the installed
files again.
Building glog - Using vcpkg
===========================
The url of vcpkg is: https://github.com/Microsoft/vcpkg
You can download and install glog using the vcpkg dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install glog
The glog port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that the
`configure' script does not know about. Run `./configure --help' for
details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README.md' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out automatically,
but needs to determine by the type of machine the package will run on.
Usually, assuming the package is built to be run on the _same_
architectures, `configure' can figure that out, but if it prints a
message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share, you
can create a site shell script called `config.site' that gives default
values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

259
Makefile.am Normal file
View file

@ -0,0 +1,259 @@
## Process this file with automake to produce Makefile.in
AUTOMAKE_OPTIONS = subdir-objects foreign
# Make sure that when we re-make ./configure, we get the macros we need
ACLOCAL_AMFLAGS = -I m4
# This is so we can #include <glog/foo>
AM_CPPFLAGS = -I$(top_srcdir)/src
# This is mostly based on configure options
AM_CXXFLAGS =
# These are good warnings to turn on by default
if GCC
AM_CXXFLAGS += -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare
endif
# These are x86-specific, having to do with frame-pointers
if X86_64
if ENABLE_FRAME_POINTERS
AM_CXXFLAGS += -fno-omit-frame-pointer
else
# TODO(csilvers): check if -fomit-frame-pointer might be in $(CXXFLAGS),
# before setting this.
AM_CXXFLAGS += -DNO_FRAME_POINTER
endif
endif
if DISABLE_RTTI
AM_CXXFLAGS += -fno-rtti
endif
glogincludedir = $(includedir)/glog
## The .h files you want to install (that is, .h files that people
## who install this package can include in their own applications.)
## We have to include both the .h and .h.in forms. The latter we
## put in noinst_HEADERS.
gloginclude_HEADERS = src/glog/log_severity.h
nodist_gloginclude_HEADERS = src/glog/logging.h src/glog/raw_logging.h src/glog/vlog_is_on.h src/glog/stl_logging.h
noinst_HEADERS = src/glog/logging.h.in src/glog/raw_logging.h.in src/glog/vlog_is_on.h.in src/glog/stl_logging.h.in
## This is for HTML and other documentation you want to install.
## Add your documentation files (in doc/) in addition to these
## top-level boilerplate files. Also add a TODO file if you have one.
dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL README.md README.windows \
doc/designstyle.css doc/glog.html
## The libraries (.so's) you want to install
lib_LTLIBRARIES =
# The libraries libglog depends on.
COMMON_LIBS = $(PTHREAD_LIBS) $(GFLAGS_LIBS) $(UNWIND_LIBS)
# Compile switches for our unittest.
TEST_CFLAGS = $(GTEST_CFLAGS) $(GMOCK_CFLAGS) $(GFLAGS_CFLAGS) \
$(MINGW_CFLAGS) $(AM_CXXFLAGS)
# Libraries for our unittest.
TEST_LIBS = $(GTEST_LIBS) $(GMOCK_LIBS) $(GFLAGS_LIBS)
## unittests you want to run when people type 'make check'.
## TESTS is for binary unittests, check_SCRIPTS for script-based unittests.
## TESTS_ENVIRONMENT sets environment variables for when you run unittest,
## but it only seems to take effect for *binary* unittests (argh!)
TESTS =
# Set a small stack size so that (at least on Linux) PIEs are mapped at a lower
# address than DSOs. This is used by symbolize_pie_unittest to check that we can
# successfully symbolize PIEs loaded at low addresses.
TESTS_ENVIRONMENT = ulimit -s 8192;
check_SCRIPTS =
# Every time you add a unittest to check_SCRIPTS, add it here too
noinst_SCRIPTS =
# Binaries used for script-based unittests.
TEST_BINARIES =
TESTS += logging_unittest
logging_unittest_SOURCES = $(gloginclude_HEADERS) \
src/logging_unittest.cc \
src/config_for_unittests.h \
src/mock-log.h
nodist_logging_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
logging_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
logging_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
logging_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
check_SCRIPTS += logging_striplog_test_sh
noinst_SCRIPTS += src/logging_striplog_test.sh
logging_striplog_test_sh: logging_striptest0 logging_striptest2 logging_striptest10
$(top_srcdir)/src/logging_striplog_test.sh
check_SCRIPTS += demangle_unittest_sh
noinst_SCRIPTS += src/demangle_unittest.sh
demangle_unittest_sh: demangle_unittest
$(builddir)/demangle_unittest # force to create lt-demangle_unittest
$(top_srcdir)/src/demangle_unittest.sh
check_SCRIPTS += signalhandler_unittest_sh
noinst_SCRIPTS += src/signalhandler_unittest.sh
signalhandler_unittest_sh: signalhandler_unittest
$(builddir)/signalhandler_unittest # force to create lt-signalhandler_unittest
$(top_srcdir)/src/signalhandler_unittest.sh
TEST_BINARIES += logging_striptest0
logging_striptest0_SOURCES = $(gloginclude_HEADERS) \
src/logging_striptest_main.cc
nodist_logging_striptest0_SOURCES = $(nodist_gloginclude_HEADERS)
logging_striptest0_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
logging_striptest0_LDFLAGS = $(PTHREAD_CFLAGS)
logging_striptest0_LDADD = libglog.la $(COMMON_LIBS)
TEST_BINARIES += logging_striptest2
logging_striptest2_SOURCES = $(gloginclude_HEADERS) \
src/logging_striptest2.cc
nodist_logging_striptest2_SOURCES = $(nodist_gloginclude_HEADERS)
logging_striptest2_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
logging_striptest2_LDFLAGS = $(PTHREAD_CFLAGS)
logging_striptest2_LDADD = libglog.la $(COMMON_LIBS)
TEST_BINARIES += logging_striptest10
logging_striptest10_SOURCES = $(gloginclude_HEADERS) \
src/logging_striptest10.cc
nodist_logging_striptest10_SOURCES = $(nodist_gloginclude_HEADERS)
logging_striptest10_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
logging_striptest10_LDFLAGS = $(PTHREAD_CFLAGS)
logging_striptest10_LDADD = libglog.la $(COMMON_LIBS)
TESTS += demangle_unittest
demangle_unittest_SOURCES = $(gloginclude_HEADERS) \
src/demangle_unittest.cc
nodist_demangle_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
demangle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
demangle_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
demangle_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
TESTS += stacktrace_unittest
stacktrace_unittest_SOURCES = $(gloginclude_HEADERS) \
src/stacktrace_unittest.cc
nodist_stacktrace_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
stacktrace_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
stacktrace_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
stacktrace_unittest_LDADD = libglog.la $(COMMON_LIBS)
TESTS += symbolize_unittest
symbolize_unittest_SOURCES = $(gloginclude_HEADERS) \
src/symbolize_unittest.cc
nodist_symbolize_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
symbolize_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
symbolize_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
symbolize_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
TESTS += symbolize_pie_unittest
symbolize_pie_unittest_SOURCES = $(gloginclude_HEADERS) \
src/symbolize_unittest.cc
nodist_symbolize_pie_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
symbolize_pie_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS) -fPIE
symbolize_pie_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -pie
symbolize_pie_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
TESTS += stl_logging_unittest
stl_logging_unittest_SOURCES = $(gloginclude_HEADERS) \
src/stl_logging_unittest.cc
nodist_stl_logging_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
stl_logging_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
stl_logging_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
stl_logging_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
TEST_BINARIES += signalhandler_unittest
signalhandler_unittest_SOURCES = $(gloginclude_HEADERS) \
src/signalhandler_unittest.cc
nodist_signalhandler_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
signalhandler_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
signalhandler_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
signalhandler_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
TESTS += utilities_unittest
utilities_unittest_SOURCES = $(gloginclude_HEADERS) \
src/utilities_unittest.cc
nodist_utilities_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
utilities_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
utilities_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
utilities_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
if HAVE_GMOCK
TESTS += mock_log_test
mock_log_test_SOURCES = $(gloginclude_HEADERS) \
src/mock-log_test.cc
nodist_mock_log_test_SOURCES = $(nodist_gloginclude_HEADERS)
mock_log_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
mock_log_test_LDFLAGS = $(PTHREAD_CFLAGS)
mock_log_test_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
endif
## vvvv RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS
lib_LTLIBRARIES += libglog.la
libglog_la_SOURCES = $(gloginclude_HEADERS) \
src/logging.cc src/raw_logging.cc src/vlog_is_on.cc \
src/utilities.cc src/utilities.h \
src/demangle.cc src/demangle.h \
src/stacktrace.h \
src/stacktrace_generic-inl.h \
src/stacktrace_libunwind-inl.h \
src/stacktrace_powerpc-inl.h \
src/stacktrace_x86-inl.h \
src/stacktrace_x86_64-inl.h \
src/symbolize.cc src/symbolize.h \
src/signalhandler.cc \
src/base/mutex.h src/base/googleinit.h \
src/base/commandlineflags.h src/googletest.h
nodist_libglog_la_SOURCES = $(nodist_gloginclude_HEADERS)
libglog_la_CXXFLAGS = $(PTHREAD_CFLAGS) $(GFLAGS_CFLAGS) $(MINGW_CFLAGS) \
$(AM_CXXFLAGS) -DNDEBUG
libglog_la_LDFLAGS = $(PTHREAD_CFLAGS) $(GFLAGS_LDFLAGS)
libglog_la_LIBADD = $(COMMON_LIBS)
## The location of the windows project file for each binary we make
WINDOWS_PROJECTS = google-glog.sln
WINDOWS_PROJECTS += vsprojects/libglog/libglog.vcproj
WINDOWS_PROJECTS += vsprojects/logging_unittest/logging_unittest.vcproj
WINDOWS_PROJECTS += vsprojects/libglog_static/libglog_static.vcproj
WINDOWS_PROJECTS += vsprojects/logging_unittest_static/logging_unittest_static.vcproj
## ^^^^ END OF RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS
## This should always include $(TESTS), but may also include other
## binaries that you compile but don't want automatically installed.
noinst_PROGRAMS = $(TESTS) $(TEST_BINARIES)
rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec
@cd packages && ./rpm.sh ${PACKAGE} ${VERSION}
deb: dist-gzip packages/deb.sh packages/deb/*
@cd packages && ./deb.sh ${PACKAGE} ${VERSION}
# Windows wants write permission to .vcproj files and maybe even sln files.
dist-hook:
test -e "$(distdir)/vsprojects" \
&& chmod -R u+w $(distdir)/*.sln $(distdir)/vsprojects/
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status --recheck
EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec \
packages/deb.sh packages/deb/* \
$(SCRIPTS) src/logging_unittest.err src/demangle_unittest.txt \
src/windows/config.h src/windows/port.h src/windows/port.cc \
src/windows/preprocess.sh \
src/windows/glog/log_severity.h src/windows/glog/logging.h \
src/windows/glog/raw_logging.h src/windows/glog/stl_logging.h \
src/windows/glog/vlog_is_on.h \
$(WINDOWS_PROJECTS)
CLEANFILES = core demangle.dm demangle.nm signalhandler.out* \
signalhandler_unittest.*.log.INFO.*
# Add pkgconfig file
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libglog.pc

10
README.md Normal file
View file

@ -0,0 +1,10 @@
[![Build Status](https://img.shields.io/travis/google/glog/master.svg?label=Travis)](https://travis-ci.org/google/glog/builds)
[![Grunt status](https://img.shields.io/appveyor/ci/google-admin/glog/master.svg?label=Appveyor)](https://ci.appveyor.com/project/google-admin/glog/history)
This repository contains a C++ implementation of the Google logging
module. Documentation for the implementation is in doc/.
See INSTALL for (generic) installation instructions for C++: basically
```sh
./autogen.sh && ./configure && make && make install
```

17
README.windows Normal file
View file

@ -0,0 +1,17 @@
This project has been ported to Windows, including stack tracing, signal
handling, and unit tests.
A Visual Studio solution file is explicitly not provided because it is not
maintainable. Instead, a CMake build system exists to generate the correct
solution for your version of Visual Studio.
In short,
(1) Install CMake from: https://cmake.org/download/
(2) With CMake on your PATH, run `cmake .` to generate the build files
(3) Either use `cmake --build`, or open the generated solution
CMake provides different generators, and by default will pick the most relevant
one to your environment. If you need a specific version of Visual Studio, use
`cmake . -G <generator-name>`, and see `cmake --help` for the available
generators. Also see `-T <toolset-name>`, which can used to request the native
x64 toolchain with `-T host=x64`.

10
WORKSPACE Normal file
View file

@ -0,0 +1,10 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "com_github_gflags_gflags",
strip_prefix = "gflags-2.2.2",
urls = [
"https://mirror.bazel.build/github.com/gflags/gflags/archive/v2.2.2.tar.gz",
"https://github.com/gflags/gflags/archive/v2.2.2.tar.gz",
],
)

71
appveyor.yml Normal file
View file

@ -0,0 +1,71 @@
# global environment variables
environment:
global:
# path to source directory of project to be built
PROJECT_DIR: .
# output test results for failing tests
CTEST_OUTPUT_ON_FAILURE: 1
# test matrix
matrix:
- TOOLCHAIN: "vs-14-2015-sdk-8-1"
GENERATOR: "Visual Studio 14 2015 Win64"
TEST_TARGET: RUN_TESTS
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- TOOLCHAIN: "vs-14-2015-win64"
GENERATOR: "Visual Studio 14 2015 Win64"
TEST_TARGET: RUN_TESTS
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- TOOLCHAIN: "vs-15-2017-win64"
GENERATOR: "Visual Studio 15 2017 Win64"
TEST_TARGET: RUN_TESTS
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- TOOLCHAIN: "vs-15-2017-win64-cxx17"
GENERATOR: "Visual Studio 15 2017 Win64"
TEST_TARGET: RUN_TESTS
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- TOOLCHAIN: "mingw-cxx11"
GENERATOR: "MinGW Makefiles"
MINGW_PATH: "C:\\mingw-w64\\x86_64-7.2.0-posix-seh-rt_v5-rev1\\mingw64\\bin"
TEST_TARGET: test
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- TOOLCHAIN: "mingw-gnuxx11"
GENERATOR: "MinGW Makefiles"
MINGW_PATH: "C:\\mingw-w64\\x86_64-7.2.0-posix-seh-rt_v5-rev1\\mingw64\\bin"
TEST_TARGET: test
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- TOOLCHAIN: "mingw-cxx17"
GENERATOR: "MinGW Makefiles"
MINGW_PATH: "C:\\mingw-w64\\x86_64-7.2.0-posix-seh-rt_v5-rev1\\mingw64\\bin"
TEST_TARGET: test
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
install:
# Remove entry with sh.exe from PATH to fix error with MinGW toolchain
# (For MinGW make to work correctly sh.exe must NOT be in your path)
# * http://stackoverflow.com/a/3870338/2288008
- cmd: set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
# set MINGW path
- cmd: IF DEFINED MINGW_PATH set PATH=%MINGW_PATH%;%PATH%
# Visual Studio 15 2017: Mimic behavior of older versions
- cmd: set VS150COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools
build_script:
- cmd: cmake -H. -B_build_%TOOLCHAIN%_Debug -G "%GENERATOR%" -DCMAKE_TOOLCHAIN_FILE="%cd%\toolchains\%TOOLCHAIN%.cmake"
- cmd: cmake --build _build_%TOOLCHAIN%_Debug --config Debug
#- cmd: cmake -H. -B_build_%TOOLCHAIN%_Release -G "%GENERATOR%" -DCMAKE_TOOLCHAIN_FILE="%cd%\toolchains\%TOOLCHAIN%.cmake"
#- cmd: cmake --build _build_%TOOLCHAIN%_Release --config Release
# add git back to PATH for `diff` command in case of error
- cmd: set PATH=C:\Program Files\Git\usr\bin;%PATH%
- cmd: IF DEFINED TEST_TARGET cmake --build _build_%TOOLCHAIN%_Debug --target %TEST_TARGET%
#- cmd: IF DEFINED TEST_TARGET cmake --build _build_%TOOLCHAIN%_Release --target %TEST_TARGET%

5
autogen.sh Executable file
View file

@ -0,0 +1,5 @@
#!/bin/sh
set -eu
autoreconf -i

8
bazel/example/BUILD Normal file
View file

@ -0,0 +1,8 @@
cc_test(
name = "main",
size = "small",
srcs = ["main.cc"],
deps = [
"//:glog",
],
)

22
bazel/example/main.cc Normal file
View file

@ -0,0 +1,22 @@
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <glog/stl_logging.h>
int main(int argc, char* argv[]) {
// Initialize Google's logging library.
google::InitGoogleLogging(argv[0]);
// Optional: parse command line flags
gflags::ParseCommandLineFlags(&argc, &argv, true);
LOG(INFO) << "Hello, world!";
// glog/stl_logging.h allows logging STL containers.
std::vector<int> x;
x.push_back(1);
x.push_back(2);
x.push_back(3);
LOG(INFO) << "ABC, it's easy as " << x;
return 0;
}

219
bazel/glog.bzl Normal file
View file

@ -0,0 +1,219 @@
# Implement a macro glog_library() that the BUILD file can load.
# By default, glog is built with gflags support. You can change this behavior
# by using glog_library(with_gflags=0)
#
# This file is inspired by the following sample BUILD files:
# https://github.com/google/glog/issues/61
# https://github.com/google/glog/files/393474/BUILD.txt
#
# Known issue: the namespace parameter is not supported on Win32.
def glog_library(namespace = "google", with_gflags = 1, **kwargs):
if native.repository_name() != "@":
repo_name = native.repository_name().lstrip("@")
gendir = "$(GENDIR)/external/" + repo_name
src_windows = "external/%s/src/windows" % repo_name
else:
gendir = "$(GENDIR)"
src_windows = "src/windows"
# Config setting for WebAssembly target.
native.config_setting(
name = "wasm",
values = {"cpu": "wasm"},
)
common_copts = [
"-DGLOG_BAZEL_BUILD",
"-DHAVE_STDINT_H",
"-DHAVE_STRING_H",
"-DHAVE_UNWIND_H",
] + (["-DHAVE_LIB_GFLAGS"] if with_gflags else [])
wasm_copts = [
# Disable warnings that exists in glog.
"-Wno-sign-compare",
"-Wno-unused-function",
"-Wno-unused-local-typedefs",
"-Wno-unused-variable",
# Inject a C++ namespace.
"-DGOOGLE_NAMESPACE='%s'" % namespace,
# Allows src/base/mutex.h to include pthread.h.
"-DHAVE_PTHREAD",
# Allows src/logging.cc to determine the host name.
"-DHAVE_SYS_UTSNAME_H",
# For src/utilities.cc.
"-DHAVE_SYS_TIME_H",
# Enable dumping stacktrace upon sigaction.
"-DHAVE_SIGACTION",
# For logging.cc.
"-DHAVE_PREAD",
"-DHAVE___ATTRIBUTE__",
"-I%s/glog_internal" % gendir,
]
linux_or_darwin_copts = wasm_copts + [
# For src/utilities.cc.
"-DHAVE_SYS_SYSCALL_H",
]
freebsd_only_copts = [
# Enable declaration of _Unwind_Backtrace
"-D_GNU_SOURCE",
]
darwin_only_copts = [
# For stacktrace.
"-DHAVE_DLADDR",
]
windows_only_copts = [
"-DHAVE_SNPRINTF",
"-I" + src_windows,
]
windows_only_srcs = [
"src/glog/log_severity.h",
"src/windows/config.h",
"src/windows/port.cc",
"src/windows/port.h",
]
gflags_deps = ["@com_github_gflags_gflags//:gflags"] if with_gflags else []
native.cc_library(
name = "glog",
visibility = ["//visibility:public"],
srcs = [
"src/base/commandlineflags.h",
"src/base/googleinit.h",
"src/base/mutex.h",
"src/demangle.cc",
"src/demangle.h",
"src/logging.cc",
"src/raw_logging.cc",
"src/signalhandler.cc",
"src/stacktrace.h",
"src/stacktrace_generic-inl.h",
"src/stacktrace_libunwind-inl.h",
"src/stacktrace_powerpc-inl.h",
"src/stacktrace_windows-inl.h",
"src/stacktrace_x86-inl.h",
"src/stacktrace_x86_64-inl.h",
"src/symbolize.cc",
"src/symbolize.h",
"src/utilities.cc",
"src/utilities.h",
"src/vlog_is_on.cc",
] + select({
"@bazel_tools//src/conditions:windows": windows_only_srcs,
"//conditions:default": [":config_h"],
}),
copts =
select({
"@bazel_tools//src/conditions:windows": common_copts + windows_only_copts,
"@bazel_tools//src/conditions:darwin": common_copts + linux_or_darwin_copts + darwin_only_copts,
"@bazel_tools//src/conditions:freebsd": common_copts + linux_or_darwin_copts + freebsd_only_copts,
":wasm": common_copts + wasm_copts,
"//conditions:default": common_copts + linux_or_darwin_copts,
}),
deps = [
":glog_headers",
] + gflags_deps,
**kwargs
)
# glog headers vary depending on the os.
native.cc_library(
name = "glog_headers",
deps = select({
"@bazel_tools//src/conditions:windows": [":windows_glog_headers"],
"//conditions:default": [":default_glog_headers"],
}),
)
native.cc_library(
name = "windows_glog_headers",
hdrs = native.glob(["src/windows/glog/*.h"]),
strip_include_prefix = "src/windows",
# We need to override the default GOOGLE_GLOG_DLL_DECL from
# src/windows/glog/*.h to match src/windows/config.h.
defines = ["GOOGLE_GLOG_DLL_DECL=__declspec(dllexport)"],
deps = [":strip_include_prefix_hack"],
)
# Workaround https://github.com/bazelbuild/bazel/issues/6337 by declaring
# the dependencies without strip_include_prefix.
native.cc_library(
name = "strip_include_prefix_hack",
hdrs = native.glob(["src/windows/*.h"]),
)
native.cc_library(
name = "default_glog_headers",
strip_include_prefix = "src",
hdrs = [
"src/glog/log_severity.h",
":logging_h",
":raw_logging_h",
":stl_logging_h",
":vlog_is_on_h",
],
)
native.genrule(
name = "config_h",
srcs = [
"src/config.h.cmake.in",
],
outs = [
"glog_internal/config.h",
],
cmd = "awk '{ gsub(/^#cmakedefine/, \"//cmakedefine\"); print; }' $< > $@",
)
native.genrule(
name = "gen_sh",
outs = [
"gen.sh",
],
cmd = r'''\
#!/bin/sh
cat > $@ <<"EOF"
sed -e 's/@ac_cv_cxx_using_operator@/1/g' \
-e 's/@ac_cv_have_unistd_h@/1/g' \
-e 's/@ac_cv_have_stdint_h@/1/g' \
-e 's/@ac_cv_have_systypes_h@/1/g' \
-e 's/@ac_cv_have_libgflags@/{}/g' \
-e 's/@ac_cv_have_uint16_t@/1/g' \
-e 's/@ac_cv_have___builtin_expect@/1/g' \
-e 's/@ac_cv_have_.*@/0/g' \
-e 's/@ac_google_start_namespace@/namespace google {{/g' \
-e 's/@ac_google_end_namespace@/}}/g' \
-e 's/@ac_google_namespace@/google/g' \
-e 's/@ac_cv___attribute___noinline@/__attribute__((noinline))/g' \
-e 's/@ac_cv___attribute___noreturn@/__attribute__((noreturn))/g' \
-e 's/@ac_cv___attribute___printf_4_5@/__attribute__((__format__ (__printf__, 4, 5)))/g'
EOF
'''.format(int(with_gflags)),
)
[
native.genrule(
name = "%s_h" % f,
srcs = [
"src/glog/%s.h.in" % f,
],
outs = [
"src/glog/%s.h" % f,
],
cmd = "$(location :gen_sh) < $< > $@",
tools = [":gen_sh"],
)
for f in [
"vlog_is_on",
"stl_logging",
"raw_logging",
"logging",
]
]

View file

@ -0,0 +1,69 @@
macro(determine_gflags_namespace VARIABLE)
if (NOT DEFINED "${VARIABLE}")
if (CMAKE_REQUIRED_INCLUDES)
set (CHECK_INCLUDE_FILE_CXX_INCLUDE_DIRS "-DINCLUDE_DIRECTORIES=${CMAKE_REQUIRED_INCLUDES}")
else ()
set (CHECK_INCLUDE_FILE_CXX_INCLUDE_DIRS)
endif ()
set(MACRO_CHECK_INCLUDE_FILE_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(_NAMESPACES gflags google)
set(_check_code
"
#include <gflags/gflags.h>
int main(int argc, char**argv)
{
GLOG_GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true);
}
")
if (NOT CMAKE_REQUIRED_QUIET)
message (STATUS "Looking for gflags namespace")
endif ()
if (${ARGC} EQUAL 3)
set (CMAKE_CXX_FLAGS_SAVE ${CMAKE_CXX_FLAGS})
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARGV2}")
endif ()
set (_check_file
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/DetermineGflagsNamespace.cxx)
foreach (_namespace ${_NAMESPACES})
file (WRITE "${_check_file}" "${_check_code}")
try_compile (${VARIABLE}
"${CMAKE_BINARY_DIR}" "${_check_file}"
COMPILE_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}" -DGLOG_GFLAGS_NAMESPACE=${_namespace}
LINK_LIBRARIES gflags
CMAKE_FLAGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
OUTPUT_VARIABLE OUTPUT)
if (${VARIABLE})
set (${VARIABLE} ${_namespace} CACHE INTERNAL "gflags namespace" FORCE)
break ()
else ()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining the gflags namespace ${_namespace} failed with the following output:\n"
"${OUTPUT}\n\n")
endif ()
endforeach (_namespace)
if (${ARGC} EQUAL 3)
set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS_SAVE})
endif ()
if (${VARIABLE})
if (NOT CMAKE_REQUIRED_QUIET)
message (STATUS "Looking for gflags namespace - ${${VARIABLE}}")
endif ()
file (APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining the gflags namespace passed with the following output:\n"
"${OUTPUT}\n\n")
else ()
if (NOT CMAKE_REQUIRED_QUIET)
message (STATUS "Looking for gflags namespace - failed")
endif ()
set (${VARIABLE} ${_namespace} CACHE INTERNAL "gflags namespace")
endif ()
endif ()
endmacro ()

78
cmake/FindUnwind.cmake Normal file
View file

@ -0,0 +1,78 @@
# - Try to find libunwind
# Once done this will define
#
# Unwind_FOUND - system has libunwind
# unwind::unwind - cmake target for libunwind
include (FindPackageHandleStandardArgs)
find_path (Unwind_INCLUDE_DIR NAMES unwind.h libunwind.h DOC "unwind include directory")
find_library (Unwind_LIBRARY NAMES unwind DOC "unwind library")
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
set (Unwind_ARCH "arm")
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
set (Unwind_ARCH "aarch64")
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR
CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64" OR
CMAKE_SYSTEM_PROCESSOR STREQUAL "corei7-64")
set (Unwind_ARCH "x86_64")
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^i.86$")
set (Unwind_ARCH "x86")
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64")
set (Unwind_ARCH "ppc64")
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc")
set (Unwind_ARCH "ppc32")
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
set (Unwind_ARCH "mips")
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^hppa")
set (Unwind_ARCH "hppa")
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^ia64")
set (Unwind_ARCH "ia64")
endif (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
find_library (Unwind_PLATFORM_LIBRARY NAMES "unwind-${Unwind_ARCH}"
DOC "unwind library platform")
mark_as_advanced (Unwind_INCLUDE_DIR Unwind_LIBRARY Unwind_PLATFORM_LIBRARY)
# Extract version information
if (Unwind_LIBRARY)
set (_Unwind_VERSION_HEADER ${Unwind_INCLUDE_DIR}/libunwind-common.h)
if (EXISTS ${_Unwind_VERSION_HEADER})
FILE (READ ${_Unwind_VERSION_HEADER} _Unwind_VERSION_CONTENTS)
string (REGEX REPLACE ".*#define UNW_VERSION_MAJOR[ \t]+([0-9]+).*" "\\1"
Unwind_VERSION_MAJOR "${_Unwind_VERSION_CONTENTS}")
string (REGEX REPLACE ".*#define UNW_VERSION_MINOR[ \t]+([0-9]+).*" "\\1"
Unwind_VERSION_MINOR "${_Unwind_VERSION_CONTENTS}")
string (REGEX REPLACE ".*#define UNW_VERSION_EXTRA[ \t]+([0-9]+).*" "\\1"
Unwind_VERSION_PATCH "${_Unwind_VERSION_CONTENTS}")
set (Unwind_VERSION
${Unwind_VERSION_MAJOR}.${Unwind_VERSION_MINOR}.${Unwind_VERSION_PATCH})
set (Unwind_VERSION_COMPONENTS 3)
endif (EXISTS ${_Unwind_VERSION_HEADER})
endif (Unwind_LIBRARY)
# handle the QUIETLY and REQUIRED arguments and set Unwind_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args (Unwind REQUIRED_VARS Unwind_INCLUDE_DIR
Unwind_LIBRARY Unwind_PLATFORM_LIBRARY VERSION_VAR Unwind_VERSION)
if (Unwind_FOUND)
if (NOT TARGET unwind::unwind)
add_library (unwind::unwind INTERFACE IMPORTED)
set_property (TARGET unwind::unwind PROPERTY
INTERFACE_INCLUDE_DIRECTORIES ${Unwind_INCLUDE_DIR}
)
set_property (TARGET unwind::unwind PROPERTY
INTERFACE_LINK_LIBRARIES ${Unwind_LIBRARY} ${Unwind_PLATFORM_LIBRARY}
)
set_property (TARGET unwind::unwind PROPERTY
IMPORTED_CONFIGURATIONS RELEASE
)
endif (NOT TARGET unwind::unwind)
endif (Unwind_FOUND)

View file

@ -0,0 +1,63 @@
cmake_policy (PUSH)
cmake_policy (VERSION 3.3)
include (CMakeParseArguments)
function (get_cache_variables _CACHEVARS)
set (_SINGLE)
set (_MULTI EXCLUDE)
set (_OPTIONS)
cmake_parse_arguments (_ARGS "${_OPTIONS}" "${_SINGLE}" "${_MULTI}" ${ARGS} ${ARGN})
get_cmake_property (_VARIABLES VARIABLES)
set (CACHEVARS)
foreach (_VAR ${_VARIABLES})
if (DEFINED _ARGS_EXCLUDE)
if ("${_VAR}" IN_LIST _ARGS_EXCLUDE)
continue ()
endif ("${_VAR}" IN_LIST _ARGS_EXCLUDE)
endif (DEFINED _ARGS_EXCLUDE)
get_property (_CACHEVARTYPE CACHE ${_VAR} PROPERTY TYPE)
if ("${_CACHEVARTYPE}" STREQUAL INTERNAL OR
"${_CACHEVARTYPE}" STREQUAL STATIC OR
"${_CACHEVARTYPE}" STREQUAL UNINITIALIZED)
continue ()
endif ("${_CACHEVARTYPE}" STREQUAL INTERNAL OR
"${_CACHEVARTYPE}" STREQUAL STATIC OR
"${_CACHEVARTYPE}" STREQUAL UNINITIALIZED)
get_property (_CACHEVARVAL CACHE ${_VAR} PROPERTY VALUE)
if ("${_CACHEVARVAL}" STREQUAL "")
continue ()
endif ("${_CACHEVARVAL}" STREQUAL "")
get_property (_CACHEVARDOC CACHE ${_VAR} PROPERTY HELPSTRING)
# Escape " in values
string (REPLACE "\"" "\\\"" _CACHEVARVAL "${_CACHEVARVAL}")
# Escape " in help strings
string (REPLACE "\"" "\\\"" _CACHEVARDOC "${_CACHEVARDOC}")
# Escape ; in values
string (REPLACE ";" "\\\;" _CACHEVARVAL "${_CACHEVARVAL}")
# Escape backslash in values
string (REGEX REPLACE "\\\\([^\"])" "\\\\\\1" _CACHEVARVAL "${_CACHEVARVAL}")
if (NOT "${_CACHEVARTYPE}" STREQUAL BOOL)
set (_CACHEVARVAL "\"${_CACHEVARVAL}\"")
endif (NOT "${_CACHEVARTYPE}" STREQUAL BOOL)
if (NOT "${_CACHEVARTYPE}" STREQUAL "" AND NOT "${_CACHEVARVAL}" STREQUAL "")
set (CACHEVARS "${CACHEVARS}set (${_VAR} ${_CACHEVARVAL} CACHE ${_CACHEVARTYPE} \"${_CACHEVARDOC}\")\n")
endif (NOT "${_CACHEVARTYPE}" STREQUAL "" AND NOT "${_CACHEVARVAL}" STREQUAL "")
endforeach (_VAR)
set (${_CACHEVARS} ${CACHEVARS} PARENT_SCOPE)
endfunction (get_cache_variables)
cmake_policy (POP)

81
cmake/INSTALL.md Normal file
View file

@ -0,0 +1,81 @@
# Glog - CMake Support
Glog comes with a CMake build script ([CMakeLists.txt](../CMakeLists.txt)) that can be used on a wide range of platforms.
If you don't have CMake installed already, you can download it for free from <http://www.cmake.org/>.
CMake works by generating native makefiles or build projects that can be used in the compiler environment of your choice.
You can either build Glog with CMake as a standalone project or it can be incorporated into an existing CMake build for another project.
## Table of Contents
- [Building Glog with CMake](#building-glog-with-cmake)
- [Consuming Glog in a CMake Project](#consuming-glog-in-a-cmake-project)
- [Incorporating Glog into a CMake Project](#incorporating-glog-into-a-cmake-project)
## Building Glog with CMake
When building Glog as a standalone project, on Unix-like systems with GNU Make as build tool, the typical workflow is:
1. Get the source code and change to it.
e.g. cloning with git:
```bash
git clone git@github.com:google/glog.git
cd glog
```
2. Run CMake to configure the build tree.
```bash
cmake -H. -Bbuild -G "Unix Makefiles"
```
note: To get the list of available generators (e.g. Visual Studio), use `-G ""`
3. Afterwards, generated files can be used to compile the project.
```bash
cmake --build build
```
4. Test the build software (optional).
```bash
cmake --build build --target test
```
5. Install the built files (optional).
```bash
cmake --build build --target install
```
## Consuming Glog in a CMake Project
If you have Glog installed in your system, you can use the CMake command
`find_package()` to include it in your CMake Project.
```cmake
cmake_minimum_required(VERSION 3.0.2)
project(myproj VERSION 1.0)
find_package(glog 0.4.0 REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp glog::glog)
```
Compile definitions and options will be added automatically to your target as
needed.
## Incorporating Glog into a CMake Project
You can also use the CMake command `add_subdirectory()` to include Glog directly from a subdirectory of your project.
The **glog::glog** target is in this case an ALIAS library target for the **glog** library target.
```cmake
cmake_minimum_required(VERSION 3.0.2)
project(myproj VERSION 1.0)
add_subdirectory(glog)
add_executable(myapp main.cpp)
target_link_libraries(myapp glog::glog)
```
Again, compile definitions and options will be added automatically to your target as
needed.

View file

@ -0,0 +1,12 @@
# Create the build directory
execute_process (
COMMAND ${CMAKE_COMMAND} -E make_directory ${TEST_BINARY_DIR}
RESULT_VARIABLE _DIRECTORY_CREATED_SUCCEEDED
)
if (NOT _DIRECTORY_CREATED_SUCCEEDED EQUAL 0)
message (FATAL_ERROR "Failed to create build directory")
endif (NOT _DIRECTORY_CREATED_SUCCEEDED EQUAL 0)
file (WRITE ${INITIAL_CACHE} "${CACHEVARS}")

View file

@ -0,0 +1,33 @@
# Create the build directory
execute_process (
COMMAND ${CMAKE_COMMAND} -E make_directory ${TEST_BINARY_DIR}
RESULT_VARIABLE _DIRECTORY_CREATED_SUCCEEDED
)
if (NOT _DIRECTORY_CREATED_SUCCEEDED EQUAL 0)
message (FATAL_ERROR "Failed to create build directory")
endif (NOT _DIRECTORY_CREATED_SUCCEEDED EQUAL 0)
# Capture the PATH environment variable content set during project
# generation stage. This is required because later during the build stage
# the PATH is modified again (e.g., for MinGW AppVeyor CI builds) by adding
# back the directory containing git.exe. Incidently, the Git installation
# directory also contains sh.exe which causes MinGW Makefile generation to
# fail.
set (ENV{PATH} ${PATH})
# Run CMake
execute_process (
COMMAND ${CMAKE_COMMAND} -C ${INITIAL_CACHE}
-G ${GENERATOR}
-DCMAKE_PREFIX_PATH=${PACKAGE_DIR}
-DCMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=ON
-DCMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY=ON
${SOURCE_DIR}
WORKING_DIRECTORY ${TEST_BINARY_DIR}
RESULT_VARIABLE _GENERATE_SUCCEEDED
)
if (NOT _GENERATE_SUCCEEDED EQUAL 0)
message (FATAL_ERROR "Failed to generate project files using CMake")
endif (NOT _GENERATE_SUCCEEDED EQUAL 0)

246
configure.ac Normal file
View file

@ -0,0 +1,246 @@
## Process this file with autoconf to produce configure.
## In general, the safest way to proceed is to run the following:
## % aclocal -I . -I `pwd`/../autoconf && autoheader && autoconf && automake
# make sure we're interpreted by some minimal autoconf
AC_PREREQ(2.57)
AC_INIT(glog, 0.4.0, opensource@google.com)
# The argument here is just something that should be in the current directory
# (for sanity checking)
AC_CONFIG_SRCDIR(README.md)
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(src/config.h)
AC_LANG(C++)
# Checks for programs.
AC_PROG_CC
AC_PROG_CPP
AC_PROG_CXX
AM_CONDITIONAL(GCC, test "$GCC" = yes) # let the Makefile know if we're gcc
AC_PROG_LIBTOOL
AC_SUBST(LIBTOOL_DEPS)
# Check whether some low-level functions/files are available
AC_HEADER_STDC
# These are tested for by AC_HEADER_STDC, but I check again to set the var
AC_CHECK_HEADER(stdint.h, ac_cv_have_stdint_h=1, ac_cv_have_stdint_h=0)
AC_CHECK_HEADER(sys/types.h, ac_cv_have_systypes_h=1, ac_cv_have_systypes_h=0)
AC_CHECK_HEADER(inttypes.h, ac_cv_have_inttypes_h=1, ac_cv_have_inttypes_h=0)
AC_CHECK_HEADER(pwd.h, ac_cv_have_pwd_h=1, ac_cv_have_pwd_h=0)
AC_CHECK_HEADERS(unistd.h, ac_cv_have_unistd_h=1, ac_cv_have_unistd_h=0)
AC_CHECK_HEADERS(syscall.h)
AC_CHECK_HEADERS(sys/syscall.h)
# For backtrace with glibc.
AC_CHECK_HEADERS(execinfo.h)
# For backtrace with libunwind.
AC_CHECK_HEADERS(libunwind.h, ac_cv_have_libunwind_h=1, ac_cv_have_libunwind_h=0)
AC_CHECK_HEADERS(ucontext.h)
AC_CHECK_HEADERS(sys/utsname.h)
AC_CHECK_HEADERS(pwd.h)
AC_CHECK_HEADERS(syslog.h)
AC_CHECK_HEADERS(sys/time.h)
AC_CHECK_HEADERS(glob.h)
# For backtrace with gcc.
AC_CHECK_HEADERS(unwind.h)
AC_CHECK_HEADER(windows.h, ac_cv_have_windows_h=1, ac_cv_have_windows_h=0)
if test x"$ac_cv_have_windows_h" = x"1"; then
MINGW_CFLAGS=-Isrc/windows
fi
AC_CHECK_SIZEOF(void *)
# These are the types I need. We look for them in either stdint.h,
# sys/types.h, or inttypes.h, all of which are part of the default-includes.
AC_CHECK_TYPE(uint16_t, ac_cv_have_uint16_t=1, ac_cv_have_uint16_t=0)
AC_CHECK_TYPE(u_int16_t, ac_cv_have_u_int16_t=1, ac_cv_have_u_int16_t=0)
AC_CHECK_TYPE(__uint16, ac_cv_have___uint16=1, ac_cv_have___uint16=0)
AC_CHECK_FUNC(sigaltstack,
AC_DEFINE(HAVE_SIGALTSTACK, 1,
[Define if you have the `sigaltstack' function]))
AC_CHECK_FUNC(sigaction,
AC_DEFINE(HAVE_SIGACTION, 1,
[Define if you have the 'sigaction' function]))
AC_CHECK_FUNC(dladdr,
AC_DEFINE(HAVE_DLADDR, 1,
[Define if you have the `dladdr' function]))
AC_CHECK_FUNC(fcntl,
AC_DEFINE(HAVE_FCNTL, 1,
[Define if you have the `fcntl' function]))
AC_CHECK_FUNC(pread,
AC_DEFINE(HAVE_PREAD, 1,
[Define if you have the 'pread' function]))
AC_CHECK_FUNC(pwrite,
AC_DEFINE(HAVE_PWRITE, 1,
[Define if you have the 'pwrite' function]))
AX_C___ATTRIBUTE__
# We only care about these two attributes.
if test x"$ac_cv___attribute__" = x"yes"; then
ac_cv___attribute___noreturn="__attribute__ ((noreturn))"
ac_cv___attribute___noinline="__attribute__ ((noinline))"
ac_cv___attribute___printf_4_5="__attribute__((__format__ (__printf__, 4, 5)))"
else
ac_cv___attribute___noreturn=
ac_cv___attribute___noinline=
ac_cv___attribute___printf_4_5=
fi
AX_C___BUILTIN_EXPECT
if test x"$ac_cv___builtin_expect" = x"yes"; then
ac_cv_have___builtin_expect=1
else
ac_cv_have___builtin_expect=0
fi
AX_C___SYNC_VAL_COMPARE_AND_SWAP
# On x86_64, instead of libunwind, we can choose to compile with frame-pointers
# (This isn't needed on i386, where -fno-omit-frame-pointer is the default).
AC_ARG_ENABLE(frame_pointers,
AS_HELP_STRING([--enable-frame-pointers],
[On x86_64 systems, compile with -fno-omit-frame-pointer (see INSTALL)]),,
enable_frame_pointers=no)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [return __x86_64__ == 1 ? 0 : 1])],
[is_x86_64=yes], [is_x86_64=no])
AM_CONDITIONAL(ENABLE_FRAME_POINTERS, test "$enable_frame_pointers" = yes)
AM_CONDITIONAL(X86_64, test "$is_x86_64" = yes)
AC_ARG_ENABLE(rtti,
AS_HELP_STRING([--disable-rtti],
[Disable RTTI in glog]))
AM_CONDITIONAL(DISABLE_RTTI, test x"$enable_rtti" = x"no")
if test x"$enable_rtti" = x"no"; then
AC_DEFINE(DISABLE_RTTI, 1, [define if glog doesn't use RTTI])
fi
# Some of the code in this directory depends on pthreads
ACX_PTHREAD
if test x"$acx_pthread_ok" = x"yes"; then
# To make libglog depend on libpthread on Linux, we need to add
# -lpthread in addition to -pthread.
AC_CHECK_LIB(pthread, pthread_self)
fi
# Check if there is google-gflags library installed.
SAVE_CFLAGS="$CFLAGS"
SAVE_LIBS="$LIBS"
AC_ARG_WITH(gflags, AS_HELP_STRING[--with-gflags=GFLAGS_DIR],
GFLAGS_CFLAGS="-I${with_gflags}/include"
GFLAGS_LIBS="-L${with_gflags}/lib -lgflags"
CFLAGS="$CFLAGS $GFLAGS_CFLAGS"
LIBS="$LIBS $GFLAGS_LIBS"
)
AC_CHECK_LIB(gflags, main, ac_cv_have_libgflags=1, ac_cv_have_libgflags=0)
if test x"$ac_cv_have_libgflags" = x"1"; then
AC_DEFINE(HAVE_LIB_GFLAGS, 1, [define if you have google gflags library])
if test x"$GFLAGS_LIBS" = x""; then
GFLAGS_LIBS="-lgflags"
fi
else
GFLAGS_CFLAGS=
GFLAGS_LIBS=
fi
CFLAGS="$SAVE_CFLAGS"
LIBS="$SAVE_LIBS"
# TODO(hamaji): Use official m4 macros provided by testing libraries
# once the m4 macro of Google Mocking becomes ready.
# Check if there is Google Test library installed.
AC_CHECK_PROG(GTEST_CONFIG, gtest-config, "yes")
AC_CHECK_LIB(gtest, main, have_gtest_lib="yes")
if test x"$GTEST_CONFIG" = "xyes" -a x"$have_gtest_lib" = "xyes"; then
GTEST_CFLAGS=`gtest-config --cppflags --cxxflags`
GTEST_LIBS=`gtest-config --ldflags --libs`
AC_DEFINE(HAVE_LIB_GTEST, 1, [define if you have google gtest library])
# Check if there is Google Mocking library installed.
AC_CHECK_PROG(GMOCK_CONFIG, gmock-config, "yes")
if test x"$GMOCK_CONFIG" = "xyes"; then
GMOCK_CFLAGS=`gmock-config --cppflags --cxxflags`
GMOCK_LIBS=`gmock-config --ldflags --libs`
AC_DEFINE(HAVE_LIB_GMOCK, 1, [define if you have google gmock library])
else
# We don't run test cases which use Google Mocking framework.
GMOCK_CFLAGS=
GMOCK_LIBS=
fi
else
# We'll use src/googletest.h for our unittests.
GTEST_CFLAGS=
GTEST_LIBS=
fi
AM_CONDITIONAL(HAVE_GMOCK, test x"$GMOCK_CONFIG" = "xyes")
# We want to link in libunwind if it exists
UNWIND_LIBS=
# Unfortunately, we need to check the header file in addition to the
# lib file to check if libunwind is available since libunwind-0.98
# doesn't install all necessary header files.
if test x"$ac_cv_have_libunwind_h" = x"1"; then
AC_CHECK_LIB(unwind, backtrace, UNWIND_LIBS=-lunwind)
fi
AC_SUBST(UNWIND_LIBS)
if test x"$UNWIND_LIBS" != x""; then
AC_DEFINE(HAVE_LIB_UNWIND, 1, [define if you have libunwind])
fi
# We'd like to use read/write locks in several places in the code.
# See if our pthreads support extends to that. Note: for linux, it
# does as long as you define _XOPEN_SOURCE appropriately.
AC_RWLOCK
# Find out what namespace 'normal' STL code lives in, and also what namespace
# the user wants our classes to be defined in
AC_CXX_STL_NAMESPACE
AC_DEFINE_GOOGLE_NAMESPACE(google)
AC_CXX_USING_OPERATOR
AC_PC_FROM_UCONTEXT(AC_MSG_WARN(Could not find the PC. Will not output failed addresses...))
AC_DEFINE_UNQUOTED(TEST_SRC_DIR, "$srcdir", [location of source code])
AC_ARG_ENABLE(unsymbolized-traces,
AS_HELP_STRING([--enable-unsymbolized-traces],
[Print file offsets in traces instead of symbolizing.]),
enable_unsymbolized_traces=yes)
if test x"$enable_unsymbolized_traces" = x"yes"; then
AC_DEFINE(PRINT_UNSYMBOLIZED_STACK_TRACES, 1,
[define if we should print file offsets in traces instead of symbolizing.])
fi
# These are what's needed by logging.h.in and raw_logging.h.in
AC_SUBST(ac_google_start_namespace)
AC_SUBST(ac_google_end_namespace)
AC_SUBST(ac_google_namespace)
AC_SUBST(ac_cv_cxx_using_operator)
AC_SUBST(ac_cv___attribute___noreturn)
AC_SUBST(ac_cv___attribute___noinline)
AC_SUBST(ac_cv___attribute___printf_4_5)
AC_SUBST(ac_cv_have___builtin_expect)
AC_SUBST(ac_cv_have_stdint_h)
AC_SUBST(ac_cv_have_systypes_h)
AC_SUBST(ac_cv_have_inttypes_h)
AC_SUBST(ac_cv_have_unistd_h)
AC_SUBST(ac_cv_have_uint16_t)
AC_SUBST(ac_cv_have_u_int16_t)
AC_SUBST(ac_cv_have___uint16)
AC_SUBST(ac_cv_have_libgflags)
AC_SUBST(GFLAGS_CFLAGS)
AC_SUBST(GTEST_CFLAGS)
AC_SUBST(GMOCK_CFLAGS)
AC_SUBST(MINGW_CFLAGS)
AC_SUBST(GFLAGS_LIBS)
AC_SUBST(GTEST_LIBS)
AC_SUBST(GMOCK_LIBS)
# Write generated configuration file
AC_CONFIG_FILES([Makefile src/glog/logging.h src/glog/raw_logging.h src/glog/vlog_is_on.h src/glog/stl_logging.h])
AC_OUTPUT(libglog.pc)

115
doc/designstyle.css Normal file
View file

@ -0,0 +1,115 @@
body {
background-color: #ffffff;
color: black;
margin-right: 1in;
margin-left: 1in;
}
h1, h2, h3, h4, h5, h6 {
color: #3366ff;
font-family: sans-serif;
}
@media print {
/* Darker version for printing */
h1, h2, h3, h4, h5, h6 {
color: #000080;
font-family: helvetica, sans-serif;
}
}
h1 {
text-align: center;
font-size: 18pt;
}
h2 {
margin-left: -0.5in;
}
h3 {
margin-left: -0.25in;
}
h4 {
margin-left: -0.125in;
}
hr {
margin-left: -1in;
}
/* Definition lists: definition term bold */
dt {
font-weight: bold;
}
address {
text-align: right;
}
/* Use the <code> tag for bits of code and <var> for variables and objects. */
code,pre,samp,var {
color: #006000;
}
/* Use the <file> tag for file and directory paths and names. */
file {
color: #905050;
font-family: monospace;
}
/* Use the <kbd> tag for stuff the user should type. */
kbd {
color: #600000;
}
div.note p {
float: right;
width: 3in;
margin-right: 0%;
padding: 1px;
border: 2px solid #6060a0;
background-color: #fffff0;
}
UL.nobullets {
list-style-type: none;
list-style-image: none;
margin-left: -1em;
}
/*
body:after {
content: "Google Confidential";
}
*/
/* pretty printing styles. See prettify.js */
.str { color: #080; }
.kwd { color: #008; }
.com { color: #800; }
.typ { color: #606; }
.lit { color: #066; }
.pun { color: #660; }
.pln { color: #000; }
.tag { color: #008; }
.atn { color: #606; }
.atv { color: #080; }
pre.prettyprint { padding: 2px; border: 1px solid #888; }
.embsrc { background: #eee; }
@media print {
.str { color: #060; }
.kwd { color: #006; font-weight: bold; }
.com { color: #600; font-style: italic; }
.typ { color: #404; font-weight: bold; }
.lit { color: #044; }
.pun { color: #440; }
.pln { color: #000; }
.tag { color: #006; font-weight: bold; }
.atn { color: #404; }
.atv { color: #060; }
}
/* Table Column Headers */
.hdr {
color: #006;
font-weight: bold;
background-color: #dddddd; }
.hdr2 {
color: #006;
background-color: #eeeeee; }

631
doc/glog.html Normal file
View file

@ -0,0 +1,631 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>How To Use Google Logging Library (glog)</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="http://www.google.com/favicon.ico" type="image/x-icon"
rel="shortcut icon">
<link href="designstyle.css" type="text/css" rel="stylesheet">
<style type="text/css">
<!--
ol.bluelist li {
color: #3366ff;
font-family: sans-serif;
}
ol.bluelist li p {
color: #000;
font-family: "Times Roman", times, serif;
}
ul.blacklist li {
color: #000;
font-family: "Times Roman", times, serif;
}
//-->
</style>
</head>
<body>
<h1>How To Use Google Logging Library (glog)</h1>
<small>(as of
<script type=text/javascript>
var lm = new Date(document.lastModified);
document.write(lm.toDateString());
</script>)
</small>
<br>
<h2> <A NAME=intro>Introduction</A> </h2>
<p><b>Google glog</b> is a library that implements application-level
logging. This library provides logging APIs based on C++-style
streams and various helper macros.
You can log a message by simply streaming things to LOG(&lt;a
particular <a href="#severity">severity level</a>&gt;), e.g.
<pre>
#include &lt;glog/logging.h&gt;
int main(int argc, char* argv[]) {
// Initialize Google's logging library.
google::InitGoogleLogging(argv[0]);
// ...
LOG(INFO) &lt;&lt; "Found " &lt;&lt; num_cookies &lt;&lt; " cookies";
}
</pre>
<p>Google glog defines a series of macros that simplify many common logging
tasks. You can log messages by severity level, control logging
behavior from the command line, log based on conditionals, abort the
program when expected conditions are not met, introduce your own
verbose logging levels, and more. This document describes the
functionality supported by glog. Please note that this document
doesn't describe all features in this library, but the most useful
ones. If you want to find less common features, please check
header files under <code>src/glog</code> directory.
<h2> <A NAME=severity>Severity Level</A> </h2>
<p>
You can specify one of the following severity levels (in
increasing order of severity): <code>INFO</code>, <code>WARNING</code>,
<code>ERROR</code>, and <code>FATAL</code>.
Logging a <code>FATAL</code> message terminates the program (after the
message is logged).
Note that messages of a given severity are logged not only in the
logfile for that severity, but also in all logfiles of lower severity.
E.g., a message of severity <code>FATAL</code> will be logged to the
logfiles of severity <code>FATAL</code>, <code>ERROR</code>,
<code>WARNING</code>, and <code>INFO</code>.
<p>
The <code>DFATAL</code> severity logs a <code>FATAL</code> error in
debug mode (i.e., there is no <code>NDEBUG</code> macro defined), but
avoids halting the program in production by automatically reducing the
severity to <code>ERROR</code>.
<p>Unless otherwise specified, glog writes to the filename
"/tmp/&lt;program name&gt;.&lt;hostname&gt;.&lt;user name&gt;.log.&lt;severity level&gt;.&lt;date&gt;.&lt;time&gt;.&lt;pid&gt;"
(e.g., "/tmp/hello_world.example.com.hamaji.log.INFO.20080709-222411.10474").
By default, glog copies the log messages of severity level
<code>ERROR</code> or <code>FATAL</code> to standard error (stderr)
in addition to log files.
<h2><A NAME=flags>Setting Flags</A></h2>
<p>Several flags influence glog's output behavior.
If the <a href="https://github.com/gflags/gflags">Google
gflags library</a> is installed on your machine, the
<code>configure</code> script (see the INSTALL file in the package for
detail of this script) will automatically detect and use it,
allowing you to pass flags on the command line. For example, if you
want to turn the flag <code>--logtostderr</code> on, you can start
your application with the following command line:
<pre>
./your_application --logtostderr=1
</pre>
If the Google gflags library isn't installed, you set flags via
environment variables, prefixing the flag name with "GLOG_", e.g.
<pre>
GLOG_logtostderr=1 ./your_application
</pre>
<!-- TODO(hamaji): Fill the version number
<p>By glog version 0.x.x, you can use GLOG_* environment variables
even if you have gflags. If both an environment variable and a flag
are specified, the value specified by a flag wins. E.g., if GLOG_v=0
and --v=1, the verbosity will be 1, not 0.
-->
<p>The following flags are most commonly used:
<dl>
<dt><code>logtostderr</code> (<code>bool</code>, default=<code>false</code>)
<dd>Log messages to stderr instead of logfiles.<br>
Note: you can set binary flags to <code>true</code> by specifying
<code>1</code>, <code>true</code>, or <code>yes</code> (case
insensitive).
Also, you can set binary flags to <code>false</code> by specifying
<code>0</code>, <code>false</code>, or <code>no</code> (again, case
insensitive).
<dt><code>stderrthreshold</code> (<code>int</code>, default=2, which
is <code>ERROR</code>)
<dd>Copy log messages at or above this level to stderr in
addition to logfiles. The numbers of severity levels
<code>INFO</code>, <code>WARNING</code>, <code>ERROR</code>, and
<code>FATAL</code> are 0, 1, 2, and 3, respectively.
<dt><code>minloglevel</code> (<code>int</code>, default=0, which
is <code>INFO</code>)
<dd>Log messages at or above this level. Again, the numbers of
severity levels <code>INFO</code>, <code>WARNING</code>,
<code>ERROR</code>, and <code>FATAL</code> are 0, 1, 2, and 3,
respectively.
<dt><code>log_dir</code> (<code>string</code>, default="")
<dd>If specified, logfiles are written into this directory instead
of the default logging directory.
<dt><code>v</code> (<code>int</code>, default=0)
<dd>Show all <code>VLOG(m)</code> messages for <code>m</code> less or
equal the value of this flag. Overridable by --vmodule.
See <a href="#verbose">the section about verbose logging</a> for more
detail.
<dt><code>vmodule</code> (<code>string</code>, default="")
<dd>Per-module verbose level. The argument has to contain a
comma-separated list of &lt;module name&gt;=&lt;log level&gt;.
&lt;module name&gt;
is a glob pattern (e.g., <code>gfs*</code> for all modules whose name
starts with "gfs"), matched against the filename base
(that is, name ignoring .cc/.h./-inl.h).
&lt;log level&gt; overrides any value given by --v.
See also <a href="#verbose">the section about verbose logging</a>.
</dl>
<p>There are some other flags defined in logging.cc. Please grep the
source code for "DEFINE_" to see a complete list of all flags.
<p>You can also modify flag values in your program by modifying global
variables <code>FLAGS_*</code> . Most settings start working
immediately after you update <code>FLAGS_*</code> . The exceptions are
the flags related to destination files. For example, you might want to
set <code>FLAGS_log_dir</code> before
calling <code>google::InitGoogleLogging</code> . Here is an example:
<pre>
LOG(INFO) << "file";
// Most flags work immediately after updating values.
FLAGS_logtostderr = 1;
LOG(INFO) << "stderr";
FLAGS_logtostderr = 0;
// This won't change the log destination. If you want to set this
// value, you should do this before google::InitGoogleLogging .
FLAGS_log_dir = "/some/log/directory";
LOG(INFO) << "the same file";
</pre>
<h2><A NAME=conditional>Conditional / Occasional Logging</A></h2>
<p>Sometimes, you may only want to log a message under certain
conditions. You can use the following macros to perform conditional
logging:
<pre>
LOG_IF(INFO, num_cookies &gt; 10) &lt;&lt; "Got lots of cookies";
</pre>
The "Got lots of cookies" message is logged only when the variable
<code>num_cookies</code> exceeds 10.
If a line of code is executed many times, it may be useful to only log
a message at certain intervals. This kind of logging is most useful
for informational messages.
<pre>
LOG_EVERY_N(INFO, 10) &lt;&lt; "Got the " &lt;&lt; google::COUNTER &lt;&lt; "th cookie";
</pre>
<p>The above line outputs a log messages on the 1st, 11th,
21st, ... times it is executed. Note that the special
<code>google::COUNTER</code> value is used to identify which repetition is
happening.
<p>You can combine conditional and occasional logging with the
following macro.
<pre>
LOG_IF_EVERY_N(INFO, (size &gt; 1024), 10) &lt;&lt; "Got the " &lt;&lt; google::COUNTER
&lt;&lt; "th big cookie";
</pre>
<p>Instead of outputting a message every nth time, you can also limit
the output to the first n occurrences:
<pre>
LOG_FIRST_N(INFO, 20) &lt;&lt; "Got the " &lt;&lt; google::COUNTER &lt;&lt; "th cookie";
</pre>
<p>Outputs log messages for the first 20 times it is executed. Again,
the <code>google::COUNTER</code> identifier indicates which repetition is
happening.
<h2><A NAME=debug>Debug Mode Support</A></h2>
<p>Special "debug mode" logging macros only have an effect in debug
mode and are compiled away to nothing for non-debug mode
compiles. Use these macros to avoid slowing down your production
application due to excessive logging.
<pre>
DLOG(INFO) &lt;&lt; "Found cookies";
DLOG_IF(INFO, num_cookies &gt; 10) &lt;&lt; "Got lots of cookies";
DLOG_EVERY_N(INFO, 10) &lt;&lt; "Got the " &lt;&lt; google::COUNTER &lt;&lt; "th cookie";
</pre>
<h2><A NAME=check>CHECK Macros</A></h2>
<p>It is a good practice to check expected conditions in your program
frequently to detect errors as early as possible. The
<code>CHECK</code> macro provides the ability to abort the application
when a condition is not met, similar to the <code>assert</code> macro
defined in the standard C library.
<p><code>CHECK</code> aborts the application if a condition is not
true. Unlike <code>assert</code>, it is *not* controlled by
<code>NDEBUG</code>, so the check will be executed regardless of
compilation mode. Therefore, <code>fp-&gt;Write(x)</code> in the
following example is always executed:
<pre>
CHECK(fp-&gt;Write(x) == 4) &lt;&lt; "Write failed!";
</pre>
<p>There are various helper macros for
equality/inequality checks - <code>CHECK_EQ</code>,
<code>CHECK_NE</code>, <code>CHECK_LE</code>, <code>CHECK_LT</code>,
<code>CHECK_GE</code>, and <code>CHECK_GT</code>.
They compare two values, and log a
<code>FATAL</code> message including the two values when the result is
not as expected. The values must have <code>operator&lt;&lt;(ostream,
...)</code> defined.
<p>You may append to the error message like so:
<pre>
CHECK_NE(1, 2) &lt;&lt; ": The world must be ending!";
</pre>
<p>We are very careful to ensure that each argument is evaluated exactly
once, and that anything which is legal to pass as a function argument is
legal here. In particular, the arguments may be temporary expressions
which will end up being destroyed at the end of the apparent statement,
for example:
<pre>
CHECK_EQ(string("abc")[1], 'b');
</pre>
<p>The compiler reports an error if one of the arguments is a
pointer and the other is NULL. To work around this, simply static_cast
NULL to the type of the desired pointer.
<pre>
CHECK_EQ(some_ptr, static_cast&lt;SomeType*&gt;(NULL));
</pre>
<p>Better yet, use the CHECK_NOTNULL macro:
<pre>
CHECK_NOTNULL(some_ptr);
some_ptr-&gt;DoSomething();
</pre>
<p>Since this macro returns the given pointer, this is very useful in
constructor initializer lists.
<pre>
struct S {
S(Something* ptr) : ptr_(CHECK_NOTNULL(ptr)) {}
Something* ptr_;
};
</pre>
<p>Note that you cannot use this macro as a C++ stream due to this
feature. Please use <code>CHECK_EQ</code> described above to log a
custom message before aborting the application.
<p>If you are comparing C strings (char *), a handy set of macros
performs case sensitive as well as case insensitive comparisons -
<code>CHECK_STREQ</code>, <code>CHECK_STRNE</code>,
<code>CHECK_STRCASEEQ</code>, and <code>CHECK_STRCASENE</code>. The
CASE versions are case-insensitive. You can safely pass <code>NULL</code>
pointers for this macro. They treat <code>NULL</code> and any
non-<code>NULL</code> string as not equal. Two <code>NULL</code>s are
equal.
<p>Note that both arguments may be temporary strings which are
destructed at the end of the current "full expression"
(e.g., <code>CHECK_STREQ(Foo().c_str(), Bar().c_str())</code> where
<code>Foo</code> and <code>Bar</code> return C++'s
<code>std::string</code>).
<p>The <code>CHECK_DOUBLE_EQ</code> macro checks the equality of two
floating point values, accepting a small error margin.
<code>CHECK_NEAR</code> accepts a third floating point argument, which
specifies the acceptable error margin.
<h2><A NAME=verbose>Verbose Logging</A></h2>
<p>When you are chasing difficult bugs, thorough log messages are very
useful. However, you may want to ignore too verbose messages in usual
development. For such verbose logging, glog provides the
<code>VLOG</code> macro, which allows you to define your own numeric
logging levels. The <code>--v</code> command line option controls
which verbose messages are logged:
<pre>
VLOG(1) &lt;&lt; "I'm printed when you run the program with --v=1 or higher";
VLOG(2) &lt;&lt; "I'm printed when you run the program with --v=2 or higher";
</pre>
<p>With <code>VLOG</code>, the lower the verbose level, the more
likely messages are to be logged. For example, if
<code>--v==1</code>, <code>VLOG(1)</code> will log, but
<code>VLOG(2)</code> will not log. This is opposite of the severity
level, where <code>INFO</code> is 0, and <code>ERROR</code> is 2.
<code>--minloglevel</code> of 1 will log <code>WARNING</code> and
above. Though you can specify any integers for both <code>VLOG</code>
macro and <code>--v</code> flag, the common values for them are small
positive integers. For example, if you write <code>VLOG(0)</code>,
you should specify <code>--v=-1</code> or lower to silence it. This
is less useful since we may not want verbose logs by default in most
cases. The <code>VLOG</code> macros always log at the
<code>INFO</code> log level (when they log at all).
<p>Verbose logging can be controlled from the command line on a
per-module basis:
<pre>
--vmodule=mapreduce=2,file=1,gfs*=3 --v=0
</pre>
<p>will:
<ul>
<li>a. Print VLOG(2) and lower messages from mapreduce.{h,cc}
<li>b. Print VLOG(1) and lower messages from file.{h,cc}
<li>c. Print VLOG(3) and lower messages from files prefixed with "gfs"
<li>d. Print VLOG(0) and lower messages from elsewhere
</ul>
<p>The wildcarding functionality shown by (c) supports both '*'
(matches 0 or more characters) and '?' (matches any single character)
wildcards. Please also check the section about <a
href="#flags">command line flags</a>.
<p>There's also <code>VLOG_IS_ON(n)</code> "verbose level" condition
macro. This macro returns true when the <code>--v</code> is equal or
greater than <code>n</code>. To be used as
<pre>
if (VLOG_IS_ON(2)) {
// do some logging preparation and logging
// that can't be accomplished with just VLOG(2) &lt;&lt; ...;
}
</pre>
<p>Verbose level condition macros <code>VLOG_IF</code>,
<code>VLOG_EVERY_N</code> and <code>VLOG_IF_EVERY_N</code> behave
analogous to <code>LOG_IF</code>, <code>LOG_EVERY_N</code>,
<code>LOF_IF_EVERY</code>, but accept a numeric verbosity level as
opposed to a severity level.
<pre>
VLOG_IF(1, (size &gt; 1024))
&lt;&lt; "I'm printed when size is more than 1024 and when you run the "
"program with --v=1 or more";
VLOG_EVERY_N(1, 10)
&lt;&lt; "I'm printed every 10th occurrence, and when you run the program "
"with --v=1 or more. Present occurence is " &lt;&lt; google::COUNTER;
VLOG_IF_EVERY_N(1, (size &gt; 1024), 10)
&lt;&lt; "I'm printed on every 10th occurence of case when size is more "
" than 1024, when you run the program with --v=1 or more. ";
"Present occurence is " &lt;&lt; google::COUNTER;
</pre>
<h2> <A name="signal">Failure Signal Handler</A> </h2>
<p>
The library provides a convenient signal handler that will dump useful
information when the program crashes on certain signals such as SIGSEGV.
The signal handler can be installed by
google::InstallFailureSignalHandler(). The following is an example of output
from the signal handler.
<pre>
*** Aborted at 1225095260 (unix time) try "date -d @1225095260" if you are using GNU date ***
*** SIGSEGV (@0x0) received by PID 17711 (TID 0x7f893090a6f0) from PID 0; stack trace: ***
PC: @ 0x412eb1 TestWaitingLogSink::send()
@ 0x7f892fb417d0 (unknown)
@ 0x412eb1 TestWaitingLogSink::send()
@ 0x7f89304f7f06 google::LogMessage::SendToLog()
@ 0x7f89304f35af google::LogMessage::Flush()
@ 0x7f89304f3739 google::LogMessage::~LogMessage()
@ 0x408cf4 TestLogSinkWaitTillSent()
@ 0x4115de main
@ 0x7f892f7ef1c4 (unknown)
@ 0x4046f9 (unknown)
</pre>
<p>
By default, the signal handler writes the failure dump to the standard
error. You can customize the destination by InstallFailureWriter().
<h2> <A name="misc">Miscellaneous Notes</A> </h2>
<h3><A NAME=message>Performance of Messages</A></h3>
<p>The conditional logging macros provided by glog (e.g.,
<code>CHECK</code>, <code>LOG_IF</code>, <code>VLOG</code>, ...) are
carefully implemented and don't execute the right hand side
expressions when the conditions are false. So, the following check
may not sacrifice the performance of your application.
<pre>
CHECK(obj.ok) &lt;&lt; obj.CreatePrettyFormattedStringButVerySlow();
</pre>
<h3><A NAME=failure>User-defined Failure Function</A></h3>
<p><code>FATAL</code> severity level messages or unsatisfied
<code>CHECK</code> condition terminate your program. You can change
the behavior of the termination by
<code>InstallFailureFunction</code>.
<pre>
void YourFailureFunction() {
// Reports something...
exit(1);
}
int main(int argc, char* argv[]) {
google::InstallFailureFunction(&amp;YourFailureFunction);
}
</pre>
<p>By default, glog tries to dump stacktrace and makes the program
exit with status 1. The stacktrace is produced only when you run the
program on an architecture for which glog supports stack tracing (as
of September 2008, glog supports stack tracing for x86 and x86_64).
<h3><A NAME=raw>Raw Logging</A></h3>
<p>The header file <code>&lt;glog/raw_logging.h&gt;</code> can be
used for thread-safe logging, which does not allocate any memory or
acquire any locks. Therefore, the macros defined in this
header file can be used by low-level memory allocation and
synchronization code.
Please check <code>src/glog/raw_logging.h.in</code> for detail.
</p>
<h3><A NAME=plog>Google Style perror()</A></h3>
<p><code>PLOG()</code> and <code>PLOG_IF()</code> and
<code>PCHECK()</code> behave exactly like their <code>LOG*</code> and
<code>CHECK</code> equivalents with the addition that they append a
description of the current state of errno to their output lines.
E.g.
<pre>
PCHECK(write(1, NULL, 2) &gt;= 0) &lt;&lt; "Write NULL failed";
</pre>
<p>This check fails with the following error message.
<pre>
F0825 185142 test.cc:22] Check failed: write(1, NULL, 2) &gt;= 0 Write NULL failed: Bad address [14]
</pre>
<h3><A NAME=syslog>Syslog</A></h3>
<p><code>SYSLOG</code>, <code>SYSLOG_IF</code>, and
<code>SYSLOG_EVERY_N</code> macros are available.
These log to syslog in addition to the normal logs. Be aware that
logging to syslog can drastically impact performance, especially if
syslog is configured for remote logging! Make sure you understand the
implications of outputting to syslog before you use these macros. In
general, it's wise to use these macros sparingly.
<h3><A NAME=strip>Strip Logging Messages</A></h3>
<p>Strings used in log messages can increase the size of your binary
and present a privacy concern. You can therefore instruct glog to
remove all strings which fall below a certain severity level by using
the GOOGLE_STRIP_LOG macro:
<p>If your application has code like this:
<pre>
#define GOOGLE_STRIP_LOG 1 // this must go before the #include!
#include &lt;glog/logging.h&gt;
</pre>
<p>The compiler will remove the log messages whose severities are less
than the specified integer value. Since
<code>VLOG</code> logs at the severity level <code>INFO</code>
(numeric value <code>0</code>),
setting <code>GOOGLE_STRIP_LOG</code> to 1 or greater removes
all log messages associated with <code>VLOG</code>s as well as
<code>INFO</code> log statements.
<h3><A NAME=strip>Automatically Remove Old Logs</A></h3>
<p>To enable the log cleaner:
<pre>
google::EnableLogCleaner(3); // keep your logs for 3 days
</pre>
And then Google glog will check if there are overdue logs whenever
a flush is performed. In this example, any log file from your project whose
last modified time is greater than 3 days will be unlink()ed.
<p>This feature can be disabled at any time (if it has been enabled)
<pre>
google::DisableLogCleaner();
</pre>
<h3><A NAME=windows>Notes for Windows users</A></h3>
<p>Google glog defines a severity level <code>ERROR</code>, which is
also defined in <code>windows.h</code> . You can make glog not define
<code>INFO</code>, <code>WARNING</code>, <code>ERROR</code>,
and <code>FATAL</code> by defining
<code>GLOG_NO_ABBREVIATED_SEVERITIES</code> before
including <code>glog/logging.h</code> . Even with this macro, you can
still use the iostream like logging facilities:
<pre>
#define GLOG_NO_ABBREVIATED_SEVERITIES
#include &lt;windows.h&gt;
#include &lt;glog/logging.h&gt;
// ...
LOG(ERROR) &lt;&lt; "This should work";
LOG_IF(ERROR, x &gt; y) &lt;&lt; "This should be also OK";
</pre>
<p>
However, you cannot
use <code>INFO</code>, <code>WARNING</code>, <code>ERROR</code>,
and <code>FATAL</code> anymore for functions defined
in <code>glog/logging.h</code> .
<pre>
#define GLOG_NO_ABBREVIATED_SEVERITIES
#include &lt;windows.h&gt;
#include &lt;glog/logging.h&gt;
// ...
// This won't work.
// google::FlushLogFiles(google::ERROR);
// Use this instead.
google::FlushLogFiles(google::GLOG_ERROR);
</pre>
<p>
If you don't need <code>ERROR</code> defined
by <code>windows.h</code>, there are a couple of more workarounds
which sometimes don't work:
<ul>
<li>#define <code>WIN32_LEAN_AND_MEAN</code> or <code>NOGDI</code>
<strong>before</strong> you #include <code>windows.h</code> .
<li>#undef <code>ERROR</code> <strong>after</strong> you #include
<code>windows.h</code> .
</ul>
<p>See <a href="http://code.google.com/p/google-glog/issues/detail?id=33">
this issue</a> for more detail.
<hr>
<address>
Shinichiro Hamaji<br>
Gregor Hohpe<br>
<script type=text/javascript>
var lm = new Date(document.lastModified);
document.write(lm.toDateString());
</script>
</address>
</body>
</html>

13
glog-config.cmake.in Normal file
View file

@ -0,0 +1,13 @@
if (CMAKE_VERSION VERSION_LESS @glog_CMake_VERSION@)
message (FATAL_ERROR "CMake >= @glog_CMake_VERSION@ required")
endif (CMAKE_VERSION VERSION_LESS @glog_CMake_VERSION@)
@PACKAGE_INIT@
include (CMakeFindDependencyMacro)
include (${CMAKE_CURRENT_LIST_DIR}/glog-modules.cmake)
@gflags_DEPENDENCY@
@Unwind_DEPENDENCY@
include (${CMAKE_CURRENT_LIST_DIR}/glog-targets.cmake)

18
glog-modules.cmake.in Normal file
View file

@ -0,0 +1,18 @@
cmake_policy (PUSH)
cmake_policy (SET CMP0057 NEW)
if (CMAKE_VERSION VERSION_LESS 3.3)
message (FATAL_ERROR "glog-modules.cmake requires the consumer "
"to use CMake 3.3 (or newer)")
endif (CMAKE_VERSION VERSION_LESS 3.3)
set (glog_MODULE_PATH "@glog_FULL_CMake_DATADIR@")
list (APPEND CMAKE_MODULE_PATH ${glog_MODULE_PATH})
if (NOT glog_MODULE_PATH IN_LIST CMAKE_MODULE_PATH)
message (FATAL_ERROR "Cannot add '${glog_MODULE_PATH}' to "
"CMAKE_MODULE_PATH. This will cause glog-config.cmake to fail at "
"locating required find modules. Make sure CMAKE_MODULE_PATH is not a cache variable.")
endif (NOT glog_MODULE_PATH IN_LIST CMAKE_MODULE_PATH)
cmake_policy (POP)

10
libglog.pc.in Normal file
View file

@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libglog
Description: Google Log (glog) C++ logging framework
Version: @VERSION@
Libs: -L${libdir} -lglog
Cflags: -I${includedir}

16
m4/ac_have_attribute.m4 Normal file
View file

@ -0,0 +1,16 @@
AC_DEFUN([AX_C___ATTRIBUTE__], [
AC_MSG_CHECKING(for __attribute__)
AC_CACHE_VAL(ac_cv___attribute__, [
AC_TRY_COMPILE(
[#include <stdlib.h>
static void foo(void) __attribute__ ((unused));
void foo(void) { exit(1); }],
[],
ac_cv___attribute__=yes,
ac_cv___attribute__=no
)])
if test "$ac_cv___attribute__" = "yes"; then
AC_DEFINE(HAVE___ATTRIBUTE__, 1, [define if your compiler has __attribute__])
fi
AC_MSG_RESULT($ac_cv___attribute__)
])

View file

@ -0,0 +1,14 @@
AC_DEFUN([AX_C___BUILTIN_EXPECT], [
AC_MSG_CHECKING(for __builtin_expect)
AC_CACHE_VAL(ac_cv___builtin_expect, [
AC_TRY_COMPILE(
[int foo(void) { if (__builtin_expect(0, 0)) return 1; return 0; }],
[],
ac_cv___builtin_expect=yes,
ac_cv___builtin_expect=no
)])
if test "$ac_cv___builtin_expect" = "yes"; then
AC_DEFINE(HAVE___BUILTIN_EXPECT, 1, [define if your compiler has __builtin_expect])
fi
AC_MSG_RESULT($ac_cv___builtin_expect)
])

View file

@ -0,0 +1,14 @@
AC_DEFUN([AX_C___SYNC_VAL_COMPARE_AND_SWAP], [
AC_MSG_CHECKING(for __sync_val_compare_and_swap)
AC_CACHE_VAL(ac_cv___sync_val_compare_and_swap, [
AC_TRY_LINK(
[],
[int a; if (__sync_val_compare_and_swap(&a, 0, 1)) return 1; return 0;],
ac_cv___sync_val_compare_and_swap=yes,
ac_cv___sync_val_compare_and_swap=no
)])
if test "$ac_cv___sync_val_compare_and_swap" = "yes"; then
AC_DEFINE(HAVE___SYNC_VAL_COMPARE_AND_SWAP, 1, [define if your compiler has __sync_val_compare_and_swap])
fi
AC_MSG_RESULT($ac_cv___sync_val_compare_and_swap)
])

31
m4/ac_rwlock.m4 Normal file
View file

@ -0,0 +1,31 @@
# TODO(csilvers): it would be better to actually try to link against
# -pthreads, to make sure it defines these methods, but that may be
# too hard, since pthread support is really tricky.
# Check for support for pthread_rwlock_init() etc.
# These aren't posix, but are widely supported. To get them on linux,
# you need to define _XOPEN_SOURCE first, so this check assumes your
# application does that.
#
# Note: OS X (as of 6/1/06) seems to support pthread_rwlock, but
# doesn't define PTHREAD_RWLOCK_INITIALIZER. Therefore, we don't test
# that particularly macro. It's probably best if you don't use that
# macro in your code either.
AC_DEFUN([AC_RWLOCK],
[AC_CACHE_CHECK(support for pthread_rwlock_* functions,
ac_cv_rwlock,
[AC_LANG_SAVE
AC_LANG_C
AC_TRY_COMPILE([#define _XOPEN_SOURCE 500
#include <pthread.h>],
[pthread_rwlock_t l; pthread_rwlock_init(&l, NULL);
pthread_rwlock_rdlock(&l);
return 0;],
ac_cv_rwlock=yes, ac_cv_rwlock=no)
AC_LANG_RESTORE
])
if test "$ac_cv_rwlock" = yes; then
AC_DEFINE(HAVE_RWLOCK,1,[define if the compiler implements pthread_rwlock_*])
fi
])

363
m4/acx_pthread.m4 Normal file
View file

@ -0,0 +1,363 @@
# This was retrieved from
# http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?revision=1277&root=avahi
# See also (perhaps for new versions?)
# http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?root=avahi
#
# We've rewritten the inconsistency check code (from avahi), to work
# more broadly. In particular, it no longer assumes ld accepts -zdefs.
# This caused a restructing of the code, but the functionality has only
# changed a little.
dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
dnl
dnl @summary figure out how to build C programs using POSIX threads
dnl
dnl This macro figures out how to build C programs using POSIX threads.
dnl It sets the PTHREAD_LIBS output variable to the threads library and
dnl linker flags, and the PTHREAD_CFLAGS output variable to any special
dnl C compiler flags that are needed. (The user can also force certain
dnl compiler flags/libs to be tested by setting these environment
dnl variables.)
dnl
dnl Also sets PTHREAD_CC to any special C compiler that is needed for
dnl multi-threaded programs (defaults to the value of CC otherwise).
dnl (This is necessary on AIX to use the special cc_r compiler alias.)
dnl
dnl NOTE: You are assumed to not only compile your program with these
dnl flags, but also link it with them as well. e.g. you should link
dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
dnl $LIBS
dnl
dnl If you are only building threads programs, you may wish to use
dnl these variables in your default LIBS, CFLAGS, and CC:
dnl
dnl LIBS="$PTHREAD_LIBS $LIBS"
dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
dnl CC="$PTHREAD_CC"
dnl
dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
dnl
dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
dnl default action will define HAVE_PTHREAD.
dnl
dnl Please let the authors know if this macro fails on any platform, or
dnl if you have any other suggestions or comments. This macro was based
dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with
dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros
dnl posted by Alejandro Forero Cuervo to the autoconf macro repository.
dnl We are also grateful for the helpful feedback of numerous users.
dnl
dnl @category InstalledPackages
dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
dnl @version 2006-05-29
dnl @license GPLWithACException
dnl
dnl Checks for GCC shared/pthread inconsistency based on work by
dnl Marcin Owsiany <marcin@owsiany.pl>
AC_DEFUN([ACX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_LANG_SAVE
AC_LANG_C
acx_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
AC_MSG_RESULT($acx_pthread_ok)
if test x"$acx_pthread_ok" = xno; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.
acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# ... -mt is also the pthreads flag for HP/aCC
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case "${host_cpu}-${host_os}" in
*solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
;;
esac
if test x"$acx_pthread_ok" = xno; then
for flag in $acx_pthread_flags; do
case $flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
PTHREAD_CFLAGS="$flag"
;;
pthread-config)
AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
if test x"$acx_pthread_config" = xno; then continue; fi
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
PTHREAD_LIBS="-l$flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_TRY_LINK([#include <pthread.h>],
[pthread_t th; pthread_join(th, 0);
pthread_attr_init(0); pthread_cleanup_push(0, 0);
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
[acx_pthread_ok=yes])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
AC_MSG_RESULT($acx_pthread_ok)
if test "x$acx_pthread_ok" = xyes; then
break;
fi
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Various other checks:
if test "x$acx_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
AC_MSG_CHECKING([for joinable pthread attribute])
attr_name=unknown
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
[attr_name=$attr; break])
done
AC_MSG_RESULT($attr_name)
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
case "${host_cpu}-${host_os}" in
*-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
*solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
esac
AC_MSG_RESULT(${flag})
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
# More AIX lossage: must compile with xlc_r or cc_r
if test x"$GCC" != xyes; then
AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
else
PTHREAD_CC=$CC
fi
# The next part tries to detect GCC inconsistency with -shared on some
# architectures and systems. The problem is that in certain
# configurations, when -shared is specified, GCC "forgets" to
# internally use various flags which are still necessary.
#
# Prepare the flags
#
save_CFLAGS="$CFLAGS"
save_LIBS="$LIBS"
save_CC="$CC"
# Try with the flags determined by the earlier checks.
#
# -Wl,-z,defs forces link-time symbol resolution, so that the
# linking checks with -shared actually have any value
#
# FIXME: -fPIC is required for -shared on many architectures,
# so we specify it here, but the right way would probably be to
# properly detect whether it is actually required.
CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CC="$PTHREAD_CC"
# In order not to create several levels of indentation, we test
# the value of "$done" until we find the cure or run out of ideas.
done="no"
# First, make sure the CFLAGS we added are actually accepted by our
# compiler. If not (and OS X's ld, for instance, does not accept -z),
# then we can't do this test.
if test x"$done" = xno; then
AC_MSG_CHECKING([whether to check for GCC pthread/shared inconsistencies])
AC_TRY_LINK(,, , [done=yes])
if test "x$done" = xyes ; then
AC_MSG_RESULT([no])
else
AC_MSG_RESULT([yes])
fi
fi
if test x"$done" = xno; then
AC_MSG_CHECKING([whether -pthread is sufficient with -shared])
AC_TRY_LINK([#include <pthread.h>],
[pthread_t th; pthread_join(th, 0);
pthread_attr_init(0); pthread_cleanup_push(0, 0);
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
[done=yes])
if test "x$done" = xyes; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
fi
#
# Linux gcc on some architectures such as mips/mipsel forgets
# about -lpthread
#
if test x"$done" = xno; then
AC_MSG_CHECKING([whether -lpthread fixes that])
LIBS="-lpthread $PTHREAD_LIBS $save_LIBS"
AC_TRY_LINK([#include <pthread.h>],
[pthread_t th; pthread_join(th, 0);
pthread_attr_init(0); pthread_cleanup_push(0, 0);
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
[done=yes])
if test "x$done" = xyes; then
AC_MSG_RESULT([yes])
PTHREAD_LIBS="-lpthread $PTHREAD_LIBS"
else
AC_MSG_RESULT([no])
fi
fi
#
# FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc
#
if test x"$done" = xno; then
AC_MSG_CHECKING([whether -lc_r fixes that])
LIBS="-lc_r $PTHREAD_LIBS $save_LIBS"
AC_TRY_LINK([#include <pthread.h>],
[pthread_t th; pthread_join(th, 0);
pthread_attr_init(0); pthread_cleanup_push(0, 0);
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
[done=yes])
if test "x$done" = xyes; then
AC_MSG_RESULT([yes])
PTHREAD_LIBS="-lc_r $PTHREAD_LIBS"
else
AC_MSG_RESULT([no])
fi
fi
if test x"$done" = xno; then
# OK, we have run out of ideas
AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries])
# so it's not safe to assume that we may use pthreads
acx_pthread_ok=no
fi
CFLAGS="$save_CFLAGS"
LIBS="$save_LIBS"
CC="$save_CC"
else
PTHREAD_CC="$CC"
fi
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(PTHREAD_CFLAGS)
AC_SUBST(PTHREAD_CC)
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$acx_pthread_ok" = xyes; then
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
:
else
acx_pthread_ok=no
$2
fi
AC_LANG_RESTORE
])dnl ACX_PTHREAD

36
m4/google_namespace.m4 Normal file
View file

@ -0,0 +1,36 @@
# Allow users to override the namespace we define our application's classes in
# Arg $1 is the default namespace to use if --enable-namespace isn't present.
# In general, $1 should be 'google', so we put all our exported symbols in a
# unique namespace that is not likely to conflict with anyone else. However,
# when it makes sense -- for instance, when publishing stl-like code -- you
# may want to go with a different default, like 'std'.
AC_DEFUN([AC_DEFINE_GOOGLE_NAMESPACE],
[google_namespace_default=[$1]
AC_ARG_ENABLE(namespace, [ --enable-namespace=FOO to define these Google
classes in the FOO namespace. --disable-namespace
to define them in the global namespace. Default
is to define them in namespace $1.],
[case "$enableval" in
yes) google_namespace="$google_namespace_default" ;;
no) google_namespace="" ;;
*) google_namespace="$enableval" ;;
esac],
[google_namespace="$google_namespace_default"])
if test -n "$google_namespace"; then
ac_google_namespace="$google_namespace"
ac_google_start_namespace="namespace $google_namespace {"
ac_google_end_namespace="}"
else
ac_google_namespace=""
ac_google_start_namespace=""
ac_google_end_namespace=""
fi
AC_DEFINE_UNQUOTED(GOOGLE_NAMESPACE, $ac_google_namespace,
Namespace for Google classes)
AC_DEFINE_UNQUOTED(_START_GOOGLE_NAMESPACE_, $ac_google_start_namespace,
Puts following code inside the Google namespace)
AC_DEFINE_UNQUOTED(_END_GOOGLE_NAMESPACE_, $ac_google_end_namespace,
Stops putting the code inside the Google namespace)
])

123
m4/ltsugar.m4 vendored Normal file
View file

@ -0,0 +1,123 @@
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59 which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])

98
m4/lt~obsolete.m4 vendored Normal file
View file

@ -0,0 +1,98 @@
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 5 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])

15
m4/namespaces.m4 Normal file
View file

@ -0,0 +1,15 @@
# Checks whether the compiler implements namespaces
AC_DEFUN([AC_CXX_NAMESPACES],
[AC_CACHE_CHECK(whether the compiler implements namespaces,
ac_cv_cxx_namespaces,
[AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_COMPILE([namespace Outer {
namespace Inner { int i = 0; }}],
[using namespace Outer::Inner; return i;],
ac_cv_cxx_namespaces=yes,
ac_cv_cxx_namespaces=no)
AC_LANG_RESTORE])
if test "$ac_cv_cxx_namespaces" = yes; then
AC_DEFINE(HAVE_NAMESPACES, 1, [define if the compiler implements namespaces])
fi])

71
m4/pc_from_ucontext.m4 Normal file
View file

@ -0,0 +1,71 @@
# We want to access the "PC" (Program Counter) register from a struct
# ucontext. Every system has its own way of doing that. We try all the
# possibilities we know about. Note REG_PC should come first (REG_RIP
# is also defined on solaris, but does the wrong thing).
# OpenBSD doesn't have ucontext.h, but we can get PC from ucontext_t
# by using signal.h.
# The first argument of AC_PC_FROM_UCONTEXT will be invoked when we
# cannot find a way to obtain PC from ucontext.
AC_DEFUN([AC_PC_FROM_UCONTEXT],
[AC_CHECK_HEADERS(ucontext.h)
AC_CHECK_HEADERS(sys/ucontext.h) # ucontext on OS X 10.6 (at least)
AC_MSG_CHECKING([how to access the program counter from a struct ucontext])
pc_fields=" uc_mcontext.gregs[[REG_PC]]" # Solaris x86 (32 + 64 bit)
pc_fields="$pc_fields uc_mcontext.gregs[[REG_EIP]]" # Linux (i386)
pc_fields="$pc_fields uc_mcontext.gregs[[REG_RIP]]" # Linux (x86_64)
pc_fields="$pc_fields uc_mcontext.sc_ip" # Linux (ia64)
pc_fields="$pc_fields uc_mcontext.uc_regs->gregs[[PT_NIP]]" # Linux (ppc)
pc_fields="$pc_fields uc_mcontext.gregs[[R15]]" # Linux (arm old [untested])
pc_fields="$pc_fields uc_mcontext.arm_pc" # Linux (arm new [untested])
pc_fields="$pc_fields uc_mcontext.mc_eip" # FreeBSD (i386)
pc_fields="$pc_fields uc_mcontext.mc_rip" # FreeBSD (x86_64 [untested])
pc_fields="$pc_fields uc_mcontext.__gregs[[_REG_EIP]]" # NetBSD (i386)
pc_fields="$pc_fields uc_mcontext.__gregs[[_REG_RIP]]" # NetBSD (x86_64)
pc_fields="$pc_fields uc_mcontext->ss.eip" # OS X (i386, <=10.4)
pc_fields="$pc_fields uc_mcontext->__ss.__eip" # OS X (i386, >=10.5)
pc_fields="$pc_fields uc_mcontext->ss.rip" # OS X (x86_64)
pc_fields="$pc_fields uc_mcontext->__ss.__rip" # OS X (>=10.5 [untested])
pc_fields="$pc_fields uc_mcontext->ss.srr0" # OS X (ppc, ppc64 [untested])
pc_fields="$pc_fields uc_mcontext->__ss.__srr0" # OS X (>=10.5 [untested])
pc_field_found=false
for pc_field in $pc_fields; do
if ! $pc_field_found; then
if test "x$ac_cv_header_sys_ucontext_h" = xyes; then
AC_TRY_COMPILE([#define _GNU_SOURCE 1
#include <sys/ucontext.h>],
[ucontext_t u; return u.$pc_field == 0;],
AC_DEFINE_UNQUOTED(PC_FROM_UCONTEXT, $pc_field,
How to access the PC from a struct ucontext)
AC_MSG_RESULT([$pc_field])
pc_field_found=true)
else
AC_TRY_COMPILE([#define _GNU_SOURCE 1
#include <ucontext.h>],
[ucontext_t u; return u.$pc_field == 0;],
AC_DEFINE_UNQUOTED(PC_FROM_UCONTEXT, $pc_field,
How to access the PC from a struct ucontext)
AC_MSG_RESULT([$pc_field])
pc_field_found=true)
fi
fi
done
if ! $pc_field_found; then
pc_fields=" sc_eip" # OpenBSD (i386)
pc_fields="$pc_fields sc_rip" # OpenBSD (x86_64)
for pc_field in $pc_fields; do
if ! $pc_field_found; then
AC_TRY_COMPILE([#include <signal.h>],
[ucontext_t u; return u.$pc_field == 0;],
AC_DEFINE_UNQUOTED(PC_FROM_UCONTEXT, $pc_field,
How to access the PC from a struct ucontext)
AC_MSG_RESULT([$pc_field])
pc_field_found=true)
fi
done
fi
if ! $pc_field_found; then
[$1]
fi])

25
m4/stl_namespace.m4 Normal file
View file

@ -0,0 +1,25 @@
# We check what namespace stl code like vector expects to be executed in
AC_DEFUN([AC_CXX_STL_NAMESPACE],
[AC_CACHE_CHECK(
what namespace STL code is in,
ac_cv_cxx_stl_namespace,
[AC_REQUIRE([AC_CXX_NAMESPACES])
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_COMPILE([#include <vector>],
[vector<int> t; return 0;],
ac_cv_cxx_stl_namespace=none)
AC_TRY_COMPILE([#include <vector>],
[std::vector<int> t; return 0;],
ac_cv_cxx_stl_namespace=std)
AC_LANG_RESTORE])
if test "$ac_cv_cxx_stl_namespace" = none; then
AC_DEFINE(STL_NAMESPACE,,
[the namespace where STL code like vector<> is defined])
fi
if test "$ac_cv_cxx_stl_namespace" = std; then
AC_DEFINE(STL_NAMESPACE,std,
[the namespace where STL code like vector<> is defined])
fi
])

15
m4/using_operator.m4 Normal file
View file

@ -0,0 +1,15 @@
AC_DEFUN([AC_CXX_USING_OPERATOR],
[AC_CACHE_CHECK(
whether compiler supports using ::operator<<,
ac_cv_cxx_using_operator,
[AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_COMPILE([#include <iostream>
std::ostream& operator<<(std::ostream&, struct s);],
[using ::operator<<; return 0;],
ac_cv_cxx_using_operator=1,
ac_cv_cxx_using_operator=0)
AC_LANG_RESTORE])
if test "$ac_cv_cxx_using_operator" = 1; then
AC_DEFINE(HAVE_USING_OPERATOR, 1, [define if the compiler supports using expression for operator])
fi])

73
packages/deb.sh Executable file
View file

@ -0,0 +1,73 @@
#!/bin/bash -e
# This takes one commandline argument, the name of the package. If no
# name is given, then we'll end up just using the name associated with
# an arbitrary .tar.gz file in the rootdir. That's fine: there's probably
# only one.
#
# Run this from the 'packages' directory, just under rootdir
## Set LIB to lib if exporting a library, empty-string else
LIB=
#LIB=lib
PACKAGE="$1"
VERSION="$2"
# We can only build Debian packages, if the Debian build tools are installed
if [ \! -x /usr/bin/debuild ]; then
echo "Cannot find /usr/bin/debuild. Not building Debian packages." 1>&2
exit 0
fi
# Double-check we're in the packages directory, just under rootdir
if [ \! -r ../Makefile -a \! -r ../INSTALL ]; then
echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2
echo "Also, you must run \"make dist\" before running this script." 1>&2
exit 0
fi
# Find the top directory for this package
topdir="${PWD%/*}"
# Find the tar archive built by "make dist"
archive="$PACKAGE-$VERSION"
if [ -z "${archive}" ]; then
echo "Cannot find ../$PACKAGE*.tar.gz. Run \"make dist\" first." 1>&2
exit 0
fi
# Create a pristine directory for building the Debian package files
trap 'rm -rf '`pwd`/tmp'; exit $?' EXIT SIGHUP SIGINT SIGTERM
rm -rf tmp
mkdir -p tmp
cd tmp
package="google-glog_$VERSION"
# Debian has very specific requirements about the naming of build
# directories, and tar archives. It also wants to write all generated
# packages to the parent of the source directory. We accommodate these
# requirements by building directly from the tar file.
ln -s "${topdir}/${archive}.tar.gz" "${LIB}${package}.orig.tar.gz"
tar zfx "${LIB}${package}.orig.tar.gz"
mv "${archive}" "${LIB}${package}"
cd "${LIB}${package}"
# This is one of those 'specific requirements': where the deb control files live
cp -a "packages/deb" "debian"
# Now, we can call Debian's standard build tool
debuild -uc -us
cd ../.. # get back to the original top-level dir
# We'll put the result in a subdirectory that's named after the OS version
# we've made this .deb file for.
destdir="debian-$(cat /etc/debian_version 2>/dev/null || echo UNKNOWN)"
rm -rf "$destdir"
mkdir -p "$destdir"
mv $(find tmp -mindepth 1 -maxdepth 1 -type f) "$destdir"
echo
echo "The Debian package files are located in $PWD/$destdir"

7
packages/deb/README Normal file
View file

@ -0,0 +1,7 @@
The list of files here isn't complete. For a step-by-step guide on
how to set this package up correctly, check out
http://www.debian.org/doc/maint-guide/
Most of the files that are in this directory are boilerplate.
However, you may need to change the list of binary-arch dependencies
in 'rules'.

71
packages/deb/changelog Normal file
View file

@ -0,0 +1,71 @@
google-glog (0.4.0-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Tue, 22 Jan 2019 21:00:26 +0900
google-glog (0.3.5-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Tue, 09 May 2017 16:22:12 +0900
google-glog (0.3.4-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Tue, 10 Mar 2015 12:02:20 +0900
google-glog (0.3.3-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Fri, 01 Feb 2012 14:54:14 +0900
google-glog (0.3.2-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Thu, 12 Jan 2012 17:36:14 +0900
google-glog (0.3.1-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Tue, 15 Jun 2010 13:50:47 +0900
google-glog (0.3-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Thu, 30 Jul 2009 21:31:35 +0900
google-glog (0.2.1-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Fri, 10 Apr 2009 15:24:17 +0900
google-glog (0.2-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Fri, 23 Jan 2009 03:14:29 +0900
google-glog (0.1.2-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Tue, 18 Nov 2008 20:37:00 +0900
google-glog (0.1.1-1) unstable; urgency=low
* New upstream release.
-- Google Inc. <opensource@google.com> Wed, 15 Oct 2008 20:38:19 +0900
google-glog (0.1-1) unstable; urgency=low
* Initial release.
-- Google Inc. <opensource@google.com> Sat, 10 May 2008 12:31:10 +0900

1
packages/deb/compat Normal file
View file

@ -0,0 +1 @@
4

23
packages/deb/control Normal file
View file

@ -0,0 +1,23 @@
Source: google-glog
Priority: optional
Maintainer: Google Inc. <opensource@google.com>
Build-Depends: debhelper (>= 4.0.0), binutils
Standards-Version: 3.6.1
Package: libgoogle-glog-dev
Section: libdevel
Architecture: any
Depends: libgoogle-glog0 (= ${Source-Version})
Description: a library that implements application-level logging.
This library provides logging APIs based on C++-style streams and
various helper macros. The devel package contains static and debug
libraries and header files for developing applications that use the
google-glog package.
Package: libgoogle-glog0
Section: libs
Architecture: any
Depends: ${shlibs:Depends}
Description: a library that implements application-level logging.
This library provides logging APIs based on C++-style streams and
various helper macros.

35
packages/deb/copyright Normal file
View file

@ -0,0 +1,35 @@
This package was debianized by Google Inc. <opensource@google.com> on
13 June 2008.
It was downloaded from https://github.com/google/glog
Upstream Author: opensource@google.com
Copyright (c) 2008, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

7
packages/deb/docs Normal file
View file

@ -0,0 +1,7 @@
AUTHORS
COPYING
ChangeLog
INSTALL
README.md
doc/designstyle.css
doc/glog.html

View file

@ -0,0 +1,4 @@
usr/lib
usr/lib/pkgconfig
usr/include
usr/include/glog

View file

@ -0,0 +1,10 @@
usr/include/glog/*
usr/lib/lib*.so
usr/lib/lib*.a
usr/lib/*.la
usr/lib/pkgconfig/*
debian/tmp/usr/include/glog/*
debian/tmp/usr/lib/lib*.so
debian/tmp/usr/lib/lib*.a
debian/tmp/usr/lib/*.la
debian/tmp/usr/lib/pkgconfig/*

View file

@ -0,0 +1 @@
usr/lib

View file

@ -0,0 +1,2 @@
usr/lib/lib*.so.*
debian/tmp/usr/lib/lib*.so.*

117
packages/deb/rules Executable file
View file

@ -0,0 +1,117 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
CFLAGS = -Wall -g
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS += -O0
else
CFLAGS += -O2
endif
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
INSTALL_PROGRAM += -s
endif
# shared library versions, option 1
#version=2.0.5
#major=2
# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so
version=`ls src/.libs/lib*.so.* | \
awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
major=`ls src/.libs/lib*.so.* | \
awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
config.status: configure
dh_testdir
# Add here commands to configure the package.
CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info
build: build-stamp
build-stamp: config.status
dh_testdir
# Add here commands to compile the package.
$(MAKE)
touch build-stamp
clean:
dh_testdir
dh_testroot
rm -f build-stamp
# Add here commands to clean up after the build process.
-$(MAKE) distclean
ifneq "$(wildcard /usr/share/misc/config.sub)" ""
cp -f /usr/share/misc/config.sub config.sub
endif
ifneq "$(wildcard /usr/share/misc/config.guess)" ""
cp -f /usr/share/misc/config.guess config.guess
endif
dh_clean
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/tmp
$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp
# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
dh_installchangelogs ChangeLog
dh_installdocs
dh_installexamples
dh_install --sourcedir=debian/tmp
# dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_python
dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install

75
packages/rpm.sh Executable file
View file

@ -0,0 +1,75 @@
#!/bin/sh -e
# Run this from the 'packages' directory, just under rootdir
# We can only build rpm packages, if the rpm build tools are installed
if [ \! -x /usr/bin/rpmbuild ]
then
echo "Cannot find /usr/bin/rpmbuild. Not building an rpm." 1>&2
exit 0
fi
# Check the commandline flags
PACKAGE="$1"
VERSION="$2"
fullname="${PACKAGE}-${VERSION}"
archive=../$fullname.tar.gz
if [ -z "$1" -o -z "$2" ]
then
echo "Usage: $0 <package name> <package version>" 1>&2
exit 0
fi
# Double-check we're in the packages directory, just under rootdir
if [ \! -r ../Makefile -a \! -r ../INSTALL ]
then
echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2
echo "Also, you must run \"make dist\" before running this script." 1>&2
exit 0
fi
if [ \! -r "$archive" ]
then
echo "Cannot find $archive. Run \"make dist\" first." 1>&2
exit 0
fi
# Create the directory where the input lives, and where the output should live
RPM_SOURCE_DIR="/tmp/rpmsource-$fullname"
RPM_BUILD_DIR="/tmp/rpmbuild-$fullname"
trap 'rm -rf $RPM_SOURCE_DIR $RPM_BUILD_DIR; exit $?' EXIT SIGHUP SIGINT SIGTERM
rm -rf "$RPM_SOURCE_DIR" "$RPM_BUILD_DIR"
mkdir "$RPM_SOURCE_DIR"
mkdir "$RPM_BUILD_DIR"
cp "$archive" "$RPM_SOURCE_DIR"/v"$VERSION".tar.gz
rpmbuild -bb rpm/rpm.spec \
--define "NAME $PACKAGE" \
--define "VERSION $VERSION" \
--define "_sourcedir $RPM_SOURCE_DIR" \
--define "_builddir $RPM_BUILD_DIR" \
--define "_rpmdir $RPM_SOURCE_DIR"
# We put the output in a directory based on what system we've built for
destdir=rpm-unknown
if [ -r /etc/issue ]
then
grep "Red Hat.*release 7" /etc/issue >/dev/null 2>&1 && destdir=rh7
grep "Red Hat.*release 8" /etc/issue >/dev/null 2>&1 && destdir=rh8
grep "Red Hat.*release 9" /etc/issue >/dev/null 2>&1 && destdir=rh9
if grep Fedora /etc/issue >/dev/null; then
destdir=fc`grep Fedora /etc/issue | cut -d' ' -f 4`;
fi
fi
rm -rf "$destdir"
mkdir -p "$destdir"
# We want to get not only the main package but devel etc, hence the middle *
mv "$RPM_SOURCE_DIR"/*/"${PACKAGE}"-*"${VERSION}"*.rpm "$destdir"
echo
echo "The rpm package file(s) are located in $PWD/$destdir"

72
packages/rpm/rpm.spec Normal file
View file

@ -0,0 +1,72 @@
%define RELEASE 1
%define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
%define prefix /usr
Name: %NAME
Summary: A C++ application logging library
Version: %VERSION
Release: %rel
Group: Development/Libraries
URL: http://github.com/google/glog
License: BSD
Vendor: Google
Packager: Google Inc. <opensource@google.com>
Source: https://github.com/google/glog/archive/v%{VERSION}.tar.gz
Distribution: Redhat 7 and above.
Buildroot: %{_tmppath}/%{name}-root
Prefix: %prefix
%description
The %name package contains a library that implements application-level
logging. This library provides logging APIs based on C++-style
streams and various helper macros.
%package devel
Summary: A C++ application logging library
Group: Development/Libraries
Requires: %{NAME} = %{VERSION}
%description devel
The %name-devel package contains static and debug libraries and header
files for developing applications that use the %name package.
%changelog
* Wed Mar 26 2008 <opensource@google.com>
- First draft
%prep
%setup
%build
./configure
make prefix=%prefix
%install
rm -rf $RPM_BUILD_ROOT
make prefix=$RPM_BUILD_ROOT%{prefix} install
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
## Mark all installed files within /usr/share/doc/{package name} as
## documentation. This depends on the following two lines appearing in
## Makefile.am:
## docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
## dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL README.md
%docdir %{prefix}/share/doc/%{NAME}-%{VERSION}
%{prefix}/share/doc/%{NAME}-%{VERSION}/*
%{prefix}/lib/libglog.so.0
%{prefix}/lib/libglog.so.0.0.0
%files devel
%defattr(-,root,root)
%{prefix}/include/glog
%{prefix}/lib/libglog.a
%{prefix}/lib/libglog.la
%{prefix}/lib/libglog.so
%{prefix}/lib/pkgconfig/libglog.pc

133
src/base/commandlineflags.h Normal file
View file

@ -0,0 +1,133 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// This file is a compatibility layer that defines Google's version of
// command line flags that are used for configuration.
//
// We put flags into their own namespace. It is purposefully
// named in an opaque way that people should have trouble typing
// directly. The idea is that DEFINE puts the flag in the weird
// namespace, and DECLARE imports the flag from there into the
// current namespace. The net result is to force people to use
// DECLARE to get access to a flag, rather than saying
// extern bool FLAGS_logtostderr;
// or some such instead. We want this so we can put extra
// functionality (like sanity-checking) in DECLARE if we want,
// and make sure it is picked up everywhere.
//
// We also put the type of the variable in the namespace, so that
// people can't DECLARE_int32 something that they DEFINE_bool'd
// elsewhere.
#ifndef BASE_COMMANDLINEFLAGS_H__
#define BASE_COMMANDLINEFLAGS_H__
#include "config.h"
#include <string>
#include <string.h> // for memchr
#include <stdlib.h> // for getenv
#ifdef HAVE_LIB_GFLAGS
#include <gflags/gflags.h>
#else
#include "glog/logging.h"
#define DECLARE_VARIABLE(type, shorttype, name, tn) \
namespace fL##shorttype { \
extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
} \
using fL##shorttype::FLAGS_##name
#define DEFINE_VARIABLE(type, shorttype, name, value, meaning, tn) \
namespace fL##shorttype { \
GOOGLE_GLOG_DLL_DECL type FLAGS_##name(value); \
char FLAGS_no##name; \
} \
using fL##shorttype::FLAGS_##name
// bool specialization
#define DECLARE_bool(name) \
DECLARE_VARIABLE(bool, B, name, bool)
#define DEFINE_bool(name, value, meaning) \
DEFINE_VARIABLE(bool, B, name, value, meaning, bool)
// int32 specialization
#define DECLARE_int32(name) \
DECLARE_VARIABLE(GOOGLE_NAMESPACE::int32, I, name, int32)
#define DEFINE_int32(name, value, meaning) \
DEFINE_VARIABLE(GOOGLE_NAMESPACE::int32, I, name, value, meaning, int32)
// Special case for string, because we have to specify the namespace
// std::string, which doesn't play nicely with our FLAG__namespace hackery.
#define DECLARE_string(name) \
namespace fLS { \
extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \
} \
using fLS::FLAGS_##name
#define DEFINE_string(name, value, meaning) \
namespace fLS { \
std::string FLAGS_##name##_buf(value); \
GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name = FLAGS_##name##_buf; \
char FLAGS_no##name; \
} \
using fLS::FLAGS_##name
#endif // HAVE_LIB_GFLAGS
// Define GLOG_DEFINE_* using DEFINE_* . By using these macros, we
// have GLOG_* environ variables even if we have gflags installed.
//
// If both an environment variable and a flag are specified, the value
// specified by a flag wins. E.g., if GLOG_v=0 and --v=1, the
// verbosity will be 1, not 0.
#define GLOG_DEFINE_bool(name, value, meaning) \
DEFINE_bool(name, EnvToBool("GLOG_" #name, value), meaning)
#define GLOG_DEFINE_int32(name, value, meaning) \
DEFINE_int32(name, EnvToInt("GLOG_" #name, value), meaning)
#define GLOG_DEFINE_string(name, value, meaning) \
DEFINE_string(name, EnvToString("GLOG_" #name, value), meaning)
// These macros (could be functions, but I don't want to bother with a .cc
// file), make it easier to initialize flags from the environment.
#define EnvToString(envname, dflt) \
(!getenv(envname) ? (dflt) : getenv(envname))
#define EnvToBool(envname, dflt) \
(!getenv(envname) ? (dflt) : memchr("tTyY1\0", getenv(envname)[0], 6) != NULL)
#define EnvToInt(envname, dflt) \
(!getenv(envname) ? (dflt) : strtol(getenv(envname), NULL, 10))
#endif // BASE_COMMANDLINEFLAGS_H__

51
src/base/googleinit.h Normal file
View file

@ -0,0 +1,51 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// Author: Jacob Hoffman-Andrews
#ifndef _GOOGLEINIT_H
#define _GOOGLEINIT_H
class GoogleInitializer {
public:
typedef void (*void_function)(void);
GoogleInitializer(const char*, void_function f) {
f();
}
};
#define REGISTER_MODULE_INITIALIZER(name, body) \
namespace { \
static void google_init_module_##name () { body; } \
GoogleInitializer google_initializer_module_##name(#name, \
google_init_module_##name); \
}
#endif /* _GOOGLEINIT_H */

333
src/base/mutex.h Normal file
View file

@ -0,0 +1,333 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
// Author: Craig Silverstein.
//
// A simple mutex wrapper, supporting locks and read-write locks.
// You should assume the locks are *not* re-entrant.
//
// To use: you should define the following macros in your configure.ac:
// ACX_PTHREAD
// AC_RWLOCK
// The latter is defined in ../autoconf.
//
// This class is meant to be internal-only and should be wrapped by an
// internal namespace. Before you use this module, please give the
// name of your internal namespace for this module. Or, if you want
// to expose it, you'll want to move it to the Google namespace. We
// cannot put this class in global namespace because there can be some
// problems when we have multiple versions of Mutex in each shared object.
//
// NOTE: by default, we have #ifdef'ed out the TryLock() method.
// This is for two reasons:
// 1) TryLock() under Windows is a bit annoying (it requires a
// #define to be defined very early).
// 2) TryLock() is broken for NO_THREADS mode, at least in NDEBUG
// mode.
// If you need TryLock(), and either these two caveats are not a
// problem for you, or you're willing to work around them, then
// feel free to #define GMUTEX_TRYLOCK, or to remove the #ifdefs
// in the code below.
//
// CYGWIN NOTE: Cygwin support for rwlock seems to be buggy:
// http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html
// Because of that, we might as well use windows locks for
// cygwin. They seem to be more reliable than the cygwin pthreads layer.
//
// TRICKY IMPLEMENTATION NOTE:
// This class is designed to be safe to use during
// dynamic-initialization -- that is, by global constructors that are
// run before main() starts. The issue in this case is that
// dynamic-initialization happens in an unpredictable order, and it
// could be that someone else's dynamic initializer could call a
// function that tries to acquire this mutex -- but that all happens
// before this mutex's constructor has run. (This can happen even if
// the mutex and the function that uses the mutex are in the same .cc
// file.) Basically, because Mutex does non-trivial work in its
// constructor, it's not, in the naive implementation, safe to use
// before dynamic initialization has run on it.
//
// The solution used here is to pair the actual mutex primitive with a
// bool that is set to true when the mutex is dynamically initialized.
// (Before that it's false.) Then we modify all mutex routines to
// look at the bool, and not try to lock/unlock until the bool makes
// it to true (which happens after the Mutex constructor has run.)
//
// This works because before main() starts -- particularly, during
// dynamic initialization -- there are no threads, so a) it's ok that
// the mutex operations are a no-op, since we don't need locking then
// anyway; and b) we can be quite confident our bool won't change
// state between a call to Lock() and a call to Unlock() (that would
// require a global constructor in one translation unit to call Lock()
// and another global constructor in another translation unit to call
// Unlock() later, which is pretty perverse).
//
// That said, it's tricky, and can conceivably fail; it's safest to
// avoid trying to acquire a mutex in a global constructor, if you
// can. One way it can fail is that a really smart compiler might
// initialize the bool to true at static-initialization time (too
// early) rather than at dynamic-initialization time. To discourage
// that, we set is_safe_ to true in code (not the constructor
// colon-initializer) and set it to true via a function that always
// evaluates to true, but that the compiler can't know always
// evaluates to true. This should be good enough.
#ifndef GOOGLE_MUTEX_H_
#define GOOGLE_MUTEX_H_
#include "config.h" // to figure out pthreads support
#if defined(NO_THREADS)
typedef int MutexType; // to keep a lock-count
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
# endif
# ifdef GMUTEX_TRYLOCK
// We need Windows NT or later for TryEnterCriticalSection(). If you
// don't need that functionality, you can remove these _WIN32_WINNT
// lines, and change TryLock() to assert(0) or something.
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0400
# endif
# endif
// To avoid macro definition of ERROR.
# ifndef NOGDI
# define NOGDI
# endif
// To avoid macro definition of min/max.
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <windows.h>
typedef CRITICAL_SECTION MutexType;
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
// Needed for pthread_rwlock_*. If it causes problems, you could take it
// out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it
// *does* cause problems for FreeBSD, or MacOSX, but isn't needed
// for locking there.)
# ifdef __linux__
# ifndef _XOPEN_SOURCE // Some other header might have already set it for us.
# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
# endif
# endif
# include <pthread.h>
typedef pthread_rwlock_t MutexType;
#elif defined(HAVE_PTHREAD)
# include <pthread.h>
typedef pthread_mutex_t MutexType;
#else
# error Need to implement mutex.h for your architecture, or #define NO_THREADS
#endif
// We need to include these header files after defining _XOPEN_SOURCE
// as they may define the _XOPEN_SOURCE macro.
#include <assert.h>
#include <stdlib.h> // for abort()
#define MUTEX_NAMESPACE glog_internal_namespace_
namespace MUTEX_NAMESPACE {
class Mutex {
public:
// Create a Mutex that is not held by anybody. This constructor is
// typically used for Mutexes allocated on the heap or the stack.
// See below for a recommendation for constructing global Mutex
// objects.
inline Mutex();
// Destructor
inline ~Mutex();
inline void Lock(); // Block if needed until free then acquire exclusively
inline void Unlock(); // Release a lock acquired via Lock()
#ifdef GMUTEX_TRYLOCK
inline bool TryLock(); // If free, Lock() and return true, else return false
#endif
// Note that on systems that don't support read-write locks, these may
// be implemented as synonyms to Lock() and Unlock(). So you can use
// these for efficiency, but don't use them anyplace where being able
// to do shared reads is necessary to avoid deadlock.
inline void ReaderLock(); // Block until free or shared then acquire a share
inline void ReaderUnlock(); // Release a read share of this Mutex
inline void WriterLock() { Lock(); } // Acquire an exclusive lock
inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
// TODO(hamaji): Do nothing, implement correctly.
inline void AssertHeld() {}
private:
MutexType mutex_;
// We want to make sure that the compiler sets is_safe_ to true only
// when we tell it to, and never makes assumptions is_safe_ is
// always true. volatile is the most reliable way to do that.
volatile bool is_safe_;
inline void SetIsSafe() { is_safe_ = true; }
// Catch the error of writing Mutex when intending MutexLock.
Mutex(Mutex* /*ignored*/) {}
// Disallow "evil" constructors
Mutex(const Mutex&);
void operator=(const Mutex&);
};
// Now the implementation of Mutex for various systems
#if defined(NO_THREADS)
// When we don't have threads, we can be either reading or writing,
// but not both. We can have lots of readers at once (in no-threads
// mode, that's most likely to happen in recursive function calls),
// but only one writer. We represent this by having mutex_ be -1 when
// writing and a number > 0 when reading (and 0 when no lock is held).
//
// In debug mode, we assert these invariants, while in non-debug mode
// we do nothing, for efficiency. That's why everything is in an
// assert.
Mutex::Mutex() : mutex_(0) { }
Mutex::~Mutex() { assert(mutex_ == 0); }
void Mutex::Lock() { assert(--mutex_ == -1); }
void Mutex::Unlock() { assert(mutex_++ == -1); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; }
#endif
void Mutex::ReaderLock() { assert(++mutex_ > 0); }
void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
Mutex::Mutex() { InitializeCriticalSection(&mutex_); SetIsSafe(); }
Mutex::~Mutex() { DeleteCriticalSection(&mutex_); }
void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); }
void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
TryEnterCriticalSection(&mutex_) != 0 : true; }
#endif
void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
void Mutex::ReaderUnlock() { Unlock(); }
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
Mutex::Mutex() {
SetIsSafe();
if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
}
Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
pthread_rwlock_trywrlock(&mutex_) == 0 :
true; }
#endif
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); }
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#undef SAFE_PTHREAD
#elif defined(HAVE_PTHREAD)
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
Mutex::Mutex() {
SetIsSafe();
if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
}
Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
pthread_mutex_trylock(&mutex_) == 0 : true; }
#endif
void Mutex::ReaderLock() { Lock(); }
void Mutex::ReaderUnlock() { Unlock(); }
#undef SAFE_PTHREAD
#endif
// --------------------------------------------------------------------------
// Some helper classes
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
class MutexLock {
public:
explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
~MutexLock() { mu_->Unlock(); }
private:
Mutex * const mu_;
// Disallow "evil" constructors
MutexLock(const MutexLock&);
void operator=(const MutexLock&);
};
// ReaderMutexLock and WriterMutexLock do the same, for rwlocks
class ReaderMutexLock {
public:
explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
~ReaderMutexLock() { mu_->ReaderUnlock(); }
private:
Mutex * const mu_;
// Disallow "evil" constructors
ReaderMutexLock(const ReaderMutexLock&);
void operator=(const ReaderMutexLock&);
};
class WriterMutexLock {
public:
explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
~WriterMutexLock() { mu_->WriterUnlock(); }
private:
Mutex * const mu_;
// Disallow "evil" constructors
WriterMutexLock(const WriterMutexLock&);
void operator=(const WriterMutexLock&);
};
// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
} // namespace MUTEX_NAMESPACE
using namespace MUTEX_NAMESPACE;
#undef MUTEX_NAMESPACE
#endif /* #define GOOGLE_MUTEX_H__ */

219
src/config.h.cmake.in Normal file
View file

@ -0,0 +1,219 @@
#ifndef GLOG_CONFIG_H
#define GLOG_CONFIG_H
/* define if glog doesn't use RTTI */
#cmakedefine DISABLE_RTTI
/* Namespace for Google classes */
#cmakedefine GOOGLE_NAMESPACE ${GOOGLE_NAMESPACE}
/* Define if you have the `dladdr' function */
#cmakedefine HAVE_DLADDR
/* Define if you have the `snprintf' function */
#cmakedefine HAVE_SNPRINTF
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H
/* Define to 1 if you have the <execinfo.h> header file. */
#cmakedefine HAVE_EXECINFO_H
/* Define if you have the `fcntl' function */
#cmakedefine HAVE_FCNTL
/* Define to 1 if you have the <glob.h> header file. */
#cmakedefine HAVE_GLOB_H
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H}
/* Define to 1 if you have the `pthread' library (-lpthread). */
#cmakedefine HAVE_LIBPTHREAD
/* Define to 1 if you have the <libunwind.h> header file. */
#cmakedefine HAVE_LIBUNWIND_H
/* define if you have google gflags library */
#cmakedefine HAVE_LIB_GFLAGS
/* define if you have google gmock library */
#cmakedefine HAVE_LIB_GMOCK
/* define if you have google gtest library */
#cmakedefine HAVE_LIB_GTEST
/* define if you have libunwind */
#cmakedefine HAVE_LIB_UNWIND
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H
/* define to disable multithreading support. */
#cmakedefine NO_THREADS
/* define if the compiler implements namespaces */
#cmakedefine HAVE_NAMESPACES
/* Define if you have the 'pread' function */
#cmakedefine HAVE_PREAD
/* Define if you have POSIX threads libraries and header files. */
#cmakedefine HAVE_PTHREAD
/* Define to 1 if you have the <pwd.h> header file. */
#cmakedefine HAVE_PWD_H
/* Define if you have the 'pwrite' function */
#cmakedefine HAVE_PWRITE
/* define if the compiler implements pthread_rwlock_* */
#cmakedefine HAVE_RWLOCK
/* Define if you have the 'sigaction' function */
#cmakedefine HAVE_SIGACTION
/* Define if you have the `sigaltstack' function */
#cmakedefine HAVE_SIGALTSTACK
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H}
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H
/* Define to 1 if you have the <syscall.h> header file. */
#cmakedefine HAVE_SYSCALL_H
/* Define to 1 if you have the <syslog.h> header file. */
#cmakedefine HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/syscall.h> header file. */
#cmakedefine HAVE_SYS_SYSCALL_H
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H}
/* Define to 1 if you have the <sys/ucontext.h> header file. */
#cmakedefine HAVE_SYS_UCONTEXT_H
/* Define to 1 if you have the <sys/utsname.h> header file. */
#cmakedefine HAVE_SYS_UTSNAME_H
/* Define to 1 if you have the <sys/wait.h> header file. */
#cmakedefine HAVE_SYS_WAIT_H
/* Define to 1 if you have the <ucontext.h> header file. */
#cmakedefine HAVE_UCONTEXT_H
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H}
/* Define to 1 if you have the <unwind.h> header file. */
#cmakedefine HAVE_UNWIND_H ${HAVE_UNWIND_H}
/* define if the compiler supports using expression for operator */
#cmakedefine HAVE_USING_OPERATOR
/* define if your compiler has __attribute__ */
#cmakedefine HAVE___ATTRIBUTE__
/* define if your compiler has __builtin_expect */
#cmakedefine HAVE___BUILTIN_EXPECT ${HAVE___BUILTIN_EXPECT}
/* define if your compiler has __sync_val_compare_and_swap */
#cmakedefine HAVE___SYNC_VAL_COMPARE_AND_SWAP
/* define if symbolize support is available */
#cmakedefine HAVE_SYMBOLIZE
/* define if localtime_r is available in time.h */
#cmakedefine HAVE_LOCALTIME_R
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#cmakedefine LT_OBJDIR
/* Name of package */
#cmakedefine PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#cmakedefine PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#cmakedefine PACKAGE_NAME
/* Define to the full name and version of this package. */
#cmakedefine PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#cmakedefine PACKAGE_TARNAME
/* Define to the home page for this package. */
#cmakedefine PACKAGE_URL
/* Define to the version of this package. */
#cmakedefine PACKAGE_VERSION
/* How to access the PC from a struct ucontext */
#cmakedefine PC_FROM_UCONTEXT
/* define if we should print file offsets in traces instead of symbolizing. */
#cmakedefine PRINT_UNSYMBOLIZED_STACK_TRACES
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#cmakedefine PTHREAD_CREATE_JOINABLE
/* The size of `void *', as computed by sizeof. */
#cmakedefine SIZEOF_VOID_P ${SIZEOF_VOID_P}
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS
/* the namespace where STL code like vector<> is defined */
#cmakedefine STL_NAMESPACE ${STL_NAMESPACE}
/* location of source code */
#cmakedefine TEST_SRC_DIR ${TEST_SRC_DIR}
/* Define to necessary thread-local storage attribute. */
#cmakedefine GLOG_THREAD_LOCAL_STORAGE ${GLOG_THREAD_LOCAL_STORAGE}
/* Check whether aligned_storage and alignof present */
#cmakedefine HAVE_ALIGNED_STORAGE ${HAVE_ALIGNED_STORAGE}
/* Version number of package */
#cmakedefine VERSION
#ifdef GLOG_BAZEL_BUILD
/* TODO(rodrigoq): remove this workaround once bazel#3979 is resolved:
* https://github.com/bazelbuild/bazel/issues/3979 */
#define _START_GOOGLE_NAMESPACE_ namespace GOOGLE_NAMESPACE {
#define _END_GOOGLE_NAMESPACE_ }
#else
/* Stops putting the code inside the Google namespace */
#cmakedefine _END_GOOGLE_NAMESPACE_ ${_END_GOOGLE_NAMESPACE_}
/* Puts following code inside the Google namespace */
#cmakedefine _START_GOOGLE_NAMESPACE_ ${_START_GOOGLE_NAMESPACE_}
#endif
#endif // GLOG_CONFIG_H

View file

@ -0,0 +1,66 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// All Rights Reserved.
//
// Author: Craig Silverstein
// Copied from google-perftools and modified by Shinichiro Hamaji
//
// This file is needed for windows -- unittests are not part of the
// glog dll, but still want to include config.h just like the
// dll does, so they can use internal tools and APIs for testing.
//
// The problem is that config.h declares GOOGLE_GLOG_DLL_DECL to be
// for exporting symbols, but the unittest needs to *import* symbols
// (since it's not the dll).
//
// The solution is to have this file, which is just like config.h but
// sets GOOGLE_GLOG_DLL_DECL to do a dllimport instead of a dllexport.
//
// The reason we need this extra GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS
// variable is in case people want to set GOOGLE_GLOG_DLL_DECL explicitly
// to something other than __declspec(dllexport). In that case, they
// may want to use something other than __declspec(dllimport) for the
// unittest case. For that, we allow folks to define both
// GOOGLE_GLOG_DLL_DECL and GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS explicitly.
//
// NOTE: This file is equivalent to config.h on non-windows systems,
// which never defined GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS and always
// define GOOGLE_GLOG_DLL_DECL to the empty string.
#include "config.h"
#undef GOOGLE_GLOG_DLL_DECL
#ifdef GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS
# define GOOGLE_GLOG_DLL_DECL GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS
#else
// if DLL_DECL_FOR_UNITTESTS isn't defined, use ""
# define GOOGLE_GLOG_DLL_DECL
#endif

1356
src/demangle.cc Normal file

File diff suppressed because it is too large Load diff

85
src/demangle.h Normal file
View file

@ -0,0 +1,85 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Satoru Takabayashi
//
// An async-signal-safe and thread-safe demangler for Itanium C++ ABI
// (aka G++ V3 ABI).
// The demangler is implemented to be used in async signal handlers to
// symbolize stack traces. We cannot use libstdc++'s
// abi::__cxa_demangle() in such signal handlers since it's not async
// signal safe (it uses malloc() internally).
//
// Note that this demangler doesn't support full demangling. More
// specifically, it doesn't print types of function parameters and
// types of template arguments. It just skips them. However, it's
// still very useful to extract basic information such as class,
// function, constructor, destructor, and operator names.
//
// See the implementation note in demangle.cc if you are interested.
//
// Example:
//
// | Mangled Name | The Demangler | abi::__cxa_demangle()
// |---------------|---------------|-----------------------
// | _Z1fv | f() | f()
// | _Z1fi | f() | f(int)
// | _Z3foo3bar | foo() | foo(bar)
// | _Z1fIiEvi | f<>() | void f<int>(int)
// | _ZN1N1fE | N::f | N::f
// | _ZN3Foo3BarEv | Foo::Bar() | Foo::Bar()
// | _Zrm1XS_" | operator%() | operator%(X, X)
// | _ZN3FooC1Ev | Foo::Foo() | Foo::Foo()
// | _Z1fSs | f() | f(std::basic_string<char,
// | | | std::char_traits<char>,
// | | | std::allocator<char> >)
//
// See the unit test for more examples.
//
// Note: we might want to write demanglers for ABIs other than Itanium
// C++ ABI in the future.
//
#ifndef BASE_DEMANGLE_H_
#define BASE_DEMANGLE_H_
#include "config.h"
#include "glog/logging.h"
_START_GOOGLE_NAMESPACE_
// Demangle "mangled". On success, return true and write the
// demangled symbol name to "out". Otherwise, return false.
// "out" is modified even if demangling is unsuccessful.
bool GOOGLE_GLOG_DLL_DECL Demangle(const char *mangled, char *out, int out_size);
_END_GOOGLE_NAMESPACE_
#endif // BASE_DEMANGLE_H_

168
src/demangle_unittest.cc Normal file
View file

@ -0,0 +1,168 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Satoru Takabayashi
//
// Unit tests for functions in demangle.c.
#include "utilities.h"
#include <iostream>
#include <fstream>
#include <string>
#include "glog/logging.h"
#include "demangle.h"
#include "googletest.h"
#include "config.h"
#ifdef HAVE_LIB_GFLAGS
#include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE;
#endif
GLOG_DEFINE_bool(demangle_filter, false,
"Run demangle_unittest in filter mode");
using namespace std;
using namespace GOOGLE_NAMESPACE;
// A wrapper function for Demangle() to make the unit test simple.
static const char *DemangleIt(const char * const mangled) {
static char demangled[4096];
if (Demangle(mangled, demangled, sizeof(demangled))) {
return demangled;
} else {
return mangled;
}
}
#if defined(OS_WINDOWS)
TEST(Demangle, Windows) {
EXPECT_STREQ(
"public: static void __cdecl Foo::func(int)",
DemangleIt("?func@Foo@@SAXH@Z"));
EXPECT_STREQ(
"public: static void __cdecl Foo::func(int)",
DemangleIt("@ILT+1105(?func@Foo@@SAXH@Z)"));
EXPECT_STREQ(
"int __cdecl foobarArray(int * const)",
DemangleIt("?foobarArray@@YAHQAH@Z"));
}
#else
// Test corner cases of bounary conditions.
TEST(Demangle, CornerCases) {
const size_t size = 10;
char tmp[size] = { 0 };
const char *demangled = "foobar()";
const char *mangled = "_Z6foobarv";
EXPECT_TRUE(Demangle(mangled, tmp, sizeof(tmp)));
// sizeof("foobar()") == size - 1
EXPECT_STREQ(demangled, tmp);
EXPECT_TRUE(Demangle(mangled, tmp, size - 1));
EXPECT_STREQ(demangled, tmp);
EXPECT_FALSE(Demangle(mangled, tmp, size - 2)); // Not enough.
EXPECT_FALSE(Demangle(mangled, tmp, 1));
EXPECT_FALSE(Demangle(mangled, tmp, 0));
EXPECT_FALSE(Demangle(mangled, NULL, 0)); // Should not cause SEGV.
}
// Test handling of functions suffixed with .clone.N, which is used by GCC
// 4.5.x, and .constprop.N and .isra.N, which are used by GCC 4.6.x. These
// suffixes are used to indicate functions which have been cloned during
// optimization. We ignore these suffixes.
TEST(Demangle, Clones) {
char tmp[20];
EXPECT_TRUE(Demangle("_ZL3Foov", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.clone.3", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.constprop.80", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.isra.18", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.18", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
// Invalid (truncated), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp)));
// Invalid (.clone. not followed by number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp)));
// Invalid (.clone. followed by non-number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.clone.foo", tmp, sizeof(tmp)));
// Invalid (.constprop. not followed by number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp)));
}
TEST(Demangle, FromFile) {
string test_file = FLAGS_test_srcdir + "/src/demangle_unittest.txt";
ifstream f(test_file.c_str()); // The file should exist.
EXPECT_FALSE(f.fail());
string line;
while (getline(f, line)) {
// Lines start with '#' are considered as comments.
if (line.empty() || line[0] == '#') {
continue;
}
// Each line should contain a mangled name and a demangled name
// separated by '\t'. Example: "_Z3foo\tfoo"
string::size_type tab_pos = line.find('\t');
EXPECT_NE(string::npos, tab_pos);
string mangled = line.substr(0, tab_pos);
string demangled = line.substr(tab_pos + 1);
EXPECT_EQ(demangled, DemangleIt(mangled.c_str()));
}
}
#endif
int main(int argc, char **argv) {
#ifdef HAVE_LIB_GFLAGS
ParseCommandLineFlags(&argc, &argv, true);
#endif
InitGoogleTest(&argc, argv);
FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]);
if (FLAGS_demangle_filter) {
// Read from cin and write to cout.
string line;
while (getline(cin, line, '\n')) {
cout << DemangleIt(line.c_str()) << endl;
}
return 0;
} else if (argc > 1) {
cout << DemangleIt(argv[1]) << endl;
return 0;
} else {
return RUN_ALL_TESTS();
}
}

95
src/demangle_unittest.sh Executable file
View file

@ -0,0 +1,95 @@
#! /bin/sh
#
# Copyright (c) 2006, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Author: Satoru Takabayashi
#
# Unit tests for demangle.c with a real binary.
set -e
die () {
echo $1
exit 1
}
BINDIR=".libs"
LIBGLOG="$BINDIR/libglog.so"
DEMANGLER="$BINDIR/demangle_unittest"
if test -e "$DEMANGLER"; then
# We need shared object.
export LD_LIBRARY_PATH=$BINDIR
export DYLD_LIBRARY_PATH=$BINDIR
else
# For windows
DEMANGLER="./demangle_unittest.exe"
if ! test -e "$DEMANGLER"; then
echo "We coundn't find demangle_unittest binary."
exit 1
fi
fi
# Extract C++ mangled symbols from libbase.so.
NM_OUTPUT="demangle.nm"
nm "$LIBGLOG" | perl -nle 'print $1 if /\s(_Z\S+$)/' > "$NM_OUTPUT"
# Check if mangled symbols exist. If there are none, we quit.
# The binary is more likely compiled with GCC 2.95 or something old.
if ! grep --quiet '^_Z' "$NM_OUTPUT"; then
echo "PASS"
exit 0
fi
# Demangle the symbols using our demangler.
DM_OUTPUT="demangle.dm"
GLOG_demangle_filter=1 "$DEMANGLER" --demangle_filter < "$NM_OUTPUT" > "$DM_OUTPUT"
# Calculate the numbers of lines.
NM_LINES=`wc -l "$NM_OUTPUT" | awk '{ print $1 }'`
DM_LINES=`wc -l "$DM_OUTPUT" | awk '{ print $1 }'`
# Compare the numbers of lines. They must be the same.
if test "$NM_LINES" != "$DM_LINES"; then
die "$NM_OUTPUT and $DM_OUTPUT don't have the same numbers of lines"
fi
# Check if mangled symbols exist. They must not exist.
if grep --quiet '^_Z' "$DM_OUTPUT"; then
MANGLED=`grep '^_Z' "$DM_OUTPUT" | wc -l | awk '{ print \$1 }'`
echo "Mangled symbols ($MANGLED out of $NM_LINES) found in $DM_OUTPUT:"
grep '^_Z' "$DM_OUTPUT"
die "Mangled symbols ($MANGLED out of $NM_LINES) found in $DM_OUTPUT"
fi
# All C++ symbols are demangled successfully.
echo "PASS"
exit 0

145
src/demangle_unittest.txt Normal file
View file

@ -0,0 +1,145 @@
# Test caces for demangle_unittest. Each line consists of a
# tab-separated pair of mangled and demangled symbol names.
# Constructors and destructors.
_ZN3FooC1Ev Foo::Foo()
_ZN3FooD1Ev Foo::~Foo()
_ZNSoD0Ev std::ostream::~ostream()
# G++ extensions.
_ZTCN10LogMessage9LogStreamE0_So LogMessage::LogStream
_ZTv0_n12_N10LogMessage9LogStreamD0Ev LogMessage::LogStream::~LogStream()
_ZThn4_N7icu_3_410UnicodeSetD0Ev icu_3_4::UnicodeSet::~UnicodeSet()
# A bug in g++'s C++ ABI version 2 (-fabi-version=2).
_ZN7NSSInfoI5groupjjXadL_Z10getgrgid_rEELZ19nss_getgrgid_r_nameEEC1Ei NSSInfo<>::NSSInfo()
# C linkage symbol names. Should keep them untouched.
main main
Demangle Demangle
_ZERO _ZERO
# Cast operator.
_Zcviv operator int()
_ZN3foocviEv foo::operator int()
# Versioned symbols.
_Z3Foo@GLIBCXX_3.4 Foo@GLIBCXX_3.4
_Z3Foo@@GLIBCXX_3.4 Foo@@GLIBCXX_3.4
# Abbreviations.
_ZNSaE std::allocator
_ZNSbE std::basic_string
_ZNSdE std::iostream
_ZNSiE std::istream
_ZNSoE std::ostream
_ZNSsE std::string
# Substitutions. We just replace them with ?.
_ZN3fooS_E foo::?
_ZN3foo3barS0_E foo::bar::?
_ZNcvT_IiEEv operator ?<>()
# "<< <" case.
_ZlsI3fooE operator<< <>
# ABI tags.
_Z1AB3barB3foo A
_ZN3fooL3barB5cxx11E foo::bar
# Random things we found interesting.
_ZN3FooISt6vectorISsSaISsEEEclEv Foo<>::operator()()
_ZTI9Callback1IiE Callback1<>
_ZN7icu_3_47UMemorynwEj icu_3_4::UMemory::operator new()
_ZNSt6vectorIbE9push_backE std::vector<>::push_back
_ZNSt6vectorIbSaIbEE9push_backEb std::vector<>::push_back()
_ZlsRSoRK15PRIVATE_Counter operator<<()
_ZSt6fill_nIPPN9__gnu_cxx15_Hashtable_nodeISt4pairIKPKcjEEEjS8_ET_SA_T0_RKT1_ std::fill_n<>()
_ZZ3FoovE3Bar Foo()::Bar
_ZGVZ7UpTimervE8up_timer UpTimer()::up_timer
# Test cases from gcc-4.1.0/libstdc++-v3/testsuite/demangle.
# Collected by:
# % grep verify_demangle **/*.cc | perl -nle 'print $1 if /"(_Z.*?)"/' |
# sort | uniq
#
# Note that the following symbols are invalid.
# That's why they are not demangled.
# - _ZNZN1N1fEiE1X1gE
# - _ZNZN1N1fEiE1X1gEv
# - _Z1xINiEE
_Z1fA37_iPS_ f()
_Z1fAszL_ZZNK1N1A1fEvE3foo_0E_i f()
_Z1fI1APS0_PKS0_EvT_T0_T1_PA4_S3_M1CS8_ f<>()
_Z1fI1XENT_1tES2_ f<>()
_Z1fI1XEvPVN1AIT_E1TE f<>()
_Z1fILi1ELc120EEv1AIXplT_cviLd4028ae147ae147aeEEE f<>()
_Z1fILi1ELc120EEv1AIXplT_cviLf3f800000EEE f<>()
_Z1fILi5E1AEvN1CIXqugtT_Li0ELi1ELi2EEE1qE f<>()
_Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE f<>()
_Z1fILi5EEvN1AIXcvimlT_Li22EEE1qE f<>()
_Z1fIiEvi f<>()
_Z1fKPFiiE f()
_Z1fM1AFivEPS0_ f()
_Z1fM1AKFivE f()
_Z1fM1AKFvvE f()
_Z1fPFPA1_ivE f()
_Z1fPFYPFiiEiE f()
_Z1fPFvvEM1SFvvE f()
_Z1fPKM1AFivE f()
_Z1fi f()
_Z1fv f()
_Z1jM1AFivEPS1_ j()
_Z1rM1GFivEMS_KFivES_M1HFivES1_4whatIKS_E5what2IS8_ES3_ r()
_Z1sPA37_iPS0_ s()
_Z1xINiEE _Z1xINiEE
_Z3absILi11EEvv abs<>()
_Z3foo3bar foo()
_Z3foo5Hello5WorldS0_S_ foo()
_Z3fooA30_A_i foo()
_Z3fooIA6_KiEvA9_KT_rVPrS4_ foo<>()
_Z3fooILi2EEvRAplT_Li1E_i foo<>()
_Z3fooIiFvdEiEvv foo<>()
_Z3fooPM2ABi foo()
_Z3fooc foo()
_Z3fooiPiPS_PS0_PS1_PS2_PS3_PS4_PS5_PS6_PS7_PS8_PS9_PSA_PSB_PSC_ foo()
_Z3kooPA28_A30_i koo()
_Z4makeI7FactoryiET_IT0_Ev make<>()
_Z5firstI3DuoEvS0_ first<>()
_Z5firstI3DuoEvT_ first<>()
_Z9hairyfuncM1YKFPVPFrPA2_PM1XKFKPA3_ilEPcEiE hairyfunc()
_ZGVN5libcw24_GLOBAL__N_cbll.cc0ZhUKa23compiler_bug_workaroundISt6vectorINS_13omanip_id_tctINS_5debug32memblk_types_manipulator_data_ctEEESaIS6_EEE3idsE libcw::(anonymous namespace)::compiler_bug_workaround<>::ids
_ZN12libcw_app_ct10add_optionIS_EEvMT_FvPKcES3_cS3_S3_ libcw_app_ct::add_option<>()
_ZN1AIfEcvT_IiEEv A<>::operator ?<>()
_ZN1N1TIiiE2mfES0_IddE N::T<>::mf()
_ZN1N1fE N::f
_ZN1f1fE f::f
_ZN3FooIA4_iE3barE Foo<>::bar
_ZN5Arena5levelE Arena::level
_ZN5StackIiiE5levelE Stack<>::level
_ZN5libcw5debug13cwprint_usingINS_9_private_12GlobalObjectEEENS0_17cwprint_using_tctIT_EERKS5_MS5_KFvRSt7ostreamE libcw::debug::cwprint_using<>()
_ZN6System5Sound4beepEv System::Sound::beep()
_ZNKSt14priority_queueIP27timer_event_request_base_ctSt5dequeIS1_SaIS1_EE13timer_greaterE3topEv std::priority_queue<>::top()
_ZNKSt15_Deque_iteratorIP15memory_block_stRKS1_PS2_EeqERKS5_ std::_Deque_iterator<>::operator==()
_ZNKSt17__normal_iteratorIPK6optionSt6vectorIS0_SaIS0_EEEmiERKS6_ std::__normal_iterator<>::operator-()
_ZNSbIcSt11char_traitsIcEN5libcw5debug27no_alloc_checking_allocatorEE12_S_constructIPcEES6_T_S7_RKS3_ std::basic_string<>::_S_construct<>()
_ZNSt13_Alloc_traitsISbIcSt18string_char_traitsIcEN5libcw5debug9_private_17allocator_adaptorIcSt24__default_alloc_templateILb0ELi327664EELb1EEEENS5_IS9_S7_Lb1EEEE15_S_instancelessE std::_Alloc_traits<>::_S_instanceless
_ZNSt3_In4wardE std::_In::ward
_ZNZN1N1fEiE1X1gE _ZNZN1N1fEiE1X1gE
_ZNZN1N1fEiE1X1gEv _ZNZN1N1fEiE1X1gEv
_ZSt1BISt1DIP1ARKS2_PS3_ES0_IS2_RS2_PS2_ES2_ET0_T_SB_SA_PT1_ std::B<>()
_ZSt5state std::state
_ZTI7a_class a_class
_ZZN1N1fEiE1p N::f()::p
_ZZN1N1fEiEs N::f()
_ZlsRK1XS1_ operator<<()
_ZlsRKU3fooU4bart1XS0_ operator<<()
_ZlsRKU3fooU4bart1XS2_ operator<<()
_ZlsRSoRKSs operator<<()
_ZngILi42EEvN1AIXplT_Li2EEE1TE operator-<>()
_ZplR1XS0_ operator+()
_Zrm1XS_ operator%()
# Template argument packs can start with I or J.
_Z3addIIiEEvDpT_ add<>()
_Z3addIJiEEvDpT_ add<>()

107
src/glog/log_severity.h Normal file
View file

@ -0,0 +1,107 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASE_LOG_SEVERITY_H__
#define BASE_LOG_SEVERITY_H__
// The recommended semantics of the log levels are as follows:
//
// INFO:
// Use for state changes or other major events, or to aid debugging.
// WARNING:
// Use for undesired but relatively expected events, which may indicate a
// problem
// ERROR:
// Use for undesired and unexpected events that the program can recover from.
// All ERRORs should be actionable - it should be appropriate to file a bug
// whenever an ERROR occurs in production.
// FATAL:
// Use for undesired and unexpected events that the program cannot recover
// from.
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GOOGLE_GLOG_DLL_DECL
# if defined(_WIN32) && !defined(__CYGWIN__)
# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
# else
# define GOOGLE_GLOG_DLL_DECL
# endif
#endif
// Variables of type LogSeverity are widely taken to lie in the range
// [0, NUM_SEVERITIES-1]. Be careful to preserve this assumption if
// you ever need to change their values or add a new severity.
typedef int LogSeverity;
const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
NUM_SEVERITIES = 4;
#ifndef GLOG_NO_ABBREVIATED_SEVERITIES
# ifdef ERROR
# error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail.
# endif
const int INFO = GLOG_INFO, WARNING = GLOG_WARNING,
ERROR = GLOG_ERROR, FATAL = GLOG_FATAL;
#endif
// DFATAL is FATAL in debug mode, ERROR in normal mode
#ifdef NDEBUG
#define DFATAL_LEVEL ERROR
#else
#define DFATAL_LEVEL FATAL
#endif
extern GOOGLE_GLOG_DLL_DECL const char* const LogSeverityNames[NUM_SEVERITIES];
// NDEBUG usage helpers related to (RAW_)DCHECK:
//
// DEBUG_MODE is for small !NDEBUG uses like
// if (DEBUG_MODE) foo.CheckThatFoo();
// instead of substantially more verbose
// #ifndef NDEBUG
// foo.CheckThatFoo();
// #endif
//
// IF_DEBUG_MODE is for small !NDEBUG uses like
// IF_DEBUG_MODE( string error; )
// DCHECK(Foo(&error)) << error;
// instead of substantially more verbose
// #ifndef NDEBUG
// string error;
// DCHECK(Foo(&error)) << error;
// #endif
//
#ifdef NDEBUG
enum { DEBUG_MODE = 0 };
#define IF_DEBUG_MODE(x)
#else
enum { DEBUG_MODE = 1 };
#define IF_DEBUG_MODE(x) x
#endif
#endif // BASE_LOG_SEVERITY_H__

1689
src/glog/logging.h.in Normal file

File diff suppressed because it is too large Load diff

180
src/glog/raw_logging.h.in Normal file
View file

@ -0,0 +1,180 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Maxim Lifantsev
//
// Thread-safe logging routines that do not allocate any memory or
// acquire any locks, and can therefore be used by low-level memory
// allocation and synchronization code.
#ifndef BASE_RAW_LOGGING_H_
#define BASE_RAW_LOGGING_H_
#include <time.h>
@ac_google_start_namespace@
#include "glog/log_severity.h"
#include "glog/vlog_is_on.h"
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GOOGLE_GLOG_DLL_DECL
# if defined(_WIN32) && !defined(__CYGWIN__)
# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
# else
# define GOOGLE_GLOG_DLL_DECL
# endif
#endif
// This is similar to LOG(severity) << format... and VLOG(level) << format..,
// but
// * it is to be used ONLY by low-level modules that can't use normal LOG()
// * it is desiged to be a low-level logger that does not allocate any
// memory and does not need any locks, hence:
// * it logs straight and ONLY to STDERR w/o buffering
// * it uses an explicit format and arguments list
// * it will silently chop off really long message strings
// Usage example:
// RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
// RAW_VLOG(3, "status is %i", status);
// These will print an almost standard log lines like this to stderr only:
// E20200821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
// I20200821 211317 file.cc:142] RAW: status is 20
#define RAW_LOG(severity, ...) \
do { \
switch (@ac_google_namespace@::GLOG_ ## severity) { \
case 0: \
RAW_LOG_INFO(__VA_ARGS__); \
break; \
case 1: \
RAW_LOG_WARNING(__VA_ARGS__); \
break; \
case 2: \
RAW_LOG_ERROR(__VA_ARGS__); \
break; \
case 3: \
RAW_LOG_FATAL(__VA_ARGS__); \
break; \
default: \
break; \
} \
} while (0)
// The following STRIP_LOG testing is performed in the header file so that it's
// possible to completely compile out the logging code and the log messages.
#if STRIP_LOG == 0
#define RAW_VLOG(verboselevel, ...) \
do { \
if (VLOG_IS_ON(verboselevel)) { \
RAW_LOG_INFO(__VA_ARGS__); \
} \
} while (0)
#else
#define RAW_VLOG(verboselevel, ...) RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG == 0
#if STRIP_LOG == 0
#define RAW_LOG_INFO(...) @ac_google_namespace@::RawLog__(@ac_google_namespace@::GLOG_INFO, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_INFO(...) @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG == 0
#if STRIP_LOG <= 1
#define RAW_LOG_WARNING(...) @ac_google_namespace@::RawLog__(@ac_google_namespace@::GLOG_WARNING, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_WARNING(...) @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 1
#if STRIP_LOG <= 2
#define RAW_LOG_ERROR(...) @ac_google_namespace@::RawLog__(@ac_google_namespace@::GLOG_ERROR, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_ERROR(...) @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 2
#if STRIP_LOG <= 3
#define RAW_LOG_FATAL(...) @ac_google_namespace@::RawLog__(@ac_google_namespace@::GLOG_FATAL, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_FATAL(...) \
do { \
@ac_google_namespace@::RawLogStub__(0, __VA_ARGS__); \
exit(1); \
} while (0)
#endif // STRIP_LOG <= 3
// Similar to CHECK(condition) << message,
// but for low-level modules: we use only RAW_LOG that does not allocate memory.
// We do not want to provide args list here to encourage this usage:
// if (!cond) RAW_LOG(FATAL, "foo ...", hard_to_compute_args);
// so that the args are not computed when not needed.
#define RAW_CHECK(condition, message) \
do { \
if (!(condition)) { \
RAW_LOG(FATAL, "Check %s failed: %s", #condition, message); \
} \
} while (0)
// Debug versions of RAW_LOG and RAW_CHECK
#ifndef NDEBUG
#define RAW_DLOG(severity, ...) RAW_LOG(severity, __VA_ARGS__)
#define RAW_DCHECK(condition, message) RAW_CHECK(condition, message)
#else // NDEBUG
#define RAW_DLOG(severity, ...) \
while (false) \
RAW_LOG(severity, __VA_ARGS__)
#define RAW_DCHECK(condition, message) \
while (false) \
RAW_CHECK(condition, message)
#endif // NDEBUG
// Stub log function used to work around for unused variable warnings when
// building with STRIP_LOG > 0.
static inline void RawLogStub__(int /* ignored */, ...) {
}
// Helper function to implement RAW_LOG and RAW_VLOG
// Logs format... at "severity" level, reporting it
// as called from file:line.
// This does not allocate memory or acquire locks.
GOOGLE_GLOG_DLL_DECL void RawLog__(LogSeverity severity,
const char* file,
int line,
const char* format, ...)
@ac_cv___attribute___printf_4_5@;
@ac_google_end_namespace@
#endif // BASE_RAW_LOGGING_H_

220
src/glog/stl_logging.h.in Normal file
View file

@ -0,0 +1,220 @@
// Copyright (c) 2003, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Stream output operators for STL containers; to be used for logging *only*.
// Inclusion of this file lets you do:
//
// list<string> x;
// LOG(INFO) << "data: " << x;
// vector<int> v1, v2;
// CHECK_EQ(v1, v2);
//
// If you want to use this header file with hash maps or slist, you
// need to define macros before including this file:
//
// - GLOG_STL_LOGGING_FOR_UNORDERED - <unordered_map> and <unordered_set>
// - GLOG_STL_LOGGING_FOR_TR1_UNORDERED - <tr1/unordered_(map|set)>
// - GLOG_STL_LOGGING_FOR_EXT_HASH - <ext/hash_(map|set)>
// - GLOG_STL_LOGGING_FOR_EXT_SLIST - <ext/slist>
//
#ifndef UTIL_GTL_STL_LOGGING_INL_H_
#define UTIL_GTL_STL_LOGGING_INL_H_
#if !@ac_cv_cxx_using_operator@
# error We do not support stl_logging for this compiler
#endif
#include <deque>
#include <list>
#include <map>
#include <ostream>
#include <set>
#include <utility>
#include <vector>
#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
# include <unordered_map>
# include <unordered_set>
#endif
#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
# include <tr1/unordered_map>
# include <tr1/unordered_set>
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
# include <ext/hash_set>
# include <ext/hash_map>
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_SLIST
# include <ext/slist>
#endif
// Forward declare these two, and define them after all the container streams
// operators so that we can recurse from pair -> container -> container -> pair
// properly.
template<class First, class Second>
std::ostream& operator<<(std::ostream& out, const std::pair<First, Second>& p);
@ac_google_start_namespace@
template<class Iter>
void PrintSequence(std::ostream& out, Iter begin, Iter end);
@ac_google_end_namespace@
#define OUTPUT_TWO_ARG_CONTAINER(Sequence) \
template<class T1, class T2> \
inline std::ostream& operator<<(std::ostream& out, \
const Sequence<T1, T2>& seq) { \
@ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
return out; \
}
OUTPUT_TWO_ARG_CONTAINER(std::vector)
OUTPUT_TWO_ARG_CONTAINER(std::deque)
OUTPUT_TWO_ARG_CONTAINER(std::list)
#ifdef GLOG_STL_LOGGING_FOR_EXT_SLIST
OUTPUT_TWO_ARG_CONTAINER(__gnu_cxx::slist)
#endif
#undef OUTPUT_TWO_ARG_CONTAINER
#define OUTPUT_THREE_ARG_CONTAINER(Sequence) \
template<class T1, class T2, class T3> \
inline std::ostream& operator<<(std::ostream& out, \
const Sequence<T1, T2, T3>& seq) { \
@ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
return out; \
}
OUTPUT_THREE_ARG_CONTAINER(std::set)
OUTPUT_THREE_ARG_CONTAINER(std::multiset)
#undef OUTPUT_THREE_ARG_CONTAINER
#define OUTPUT_FOUR_ARG_CONTAINER(Sequence) \
template<class T1, class T2, class T3, class T4> \
inline std::ostream& operator<<(std::ostream& out, \
const Sequence<T1, T2, T3, T4>& seq) { \
@ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
return out; \
}
OUTPUT_FOUR_ARG_CONTAINER(std::map)
OUTPUT_FOUR_ARG_CONTAINER(std::multimap)
#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
OUTPUT_FOUR_ARG_CONTAINER(std::unordered_set)
OUTPUT_FOUR_ARG_CONTAINER(std::unordered_multiset)
#endif
#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
OUTPUT_FOUR_ARG_CONTAINER(std::tr1::unordered_set)
OUTPUT_FOUR_ARG_CONTAINER(std::tr1::unordered_multiset)
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_set)
OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_multiset)
#endif
#undef OUTPUT_FOUR_ARG_CONTAINER
#define OUTPUT_FIVE_ARG_CONTAINER(Sequence) \
template<class T1, class T2, class T3, class T4, class T5> \
inline std::ostream& operator<<(std::ostream& out, \
const Sequence<T1, T2, T3, T4, T5>& seq) { \
@ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
return out; \
}
#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
OUTPUT_FIVE_ARG_CONTAINER(std::unordered_map)
OUTPUT_FIVE_ARG_CONTAINER(std::unordered_multimap)
#endif
#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
OUTPUT_FIVE_ARG_CONTAINER(std::tr1::unordered_map)
OUTPUT_FIVE_ARG_CONTAINER(std::tr1::unordered_multimap)
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_map)
OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_multimap)
#endif
#undef OUTPUT_FIVE_ARG_CONTAINER
template<class First, class Second>
inline std::ostream& operator<<(std::ostream& out,
const std::pair<First, Second>& p) {
out << '(' << p.first << ", " << p.second << ')';
return out;
}
@ac_google_start_namespace@
template<class Iter>
inline void PrintSequence(std::ostream& out, Iter begin, Iter end) {
// Output at most 100 elements -- appropriate if used for logging.
for (int i = 0; begin != end && i < 100; ++i, ++begin) {
if (i > 0) out << ' ';
out << *begin;
}
if (begin != end) {
out << " ...";
}
}
@ac_google_end_namespace@
// Note that this is technically undefined behavior! We are adding things into
// the std namespace for a reason though -- we are providing new operations on
// types which are themselves defined with this namespace. Without this, these
// operator overloads cannot be found via ADL. If these definitions are not
// found via ADL, they must be #included before they're used, which requires
// this header to be included before apparently independent other headers.
//
// For example, base/logging.h defines various template functions to implement
// CHECK_EQ(x, y) and stream x and y into the log in the event the check fails.
// It does so via the function template MakeCheckOpValueString:
// template<class T>
// void MakeCheckOpValueString(strstream* ss, const T& v) {
// (*ss) << v;
// }
// Because 'glog/logging.h' is included before 'glog/stl_logging.h',
// subsequent CHECK_EQ(v1, v2) for vector<...> typed variable v1 and v2 can only
// find these operator definitions via ADL.
//
// Even this solution has problems -- it may pull unintended operators into the
// namespace as well, allowing them to also be found via ADL, and creating code
// that only works with a particular order of includes. Long term, we need to
// move all of the *definitions* into namespace std, bet we need to ensure no
// one references them first. This lets us take that step. We cannot define them
// in both because that would create ambiguous overloads when both are found.
namespace std { using ::operator<<; }
#endif // UTIL_GTL_STL_LOGGING_INL_H_

129
src/glog/vlog_is_on.h.in Normal file
View file

@ -0,0 +1,129 @@
// Copyright (c) 1999, 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Ray Sidney and many others
//
// Defines the VLOG_IS_ON macro that controls the variable-verbosity
// conditional logging.
//
// It's used by VLOG and VLOG_IF in logging.h
// and by RAW_VLOG in raw_logging.h to trigger the logging.
//
// It can also be used directly e.g. like this:
// if (VLOG_IS_ON(2)) {
// // do some logging preparation and logging
// // that can't be accomplished e.g. via just VLOG(2) << ...;
// }
//
// The truth value that VLOG_IS_ON(level) returns is determined by
// the three verbosity level flags:
// --v=<n> Gives the default maximal active V-logging level;
// 0 is the default.
// Normally positive values are used for V-logging levels.
// --vmodule=<str> Gives the per-module maximal V-logging levels to override
// the value given by --v.
// E.g. "my_module=2,foo*=3" would change the logging level
// for all code in source files "my_module.*" and "foo*.*"
// ("-inl" suffixes are also disregarded for this matching).
//
// SetVLOGLevel helper function is provided to do limited dynamic control over
// V-logging by overriding the per-module settings given via --vmodule flag.
//
// CAVEAT: --vmodule functionality is not available in non gcc compilers.
//
#ifndef BASE_VLOG_IS_ON_H_
#define BASE_VLOG_IS_ON_H_
#include "glog/log_severity.h"
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GOOGLE_GLOG_DLL_DECL
# if defined(_WIN32) && !defined(__CYGWIN__)
# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
# else
# define GOOGLE_GLOG_DLL_DECL
# endif
#endif
#if defined(__GNUC__)
// We emit an anonymous static int* variable at every VLOG_IS_ON(n) site.
// (Normally) the first time every VLOG_IS_ON(n) site is hit,
// we determine what variable will dynamically control logging at this site:
// it's either FLAGS_v or an appropriate internal variable
// matching the current source file that represents results of
// parsing of --vmodule flag and/or SetVLOGLevel calls.
#define VLOG_IS_ON(verboselevel) \
__extension__ \
({ static @ac_google_namespace@::int32* vlocal__ = &@ac_google_namespace@::kLogSiteUninitialized; \
@ac_google_namespace@::int32 verbose_level__ = (verboselevel); \
(*vlocal__ >= verbose_level__) && \
((vlocal__ != &@ac_google_namespace@::kLogSiteUninitialized) || \
(@ac_google_namespace@::InitVLOG3__(&vlocal__, &FLAGS_v, \
__FILE__, verbose_level__))); })
#else
// GNU extensions not available, so we do not support --vmodule.
// Dynamic value of FLAGS_v always controls the logging level.
#define VLOG_IS_ON(verboselevel) (FLAGS_v >= (verboselevel))
#endif
// Set VLOG(_IS_ON) level for module_pattern to log_level.
// This lets us dynamically control what is normally set by the --vmodule flag.
// Returns the level that previously applied to module_pattern.
// NOTE: To change the log level for VLOG(_IS_ON) sites
// that have already executed after/during InitGoogleLogging,
// one needs to supply the exact --vmodule pattern that applied to them.
// (If no --vmodule pattern applied to them
// the value of FLAGS_v will continue to control them.)
extern GOOGLE_GLOG_DLL_DECL int SetVLOGLevel(const char* module_pattern,
int log_level);
// Various declarations needed for VLOG_IS_ON above: =========================
// Special value used to indicate that a VLOG_IS_ON site has not been
// initialized. We make this a large value, so the common-case check
// of "*vlocal__ >= verbose_level__" in VLOG_IS_ON definition
// passes in such cases and InitVLOG3__ is then triggered.
extern @ac_google_namespace@::int32 kLogSiteUninitialized;
// Helper routine which determines the logging info for a particalur VLOG site.
// site_flag is the address of the site-local pointer to the controlling
// verbosity level
// site_default is the default to use for *site_flag
// fname is the current source file name
// verbose_level is the argument to VLOG_IS_ON
// We will return the return value for VLOG_IS_ON
// and if possible set *site_flag appropriately.
extern GOOGLE_GLOG_DLL_DECL bool InitVLOG3__(
@ac_google_namespace@::int32** site_flag,
@ac_google_namespace@::int32* site_default,
const char* fname,
@ac_google_namespace@::int32 verbose_level);
#endif // BASE_VLOG_IS_ON_H_

611
src/googletest.h Normal file
View file

@ -0,0 +1,611 @@
// Copyright (c) 2009, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Shinichiro Hamaji
// (based on googletest: http://code.google.com/p/googletest/)
#ifdef GOOGLETEST_H__
#error You must not include this file twice.
#endif
#define GOOGLETEST_H__
#include "utilities.h"
#include <ctype.h>
#include <setjmp.h>
#include <time.h>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "base/commandlineflags.h"
using std::map;
using std::string;
using std::vector;
_START_GOOGLE_NAMESPACE_
extern GOOGLE_GLOG_DLL_DECL void (*g_logging_fail_func)();
_END_GOOGLE_NAMESPACE_
#undef GOOGLE_GLOG_DLL_DECL
#define GOOGLE_GLOG_DLL_DECL
static inline string GetTempDir() {
#ifndef OS_WINDOWS
return "/tmp";
#else
char tmp[MAX_PATH];
GetTempPathA(MAX_PATH, tmp);
return tmp;
#endif
}
#if defined(OS_WINDOWS) && defined(_MSC_VER) && !defined(TEST_SRC_DIR)
// The test will run in glog/vsproject/<project name>
// (e.g., glog/vsproject/logging_unittest).
static const char TEST_SRC_DIR[] = "../..";
#elif !defined(TEST_SRC_DIR)
# warning TEST_SRC_DIR should be defined in config.h
static const char TEST_SRC_DIR[] = ".";
#endif
static const uint32_t PTR_TEST_VALUE = 0x12345678;
DEFINE_string(test_tmpdir, GetTempDir(), "Dir we use for temp files");
DEFINE_string(test_srcdir, TEST_SRC_DIR,
"Source-dir root, needed to find glog_unittest_flagfile");
DEFINE_bool(run_benchmark, false, "If true, run benchmarks");
#ifdef NDEBUG
DEFINE_int32(benchmark_iters, 100000000, "Number of iterations per benchmark");
#else
DEFINE_int32(benchmark_iters, 100000, "Number of iterations per benchmark");
#endif
#ifdef HAVE_LIB_GTEST
# include <gtest/gtest.h>
// Use our ASSERT_DEATH implementation.
# undef ASSERT_DEATH
# undef ASSERT_DEBUG_DEATH
using testing::InitGoogleTest;
#else
_START_GOOGLE_NAMESPACE_
void InitGoogleTest(int*, char**);
void InitGoogleTest(int*, char**) {}
// The following is some bare-bones testing infrastructure
#define EXPECT_TRUE(cond) \
do { \
if (!(cond)) { \
fprintf(stderr, "Check failed: %s\n", #cond); \
exit(1); \
} \
} while (0)
#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
#define EXPECT_OP(op, val1, val2) \
do { \
if (!((val1) op (val2))) { \
fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
exit(1); \
} \
} while (0)
#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
#define EXPECT_GT(val1, val2) EXPECT_OP(>, val1, val2)
#define EXPECT_LT(val1, val2) EXPECT_OP(<, val1, val2)
#define EXPECT_NAN(arg) \
do { \
if (!isnan(arg)) { \
fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
exit(1); \
} \
} while (0)
#define EXPECT_INF(arg) \
do { \
if (!isinf(arg)) { \
fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
exit(1); \
} \
} while (0)
#define EXPECT_DOUBLE_EQ(val1, val2) \
do { \
if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
exit(1); \
} \
} while (0)
#define EXPECT_STREQ(val1, val2) \
do { \
if (strcmp((val1), (val2)) != 0) { \
fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
exit(1); \
} \
} while (0)
vector<void (*)()> g_testlist; // the tests to run
#define TEST(a, b) \
struct Test_##a##_##b { \
Test_##a##_##b() { g_testlist.push_back(&Run); } \
static void Run() { FlagSaver fs; RunTest(); } \
static void RunTest(); \
}; \
static Test_##a##_##b g_test_##a##_##b; \
void Test_##a##_##b::RunTest()
static inline int RUN_ALL_TESTS() {
vector<void (*)()>::const_iterator it;
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
(*it)();
}
fprintf(stderr, "Passed %d tests\n\nPASS\n", (int)g_testlist.size());
return 0;
}
_END_GOOGLE_NAMESPACE_
#endif // ! HAVE_LIB_GTEST
_START_GOOGLE_NAMESPACE_
static bool g_called_abort;
static jmp_buf g_jmp_buf;
static inline void CalledAbort() {
g_called_abort = true;
longjmp(g_jmp_buf, 1);
}
#ifdef OS_WINDOWS
// TODO(hamaji): Death test somehow doesn't work in Windows.
#define ASSERT_DEATH(fn, msg)
#else
#define ASSERT_DEATH(fn, msg) \
do { \
g_called_abort = false; \
/* in logging.cc */ \
void (*original_logging_fail_func)() = g_logging_fail_func; \
g_logging_fail_func = &CalledAbort; \
if (!setjmp(g_jmp_buf)) fn; \
/* set back to their default */ \
g_logging_fail_func = original_logging_fail_func; \
if (!g_called_abort) { \
fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
exit(1); \
} \
} while (0)
#endif
#ifdef NDEBUG
#define ASSERT_DEBUG_DEATH(fn, msg)
#else
#define ASSERT_DEBUG_DEATH(fn, msg) ASSERT_DEATH(fn, msg)
#endif // NDEBUG
// Benchmark tools.
#define BENCHMARK(n) static BenchmarkRegisterer __benchmark_ ## n (#n, &n);
map<string, void (*)(int)> g_benchlist; // the benchmarks to run
class BenchmarkRegisterer {
public:
BenchmarkRegisterer(const char* name, void (*function)(int iters)) {
EXPECT_TRUE(g_benchlist.insert(std::make_pair(name, function)).second);
}
};
static inline void RunSpecifiedBenchmarks() {
if (!FLAGS_run_benchmark) {
return;
}
int iter_cnt = FLAGS_benchmark_iters;
puts("Benchmark\tTime(ns)\tIterations");
for (map<string, void (*)(int)>::const_iterator iter = g_benchlist.begin();
iter != g_benchlist.end();
++iter) {
clock_t start = clock();
iter->second(iter_cnt);
double elapsed_ns =
((double)clock() - start) / CLOCKS_PER_SEC * 1000*1000*1000;
printf("%s\t%8.2lf\t%10d\n",
iter->first.c_str(), elapsed_ns / iter_cnt, iter_cnt);
}
puts("");
}
// ----------------------------------------------------------------------
// Golden file functions
// ----------------------------------------------------------------------
class CapturedStream {
public:
CapturedStream(int fd, const string & filename) :
fd_(fd),
uncaptured_fd_(-1),
filename_(filename) {
Capture();
}
~CapturedStream() {
if (uncaptured_fd_ != -1) {
CHECK(close(uncaptured_fd_) != -1);
}
}
// Start redirecting output to a file
void Capture() {
// Keep original stream for later
CHECK(uncaptured_fd_ == -1) << ", Stream " << fd_ << " already captured!";
uncaptured_fd_ = dup(fd_);
CHECK(uncaptured_fd_ != -1);
// Open file to save stream to
int cap_fd = open(filename_.c_str(),
O_CREAT | O_TRUNC | O_WRONLY,
S_IRUSR | S_IWUSR);
CHECK(cap_fd != -1);
// Send stdout/stderr to this file
fflush(NULL);
CHECK(dup2(cap_fd, fd_) != -1);
CHECK(close(cap_fd) != -1);
}
// Remove output redirection
void StopCapture() {
// Restore original stream
if (uncaptured_fd_ != -1) {
fflush(NULL);
CHECK(dup2(uncaptured_fd_, fd_) != -1);
}
}
const string & filename() const { return filename_; }
private:
int fd_; // file descriptor being captured
int uncaptured_fd_; // where the stream was originally being sent to
string filename_; // file where stream is being saved
};
static CapturedStream * s_captured_streams[STDERR_FILENO+1];
// Redirect a file descriptor to a file.
// fd - Should be STDOUT_FILENO or STDERR_FILENO
// filename - File where output should be stored
static inline void CaptureTestOutput(int fd, const string & filename) {
CHECK((fd == STDOUT_FILENO) || (fd == STDERR_FILENO));
CHECK(s_captured_streams[fd] == NULL);
s_captured_streams[fd] = new CapturedStream(fd, filename);
}
static inline void CaptureTestStderr() {
CaptureTestOutput(STDERR_FILENO, FLAGS_test_tmpdir + "/captured.err");
}
// Return the size (in bytes) of a file
static inline size_t GetFileSize(FILE * file) {
fseek(file, 0, SEEK_END);
return static_cast<size_t>(ftell(file));
}
// Read the entire content of a file as a string
static inline string ReadEntireFile(FILE * file) {
const size_t file_size = GetFileSize(file);
char * const buffer = new char[file_size];
size_t bytes_last_read = 0; // # of bytes read in the last fread()
size_t bytes_read = 0; // # of bytes read so far
fseek(file, 0, SEEK_SET);
// Keep reading the file until we cannot read further or the
// pre-determined file size is reached.
do {
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
bytes_read += bytes_last_read;
} while (bytes_last_read > 0 && bytes_read < file_size);
const string content = string(buffer, buffer+bytes_read);
delete[] buffer;
return content;
}
// Get the captured stdout (when fd is STDOUT_FILENO) or stderr (when
// fd is STDERR_FILENO) as a string
static inline string GetCapturedTestOutput(int fd) {
CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO);
CapturedStream * const cap = s_captured_streams[fd];
CHECK(cap)
<< ": did you forget CaptureTestStdout() or CaptureTestStderr()?";
// Make sure everything is flushed.
cap->StopCapture();
// Read the captured file.
FILE * const file = fopen(cap->filename().c_str(), "r");
const string content = ReadEntireFile(file);
fclose(file);
delete cap;
s_captured_streams[fd] = NULL;
return content;
}
// Get the captured stderr of a test as a string.
static inline string GetCapturedTestStderr() {
return GetCapturedTestOutput(STDERR_FILENO);
}
// Check if the string is [IWEF](\d{8}|YEARDATE)
static inline bool IsLoggingPrefix(const string& s) {
if (s.size() != 9) return false;
if (!strchr("IWEF", s[0])) return false;
for (int i = 1; i <= 8; ++i) {
if (!isdigit(s[i]) && s[i] != "YEARDATE"[i-1]) return false;
}
return true;
}
// Convert log output into normalized form.
//
// Example:
// I20200102 030405 logging_unittest.cc:345] RAW: vlog -1
// => IYEARDATE TIME__ logging_unittest.cc:LINE] RAW: vlog -1
static inline string MungeLine(const string& line) {
std::istringstream iss(line);
string before, logcode_date, time, thread_lineinfo;
iss >> logcode_date;
while (!IsLoggingPrefix(logcode_date)) {
before += " " + logcode_date;
if (!(iss >> logcode_date)) {
// We cannot find the header of log output.
return before;
}
}
if (!before.empty()) before += " ";
iss >> time;
iss >> thread_lineinfo;
CHECK(!thread_lineinfo.empty());
if (thread_lineinfo[thread_lineinfo.size() - 1] != ']') {
// We found thread ID.
string tmp;
iss >> tmp;
CHECK(!tmp.empty());
CHECK_EQ(']', tmp[tmp.size() - 1]);
thread_lineinfo = "THREADID " + tmp;
}
size_t index = thread_lineinfo.find(':');
CHECK_NE(string::npos, index);
thread_lineinfo = thread_lineinfo.substr(0, index+1) + "LINE]";
string rest;
std::getline(iss, rest);
return (before + logcode_date[0] + "YEARDATE TIME__ " + thread_lineinfo +
MungeLine(rest));
}
static inline void StringReplace(string* str,
const string& oldsub,
const string& newsub) {
size_t pos = str->find(oldsub);
if (pos != string::npos) {
str->replace(pos, oldsub.size(), newsub.c_str());
}
}
static inline string Munge(const string& filename) {
FILE* fp = fopen(filename.c_str(), "rb");
CHECK(fp != NULL) << filename << ": couldn't open";
char buf[4096];
string result;
while (fgets(buf, 4095, fp)) {
string line = MungeLine(buf);
char null_str[256];
char ptr_str[256];
sprintf(null_str, "%p", static_cast<void*>(NULL));
sprintf(ptr_str, "%p", reinterpret_cast<void*>(PTR_TEST_VALUE));
StringReplace(&line, "__NULLP__", null_str);
StringReplace(&line, "__PTRTEST__", ptr_str);
StringReplace(&line, "__SUCCESS__", StrError(0));
StringReplace(&line, "__ENOENT__", StrError(ENOENT));
StringReplace(&line, "__EINTR__", StrError(EINTR));
StringReplace(&line, "__ENXIO__", StrError(ENXIO));
StringReplace(&line, "__ENOEXEC__", StrError(ENOEXEC));
result += line + "\n";
}
fclose(fp);
return result;
}
static inline void WriteToFile(const string& body, const string& file) {
FILE* fp = fopen(file.c_str(), "wb");
fwrite(body.data(), 1, body.size(), fp);
fclose(fp);
}
static inline bool MungeAndDiffTestStderr(const string& golden_filename) {
CapturedStream* cap = s_captured_streams[STDERR_FILENO];
CHECK(cap) << ": did you forget CaptureTestStderr()?";
cap->StopCapture();
// Run munge
const string captured = Munge(cap->filename());
const string golden = Munge(golden_filename);
if (captured != golden) {
fprintf(stderr,
"Test with golden file failed. We'll try to show the diff:\n");
string munged_golden = golden_filename + ".munged";
WriteToFile(golden, munged_golden);
string munged_captured = cap->filename() + ".munged";
WriteToFile(captured, munged_captured);
#ifdef OS_WINDOWS
string diffcmd("fc " + munged_golden + " " + munged_captured);
#else
string diffcmd("diff -u " + munged_golden + " " + munged_captured);
#endif
if (system(diffcmd.c_str()) != 0) {
fprintf(stderr, "diff command was failed.\n");
}
unlink(munged_golden.c_str());
unlink(munged_captured.c_str());
return false;
}
LOG(INFO) << "Diff was successful";
return true;
}
// Save flags used from logging_unittest.cc.
#ifndef HAVE_LIB_GFLAGS
struct FlagSaver {
FlagSaver()
: v_(FLAGS_v),
stderrthreshold_(FLAGS_stderrthreshold),
logtostderr_(FLAGS_logtostderr),
alsologtostderr_(FLAGS_alsologtostderr) {}
~FlagSaver() {
FLAGS_v = v_;
FLAGS_stderrthreshold = stderrthreshold_;
FLAGS_logtostderr = logtostderr_;
FLAGS_alsologtostderr = alsologtostderr_;
}
int v_;
int stderrthreshold_;
bool logtostderr_;
bool alsologtostderr_;
};
#endif
class Thread {
public:
virtual ~Thread() {}
void SetJoinable(bool) {}
#if defined(OS_WINDOWS) && !defined(OS_CYGWIN)
void Start() {
handle_ = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)&Thread::InvokeThread,
(LPVOID)this,
0,
&th_);
CHECK(handle_) << "CreateThread";
}
void Join() {
WaitForSingleObject(handle_, INFINITE);
}
#elif defined(HAVE_PTHREAD)
void Start() {
pthread_create(&th_, NULL, &Thread::InvokeThread, this);
}
void Join() {
pthread_join(th_, NULL);
}
#else
# error No thread implementation.
#endif
protected:
virtual void Run() = 0;
private:
static void* InvokeThread(void* self) {
((Thread*)self)->Run();
return NULL;
}
#if defined(OS_WINDOWS) && !defined(OS_CYGWIN)
HANDLE handle_;
DWORD th_;
#else
pthread_t th_;
#endif
};
static inline void SleepForMilliseconds(int t) {
#ifndef OS_WINDOWS
# if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L
const struct timespec req = {0, t * 1000 * 1000};
nanosleep(&req, NULL);
# else
usleep(t * 1000);
# endif
#else
Sleep(t);
#endif
}
// Add hook for operator new to ensure there are no memory allocation.
void (*g_new_hook)() = NULL;
_END_GOOGLE_NAMESPACE_
void* operator new(size_t size) {
if (GOOGLE_NAMESPACE::g_new_hook) {
GOOGLE_NAMESPACE::g_new_hook();
}
return malloc(size);
}
void* operator new[](size_t size) {
return ::operator new(size);
}
void operator delete(void* p) {
free(p);
}
void operator delete[](void* p) {
::operator delete(p);
}

2344
src/logging.cc Normal file

File diff suppressed because it is too large Load diff

79
src/logging_striplog_test.sh Executable file
View file

@ -0,0 +1,79 @@
#! /bin/sh
#
# Copyright (c) 2007, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Author: Sergey Ioffe
get_strings () {
if test -e ".libs/$1"; then
binary=".libs/$1"
elif test -e "$1.exe"; then
binary="$1.exe"
else
echo "We coundn't find $1 binary."
exit 1
fi
strings -n 10 $binary | sort | awk '/TESTMESSAGE/ {printf "%s ", $2}'
}
# Die if "$1" != "$2", print $3 as death reason
check_eq () {
if [ "$1" != "$2" ]; then
echo "Check failed: '$1' == '$2' ${3:+ ($3)}"
exit 1
fi
}
die () {
echo $1
exit 1
}
# Check that the string literals are appropriately stripped. This will
# not be the case in debug mode.
mode=`GLOG_check_mode=1 ./logging_striptest0 2> /dev/null`
if [ "$mode" = "opt" ];
then
echo "In OPT mode"
check_eq "`get_strings logging_striptest0`" "COND ERROR FATAL INFO USAGE WARNING "
check_eq "`get_strings logging_striptest2`" "COND ERROR FATAL USAGE "
check_eq "`get_strings logging_striptest10`" ""
else
echo "In DBG mode; not checking strings"
fi
# Check that LOG(FATAL) aborts even for large STRIP_LOG
./logging_striptest2 2>/dev/null && die "Did not abort for STRIP_LOG=2"
./logging_striptest10 2>/dev/null && die "Did not abort for STRIP_LOG=10"
echo "PASS"

View file

@ -0,0 +1,35 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Sergey Ioffe
#define GOOGLE_STRIP_LOG 10
// Include the actual test.
#include "logging_striptest_main.cc"

35
src/logging_striptest2.cc Normal file
View file

@ -0,0 +1,35 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Sergey Ioffe
#define GOOGLE_STRIP_LOG 2
// Include the actual test.
#include "logging_striptest_main.cc"

View file

@ -0,0 +1,73 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Sergey Ioffe
// The common part of the striplog tests.
#include <stdio.h>
#include <string>
#include <iosfwd>
#include "glog/logging.h"
#include "base/commandlineflags.h"
#include "config.h"
DECLARE_bool(logtostderr);
GLOG_DEFINE_bool(check_mode, false, "Prints 'opt' or 'dbg'");
using std::string;
using namespace GOOGLE_NAMESPACE;
int CheckNoReturn(bool b) {
string s;
if (b) {
LOG(FATAL) << "Fatal";
} else {
return 0;
}
}
struct A { };
std::ostream &operator<<(std::ostream &str, const A&) {return str;}
int main(int, char* argv[]) {
FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]);
if (FLAGS_check_mode) {
printf("%s\n", DEBUG_MODE ? "dbg" : "opt");
return 0;
}
LOG(INFO) << "TESTMESSAGE INFO";
LOG(WARNING) << 2 << "something" << "TESTMESSAGE WARNING"
<< 1 << 'c' << A() << std::endl;
LOG(ERROR) << "TESTMESSAGE ERROR";
bool flag = true;
(flag ? LOG(INFO) : LOG(ERROR)) << "TESTMESSAGE COND";
LOG(FATAL) << "TESTMESSAGE FATAL";
}

1348
src/logging_unittest.cc Normal file

File diff suppressed because it is too large Load diff

307
src/logging_unittest.err Normal file
View file

@ -0,0 +1,307 @@
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
WARNING: Logging before InitGoogleLogging() is written to STDERR
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] foo bar 10 3.4
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 1: __SUCCESS__ [0]
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 1
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 1
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 5, iteration 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 1
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if less than 3 every 2, iteration 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 2
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 3: __ENOENT__ [2]
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 3
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if less than 3 every 2, iteration 3
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 4
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 4
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 5: __EINTR__ [4]
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 5
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 5
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 5, iteration 6
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 6
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 7: __ENXIO__ [6]
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 7
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 7
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 8
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 9: __ENOEXEC__ [8]
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 9
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 9
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 10
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 10
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if this
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] array
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] const array
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] foo 1000 0000001000 3e8
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] inner
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] outer
no prefix
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo bar 10 3.400000
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: array
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: const array
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: ptr __PTRTEST__
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: ptr __NULLP__
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000 0000001000 3e8
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0 on
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1 on
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 2 on
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=-1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=1 logtostderr=0 alsologtostderr=0
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=1 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=1 logtostderr=0 alsologtostderr=0
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=3 logtostderr=0 alsologtostderr=1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected info
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected warning
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_SINK:
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected info
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected warning
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3

156
src/mock-log.h Normal file
View file

@ -0,0 +1,156 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Zhanyong Wan
//
// Defines the ScopedMockLog class (using Google C++ Mocking
// Framework), which is convenient for testing code that uses LOG().
#ifndef GLOG_SRC_MOCK_LOG_H_
#define GLOG_SRC_MOCK_LOG_H_
// For GOOGLE_NAMESPACE. This must go first so we get _XOPEN_SOURCE.
#include "utilities.h"
#include <string>
#include <gmock/gmock.h>
#include "glog/logging.h"
_START_GOOGLE_NAMESPACE_
namespace glog_testing {
// A ScopedMockLog object intercepts LOG() messages issued during its
// lifespan. Using this together with Google C++ Mocking Framework,
// it's very easy to test how a piece of code calls LOG(). The
// typical usage:
//
// TEST(FooTest, LogsCorrectly) {
// ScopedMockLog log;
//
// // We expect the WARNING "Something bad!" exactly twice.
// EXPECT_CALL(log, Log(WARNING, _, "Something bad!"))
// .Times(2);
//
// // We allow foo.cc to call LOG(INFO) any number of times.
// EXPECT_CALL(log, Log(INFO, HasSubstr("/foo.cc"), _))
// .Times(AnyNumber());
//
// Foo(); // Exercises the code under test.
// }
class ScopedMockLog : public GOOGLE_NAMESPACE::LogSink {
public:
// When a ScopedMockLog object is constructed, it starts to
// intercept logs.
ScopedMockLog() { AddLogSink(this); }
// When the object is destructed, it stops intercepting logs.
virtual ~ScopedMockLog() { RemoveLogSink(this); }
// Implements the mock method:
//
// void Log(LogSeverity severity, const string& file_path,
// const string& message);
//
// The second argument to Send() is the full path of the source file
// in which the LOG() was issued.
//
// Note, that in a multi-threaded environment, all LOG() messages from a
// single thread will be handled in sequence, but that cannot be guaranteed
// for messages from different threads. In fact, if the same or multiple
// expectations are matched on two threads concurrently, their actions will
// be executed concurrently as well and may interleave.
MOCK_METHOD3(Log, void(GOOGLE_NAMESPACE::LogSeverity severity,
const std::string& file_path,
const std::string& message));
private:
// Implements the send() virtual function in class LogSink.
// Whenever a LOG() statement is executed, this function will be
// invoked with information presented in the LOG().
//
// The method argument list is long and carries much information a
// test usually doesn't care about, so we trim the list before
// forwarding the call to Log(), which is much easier to use in
// tests.
//
// We still cannot call Log() directly, as it may invoke other LOG()
// messages, either due to Invoke, or due to an error logged in
// Google C++ Mocking Framework code, which would trigger a deadlock
// since a lock is held during send().
//
// Hence, we save the message for WaitTillSent() which will be called after
// the lock on send() is released, and we'll call Log() inside
// WaitTillSent(). Since while a single send() call may be running at a
// time, multiple WaitTillSent() calls (along with the one send() call) may
// be running simultaneously, we ensure thread-safety of the exchange between
// send() and WaitTillSent(), and that for each message, LOG(), send(),
// WaitTillSent() and Log() are executed in the same thread.
virtual void send(GOOGLE_NAMESPACE::LogSeverity severity,
const char* full_filename,
const char* /*base_filename*/, int /*line*/,
const tm* /*tm_time*/,
const char* message, size_t message_len) {
// We are only interested in the log severity, full file name, and
// log message.
message_info_.severity = severity;
message_info_.file_path = full_filename;
message_info_.message = std::string(message, message_len);
}
// Implements the WaitTillSent() virtual function in class LogSink.
// It will be executed after send() and after the global logging lock is
// released, so calls within it (or rather within the Log() method called
// within) may also issue LOG() statements.
//
// LOG(), send(), WaitTillSent() and Log() will occur in the same thread for
// a given log message.
virtual void WaitTillSent() {
// First, and very importantly, we save a copy of the message being
// processed before calling Log(), since Log() may indirectly call send()
// and WaitTillSent() in the same thread again.
MessageInfo message_info = message_info_;
Log(message_info.severity, message_info.file_path, message_info.message);
}
// All relevant information about a logged message that needs to be passed
// from send() to WaitTillSent().
struct MessageInfo {
GOOGLE_NAMESPACE::LogSeverity severity;
std::string file_path;
std::string message;
};
MessageInfo message_info_;
};
} // namespace glog_testing
_END_GOOGLE_NAMESPACE_
#endif // GLOG_SRC_MOCK_LOG_H_

106
src/mock-log_test.cc Normal file
View file

@ -0,0 +1,106 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Zhanyong Wan
// Tests the ScopedMockLog class.
#include "mock-log.h"
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace {
using GOOGLE_NAMESPACE::INFO;
using GOOGLE_NAMESPACE::WARNING;
using GOOGLE_NAMESPACE::ERROR;
using GOOGLE_NAMESPACE::glog_testing::ScopedMockLog;
using std::string;
using testing::_;
using testing::HasSubstr;
using testing::InSequence;
using testing::InvokeWithoutArgs;
// Tests that ScopedMockLog intercepts LOG()s when it's alive.
TEST(ScopedMockLogTest, InterceptsLog) {
ScopedMockLog log;
InSequence s;
EXPECT_CALL(log, Log(WARNING, HasSubstr("/mock-log_test.cc"), "Fishy."));
EXPECT_CALL(log, Log(INFO, _, "Working..."))
.Times(2);
EXPECT_CALL(log, Log(ERROR, _, "Bad!!"));
LOG(WARNING) << "Fishy.";
LOG(INFO) << "Working...";
LOG(INFO) << "Working...";
LOG(ERROR) << "Bad!!";
}
void LogBranch() {
LOG(INFO) << "Logging a branch...";
}
void LogTree() {
LOG(INFO) << "Logging the whole tree...";
}
void LogForest() {
LOG(INFO) << "Logging the entire forest.";
LOG(INFO) << "Logging the entire forest..";
LOG(INFO) << "Logging the entire forest...";
}
// The purpose of the following test is to verify that intercepting logging
// continues to work properly if a LOG statement is executed within the scope
// of a mocked call.
TEST(ScopedMockLogTest, LogDuringIntercept) {
ScopedMockLog log;
InSequence s;
EXPECT_CALL(log, Log(INFO, __FILE__, "Logging a branch..."))
.WillOnce(InvokeWithoutArgs(LogTree));
EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the whole tree..."))
.WillOnce(InvokeWithoutArgs(LogForest));
EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the entire forest."));
EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the entire forest.."));
EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the entire forest..."));
LogBranch();
}
} // namespace
int main(int argc, char **argv) {
GOOGLE_NAMESPACE::InitGoogleLogging(argv[0]);
testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}

View file

@ -0,0 +1,8 @@
cmake_minimum_required (VERSION 3.1)
project (glog_package_config)
find_package (glog REQUIRED NO_MODULE)
add_executable (glog_package_config glog_package_config.cc)
target_link_libraries (glog_package_config PRIVATE glog::glog)

View file

@ -0,0 +1,6 @@
#include <glog/logging.h>
int main(int /*argc*/, char** argv)
{
google::InitGoogleLogging(argv[0]);
}

158
src/raw_logging.cc Normal file
View file

@ -0,0 +1,158 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Maxim Lifantsev
//
// logging_unittest.cc covers the functionality herein
#include "utilities.h"
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h> // for close() and write()
#endif
#include <fcntl.h> // for open()
#include <time.h>
#include "config.h"
#include "glog/logging.h" // To pick up flag settings etc.
#include "glog/raw_logging.h"
#include "base/commandlineflags.h"
#ifdef HAVE_STACKTRACE
# include "stacktrace.h"
#endif
#if defined(HAVE_SYSCALL_H)
#include <syscall.h> // for syscall()
#elif defined(HAVE_SYS_SYSCALL_H)
#include <sys/syscall.h> // for syscall()
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#if defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)
# define safe_write(fd, s, len) syscall(SYS_write, fd, s, len)
#else
// Not so safe, but what can you do?
# define safe_write(fd, s, len) write(fd, s, len)
#endif
_START_GOOGLE_NAMESPACE_
// CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
// that invoke malloc() and getenv() that might acquire some locks.
// If this becomes a problem we should reimplement a subset of vsnprintf
// that does not need locks and malloc.
// Helper for RawLog__ below.
// *DoRawLog writes to *buf of *size and move them past the written portion.
// It returns true iff there was no overflow or error.
static bool DoRawLog(char** buf, int* size, const char* format, ...) {
va_list ap;
va_start(ap, format);
int n = vsnprintf(*buf, *size, format, ap);
va_end(ap);
if (n < 0 || n > *size) return false;
*size -= n;
*buf += n;
return true;
}
// Helper for RawLog__ below.
inline static bool VADoRawLog(char** buf, int* size,
const char* format, va_list ap) {
int n = vsnprintf(*buf, *size, format, ap);
if (n < 0 || n > *size) return false;
*size -= n;
*buf += n;
return true;
}
static const int kLogBufSize = 3000;
static bool crashed = false;
static CrashReason crash_reason;
static char crash_buf[kLogBufSize + 1] = { 0 }; // Will end in '\0'
void RawLog__(LogSeverity severity, const char* file, int line,
const char* format, ...) {
if (!(FLAGS_logtostderr || severity >= FLAGS_stderrthreshold ||
FLAGS_alsologtostderr || !IsGoogleLoggingInitialized())) {
return; // this stderr log message is suppressed
}
// can't call localtime_r here: it can allocate
char buffer[kLogBufSize];
char* buf = buffer;
int size = sizeof(buffer);
// NOTE: this format should match the specification in base/logging.h
DoRawLog(&buf, &size, "%c00000000 00:00:00.000000 %5u %s:%d] RAW: ",
LogSeverityNames[severity][0],
static_cast<unsigned int>(GetTID()),
const_basename(const_cast<char *>(file)), line);
// Record the position and size of the buffer after the prefix
const char* msg_start = buf;
const int msg_size = size;
va_list ap;
va_start(ap, format);
bool no_chop = VADoRawLog(&buf, &size, format, ap);
va_end(ap);
if (no_chop) {
DoRawLog(&buf, &size, "\n");
} else {
DoRawLog(&buf, &size, "RAW_LOG ERROR: The Message was too long!\n");
}
// We make a raw syscall to write directly to the stderr file descriptor,
// avoiding FILE buffering (to avoid invoking malloc()), and bypassing
// libc (to side-step any libc interception).
// We write just once to avoid races with other invocations of RawLog__.
safe_write(STDERR_FILENO, buffer, strlen(buffer));
if (severity == GLOG_FATAL) {
if (!sync_val_compare_and_swap(&crashed, false, true)) {
crash_reason.filename = file;
crash_reason.line_number = line;
memcpy(crash_buf, msg_start, msg_size); // Don't include prefix
crash_reason.message = crash_buf;
#ifdef HAVE_STACKTRACE
crash_reason.depth =
GetStackTrace(crash_reason.stack, ARRAYSIZE(crash_reason.stack), 1);
#else
crash_reason.depth = 0;
#endif
SetCrashReason(&crash_reason);
}
LogMessage::Fail(); // abort()
}
}
_END_GOOGLE_NAMESPACE_

403
src/signalhandler.cc Normal file
View file

@ -0,0 +1,403 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Satoru Takabayashi
//
// Implementation of InstallFailureSignalHandler().
#include "utilities.h"
#include "stacktrace.h"
#include "symbolize.h"
#include "glog/logging.h"
#include <signal.h>
#include <time.h>
#ifdef HAVE_UCONTEXT_H
# include <ucontext.h>
#endif
#ifdef HAVE_SYS_UCONTEXT_H
# include <sys/ucontext.h>
#endif
#include <algorithm>
_START_GOOGLE_NAMESPACE_
namespace {
// We'll install the failure signal handler for these signals. We could
// use strsignal() to get signal names, but we don't use it to avoid
// introducing yet another #ifdef complication.
//
// The list should be synced with the comment in signalhandler.h.
const struct {
int number;
const char *name;
} kFailureSignals[] = {
{ SIGSEGV, "SIGSEGV" },
{ SIGILL, "SIGILL" },
{ SIGFPE, "SIGFPE" },
{ SIGABRT, "SIGABRT" },
#if !defined(OS_WINDOWS)
{ SIGBUS, "SIGBUS" },
#endif
{ SIGTERM, "SIGTERM" },
};
static bool kFailureSignalHandlerInstalled = false;
// Returns the program counter from signal context, NULL if unknown.
void* GetPC(void* ucontext_in_void) {
#if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && defined(PC_FROM_UCONTEXT)
if (ucontext_in_void != NULL) {
ucontext_t *context = reinterpret_cast<ucontext_t *>(ucontext_in_void);
return (void*)context->PC_FROM_UCONTEXT;
}
#endif
return NULL;
}
// The class is used for formatting error messages. We don't use printf()
// as it's not async signal safe.
class MinimalFormatter {
public:
MinimalFormatter(char *buffer, int size)
: buffer_(buffer),
cursor_(buffer),
end_(buffer + size) {
}
// Returns the number of bytes written in the buffer.
int num_bytes_written() const { return (int) (cursor_ - buffer_); }
// Appends string from "str" and updates the internal cursor.
void AppendString(const char* str) {
int i = 0;
while (str[i] != '\0' && cursor_ + i < end_) {
cursor_[i] = str[i];
++i;
}
cursor_ += i;
}
// Formats "number" in "radix" and updates the internal cursor.
// Lowercase letters are used for 'a' - 'z'.
void AppendUint64(uint64 number, int radix) {
int i = 0;
while (cursor_ + i < end_) {
const int tmp = number % radix;
number /= radix;
cursor_[i] = (tmp < 10 ? '0' + tmp : 'a' + tmp - 10);
++i;
if (number == 0) {
break;
}
}
// Reverse the bytes written.
std::reverse(cursor_, cursor_ + i);
cursor_ += i;
}
// Formats "number" as hexadecimal number, and updates the internal
// cursor. Padding will be added in front if needed.
void AppendHexWithPadding(uint64 number, int width) {
char* start = cursor_;
AppendString("0x");
AppendUint64(number, 16);
// Move to right and add padding in front if needed.
if (cursor_ < start + width) {
const int64 delta = start + width - cursor_;
std::copy(start, cursor_, start + delta);
std::fill(start, start + delta, ' ');
cursor_ = start + width;
}
}
private:
char *buffer_;
char *cursor_;
const char * const end_;
};
// Writes the given data with the size to the standard error.
void WriteToStderr(const char* data, int size) {
if (write(STDERR_FILENO, data, size) < 0) {
// Ignore errors.
}
}
// The writer function can be changed by InstallFailureWriter().
void (*g_failure_writer)(const char* data, int size) = WriteToStderr;
// Dumps time information. We don't dump human-readable time information
// as localtime() is not guaranteed to be async signal safe.
void DumpTimeInfo() {
time_t time_in_sec = time(NULL);
char buf[256]; // Big enough for time info.
MinimalFormatter formatter(buf, sizeof(buf));
formatter.AppendString("*** Aborted at ");
formatter.AppendUint64(time_in_sec, 10);
formatter.AppendString(" (unix time)");
formatter.AppendString(" try \"date -d @");
formatter.AppendUint64(time_in_sec, 10);
formatter.AppendString("\" if you are using GNU date ***\n");
g_failure_writer(buf, formatter.num_bytes_written());
}
// TODO(hamaji): Use signal instead of sigaction?
#ifdef HAVE_SIGACTION
// Dumps information about the signal to STDERR.
void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
// Get the signal name.
const char* signal_name = NULL;
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
if (signal_number == kFailureSignals[i].number) {
signal_name = kFailureSignals[i].name;
}
}
char buf[256]; // Big enough for signal info.
MinimalFormatter formatter(buf, sizeof(buf));
formatter.AppendString("*** ");
if (signal_name) {
formatter.AppendString(signal_name);
} else {
// Use the signal number if the name is unknown. The signal name
// should be known, but just in case.
formatter.AppendString("Signal ");
formatter.AppendUint64(signal_number, 10);
}
formatter.AppendString(" (@0x");
formatter.AppendUint64(reinterpret_cast<uintptr_t>(siginfo->si_addr), 16);
formatter.AppendString(")");
formatter.AppendString(" received by PID ");
formatter.AppendUint64(getpid(), 10);
formatter.AppendString(" (TID 0x");
// We assume pthread_t is an integral number or a pointer, rather
// than a complex struct. In some environments, pthread_self()
// returns an uint64 but in some other environments pthread_self()
// returns a pointer. Hence we use C-style cast here, rather than
// reinterpret/static_cast, to support both types of environments.
formatter.AppendUint64((uintptr_t)pthread_self(), 16);
formatter.AppendString(") ");
// Only linux has the PID of the signal sender in si_pid.
#ifdef OS_LINUX
formatter.AppendString("from PID ");
formatter.AppendUint64(siginfo->si_pid, 10);
formatter.AppendString("; ");
#endif
formatter.AppendString("stack trace: ***\n");
g_failure_writer(buf, formatter.num_bytes_written());
}
#endif // HAVE_SIGACTION
// Dumps information about the stack frame to STDERR.
void DumpStackFrameInfo(const char* prefix, void* pc) {
// Get the symbol name.
const char *symbol = "(unknown)";
char symbolized[1024]; // Big enough for a sane symbol.
// Symbolizes the previous address of pc because pc may be in the
// next function.
if (Symbolize(reinterpret_cast<char *>(pc) - 1,
symbolized, sizeof(symbolized))) {
symbol = symbolized;
}
char buf[1024]; // Big enough for stack frame info.
MinimalFormatter formatter(buf, sizeof(buf));
formatter.AppendString(prefix);
formatter.AppendString("@ ");
const int width = 2 * sizeof(void*) + 2; // + 2 for "0x".
formatter.AppendHexWithPadding(reinterpret_cast<uintptr_t>(pc), width);
formatter.AppendString(" ");
formatter.AppendString(symbol);
formatter.AppendString("\n");
g_failure_writer(buf, formatter.num_bytes_written());
}
// Invoke the default signal handler.
void InvokeDefaultSignalHandler(int signal_number) {
#ifdef HAVE_SIGACTION
struct sigaction sig_action;
memset(&sig_action, 0, sizeof(sig_action));
sigemptyset(&sig_action.sa_mask);
sig_action.sa_handler = SIG_DFL;
sigaction(signal_number, &sig_action, NULL);
kill(getpid(), signal_number);
#elif defined(OS_WINDOWS)
signal(signal_number, SIG_DFL);
raise(signal_number);
#endif
}
// This variable is used for protecting FailureSignalHandler() from
// dumping stuff while another thread is doing it. Our policy is to let
// the first thread dump stuff and let other threads wait.
// See also comments in FailureSignalHandler().
static pthread_t* g_entered_thread_id_pointer = NULL;
// Dumps signal and stack frame information, and invokes the default
// signal handler once our job is done.
#if defined(OS_WINDOWS)
void FailureSignalHandler(int signal_number)
#else
void FailureSignalHandler(int signal_number,
siginfo_t *signal_info,
void *ucontext)
#endif
{
// First check if we've already entered the function. We use an atomic
// compare and swap operation for platforms that support it. For other
// platforms, we use a naive method that could lead to a subtle race.
// We assume pthread_self() is async signal safe, though it's not
// officially guaranteed.
pthread_t my_thread_id = pthread_self();
// NOTE: We could simply use pthread_t rather than pthread_t* for this,
// if pthread_self() is guaranteed to return non-zero value for thread
// ids, but there is no such guarantee. We need to distinguish if the
// old value (value returned from __sync_val_compare_and_swap) is
// different from the original value (in this case NULL).
pthread_t* old_thread_id_pointer =
glog_internal_namespace_::sync_val_compare_and_swap(
&g_entered_thread_id_pointer,
static_cast<pthread_t*>(NULL),
&my_thread_id);
if (old_thread_id_pointer != NULL) {
// We've already entered the signal handler. What should we do?
if (pthread_equal(my_thread_id, *g_entered_thread_id_pointer)) {
// It looks the current thread is reentering the signal handler.
// Something must be going wrong (maybe we are reentering by another
// type of signal?). Kill ourself by the default signal handler.
InvokeDefaultSignalHandler(signal_number);
}
// Another thread is dumping stuff. Let's wait until that thread
// finishes the job and kills the process.
while (true) {
sleep(1);
}
}
// This is the first time we enter the signal handler. We are going to
// do some interesting stuff from here.
// TODO(satorux): We might want to set timeout here using alarm(), but
// mixing alarm() and sleep() can be a bad idea.
// First dump time info.
DumpTimeInfo();
#if !defined(OS_WINDOWS)
// Get the program counter from ucontext.
void *pc = GetPC(ucontext);
DumpStackFrameInfo("PC: ", pc);
#endif
#ifdef HAVE_STACKTRACE
// Get the stack traces.
void *stack[32];
// +1 to exclude this function.
const int depth = GetStackTrace(stack, ARRAYSIZE(stack), 1);
# ifdef HAVE_SIGACTION
DumpSignalInfo(signal_number, signal_info);
# endif
// Dump the stack traces.
for (int i = 0; i < depth; ++i) {
DumpStackFrameInfo(" ", stack[i]);
}
#endif
// *** TRANSITION ***
//
// BEFORE this point, all code must be async-termination-safe!
// (See WARNING above.)
//
// AFTER this point, we do unsafe things, like using LOG()!
// The process could be terminated or hung at any time. We try to
// do more useful things first and riskier things later.
// Flush the logs before we do anything in case 'anything'
// causes problems.
FlushLogFilesUnsafe(0);
// Kill ourself by the default signal handler.
InvokeDefaultSignalHandler(signal_number);
}
} // namespace
namespace glog_internal_namespace_ {
bool IsFailureSignalHandlerInstalled() {
#ifdef HAVE_SIGACTION
// TODO(andschwa): Return kFailureSignalHandlerInstalled?
struct sigaction sig_action;
memset(&sig_action, 0, sizeof(sig_action));
sigemptyset(&sig_action.sa_mask);
sigaction(SIGABRT, NULL, &sig_action);
if (sig_action.sa_sigaction == &FailureSignalHandler)
return true;
#elif defined(OS_WINDOWS)
return kFailureSignalHandlerInstalled;
#endif // HAVE_SIGACTION
return false;
}
} // namespace glog_internal_namespace_
void InstallFailureSignalHandler() {
#ifdef HAVE_SIGACTION
// Build the sigaction struct.
struct sigaction sig_action;
memset(&sig_action, 0, sizeof(sig_action));
sigemptyset(&sig_action.sa_mask);
sig_action.sa_flags |= SA_SIGINFO;
sig_action.sa_sigaction = &FailureSignalHandler;
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
CHECK_ERR(sigaction(kFailureSignals[i].number, &sig_action, NULL));
}
kFailureSignalHandlerInstalled = true;
#elif defined(OS_WINDOWS)
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
CHECK_NE(signal(kFailureSignals[i].number, &FailureSignalHandler),
SIG_ERR);
}
kFailureSignalHandlerInstalled = true;
#endif // HAVE_SIGACTION
}
void InstallFailureWriter(void (*writer)(const char* data, int size)) {
#if defined(HAVE_SIGACTION) || defined(OS_WINDOWS)
g_failure_writer = writer;
#endif // HAVE_SIGACTION
}
_END_GOOGLE_NAMESPACE_

View file

@ -0,0 +1,112 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Satoru Takabayashi
//
// This is a helper binary for testing signalhandler.cc. The actual test
// is done in signalhandler_unittest.sh.
#include "utilities.h"
#if defined(HAVE_PTHREAD)
# include <pthread.h>
#endif
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "glog/logging.h"
#ifdef HAVE_LIB_GFLAGS
#include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE;
#endif
using namespace GOOGLE_NAMESPACE;
static void* DieInThread(void*) {
// We assume pthread_t is an integral number or a pointer, rather
// than a complex struct. In some environments, pthread_self()
// returns an uint64 but in some other environments pthread_self()
// returns a pointer. Hence we use C-style cast here, rather than
// reinterpret/static_cast, to support both types of environments.
fprintf(stderr, "0x%lx is dying\n", (long)pthread_self());
// Use volatile to prevent from these to be optimized away.
volatile int a = 0;
volatile int b = 1 / a;
fprintf(stderr, "We should have died: b=%d\n", b);
return NULL;
}
static void WriteToStdout(const char* data, int size) {
if (write(STDOUT_FILENO, data, size) < 0) {
// Ignore errors.
}
}
int main(int argc, char **argv) {
#if defined(HAVE_STACKTRACE) && defined(HAVE_SYMBOLIZE)
InitGoogleLogging(argv[0]);
#ifdef HAVE_LIB_GFLAGS
ParseCommandLineFlags(&argc, &argv, true);
#endif
InstallFailureSignalHandler();
const std::string command = argc > 1 ? argv[1] : "none";
if (command == "segv") {
// We'll check if this is outputted.
LOG(INFO) << "create the log file";
LOG(INFO) << "a message before segv";
// We assume 0xDEAD is not writable.
int *a = (int*)0xDEAD;
*a = 0;
} else if (command == "loop") {
fprintf(stderr, "looping\n");
while (true);
} else if (command == "die_in_thread") {
#if defined(HAVE_PTHREAD)
pthread_t thread;
pthread_create(&thread, NULL, &DieInThread, NULL);
pthread_join(thread, NULL);
#else
fprintf(stderr, "no pthread\n");
return 1;
#endif
} else if (command == "dump_to_stdout") {
InstallFailureWriter(WriteToStdout);
abort();
} else if (command == "installed") {
fprintf(stderr, "signal handler installed: %s\n",
IsFailureSignalHandlerInstalled() ? "true" : "false");
} else {
// Tell the shell script
puts("OK");
}
#endif
return 0;
}

131
src/signalhandler_unittest.sh Executable file
View file

@ -0,0 +1,131 @@
#! /bin/sh
#
# Copyright (c) 2008, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Author: Satoru Takabayashi
#
# Unit tests for signalhandler.cc.
die () {
echo $1
exit 1
}
BINDIR=".libs"
LIBGLOG="$BINDIR/libglog.so"
BINARY="$BINDIR/signalhandler_unittest"
LOG_INFO="./signalhandler_unittest.INFO"
# Remove temporary files.
rm -f signalhandler.out*
if test -e "$BINARY"; then
# We need shared object.
export LD_LIBRARY_PATH=$BINDIR
export DYLD_LIBRARY_PATH=$BINDIR
else
# For windows
BINARY="./signalhandler_unittest.exe"
if ! test -e "$BINARY"; then
echo "We coundn't find demangle_unittest binary."
exit 1
fi
fi
if [ x`$BINARY` != 'xOK' ]; then
echo "PASS (No stacktrace support. We don't run this test.)"
exit 0
fi
# The PC cannot be obtained in signal handlers on PowerPC correctly.
# We just skip the test for PowerPC.
if [ x`uname -p` = x"powerpc" ]; then
echo "PASS (We don't test the signal handler on PowerPC.)"
exit 0
fi
# Test for a case the program kills itself by SIGSEGV.
GOOGLE_LOG_DIR=. $BINARY segv 2> signalhandler.out1
for pattern in SIGSEGV 0xdead main "Aborted at [0-9]"; do
if ! grep --quiet "$pattern" signalhandler.out1; then
die "'$pattern' should appear in the output"
fi
done
if ! grep --quiet "a message before segv" $LOG_INFO; then
die "'a message before segv' should appear in the INFO log"
fi
rm -f $LOG_INFO
# Test for a case the program is killed by this shell script.
# $! = the process id of the last command run in the background.
# $$ = the process id of this shell.
$BINARY loop 2> signalhandler.out2 &
# Wait until "looping" is written in the file. This indicates the program
# is ready to accept signals.
while true; do
if grep --quiet looping signalhandler.out2; then
break
fi
done
kill -TERM $!
wait $!
from_pid=''
# Only linux has the process ID of the signal sender.
if [ x`uname` = "xLinux" ]; then
from_pid="from PID $$"
fi
for pattern in SIGTERM "by PID $!" "$from_pid" main "Aborted at [0-9]"; do
if ! grep --quiet "$pattern" signalhandler.out2; then
die "'$pattern' should appear in the output"
fi
done
# Test for a case the program dies in a non-main thread.
$BINARY die_in_thread 2> signalhandler.out3
EXPECTED_TID="`sed 's/ .*//; q' signalhandler.out3`"
for pattern in SIGFPE DieInThread "TID $EXPECTED_TID" "Aborted at [0-9]"; do
if ! grep --quiet "$pattern" signalhandler.out3; then
die "'$pattern' should appear in the output"
fi
done
# Test for a case the program installs a custom failure writer that writes
# stuff to stdout instead of stderr.
$BINARY dump_to_stdout 1> signalhandler.out4
for pattern in SIGABRT main "Aborted at [0-9]"; do
if ! grep --quiet "$pattern" signalhandler.out4; then
die "'$pattern' should appear in the output"
fi
done
echo PASS

61
src/stacktrace.h Normal file
View file

@ -0,0 +1,61 @@
// Copyright (c) 2000 - 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Routines to extract the current stack trace. These functions are
// thread-safe.
#ifndef BASE_STACKTRACE_H_
#define BASE_STACKTRACE_H_
#include "config.h"
#include "glog/logging.h"
_START_GOOGLE_NAMESPACE_
// This is similar to the GetStackFrames routine, except that it returns
// the stack trace only, and not the stack frame sizes as well.
// Example:
// main() { foo(); }
// foo() { bar(); }
// bar() {
// void* result[10];
// int depth = GetStackFrames(result, 10, 1);
// }
//
// This produces:
// result[0] foo
// result[1] main
// .... ...
//
// "result" must not be NULL.
GOOGLE_GLOG_DLL_DECL int GetStackTrace(void** result, int max_depth, int skip_count);
_END_GOOGLE_NAMESPACE_
#endif // BASE_STACKTRACE_H_

View file

@ -0,0 +1,59 @@
// Copyright (c) 2000 - 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Portable implementation - just use glibc
//
// Note: The glibc implementation may cause a call to malloc.
// This can cause a deadlock in HeapProfiler.
#include <execinfo.h>
#include <string.h>
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
static const int kStackLength = 64;
void * stack[kStackLength];
int size;
size = backtrace(stack, kStackLength);
skip_count++; // we want to skip the current frame as well
int result_count = size - skip_count;
if (result_count < 0)
result_count = 0;
if (result_count > max_depth)
result_count = max_depth;
for (int i = 0; i < result_count; i++)
result[i] = stack[i + skip_count];
return result_count;
}
_END_GOOGLE_NAMESPACE_

View file

@ -0,0 +1,90 @@
// Copyright (c) 2005 - 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Arun Sharma
//
// Produce stack trace using libunwind
#include "utilities.h"
extern "C" {
#define UNW_LOCAL_ONLY
#include <libunwind.h>
}
#include "glog/raw_logging.h"
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
// Sometimes, we can try to get a stack trace from within a stack
// trace, because libunwind can call mmap (maybe indirectly via an
// internal mmap based memory allocator), and that mmap gets trapped
// and causes a stack-trace request. If were to try to honor that
// recursive request, we'd end up with infinite recursion or deadlock.
// Luckily, it's safe to ignore those subsequent traces. In such
// cases, we return 0 to indicate the situation.
// We can use the GCC __thread syntax here since libunwind is not supported on
// Windows.
static __thread bool g_tl_entered; // Initialized to false.
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
void *ip;
int n = 0;
unw_cursor_t cursor;
unw_context_t uc;
if (g_tl_entered) {
return 0;
}
g_tl_entered = true;
unw_getcontext(&uc);
RAW_CHECK(unw_init_local(&cursor, &uc) >= 0, "unw_init_local failed");
skip_count++; // Do not include the "GetStackTrace" frame
while (n < max_depth) {
int ret = unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip);
if (ret < 0)
break;
if (skip_count > 0) {
skip_count--;
} else {
result[n++] = ip;
}
ret = unw_step(&cursor);
if (ret <= 0)
break;
}
g_tl_entered = false;
return n;
}
_END_GOOGLE_NAMESPACE_

View file

@ -0,0 +1,130 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Craig Silverstein
//
// Produce stack trace. I'm guessing (hoping!) the code is much like
// for x86. For apple machines, at least, it seems to be; see
// http://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html
// http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
// Linux has similar code: http://patchwork.ozlabs.org/linuxppc/patch?id=8882
#include <stdio.h>
#include <stdint.h> // for uintptr_t
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
// Given a pointer to a stack frame, locate and return the calling
// stackframe, or return NULL if no stackframe can be found. Perform sanity
// checks (the strictness of which is controlled by the boolean parameter
// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
template<bool STRICT_UNWINDING>
static void **NextStackFrame(void **old_sp) {
void **new_sp = (void **) *old_sp;
// Check that the transition from frame pointer old_sp to frame
// pointer new_sp isn't clearly bogus
if (STRICT_UNWINDING) {
// With the stack growing downwards, older stack frame must be
// at a greater address that the current one.
if (new_sp <= old_sp) return NULL;
// Assume stack frames larger than 100,000 bytes are bogus.
if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL;
} else {
// In the non-strict mode, allow discontiguous stack frames.
// (alternate-signal-stacks for example).
if (new_sp == old_sp) return NULL;
// And allow frames upto about 1MB.
if ((new_sp > old_sp)
&& ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL;
}
if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL;
return new_sp;
}
// This ensures that GetStackTrace stes up the Link Register properly.
void StacktracePowerPCDummyFunction() __attribute__((noinline));
void StacktracePowerPCDummyFunction() { __asm__ volatile(""); }
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
void **sp;
// Apple OS X uses an old version of gnu as -- both Darwin 7.9.0 (Panther)
// and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a
// different asm syntax. I don't know quite the best way to discriminate
// systems using the old as from the new one; I've gone with __APPLE__.
#ifdef __APPLE__
__asm__ volatile ("mr %0,r1" : "=r" (sp));
#else
__asm__ volatile ("mr %0,1" : "=r" (sp));
#endif
// On PowerPC, the "Link Register" or "Link Record" (LR), is a stack
// entry that holds the return address of the subroutine call (what
// instruction we run after our function finishes). This is the
// same as the stack-pointer of our parent routine, which is what we
// want here. While the compiler will always(?) set up LR for
// subroutine calls, it may not for leaf functions (such as this one).
// This routine forces the compiler (at least gcc) to push it anyway.
StacktracePowerPCDummyFunction();
// The LR save area is used by the callee, so the top entry is bogus.
skip_count++;
int n = 0;
while (sp && n < max_depth) {
if (skip_count > 0) {
skip_count--;
} else {
// PowerPC has 3 main ABIs, which say where in the stack the
// Link Register is. For DARWIN and AIX (used by apple and
// linux ppc64), it's in sp[2]. For SYSV (used by linux ppc),
// it's in sp[1].
#if defined(_CALL_AIX) || defined(_CALL_DARWIN)
result[n++] = *(sp+2);
#elif defined(_CALL_SYSV)
result[n++] = *(sp+1);
#elif defined(__APPLE__) || ((defined(__linux) || defined(__linux__)) && defined(__PPC64__))
// This check is in case the compiler doesn't define _CALL_AIX/etc.
result[n++] = *(sp+2);
#elif defined(__linux)
// This check is in case the compiler doesn't define _CALL_SYSV.
result[n++] = *(sp+1);
#else
#error Need to specify the PPC ABI for your archiecture.
#endif
}
// Use strict unwinding rules.
sp = NextStackFrame<true>(sp);
}
return n;
}
_END_GOOGLE_NAMESPACE_

217
src/stacktrace_unittest.cc Normal file
View file

@ -0,0 +1,217 @@
// Copyright (c) 2004, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "utilities.h"
#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include "base/commandlineflags.h"
#include "glog/logging.h"
#include "stacktrace.h"
#ifdef HAVE_EXECINFO_H
# include <execinfo.h>
#endif
using namespace GOOGLE_NAMESPACE;
#ifdef HAVE_STACKTRACE
// Obtain a backtrace, verify that the expected callers are present in the
// backtrace, and maybe print the backtrace to stdout.
// The sequence of functions whose return addresses we expect to see in the
// backtrace.
const int BACKTRACE_STEPS = 6;
struct AddressRange {
const void *start, *end;
};
// Expected function [start,end] range.
AddressRange expected_range[BACKTRACE_STEPS];
#if __GNUC__
// Using GCC extension: address of a label can be taken with '&&label'.
// Start should be a label somewhere before recursive call, end somewhere
// after it.
#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
do { \
(prange)->start = &&start_label; \
(prange)->end = &&end_label; \
CHECK_LT((prange)->start, (prange)->end); \
} while (0)
// This macro expands into "unmovable" code (opaque to GCC), and that
// prevents GCC from moving a_label up or down in the code.
// Without it, there is no code following the 'end' label, and GCC
// (4.3.1, 4.4.0) thinks it safe to assign &&end an address that is before
// the recursive call.
#define DECLARE_ADDRESS_LABEL(a_label) \
a_label: do { __asm__ __volatile__(""); } while (0)
// Gcc 4.4.0 may split function into multiple chunks, and the chunk
// performing recursive call may end up later in the code then the return
// instruction (this actually happens with FDO).
// Adjust function range from __builtin_return_address.
#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \
do { \
void *ra = __builtin_return_address(0); \
CHECK_LT((prange)->start, ra); \
if (ra > (prange)->end) { \
printf("Adjusting range from %p..%p to %p..%p\n", \
(prange)->start, (prange)->end, \
(prange)->start, ra); \
(prange)->end = ra; \
} \
} while (0)
#else
// Assume the Check* functions below are not longer than 256 bytes.
#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
do { \
(prange)->start = reinterpret_cast<const void *>(&fn); \
(prange)->end = reinterpret_cast<const char *>(&fn) + 256; \
} while (0)
#define DECLARE_ADDRESS_LABEL(a_label) do { } while (0)
#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) do { } while (0)
#endif // __GNUC__
//-----------------------------------------------------------------------//
static void CheckRetAddrIsInFunction(void *ret_addr, const AddressRange &range)
{
CHECK_GE(ret_addr, range.start);
CHECK_LE(ret_addr, range.end);
}
//-----------------------------------------------------------------------//
void ATTRIBUTE_NOINLINE CheckStackTrace(int);
static void ATTRIBUTE_NOINLINE CheckStackTraceLeaf(void) {
const int STACK_LEN = 10;
void *stack[STACK_LEN];
int size;
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[1]);
INIT_ADDRESS_RANGE(CheckStackTraceLeaf, start, end, &expected_range[0]);
DECLARE_ADDRESS_LABEL(start);
size = GetStackTrace(stack, STACK_LEN, 0);
printf("Obtained %d stack frames.\n", size);
CHECK_GE(size, 1);
CHECK_LE(size, STACK_LEN);
if (1) {
#ifdef HAVE_EXECINFO_H
char **strings = backtrace_symbols(stack, size);
printf("Obtained %d stack frames.\n", size);
for (int i = 0; i < size; i++)
printf("%s %p\n", strings[i], stack[i]);
printf("CheckStackTrace() addr: %p\n", &CheckStackTrace);
free(strings);
#endif
}
for (int i = 0; i < BACKTRACE_STEPS; i++) {
printf("Backtrace %d: expected: %p..%p actual: %p ... ",
i, expected_range[i].start, expected_range[i].end, stack[i]);
fflush(stdout);
CheckRetAddrIsInFunction(stack[i], expected_range[i]);
printf("OK\n");
}
DECLARE_ADDRESS_LABEL(end);
}
//-----------------------------------------------------------------------//
/* Dummy functions to make the backtrace more interesting. */
static void ATTRIBUTE_NOINLINE CheckStackTrace4(int i) {
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[2]);
INIT_ADDRESS_RANGE(CheckStackTrace4, start, end, &expected_range[1]);
DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTraceLeaf();
DECLARE_ADDRESS_LABEL(end);
}
static void ATTRIBUTE_NOINLINE CheckStackTrace3(int i) {
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[3]);
INIT_ADDRESS_RANGE(CheckStackTrace3, start, end, &expected_range[2]);
DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTrace4(j);
DECLARE_ADDRESS_LABEL(end);
}
static void ATTRIBUTE_NOINLINE CheckStackTrace2(int i) {
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[4]);
INIT_ADDRESS_RANGE(CheckStackTrace2, start, end, &expected_range[3]);
DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTrace3(j);
DECLARE_ADDRESS_LABEL(end);
}
static void ATTRIBUTE_NOINLINE CheckStackTrace1(int i) {
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[5]);
INIT_ADDRESS_RANGE(CheckStackTrace1, start, end, &expected_range[4]);
DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTrace2(j);
DECLARE_ADDRESS_LABEL(end);
}
#ifndef __GNUC__
// On non-GNU environment, we use the address of `CheckStackTrace` to
// guess the address range of this function. This guess is wrong for
// non-static function on Windows. This is probably because
// `&CheckStackTrace` returns the address of a trampoline like PLT,
// not the actual address of `CheckStackTrace`.
// See https://github.com/google/glog/issues/421 for the detail.
static
#endif
void ATTRIBUTE_NOINLINE CheckStackTrace(int i) {
INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]);
DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTrace1(j);
DECLARE_ADDRESS_LABEL(end);
}
//-----------------------------------------------------------------------//
int main(int, char ** argv) {
FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]);
CheckStackTrace(0);
printf("PASS\n");
return 0;
}
#else
int main() {
printf("PASS (no stacktrace support)\n");
return 0;
}
#endif // HAVE_STACKTRACE

View file

@ -0,0 +1,50 @@
// Copyright (c) 2000 - 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Andrew Schwartzmeyer
//
// Windows implementation - just use CaptureStackBackTrace
#include "config.h"
#include "port.h"
#include "stacktrace.h"
#include <dbghelp.h>
_START_GOOGLE_NAMESPACE_
int GetStackTrace(void** result, int max_depth, int skip_count) {
if (max_depth > 64) {
max_depth = 64;
}
skip_count++; // we want to skip the current frame as well
// This API is thread-safe (moreover it walks only the current thread).
return CaptureStackBackTrace(skip_count, max_depth, result, NULL);
}
_END_GOOGLE_NAMESPACE_

146
src/stacktrace_x86-inl.h Normal file
View file

@ -0,0 +1,146 @@
// Copyright (c) 2000 - 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Produce stack trace
#include <stdint.h> // for uintptr_t
#include "utilities.h" // for OS_* macros
#if !defined(OS_WINDOWS)
#include <unistd.h>
#include <sys/mman.h>
#endif
#include <stdio.h> // for NULL
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
// Given a pointer to a stack frame, locate and return the calling
// stackframe, or return NULL if no stackframe can be found. Perform sanity
// checks (the strictness of which is controlled by the boolean parameter
// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
template<bool STRICT_UNWINDING>
static void **NextStackFrame(void **old_sp) {
void **new_sp = (void **) *old_sp;
// Check that the transition from frame pointer old_sp to frame
// pointer new_sp isn't clearly bogus
if (STRICT_UNWINDING) {
// With the stack growing downwards, older stack frame must be
// at a greater address that the current one.
if (new_sp <= old_sp) return NULL;
// Assume stack frames larger than 100,000 bytes are bogus.
if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL;
} else {
// In the non-strict mode, allow discontiguous stack frames.
// (alternate-signal-stacks for example).
if (new_sp == old_sp) return NULL;
// And allow frames upto about 1MB.
if ((new_sp > old_sp)
&& ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL;
}
if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL;
#ifdef __i386__
// On 64-bit machines, the stack pointer can be very close to
// 0xffffffff, so we explicitly check for a pointer into the
// last two pages in the address space
if ((uintptr_t)new_sp >= 0xffffe000) return NULL;
#endif
#if !defined(OS_WINDOWS)
if (!STRICT_UNWINDING) {
// Lax sanity checks cause a crash in 32-bit tcmalloc/crash_reason_test
// on AMD-based machines with VDSO-enabled kernels.
// Make an extra sanity check to insure new_sp is readable.
// Note: NextStackFrame<false>() is only called while the program
// is already on its last leg, so it's ok to be slow here.
static int page_size = getpagesize();
void *new_sp_aligned = (void *)((uintptr_t)new_sp & ~(page_size - 1));
if (msync(new_sp_aligned, page_size, MS_ASYNC) == -1)
return NULL;
}
#endif
return new_sp;
}
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
void **sp;
#ifdef __GNUC__
#if __GNUC__ * 100 + __GNUC_MINOR__ >= 402
#define USE_BUILTIN_FRAME_ADDRESS
#endif
#endif
#ifdef USE_BUILTIN_FRAME_ADDRESS
sp = reinterpret_cast<void**>(__builtin_frame_address(0));
#elif defined(__i386__)
// Stack frame format:
// sp[0] pointer to previous frame
// sp[1] caller address
// sp[2] first argument
// ...
sp = (void **)&result - 2;
#elif defined(__x86_64__)
// __builtin_frame_address(0) can return the wrong address on gcc-4.1.0-k8
unsigned long rbp;
// Move the value of the register %rbp into the local variable rbp.
// We need 'volatile' to prevent this instruction from getting moved
// around during optimization to before function prologue is done.
// An alternative way to achieve this
// would be (before this __asm__ instruction) to call Noop() defined as
// static void Noop() __attribute__ ((noinline)); // prevent inlining
// static void Noop() { asm(""); } // prevent optimizing-away
__asm__ volatile ("mov %%rbp, %0" : "=r" (rbp));
// Arguments are passed in registers on x86-64, so we can't just
// offset from &result
sp = (void **) rbp;
#endif
int n = 0;
while (sp && n < max_depth) {
if (*(sp+1) == (void *)0) {
// In 64-bit code, we often see a frame that
// points to itself and has a return address of 0.
break;
}
if (skip_count > 0) {
skip_count--;
} else {
result[n++] = *(sp+1);
}
// Use strict unwinding rules.
sp = NextStackFrame<true>(sp);
}
return n;
}
_END_GOOGLE_NAMESPACE_

105
src/stacktrace_x86_64-inl.h Normal file
View file

@ -0,0 +1,105 @@
// Copyright (c) 2005 - 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Arun Sharma
//
// Produce stack trace using libgcc
extern "C" {
#include <stdlib.h> // for NULL
#include <unwind.h> // ABI defined unwinder
}
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
typedef struct {
void **result;
int max_depth;
int skip_count;
int count;
} trace_arg_t;
// Workaround for the malloc() in _Unwind_Backtrace() issue.
static _Unwind_Reason_Code nop_backtrace(struct _Unwind_Context *uc, void *opq) {
return _URC_NO_REASON;
}
// This code is not considered ready to run until
// static initializers run so that we are guaranteed
// that any malloc-related initialization is done.
static bool ready_to_run = false;
class StackTraceInit {
public:
StackTraceInit() {
// Extra call to force initialization
_Unwind_Backtrace(nop_backtrace, NULL);
ready_to_run = true;
}
};
static StackTraceInit module_initializer; // Force initialization
static _Unwind_Reason_Code GetOneFrame(struct _Unwind_Context *uc, void *opq) {
trace_arg_t *targ = (trace_arg_t *) opq;
if (targ->skip_count > 0) {
targ->skip_count--;
} else {
targ->result[targ->count++] = (void *) _Unwind_GetIP(uc);
}
if (targ->count == targ->max_depth)
return _URC_END_OF_STACK;
return _URC_NO_REASON;
}
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
if (!ready_to_run)
return 0;
trace_arg_t targ;
skip_count += 1; // Do not include the "GetStackTrace" frame
targ.result = result;
targ.max_depth = max_depth;
targ.skip_count = skip_count;
targ.count = 0;
_Unwind_Backtrace(GetOneFrame, &targ);
return targ.count;
}
_END_GOOGLE_NAMESPACE_

197
src/stl_logging_unittest.cc Normal file
View file

@ -0,0 +1,197 @@
// Copyright (c) 2003, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "config.h"
#ifdef HAVE_USING_OPERATOR
#include <functional>
#include <iostream>
#include <map>
#include <ostream>
#include <string>
#include <vector>
#ifdef __GNUC__
// C++0x isn't enabled by default in GCC and libc++ does not have
// non-standard ext/* and tr1/unordered_*.
# if defined(_LIBCPP_VERSION)
# ifndef GLOG_STL_LOGGING_FOR_UNORDERED
# define GLOG_STL_LOGGING_FOR_UNORDERED
# endif
# else
# ifndef GLOG_STL_LOGGING_FOR_EXT_HASH
# define GLOG_STL_LOGGING_FOR_EXT_HASH
# endif
# ifndef GLOG_STL_LOGGING_FOR_EXT_SLIST
# define GLOG_STL_LOGGING_FOR_EXT_SLIST
# endif
# ifndef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
# define GLOG_STL_LOGGING_FOR_TR1_UNORDERED
# endif
# endif
#endif
#include "glog/logging.h"
#include "glog/stl_logging.h"
#include "googletest.h"
using namespace std;
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
using namespace __gnu_cxx;
#endif
struct user_hash {
size_t operator()(int x) const { return x; }
};
static void TestSTLLogging() {
{
// Test a sequence.
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
ostringstream ss;
ss << v;
EXPECT_EQ(ss.str(), "10 20 30");
vector<int> copied_v(v);
CHECK_EQ(v, copied_v); // This must compile.
}
{
// Test a sorted pair associative container.
map< int, string > m;
m[20] = "twenty";
m[10] = "ten";
m[30] = "thirty";
ostringstream ss;
ss << m;
EXPECT_EQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)");
map< int, string > copied_m(m);
CHECK_EQ(m, copied_m); // This must compile.
}
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
{
// Test a hashed simple associative container.
hash_set<int> hs;
hs.insert(10);
hs.insert(20);
hs.insert(30);
ostringstream ss;
ss << hs;
EXPECT_EQ(ss.str(), "10 20 30");
hash_set<int> copied_hs(hs);
CHECK_EQ(hs, copied_hs); // This must compile.
}
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
{
// Test a hashed pair associative container.
hash_map<int, string> hm;
hm[10] = "ten";
hm[20] = "twenty";
hm[30] = "thirty";
ostringstream ss;
ss << hm;
EXPECT_EQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)");
hash_map<int, string> copied_hm(hm);
CHECK_EQ(hm, copied_hm); // this must compile
}
#endif
{
// Test a long sequence.
vector<int> v;
string expected;
for (int i = 0; i < 100; i++) {
v.push_back(i);
if (i > 0) expected += ' ';
char buf[256];
sprintf(buf, "%d", i);
expected += buf;
}
v.push_back(100);
expected += " ...";
ostringstream ss;
ss << v;
CHECK_EQ(ss.str(), expected.c_str());
}
{
// Test a sorted pair associative container.
// Use a non-default comparison functor.
map< int, string, greater<int> > m;
m[20] = "twenty";
m[10] = "ten";
m[30] = "thirty";
ostringstream ss;
ss << m;
EXPECT_EQ(ss.str(), "(30, thirty) (20, twenty) (10, ten)");
map< int, string, greater<int> > copied_m(m);
CHECK_EQ(m, copied_m); // This must compile.
}
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
{
// Test a hashed simple associative container.
// Use a user defined hash function.
hash_set<int, user_hash> hs;
hs.insert(10);
hs.insert(20);
hs.insert(30);
ostringstream ss;
ss << hs;
EXPECT_EQ(ss.str(), "10 20 30");
hash_set<int, user_hash> copied_hs(hs);
CHECK_EQ(hs, copied_hs); // This must compile.
}
#endif
}
int main(int, char**) {
TestSTLLogging();
std::cout << "PASS\n";
return 0;
}
#else
#include <iostream>
int main(int, char**) {
std::cout << "We don't support stl_logging for this compiler.\n"
<< "(we need compiler support of 'using ::operator<<' "
<< "for this feature.)\n";
return 0;
}
#endif // HAVE_USING_OPERATOR

Some files were not shown because too many files have changed in this diff Show more