diff --git a/CHANGELOG b/CHANGELOG index af2958b..755e084 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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: diff --git a/build.sh b/build.sh index d2e58ee..36d3bfc 100755 --- a/build.sh +++ b/build.sh @@ -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 diff --git a/wrapper/build.sh b/wrapper/build.sh index 2da08ac..7ff4644 100755 --- a/wrapper/build.sh +++ b/wrapper/build.sh @@ -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++ diff --git a/wrapper/main.cpp b/wrapper/main.cpp index 806343a..ed799af 100644 --- a/wrapper/main.cpp +++ b/wrapper/main.cpp @@ -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(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 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(); diff --git a/wrapper/programs/osxcross-conf.cpp b/wrapper/programs/osxcross-conf.cpp index 8f12efa..fc5b936 100644 --- a/wrapper/programs/osxcross-conf.cpp +++ b/wrapper/programs/osxcross-conf.cpp @@ -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" diff --git a/wrapper/programs/osxcross-env.cpp b/wrapper/programs/osxcross-env.cpp old mode 100644 new mode 100755 index 4a7a894..db469aa --- a/wrapper/programs/osxcross-env.cpp +++ b/wrapper/programs/osxcross-env.cpp @@ -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(p - pp, 30); size_t len = std::min(strlen(start), 60); + + std::cerr << std::endl; std::cerr << std::string(start, len) << std::endl; while (start++ != p) diff --git a/wrapper/programs/osxcross-version.cpp b/wrapper/programs/osxcross-version.cpp old mode 100644 new mode 100755 diff --git a/wrapper/programs/pkg-config.cpp b/wrapper/programs/pkg-config.cpp old mode 100644 new mode 100755 index d3b1d25..48bc126 --- a/wrapper/programs/pkg-config.cpp +++ b/wrapper/programs/pkg-config.cpp @@ -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; diff --git a/wrapper/programs/sw_vers.cpp b/wrapper/programs/sw_vers.cpp old mode 100644 new mode 100755 diff --git a/wrapper/target.cpp b/wrapper/target.cpp index fd3dba2..7031348 100644 --- a/wrapper/target.cpp +++ b/wrapper/target.cpp @@ -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; } } diff --git a/wrapper/tools.cpp b/wrapper/tools.cpp old mode 100644 new mode 100755 index 6b1987f..2de3751 --- a/wrapper/tools.cpp +++ b/wrapper/tools.cpp @@ -31,11 +31,11 @@ #include #include #include -#include #include #include #ifndef _WIN32 +#include #include #include #include @@ -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__ diff --git a/wrapper/tools.h b/wrapper/tools.h old mode 100644 new mode 100755 index 0112b49..1adc11c --- a/wrapper/tools.h +++ b/wrapper/tools.h @@ -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 + bool isendl(T&&) { return false; } + template + 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: