* improve and colorize warning/error/debug/info messages
* add include path warnings for /usr/include and /usr/local/include
other changes:
* bump version to 0.10
This commit is contained in:
Thomas Pöchtrager 2015-05-02 21:49:23 +02:00
parent 5127b44d52
commit 9033b6b847
12 changed files with 322 additions and 117 deletions

View File

@ -1,3 +1,14 @@
/****************************** v0.10 ********************************/
changed:
* improved and colorized wrapper error/warning/debug/info messages
added:
* include path warnings for /usr/include and /usr/local/include
(can be switched off via 'OSXCROSS_NO_INCLUDE_PATH_WARNINGS=1')
* an option to silence osxcross extension warnings
(OSXCROSS_NO_EXTENSION_WARNINGS=1)
/******************************* v0.9 *******************************/
changed:

View File

@ -77,7 +77,7 @@ if [ -z "$OSX_VERSION_MIN" ]; then
fi
# Don't change this
OSXCROSS_VERSION=0.9
OSXCROSS_VERSION=0.10
TARBALL_DIR=$BASE_DIR/tarballs
BUILD_DIR=$BASE_DIR/build

View File

@ -75,8 +75,8 @@ if [ -n "$BWPLATFORM" ]; then
#CXX=o32-g++
FLAGS+="-fvisibility-inlines-hidden "
elif [ $PLATFORM = "FreeBSD" -a $(uname -s) != "FreeBSD" ]; then
CXX=amd64-pc-freebsd10.0-clang++
#CXX=amd64-pc-freebsd10.0-g++
CXX=amd64-pc-freebsd10.1-clang++
#CXX=amd64-pc-freebsd10.1-g++
elif [ $PLATFORM = "NetBSD" -a $(uname -s) != "NetBSD" ]; then
CXX=amd64-pc-netbsd6.1.3-clang++
#CXX=amd64-pc-netbsd6.1.3-g++

View File

@ -54,10 +54,70 @@ namespace {
// detect target and setup invocation command
//
void checkIncludePath(const char *opt, const char *path) {
#ifndef __APPLE__
constexpr const char *DangerousIncludePaths[] = { "/usr/include",
"/usr/local/include" };
if (!path)
return;
static bool noinccheck = !!getenv("OSXCROSS_NO_INCLUDE_PATH_WARNINGS");
if (noinccheck)
return;
char buf[PATH_MAX + 1];
const char *rpath = realpath(path, buf);
if (!rpath)
rpath = path;
for (const char *dpath : DangerousIncludePaths) {
if (!strncmp(rpath, dpath, strlen(dpath))) {
warn << "possible dangerous include path specified: '" << opt << " "
<< path << "'";
if (strcmp(path, rpath))
warn << " (" << rpath << ")";
warn << warn.endl();
warninfo << "you can silence this warning via "
<< "'OSXCROSS_NO_INCLUDE_PATH_WARNINGS=1' (env)"
<< warninfo.endl();
}
}
#else
(void)opt;
(void)path;
#endif
}
void warnExtension(const char *extension) {
static bool noextwarnings = !!getenv("OSXCROSS_NO_EXTENSION_WARNINGS");
if (noextwarnings)
return;
warn << extension << " is an osxcross extension" << warn.endl();
warninfo << "you can silence this warning via "
<< "'OSXCROSS_NO_EXTENSION_WARNINGS=1' (env)" << warninfo.endl();
}
#define PABREAK \
else target.args.push_back(arg); \
break
#define PAPUSHARG \
target.args.push_back(arg); \
break
#define PAPUSHARGANDVAL(splitted) \
do { \
target.args.push_back(arg); \
if (splitted && i < argc) \
target.args.push_back(argv[i]); \
} while (0); \
break
bool detectTarget(int argc, char **argv, Target &target) {
const char *cmd = argv[0];
const char *p = strrchr(cmd, '/');
@ -69,15 +129,18 @@ bool detectTarget(int argc, char **argv, Target &target) {
target.args.reserve(static_cast<size_t>(argc));
auto warnExtension = [](const char *extension) {
std::cerr << "warning: '" << extension << "' is an OSXCross extension"
<< std::endl;
};
auto parseArgs = [&]()->bool {
typedef bool (*delayedfun)(Target &);
std::vector<delayedfun> delayedfuncs;
auto runLater = [&](delayedfun fun) {
for (auto dfun : delayedfuncs) {
if (dfun == fun)
return;
}
delayedfuncs.push_back(fun);
};
auto getVal = [&](char * arg, const char * flag, int & i)->const char * {
const char *val = arg + strlen(flag);
@ -85,7 +148,7 @@ bool detectTarget(int argc, char **argv, Target &target) {
val = argv[++i];
if (i >= argc) {
std::cerr << "missing argument for '" << flag << "'" << std::endl;
err << "missing argument for '" << flag << "'" << err.endl();
return nullptr;
}
}
@ -93,6 +156,14 @@ bool detectTarget(int argc, char **argv, Target &target) {
return val;
};
auto installGCCArchExtensionWarning = [&]() {
runLater([](Target &t) {
if (t.targetarch.size() > 1 && t.isGCC())
warnExtension("using multiple '-arch' flags with gcc");
return true;
});
};
if (char *p = getenv("MACOSX_DEPLOYMENT_TARGET")) {
target.OSNum = parseOSVersion(p);
unsetenv("MACOSX_DEPLOYMENT_TARGET");
@ -115,18 +186,18 @@ bool detectTarget(int argc, char **argv, Target &target) {
Arch arch = parseArch(val);
if (arch == Arch::unknown) {
std::cerr << "warning: '-arch': unknown architecture '" << val
<< "'" << std::endl;
warn << "'-arch': unknown architecture '" << val << "'"
<< warn.endl();
}
const char *name = getArchName(arch);
if (strcmp(val, name)) {
std::cerr << "warning: '-arch': " << val << " != " << name
<< std::endl;
}
if (strcmp(val, name))
warn << "'-arch': '" << val << "' != '" << name << "'"
<< warn.endl();
target.addArch(arch);
installGCCArchExtensionWarning();
}
PABREAK;
@ -137,10 +208,10 @@ bool detectTarget(int argc, char **argv, Target &target) {
if (!strcmp(arg, "-E")) {
target.nocodegen = true;
delayedfuncs.push_back([](Target &t) {
runLater([](Target &t) {
if (t.targetarch.size() > 1) {
std::cerr << "cannot use '-E' with multiple -arch options"
<< std::endl;
err << "cannot use '-E' with multiple -arch options"
<< err.endl();
return false;
}
return true;
@ -160,10 +231,10 @@ bool detectTarget(int argc, char **argv, Target &target) {
if (target.isClang())
continue;
delayedfuncs.push_back([](Target &t) {
runLater([](Target &t) {
if (t.targetarch.size() > 1) {
std::cerr << "gcc does not support '-flto' with multiple "
<< "-arch flags" << std::endl;
err << "gcc does not support '-flto' with multiple "
<< "'-arch' flags" << err.endl();
return false;
}
return true;
@ -172,6 +243,30 @@ bool detectTarget(int argc, char **argv, Target &target) {
PABREAK;
}
case 'c':
case 'i':
case 'I': {
// c
// i
// I
constexpr const char *OptsToCheck[] = {
"-isystem", "-icxx-isystem", "-cxx-isystem", "-I"
};
bool splitted = false;
for (const char *opt : OptsToCheck) {
if (!strncmp(arg, opt, strlen(opt))) {
int iold = i;
checkIncludePath(opt, getVal(arg, opt, i));
splitted = i > iold;
break;
}
}
PAPUSHARGANDVAL(splitted);
}
case 'm': {
// -m
@ -180,17 +275,18 @@ bool detectTarget(int argc, char **argv, Target &target) {
target.OSNum = parseOSVersion(val);
if (target.OSNum != val) {
std::cerr << "warning: '-mmacosx-version-min=' ("
<< target.OSNum.Str() << " != " << val << ")"
<< std::endl;
warn << "'-mmacosx-version-min=' (" << target.OSNum.Str()
<< " != " << val << ")" << warn.endl();
}
} else if (!strcmp(arg, "-m16") || !strcmp(arg, "-mx32")) {
std::cerr << "'" << arg << "' not supported" << std::endl;
err << "'" << arg << "' is not supported" << err.endl();
return false;
} else if (!strcmp(arg, "-m32")) {
target.addArch(Arch::i386);
installGCCArchExtensionWarning();
} else if (!strcmp(arg, "-m64")) {
target.addArch(Arch::x86_64);
installGCCArchExtensionWarning();
}
PABREAK;
@ -200,8 +296,7 @@ bool detectTarget(int argc, char **argv, Target &target) {
if (!strcmp(arg, "-oc-use-gcc-libs")) {
if (target.isGCC()) {
std::cerr << "warning: '" << arg << "' has no effect"
<< std::endl;
warn << arg << "' has no effect" << warn.endl();
break;
}
target.stdlib = StdLib::libstdcxx;
@ -219,8 +314,12 @@ bool detectTarget(int argc, char **argv, Target &target) {
const char *val = arg + 8;
size_t i = 0;
if (target.isGCC())
warnExtension("-stdlib=");
if (target.isGCC()) {
runLater([](Target &) {
warnExtension("'-stdlib='");
return true;
});
}
for (auto stdlibname : StdLibNames) {
if (!strcmp(val, stdlibname)) {
@ -231,18 +330,17 @@ bool detectTarget(int argc, char **argv, Target &target) {
}
if (i == (sizeof(StdLibNames) / sizeof(StdLibNames[0]))) {
std::cerr << "value of '-stdlib=' must be ";
err << "value of '-stdlib=' must be ";
for (size_t j = 0; j < i; ++j) {
std::cerr << "'" << StdLibNames[j] << "'";
if (j == i - 2) {
std::cerr << " or ";
} else if (j < i - 2) {
std::cerr << ", ";
}
err << "'" << StdLibNames[j] << "'";
if (j == i - 2)
err << " or ";
else if (j < i - 2)
err << ", ";
}
std::cerr << std::endl;
err << err.endl();
return false;
}
@ -254,9 +352,8 @@ bool detectTarget(int argc, char **argv, Target &target) {
PABREAK;
}
case 'x': {
if (!strncmp(arg, "-x", 2)) {
if (!strncmp(arg, "-x", 2))
target.lang = getVal(arg, "-x", i);
}
PABREAK;
}
@ -311,8 +408,8 @@ bool detectTarget(int argc, char **argv, Target &target) {
if (target.compiler.rfind("-libc++") == (target.compiler.size() - 7)) {
if (target.stdlib != StdLib::unset && target.stdlib != StdLib::libcxx) {
std::cerr << "warning: '-stdlib=" << getStdLibString(target.stdlib)
<< "' will be ignored" << std::endl;
warn << "'-stdlib=" << getStdLibString(target.stdlib)
<< "' will be ignored" << warn.endl();
}
target.compiler.resize(target.compiler.size() - 7);
@ -359,8 +456,8 @@ bool detectTarget(int argc, char **argv, Target &target) {
(*prog)(argc, argv, target);
if (target.target != getDefaultTarget()) {
std::cerr << "warning: target mismatch (" << target.target
<< " != " << getDefaultTarget() << ")" << std::endl;
warn << "target mismatch (" << target.target
<< " != " << getDefaultTarget() << ")" << warn.endl();
}
if (!parseArgs())
@ -396,8 +493,8 @@ bool detectTarget(int argc, char **argv, Target &target) {
// and clang + -oc-use-gcc-libs
//
void generateMultiArchObjectFile(int &rc, int argc, char **argv,
Target &target, int debug) {
void generateMultiArchObjectFile(int &rc, int argc, char **argv, Target &target,
int debug) {
#ifndef _WIN32
std::string stdintmpfile;
string_vector objs;
@ -469,10 +566,8 @@ void generateMultiArchObjectFile(int &rc, int argc, char **argv,
target.outputname = outputname.c_str() + pos;
} else {
if (f) {
std::cerr << "source filename detection failed" << std::endl;
std::cerr << "using a.out" << std::endl;
}
if (f)
warn << "source filename detection failed (using a.out)" << warn.endl();
target.outputname = "a.out";
}
}
@ -499,7 +594,7 @@ void generateMultiArchObjectFile(int &rc, int argc, char **argv,
int status = 1;
if (wait(&status) == -1) {
std::cerr << "wait() failed" << std::endl;
err << "wait() failed" << err.endl();
cleanup();
rc = 1;
break;
@ -558,15 +653,14 @@ void generateMultiArchObjectFile(int &rc, int argc, char **argv,
}
if (debug) {
std::cerr << "[d] "
<< "[" << num << "/" << target.targetarch.size()
<< "] [compiling] " << archname << std::endl;
dbg << "[" << num << "/" << target.targetarch.size() << "] [compiling] "
<< archname << dbg.endl();
}
compile = true;
break;
} else {
std::cerr << "fork() failed" << std::endl;
err << "fork() failed" << err.endl();
rc = 1;
break;
}
@ -585,7 +679,7 @@ void generateMultiArchObjectFile(int &rc, int argc, char **argv,
lipo = "lipo";
if (getPathOfCommand(lipo.c_str(), path).empty()) {
std::cerr << "cannot find lipo binary" << std::endl;
err << "cannot find lipo binary" << err.endl();
rc = 1;
}
}
@ -604,9 +698,8 @@ void generateMultiArchObjectFile(int &rc, int argc, char **argv,
cmd += "-output ";
cmd += target.outputname;
if (debug) {
std::cerr << "[d] [lipo] <-- " << cmd << std::endl;
}
if (debug)
dbg << "[lipo] <-- " << cmd << dbg.endl();
rc = system(cmd.c_str());
rc = WEXITSTATUS(rc);
@ -621,7 +714,7 @@ void generateMultiArchObjectFile(int &rc, int argc, char **argv,
(void)argv;
(void)target;
(void)debug;
std::cerr << __func__ << " not supported" << std::endl;
err << __func__ << " not supported" << err.endl();
rc = 1;
#endif
}
@ -641,31 +734,28 @@ int main(int argc, char **argv) {
int rc = -1;
if (!detectTarget(argc, argv, target)) {
std::cerr << "cannot detect target" << std::endl;
err << "while detecting target" << err.endl();
return 1;
}
if (char *p = getenv("OCDEBUG")) {
if (char *p = getenv("OCDEBUG"))
debug = ((*p >= '1' && *p <= '9') ? *p - '0' + 0 : 0);
}
if (debug) {
b->halt();
if (debug >= 2) {
std::cerr << "[d] detected target triple: " << target.getTriple()
<< std::endl;
std::cerr << "[d] detected compiler: " << target.compiler << std::endl;
dbg << "detected target triple: " << target.getTriple() << dbg.endl();
dbg << "detected compiler: " << target.compiler << dbg.endl();
std::cerr << "[d] detected stdlib: " << getStdLibString(target.stdlib)
<< std::endl;
dbg << "detected stdlib: " << getStdLibString(target.stdlib)
<< dbg.endl();
if (debug >= 3) {
std::cerr << "[d] detected source file: "
<< (target.sourcefile ? target.sourcefile : "-") << std::endl;
dbg << "detected source file: "
<< (target.sourcefile ? target.sourcefile : "-") << dbg.endl();
std::cerr << "[d] detected language: " << target.getLangName()
<< std::endl;
dbg << "detected language: " << target.getLangName() << dbg.endl();
}
b->resume();
@ -696,8 +786,8 @@ int main(int argc, char **argv) {
out += " ";
}
std::cerr << "[d] --> " << in << std::endl;
std::cerr << "[d] <-- " << out << std::endl;
dbg << "--> " << in << dbg.endl();
dbg << "<-- " << out << dbg.endl();
};
if (rc == -1) {
@ -719,12 +809,12 @@ int main(int argc, char **argv) {
if (rc == -1)
printCommand();
std::cerr << "[d] === time spent in wrapper: " << diff / 1000000.0 << " ms"
<< std::endl;
dbg << "=== time spent in wrapper: " << diff / 1000000.0 << " ms"
<< dbg.endl();
}
if (rc == -1 && execvp(cargs[0], cargs)) {
std::cerr << "invoking compiler failed" << std::endl;
err << "invoking compiler failed" << err.endl();
if (!debug)
printCommand();

View File

@ -28,12 +28,13 @@ namespace program {
namespace osxcross {
int conf(Target &target) {
std::string sdkpath;
std::string SDKPath;
OSVersion OSXVersionMin = getDefaultMinTarget();
const char *ltopath = getLibLTOPath();
if (!target.getSDKPath(sdkpath)) {
std::cerr << "cannot find Mac OS X SDK!" << std::endl;
if (!target.getSDKPath(SDKPath)) {
err << "cannot find Mac OS X SDK (expected in: " << SDKPath << ")"
<< err.endl();
return 1;
}
@ -47,10 +48,11 @@ int conf(Target &target) {
<< std::endl;
std::cout << "export OSXCROSS_OSX_VERSION_MIN=" << OSXVersionMin.shortStr()
<< std::endl;
std::cout << "export OSXCROSS_TARGET=" << getDefaultTarget() << std::endl;
std::cout << "export OSXCROSS_TARGET=" << getDefaultTarget()
<< std::endl;
std::cout << "export OSXCROSS_SDK_VERSION=" << target.getSDKOSNum().shortStr()
<< std::endl;
std::cout << "export OSXCROSS_SDK=" << sdkpath
std::cout << "export OSXCROSS_SDK=" << SDKPath
<< std::endl;
std::cout << "export OSXCROSS_TARBALL_DIR=" << target.execpath
<< "/../../tarballs"

4
wrapper/programs/osxcross-env.cpp Normal file → Executable file
View File

@ -47,11 +47,13 @@ int env(int argc, char **argv) {
do {
auto badChar = [&](const char *p) {
std::cerr << desc << " should not contain '" << *p << "'" << std::endl;
err << desc << " should not contain '" << *p << "'" << warn.endl();
const char *start = p - std::min<size_t>(p - pp, 30);
size_t len = std::min<size_t>(strlen(start), 60);
std::cerr << std::endl;
std::cerr << std::string(start, len) << std::endl;
while (start++ != p)

0
wrapper/programs/osxcross-version.cpp Normal file → Executable file
View File

2
wrapper/programs/pkg-config.cpp Normal file → Executable file
View File

@ -93,7 +93,7 @@ int pkg_config(int argc, char **argv, Target &target) {
setenv("PKG_CONFIG_LIBDIR", "", 1);
if (execvp("pkg-config", argv))
std::cerr << "cannot find or execute pkg-config" << std::endl;
err << "cannot find or execute pkg-config" << err.endl();
}
return 1;

0
wrapper/programs/sw_vers.cpp Normal file → Executable file
View File

View File

@ -358,8 +358,8 @@ void Target::setupGCCLibs(Arch arch) {
getSDKPath(SDKPath);
GCCLibPath << SDKPath << "/../../lib/gcc/"
<< otriple << "/" << gccversion.Str();
GCCLibPath << SDKPath << "/../../lib/gcc/" << otriple << "/"
<< gccversion.Str();
GCCLibSTDCXXPath << SDKPath << "/../../" << otriple << "/lib";
@ -408,13 +408,12 @@ bool Target::setup() {
std::string SDKPath;
OSVersion SDKOSNum = getSDKOSNum();
if (!isKnownCompiler()) {
std::cerr << "warning: unknown compiler '" << compiler << "'" << std::endl;
}
if (!isKnownCompiler())
warn << "unknown compiler '" << compiler << "'" << warn.endl();
if (!getSDKPath(SDKPath)) {
std::cerr << "cannot find Mac OS X SDK (expected in: " << SDKPath << ")"
<< std::endl;
err << "cannot find Mac OS X SDK (expected in: " << SDKPath << ")"
<< err.endl();
return false;
}
@ -444,8 +443,8 @@ bool Target::setup() {
if (haveArch(Arch::x86_64h)) {
OSNum = OSVersion(10, 8); // Default to 10.8 for x86_64h
if (SDKOSNum < OSNum) {
std::cerr << getArchName(arch) << " requires the SDK from "
<< OSNum.Str() << " (or later)" << std::endl;
err << "'" << getArchName(arch) << "' requires the SDK from "
<< OSNum.Str() << " (or later)" << err.endl();
return false;
}
} else if (stdlib == StdLib::libcxx) {
@ -456,17 +455,17 @@ bool Target::setup() {
}
if (OSNum > SDKOSNum) {
std::cerr << "targeted OS X Version must be <= " << SDKOSNum.Str()
<< " (SDK)" << std::endl;
err << "targeted OS X version must be <= " << SDKOSNum.Str() << " (SDK)"
<< err.endl();
return false;
} else if (OSNum < OSVersion(10, 4)) {
std::cerr << "targeted OS X Version must be >= 10.4" << std::endl;
err << "targeted OS X version must be >= 10.4" << err.endl();
return false;
}
if (haveArch(Arch::x86_64h) && OSNum < OSVersion(10, 8)) {
std::cerr << getArchName(Arch::x86_64h) << " requires "
<< "'-mmacosx-version-min=10.8' (or later)" << std::endl;
err << "'" << getArchName(Arch::x86_64h) << "' requires "
<< "'-mmacosx-version-min=10.8' (or later)" << err.endl();
return false;
}
@ -478,13 +477,13 @@ bool Target::setup() {
}
} else if (stdlib == StdLib::libcxx) {
if (!hasLibCXX()) {
std::cerr << "libc++ requires the SDK from 10.7 (or later)" << std::endl;
err << "libc++ requires the SDK from 10.7 (or later)" << err.endl();
return false;
}
if (OSNum.Num() && OSNum < OSVersion(10, 7)) {
std::cerr << "libc++ requires '-mmacosx-version-min=10.7' (or later)"
<< std::endl;
err << "libc++ requires '-mmacosx-version-min=10.7' (or later)"
<< err.endl();
return false;
}
}
@ -504,8 +503,8 @@ bool Target::setup() {
case StdLib::libcxx: {
CXXHeaderPath += "/usr/include/c++/v1";
if (!dirExists(CXXHeaderPath)) {
std::cerr << "cannot find " << getStdLibString(stdlib) << " headers"
<< std::endl;
err << "cannot find " << getStdLibString(stdlib) << " headers"
<< err.endl();
return false;
}
break;
@ -531,8 +530,8 @@ bool Target::setup() {
});
if (v.empty()) {
std::cerr << "'-oc-use-gcc-libs' requires gcc to be installed "
"(./build_gcc.sh)" << std::endl;
err << "'-oc-use-gcc-libs' requires gcc to be installed "
"(./build_gcc.sh)" << err.endl();
return false;
}
@ -559,8 +558,8 @@ bool Target::setup() {
}
if (!dirExists(CXXHeaderPath)) {
std::cerr << "cannot find " << getStdLibString(stdlib) << " headers"
<< std::endl;
err << "cannot find " << getStdLibString(stdlib) << " headers"
<< err.endl();
return false;
}
@ -586,8 +585,8 @@ bool Target::setup() {
#ifndef __APPLE__
if (!findClangIntrinsicHeaders(tmp)) {
std::cerr << "cannot find clang intrinsic headers, please report this "
"issue to the OSXCross project" << std::endl;
warn << "cannot find clang intrinsic headers, please report this "
"issue to the OSXCross project" << warn.endl();
} else {
fargs.push_back("-isystem");
fargs.push_back(tmp);
@ -620,10 +619,8 @@ bool Target::setup() {
if (isLibCXX()) {
if (!langStdGiven())
langstd = "c++0x";
else if (!isCXX11orNewer()) {
std::cerr << "warning: libc++ requires -std=c++11 (or later) with gcc"
<< std::endl;
}
else if (!isCXX11orNewer())
warn << "libc++ requires -std=c++11 (or later) with gcc" << warn.endl();
}
if (isCXX() && isLibCXX()) {
@ -720,7 +717,7 @@ bool Target::setup() {
fargs.push_back(is32bit ? "-m32" : "-m64");
if (arch == Arch::x86_64h) {
std::cerr << getArchName(arch) << " requires clang" << std::endl;
err << "'" << getArchName(arch) << "' requires clang" << err.endl();
return false;
// fargs.push_back("-march=core-avx2");
// fargs.push_back("-Wl,-arch,x86_64h");
@ -733,8 +730,8 @@ bool Target::setup() {
}
break;
default:
std::cerr << "unsupported architecture " << getArchName(arch) << ""
<< std::endl;
err << "unsupported architecture: '" << getArchName(arch) << "'"
<< err.endl();
return false;
}
}

26
wrapper/tools.cpp Normal file → Executable file
View File

@ -31,11 +31,11 @@
#include <cstring>
#include <climits>
#include <cassert>
#include <unistd.h>
#include <sys/time.h>
#include <sys/stat.h>
#ifndef _WIN32
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
@ -63,6 +63,30 @@
namespace tools {
//
// Terminal text colors
//
bool isTerminal() {
#ifndef _WIN32
static bool first = false;
static bool val;
if (!first) {
val = !!isatty(fileno(stderr));
first = true;
}
return val;
#else
return false;
#endif
}
//
// Executable path
//
char *getExecutablePath(char *buf, size_t len) {
char *p;
#ifdef __APPLE__

81
wrapper/tools.h Normal file → Executable file
View File

@ -33,6 +33,85 @@ static inline void clear(std::stringstream &sstr)
sstr.str(std::string());
}
//
// Terminal text colors
//
bool isTerminal();
// http://stackoverflow.com/a/17469726
enum ColorCode {
FG_DEFAULT = 39,
FG_BLACK = 30,
FG_RED = 31,
FG_GREEN = 32,
FG_YELLOW = 33,
FG_BLUE = 34,
FG_MAGENTA = 35,
FG_CYAN = 36,
FG_LIGHT_GRAY = 37,
FG_DARK_GRAY = 90,
FG_LIGHT_RED = 91,
FG_LIGHT_GREEN = 92,
FG_LIGHT_YELLOW = 93,
FG_LIGHT_BLUE = 94,
FG_LIGHT_MAGENTA = 95,
FG_LIGHT_CYAN = 96,
FG_WHITE = 97,
BG_RED = 41,
BG_GREEN = 42,
BG_BLUE = 44,
BG_DEFAULT = 49
};
class Color {
ColorCode cc;
public:
Color(ColorCode cc) : cc(cc) {}
friend std::ostream &
operator<<(std::ostream &os, const Color &color) {
if (isTerminal())
return os << "\033[" << color.cc << "m";
return os;
}
};
//
// Error message helper
//
static class Message {
private:
const char *msg;
Color color;
std::ostream &os;
bool printprefix;
public:
static constexpr char endl() { return '\n'; }
bool isendl(char c) { return c == '\n'; }
template<typename T>
bool isendl(T&&) { return false; }
template<typename T>
Message &operator<<(T &&v) {
if (printprefix) {
os << Color(FG_DARK_GRAY) << "osxcross: " << color << msg << ": "
<< Color(FG_DEFAULT);
printprefix = false;
}
if (isendl(v)) {
printprefix = true;
os << std::endl;
} else {
os << v;
}
return *this;
}
Message(const char *msg, Color color = FG_RED, std::ostream &os = std::cerr)
: msg(msg), color(color), os(os), printprefix(true) {}
} warn("warning"), err("error"), dbg("debug", FG_LIGHT_MAGENTA),
info("info", FG_LIGHT_MAGENTA), warninfo(" info", FG_LIGHT_MAGENTA);
//
// Executable path
//
@ -95,7 +174,7 @@ public:
~benchmark() {
time_type diff = getTime() - s;
std::cerr << "took: " << diff / 1000000.0 << " ms" << std::endl;
dbg << "took: " << diff / 1000000.0 << " ms" << dbg.endl();
}
private: