mirror of
https://github.com/Relintai/osxcross.git
synced 2025-02-03 22:45:56 +01:00
split the wrapper into multiple files + some generic wrapper cleanups
This commit is contained in:
parent
07fb200d6c
commit
413c33a5e9
58
wrapper/Makefile
Normal file
58
wrapper/Makefile
Normal 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)
|
132
wrapper/build.sh
132
wrapper/build.sh
@ -15,12 +15,33 @@ EXESUFFIX=""
|
||||
|
||||
function create_wrapper_link
|
||||
{
|
||||
verbose_cmd ln -sf "${TARGETTRIPLE}-wrapper${EXESUFFIX}" "${1}${EXESUFFIX}"
|
||||
# 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}"
|
||||
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
|
||||
|
||||
TARGETTRIPLE=x86_64-apple-${OSXCROSS_TARGET}
|
||||
@ -32,9 +53,14 @@ if [ -n "$BWPLATFORM" ]; then
|
||||
|
||||
if [ $PLATFORM = "Darwin" -a $(uname -s) != "Darwin" ]; then
|
||||
CXX=o32-clang++
|
||||
#CXX=o32-g++
|
||||
FLAGS+="-fvisibility-inlines-hidden "
|
||||
elif [ $PLATFORM = "FreeBSD" -a $(uname -s) != "FreeBSD" ]; then
|
||||
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
|
||||
CXX=w32-clang++
|
||||
FLAGS+="-wc-static-runtime -g "
|
||||
@ -44,6 +70,8 @@ if [ -n "$BWPLATFORM" ]; then
|
||||
FLAGS+="-static-libgcc -static-libstdc++ -g "
|
||||
EXESUFFIX=".exe"
|
||||
fi
|
||||
|
||||
[ -z "$BWCOMPILEONLY" ] && BWCOMPILEONLY=1
|
||||
else
|
||||
PLATFORM=$(uname -s)
|
||||
FLAGS="-march=native $CXXFLAGS "
|
||||
@ -54,92 +82,54 @@ if [ -n "$BWCXX" ]; then
|
||||
CXX=$BWCXX
|
||||
fi
|
||||
|
||||
[ $PLATFORM = "Darwin" ] && FLAGS+="-framework CoreServices -Wno-deprecated "
|
||||
[ $PLATFORM = "FreeBSD" ] && FLAGS+="-lutil "
|
||||
|
||||
if [[ $PLATFORM != *Windows ]] && [ $PLATFORM != "Darwin" ]; then
|
||||
FLAGS+="-lrt -isystem quirks/include"
|
||||
if [ "$PLATFORM" == "Linux" ]; then
|
||||
FLAGS+="-isystem quirks/include "
|
||||
fi
|
||||
|
||||
function compile_wrapper()
|
||||
{
|
||||
mkdir -p ../target ../target/bin
|
||||
export PLATFORM
|
||||
export CXX
|
||||
|
||||
verbose_cmd $CXX compiler.cpp -std=c++0x -pedantic -Wall -Wextra \
|
||||
"-DOSXCROSS_VERSION=\"\\\"$OSXCROSS_VERSION\\\"\"" \
|
||||
"-DOSXCROSS_TARGET=\"\\\"$OSXCROSS_TARGET\\\"\"" \
|
||||
"-DOSXCROSS_OSX_VERSION_MIN=\"\\\"$OSXCROSS_OSX_VERSION_MIN\\\"\"" \
|
||||
"-DOSXCROSS_LINKER_VERSION=\"\\\"$OSXCROSS_LINKER_VERSION\\\"\"" \
|
||||
"-DOSXCROSS_LIBLTO_PATH=\"\\\"$OSXCROSS_LIBLTO_PATH\\\"\"" \
|
||||
-o "../target/bin/${TARGETTRIPLE}-wrapper${EXESUFFIX}" -O2 \
|
||||
$FLAGS $*
|
||||
verbose_cmd make clean
|
||||
|
||||
OSXCROSS_CXXFLAGS="$FLAGS" \
|
||||
verbose_cmd make wrapper -j$JOBS
|
||||
}
|
||||
|
||||
compile_wrapper
|
||||
|
||||
if [ -n "$BWCOMPILEONLY" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
verbose_cmd mv wrapper "../target/bin/${TARGETTRIPLE}-wrapper${EXESUFFIX}"
|
||||
|
||||
pushd "../target/bin" &>/dev/null
|
||||
|
||||
if [ $TARGETCOMPILER = "clang" ]; then
|
||||
create_wrapper_link o32-clang
|
||||
create_wrapper_link o32-clang++
|
||||
create_wrapper_link o32-clang++-libc++
|
||||
|
||||
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++
|
||||
create_wrapper_link clang 2
|
||||
create_wrapper_link clang++ 2
|
||||
create_wrapper_link clang++-libc++ 2
|
||||
elif [ $TARGETCOMPILER = "gcc" ]; then
|
||||
create_wrapper_link o32-gcc
|
||||
create_wrapper_link o32-g++
|
||||
create_wrapper_link o32-g++-libc++
|
||||
|
||||
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++
|
||||
create_wrapper_link gcc 2
|
||||
create_wrapper_link g++ 2
|
||||
create_wrapper_link g++-libc++ 2
|
||||
fi
|
||||
|
||||
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-cc
|
||||
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-c++
|
||||
create_wrapper_link cc
|
||||
create_wrapper_link c++
|
||||
|
||||
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-cc
|
||||
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-c++
|
||||
|
||||
create_wrapper_link osxcross-conf
|
||||
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
|
||||
create_wrapper_link osxcross 1
|
||||
create_wrapper_link osxcross-conf 1
|
||||
create_wrapper_link osxcross-env 1
|
||||
create_wrapper_link osxcross-cmp 1
|
||||
|
||||
if [ "$PLATFORM" != "Darwin" ]; then
|
||||
create_wrapper_link sw_vers
|
||||
create_wrapper_link i386-apple-${OSXCROSS_TARGET}-sw_vers
|
||||
create_wrapper_link x86_64-apple-${OSXCROSS_TARGET}-sw_vers
|
||||
create_wrapper_link sw_vers 1
|
||||
create_wrapper_link dsymutil 1
|
||||
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
|
||||
|
1913
wrapper/compiler.cpp
1913
wrapper/compiler.cpp
File diff suppressed because it is too large
Load Diff
477
wrapper/main.cpp
Normal file
477
wrapper/main.cpp
Normal 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;
|
||||
}
|
@ -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
|
||||
}
|
70
wrapper/programs/osxcross-conf.cpp
Normal file
70
wrapper/programs/osxcross-conf.cpp
Normal 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
|
185
wrapper/programs/osxcross-env.cpp
Normal file
185
wrapper/programs/osxcross-env.cpp
Normal 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
|
36
wrapper/programs/osxcross-version.cpp
Normal file
36
wrapper/programs/osxcross-version.cpp
Normal 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
|
13
wrapper/programs/proginc.h
Normal file
13
wrapper/programs/proginc.h
Normal 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"
|
93
wrapper/programs/sw_vers.cpp
Normal file
93
wrapper/programs/sw_vers.cpp
Normal 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
102
wrapper/progs.h
Normal 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
662
wrapper/target.cpp
Normal 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
153
wrapper/target.h
Normal 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
458
wrapper/tools.cpp
Normal 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
257
wrapper/tools.h
Normal 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
|
Loading…
Reference in New Issue
Block a user