split the wrapper into multiple files + some generic wrapper cleanups

This commit is contained in:
Thomas Pöchtrager 2014-05-17 23:15:15 +02:00
parent 07fb200d6c
commit 413c33a5e9
15 changed files with 2625 additions and 2000 deletions

58
wrapper/Makefile Normal file
View File

@ -0,0 +1,58 @@
PLATFORM ?= $(shell uname -s)
OPTIMIZE ?= 2
LTO ?= 0
OSXCROSS_VERSION ?= unknown
OSXCROSS_TARGET ?= darwin12
OSXCROSS_OSX_VERSION_MIN ?= 10.5
OSXCROSS_LINKER_VERSION ?= 134.9
OSXCROSS_LIBLTO_PATH ?=
OSXCROSS_CXXFLAGS ?=
override CXXFLAGS=-std=c++0x -Wall -Wextra -pedantic -I. -O$(OPTIMIZE)
ifeq ($(LTO), 1)
override CXXFLAGS+=-flto
endif
override CXXFLAGS+=-DOSXCROSS_VERSION="\"$(OSXCROSS_VERSION)\""
override CXXFLAGS+=-DOSXCROSS_TARGET="\"$(OSXCROSS_TARGET)\""
override CXXFLAGS+=-DOSXCROSS_OSX_VERSION_MIN="\"$(OSXCROSS_OSX_VERSION_MIN)\""
override CXXFLAGS+=-DOSXCROSS_LINKER_VERSION="\"$(OSXCROSS_LINKER_VERSION)\""
override CXXFLAGS+=-DOSXCROSS_LIBLTO_PATH="\"$(OSXCROSS_LIBLTO_PATH)\""
override CXXFLAGS+= $(OSXCROSS_CXXFLAGS)
ifneq (,$(findstring FreeBSD, $(PLATFORM)))
override LDFLAGS+=-lutil
else ifneq (,$(findstring Darwin, $(PLATFORM)))
override CXXFLAGS+=-Wno-deprecated
override LDFLAGS+=-framework CoreServices -Wno-deprecated
else ifeq (,$(findstring Windows, $(PLATFORM)))
override LDFLAGS+=-lrt
endif
BIN=wrapper
SRCS= \
main.cpp \
tools.cpp \
target.cpp \
programs/osxcross-version.cpp \
programs/osxcross-env.cpp \
programs/osxcross-conf.cpp \
programs/sw_vers.cpp
OBJS=$(subst .cpp,.o,$(SRCS))
all: wrapper
wrapper: $(OBJS)
$(CXX) $(CXXFLAGS) -o wrapper $(OBJS) $(LDFLAGS)
.PHONY: clean
clean:
rm -f $(BIN) $(OBJS)
-include $(SRCS:cpp=d)

View File

@ -15,12 +15,33 @@ EXESUFFIX=""
function create_wrapper_link function create_wrapper_link
{ {
# arg 2:
# 1: Create a standalone link and links with target triple prefix
# 2: Create links with target triple prefix and shorcut links such as o32, o64, ...
if [ $# -ge 2 ] && [ $2 -eq 1 ]; then
verbose_cmd ln -sf "${TARGETTRIPLE}-wrapper${EXESUFFIX}" "${1}${EXESUFFIX}" verbose_cmd ln -sf "${TARGETTRIPLE}-wrapper${EXESUFFIX}" "${1}${EXESUFFIX}"
fi
verbose_cmd ln -sf "${TARGETTRIPLE}-wrapper${EXESUFFIX}" "i386-apple-${OSXCROSS_TARGET}-${1}${EXESUFFIX}"
verbose_cmd ln -sf "${TARGETTRIPLE}-wrapper${EXESUFFIX}" "x86_64-apple-${OSXCROSS_TARGET}-${1}${EXESUFFIX}"
if [[ $1 == *clang* ]]; then
# Do not create Haswell links for gcc
verbose_cmd ln -sf "${TARGETTRIPLE}-wrapper${EXESUFFIX}" "x86_64h-apple-${OSXCROSS_TARGET}-${1}${EXESUFFIX}"
fi
if [ $# -ge 2 ] && [ $2 -eq 2 ]; then
verbose_cmd ln -sf "${TARGETTRIPLE}-wrapper${EXESUFFIX}" "o32-${1}${EXESUFFIX}"
verbose_cmd ln -sf "${TARGETTRIPLE}-wrapper${EXESUFFIX}" "o64-${1}${EXESUFFIX}"
if [[ $1 == *clang* ]]; then
# Do not create Haswell links for gcc
verbose_cmd ln -sf "${TARGETTRIPLE}-wrapper${EXESUFFIX}" "o64h-${1}${EXESUFFIX}"
fi
fi
} }
[ -z "$OSXCROSS_TARGET" ] && OSXCROSS_TARGET=darwin12
[ -z "$OSXCROSS_OSX_VERSION_MIN" ] && OSXCROSS_OSX_VERSION_MIN=10.5
[ -z "$OSXCROSS_LINKER_VERSION" ] && OSXCROSS_LINKER_VERSION=134.9
[ -z "$TARGETCOMPILER" ] && TARGETCOMPILER=clang [ -z "$TARGETCOMPILER" ] && TARGETCOMPILER=clang
TARGETTRIPLE=x86_64-apple-${OSXCROSS_TARGET} TARGETTRIPLE=x86_64-apple-${OSXCROSS_TARGET}
@ -32,9 +53,14 @@ if [ -n "$BWPLATFORM" ]; then
if [ $PLATFORM = "Darwin" -a $(uname -s) != "Darwin" ]; then if [ $PLATFORM = "Darwin" -a $(uname -s) != "Darwin" ]; then
CXX=o32-clang++ CXX=o32-clang++
#CXX=o32-g++
FLAGS+="-fvisibility-inlines-hidden "
elif [ $PLATFORM = "FreeBSD" -a $(uname -s) != "FreeBSD" ]; then elif [ $PLATFORM = "FreeBSD" -a $(uname -s) != "FreeBSD" ]; then
CXX=amd64-pc-freebsd10.0-clang++ CXX=amd64-pc-freebsd10.0-clang++
FLAGS+="-lrt " #CXX=amd64-pc-freebsd10.0-g++
elif [ $PLATFORM = "NetBSD" -a $(uname -s) != "NetBSD" ]; then
CXX=amd64-pc-netbsd6.1.3-clang++
#CXX=amd64-pc-netbsd6.1.3-g++
elif [ $PLATFORM = "Windows" ]; then elif [ $PLATFORM = "Windows" ]; then
CXX=w32-clang++ CXX=w32-clang++
FLAGS+="-wc-static-runtime -g " FLAGS+="-wc-static-runtime -g "
@ -44,6 +70,8 @@ if [ -n "$BWPLATFORM" ]; then
FLAGS+="-static-libgcc -static-libstdc++ -g " FLAGS+="-static-libgcc -static-libstdc++ -g "
EXESUFFIX=".exe" EXESUFFIX=".exe"
fi fi
[ -z "$BWCOMPILEONLY" ] && BWCOMPILEONLY=1
else else
PLATFORM=$(uname -s) PLATFORM=$(uname -s)
FLAGS="-march=native $CXXFLAGS " FLAGS="-march=native $CXXFLAGS "
@ -54,92 +82,54 @@ if [ -n "$BWCXX" ]; then
CXX=$BWCXX CXX=$BWCXX
fi fi
[ $PLATFORM = "Darwin" ] && FLAGS+="-framework CoreServices -Wno-deprecated " if [ "$PLATFORM" == "Linux" ]; then
[ $PLATFORM = "FreeBSD" ] && FLAGS+="-lutil " FLAGS+="-isystem quirks/include "
if [[ $PLATFORM != *Windows ]] && [ $PLATFORM != "Darwin" ]; then
FLAGS+="-lrt -isystem quirks/include"
fi fi
function compile_wrapper() function compile_wrapper()
{ {
mkdir -p ../target ../target/bin mkdir -p ../target ../target/bin
export PLATFORM
export CXX
verbose_cmd $CXX compiler.cpp -std=c++0x -pedantic -Wall -Wextra \ verbose_cmd make clean
"-DOSXCROSS_VERSION=\"\\\"$OSXCROSS_VERSION\\\"\"" \
"-DOSXCROSS_TARGET=\"\\\"$OSXCROSS_TARGET\\\"\"" \ OSXCROSS_CXXFLAGS="$FLAGS" \
"-DOSXCROSS_OSX_VERSION_MIN=\"\\\"$OSXCROSS_OSX_VERSION_MIN\\\"\"" \ verbose_cmd make wrapper -j$JOBS
"-DOSXCROSS_LINKER_VERSION=\"\\\"$OSXCROSS_LINKER_VERSION\\\"\"" \
"-DOSXCROSS_LIBLTO_PATH=\"\\\"$OSXCROSS_LIBLTO_PATH\\\"\"" \
-o "../target/bin/${TARGETTRIPLE}-wrapper${EXESUFFIX}" -O2 \
$FLAGS $*
} }
compile_wrapper compile_wrapper
if [ -n "$BWCOMPILEONLY" ]; then
exit 0
fi
verbose_cmd mv wrapper "../target/bin/${TARGETTRIPLE}-wrapper${EXESUFFIX}"
pushd "../target/bin" &>/dev/null pushd "../target/bin" &>/dev/null
if [ $TARGETCOMPILER = "clang" ]; then if [ $TARGETCOMPILER = "clang" ]; then
create_wrapper_link o32-clang create_wrapper_link clang 2
create_wrapper_link o32-clang++ create_wrapper_link clang++ 2
create_wrapper_link o32-clang++-libc++ create_wrapper_link clang++-libc++ 2
create_wrapper_link o64-clang
create_wrapper_link o64-clang++
create_wrapper_link o64-clang++-libc++
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-clang
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-clang++
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-clang++-libc++
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-clang
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-clang++
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-clang++-libc++
elif [ $TARGETCOMPILER = "gcc" ]; then elif [ $TARGETCOMPILER = "gcc" ]; then
create_wrapper_link o32-gcc create_wrapper_link gcc 2
create_wrapper_link o32-g++ create_wrapper_link g++ 2
create_wrapper_link o32-g++-libc++ create_wrapper_link g++-libc++ 2
create_wrapper_link o64-gcc
create_wrapper_link o64-g++
create_wrapper_link o64-g++-libc++
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-gcc
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-g++
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-g++-libc++
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-gcc
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-g++
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-g++-libc++
fi fi
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-cc create_wrapper_link cc
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-c++ create_wrapper_link c++
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-cc create_wrapper_link osxcross 1
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-c++ create_wrapper_link osxcross-conf 1
create_wrapper_link osxcross-env 1
create_wrapper_link osxcross-conf create_wrapper_link osxcross-cmp 1
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-osxcross-conf
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-osxcross-conf
create_wrapper_link osxcross-env
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-osxcross-env
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-osxcross-env
create_wrapper_link osxcross
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-osxcross
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-osxcross
if [ "$PLATFORM" != "Darwin" ]; then if [ "$PLATFORM" != "Darwin" ]; then
create_wrapper_link sw_vers create_wrapper_link sw_vers 1
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-sw_vers create_wrapper_link dsymutil 1
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-sw_vers
fi fi
create_wrapper_link dsymutil
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-dsymutil
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-dsymutil
popd &>/dev/null popd &>/dev/null
popd &>/dev/null popd &>/dev/null

File diff suppressed because it is too large Load Diff

477
wrapper/main.cpp Normal file
View File

@ -0,0 +1,477 @@
/***********************************************************************
* OSXCross Compiler Wrapper *
* Copyright (C) 2014 by Thomas Poechtrager *
* t.poechtrager@gmail.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***********************************************************************/
/*
* Debug messages can be enabled by setting 'OCDEBUG' (ENV) to >= 1.
*/
#include "compat.h"
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <climits>
#include <cassert>
#ifndef _WIN32
#include <unistd.h>
#include <sys/wait.h>
#endif
#include "tools.h"
#include "target.h"
#include "progs.h"
using namespace tools;
using namespace target;
namespace {
//
// detectTarget():
// detect target and setup invocation command
//
#define PABREAK \
else target.args.push_back(arg); \
break
bool detectTarget(int argc, char **argv, Target &target) {
const char *cmd = argv[0];
const char *p = strrchr(cmd, '/');
size_t len;
size_t i = 0;
if (p)
cmd = &p[1];
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 getVal = [&](char * arg, const char * flag, int & i)->const char * {
const char *val = arg + strlen(flag);
if (!*val) {
val = argv[++i];
if (i >= argc) {
std::cerr << "missing argument for '" << val << "'" << std::endl;
return nullptr;
}
}
return val;
};
if (char *p = getenv("MACOSX_DEPLOYMENT_TARGET")) {
target.OSNum = parseOSVersion(p);
unsetenv("MACOSX_DEPLOYMENT_TARGET");
}
for (int i = 1; i < argc; ++i) {
char *arg = argv[i];
if (arg[0] == '-') {
switch (arg[1]) {
case 'a': {
// -a
if (!strncmp(arg, "-arch", 5)) {
const char *val = getVal(arg, "-arch", i);
if (!val)
return false;
Arch arch = parseArch(val);
if (arch == Arch::unknown) {
std::cerr << "warning: '-arch': unknown architecture '" << val
<< "'" << std::endl;
}
const char *name = getArchName(arch);
if (strcmp(val, name)) {
std::cerr << "warning: '-arch': " << val << " != " << name
<< std::endl;
}
target.addArch(arch);
}
PABREAK;
}
case 'E': {
// -E
if (!strcmp(arg, "-E")) {
target.nocodegen = true;
delayedfuncs.push_back([](Target &t) {
if (t.targetarch.size() > 1) {
std::cerr << "cannot use '-E' with multiple -arch options"
<< std::endl;
return false;
}
return true;
});
target.args.push_back(arg);
}
PABREAK;
}
case 'm': {
// -m
if (!strncmp(arg, "-mmacosx-version-min=", 21)) {
const char *val = arg + 21;
target.OSNum = parseOSVersion(val);
if (target.OSNum != val) {
std::cerr << "warning: '-mmacosx-version-min=' ("
<< target.OSNum.Str() << " != " << val << ")"
<< std::endl;
}
} else if (!strcmp(arg, "-m16") || !strcmp(arg, "-mx32")) {
std::cerr << "'" << arg << "' not supported" << std::endl;
return false;
} else if (!strcmp(arg, "-m32")) {
target.addArch(Arch::i386);
} else if (!strcmp(arg, "-m64")) {
target.addArch(Arch::x86_64);
}
PABREAK;
}
case 'o': {
// -o
if (!strcmp(arg, "-oc-use-gcc-libs")) {
if (target.isGCC()) {
std::cerr << "warning: '" << arg << "' has no effect"
<< std::endl;
break;
}
target.stdlib = StdLib::libstdcxx;
target.usegcclibs = true;
} else if (!strncmp(arg, "-o", 2)) {
target.outputname = getVal(arg, "-o", i);
}
PABREAK;
}
case 's': {
// -s
if (!strncmp(arg, "-stdlib=", 8)) {
const char *val = arg + 8;
size_t i = 0;
if (target.isGCC())
warnExtension("-stdlib=");
for (auto stdlibname : StdLibNames) {
if (!strcmp(val, stdlibname)) {
target.stdlib = static_cast<StdLib>(i);
break;
}
++i;
}
if (i == (sizeof(StdLibNames) / sizeof(StdLibNames[0]))) {
std::cerr << "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 << ", ";
}
}
std::cerr << std::endl;
return false;
}
} else if (!strncmp(arg, "-std=", 5)) {
const char *val = arg + 5;
target.langstd = val;
}
PABREAK;
}
case 'x': {
if (!strncmp(arg, "-x", 2)) {
target.lang = getVal(arg, "-x", i);
}
PABREAK;
}
default:
target.args.push_back(arg);
}
continue;
}
// Detect source file
target.args.push_back(arg);
const char *prevarg = "";
if (i > 1) {
prevarg = argv[i - 1];
if (prevarg[0] == '-' && strlen(prevarg) > 2 &&
strcmp(prevarg, "-MT") && strcmp(prevarg, "-MF"))
prevarg = "";
}
if (prevarg[0] != '-' || !strcmp(prevarg, "-c")) {
constexpr const char *badexts[] = { ".o", ".a" };
const char *ext = getFileExtension(arg);
bool b = false;
for (auto &badext : badexts) {
if (!strcmp(ext, badext)) {
b = true;
break;
}
}
if (!b)
target.sourcefile = arg;
}
}
for (auto fun : delayedfuncs) {
if (!fun(target))
return false;
}
return true;
};
auto checkCXXLib = [&]() {
if (target.compiler.size() <= 7)
return;
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;
}
target.compiler.resize(target.compiler.size() - 7);
target.stdlib = StdLib::libcxx;
}
};
if (auto *prog = program::getprog(cmd))
(*prog)(argc, argv, target);
// -> x86_64 <- -apple-darwin13
p = strchr(cmd, '-');
len = (p ? p : cmd) - cmd;
for (auto arch : ArchNames) {
++i;
if (!strncmp(cmd, arch, len)) {
target.arch = static_cast<Arch>(i - 1);
cmd += len;
if (*cmd++ != '-')
return false;
if (strncmp(cmd, "apple-", 6))
return false;
cmd += 6;
if (strncmp(cmd, "darwin", 6))
return false;
if (!(p = strchr(cmd, '-')))
return false;
target.target = std::string(cmd, p - cmd);
target.compiler = &p[1];
if (target.compiler == "cc")
target.compiler = getDefaultCompiler();
else if (target.compiler == "c++")
target.compiler = getDefaultCXXCompiler();
else if (auto *prog = program::getprog(target.compiler))
(*prog)(argc, argv, target);
if (target.target != getDefaultTarget()) {
std::cerr << "warning: target mismatch (" << target.target
<< " != " << getDefaultTarget() << ")" << std::endl;
}
if (!parseArgs())
return false;
checkCXXLib();
return target.setup();
}
}
if (!strncmp(cmd, "o32", 3))
target.arch = Arch::i386;
else if (!strncmp(cmd, "o64", 3))
target.arch = Arch::x86_64;
else
return false;
if (const char *p = strchr(cmd, '-')) {
target.compiler = &cmd[p - cmd + 1];
}
if (!parseArgs())
return false;
checkCXXLib();
return target.setup();
}
} // unnamed namespace
//
// Main routine
//
int main(int argc, char **argv) {
char bbuf[sizeof(benchmark)];
auto b = new (bbuf) benchmark;
Target target;
char **cargs = nullptr;
int debug = 0;
int rc = -1;
if (!detectTarget(argc, argv, target)) {
std::cerr << "cannot detect target" << std::endl;
return 1;
}
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;
std::cerr << "[d] detected stdlib: " << getStdLibString(target.stdlib)
<< std::endl;
if (debug >= 3) {
std::cerr << "[d] detected source file: "
<< (target.sourcefile ? target.sourcefile : "-") << std::endl;
std::cerr << "[d] detected language: " << target.getLangName()
<< std::endl;
}
b->resume();
}
}
concatEnvVariable("COMPILER_PATH", target.execpath);
auto printCommand = [&]() {
std::string in;
std::string out;
for (int i = 0; i < argc; ++i) {
in += argv[i];
in += " ";
}
for (auto &arg : target.fargs) {
out += arg;
out += " ";
}
for (auto &arg : target.args) {
out += arg;
out += " ";
}
std::cerr << "[d] --> " << in << std::endl;
std::cerr << "[d] <-- " << out << std::endl;
};
if (rc == -1) {
cargs = new char *[target.fargs.size() + target.args.size() + 1];
size_t i = 0;
for (auto &arg : target.fargs) {
cargs[i++] = const_cast<char *>(arg.c_str());
}
for (auto &arg : target.args) {
cargs[i++] = const_cast<char *>(arg.c_str());
}
cargs[i] = nullptr;
}
if (debug) {
time_type diff = b->getDiff();
if (rc == -1)
printCommand();
std::cerr << "[d] === time spent in wrapper: " << diff / 1000000.0 << " ms"
<< std::endl;
}
if (rc == -1 && execvp(cargs[0], cargs)) {
std::cerr << "invoking compiler failed" << std::endl;
if (!debug)
printCommand();
return 1;
}
return rc;
}

View File

@ -1,16 +0,0 @@
namespace {
#ifdef _WIN32
int setenv(const char *name, const char *value, int overwrite) {
std::string buf;
(void)overwrite; // TODO
buf = name;
buf += '=';
buf += value;
return putenv(buf.c_str());
}
int unsetenv(const char *name) { return setenv(name, "", 1); }
#endif
}

View File

@ -0,0 +1,70 @@
/***********************************************************************
* OSXCross Compiler Wrapper *
* Copyright (C) 2014 by Thomas Poechtrager *
* t.poechtrager@gmail.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***********************************************************************/
#include "proginc.h"
using namespace tools;
using namespace target;
namespace program {
namespace osxcross {
int conf(const Target &target) {
std::string sdkpath;
OSVersion OSXVersionMin = getDefaultMinTarget();
const char *ltopath = getLibLTOPath();
if (!target.getSDKPath(sdkpath)) {
std::cerr << "cannot find Mac OS X SDK!" << std::endl;
return 1;
}
if (!OSXVersionMin.Num())
OSXVersionMin = target.getSDKOSNum();
if (!ltopath)
ltopath = "";
std::cout << "export OSXCROSS_VERSION=" << getOSXCrossVersion() << 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_SDK_VERSION=" << target.getSDKOSNum().shortStr()
<< std::endl;
std::cout << "export OSXCROSS_SDK=" << sdkpath << std::endl;
std::cout << "export OSXCROSS_TARBALL_DIR=" << target.execpath
<< "/../../tarballs" << std::endl;
std::cout << "export OSXCROSS_PATCH_DIR=" << target.execpath
<< "/../../patches" << std::endl;
std::cout << "export OSXCROSS_TARGET_DIR=" << target.execpath << "/.."
<< std::endl;
std::cout << "export OSXCROSS_BUILD_DIR=" << target.execpath << "/../../build"
<< std::endl;
std::cout << "export OSXCROSS_CCTOOLS_PATH=" << target.execpath << std::endl;
std::cout << "export OSXCROSS_LIBLTO_PATH=" << ltopath << std::endl;
std::cout << "export OSXCROSS_LINKER_VERSION=" << getLinkerVersion()
<< std::endl;
return 0;
}
} // namespace osxcross
} // namespace program

View File

@ -0,0 +1,185 @@
/***********************************************************************
* OSXCross Compiler Wrapper *
* Copyright (C) 2014 by Thomas Poechtrager *
* t.poechtrager@gmail.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***********************************************************************/
#include "proginc.h"
#include <map>
using namespace tools;
using namespace target;
namespace program {
namespace osxcross {
int env(int argc, char **argv) {
char epath[PATH_MAX + 1];
char *oldpath = getenv("PATH");
char *oldlibpath = getenv("LD_LIBRARY_PATH");
constexpr const char *ltopath = getLibLTOPath();
assert(oldpath);
if (!getExecutablePath(epath, sizeof(epath)))
exit(EXIT_FAILURE);
// TODO: escape?
auto check = [](const char * p, const char * desc)->const char * {
if (!p)
return nullptr;
const char *pp = p;
for (; *p; ++p) {
auto badChar = [&](const char *p) {
std::cerr << desc << " should not contain '" << *p << "'" << std::endl;
const char *start =
p - std::min(static_cast<size_t>(p - pp), static_cast<size_t>(30));
size_t len = std::min(strlen(start), static_cast<size_t>(60));
std::cerr << std::string(start, len) << std::endl;
while (start++ != p)
std::cerr << " ";
std::cerr << "^" << std::endl;
};
switch (*p) {
case '"':
case '\'':
case '$':
case ' ':
case ';':
badChar(p);
return nullptr;
}
}
return pp;
};
if (argc <= 1) {
const std::string &pname = getParentProcessName();
if (pname == "csh" || pname == "tcsh") {
std::cerr << std::endl << "you are invoking this program from a C shell, "
<< std::endl << "please use " << std::endl << std::endl
<< "setenv PATH `" << epath << "/osxcross-env -v=PATH`"
<< std::endl << "setenv LD_LIBRARY_PATH `" << epath
<< "/osxcross-env -v=LD_LIBRARY_PATH`" << std::endl << std::endl
<< "instead." << std::endl << std::endl;
}
}
auto hasPath = [](const char * ov, const char * v, const char * vs)->bool {
// ov = old value
// v = value
// vs = value suffix
if (!ov || !v)
return false;
bool hasPathSeparator = false;
for (auto p = ov; *p; ++p) {
if (*p == ':') {
hasPathSeparator = true;
break;
}
}
static std::string tmp;
auto check = [&](int t)->bool {
tmp.clear();
if (t == 0)
tmp = ':';
tmp += v;
if (vs)
tmp += vs;
if (t == 1)
tmp += ':';
return strstr(ov, tmp.c_str()) != nullptr;
};
return ((hasPathSeparator && (check(0) || check(1))) || check(-1));
};
if (!check(oldpath, "PATH") || !check(oldlibpath, "LD_LIBRARY_PATH") ||
!check(ltopath, "LIB LTO PATH"))
return 1;
std::stringstream path;
std::stringstream librarypath;
std::map<std::string, std::string> vars;
path << oldpath;
if (!hasPath(oldpath, epath, nullptr))
path << ":" << epath;
if (oldlibpath)
librarypath << oldlibpath;
if (!hasPath(oldlibpath, epath, "/../lib"))
librarypath << ":" << epath << "/../lib";
if (ltopath && !hasPath(oldlibpath, ltopath, nullptr))
librarypath << ":" << ltopath;
vars["PATH"] = path.str();
vars["LD_LIBRARY_PATH"] = librarypath.str();
auto printVariable = [&](const std::string & var)->bool {
auto it = vars.find(var);
if (it == vars.end()) {
std::cerr << "unknown variable '" << var << "'" << std::endl;
return false;
}
std::cout << it->second << std::endl;
return true;
};
if (argc <= 1) {
std::cout << std::endl;
for (auto &v : vars) {
std::cout << "export " << v.first << "=";
if (!printVariable(v.first))
return 1;
std::cout << std::endl;
}
} else {
if (strncmp(argv[1], "-v=", 3))
return 1;
const char *var = argv[1] + 3;
return static_cast<int>(printVariable(var));
}
return 0;
}
} // namespace osxcross
} // namespace program

View File

@ -0,0 +1,36 @@
/***********************************************************************
* OSXCross Compiler Wrapper *
* Copyright (C) 2014 by Thomas Poechtrager *
* t.poechtrager@gmail.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***********************************************************************/
#include "proginc.h"
using namespace tools;
using namespace target;
namespace program {
namespace osxcross {
int version() {
std::cout << "version: " << getOSXCrossVersion() << std::endl;
return 0;
}
} // namespace osxcross
} // namespace program

View File

@ -0,0 +1,13 @@
#include "compat.h"
#include <vector>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cassert>
#include "tools.h"
#include "target.h"
#include "progs.h"

View File

@ -0,0 +1,93 @@
/***********************************************************************
* OSXCross Compiler Wrapper *
* Copyright (C) 2014 by Thomas Poechtrager *
* t.poechtrager@gmail.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***********************************************************************/
#include "proginc.h"
using namespace tools;
using namespace target;
namespace program {
int sw_vers(int argc, char **argv, const Target &target) {
auto genFakeBuildVer = [](std::string & build)->std::string & {
std::stringstream tmp;
#if __has_builtin(__builtin_readcyclecounter)
srand(static_cast<unsigned int>(__builtin_readcyclecounter()));
#else
srand(static_cast<unsigned int>(getNanoSeconds()));
#endif
for (int i = 0; i < 5; ++i)
tmp << std::hex << (rand() % 16 + 1);
build = tmp.str();
build.resize(5);
return build;
};
auto getProductVer = [&]()->OSVersion {
char *p = getenv("OSXCROSS_SW_VERS_OSX_VERSION");
OSVersion OSNum;
if (!p)
p = getenv("MACOSX_DEPLOYMENT_TARGET");
if (p)
OSNum = parseOSVersion(p);
else
OSNum = getDefaultMinTarget();
if (!OSNum.Num())
OSNum = target.getSDKOSNum();
return OSNum;
};
if (argc == 2) {
std::stringstream str;
if (!strcmp(argv[1], "-productName")) {
str << "Mac OS X";
} else if (!strcmp(argv[1], "-productVersion")) {
str << getProductVer().shortStr();
} else if (!strcmp(argv[1], "-buildVersion")) {
std::string build;
str << genFakeBuildVer(build);
} else {
return 1;
}
std::cout << str.str() << std::endl;
} else if (argc == 1) {
std::string build;
std::cout << "ProductName: Mac OS X" << std::endl;
std::cout << "ProductVersion: " << getProductVer().shortStr() << std::endl;
std::cout << "BuildVersion: " << genFakeBuildVer(build) << std::endl;
}
return 0;
}
} // namespace program

102
wrapper/progs.h Normal file
View File

@ -0,0 +1,102 @@
/***********************************************************************
* OSXCross Compiler Wrapper *
* Copyright (C) 2014 by Thomas Poechtrager *
* t.poechtrager@gmail.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***********************************************************************/
namespace target {
struct Target;
}
namespace program {
using target::Target;
class prog {
public:
typedef int (*f1)();
typedef int (*f2)(int, char **);
typedef int (*f3)(int, char **, const target::Target &);
typedef int (*f4)(const target::Target &);
constexpr prog(const char *name, f1 fun)
: name(name), fun1(fun), fun2(), fun3(), fun4(), type(1) {}
constexpr prog(const char *name, f2 fun)
: name(name), fun1(), fun2(fun), fun3(), fun4(), type(2) {}
constexpr prog(const char *name, f3 fun)
: name(name), fun1(), fun2(), fun3(fun), fun4(), type(3) {}
constexpr prog(const char *name, f4 fun)
: name(name), fun1(), fun2(), fun3(), fun4(fun), type(4) {}
void operator()(int argc, char **argv, const Target &target) const {
switch (type) {
case 1:
exit(fun1());
case 2:
exit(fun2(argc, argv));
case 3:
exit(fun3(argc, argv, target));
case 4:
exit(fun4(target));
}
}
bool operator==(const char *name) const { return !strcmp(name, this->name); }
template<class T>
bool operator==(const T &name) const { return name == this->name; }
const char *name;
private:
f1 fun1;
f2 fun2;
f3 fun3;
f4 fun4;
int type;
};
int sw_vers(int argc, char **argv, const target::Target &target);
namespace osxcross {
int version();
int env(int argc, char **argv);
int conf(const Target &target);
} // namespace osxcross
static int dummy() { return 0; }
constexpr prog programs[] = { { "sw_vers", sw_vers },
{ "dsymutil", dummy },
{ "osxcross", osxcross::version },
{ "osxcross-env", osxcross::env },
{ "osxcross-conf", osxcross::conf },
{ "wrapper", dummy } };
template <class T> const prog *getprog(const T &name) {
for (auto &p : programs) {
if (p == name)
return &p;
}
return nullptr;
}
} // namespace program

662
wrapper/target.cpp Normal file
View File

@ -0,0 +1,662 @@
/***********************************************************************
* OSXCross Compiler Wrapper *
* Copyright (C) 2014 by Thomas Poechtrager *
* t.poechtrager@gmail.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***********************************************************************/
#include "compat.h"
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <map>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <cassert>
#include "tools.h"
#include "target.h"
namespace target {
OSVersion Target::getSDKOSNum() const {
if (target.size() < 7)
return OSVersion();
int n = atoi(target.c_str() + 6);
return OSVersion(10, 4 + (n - 8));
}
bool Target::getSDKPath(std::string &path) const {
OSVersion SDKVer = getSDKOSNum();
path = execpath;
path += "/../SDK/MacOSX";
path += SDKVer.shortStr();
if (SDKVer <= OSVersion(10, 4))
path += "u";
path += ".sdk";
return dirExists(path);
}
void Target::addArch(const Arch arch) {
auto &v = targetarch;
for (size_t i = 0; i < v.size(); ++i) {
if (v[i] == arch) {
v.erase(v.begin() + i);
addArch(arch);
return;
}
}
v.push_back(arch);
}
bool Target::haveArch(const Arch arch) {
for (auto a : targetarch) {
if (arch == a)
return true;
}
return false;
}
bool Target::hasLibCXX() const { return getSDKOSNum() >= OSVersion(10, 7); }
bool Target::libCXXIsDefaultCXXLib() const {
OSVersion OSNum = this->OSNum;
if (!OSNum.Num())
OSNum = getSDKOSNum();
return stdlib != libstdcxx && hasLibCXX() && !isGCC() &&
OSNum >= OSVersion(10, 9);
}
bool Target::isLibCXX() const {
return stdlib == StdLib::libcxx || libCXXIsDefaultCXXLib();
}
bool Target::isLibSTDCXX() const { return stdlib == StdLib::libstdcxx; }
bool Target::isC(bool r) {
if (!r && isCXX())
return false;
if (langGiven() && lang[0] != 'o' &&
(!strcmp(lang, "c") || !strcmp(lang, "c-header")))
return true;
if (haveSourceFile()) {
if (!strcmp(getFileExtension(sourcefile), ".c"))
return true;
}
return compiler.find("++") == std::string::npos && !isObjC(true);
}
bool Target::isCXX() {
bool CXXCompiler = compiler.find("++") != std::string::npos;
if (!langGiven() && CXXCompiler && !isObjC(true))
return true;
if (langGiven() && !strncmp(lang, "c++", 3))
return true;
constexpr const char *CXXFileExts[] = { ".C", ".cc", ".cpp", ".CPP",
".c++", ".cp", ".cxx" };
if (haveSourceFile()) {
const char *ext = getFileExtension(sourcefile);
if (*ext) {
for (auto &cxxfe : CXXFileExts) {
if (!strcmp(ext, cxxfe))
return true;
}
}
}
return CXXCompiler && !isC(true) && !isObjC(true);
}
bool Target::isObjC(bool r) {
if (!r && isCXX())
return false;
if (langGiven() && lang[0] == 'o')
return true;
if (haveSourceFile()) {
const char *ext = getFileExtension(sourcefile);
if (!strcmp(ext, ".m") || !strcmp(ext, ".mm"))
return true;
}
return false;
}
const char *Target::getLangName() {
if (isC())
return "C";
else if (isCXX())
return "C++";
else if (isObjC())
return "Obj-C";
else
return "unknown";
}
bool Target::isCXX11orNewer() const {
if (!langStdGiven())
return false;
constexpr const char *STD[] = { "c++0x", "gnu++0x", "c++11", "gnu++11",
"c++1y", "gnu++1y", "c++14", "gnu++14",
"c++1z", "gnu++1z" };
for (auto std : STD) {
if (!strcmp(langstd, std))
return true;
}
return false;
}
const std::string Target::getFullCompilerName() const {
std::string compiler;
if (isGCC()) {
compiler = execpath;
compiler += "/";
compiler += getTriple();
compiler += "-";
}
if (isGCC())
compiler += "base-";
compiler += this->compiler;
return compiler;
}
bool Target::findClangIntrinsicHeaders(std::string &path) const {
std::string clangbin;
static std::stringstream dir;
assert(isClang());
getPathOfCommand(compiler.c_str(), clangbin);
if (clangbin.empty())
return false;
static ClangVersion clangversion;
static std::string pathtmp;
dir.str(std::string());
clangversion = ClangVersion();
pathtmp.clear();
auto check = []()->bool {
listFiles(dir.str().c_str(), nullptr, [](const char *file) {
if (file[0] != '.' && isDirectory(file, dir.str().c_str())) {
ClangVersion cv = parseClangVersion(file);
if (cv != ClangVersion()) {
static std::stringstream tmp;
tmp.str(std::string());
auto checkDir = [&](std::stringstream &dir)
{
static std::string intrindir;
auto &file = dir;
intrindir = dir.str();
file << "/xmmintrin.h";
if (fileExists(file.str())) {
if (cv > clangversion) {
clangversion = cv;
pathtmp.swap(intrindir);
}
return true;
}
return false;
};
tmp << dir.str() << "/" << file << "/include";
if (!checkDir(tmp)) {
tmp.str(std::string());
tmp << dir.str() << "/" << file;
checkDir(tmp);
}
}
return true;
}
return true;
});
return clangversion != ClangVersion();
};
dir << clangbin << "/../lib/clang";
if (!check()) {
dir.str(std::string());
#ifdef __APPLE__
constexpr const char *OSXIntrinDirs[] = {
"/Library/Developer/CommandLineTools/usr/lib/clang",
"/Applications/Contents/Developer/Toolchains/"
"XcodeDefault.xctoolchain/usr/lib/clang"
};
for (auto intrindir : OSXIntrinDirs) {
dir << intrindir;
if (check()) {
break;
}
dir.str(std::string());
}
#endif
if (!dir.rdbuf()->in_avail()) {
dir << clangbin << "/../include/clang";
if (!check())
return false;
}
}
path.swap(pathtmp);
return clangversion != ClangVersion();
}
void Target::setupGCCLibs(Arch arch) {
assert(stdlib == StdLib::libstdcxx);
fargs.push_back("-nodefaultlibs");
std::string SDKPath;
std::stringstream GCCLibSTDCXXPath;
std::stringstream GCCLibPath;
std::stringstream tmp;
getSDKPath(SDKPath);
GCCLibSTDCXXPath << SDKPath << "/../../" << otriple << "/lib";
GCCLibPath << SDKPath << "/../../lib/gcc/" << otriple << "/"
<< gccversion.Str();
switch (arch) {
case Arch::i386:
case Arch::i486:
case Arch::i586:
case Arch::i686:
GCCLibSTDCXXPath << "/" << getArchName(i386);
GCCLibPath << "/" << getArchName(Arch::i386);
default:
;
}
fargs.push_back("-Qunused-arguments");
tmp << GCCLibSTDCXXPath.str() << "/libstdc++.a";
fargs.push_back(tmp.str());
tmp.str(std::string());
tmp << GCCLibSTDCXXPath.str() << "/libsupc++.a";
fargs.push_back(tmp.str());
tmp.str(std::string());
tmp << GCCLibPath.str() << "/libgcc.a";
fargs.push_back(tmp.str());
tmp.str(std::string());
tmp << GCCLibPath.str() << "/libgcc_eh.a";
fargs.push_back(tmp.str());
fargs.push_back("-lc");
}
bool Target::setup() {
std::string SDKPath;
OSVersion SDKOSNum = getSDKOSNum();
if (!isKnownCompiler()) {
std::cerr << "warning: unknown compiler '" << compiler << "'" << std::endl;
}
if (!getSDKPath(SDKPath)) {
std::cerr << "cannot find Mac OS X SDK (expected in: " << SDKPath << ")"
<< std::endl;
return false;
}
if (targetarch.empty())
targetarch.push_back(arch);
if (!langStdGiven()) {
if (isC())
langstd = getDefaultCStandard();
else if (isCXX())
langstd = getDefaultCXXStandard();
}
triple = getArchName(arch);
triple += "-";
triple += vendor;
triple += "-";
triple += target;
otriple = getArchName(Arch::x86_64);
otriple += "-";
otriple += vendor;
otriple += "-";
otriple += target;
if (!OSNum.Num()) {
if (stdlib == StdLib::libcxx) {
OSNum = OSVersion(10, 7); // Default to 10.7 for libc++
} else {
OSNum = getDefaultMinTarget();
}
}
if (OSNum > SDKOSNum) {
std::cerr << "targeted OS X Version must be <= " << SDKOSNum.Str()
<< " (SDK)" << std::endl;
return false;
} else if (OSNum < OSVersion(10, 4)) {
std::cerr << "targeted OS X Version must be >= 10.4" << std::endl;
return false;
}
if (stdlib == StdLib::unset) {
if (libCXXIsDefaultCXXLib()) {
stdlib = StdLib::libcxx;
} else {
stdlib = StdLib::libstdcxx;
}
} else if (stdlib == StdLib::libcxx) {
if (!hasLibCXX()) {
std::cerr << "libc++ requires the SDK from 10.7 (or later)" << std::endl;
return false;
}
if (OSNum.Num() && OSNum < OSVersion(10, 7)) {
std::cerr << "libc++ requires '-mmacosx-version-min=10.7' (or later)"
<< std::endl;
return false;
}
}
std::string CXXHeaderPath = SDKPath;
string_vector AdditionalCXXHeaderPaths;
auto addCXXPath = [&](const std::string &path) {
std::string tmp;
tmp = CXXHeaderPath;
tmp += "/";
tmp += path;
AdditionalCXXHeaderPaths.push_back(tmp);
};
switch (stdlib) {
case StdLib::libcxx: {
CXXHeaderPath += "/usr/include/c++/v1";
if (!dirExists(CXXHeaderPath)) {
std::cerr << "cannot find " << getStdLibString(stdlib) << " headers"
<< std::endl;
return false;
}
break;
}
case StdLib::libstdcxx: {
if (isGCC() && /*isCXX11orNewer()*/ true)
break;
if (usegcclibs) {
// Use libs from './build_gcc.sh' installation
CXXHeaderPath += "/../../";
CXXHeaderPath += otriple;
CXXHeaderPath += "/include/c++";
static std::vector<GCCVersion> v;
v.clear();
listFiles(CXXHeaderPath.c_str(), nullptr, [](const char *path) {
if (path[0] != '.')
v.push_back(parseGCCVersion(path));
return false;
});
if (v.empty()) {
std::cerr << "'-oc-use-gcc-libs' requires gcc to be installed "
"(./build_gcc.sh)" << std::endl;
return false;
}
std::sort(v.begin(), v.end());
gccversion = v[v.size() - 1];
CXXHeaderPath += "/";
CXXHeaderPath += gccversion.Str();
addCXXPath(otriple);
} else {
// Use SDK libs
std::string tmp;
if (SDKOSNum <= OSVersion(10, 5))
CXXHeaderPath += "/usr/include/c++/4.0.0";
else
CXXHeaderPath += "/usr/include/c++/4.2.1";
tmp = getArchName(arch);
tmp += "-apple-";
tmp += target;
addCXXPath(tmp);
}
if (!dirExists(CXXHeaderPath)) {
std::cerr << "cannot find " << getStdLibString(stdlib) << " headers"
<< std::endl;
return false;
}
break;
}
case StdLib::unset:
abort();
}
fargs.push_back(getFullCompilerName());
if (isClang()) {
std::string tmp;
fargs.push_back("-target");
fargs.push_back(getTriple());
tmp = "-mlinker-version=";
tmp += getLinkerVersion();
fargs.push_back(tmp);
tmp.clear();
#ifndef __APPLE__
if (!findClangIntrinsicHeaders(tmp)) {
std::cerr << "cannot find clang intrinsic headers, please report this "
"issue to the OSXCross project" << std::endl;
} else {
fargs.push_back("-isystem");
fargs.push_back(tmp);
}
tmp.clear();
#endif
fargs.push_back("-isysroot");
fargs.push_back(SDKPath);
if (isCXX()) {
tmp = "-stdlib=";
tmp += getStdLibString(stdlib);
fargs.push_back(tmp);
if (stdlib == StdLib::libcxx ||
(stdlib == StdLib::libstdcxx && usegcclibs)) {
fargs.push_back("-nostdinc++");
fargs.push_back("-Qunused-arguments");
}
if (stdlib == StdLib::libstdcxx && usegcclibs && targetarch.size() < 2) {
// Use libs from './build_gcc' installation
setupGCCLibs(targetarch[0]);
}
}
} else if (isGCC()) {
if (isLibCXX()) {
if (!langStdGiven())
langstd = "c++0x";
else if (!isCXX11orNewer()) {
std::cerr << "warning: libc++ requires -std=c++11 (or later) with gcc"
<< std::endl;
}
}
/* TODO: libgcc */
if (isCXX() && (/*!isCXX11orNewer() ||*/ isLibCXX())) {
fargs.push_back("-nostdinc++");
fargs.push_back("-nodefaultlibs");
if (haveSourceFile() && !isGCH()) {
std::string tmp;
tmp = "-L";
tmp += SDKPath;
tmp += "/usr/lib";
fargs.push_back(tmp);
fargs.push_back("-lc");
if (isLibCXX()) {
fargs.push_back("-lc++");
fargs.push_back("-lc++abi");
} else if (isLibSTDCXX()) {
// Hack: Use SDKs libstdc++ as long
// >= -std=c++11 is not given.
fargs.push_back("-lstdc++");
}
fargs.push_back(OSNum <= OSVersion(10, 4) ? "-lgcc_s.10.4"
: "-lgcc_s.10.5");
}
} else if (!isLibCXX() /*&& isCXX11orNewer()*/ && !isGCH()) {
fargs.push_back("-static-libgcc");
fargs.push_back("-static-libstdc++");
}
if (OSNum <= OSVersion(10, 5))
fargs.push_back("-Wl,-no_compact_unwind");
}
auto addCXXHeaderPath = [&](const std::string &path) {
fargs.push_back(isClang() ? "-cxx-isystem" : "-isystem");
fargs.push_back(path);
};
addCXXHeaderPath(CXXHeaderPath);
for (auto &path : AdditionalCXXHeaderPaths)
addCXXHeaderPath(path);
if (langGiven() && !usegcclibs) {
// usegcclibs: delay it to later
fargs.push_back("-x");
fargs.push_back(lang);
}
if (langStdGiven()) {
std::string tmp;
tmp = "-std=";
tmp += langstd;
fargs.push_back(tmp);
}
if (OSNum.Num()) {
std::string tmp;
tmp = "-mmacosx-version-min=";
tmp += OSNum.Str();
fargs.push_back(tmp);
}
for (auto arch : targetarch) {
bool is32bit = false;
switch (arch) {
case Arch::i386:
case Arch::i486:
case Arch::i586:
case Arch::i686:
is32bit = true;
case Arch::x86_64:
if (isGCC()) {
if (targetarch.size() > 1)
break;
fargs.push_back(is32bit ? "-m32" : "-m64");
} else if (isClang()) {
if (usegcclibs && targetarch.size() > 1)
break;
fargs.push_back("-arch");
fargs.push_back(getArchName(arch));
}
break;
default:
std::cerr << "unsupported architecture " << getArchName(arch) << ""
<< std::endl;
return false;
}
}
if (haveOutputName() &&
(targetarch.size() <= 1 || (!isGCC() && !usegcclibs))) {
fargs.push_back("-o");
fargs.push_back(outputname);
}
return true;
}
} // namespace target

153
wrapper/target.h Normal file
View File

@ -0,0 +1,153 @@
/***********************************************************************
* OSXCross Compiler Wrapper *
* Copyright (C) 2014 by Thomas Poechtrager *
* t.poechtrager@gmail.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***********************************************************************/
namespace target {
using namespace tools;
//
// Default values for the Target struct
//
constexpr const char *getDefaultVendor() { return "apple"; }
constexpr const char *getDefaultTarget() { return OSXCROSS_TARGET; }
constexpr const char *getDefaultCompiler() { return "clang"; }
constexpr const char *getDefaultCXXCompiler() { return "clang++"; }
constexpr const char *getLinkerVersion() { return OSXCROSS_LINKER_VERSION; }
constexpr const char *getLibLTOPath() {
#ifdef OSXCROSS_LIBLTO_PATH
return OSXCROSS_LIBLTO_PATH;
#else
return nullptr;
#endif
}
constexpr const char *getOSXCrossVersion() {
#ifdef OSXCROSS_VERSION
return OSXCROSS_VERSION[0] ? OSXCROSS_VERSION : "unknown";
#else
return "unknown";
#endif
}
inline const char *getDefaultCStandard() {
return getenv("OSXCROSS_C_STANDARD");
}
inline const char *getDefaultCXXStandard() {
return getenv("OSXCROSS_CXX_STANDARD");
}
#ifdef OSXCROSS_OSX_VERSION_MIN
inline OSVersion getDefaultMinTarget() {
if (!strcmp(OSXCROSS_OSX_VERSION_MIN, "default"))
return OSVersion();
return parseOSVersion(OSXCROSS_OSX_VERSION_MIN);
}
#else
constexpr OSVersion getDefaultMinTarget() { return OSVersion(); }
#endif
//
// Target
//
struct Target {
Target()
: vendor(getDefaultVendor()), target(getDefaultTarget()),
stdlib(StdLib::unset), usegcclibs(), nocodegen(),
compiler(getDefaultCompiler()), lang(), langstd(), sourcefile(),
outputname() {
if (!getExecutablePath(execpath, sizeof(execpath)))
abort();
}
OSVersion getSDKOSNum() const;
bool getSDKPath(std::string &path) const;
void addArch(const Arch arch);
bool haveArch(const Arch arch);
bool hasLibCXX() const;
bool libCXXIsDefaultCXXLib() const;
bool isLibCXX() const;
bool isLibSTDCXX() const;
bool haveSourceFile() { return sourcefile != nullptr; }
bool haveOutputName() { return outputname != nullptr; }
bool isC(bool r = false);
bool isCXX();
bool isObjC(bool r = false);
bool isGCH() {
if (haveOutputName()) {
const char *ext = getFileExtension(outputname);
return !strcmp(ext, ".gch");
}
return false;
}
bool isClang() const { return !compiler.compare(0, 4, "clang", 4); }
bool isGCC() const {
return !compiler.compare(0, 3, "gcc") || !compiler.compare(0, 3, "g++");
}
bool isKnownCompiler() const { return isClang() || isGCC(); }
bool langGiven() const { return lang != nullptr; }
bool langStdGiven() const { return langstd != nullptr; }
const char *getLangName();
bool isCXX11orNewer() const;
const std::string &getTriple() const { return triple; }
const std::string getFullCompilerName() const;
bool findClangIntrinsicHeaders(std::string &path) const;
void setupGCCLibs(Arch arch);
bool setup();
const char *vendor;
Arch arch;
std::vector<Arch> targetarch;
std::string target;
OSVersion OSNum;
StdLib stdlib;
bool usegcclibs;
GCCVersion gccversion;
bool nocodegen;
std::string compiler;
std::string triple;
std::string otriple;
const char *lang;
const char *langstd;
string_vector fargs;
string_vector args;
const char *sourcefile;
const char *outputname;
char execpath[PATH_MAX + 1];
};
} // namespace target

458
wrapper/tools.cpp Normal file
View File

@ -0,0 +1,458 @@
/***********************************************************************
* OSXCross Compiler Wrapper *
* Copyright (C) 2014 by Thomas Poechtrager *
* t.poechtrager@gmail.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***********************************************************************/
#include "compat.h"
#include <vector>
#include <string>
#include <sstream>
#include <istream>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cassert>
#include <unistd.h>
#include <sys/time.h>
#include <sys/stat.h>
#ifndef _WIN32
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#else
#include <windows.h>
#include <tlhelp32.h>
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <libproc.h>
#endif
#ifdef __FreeBSD__
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/user.h>
#include <libutil.h>
#endif
#include "tools.h"
namespace tools {
char *getExecutablePath(char *buf, size_t len) {
char *p;
#ifdef __APPLE__
unsigned int l = len;
if (_NSGetExecutablePath(buf, &l) != 0)
return nullptr;
#elif defined(__FreeBSD__)
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
size_t l = len;
if (sysctl(mib, 4, buf, &l, nullptr, 0) != 0)
return nullptr;
#elif defined(_WIN32)
size_t l = GetModuleFileName(nullptr, buf, (DWORD)len);
#else
ssize_t l = readlink("/proc/self/exe", buf, len);
#endif
if (l <= 0)
return nullptr;
buf[len - 1] = '\0';
p = strrchr(buf, '/');
if (*p) {
*p = '\0';
}
return buf;
}
const std::string &getParentProcessName() {
static std::string name;
#ifdef _WIN32
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe;
auto zerope = [&]() {
memset(&pe, 0, sizeof(pe));
pe.dwSize = sizeof(PROCESSENTRY32);
};
zerope();
auto pid = GetCurrentProcessId();
decltype(pid) ppid = -1;
if (Process32First(h, &pe)) {
do {
if (pe.th32ProcessID == pid) {
ppid = pe.th32ParentProcessID;
break;
}
} while (Process32Next(h, &pe));
}
if (ppid != static_cast<decltype(ppid)>(-1)) {
PROCESSENTRY32 *ppe = nullptr;
zerope();
if (Process32First(h, &pe)) {
do {
std::cout << pe.szExeFile << " " << pe.th32ProcessID << std::endl;
if (pe.th32ProcessID == ppid) {
ppe = &pe;
break;
}
} while (Process32Next(h, &pe));
}
if (ppe) {
char *p = strrchr(ppe->szExeFile, '\\');
if (p) {
name = p + 1;
} else {
name = ppe->szExeFile;
}
}
}
CloseHandle(h);
if (!name.empty()) {
return name;
}
#else
auto getName = [](const char * path)->const char * {
if (const char *p = strrchr(path, '/')) {
return p + 1;
}
return path;
};
auto ppid = getppid();
#ifdef __APPLE__
char path[PROC_PIDPATHINFO_MAXSIZE];
if (proc_pidpath(ppid, path, sizeof(path))) {
name = getName(path);
return name;
}
#elif defined(__FreeBSD__)
struct kinfo_proc *proc = kinfo_getproc(ppid);
if (proc) {
name = getName(proc->ki_comm);
free(proc);
return name;
}
#else
std::stringstream file;
file << "/proc/" << ppid << "/comm";
if (getFileContent(file.str(), name)) {
if (!name.empty() && name.rbegin()[0] == '\n') {
name.resize(name.size() - 1);
}
return name;
} else {
file.str(std::string());
file << "/proc/" << ppid << "/exe";
char buf[PATH_MAX + 1];
if (readlink(file.str().c_str(), buf, sizeof(buf)) > 0) {
buf[PATH_MAX] = '\0';
name = getName(buf);
return name;
}
}
#endif
#endif
name = "unknown";
return name;
}
#ifdef _WIN32
std::string &fixPathDiv(std::string &path) {
for (auto &c : path) {
if (c == '/')
c = '\\';
}
return path;
}
#endif
//
// Environment
//
void concatEnvVariable(const char *var, const std::string val) {
std::string nval = val;
if (char *oldval = getenv(var)) {
nval += ":";
nval += oldval;
}
setenv(var, nval.c_str(), 1);
}
//
// Files and Directories
//
std::string *getFileContent(const std::string &file, std::string &content) {
std::ifstream f(file.c_str());
if (!f.is_open())
return nullptr;
f.seekg(0, std::ios::end);
auto len = f.tellg();
f.seekg(0, std::ios::beg);
if (len != static_cast<decltype(len)>(-1))
content.reserve(static_cast<size_t>(f.tellg()));
content.assign(std::istreambuf_iterator<char>(f),
std::istreambuf_iterator<char>());
return &content;
}
bool writeFileContent(const std::string &file, const std::string &content) {
std::ofstream f(file.c_str());
if (!f.is_open())
return false;
f << content;
return f.good();
}
bool fileExists(const std::string &dir) {
struct stat st;
return !stat(dir.c_str(), &st);
}
bool dirExists(const std::string &dir) {
struct stat st;
return !stat(dir.c_str(), &st) && S_ISDIR(st.st_mode);
}
typedef bool (*listfilescallback)(const char *file);
bool isDirectory(const char *file, const char *prefix) {
struct stat st;
if (prefix) {
std::string tmp = prefix;
tmp += "/";
tmp += file;
return !stat(tmp.c_str(), &st) && S_ISDIR(st.st_mode);
} else {
return !stat(file, &st) && S_ISDIR(st.st_mode);
}
}
bool listFiles(const char *dir, std::vector<std::string> *files,
listfilescallback cmp) {
#ifndef _WIN32
DIR *d = opendir(dir);
dirent *de;
if (!d)
return false;
while ((de = readdir(d))) {
if ((!cmp || cmp(de->d_name)) && files) {
files->push_back(de->d_name);
}
}
closedir(d);
return true;
#else
WIN32_FIND_DATA fdata;
HANDLE handle;
handle = FindFirstFile(dir, &fdata);
if (handle == INVALID_HANDLE_VALUE)
return false;
do {
if ((!cmp || cmp(fdata.cFileName)) && files) {
files->push_back(fdata.cFileName);
}
} while (FindNextFile(handle, &fdata));
FindClose(handle);
return true;
#endif
}
typedef bool (*realpathcmp)(const char *file, const struct stat &st);
bool isExecutable(const char *f, const struct stat &) {
return !access(f, F_OK | X_OK);
}
std::string &realPath(const char *file, std::string &result, realpathcmp cmp) {
char *PATH = getenv("PATH");
const char *p = PATH ? PATH : "";
std::string sfile;
struct stat st;
do {
if (*p == ':')
++p;
while (*p && *p != ':')
sfile += *p++;
sfile += "/";
sfile += file;
if (!stat(sfile.c_str(), &st) && (!cmp || cmp(sfile.c_str(), st))) {
break;
}
sfile.clear();
} while (*p);
#ifndef _WIN32
if (!sfile.empty()) {
char buf[PATH_MAX + 1];
ssize_t len;
if ((len = readlink(sfile.c_str(), buf, PATH_MAX)) != -1) {
result.assign(buf, len);
}
}
#endif
result.swap(sfile);
return result;
}
std::string &getPathOfCommand(const char *command, std::string &result) {
realPath(command, result, isExecutable);
const size_t len = strlen(command) + 1;
if (result.size() < len) {
result.clear();
return result;
}
result.resize(result.size() - len);
return result;
}
const char *getFileName(const char *file) {
const char *p = strrchr(file, '/');
if (!p)
p = file;
else
++p;
return p;
}
const char *getFileExtension(const char *file) {
const char *p = strrchr(file, '.');
if (!p)
p = "";
return p;
}
//
// Time
//
time_type getNanoSeconds() {
#ifdef __APPLE__
union {
AbsoluteTime at;
time_type ull;
} tmp;
tmp.ull = mach_absolute_time();
Nanoseconds ns = AbsoluteToNanoseconds(tmp.at);
tmp.ull = UnsignedWideToUInt64(ns);
return tmp.ull;
#elif defined(__linux__)
struct timespec tp;
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
return static_cast<time_type>((tp.tv_sec * 1000000000LL) + tp.tv_nsec);
#endif
struct timeval tv;
if (gettimeofday(&tv, nullptr) == 0)
return static_cast<time_type>((tv.tv_sec * 1000000000LL) +
(tv.tv_usec * 1000));
abort();
}
//
// OSVersion
//
OSVersion parseOSVersion(const char *OSVer) {
const char *p = OSVer;
OSVersion OSNum;
OSNum.major = atoi(p);
while (*p && *p++ != '.')
;
if (!*p)
return OSNum;
OSNum.minor = atoi(p);
while (*p && *p++ != '.')
;
if (!*p)
return OSNum;
OSNum.patch = atoi(p);
return OSNum;
}
//
// OS Compat
//
#ifdef _WIN32
int setenv(const char *name, const char *value, int overwrite) {
std::string buf;
(void)overwrite; // TODO
buf = name;
buf += '=';
buf += value;
return putenv(buf.c_str());
}
int unsetenv(const char *name) { return setenv(name, "", 1); }
#endif
} // namespace tools

257
wrapper/tools.h Normal file
View File

@ -0,0 +1,257 @@
/***********************************************************************
* OSXCross Compiler Wrapper *
* Copyright (C) 2014 by Thomas Poechtrager *
* t.poechtrager@gmail.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***********************************************************************/
namespace tools {
typedef std::vector<std::string> string_vector;
//
// Executable path
//
char *getExecutablePath(char *buf, size_t len);
const std::string &getParentProcessName();
std::string &fixPathDiv(std::string &path);
//
// Environment
//
void concatEnvVariable(const char *var, const std::string val);
//
// Files and Directories
//
std::string *getFileContent(const std::string &file, std::string &content);
bool writeFileContent(const std::string &file, const std::string &content);
bool fileExists(const std::string &dir);
bool dirExists(const std::string &dir);
typedef bool (*listfilescallback)(const char *file);
bool isDirectory(const char *file, const char *prefix);
bool listFiles(const char *dir, std::vector<std::string> *files,
listfilescallback cmp);
typedef bool (*realpathcmp)(const char *file, const struct stat &st);
bool isExecutable(const char *f, const struct stat &);
std::string &realPath(const char *file, std::string &result, realpathcmp cmp);
std::string &getPathOfCommand(const char *command, std::string &result);
const char *getFileName(const char *file);
const char *getFileExtension(const char *file);
inline const char *getFileName(const std::string &file) {
return getFileName(file.c_str());
}
inline const char *getFileExtension(const std::string &file) {
return getFileExtension(file.c_str());
}
//
// Time
//
typedef unsigned long long time_type;
time_type getNanoSeconds();
class benchmark {
public:
benchmark() { s = getTime(); }
time_type getDiff() { return getTime() - s; }
void halt() { h = getTime(); }
void resume() { s += getTime() - h; }
~benchmark() {
time_type diff = getTime() - s;
std::cerr << "took: " << diff / 1000000.0 << " ms" << std::endl;
}
private:
__attribute__((always_inline)) time_type getTime() {
return getNanoSeconds();
}
time_type h;
time_type s;
};
//
// OSVersion
//
#undef major
#undef minor
#undef patch
struct OSVersion {
constexpr OSVersion(int major, int minor, int patch = 0)
: major(major), minor(minor), patch(patch) {}
constexpr OSVersion() : major(), minor(), patch() {}
constexpr int Num() const {
return major * 10000 + minor * 100 + patch;
};
constexpr bool operator>(const OSVersion &OSNum) const {
return Num() > OSNum.Num();
}
constexpr bool operator>=(const OSVersion &OSNum) const {
return Num() >= OSNum.Num();
}
constexpr bool operator<(const OSVersion &OSNum) const {
return Num() < OSNum.Num();
}
constexpr bool operator<=(const OSVersion &OSNum) const {
return Num() <= OSNum.Num();
}
constexpr bool operator!=(const OSVersion &OSNum) const {
return Num() != OSNum.Num();
}
bool operator!=(const char *val) const {
size_t c = 0;
const char *p = val;
while (*p) {
if (*p++ == '.')
++c;
}
switch (c) {
case 1:
return shortStr() != val;
case 2:
return Str() != val;
default:
return true;
}
}
std::string Str() const {
std::stringstream tmp;
tmp << major << "." << minor << "." << patch;
return tmp.str();
}
std::string shortStr() const {
std::stringstream tmp;
tmp << major << "." << minor;
return tmp.str();
}
int major;
int minor;
int patch;
};
static_assert(OSVersion(10, 6) != OSVersion(10, 5), "");
OSVersion parseOSVersion(const char *OSVer);
typedef OSVersion GCCVersion;
#define parseGCCVersion parseOSVersion
typedef OSVersion ClangVersion;
#define parseClangVersion parseOSVersion
//
// OS Compat
//
#ifdef _WIN32
int setenv(const char *name, const char *value, int overwrite);
int unsetenv(const char *name);
#endif
//
// Arch
//
enum Arch {
armv4t,
armv5,
armv6,
armv7,
armv7f,
armv7k,
armv7s,
armv6m,
armv7m,
armv7em,
armv8,
arm64,
arm64v8,
i386,
i486,
i586,
i686,
x86_64,
x86_64h, // Haswell
ppc,
ppc64,
unknown
};
constexpr const char *ArchNames[] = {
"armv4t", "armv5", "armv6", "armv7", "armv7f", "armv7k", "armv7s",
"amrv6m", "armv7m", "armv7em", "armv8", "arm64", "arm64v8", "i386",
"i486", "i586", "i686", "x86_64", "x86_64h", "ppc", "ppc64",
"unknown"
};
constexpr const char *getArchName(Arch arch) { return ArchNames[arch]; }
inline Arch parseArch(const char *arch) {
size_t i = 0;
for (auto archname : ArchNames) {
if (!strcmp(arch, archname)) {
return static_cast<Arch>(i);
}
++i;
}
return Arch::unknown;
}
//
// Stdlib
//
enum StdLib {
unset,
libcxx,
libstdcxx
};
constexpr const char *StdLibNames[] = { "default", "libc++", "libstdc++" };
constexpr const char *getStdLibString(StdLib stdlib) {
return StdLibNames[stdlib];
}
} // namespace tools