Wrapper changes:

* Support for generating fat object files with gcc and '-foc-use-gcc-libstdc++'
  has been removed.

  This feature was not 100% correctly implemented; using multiple source files
  did not work, i.e.: 'o32-g++ -m32 -m64 a.cpp b.cpp' would have failed;
  And I refuse to implement that, instead I am removing all source file handling
  from the wrapper with this commit for simplicity.

  This feature should be implemented in the gcc driver instead.

  This does NOT affect clang's fat object file support, which is implemented in
  clang's darwin driver.

* '-oc-use-gcc-lib' has been renamed to '-foc-use-gcc-libstdc++'.

* Added support for '-stdc++' and '-gstdc++' compiler "shortcuts"

  o32-clang++ --> uses libstdc++ for <= 10.8 and libc++ for >= 10.9

  o32-clang++-libc++ --> uses the SDK's libc++
  o32-clang++-stdc++ --> uses the SDK's libstdc++
  o32-clang++-gstdc++ --> uses gcc's (build_gcc.sh) libstdc++

* Entirely rewrote the command line parser; the previous one wasn't very
  readable.

* Minor Readme Updates

* Added unit tests

* Removed OSXCROSS_C_STANDARD / OSXCROSS_CXX_STANDARD support

  I am no longer parsing -std=, so this feature has to be dropped.
  Setting the language standard via an env variable isn't a good idea anyway.

* Removed unneeded stuff

Other Changes:

* Version bump to 0.11
This commit is contained in:
Thomas Pöchtrager 2015-08-22 23:15:27 +02:00
parent 03e904d5f1
commit 5afdf2b471
15 changed files with 869 additions and 742 deletions

View File

@ -1,3 +1,18 @@
/****************************** v0.11 ********************************/
changed:
* '-oc-use-gcc-libs' has been renamed to '-foc-use-gcc-libstdc++'
* support for generating fat object files with gcc and '-foc-use-gcc-libstdc++'
has been removed.
added:
* support for '-stdc++' and '-gstdc++' compiler "shortcuts"
o32-clang++ --> uses libstdc++ for <= 10.8 and libc++ for >= 10.9
o32-clang++-libc++ --> uses the SDK's libc++
o32-clang++-stdc++ --> uses the SDK's libstdc++
o32-clang++-gstdc++ --> uses gcc's (build_gcc.sh) libstdc++
* unit tests (wrapper)
/****************************** v0.10 ********************************/
changed:

View File

@ -12,7 +12,7 @@ Note: *You can compile for 64-bit in a 32-bit environment.*
Click on setup-*.exe and install the following packages:
`git`, `make`, `clang`, `gcc-core`, `gcc-objc`, `gcc-g++`,
`patch`, `wget`, `libuuid-devel` and `pkg-config`
`patch`, `wget`, `libuuid-devel`, `openssl` and `pkg-config`
#### Step 2: ####
@ -87,7 +87,7 @@ Verify Compiler-RT works:
![](images/cygwin/compiler-rt/4.png)
## EXAMPLES: ###
## EXAMPLE USAGE: ###
### osxcross-macports ###

View File

@ -72,7 +72,7 @@ to install them.
ATTENTION:
OSXCross links libgcc and libstdc++ statically by default (this affects `-oc-use-gcc-libs` too).
OSXCross links libgcc and libstdc++ statically by default (this affects `-foc-use-gcc-libstdc++` too).
You can turn this behavior off with `OSXCROSS_GCC_NO_STATIC_RUNTIME=1` (env).
### PACKAGING THE SDK: ###
@ -152,26 +152,29 @@ Note: libc++ requires Mac OS X 10.7 or newer! If you really need C++11 for
an older OS X version, then you can do the following:
1. Build GCC so you have an up-to-date libstdc++
2. Build your source code with GCC or with clang and '-oc-use-gcc-libs'
2. Build your source code with GCC or `clang++-gstdc++` / `clang++ -foc-use-gcc-libstdc++`
Usage Examples:
* Clang:
* C++98: `o32-clang++ -stdlib=libc++ test.cpp -o test`
* C++11: `o32-clang++ -stdlib=libc++ -std=c++11 tes1.cpp -o test`
* C++1y: `o32-clang++ -stdlib=libc++ -std=c++1y test1.cpp -o test`
* C++11: `o32-clang++ -stdlib=libc++ -std=c++11 test1.cpp -o test`
* C++14: `o32-clang++ -stdlib=libc++ -std=c++14 test1.cpp -o test`
* C++1z: `o32-clang++ -stdlib=libc++ -std=c++1z test1.cpp -o test`
* Clang (shortcut):
* C++98: `o32-clang++-libc++ test.cpp -o test`
* C++11: `o32-clang++-libc++ -std=c++11 test.cpp -o test`
* C++1y: `o32-clang++-libc++ -std=c++1y test.cpp -o test`
* C++14: `o32-clang++-libc++ -std=c++14 test.cpp -o test`
* C++1z: `o32-clang++-libc++ -std=c++1z test.cpp -o test`
* GCC (defaults to C++11 with libc++)
* GCC
* C++11: `o32-g++-libc++ test.cpp`
* C++1y: `o32-g++-libc++ -std=c++1y test.cpp -o test`
* C++11: `o32-g++-libc++ -std=c++11 test.cpp`
* C++14: `o32-g++-libc++ -std=c++14 test.cpp -o test`
* C++1z: `o32-g++-libc++ -std=c++1z test.cpp -o test`
##### Building test1.cpp and test2.cpp with LTO (Link Time Optimization): #####
@ -218,4 +221,4 @@ You will need gcc/g++/gcc-objc 4.6+.
* xar: New BSD
### CREDITS: ####
* [cjacker for the cctools linux port](https://code.google.com/p/ios-toolchain-based-on-clang-for-linux/source/browse/#svn%2Ftrunk%2Fcctools-porting%2Fpatches)
* [cjacker for the initial cctools port](https://code.google.com/p/ios-toolchain-based-on-clang-for-linux/source/browse/#svn%2Ftrunk%2Fcctools-porting%2Fpatches)

1
TODO
View File

@ -0,0 +1 @@
document 'osxcross-man'

View File

@ -74,7 +74,7 @@ if [ -z "$OSX_VERSION_MIN" ]; then
fi
fi
OSXCROSS_VERSION=0.10
OSXCROSS_VERSION=0.11
X86_64H_SUPPORTED=0

View File

@ -11,8 +11,8 @@ PATCH_DIR=$BASE_DIR/patches
SDK_DIR=$TARGET_DIR/SDK
PLATFORM=$(uname -s)
SCRIPT=$(basename $0)
ARCH=$(uname -m)
SCRIPT=$(basename $0)
if [ -z "$USESYSTEMCOMPILER" ]; then
# Default to gcc on some OSs rather than clang due to either
@ -55,7 +55,7 @@ fi
# enable debug messages
test -n "$OCDEBUG" && set -x
[ -n "$OCDEBUG" ] && set -x
if [[ $SCRIPT != *wrapper/build.sh ]]; then
# how many concurrent jobs should be used for compiling?
@ -133,7 +133,7 @@ function extract()
bzip2 -dc $1 | tar $tarflags -
;;
*)
echo "Unhandled archive type"
echo "Unhandled archive type" 2>&1
exit 1
;;
esac
@ -146,7 +146,8 @@ function extract()
if [[ $PLATFORM == CYGWIN* ]]; then
# Work around Cygwin brokenness.
function ln() {
function ln()
{
[[ $1 == -* ]] && rm -f $3
$(which ln) $@
}

View File

@ -135,6 +135,8 @@ if [ $TARGETCOMPILER = "clang" ]; then
create_wrapper_link clang 2
create_wrapper_link clang++ 2
create_wrapper_link clang++-libc++ 2
create_wrapper_link clang++-stdc++ 2
create_wrapper_link clang++-gstdc++ 2
elif [ $TARGETCOMPILER = "gcc" ]; then
create_wrapper_link gcc 2
create_wrapper_link g++ 2

View File

@ -51,18 +51,149 @@ namespace {
int unittest = 0;
void checkIncludePath(const char *opt, const char *path) {
void warnExtension(const char *extension) {
static bool noextwarnings = !!getenv("OSXCROSS_NO_EXTENSION_WARNINGS");
if (noextwarnings)
return;
warn << extension << " is an osxcross extension" << warn.endl();
warninfo << "you can silence this warning via "
<< "'OSXCROSS_NO_EXTENSION_WARNINGS=1' (env)" << warninfo.endl();
}
__attribute__((unused))
void warnDeprecated(const char *flag, const char *replacement = nullptr) {
if (replacement)
warn << flag << " is deprecated; "
<< "please use " << replacement << " instead"
<< warn.endl();
else
warn << flag << " is deprecated and will be "
<< "removed soon" << warn.endl();
}
//
// Command Line Options
//
namespace commandopts {
typedef bool (*optFun)(Target &target, const char *opt, const char *val,
char **);
bool versionmin(Target &target, const char *, const char *val, char **) {
target.OSNum = parseOSVersion(val);
if (target.OSNum != val)
warn << "'-mmacosx-version-min=' (" << target.OSNum.Str()
<< " != " << val << ")" << warn.endl();
return true;
}
bool arch(Target &target, const char *opt, const char *val, char **) {
Arch arch;
if (!strcmp(opt, "-arch")) {
arch = parseArch(val);
if (arch == Arch::unknown)
warn << "'-arch': unknown architecture '" << val << "'"
<< warn.endl();
const char *name = getArchName(arch);
if (strcmp(val, name))
warn << "'-arch': '" << val << "' != '" << name << "'" << warn.endl();
} else {
if (!strcmp(opt, "-m16") || !strcmp(opt, "-mx32")) {
err << "'" << opt << "' is not supported" << err.endl();
return false;
} else if (!strcmp(opt, "-m32")) {
arch = Arch::i386;
} else if (!strcmp(opt, "-m64")) {
arch = Arch::x86_64;
} else {
__builtin_unreachable();
}
}
if (target.isClang())
target.addArch(arch);
else
target.arch = arch;
return true;
}
bool stdlib(Target &target, const char *, const char *val, char **) {
if (target.isGCC())
warnExtension("'-stdlib='");
size_t i = 0;
for (auto stdlibname : StdLibNames) {
if (!strcmp(val, stdlibname)) {
target.stdlib = static_cast<StdLib>(i);
break;
}
++i;
}
if (i == (sizeof(StdLibNames) / sizeof(StdLibNames[0]))) {
err << "value of '-stdlib=' must be ";
for (size_t j = 0; j < i; ++j) {
err << "'" << StdLibNames[j] << "'";
if (j == i - 2)
err << " or ";
else if (j < i - 2)
err << ", ";
}
err << err.endl();
return false;
}
return true;
}
bool outputname(Target &target, const char *, const char *val, char **) {
target.outputname = val;
return true;
}
bool usegcclibstdcxx(Target &target, const char *, const char *, char **) {
target.stdlib = StdLib::libstdcxx;
target.usegcclibs = true;
return true;
}
bool runprog(Target &target, const char *, const char *progname, char **cargs) {
auto *prog = program::getprog(progname);
if (!prog)
exit(EXIT_FAILURE);
std::vector<char *> args;
args.push_back(const_cast<char *>(progname));
while (*cargs)
args.push_back(*cargs++);
args.push_back(nullptr);
(*prog)(args.size() - 1, args.data(), target);
}
bool checkincludepath(Target &, const char *opt, const char *path, char **) {
#ifndef __APPLE__
constexpr const char *DangerousIncludePaths[] = { "/usr/include",
"/usr/local/include" };
if (!path)
return;
static bool noinccheck = !!getenv("OSXCROSS_NO_INCLUDE_PATH_WARNINGS");
if (noinccheck)
return;
return true;
#ifndef _WIN32
char buf[PATH_MAX + 1];
@ -93,15 +224,127 @@ void checkIncludePath(const char *opt, const char *path) {
(void)opt;
(void)path;
#endif
return true;
}
void warnExtension(const char *extension) {
static bool noextwarnings = !!getenv("OSXCROSS_NO_EXTENSION_WARNINGS");
if (noextwarnings)
constexpr struct Opt {
const char *name;
const size_t namelen;
const optFun fun;
const bool valrequired;
const bool pusharg;
const char *valseparator;
const size_t valseparatorlen;
constexpr Opt(const char *name, optFun fun, const bool valrequired = false,
const bool pusharg = false, const char *valseparator = nullptr)
: name(name), namelen(slen(name)), fun(fun),
valrequired(valrequired), pusharg(pusharg),
valseparator(valseparator),
valseparatorlen(valseparator ? slen(valseparator) : 0) {}
} opts[] = {
{"-mmacosx-version-min", versionmin, true, false, "="},
{"-stdlib", stdlib, true, false, "="},
{"-arch", arch, true},
{"-m16", arch},
{"-m32", arch},
{"-mx32", arch},
{"-m64", arch},
{"-o", outputname, true, true},
{"-foc-use-gcc-libstdc++", usegcclibstdcxx},
{"-foc-run-prog", runprog, true, false, "="}, // for internal use only
{"-isystem", checkincludepath, true, true},
{"-icxx-isystem", checkincludepath, true, true},
{"-cxx-isystem", checkincludepath, true, true},
{"-I", checkincludepath, true, true},
};
bool parse(int argc, char **argv, Target &target) {
target.args.reserve(argc);
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 != '-') {
target.args.push_back(arg);
continue;
}
bool pusharg = true;
int j = i;
for (const Opt &opt : opts) {
if (strncmp(arg, opt.name, opt.namelen))
continue;
pusharg = opt.pusharg;
const char *val = nullptr;
if (opt.valrequired) {
val = arg + opt.namelen;
if (opt.valseparator &&
strncmp(val, opt.valseparator, opt.valseparatorlen)) {
err << "expected '" << opt.name << opt.valseparator << "<val>' "
<< "instead of '" << arg << "'" << err.endl();
return false;
} else {
val += opt.valseparatorlen;
}
if (!opt.valseparator && !*val && i < argc - 1)
val = argv[++i];
if (!*val) {
err << "missing argument for '" << opt.name << "'" << err.endl();
return false;
}
}
if (opt.fun && !opt.fun(target, opt.name, val, &argv[i + 1]))
return false;
break;
}
if (pusharg) {
for (; j <= i; ++j)
target.args.push_back(argv[j]);
}
}
return true;
}
} // namespace commandopts
void detectCXXLib(Target &target) {
if (target.compilername.size() <= 7)
return;
warn << extension << " is an osxcross extension" << warn.endl();
warninfo << "you can silence this warning via "
<< "'OSXCROSS_NO_EXTENSION_WARNINGS=1' (env)" << warninfo.endl();
StdLib prevstdlib = target.stdlib;
if (endsWith(target.compilername, "-stdc++")) {
target.stdlib = StdLib::libstdcxx;
target.compilername.resize(target.compilername.size() - 7);
} else if (endsWith(target.compilername, "-gstdc++")) {
target.stdlib = StdLib::libstdcxx;
target.usegcclibs = true;
target.compilername.resize(target.compilername.size() - 8);
} else if (endsWith(target.compilername, "-libc++")) {
target.stdlib = StdLib::libcxx;
target.compilername.resize(target.compilername.size() - 7);
}
if (prevstdlib != StdLib::unset && prevstdlib != target.stdlib)
warn << "ignoring '-stdlib=" << getStdLibString(prevstdlib) << "'"
<< warn.endl();
}
//
@ -109,22 +352,6 @@ void warnExtension(const char *extension) {
// detect target and setup invocation command
//
#define PABREAK \
else target.args.push_back(arg); \
break
#define PAPUSHARG \
target.args.push_back(arg); \
break
#define PAPUSHARGANDVAL(splitted) \
do { \
target.args.push_back(arg); \
if (splitted && i < argc) \
target.args.push_back(argv[i]); \
} while (0); \
break
bool detectTarget(int argc, char **argv, Target &target) {
const char *cmd = argv[0];
const char *p = strrchr(cmd, '/');
@ -134,297 +361,6 @@ bool detectTarget(int argc, char **argv, Target &target) {
if (p)
cmd = &p[1];
target.args.reserve(static_cast<size_t>(argc));
auto parseArgs = [&]()->bool {
typedef bool (*delayedfun)(Target &);
std::vector<delayedfun> delayedfuncs;
auto runLater = [&](delayedfun fun) {
for (auto dfun : delayedfuncs) {
if (dfun == fun)
return;
}
delayedfuncs.push_back(fun);
};
auto getVal = [&](char * arg, const char * flag, int & i)->const char * {
const char *val = arg + strlen(flag);
if (!*val) {
val = argv[++i];
if (i >= argc) {
err << "missing argument for '" << flag << "'" << err.endl();
return nullptr;
}
}
return val;
};
auto installGCCArchExtensionWarning = [&]() {
runLater([](Target &t) {
if (t.targetarch.size() > 1 && t.isGCC())
warnExtension("using multiple '-arch' flags with gcc");
return true;
});
};
if (char *p = getenv("MACOSX_DEPLOYMENT_TARGET")) {
target.OSNum = parseOSVersion(p);
unsetenv("MACOSX_DEPLOYMENT_TARGET");
}
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) {
warn << "'-arch': unknown architecture '" << val << "'"
<< warn.endl();
}
const char *name = getArchName(arch);
if (strcmp(val, name))
warn << "'-arch': '" << val << "' != '" << name << "'"
<< warn.endl();
target.addArch(arch);
installGCCArchExtensionWarning();
}
PABREAK;
}
case 'E': {
// -E
if (!strcmp(arg, "-E")) {
target.nocodegen = true;
runLater([](Target &t) {
if (t.targetarch.size() > 1) {
err << "cannot use '-E' with multiple -arch options"
<< err.endl();
return false;
}
return true;
});
target.args.push_back(arg);
}
PABREAK;
}
case 'f': {
// -f
if (!strcmp(arg, "-flto") || !strncmp(arg, "-flto=", 5)) {
target.args.push_back(arg);
if (target.isClang())
continue;
runLater([](Target &t) {
if (t.targetarch.size() > 1) {
err << "gcc does not support '-flto' with multiple "
<< "'-arch' flags" << err.endl();
return false;
}
return true;
});
}
PABREAK;
}
case 'c':
case 'i':
case 'I': {
// c
// i
// I
constexpr const char *OptsToCheck[] = {
"-isystem", "-icxx-isystem", "-cxx-isystem", "-I"
};
bool splitted = false;
for (const char *opt : OptsToCheck) {
if (!strncmp(arg, opt, strlen(opt))) {
int iold = i;
checkIncludePath(opt, getVal(arg, opt, i));
splitted = i > iold;
break;
}
}
PAPUSHARGANDVAL(splitted);
}
case 'm': {
// -m
if (!strncmp(arg, "-mmacosx-version-min=", 21)) {
const char *val = arg + 21;
target.OSNum = parseOSVersion(val);
if (target.OSNum != val) {
warn << "'-mmacosx-version-min=' (" << target.OSNum.Str()
<< " != " << val << ")" << warn.endl();
}
} else if (!strcmp(arg, "-m16") || !strcmp(arg, "-mx32")) {
err << "'" << arg << "' is not supported" << err.endl();
return false;
} else if (!strcmp(arg, "-m32")) {
target.addArch(Arch::i386);
installGCCArchExtensionWarning();
} else if (!strcmp(arg, "-m64")) {
target.addArch(Arch::x86_64);
installGCCArchExtensionWarning();
}
PABREAK;
}
case 'o': {
// -o
if (!strcmp(arg, "-oc-use-gcc-libs")) {
if (target.isGCC()) {
warn << "'" << arg << "' has no effect" << warn.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()) {
runLater([](Target &) {
warnExtension("'-stdlib='");
return true;
});
}
for (auto stdlibname : StdLibNames) {
if (!strcmp(val, stdlibname)) {
target.stdlib = static_cast<StdLib>(i);
break;
}
++i;
}
if (i == (sizeof(StdLibNames) / sizeof(StdLibNames[0]))) {
err << "value of '-stdlib=' must be ";
for (size_t j = 0; j < i; ++j) {
err << "'" << StdLibNames[j] << "'";
if (j == i - 2)
err << " or ";
else if (j < i - 2)
err << ", ";
}
err << err.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.compilername.size() <= 7)
return;
if (target.compilername.rfind("-libc++") ==
(target.compilername.size() - 7)) {
if (target.stdlib != StdLib::unset && target.stdlib != StdLib::libcxx) {
warn << "'-stdlib=" << getStdLibString(target.stdlib)
<< "' will be ignored" << warn.endl();
}
target.compilername.resize(target.compilername.size() - 7);
target.stdlib = StdLib::libcxx;
}
};
if (auto *prog = program::getprog(cmd))
(*prog)(argc, argv, target);
@ -463,15 +399,14 @@ bool detectTarget(int argc, char **argv, Target &target) {
else if (auto *prog = program::getprog(target.compilername))
(*prog)(argc, argv, target);
if (target.target != getDefaultTarget()) {
if (target.target != getDefaultTarget())
warn << "this wrapper was built for target "
<< "'" << getDefaultTarget() << "'" << warn.endl();
}
if (!parseArgs())
if (!commandopts::parse(argc, argv, target))
return false;
checkCXXLib();
detectCXXLib(target);
return target.setup();
}
}
@ -488,249 +423,13 @@ bool detectTarget(int argc, char **argv, Target &target) {
if (const char *p = strchr(cmd, '-'))
target.compilername = &cmd[p - cmd + 1];
if (!parseArgs())
if (!commandopts::parse(argc, argv, target))
return false;
checkCXXLib();
detectCXXLib(target);
return target.setup();
}
//
// generateMultiArchObjectFile():
// support multiple -arch flags with gcc
// and clang + -oc-use-gcc-libs
//
void generateMultiArchObjectFile(int &rc, int argc, char **argv, Target &target,
int debug) {
#ifndef _WIN32
std::string stdintmpfile;
string_vector objs;
std::stringstream obj;
bool compile = false;
size_t num = 0;
if (!strcmp(argv[argc - 1], "-")) {
//
// fork() + reading from stdin isn't a good idea
//
std::stringstream file;
std::string stdinsrc;
std::string line;
while (std::getline(std::cin, line)) {
stdinsrc += line;
stdinsrc += '\n';
}
file << "/tmp/" << getNanoSeconds() << "_stdin";
if (target.isC())
file << ".c";
else if (target.isCXX())
file << ".cpp";
else if (target.isObjC())
file << ".m";
stdintmpfile = file.str();
writeFileContent(stdintmpfile, stdinsrc);
target.args[target.args.size() - 1] = stdintmpfile;
}
auto cleanup = [&]() {
if (!stdintmpfile.empty())
remove(stdintmpfile.c_str());
for (auto &obj : objs)
remove(obj.c_str());
};
if (!target.outputname) {
bool f = false;
for (auto &arg : target.args) {
if (arg == "-c") {
f = true;
break;
}
}
if (f && target.haveSourceFile()) {
static std::string outputname;
const char *ext = getFileExtension(target.sourcefile);
size_t pos;
if (*ext)
outputname = std::string(target.sourcefile, ext - target.sourcefile);
else
outputname = target.sourcefile;
outputname += ".o";
if ((pos = outputname.find_last_of('/')) == std::string::npos)
pos = 0;
else
++pos;
target.outputname = outputname.c_str() + pos;
} else {
if (f)
warn << "source filename detection failed (using a.out)" << warn.endl();
target.outputname = "a.out";
}
}
const char *outputname = strrchr(target.outputname, '/');
if (!outputname)
outputname = target.outputname;
else
++outputname;
for (auto &arch : target.targetarch) {
const char *archname = getArchName(arch);
pid_t pid;
++num;
clear(obj);
obj << "/tmp/" << getNanoSeconds() << "_" << outputname << "_" << archname;
objs.push_back(obj.str());
pid = fork();
if (pid > 0) {
int status = 1;
if (wait(&status) == -1) {
err << "wait() failed" << err.endl();
cleanup();
rc = 1;
break;
}
if (WIFEXITED(status)) {
status = WEXITSTATUS(status);
if (status) {
rc = status;
break;
}
} else {
rc = 1;
break;
}
} else if (pid == 0) {
if (target.isGCC()) {
// GCC
bool is32bit = false;
switch (arch) {
case Arch::i386:
case Arch::i486:
case Arch::i586:
case Arch::i686:
is32bit = true;
case Arch::x86_64:
break;
default:
assert(false && "unsupported arch");
}
target.fargs.push_back(is32bit ? "-m32" : "-m64");
} else if (target.isClang()) {
// Clang
target.fargs.push_back("-arch");
target.fargs.push_back(getArchName(arch));
} else {
assert(false && "unsupported compiler");
}
target.fargs.push_back("-o");
target.fargs.push_back(obj.str());
if (target.usegcclibs) {
target.setupGCCLibs(arch);
if (target.langGiven()) {
// -x must be added *after* the static libstdc++ *.a
// otherwise clang thinks they are source files
target.fargs.push_back("-x");
target.fargs.push_back(target.lang);
}
}
if (debug) {
dbg << "[" << num << "/" << target.targetarch.size() << "] [compiling] "
<< archname << dbg.endl();
}
compile = true;
break;
} else {
err << "fork() failed" << err.endl();
rc = 1;
break;
}
}
if (!compile && !target.nocodegen && rc == -1) {
std::string cmd;
std::string lipo;
std::string path;
lipo = "x86_64-apple-";
lipo += getDefaultTarget();
lipo += "-lipo";
if (!getPathOfCommand(lipo.c_str(), path)) {
lipo = "lipo";
if (!getPathOfCommand(lipo.c_str(), path)) {
err << "cannot find lipo binary" << err.endl();
rc = 1;
}
}
if (rc == -1) {
cmd.swap(path);
cmd += "/";
cmd += lipo;
cmd += " -create ";
for (auto &obj : objs) {
cmd += obj;
cmd += " ";
}
cmd += "-output ";
cmd += target.outputname;
if (debug)
dbg << "[lipo] <-- " << cmd << dbg.endl();
if (unittest == 2) {
rc = 0;
} else {
rc = system(cmd.c_str());
rc = WEXITSTATUS(rc);
}
}
}
if (!compile)
cleanup();
#else
(void)rc;
(void)argc;
(void)argv;
(void)target;
(void)debug;
err << __func__ << " not supported" << err.endl();
rc = 1;
#endif
}
} // unnamed namespace
//
@ -748,9 +447,13 @@ int main(int argc, char **argv) {
if (char *p = getenv("OCDEBUG"))
debug = atoi(p);
if (char *p = getenv("OSXCROSS_UNIT_TEST"))
if (char *p = getenv("OSXCROSS_UNIT_TEST")) {
unittest = atoi(p);
if ((p = getenv("OSXCROSS_PROG_NAME")))
argv[0] = p;
}
if (!detectTarget(argc, argv, target)) {
err << "while detecting target" << err.endl();
return 1;
@ -766,13 +469,6 @@ int main(int argc, char **argv) {
dbg << "detected stdlib: " << getStdLibString(target.stdlib)
<< dbg.endl();
if (debug >= 3) {
dbg << "detected source file: "
<< (target.sourcefile ? target.sourcefile : "-") << dbg.endl();
dbg << "detected language: " << target.getLangName() << dbg.endl();
}
b->resume();
}
}
@ -786,9 +482,6 @@ int main(int argc, char **argv) {
concatEnvVariable("COMPILER_PATH", target.execpath);
#endif
if (target.targetarch.size() > 1 && (target.usegcclibs || target.isGCC()))
generateMultiArchObjectFile(rc, argc, argv, target, debug);
auto printCommand = [&]() {
std::string in;
std::string out;

View File

@ -46,6 +46,8 @@ int cmp(int argc, char **argv) {
res = a <= b;
else if (!strcmp(op, "=="))
res = a == b;
else if (!strcmp(op, "!="))
res = a != b;
else
return 1;

View File

@ -46,6 +46,7 @@ public:
constexpr prog(const char *name, f4 fun)
: name(name), fun1(), fun2(), fun3(), fun4(fun), type(4) {}
__attribute__((noreturn))
void operator()(int argc, char **argv, Target &target) const {
switch (type) {
case 1:
@ -57,6 +58,7 @@ public:
case 4:
exit(fun4(target));
}
__builtin_unreachable();
}
bool operator==(const char *name) const { return !strcmp(name, this->name); }
@ -88,16 +90,18 @@ int pkg_config(int argc, char **argv, Target &target);
static int dummy() { return 0; }
constexpr prog programs[] = { { "sw_vers", sw_vers },
{ "xcrun", xcrun },
{ "dsymutil", dummy },
{ "osxcross", osxcross::version },
{ "osxcross-env", osxcross::env },
{ "osxcross-conf", osxcross::conf },
{ "osxcross-cmp", osxcross::cmp },
{ "osxcross-man", osxcross::man },
{ "pkg-config", osxcross::pkg_config },
{ "wrapper", dummy } };
constexpr prog programs[] = {
{ "sw_vers", sw_vers },
{ "xcrun", xcrun },
{ "dsymutil", dummy },
{ "osxcross", osxcross::version },
{ "osxcross-env", osxcross::env },
{ "osxcross-conf", osxcross::conf },
{ "osxcross-cmp", osxcross::cmp },
{ "osxcross-man", osxcross::man },
{ "pkg-config", osxcross::pkg_config },
{ "wrapper", dummy }
};
template <class T> const prog *getprog(const T &name) {
for (auto &p : programs) {

View File

@ -169,90 +169,8 @@ bool Target::isLibCXX() const {
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 compilername.find("++") == std::string::npos && !isObjC(true);
}
bool Target::isCXX() {
bool CXXCompiler = compilername.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;
return endsWith(compilername, "++");
}
const std::string &Target::getDefaultTriple(std::string &triple) const {
@ -469,13 +387,6 @@ bool Target::setup() {
if (targetarch.empty())
targetarch.push_back(arch);
if (!langStdGiven()) {
if (isC())
langstd = getDefaultCStandard();
else if (isCXX())
langstd = getDefaultCXXStandard();
}
triple = getArchName(arch);
triple += "-";
triple += vendor;
@ -567,7 +478,7 @@ bool Target::setup() {
break;
}
case StdLib::libstdcxx: {
if (isGCC() && /*isCXX11orNewer()*/ true)
if (isGCC())
break;
if (usegcclibs) {
@ -587,7 +498,7 @@ bool Target::setup() {
});
if (v.empty()) {
err << "'-oc-use-gcc-libs' requires gcc to be installed "
err << "'-foc-use-gcc-libstdc++' requires gcc to be installed "
"(./build_gcc.sh)" << err.endl();
return false;
}
@ -614,6 +525,8 @@ bool Target::setup() {
addCXXPath(tmp);
}
addCXXPath("backward");
if (!dirExists(CXXHeaderPath)) {
err << "cannot find " << getStdLibString(stdlib) << " headers"
<< err.endl();
@ -679,13 +592,6 @@ bool Target::setup() {
}
} else if (isGCC()) {
if (isLibCXX()) {
if (!langStdGiven())
langstd = "c++0x";
else if (!isCXX11orNewer())
warn << "libc++ requires -std=c++11 (or later) with gcc" << warn.endl();
}
if (isCXX() && isLibCXX()) {
fargs.push_back("-nostdinc++");
fargs.push_back("-nodefaultlibs");
@ -693,8 +599,7 @@ bool Target::setup() {
if (!isGCH()) {
fargs.push_back("-lc");
fargs.push_back("-lc++");
fargs.push_back(OSNum <= OSVersion(10, 4) ? "-lgcc_s.10.4"
: "-lgcc_s.10.5");
fargs.push_back("-lgcc_s.10.5");
}
} else if (!isLibCXX() && !isGCH() &&
!getenv("OSXCROSS_GCC_NO_STATIC_RUNTIME")) {
@ -742,19 +647,6 @@ bool Target::setup() {
}
}
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=";
@ -798,12 +690,6 @@ bool Target::setup() {
}
}
if (haveOutputName() &&
(targetarch.size() <= 1 || (!isGCC() && !usegcclibs))) {
fargs.push_back("-o");
fargs.push_back(outputname);
}
return true;
}
} // namespace target

View File

@ -50,13 +50,6 @@ constexpr const char *getOSXCrossVersion() {
#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"))
@ -76,8 +69,8 @@ struct Target {
Target()
: vendor(getDefaultVendor()), SDK(getenv("OSXCROSS_SDKROOT")),
arch(Arch::x86_64), target(getDefaultTarget()), stdlib(StdLib::unset),
usegcclibs(), nocodegen(), compilername(getDefaultCompiler()), lang(),
langstd(), sourcefile(), outputname() {
usegcclibs(), nocodegen(), compilername(getDefaultCompiler()),
outputname() {
if (!getExecutablePath(execpath, sizeof(execpath)))
abort();
}
@ -100,12 +93,9 @@ struct Target {
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()) {
@ -126,12 +116,6 @@ struct Target {
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 &getDefaultTriple(std::string &triple) const;
const std::string &getTriple() const { return triple; }
@ -157,11 +141,8 @@ struct Target {
std::string compilerexecname; // clang | *-apple-darwin-gcc
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];
};

View File

@ -362,9 +362,9 @@ bool writeFileContent(const std::string &file, const std::string &content) {
return f.good();
}
bool fileExists(const std::string &dir) {
bool fileExists(const std::string &file) {
struct stat st;
return !stat(dir.c_str(), &st);
return !stat(file.c_str(), &st);
}
bool dirExists(const std::string &dir) {

View File

@ -29,12 +29,21 @@ namespace tools {
typedef std::vector<std::string> string_vector;
static inline void clear(std::stringstream &sstr)
{
static inline void clear(std::stringstream &sstr) {
sstr.clear();
sstr.str(std::string());
}
static inline bool endsWith(std::string const &str, std::string const &end) {
if (end.size() > str.size())
return false;
return std::equal(end.rbegin(), end.rend(), str.rbegin());
}
size_t constexpr slen(const char *str) {
return *str ? 1 + slen(str + 1) : 0;
}
//
// Terminal text colors
//

530
wrapper/unittests/run.bats Executable file
View File

@ -0,0 +1,530 @@
#!/usr/bin/env bats
#
# Requirements:
# * bats (https://github.com/sstephenson/bats)
# * OSXCRoss >= 0.11 must be in PATH
#
export OSXCROSS_UNIT_TEST=2
export OCDEBUG=1
unset OSXCROSS_NO_EXTENSION_WARNINGS
unset OSXCROSS_NO_X86_64H_DEPLOYMENT_TARGET_WARNING
unset OSXCROSS_GCC_NO_STATIC_RUNTIME
unset MACOSX_DEPLOYMENT_TARGET
unset OSXCROSS_SDKROOT
GCC_INSTALLED=1
command -v o64-clang++ >/dev/null 2>&1 || { echo "OSXCross must be in PATH" 1>&2; exit 1; }
command -v o64-g++ >/dev/null 2>&1 || GCC_INSTALLED=0
if [ $GCC_INSTALLED -eq 1 ]; then
if [ "$(o64-clang++ -foc-run-prog=osxcross-conf 2>/dev/null)" != \
"$(o64-g++ -foc-run-prog=osxcross-conf 2>/dev/null)" ]; then
true
#echo "warning: o64-clang++ and o64-g++ come from different installations; aborting unit testing" 1>&2
GCC_INSTALLED=0
fi
fi
eval $(osxcross-conf)
@test "osxcross-cmp" {
run osxcross-cmp
[ "$status" -ne 0 ]
run osxcross-cmp 10.5 '>' 10.6
[ "$status" -eq 0 ]
[ "$output" = "0" ]
run osxcross-cmp 10.11 '>' 10.10
[ "$status" -eq 0 ]
[ "$output" = "1" ]
run osxcross-cmp 10.11 '>=' 10.12
[ "$status" -eq 0 ]
[ "$output" = "0" ]
run osxcross-cmp 10.11 '<=' 10.12
[ "$status" -eq 0 ]
[ "$output" = "1" ]
run osxcross-cmp 10.10 '==' 10.10
[ "$status" -eq 0 ]
[ "$output" = "1" ]
run osxcross-cmp 10.10 '!=' 10.10
[ "$status" -eq 0 ]
[ "$output" = "0" ]
run osxcross-cmp 10.10 '?' 10.10
[ "$status" -ne 0 ]
run osxcross-cmp 10.10 '>'
[ "$status" -ne 0 ]
}
@test "cross compiler arguments" {
run o64-clang++
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ *clang*\ \(clang++\)\ * ]]
[[ "${lines[0]}" == *\ -target\ x86_64-apple-darwin*\ * ]]
[[ "${lines[0]}" == *\ -mlinker-version=$OSXCROSS_LINKER_VERSION\ * ]]
[[ "${lines[0]}" == *\ -isystem\ */clang/*.*/include\ * ]]
[[ "${lines[0]}" == *\ -isysroot\ */MacOSX10.*.sdk\ * ]]
[[ "${lines[0]}" == *\ -stdlib=*++*\ * ]]
[[ "${lines[0]}" == *\ -mmacosx-version-min=10.* ]]
[[ "${lines[0]}" == *\ -arch\ x86_64\ * ]]
[[ "${lines[0]}" != *\ -Wl,-no_compact_unwind\ * ]]
run o32-clang
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ *clang*\ \(clang\)\ * ]]
[[ "${lines[0]}" == *\ -target\ i386-apple-darwin*\ * ]]
if [ $GCC_INSTALLED -eq 1 ]; then
run o64-g++
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ *x86_64-apple-darwin*-base-g++*\ \(x86_64-apple-darwin*-g++\)\ * ]]
[[ "${lines[0]}" != *\ -target\ x86_64-apple-darwin*\ * ]]
[[ "${lines[0]}" != *\ -mlinker-version=*\ * ]]
[[ "${lines[0]}" != *\ -isystem\ */clang/*.*/include\ * ]]
[[ "${lines[0]}" != *\ -isysroot\ */MacOSX10.*.sdk\ * ]]
[[ "${lines[0]}" != *\ -stdlib=*++*\ * ]]
[[ "${lines[0]}" == *\ -mmacosx-version-min=10.* ]]
[[ "${lines[0]}" == *\ -m64\ * ]]
[[ "${lines[0]}" == *\ -Wl,-no_compact_unwind\ * ]]
run o32-g++
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ *i386-apple-darwin*-base-g++*\ \(i386-apple-darwin*-g++\)\ * ]]
fi
}
@test "OCDEBUG=2" {
OCDEBUG=2 run o64-clang++
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *debug:\ detected\ target\ triple:\ *-apple-darwin* ]]
[[ "${lines[1]}" == *debug:\ detected\ compiler:\ * ]]
[[ "${lines[2]}" == *debug:\ detected\ stdlib:\ * ]]
}
@test "argv[0] parsing" {
OSXCROSS_PROG_NAME=x86_64-apple-darwin999999-clang++ run o64-clang++
[ "$status" -ne 0 ]
[[ "${lines[0]}" == *warning:\ this\ wrapper\ was\ built\ for\ target\ \'darwin*\' ]]
[[ "${lines[1]}" == *error:\ cannot\ find\ Mac\ OS\ X\ SDK\ \(expected\ in:\ */SDK/MacOSX10.999995.sdk\) ]]
OSXCROSS_PROG_NAME=x86_64-apple-$OSXCROSS_TARGET-gcc run o64-clang++
[ "$status" -eq 0 ]
[[ -z "$OUTPUT" ]]
OSXCROSS_PROG_NAME=x86_64-apple-$OSXCROSS_TARGET-g++ run o64-clang++
[ "$status" -eq 0 ]
[[ -z "$OUTPUT" ]]
OSXCROSS_PROG_NAME=x86_64-apple-$OSXCROSS_TARGET-cc run o64-clang++
[ "$status" -eq 0 ]
[[ -z "$OUTPUT" ]]
OSXCROSS_PROG_NAME=x86_64-apple-$OSXCROSS_TARGET-c++ run o64-clang++
[ "$status" -eq 0 ]
[[ -z "$OUTPUT" ]]
OSXCROSS_PROG_NAME=i386-apple-$OSXCROSS_TARGET-clang++ run o64-clang++
[ "$status" -eq 0 ]
OSXCROSS_PROG_NAME=i486-apple-$OSXCROSS_TARGET-clang++ run o64-clang++
[ "$status" -eq 0 ]
OSXCROSS_PROG_NAME=i586-apple-$OSXCROSS_TARGET-clang++ run o64-clang++
[ "$status" -eq 0 ]
OSXCROSS_PROG_NAME=i686-apple-$OSXCROSS_TARGET-clang++ run o64-clang++
[ "$status" -eq 0 ]
OSXCROSS_PROG_NAME=i786-apple-$OSXCROSS_TARGET-clang++ run o64-clang++
[ "$status" -ne 0 ]
OSXCROSS_PROG_NAME=armv6-apple-$OSXCROSS_TARGET-clang++ run o64-clang++
[ "$status" -ne 0 ]
OSXCROSS_PROG_NAME=x86_64-mapple-$OSXCROSS_TARGET-clang++ run o64-clang++
[ "$status" -ne 0 ]
OSXCROSS_PROG_NAME=x86_64-apple-ddarwin13-clang++ run o64-clang++
[ "$status" -ne 0 ]
OSXCROSS_PROG_NAME=x86_64-apple--clang++ run o64-clang++
[ "$status" -ne 0 ]
OSXCROSS_PROG_NAME=x86_64-apple-$OSXCROSS_TARGET-foo run o64-clang++
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *warning:\ unknown\ compiler\ \'foo\' ]]
OSXCROSS_PROG_NAME= run o64-clang++
[ "$status" -ne 0 ]
OSXCROSS_PROG_NAME=? run o64-clang++
[ "$status" -ne 0 ]
}
@test "command line parsing" {
run o64-clang++ -mmacosx-version-min=10.4 -g -I test1 -march=native -Itest2 -O2 -stdlib=libstdc++ -stdlib=default -stdlib=libstdc++ -otest1 -o test2 foo.cpp -c
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ -mmacosx-version-min=10.4*\ * ]]
[[ "${lines[0]}" == *\ -g\ *\ * ]]
[[ "${lines[0]}" == *\ -I\ test1\ * ]]
[[ "${lines[0]}" == *\ -march=native\ * ]]
[[ "${lines[0]}" == *\ -Itest2\ * ]]
[[ "${lines[0]}" == *\ -O2\ * ]]
[[ "${lines[0]}" != *\ -stdlib=default\ * ]]
[[ "${lines[0]}" == *\ -otest1\ * ]]
[[ "${lines[0]}" == *\ -o\ test2\ * ]]
[[ "${lines[0]}" == *\ foo.cpp\ * ]]
[[ "${lines[0]}" == *\ -c\ * ]]
}
@test "-mmacosx-version-min/MACOSX_DEPLOYMENT_TARGET" {
run o64-clang++ -mmacosx-version-min=10.10000
[ "$status" -ne 0 ]
[[ "${lines[0]}" == *error:\ targeted\ OS\ X\ version\ must\ be\ \<=\ 10.*.0\ \(SDK\) ]]
run o64-clang++ -mmacosx-version-min=abc
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *warning:\ \'-mmacosx-version-min=\'\ \(0.0.0\ !=\ abc\) ]]
[[ "${lines[1]}" != *\ -mmacosx-version-min=abc\ * ]]
[[ "${lines[1]}" != *\ -mmacosx-version-min=0.0*\ * ]]
run o64-clang++ -mmacosx-version-min=10.0
[ "$status" -ne 0 ]
[[ "${lines[0]}" == *targeted\ OS\ X\ version\ must\ be\ \>=\ 10.4 ]]
run o64-clang++ -mmacosx-version-min=10.0 -mmacosx-version-min=$OSXCROSS_SDK_VERSION
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ -mmacosx-version-min=$OSXCROSS_SDK_VERSION.*\ * ]]
MACOSX_DEPLOYMENT_TARGET=10.4 run o64-clang++ -mmacosx-version-min=10.0 -mmacosx-version-min=10.4
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ -mmacosx-version-min=10.4.*\ * ]]
MACOSX_DEPLOYMENT_TARGET=10.4 run o64-clang++
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ -mmacosx-version-min=10.4.*\ * ]]
}
@test "-stdlib/-stdc++/-gstdc++/-foc-use-gcc-libstdc++/-libc++" {
function libcxx()
{
run $@
if [[ "$@" == *-mmacosx-version-min=10.4* ]]; then
[ "$status" -ne 0 ]
[[ "${lines[0]}" == *error:\ libc++\ requires\ \'-mmacosx-version-min=10.7\'\ \(or\ later\) ]]
else
[ "$status" -eq 0 ]
if [[ $1 == *clang++* ]]; then
[[ "${lines[0]}" == *\ -cxx-isystem\ */SDK/MacOSX10.*.sdk/usr/include/c++/v1\ * ]]
[[ "${lines[0]}" == *\ -stdlib=libc++\ * ]]
[[ "${lines[0]}" != *\ -stdlib=libstdc++\ * ]]
else
if [[ "$@" == *-stdlib* ]]; then
[[ "${lines[0]}" == *warning:\ \'-stdlib=\'\ is\ an\ osxcross\ extension* ]]
else
[[ "${lines[0]}" == *\ -nostdinc++\ -nodefaultlibs\ -lc\ -lc++\ -lgcc_s.10.5\ * ]]
[[ "${lines[0]}" == *\ -isystem\ */SDK/MacOSX10.*.sdk/usr/include/c++/v1\ * ]]
fi
fi
fi
}
if [ $(osxcross-cmp $OSXCROSS_SDK_VERSION '>=' 10.7) -eq 1 ]; then
libcxx "o64-clang++" "-stdlib=libc++"
libcxx "o64-clang++-libc++"
libcxx "o64-clang++-libc++" "-mmacosx-version-min=10.4"
if [ $GCC_INSTALLED -eq 1 ]; then
libcxx "o64-g++-libc++"
libcxx "o64-g++" "-stdlib=libc++"
libcxx "o64-g++" "-stdlib=libc++"
fi
fi
function stdcxx()
{
run $@
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ -stdlib=libstdc++\ * ]]
[[ "${lines[0]}" != *\ -stdlib=libc++\ * ]]
[[ "${lines[0]}" != *\ -cxx-isystem\ */SDK/MacOSX10.*.sdk/usr/include/c++/v1\ * ]]
[[ "${lines[0]}" == *\ -cxx-isystem\ */SDK/MacOSX10.*.sdk/usr/include/c++/4.*\ * ]]
[[ "${lines[0]}" == *\ -cxx-isystem\ */SDK/MacOSX10.*.sdk/usr/include/c++/4.*/*-apple-darwin*\ * ]]
[[ "${lines[0]}" == *\ -cxx-isystem\ */SDK/MacOSX10.*.sdk/usr/include/c++/4.*/backward\ * ]]
}
stdcxx "o64-clang++" "-stdlib=libstdc++"
stdcxx "o64-clang++-stdc++"
run o64-clang++-stdc++ -stdlib=libc++
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *warning:\ ignoring\ \'-stdlib=libc++\' ]]
function gstdcxx()
{
run $@
if [[ "${lines[0]}" == *error:\ \'-foc-use-gcc-libstdc++\'\ requires\ gcc\ to\ be\ installed\ \(./build_gcc.sh\) ]];
then
[ "$status" -ne 0 ]
else
[ "$status" -eq 0 ]
if [[ $1 == *clang++* ]]; then
[[ "${lines[0]}" == *\ -Qunused-arguments\ * ]]
fi
[[ "${lines[0]}" == *\ -cxx-isystem\ */x86_64-apple-darwin*/include/c++/*.*\ * ]]
[[ "${lines[0]}" == *\ -cxx-isystem\ */x86_64-apple-darwin*/include/c++/*.*/x86_64-apple-darwin*\ * ]]
[[ "${lines[0]}" == *\ -cxx-isystem\ */x86_64-apple-darwin*/include/c++/*.*/backward\ * ]]
if [[ $1 == *++ ]]; then
[[ "${lines[0]}" == *\ -nostdinc++\ * ]]
[[ "${lines[0]}" == *\ -stdlib=libstdc++\ * ]]
[[ "${lines[0]}" == *\ -nodefaultlibs\ * ]]
[[ "${lines[0]}" == *\ -Wl,-no_compact_unwind\ * ]]
if [ -n "$OSXCROSS_GCC_NO_STATIC_RUNTIME" ]; then
[[ "${lines[0]}" == *\ -L\ */lib/gcc/x86_64-apple-darwin*/*.*\ * ]]
[[ "${lines[0]}" == *\ -L\ */x86_64-apple-darwin*/lib*\ * ]]
[[ "${lines[0]}" == *\ -l\ stdc++\ * ]]
[[ "${lines[0]}" == *\ -l\ supc++\ * ]]
[[ "${lines[0]}" == *\ -l\ gcc\ * ]]
[[ "${lines[0]}" == *\ -l\ gcc_eh\ * ]]
else
[[ "${lines[0]}" == *\ */x86_64-apple-darwin*/lib*/libstdc++.a\ * ]]
[[ "${lines[0]}" == *\ */x86_64-apple-darwin*/lib*/libsupc++.a\ * ]]
[[ "${lines[0]}" == *\ */lib/gcc/x86_64-apple-darwin*/*.*/libgcc.a\ * ]]
[[ "${lines[0]}" == *\ */lib/gcc/x86_64-apple-darwin*/*.*/libgcc_eh.a\ * ]]
fi
else
[[ "${lines[0]}" != *\ -l\ stdc++\ * ]]
[[ "${lines[0]}" != *\ -l\ supc++\ * ]]
[[ "${lines[0]}" != *\ *libstdc++.a\ * ]]
[[ "${lines[0]}" != *\ *libsupc++.a\ * ]]
fi
fi
}
gstdcxx "o64-clang++" "-foc-use-gcc-libstdc++"
gstdcxx "o64-clang" "-foc-use-gcc-libstdc++"
gstdcxx "o64-clang++-gstdc++" "-foc-use-gcc-libstdc++"
gstdcxx "o32-clang++-gstdc++" "-foc-use-gcc-libstdc++"
OSXCROSS_GCC_NO_STATIC_RUNTIME=1 gstdcxx "o64-clang++" "-foc-use-gcc-libstdc++"
OSXCROSS_GCC_NO_STATIC_RUNTIME=1 gstdcxx "o64-clang++" "-foc-use-gcc-libstdc++" "-m32"
if [ $GCC_INSTALLED -eq 1 ]; then
run o64-g++
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ -static-libgcc\ * ]]
[[ "${lines[0]}" == *\ -static-libstdc++\ * ]]
OSXCROSS_GCC_NO_STATIC_RUNTIME=1 run o64-g++
[[ "${lines[0]}" != *\ -static-libgcc\ * ]]
[[ "${lines[0]}" != *\ -static-libstdc++\ * ]]
fi
run o64-clang++ -stdlib=default
[ "$status" -eq 0 ]
[[ "${lines[0]}" != *\ -stdlib=default\ * ]]
run o64-clang++ -stdlib=foo
[ "$status" -eq 1 ]
[[ "${lines[0]}" == *error:\ value\ of\ \'-stdlib=\'\ must\ be\ \'default\',\ \'libc++\'\ or\ \'libstdc++\' ]]
}
@test "-arch/-m32/-m64/-m16/-mx32" {
run o64-clang++ -arch x86_64 -arch i386 -arch x86_64 -arch i386
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ -arch\ x86_64\ \-arch\ i386\ * ]]
run o64-clang++ -m16
[ "$status" -eq 1 ]
run o64-clang++ -mx32
[ "$status" -eq 1 ]
run o64-clang++ -arch x86_64h
[ "$status" -eq 0 ] || [[ "${lines[0]}" == *error:\ \'x86_64\'\ requires\ Mac\ OS\ X\ SDK\ 10.8\ \(or\ later\) ]]
run o64-clang++ -arch foo
[ "$status" -ne 0 ]
[[ "${lines[0]}" == *warning:\ \'-arch\':\ \unknown\ architecture\ \'foo\' ]]
[[ "${lines[1]}" == *warning:\ \'-arch\':\ \'foo\'\ !=\ \'unknown\' ]]
[[ "${lines[2]}" == *error:\ unsupported\ architecture:\ \'unknown\' ]]
run o64-clang++ -arch armv7
[ "$status" -ne 0 ]
[[ "${lines[0]}" == *error:\ unsupported\ architecture:\ \'armv7\' ]]
run o64-clang++ -arch i386
[ "$status" -eq 0 ]
[[ "${lines[0]}" != *\ -arch\ x86_64\ * ]]
run o64-clang++ -m32
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ -arch\ i386\ * ]]
if [ $(osxcross-cmp $OSXCROSS_SDK_VERSION '>=' 10.8) -eq 1 ]; then
run o64-clang++ -arch x86_64h -mmacosx-version-min=10.7
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *warning:\ \'-mmacosx-version-min=\'\ should\ be\ \'\>=\ 10.8\'\ for\ architecture\ \'x86_64h\' ]]
OSXCROSS_NO_X86_64H_DEPLOYMENT_TARGET_WARNING=1 run o64-clang++ -arch x86_64h -mmacosx-version-min=10.7
[ "$status" -eq 0 ]
[[ "${lines[0]}" != *warning:\ * ]]
fi
if [ $GCC_INSTALLED -eq 1 ]; then
run o64-g++ -arch x86_64 -arch i386 -arch x86_64 -arch i386
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ -m32\ * ]]
[[ "${lines[0]}" != *\ -m64\ * ]]
[[ "${lines[0]}" != *\ -arch\ * ]]
run o64-g++ -arch x86_64h
[ "$status" -eq 1 ]
[[ "${lines[0]}" == *error:\ gcc\ does\ not\ support\ architecture\ \'x86_64h\' ]]
fi
}
@test "bad include path warning" {
if [ $(uname -s) == "Darwin" ]; then
skip "Not supported"
fi
run o64-clang++ -I/usr/..////////usr//include
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *warning:\ possibly\ dangerous\ include\ path\ specified:\ \'-I\ /usr/..////////usr//include\'\ \(/usr/include\) ]]
[[ "${lines[1]}" == *info:\ you\ can\ silence\ this\ warning\ via\ \'OSXCROSS_NO_INCLUDE_PATH_WARNINGS=1\'\ \(env\)* ]]
[[ "${lines[2]}" == *\ -I/usr/..////////usr//include\ * ]]
if [ $GCC_INSTALLED -eq 1 ]; then
OSXCROSS_NO_INCLUDE_PATH_WARNINGS=1 run o64-g++ -I/usr/include
[ "$status" -eq 0 ]
[[ "${lines[0]}" != *warning:\ * ]]
fi
}
@test "OSXCROSS_MP_INC" {
if [ -d "${OSXCROSS_TARGET_DIR}/macports" ]; then
function macports()
{
run $@
[ "$status" -eq 0 ]
if [ -d "${OSXCROSS_TARGET_DIR}/macports/pkgs/opt/local/include" ]; then
[[ "${lines[0]}" == *\ -isystem\ */macports/pkgs/opt/local/include\ * ]]
fi
if [ -d "${OSXCROSS_TARGET_DIR}/macports/pkgs/opt/local/lib" ]; then
[[ "${lines[0]}" == *\ -L\ */macports/pkgs/opt/local/lib\ * ]]
fi
if [ -d "${OSXCROSS_TARGET_DIR}/macports/pkgs/opt/local/Library/Frameworks" ]; then
[[ "${lines[0]}" == *\ -iframework\ */macports/pkgs/opt/local/Library/Frameworks\ * ]]
fi
if [[ $1 == *clang++* ]]; then
[[ "${lines[0]}" == *\ -Qunused-arguments\ * ]]
fi
}
OSXCROSS_MP_INC=1 macports o64-clang++
if [ $GCC_INSTALLED -eq 1 ]; then
OSXCROSS_MP_INC=1 macports o64-g++
fi
fi
}
@test "OSXCROSS_SDKROOT" {
OSXCROSS_SDKROOT=/dev/null/MacOSX10.10.sdk run o64-clang++
[ "$status" -ne 0 ]
[[ "${lines[0]}" == *error:\ cannot\ find\ Mac\ OS\ X\ SDK\ \(expected\ in:\ /dev/null/MacOSX10.10.sdk\) ]]
OSXCROSS_SDKROOT=$OSXCROSS_SDK run o64-clang++
[ "$status" -eq 0 ]
}
@test "xcrun" {
run xcrun -sdk
[ "$status" -ne 0 ]
[[ "${lines[0]}" == *error:\ too\ few\ arguments\ for\ \'-sdk\' ]]
run xcrun -sdk /
[ "$status" -eq 0 ]
run xcrun -sdk /dev/null
[ "$status" -ne 0 ]
[[ "${lines[0]}" == *error:\ xcrun:\ \'-sdk\':\ expected\ Mac\ OS\ X\ SDK ]]
OSXCROSS_SDKROOT=/dev/null/MacOSX10.9.sdk SDKROOT=/dev/null/MacOSX10.10.sdk run xcrun
[ "$status" -ne 0 ]
[[ "${lines[0]}" == *error:\ xcrun:\ \'-sdk\':\ directory\ \'/dev/null/MacOSX10.10.sdk\'\ does\ not\ exist ]]
run xcrun -sdk $OSXCROSS_SDK clang
[ "$status" -eq 0 ]
[[ "${lines[0]}" == *debug:\ \<--\ * ]]
run xcrun -f clang
[ "$status" -eq 0 ]
[[ "${lines[0]}" == */bin/x86_64-apple-darwin*-clang ]]
run xcrun -find /usr/bin/ld
[ "$status" -eq 0 ]
[[ "${lines[0]}" == */bin/x86_64-apple-darwin*-ld ]]
run xcrun -show-sdk-path -show-sdk-version
[ "$status" -eq 0 ]
[ "${lines[0]}" == "$OSXCROSS_SDK" ]
[ "${lines[1]}" == "$OSXCROSS_SDK_VERSION" ]
xcrun_log=1 run xcrun clang
[ "$status" -eq 0 ]
[[ "${lines[0]}" == */bin/x86_64-apple-darwin*-clang ]]
run xcrun -log -l clang
[ "$status" -eq 0 ]
[[ "${lines[1]}" == *debug:\ \<--\ * ]]
run xcrun -run clang
[ "$status" -eq 0 ]
run xcrun -r clang
[ "$status" -eq 0 ]
run xcrun -foo
[ "$status" -ne 0 ]
run xcrun -k -kill-cache -n -no-cache -toolchain / -v -verbose -h -help
[ "$status" -eq 0 ]
}
@test "sw_vers" {
run sw_vers
[ "$status" -eq 0 ]
[ "${lines[0]}" == "ProductName: Mac OS X" ]
[ "${lines[1]}" == "ProductVersion: $OSXCROSS_OSX_VERSION_MIN" ]
[[ "${lines[2]}" == BuildVersion:\ \ \ * ]]
run sw_vers -productName
[ "$status" -eq 0 ]
[ "${lines[0]}" == "Mac OS X" ]
OSXCROSS_SW_VERS_OSX_VERSION=10.15 MACOSX_DEPLOYMENT_TARGET=10.16 run sw_vers -productVersion
[ "$status" -eq 0 ]
[ "${lines[0]}" == "10.15" ]
MACOSX_DEPLOYMENT_TARGET=10.16 run sw_vers -productVersion
[ "$status" -eq 0 ]
[ "${lines[0]}" == "10.16" ]
run sw_vers -buildVersion
[ "$status" -eq 0 ]
[[ "${lines[0]}" == * ]]
run sw_vers -foo
[ "$status" -ne 0 ]
}