Merge to upstream r350972.

Test: ./run_tests.py --bitness 32
Test: ./run_tests.py --bitness 64
Test: ./run_tests.py --bitness 64 --host
Bug: None
Change-Id: I96552544c8305853be519855982caf716930519e
This commit is contained in:
Dan Albert
2019-01-11 14:07:42 -08:00
404 changed files with 8700 additions and 1735 deletions

180
utils/ci/macos-backdeployment.sh Executable file
View File

@@ -0,0 +1,180 @@
#!/usr/bin/env bash
set -ue
function usage() {
cat <<EOM
$(basename ${0}) [-h|--help] --libcxx-root <LIBCXX-ROOT> --libcxxabi-root <LIBCXXABI-ROOT> --std <STD> --arch <ARCHITECTURE> --deployment-target <TARGET> --sdk-version <SDK-VERSION> [--lit-args <ARGS...>]
This script is used to continually test the back-deployment use case of libc++ and libc++abi on MacOS.
--libcxx-root Full path to the root of the libc++ repository to test.
--libcxxabi-root Full path to the root of the libc++abi repository to test.
--std Version of the C++ Standard to run the tests under (c++03, c++11, etc..).
--arch Architecture to build the tests for (32, 64).
--deployment-target The deployment target to run the tests for. This should be a version number of MacOS (e.g. 10.12). All MacOS versions until and including 10.7 are supported.
--sdk-version The version of the SDK to test with. This should be a version number of MacOS (e.g. 10.12). We'll link against the libc++ dylib in that SDK, but we'll run against the one on the given deployment target.
[--lit-args] Additional arguments to pass to lit (optional). If there are multiple arguments, quote them to pass them as a single argument to this script.
[--no-cleanup] Do not cleanup the temporary directory that was used for testing at the end. This can be useful to debug failures. Make sure to clean up manually after.
[-h, --help] Print this help.
EOM
}
while [[ $# -gt 0 ]]; do
case "$1" in
--libcxx-root)
LIBCXX_ROOT="${2}"
if [[ ! -d "${LIBCXX_ROOT}" ]]; then
echo "--libcxx-root '${LIBCXX_ROOT}' is not a valid directory"
usage
exit 1
fi
shift; shift
;;
--libcxxabi-root)
LIBCXXABI_ROOT="${2}"
if [[ ! -d "${LIBCXXABI_ROOT}" ]]; then
echo "--libcxxabi-root '${LIBCXXABI_ROOT}' is not a valid directory"
usage
exit 1
fi
shift; shift
;;
--std)
STD="${2}"
shift; shift
;;
--arch)
ARCH="${2}"
shift; shift
;;
--deployment-target)
DEPLOYMENT_TARGET="${2}"
shift; shift
;;
--sdk-version)
MACOS_SDK_VERSION="${2}"
shift; shift
;;
--lit-args)
ADDITIONAL_LIT_ARGS="${2}"
shift; shift
;;
--no-cleanup)
NO_CLEANUP=""
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "${1} is not a supported argument"
usage
exit 1
;;
esac
done
if [[ -z ${LIBCXX_ROOT+x} ]]; then echo "--libcxx-root is a required parameter"; usage; exit 1; fi
if [[ -z ${LIBCXXABI_ROOT+x} ]]; then echo "--libcxxabi-root is a required parameter"; usage; exit 1; fi
if [[ -z ${STD+x} ]]; then echo "--std is a required parameter"; usage; exit 1; fi
if [[ -z ${ARCH+x} ]]; then echo "--arch is a required parameter"; usage; exit 1; fi
if [[ -z ${DEPLOYMENT_TARGET+x} ]]; then echo "--deployment-target is a required parameter"; usage; exit 1; fi
if [[ -z ${MACOS_SDK_VERSION+x} ]]; then echo "--sdk-version is a required parameter"; usage; exit 1; fi
if [[ -z ${ADDITIONAL_LIT_ARGS+x} ]]; then ADDITIONAL_LIT_ARGS=""; fi
TEMP_DIR="$(mktemp -d)"
echo "Created temporary directory ${TEMP_DIR}"
function cleanup {
if [[ -z ${NO_CLEANUP+x} ]]; then
echo "Removing temporary directory ${TEMP_DIR}"
rm -rf "${TEMP_DIR}"
else
echo "Temporary directory is at '${TEMP_DIR}', make sure to clean it up yourself"
fi
}
trap cleanup EXIT
LLVM_ROOT="${TEMP_DIR}/llvm"
LIBCXX_BUILD_DIR="${TEMP_DIR}/libcxx-build"
LIBCXX_INSTALL_DIR="${TEMP_DIR}/libcxx-install"
LIBCXXABI_BUILD_DIR="${TEMP_DIR}/libcxxabi-build"
LIBCXXABI_INSTALL_DIR="${TEMP_DIR}/libcxxabi-install"
PREVIOUS_DYLIBS_URL="http://lab.llvm.org:8080/roots/libcxx-roots.tar.gz"
LLVM_TARBALL_URL="https://github.com/llvm-mirror/llvm/archive/master.tar.gz"
export CC="$(xcrun --find clang)"
export CXX="$(xcrun --find clang++)"
echo "@@@ Downloading LLVM tarball of master (only used for CMake configuration) @@@"
mkdir "${LLVM_ROOT}"
curl -L "${LLVM_TARBALL_URL}" | tar -xz --strip-components=1 -C "${LLVM_ROOT}"
echo "@@@@@@"
echo "@@@ Configuring architecture-related stuff @@@"
if [[ "${ARCH}" == "64" ]]; then CMAKE_ARCH_STRING="x86_64"; else CMAKE_ARCH_STRING="i386"; fi
if [[ "${ARCH}" == "64" ]]; then LIT_ARCH_STRING=""; else LIT_ARCH_STRING="--param=enable_32bit=true"; fi
echo "@@@@@@"
echo "@@@ Configuring CMake for libc++ @@@"
mkdir -p "${LIBCXX_BUILD_DIR}"
(cd "${LIBCXX_BUILD_DIR}" &&
xcrun cmake "${LIBCXX_ROOT}" -GNinja \
-DLLVM_PATH="${LLVM_ROOT}" \
-DCMAKE_INSTALL_PREFIX="${LIBCXX_INSTALL_DIR}" \
-DCMAKE_OSX_ARCHITECTURES="${CMAKE_ARCH_STRING}"
)
echo "@@@@@@"
echo "@@@ Configuring CMake for libc++abi @@@"
mkdir -p "${LIBCXXABI_BUILD_DIR}"
(cd "${LIBCXXABI_BUILD_DIR}" &&
xcrun cmake "${LIBCXXABI_ROOT}" -GNinja \
-DLIBCXXABI_LIBCXX_PATH="${LIBCXX_ROOT}" \
-DLLVM_PATH="${LLVM_ROOT}" \
-DCMAKE_INSTALL_PREFIX="${LIBCXXABI_INSTALL_DIR}" \
-DCMAKE_OSX_ARCHITECTURES="${CMAKE_ARCH_STRING}"
)
echo "@@@@@@"
echo "@@@ Installing the latest libc++ headers @@@"
ninja -C "${LIBCXX_BUILD_DIR}" install-cxx-headers
echo "@@@@@@"
echo "@@@ Downloading dylibs for older deployment targets @@@"
# TODO: The tarball should contain libc++abi.dylib too, we shouldn't be relying on the system's
# TODO: We should also link against the libc++abi.dylib that was shipped in the SDK
PREVIOUS_DYLIBS_DIR="${TEMP_DIR}/libcxx-dylibs"
mkdir "${PREVIOUS_DYLIBS_DIR}"
curl "${PREVIOUS_DYLIBS_URL}" | tar -xz --strip-components=1 -C "${PREVIOUS_DYLIBS_DIR}"
LIBCXX_ON_DEPLOYMENT_TARGET="${PREVIOUS_DYLIBS_DIR}/macOS/${DEPLOYMENT_TARGET}/libc++.dylib"
LIBCXXABI_ON_DEPLOYMENT_TARGET="/usr/lib/libc++abi.dylib"
LIBCXX_IN_SDK="${PREVIOUS_DYLIBS_DIR}/macOS/${MACOS_SDK_VERSION}/libc++.dylib"
echo "@@@@@@"
# TODO: We need to also run the tests for libc++abi.
# TODO: Make sure lit will actually run against the libc++abi we specified
echo "@@@ Running tests for libc++ @@@"
"${LIBCXX_BUILD_DIR}/bin/llvm-lit" -sv "${LIBCXX_ROOT}/test" \
--param=enable_experimental=false \
--param=enable_filesystem=false \
${LIT_ARCH_STRING} \
--param=cxx_under_test="${CXX}" \
--param=cxx_headers="${LIBCXX_INSTALL_DIR}/include/c++/v1" \
--param=std="${STD}" \
--param=platform="macosx${DEPLOYMENT_TARGET}" \
--param=cxx_runtime_root="$(dirname "${LIBCXX_ON_DEPLOYMENT_TARGET}")" \
--param=abi_library_path="$(dirname "${LIBCXXABI_ON_DEPLOYMENT_TARGET}")" \
--param=use_system_cxx_lib="$(dirname "${LIBCXX_IN_SDK}")" \
${ADDITIONAL_LIT_ARGS}
echo "@@@@@@"

153
utils/ci/macos-trunk.sh Executable file
View File

@@ -0,0 +1,153 @@
#!/usr/bin/env bash
set -ue
function usage() {
cat <<EOM
$(basename ${0}) [-h|--help] --libcxx-root <LIBCXX-ROOT> --libcxxabi-root <LIBCXXABI-ROOT> --std <STD> --arch <ARCHITECTURE> [--lit-args <ARGS...>]
This script is used to continually test libc++ and libc++abi trunk on MacOS.
--libcxx-root Full path to the root of the libc++ repository to test.
--libcxxabi-root Full path to the root of the libc++abi repository to test.
--std Version of the C++ Standard to run the tests under (c++03, c++11, etc..).
--arch Architecture to build the tests for (32, 64).
[--lit-args] Additional arguments to pass to lit (optional). If there are multiple arguments, quote them to pass them as a single argument to this script.
[--no-cleanup] Do not cleanup the temporary directory that was used for testing at the end. This can be useful to debug failures. Make sure to clean up manually after.
[-h, --help] Print this help.
EOM
}
while [[ $# -gt 0 ]]; do
case "$1" in
--libcxx-root)
LIBCXX_ROOT="${2}"
if [[ ! -e "${LIBCXX_ROOT}" ]]; then
echo "--libcxx-root '${LIBCXX_ROOT}' is not a valid directory"
usage
exit 1
fi
shift; shift
;;
--libcxxabi-root)
LIBCXXABI_ROOT="${2}"
if [[ ! -e "${LIBCXXABI_ROOT}" ]]; then
echo "--libcxxabi-root '${LIBCXXABI_ROOT}' is not a valid directory"
usage
exit 1
fi
shift; shift
;;
--std)
STD="${2}"
shift; shift
;;
--arch)
ARCH="${2}"
shift; shift
;;
--lit-args)
ADDITIONAL_LIT_ARGS="${2}"
shift; shift
;;
--no-cleanup)
NO_CLEANUP=""
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "${1} is not a supported argument"
usage
exit 1
;;
esac
done
if [[ -z ${LIBCXX_ROOT+x} ]]; then echo "--libcxx-root is a required parameter"; usage; exit 1; fi
if [[ -z ${LIBCXXABI_ROOT+x} ]]; then echo "--libcxxabi-root is a required parameter"; usage; exit 1; fi
if [[ -z ${STD+x} ]]; then echo "--std is a required parameter"; usage; exit 1; fi
if [[ -z ${ARCH+x} ]]; then echo "--arch is a required parameter"; usage; exit 1; fi
if [[ -z ${ADDITIONAL_LIT_ARGS+x} ]]; then ADDITIONAL_LIT_ARGS=""; fi
TEMP_DIR="$(mktemp -d)"
echo "Created temporary directory ${TEMP_DIR}"
function cleanup {
if [[ -z ${NO_CLEANUP+x} ]]; then
echo "Removing temporary directory ${TEMP_DIR}"
rm -rf "${TEMP_DIR}"
else
echo "Temporary directory is at '${TEMP_DIR}', make sure to clean it up yourself"
fi
}
trap cleanup EXIT
LLVM_ROOT="${TEMP_DIR}/llvm"
LIBCXX_BUILD_DIR="${TEMP_DIR}/libcxx-build"
LIBCXX_INSTALL_DIR="${TEMP_DIR}/libcxx-install"
LIBCXXABI_BUILD_DIR="${TEMP_DIR}/libcxxabi-build"
LIBCXXABI_INSTALL_DIR="${TEMP_DIR}/libcxxabi-install"
LLVM_TARBALL_URL="https://github.com/llvm-mirror/llvm/archive/master.tar.gz"
export CC="$(xcrun --find clang)"
export CXX="$(xcrun --find clang++)"
echo "@@@ Downloading LLVM tarball of master (only used for CMake configuration) @@@"
mkdir "${LLVM_ROOT}"
curl -L "${LLVM_TARBALL_URL}" | tar -xz --strip-components=1 -C "${LLVM_ROOT}"
echo "@@@@@@"
echo "@@@ Setting up LIT flags @@@"
LIT_FLAGS="-sv --param=std=${STD} ${ADDITIONAL_LIT_ARGS}"
if [[ "${ARCH}" == "32" ]]; then
LIT_FLAGS+=" --param=enable_32bit=true"
fi
echo "@@@@@@"
echo "@@@ Configuring CMake for libc++ @@@"
mkdir -p "${LIBCXX_BUILD_DIR}"
(cd "${LIBCXX_BUILD_DIR}" &&
xcrun cmake "${LIBCXX_ROOT}" -GNinja \
-DLLVM_PATH="${LLVM_ROOT}" \
-DCMAKE_INSTALL_PREFIX="${LIBCXX_INSTALL_DIR}" \
-DLLVM_LIT_ARGS="${LIT_FLAGS}" \
-DCMAKE_OSX_ARCHITECTURES="i386;x86_64" # Build a universal dylib
)
echo "@@@@@@"
echo "@@@ Configuring CMake for libc++abi @@@"
mkdir -p "${LIBCXXABI_BUILD_DIR}"
(cd "${LIBCXXABI_BUILD_DIR}" &&
xcrun cmake "${LIBCXXABI_ROOT}" -GNinja \
-DLIBCXXABI_LIBCXX_PATH="${LIBCXX_ROOT}" \
-DLLVM_PATH="${LLVM_ROOT}" \
-DCMAKE_INSTALL_PREFIX="${LIBCXXABI_INSTALL_DIR}" \
-DLLVM_LIT_ARGS="${LIT_FLAGS}" \
-DCMAKE_OSX_ARCHITECTURES="i386;x86_64" # Build a universal dylib
)
echo "@@@@@@"
echo "@@@ Building libc++.dylib and libc++abi.dylib from sources (just to make sure it works) @@@"
ninja -C "${LIBCXX_BUILD_DIR}" install-cxx
ninja -C "${LIBCXXABI_BUILD_DIR}" install-cxxabi
echo "@@@@@@"
echo "@@@ Running tests for libc++ @@@"
# TODO: We should run check-cxx-abilist too
ninja -C "${LIBCXX_BUILD_DIR}" check-cxx
echo "@@@@@@"
echo "@@@ Running tests for libc++abi @@@"
ninja -C "${LIBCXXABI_BUILD_DIR}" check-cxxabi
echo "@@@@@@"

View File

@@ -109,5 +109,7 @@ RUN apt-get install -y --no-install-recommends \
python \
buildbot-slave
ADD scripts /libcxx-scripts/
RUN /libcxx-scripts/install_clang_packages.sh
ADD scripts/install_clang_packages.sh /tmp/install_clang_packages.sh
RUN /tmp/install_clang_packages.sh && rm /tmp/install_clang_packages.sh
RUN git clone https://git.llvm.org/git/libcxx.git /libcxx

View File

@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -x
# Update the libc++ sources in the image in order to use the most recent version of
# run_buildbots.sh
cd /libcxx
git pull
/libcxx/utils/docker/scripts/run_buildbot.sh "$@"

View File

@@ -12,6 +12,13 @@ mkdir -p $BOT_DIR
apt-get update -y
apt-get upgrade -y
# FIXME(EricWF): Remove this hack. It's only in place to temporarily fix linking libclang_rt from the
# debian packages.
# WARNING: If you're not a buildbot, DO NOT RUN!
apt-get install lld-8
rm /usr/bin/ld
ln -s /usr/bin/lld-8 /usr/bin/ld
systemctl set-property buildslave.service TasksMax=100000
buildslave stop $BOT_DIR

View File

@@ -1,42 +0,0 @@
licenses(["notice"])
config_setting(
name = "windows",
values = {
"cpu": "x64_windows",
},
visibility = [":__subpackages__"],
)
cc_library(
name = "benchmark",
srcs = glob(
[
"src/*.cc",
"src/*.h",
],
exclude = ["src/benchmark_main.cc"],
),
hdrs = ["include/benchmark/benchmark.h"],
linkopts = select({
":windows": ["-DEFAULTLIB:shlwapi.lib"],
"//conditions:default": ["-pthread"],
}),
strip_include_prefix = "include",
visibility = ["//visibility:public"],
)
cc_library(
name = "benchmark_main",
srcs = ["src/benchmark_main.cc"],
hdrs = ["include/benchmark/benchmark.h"],
strip_include_prefix = "include",
visibility = ["//visibility:public"],
deps = [":benchmark"],
)
cc_library(
name = "benchmark_internal_headers",
hdrs = glob(["src/*.h"]),
visibility = ["//test:__pkg__"],
)

View File

@@ -27,6 +27,7 @@ Arne Beer <arne@twobeer.de>
Billy Robert O'Neal III <billy.oneal@gmail.com> <bion@microsoft.com>
Chris Kennelly <ckennelly@google.com> <ckennelly@ckennelly.com>
Christopher Seymour <chris.j.seymour@hotmail.com>
Cyrille Faucheux <cyrille.faucheux@gmail.com>
David Coeurjolly <david.coeurjolly@liris.cnrs.fr>
Deniz Evrenci <denizevrenci@gmail.com>
Dominic Hamon <dma@stripysock.com> <dominic@google.com>

View File

@@ -255,7 +255,7 @@ that might be used to customize high-order term calculation.
```c++
BENCHMARK(BM_StringCompare)->RangeMultiplier(2)
->Range(1<<10, 1<<18)->Complexity([](int n)->double{return n; });
->Range(1<<10, 1<<18)->Complexity([](int64_t n)->double{return n; });
```
### Templated benchmarks
@@ -264,7 +264,7 @@ messages of size `sizeof(v)` `range_x` times. It also outputs throughput in the
absence of multiprogramming.
```c++
template <class Q> int BM_Sequential(benchmark::State& state) {
template <class Q> void BM_Sequential(benchmark::State& state) {
Q q;
typename Q::value_type v;
for (auto _ : state) {
@@ -428,6 +428,26 @@ BENCHMARK(BM_test)->Range(8, 8<<10)->UseRealTime();
Without `UseRealTime`, CPU time is used by default.
## Controlling timers
Normally, the entire duration of the work loop (`for (auto _ : state) {}`)
is measured. But sometimes, it is nessesary to do some work inside of
that loop, every iteration, but without counting that time to the benchmark time.
That is possible, althought it is not recommended, since it has high overhead.
```c++
static void BM_SetInsert_With_Timer_Control(benchmark::State& state) {
std::set<int> data;
for (auto _ : state) {
state.PauseTiming(); // Stop timers. They will not count until they are resumed.
data = ConstructRandomSet(state.range(0)); // Do something that should not be measured
state.ResumeTiming(); // And resume timers. They are now counting again.
// The rest will be measured.
for (int j = 0; j < state.range(1); ++j)
data.insert(RandomNumber());
}
}
BENCHMARK(BM_SetInsert_With_Timer_Control)->Ranges({{1<<10, 8<<10}, {128, 512}});
```
## Manual timing
For benchmarking something for which neither CPU time nor real-time are

View File

@@ -1293,6 +1293,15 @@ struct CPUInfo {
BENCHMARK_DISALLOW_COPY_AND_ASSIGN(CPUInfo);
};
//Adding Struct for System Information
struct SystemInfo {
std::string name;
static const SystemInfo& Get();
private:
SystemInfo();
BENCHMARK_DISALLOW_COPY_AND_ASSIGN(SystemInfo);
};
// Interface for custom benchmark result printers.
// By default, benchmark reports are printed to stdout. However an application
// can control the destination of the reports by calling
@@ -1302,6 +1311,7 @@ class BenchmarkReporter {
public:
struct Context {
CPUInfo const& cpu_info;
SystemInfo const& sys_info;
// The number of chars in the longest benchmark name.
size_t name_field_width;
static const char* executable_name;

View File

@@ -57,9 +57,9 @@ DEFINE_bool(benchmark_list_tests, false,
DEFINE_string(benchmark_filter, ".",
"A regular expression that specifies the set of benchmarks "
"to execute. If this flag is empty, no benchmarks are run. "
"If this flag is the string \"all\", all benchmarks linked "
"into the process are run.");
"to execute. If this flag is empty, or if this flag is the "
"string \"all\", all benchmarks linked into the binary are "
"run.");
DEFINE_double(benchmark_min_time, 0.5,
"Minimum number of seconds we should run benchmark before "

View File

@@ -182,14 +182,19 @@ bool BenchmarkFamilies::FindBenchmarks(
}
}
instance.name += StrFormat("%d", arg);
// we know that the args are always non-negative (see 'AddRange()'),
// thus print as 'unsigned'. BUT, do a cast due to the 32-bit builds.
instance.name += StrFormat("%lu", static_cast<unsigned long>(arg));
++arg_i;
}
if (!IsZero(family->min_time_))
instance.name += StrFormat("/min_time:%0.3f", family->min_time_);
if (family->iterations_ != 0)
instance.name += StrFormat("/iterations:%d", family->iterations_);
if (family->iterations_ != 0) {
instance.name +=
StrFormat("/iterations:%lu",
static_cast<unsigned long>(family->iterations_));
}
if (family->repetitions_ != 0)
instance.name += StrFormat("/repeats:%d", family->repetitions_);

View File

@@ -73,8 +73,8 @@ std::string GetBigOString(BigO complexity) {
// - time : Vector containing the times for the benchmark tests.
// - fitting_curve : lambda expression (e.g. [](int64_t n) {return n; };).
// For a deeper explanation on the algorithm logic, look the README file at
// http://github.com/ismaelJimenez/Minimal-Cpp-Least-Squared-Fit
// For a deeper explanation on the algorithm logic, please refer to
// https://en.wikipedia.org/wiki/Least_squares#Least_squares,_regression_analysis_and_statistics
LeastSq MinimalLeastSq(const std::vector<int64_t>& n,
const std::vector<double>& time,

View File

@@ -53,7 +53,7 @@ bool ConsoleReporter::ReportContext(const Context& context) {
}
void ConsoleReporter::PrintHeader(const Run& run) {
std::string str = FormatString("%-*s %13s %13s %10s", static_cast<int>(name_field_width_),
std::string str = FormatString("%-*s %13s %15s %12s", static_cast<int>(name_field_width_),
"Benchmark", "Time", "CPU", "Iterations");
if(!run.counters.empty()) {
if(output_options_ & OO_Tabular) {
@@ -98,6 +98,21 @@ static void IgnoreColorPrint(std::ostream& out, LogColor, const char* fmt,
va_end(args);
}
static std::string FormatTime(double time) {
// Align decimal places...
if (time < 1.0) {
return FormatString("%10.3f", time);
}
if (time < 10.0) {
return FormatString("%10.2f", time);
}
if (time < 100.0) {
return FormatString("%10.1f", time);
}
return FormatString("%10.0f", time);
}
void ConsoleReporter::PrintRunData(const Run& result) {
typedef void(PrinterFn)(std::ostream&, LogColor, const char*, ...);
auto& Out = GetOutputStream();
@@ -117,18 +132,21 @@ void ConsoleReporter::PrintRunData(const Run& result) {
const double real_time = result.GetAdjustedRealTime();
const double cpu_time = result.GetAdjustedCPUTime();
const std::string real_time_str = FormatTime(real_time);
const std::string cpu_time_str = FormatTime(cpu_time);
if (result.report_big_o) {
std::string big_o = GetBigOString(result.complexity);
printer(Out, COLOR_YELLOW, "%10.2f %s %10.2f %s ", real_time, big_o.c_str(),
printer(Out, COLOR_YELLOW, "%10.2f %-4s %10.2f %-4s ", real_time, big_o.c_str(),
cpu_time, big_o.c_str());
} else if (result.report_rms) {
printer(Out, COLOR_YELLOW, "%10.0f %% %10.0f %% ", real_time * 100,
cpu_time * 100);
printer(Out, COLOR_YELLOW, "%10.0f %-4s %10.0f %-4s ", real_time * 100, "%",
cpu_time * 100, "%");
} else {
const char* timeLabel = GetTimeUnitString(result.time_unit);
printer(Out, COLOR_YELLOW, "%10.0f %s %10.0f %s ", real_time, timeLabel,
cpu_time, timeLabel);
printer(Out, COLOR_YELLOW, "%s %-4s %s %-4s ", real_time_str.c_str(), timeLabel,
cpu_time_str.c_str(), timeLabel);
}
if (!result.report_big_o && !result.report_rms) {

View File

@@ -77,6 +77,8 @@ bool JSONReporter::ReportContext(const Context& context) {
std::string walltime_value = LocalDateTimeString();
out << indent << FormatKV("date", walltime_value) << ",\n";
out << indent << FormatKV("host_name", context.sys_info.name) << ",\n";
if (Context::executable_name) {
// windows uses backslash for its path separator,
// which must be escaped in JSON otherwise it blows up conforming JSON

View File

@@ -79,7 +79,8 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out,
// No initializer because it's already initialized to NULL.
const char *BenchmarkReporter::Context::executable_name;
BenchmarkReporter::Context::Context() : cpu_info(CPUInfo::Get()) {}
BenchmarkReporter::Context::Context()
: cpu_info(CPUInfo::Get()), sys_info(SystemInfo::Get()) {}
std::string BenchmarkReporter::Run::benchmark_name() const {
std::string name = run_name;

View File

@@ -12,7 +12,11 @@ void AppendHumanReadable(int n, std::string* str);
std::string HumanReadableNumber(double n, double one_k = 1024.0);
std::string StrFormat(const char* format, ...);
#ifdef __GNUC__
__attribute__((format(printf, 1, 2)))
#endif
std::string
StrFormat(const char* format, ...);
inline std::ostream& StrCatImp(std::ostream& out) BENCHMARK_NOEXCEPT {
return out;

View File

@@ -19,6 +19,7 @@
#undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA
#include <versionhelpers.h>
#include <windows.h>
#include <codecvt>
#else
#include <fcntl.h>
#ifndef BENCHMARK_OS_FUCHSIA
@@ -52,6 +53,7 @@
#include <limits>
#include <memory>
#include <sstream>
#include <locale>
#include "check.h"
#include "cycleclock.h"
@@ -366,6 +368,35 @@ std::vector<CPUInfo::CacheInfo> GetCacheSizes() {
#endif
}
std::string GetSystemName() {
#if defined(BENCHMARK_OS_WINDOWS)
std::string str;
const unsigned COUNT = MAX_COMPUTERNAME_LENGTH+1;
TCHAR hostname[COUNT] = {'\0'};
DWORD DWCOUNT = COUNT;
if (!GetComputerName(hostname, &DWCOUNT))
return std::string("");
#ifndef UNICODE
str = std::string(hostname, DWCOUNT);
#else
//Using wstring_convert, Is deprecated in C++17
using convert_type = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_type, wchar_t> converter;
std::wstring wStr(hostname, DWCOUNT);
str = converter.to_bytes(wStr);
#endif
return str;
#else // defined(BENCHMARK_OS_WINDOWS)
#ifdef BENCHMARK_OS_MACOSX //Mac Doesnt have HOST_NAME_MAX defined
#define HOST_NAME_MAX 64
#endif
char hostname[HOST_NAME_MAX];
int retVal = gethostname(hostname, HOST_NAME_MAX);
if (retVal != 0) return std::string("");
return std::string(hostname);
#endif // Catch-all POSIX block.
}
int GetNumCPUs() {
#ifdef BENCHMARK_HAS_SYSCTL
int NumCPU = -1;
@@ -609,4 +640,11 @@ CPUInfo::CPUInfo()
scaling_enabled(CpuScalingEnabled(num_cpus)),
load_avg(GetLoadAvg()) {}
const SystemInfo& SystemInfo::Get() {
static const SystemInfo* info = new SystemInfo();
return *info;
}
SystemInfo::SystemInfo() : name(GetSystemName()) {}
} // end namespace benchmark

View File

@@ -4,6 +4,7 @@
#include <iostream>
#include <map>
#include <memory>
#include <random>
#include <sstream>
#include <streambuf>
@@ -38,17 +39,18 @@ SubMap& GetSubstitutions() {
// Don't use 'dec_re' from header because it may not yet be initialized.
// clang-format off
static std::string safe_dec_re = "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?";
static std::string time_re = "([0-9]+[.])?[0-9]+";
static SubMap map = {
{"%float", "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?"},
// human-readable float
{"%hrfloat", "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?[kMGTPEZYmunpfazy]?"},
{"%int", "[ ]*[0-9]+"},
{" %s ", "[ ]+"},
{"%time", "[ ]*[0-9]+ ns"},
{"%console_report", "[ ]*[0-9]+ ns [ ]*[0-9]+ ns [ ]*[0-9]+"},
{"%console_time_only_report", "[ ]*[0-9]+ ns [ ]*[0-9]+ ns"},
{"%console_us_report", "[ ]*[0-9]+ us [ ]*[0-9]+ us [ ]*[0-9]+"},
{"%console_us_time_only_report", "[ ]*[0-9]+ us [ ]*[0-9]+ us"},
{"%time", "[ ]*" + time_re + "[ ]+ns"},
{"%console_report", "[ ]*" + time_re + "[ ]+ns [ ]*" + time_re + "[ ]+ns [ ]*[0-9]+"},
{"%console_time_only_report", "[ ]*" + time_re + "[ ]+ns [ ]*" + time_re + "[ ]+ns"},
{"%console_us_report", "[ ]*" + time_re + "[ ]+us [ ]*" + time_re + "[ ]+us [ ]*[0-9]+"},
{"%console_us_time_only_report", "[ ]*" + time_re + "[ ]+us [ ]*" + time_re + "[ ]+us"},
{"%csv_header",
"name,iterations,real_time,cpu_time,time_unit,bytes_per_second,"
"items_per_second,label,error_occurred,error_message"},
@@ -207,7 +209,7 @@ void ResultsChecker::Add(const std::string& entry_pattern, ResultsCheckFn fn) {
void ResultsChecker::CheckResults(std::stringstream& output) {
// first reset the stream to the start
{
auto start = std::ios::streampos(0);
auto start = std::stringstream::pos_type(0);
// clear before calling tellg()
output.clear();
// seek to zero only when needed
@@ -438,11 +440,50 @@ int SubstrCnt(const std::string& haystack, const std::string& pat) {
return count;
}
static char ToHex(int ch) {
return ch < 10 ? static_cast<char>('0' + ch)
: static_cast<char>('a' + (ch - 10));
}
static char RandomHexChar() {
static std::mt19937 rd{std::random_device{}()};
static std::uniform_int_distribution<int> mrand{0, 15};
return ToHex(mrand(rd));
}
static std::string GetRandomFileName() {
std::string model = "test.%%%%%%";
for (auto & ch : model) {
if (ch == '%')
ch = RandomHexChar();
}
return model;
}
static bool FileExists(std::string const& name) {
std::ifstream in(name.c_str());
return in.good();
}
static std::string GetTempFileName() {
// This function attempts to avoid race conditions where two tests
// create the same file at the same time. However, it still introduces races
// similar to tmpnam.
int retries = 3;
while (--retries) {
std::string name = GetRandomFileName();
if (!FileExists(name))
return name;
}
std::cerr << "Failed to create unique temporary file name" << std::endl;
std::abort();
}
std::string GetFileReporterOutput(int argc, char* argv[]) {
std::vector<char*> new_argv(argv, argv + argc);
assert(static_cast<decltype(new_argv)::size_type>(argc) == new_argv.size());
std::string tmp_file_name = std::tmpnam(nullptr);
std::string tmp_file_name = GetTempFileName();
std::cout << "Will be using this as the tmp file: " << tmp_file_name << '\n';
std::string tmp = "--benchmark_out=";

View File

@@ -23,6 +23,7 @@ static int AddContextCases() {
{{"^\\{", MR_Default},
{"\"context\":", MR_Next},
{"\"date\": \"", MR_Next},
{"\"host_name\":", MR_Next},
{"\"executable\": \".*(/|\\\\)reporter_output_test(\\.exe)?\",",
MR_Next},
{"\"num_cpus\": %int,$", MR_Next},
@@ -219,6 +220,18 @@ ADD_CASES(TC_JSONOut,
{"\"run_type\": \"iteration\",$", MR_Next}});
ADD_CASES(TC_CSVOut, {{"^\"BM_arg_names/first:2/5/third:4\",%csv_report$"}});
// ========================================================================= //
// ------------------------ Testing Big Args Output ------------------------ //
// ========================================================================= //
void BM_BigArgs(benchmark::State& state) {
for (auto _ : state) {
}
}
BENCHMARK(BM_BigArgs)->RangeMultiplier(2)->Range(1U << 30U, 1U << 31U);
ADD_CASES(TC_ConsoleOut, {{"^BM_BigArgs/1073741824 %console_report$"},
{"^BM_BigArgs/2147483648 %console_report$"}});
// ========================================================================= //
// ----------------------- Testing Complexity Output ----------------------- //
// ========================================================================= //
@@ -521,7 +534,7 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_UserStats/iterations:5/repeats:3/manual_time [ "
{"^BM_UserStats/iterations:5/repeats:3/"
"manual_time_median [ ]* 150 ns %time [ ]*3$"},
{"^BM_UserStats/iterations:5/repeats:3/"
"manual_time_stddev [ ]* 0 ns %time [ ]*3$"},
"manual_time_stddev [ ]* 0.000 ns %time [ ]*3$"},
{"^BM_UserStats/iterations:5/repeats:3/manual_time_ "
"[ ]* 150 ns %time [ ]*3$"}});
ADD_CASES(

View File

@@ -9,56 +9,56 @@ namespace {
TEST(StringUtilTest, stoul) {
{
size_t pos = 0;
EXPECT_EQ(0, benchmark::stoul("0", &pos));
EXPECT_EQ(1, pos);
EXPECT_EQ(0ul, benchmark::stoul("0", &pos));
EXPECT_EQ(1ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(7, benchmark::stoul("7", &pos));
EXPECT_EQ(1, pos);
EXPECT_EQ(7ul, benchmark::stoul("7", &pos));
EXPECT_EQ(1ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(135, benchmark::stoul("135", &pos));
EXPECT_EQ(3, pos);
EXPECT_EQ(135ul, benchmark::stoul("135", &pos));
EXPECT_EQ(3ul, pos);
}
#if ULONG_MAX == 0xFFFFFFFFul
{
size_t pos = 0;
EXPECT_EQ(0xFFFFFFFFul, benchmark::stoul("4294967295", &pos));
EXPECT_EQ(10, pos);
EXPECT_EQ(10ul, pos);
}
#elif ULONG_MAX == 0xFFFFFFFFFFFFFFFFul
{
size_t pos = 0;
EXPECT_EQ(0xFFFFFFFFFFFFFFFFul, benchmark::stoul("18446744073709551615", &pos));
EXPECT_EQ(20, pos);
EXPECT_EQ(20ul, pos);
}
#endif
{
size_t pos = 0;
EXPECT_EQ(10, benchmark::stoul("1010", &pos, 2));
EXPECT_EQ(4, pos);
EXPECT_EQ(10ul, benchmark::stoul("1010", &pos, 2));
EXPECT_EQ(4ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(520, benchmark::stoul("1010", &pos, 8));
EXPECT_EQ(4, pos);
EXPECT_EQ(520ul, benchmark::stoul("1010", &pos, 8));
EXPECT_EQ(4ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(1010, benchmark::stoul("1010", &pos, 10));
EXPECT_EQ(4, pos);
EXPECT_EQ(1010ul, benchmark::stoul("1010", &pos, 10));
EXPECT_EQ(4ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(4112, benchmark::stoul("1010", &pos, 16));
EXPECT_EQ(4, pos);
EXPECT_EQ(4112ul, benchmark::stoul("1010", &pos, 16));
EXPECT_EQ(4ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(0xBEEF, benchmark::stoul("BEEF", &pos, 16));
EXPECT_EQ(4, pos);
EXPECT_EQ(0xBEEFul, benchmark::stoul("BEEF", &pos, 16));
EXPECT_EQ(4ul, pos);
}
{
ASSERT_THROW(benchmark::stoul("this is a test"), std::invalid_argument);
@@ -69,42 +69,42 @@ TEST(StringUtilTest, stoi) {
{
size_t pos = 0;
EXPECT_EQ(0, benchmark::stoi("0", &pos));
EXPECT_EQ(1, pos);
EXPECT_EQ(1ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(-17, benchmark::stoi("-17", &pos));
EXPECT_EQ(3, pos);
EXPECT_EQ(3ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(1357, benchmark::stoi("1357", &pos));
EXPECT_EQ(4, pos);
EXPECT_EQ(4ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(10, benchmark::stoi("1010", &pos, 2));
EXPECT_EQ(4, pos);
EXPECT_EQ(4ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(520, benchmark::stoi("1010", &pos, 8));
EXPECT_EQ(4, pos);
EXPECT_EQ(4ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(1010, benchmark::stoi("1010", &pos, 10));
EXPECT_EQ(4, pos);
EXPECT_EQ(4ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(4112, benchmark::stoi("1010", &pos, 16));
EXPECT_EQ(4, pos);
EXPECT_EQ(4ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(0xBEEF, benchmark::stoi("BEEF", &pos, 16));
EXPECT_EQ(4, pos);
EXPECT_EQ(4ul, pos);
}
{
ASSERT_THROW(benchmark::stoi("this is a test"), std::invalid_argument);
@@ -115,28 +115,28 @@ TEST(StringUtilTest, stod) {
{
size_t pos = 0;
EXPECT_EQ(0.0, benchmark::stod("0", &pos));
EXPECT_EQ(1, pos);
EXPECT_EQ(1ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(-84.0, benchmark::stod("-84", &pos));
EXPECT_EQ(3, pos);
EXPECT_EQ(3ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(1234.0, benchmark::stod("1234", &pos));
EXPECT_EQ(4, pos);
EXPECT_EQ(4ul, pos);
}
{
size_t pos = 0;
EXPECT_EQ(1.5, benchmark::stod("1.5", &pos));
EXPECT_EQ(3, pos);
EXPECT_EQ(3ul, pos);
}
{
size_t pos = 0;
/* Note: exactly representable as double */
EXPECT_EQ(-1.25e+9, benchmark::stod("-1.25e+9", &pos));
EXPECT_EQ(8, pos);
EXPECT_EQ(8ul, pos);
}
{
ASSERT_THROW(benchmark::stod("this is a test"), std::invalid_argument);

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env python
import unittest
"""
compare.py - versatile benchmark output compare tool
"""
@@ -244,9 +245,6 @@ def main():
print(ln)
import unittest
class TestParser(unittest.TestCase):
def setUp(self):
self.parser = create_parser()
@@ -402,7 +400,7 @@ class TestParser(unittest.TestCase):
if __name__ == '__main__':
#unittest.main()
# unittest.main()
main()
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,3 +1,4 @@
import unittest
"""report.py - Utilities for reporting statistics about benchmark results
"""
import os
@@ -270,9 +271,6 @@ def generate_difference_report(
# Unit tests
import unittest
class TestGetUniqueBenchmarkNames(unittest.TestCase):
def load_results(self):
import json
@@ -290,7 +288,7 @@ class TestGetUniqueBenchmarkNames(unittest.TestCase):
'BM_One',
'BM_Two',
'short', # These two are not sorted
'medium', # These two are not sorted
'medium', # These two are not sorted
]
json = self.load_results()
output_lines = get_unique_benchmark_names(json)
@@ -300,6 +298,7 @@ class TestGetUniqueBenchmarkNames(unittest.TestCase):
for i in range(0, len(output_lines)):
self.assertEqual(expect_lines[i], output_lines[i])
class TestReportDifference(unittest.TestCase):
def load_results(self):
import json

View File

@@ -7,11 +7,13 @@ import subprocess
import sys
# Input file type enumeration
IT_Invalid = 0
IT_JSON = 1
IT_Invalid = 0
IT_JSON = 1
IT_Executable = 2
_num_magic_bytes = 2 if sys.platform.startswith('win') else 4
def is_executable_file(filename):
"""
Return 'True' if 'filename' names a valid file which is likely
@@ -46,7 +48,7 @@ def is_json_file(filename):
with open(filename, 'r') as f:
json.load(f)
return True
except:
except BaseException:
pass
return False
@@ -84,6 +86,7 @@ def check_input_file(filename):
sys.exit(1)
return ftype
def find_benchmark_flag(prefix, benchmark_flags):
"""
Search the specified list of flags for a flag matching `<prefix><arg>` and
@@ -97,6 +100,7 @@ def find_benchmark_flag(prefix, benchmark_flags):
result = f[len(prefix):]
return result
def remove_benchmark_flags(prefix, benchmark_flags):
"""
Return a new list containing the specified benchmark_flags except those
@@ -105,6 +109,7 @@ def remove_benchmark_flags(prefix, benchmark_flags):
assert prefix.startswith('--') and prefix.endswith('=')
return [f for f in benchmark_flags if not f.startswith(prefix)]
def load_benchmark_results(fname):
"""
Read benchmark output from a file and return the JSON object.
@@ -129,7 +134,7 @@ def run_benchmark(exe_name, benchmark_flags):
thandle, output_name = tempfile.mkstemp()
os.close(thandle)
benchmark_flags = list(benchmark_flags) + \
['--benchmark_out=%s' % output_name]
['--benchmark_out=%s' % output_name]
cmd = [exe_name] + benchmark_flags
print("RUNNING: %s" % ' '.join(cmd))
@@ -156,4 +161,4 @@ def run_or_load_benchmark(filename, benchmark_flags):
elif ftype == IT_Executable:
return run_benchmark(filename, benchmark_flags)
else:
assert False # This branch is unreachable
assert False # This branch is unreachable

View File

@@ -307,6 +307,7 @@ class Configuration(object):
self.use_system_cxx_lib = False
elif self.use_system_cxx_lib:
assert os.path.isdir(self.use_system_cxx_lib), "the specified use_system_cxx_lib parameter (%s) is not a valid directory" % self.use_system_cxx_lib
self.use_system_cxx_lib = os.path.abspath(self.use_system_cxx_lib)
self.lit_config.note(
"inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib)
@@ -406,11 +407,10 @@ class Configuration(object):
if self.use_deployment:
self.add_deployment_feature('with_system_cxx_lib')
# Configure the availability markup checks features.
if self.use_deployment:
self.config.available_features.add('availability_markup')
self.add_deployment_feature('availability_markup')
# Configure the availability feature. Availability is only enabled
# with libc++, because other standard libraries do not provide
# availability markup.
if self.use_deployment and self.cxx_stdlib_under_test == 'libc++':
self.config.available_features.add('availability')
self.add_deployment_feature('availability')
@@ -487,13 +487,7 @@ class Configuration(object):
self.config.available_features.add("objective-c++")
def configure_compile_flags(self):
no_default_flags = self.get_lit_bool('no_default_flags', False)
if not no_default_flags:
self.configure_default_compile_flags()
# This include is always needed so add so add it regardless of
# 'no_default_flags'.
support_path = os.path.join(self.libcxx_src_root, 'test/support')
self.cxx.compile_flags += ['-I' + support_path]
self.configure_default_compile_flags()
# Configure extra flags
compile_flags_str = self.get_lit_conf('compile_flags', '')
self.cxx.compile_flags += shlex.split(compile_flags_str)
@@ -574,6 +568,10 @@ class Configuration(object):
self.cxx.flags += ['-arch', arch]
self.cxx.flags += ['-m' + name + '-version-min=' + version]
# Add includes for support headers used in the tests.
support_path = os.path.join(self.libcxx_src_root, 'test/support')
self.cxx.compile_flags += ['-I' + support_path]
# FIXME(EricWF): variant_size.pass.cpp requires a slightly larger
# template depth with older Clang versions.
self.cxx.addFlagIfSupported('-ftemplate-depth=270')
@@ -731,37 +729,33 @@ class Configuration(object):
def configure_link_flags(self):
no_default_flags = self.get_lit_bool('no_default_flags', False)
if not no_default_flags:
# Configure library path
self.configure_link_flags_cxx_library_path()
self.configure_link_flags_abi_library_path()
# Configure library path
self.configure_link_flags_cxx_library_path()
self.configure_link_flags_abi_library_path()
# Configure libraries
if self.cxx_stdlib_under_test == 'libc++':
self.cxx.link_flags += ['-nodefaultlibs']
# FIXME: Handle MSVCRT as part of the ABI library handling.
if self.is_windows:
self.cxx.link_flags += ['-nostdlib']
self.configure_link_flags_cxx_library()
self.configure_link_flags_abi_library()
self.configure_extra_library_flags()
elif self.cxx_stdlib_under_test == 'libstdc++':
enable_fs = self.get_lit_bool('enable_filesystem',
default=False)
if enable_fs:
self.config.available_features.add('c++experimental')
self.cxx.link_flags += ['-lstdc++fs']
self.cxx.link_flags += ['-lm', '-pthread']
elif self.cxx_stdlib_under_test == 'msvc':
# FIXME: Correctly setup debug/release flags here.
pass
elif self.cxx_stdlib_under_test == 'cxx_default':
self.cxx.link_flags += ['-pthread']
else:
self.lit_config.fatal(
'unsupported value for "use_stdlib_type": %s'
% use_stdlib_type)
# Configure libraries
if self.cxx_stdlib_under_test == 'libc++':
self.cxx.link_flags += ['-nodefaultlibs']
# FIXME: Handle MSVCRT as part of the ABI library handling.
if self.is_windows:
self.cxx.link_flags += ['-nostdlib']
self.configure_link_flags_cxx_library()
self.configure_link_flags_abi_library()
self.configure_extra_library_flags()
elif self.cxx_stdlib_under_test == 'libstdc++':
enable_fs = self.get_lit_bool('enable_filesystem',
default=False)
if enable_fs:
self.config.available_features.add('c++experimental')
self.cxx.link_flags += ['-lstdc++fs']
self.cxx.link_flags += ['-lm', '-pthread']
elif self.cxx_stdlib_under_test == 'msvc':
# FIXME: Correctly setup debug/release flags here.
pass
elif self.cxx_stdlib_under_test == 'cxx_default':
self.cxx.link_flags += ['-pthread']
else:
self.lit_config.fatal('invalid stdlib under test')
link_flags_str = self.get_lit_conf('link_flags', '')
self.cxx.link_flags += shlex.split(link_flags_str)

View File

@@ -144,12 +144,12 @@ class DarwinLocalTI(DefaultTargetInfo):
def configure_env(self, env):
library_paths = []
# Configure the library path for libc++
if self.full_config.use_system_cxx_lib:
if self.full_config.cxx_runtime_root:
library_paths += [self.full_config.cxx_runtime_root]
elif self.full_config.use_system_cxx_lib:
if (os.path.isdir(str(self.full_config.use_system_cxx_lib))):
library_paths += [self.full_config.use_system_cxx_lib]
pass
elif self.full_config.cxx_runtime_root:
library_paths += [self.full_config.cxx_runtime_root]
# Configure the abi library path
if self.full_config.abi_library_root:
library_paths += [self.full_config.abi_library_root]
@@ -182,6 +182,18 @@ class FreeBSDLocalTI(DefaultTargetInfo):
flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt']
class NetBSDLocalTI(DefaultTargetInfo):
def __init__(self, full_config):
super(NetBSDLocalTI, self).__init__(full_config)
def add_locale_features(self, features):
add_common_locales(features, self.full_config.lit_config)
def add_cxx_link_flags(self, flags):
flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lc++abi',
'-lunwind']
class LinuxLocalTI(DefaultTargetInfo):
def __init__(self, full_config):
super(LinuxLocalTI, self).__init__(full_config)
@@ -280,6 +292,7 @@ def make_target_info(full_config):
target_system = platform.system()
if target_system == 'Darwin': return DarwinLocalTI(full_config)
if target_system == 'FreeBSD': return FreeBSDLocalTI(full_config)
if target_system == 'NetBSD': return NetBSDLocalTI(full_config)
if target_system == 'Linux': return LinuxLocalTI(full_config)
if target_system == 'Windows': return WindowsLocalTI(full_config)
return DefaultTargetInfo(full_config)