This commit is contained in:
Thomas Pöchtrager 2015-05-30 21:04:51 +02:00
parent bae6ac72cd
commit f5aaf9faf9
11 changed files with 183 additions and 113 deletions

View File

@ -4,6 +4,7 @@ changed:
* improved and colorized wrapper error/warning/debug/info messages
added:
* support for ccache symlinks
* darling-dmg sdk packaging script
* include path warnings for /usr/include and /usr/local/include
(can be switched off via 'OSXCROSS_NO_INCLUDE_PATH_WARNINGS=1')

View File

@ -12,11 +12,11 @@ Also ensure that you are using the 10.6 SDK (or later).
### INSTALLATION: ###
Run OSXCross's `./build.sh`, then you should have `osxcross-macports` in PATH.
Run OSXCross' `./build.sh`, then you should have `osxcross-macports` in PATH.
**Setting up osxcross-macports:**
MacPorts doesn't support 10.5 anymore, so we need to change OSXCross's
MacPorts doesn't support 10.5 anymore, so we need to change OSXCross'
default target to 10.6 (better 10.7, or later).
To achive this, add the following to your bashrc (or similar):
@ -35,7 +35,7 @@ Then run `osxcross-macports <cmd>`.
**pkg-config:**
OSXCross's `pkg-config` (`<arch>-apple-darwinXX-pkg-config`)
OSXCross' `pkg-config` (`<arch>-apple-darwinXX-pkg-config`)
is automatically aware of MacPorts packages.
If you want `pkg-config` to be unaware of MacPorts packages

54
wrapper/main.cpp Executable file → Normal file
View File

@ -51,15 +51,11 @@ namespace {
int unittest = 0;
//
// detectTarget():
// detect target and setup invocation command
//
void checkIncludePath(const char *opt, const char *path) {
#ifndef __APPLE__
constexpr const char *DangerousIncludePaths[] = { "/usr/include",
"/usr/local/include" };
if (!path)
return;
@ -108,6 +104,11 @@ void warnExtension(const char *extension) {
<< "'OSXCROSS_NO_EXTENSION_WARNINGS=1' (env)" << warninfo.endl();
}
//
// detectTarget():
// detect target and setup invocation command
//
#define PABREAK \
else target.args.push_back(arg); \
break
@ -409,16 +410,17 @@ bool detectTarget(int argc, char **argv, Target &target) {
};
auto checkCXXLib = [&]() {
if (target.compiler.size() <= 7)
if (target.compilername.size() <= 7)
return;
if (target.compiler.rfind("-libc++") == (target.compiler.size() - 7)) {
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.compiler.resize(target.compiler.size() - 7);
target.compilername.resize(target.compilername.size() - 7);
target.stdlib = StdLib::libcxx;
}
};
@ -452,13 +454,13 @@ bool detectTarget(int argc, char **argv, Target &target) {
return false;
target.target = std::string(cmd, p - cmd);
target.compiler = &p[1];
target.compilername = &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))
if (target.compilername == "cc")
target.compilername = getDefaultCompiler();
else if (target.compilername == "c++")
target.compilername = getDefaultCXXCompiler();
else if (auto *prog = program::getprog(target.compilername))
(*prog)(argc, argv, target);
if (target.target != getDefaultTarget()) {
@ -484,7 +486,7 @@ bool detectTarget(int argc, char **argv, Target &target) {
return false;
if (const char *p = strchr(cmd, '-'))
target.compiler = &cmd[p - cmd + 1];
target.compilername = &cmd[p - cmd + 1];
if (!parseArgs())
return false;
@ -681,10 +683,10 @@ void generateMultiArchObjectFile(int &rc, int argc, char **argv, Target &target,
lipo += getDefaultTarget();
lipo += "-lipo";
if (getPathOfCommand(lipo.c_str(), path).empty()) {
if (!getPathOfCommand(lipo.c_str(), path)) {
lipo = "lipo";
if (getPathOfCommand(lipo.c_str(), path).empty()) {
if (!getPathOfCommand(lipo.c_str(), path)) {
err << "cannot find lipo binary" << err.endl();
rc = 1;
}
@ -759,7 +761,7 @@ int main(int argc, char **argv) {
if (debug >= 2) {
dbg << "detected target triple: " << target.getTriple() << dbg.endl();
dbg << "detected compiler: " << target.compiler << dbg.endl();
dbg << "detected compiler: " << target.compilername << dbg.endl();
dbg << "detected stdlib: " << getStdLibString(target.stdlib)
<< dbg.endl();
@ -789,8 +791,18 @@ int main(int argc, char **argv) {
in += " ";
}
for (auto &arg : target.fargs) {
out += arg;
out += target.compilerpath;
if (target.compilerpath != target.fargs[0]) {
out += " (";
out += target.fargs[0];
out += ") ";
} else {
out += " ";
}
for (size_t i = 1; i < target.fargs.size(); ++i) {
out += target.fargs[i];
out += " ";
}
@ -831,7 +843,7 @@ int main(int argc, char **argv) {
if (unittest == 2)
return 0;
if (rc == -1 && execvp(cargs[0], cargs)) {
if (rc == -1 && execvp(target.compilerpath.c_str(), cargs)) {
err << "invoking compiler failed" << err.endl();
if (!debug)

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

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

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

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

View File

@ -156,11 +156,11 @@ bool Target::isC(bool r) {
return true;
}
return compiler.find("++") == std::string::npos && !isObjC(true);
return compilername.find("++") == std::string::npos && !isObjC(true);
}
bool Target::isCXX() {
bool CXXCompiler = compiler.find("++") != std::string::npos;
bool CXXCompiler = compilername.find("++") != std::string::npos;
if (!langGiven() && CXXCompiler && !isObjC(true))
return true;
@ -229,34 +229,37 @@ bool Target::isCXX11orNewer() const {
return false;
}
const std::string Target::getFullCompilerName() const {
std::string compiler;
void Target::setCompilerPath() {
if (isGCC()) {
compiler = execpath;
compiler += "/";
compiler += getTriple();
compiler += "-";
compilerpath = execpath;
compilerpath += "/";
compilerpath += getTriple();
compilerpath += "-";
compilerpath += "base-";
compilerpath += compilername;
compilerexecname = getTriple();
compilerexecname += "-";
compilerexecname += compilername;
} else {
if (!realPath(compilername.c_str(), compilerpath, ignoreCCACHE))
compilerpath = compilername;
compilerexecname += compilername;
}
if (isGCC())
compiler += "base-";
compiler += this->compiler;
return compiler;
}
bool Target::findClangIntrinsicHeaders(std::string &path) {
std::string clangbin;
static std::stringstream dir;
assert(isClang());
getPathOfCommand(compiler.c_str(), clangbin);
if (clangbin.empty())
if (compilerpath.empty())
return false;
std::string clangbindir = compilerpath;
stripFileName(clangbindir);
static ClangVersion *clangversion;
static std::string pathtmp;
@ -266,10 +269,8 @@ bool Target::findClangIntrinsicHeaders(std::string &path) {
*clangversion = ClangVersion();
pathtmp.clear();
auto check = []()->bool {
auto tryDir = [&]()->bool {
listFiles(dir.str().c_str(), nullptr, [](const char *file) {
if (file[0] != '.' && isDirectory(file, dir.str().c_str())) {
ClangVersion cv = parseClangVersion(file);
@ -303,47 +304,55 @@ bool Target::findClangIntrinsicHeaders(std::string &path) {
checkDir(tmp);
}
}
return true;
}
return true;
});
return *clangversion != ClangVersion();
};
dir << clangbin << "/../lib/clang";
#define TRYDIR(basedir, subdir) \
do { \
dir << basedir << subdir; \
if (tryDir()) { \
path.swap(pathtmp); \
return true; \
} \
clear(dir); \
} while (0)
if (!check()) {
clear(dir);
#define TRYDIR2(libdir) TRYDIR(clangbindir, libdir)
#define TRYDIR3(libdir) TRYDIR(std::string(), libdir)
#ifdef __APPLE__
constexpr const char *OSXIntrinDirs[] = {
"/Library/Developer/CommandLineTools/usr/lib/clang",
"/Applications/Contents/Developer/Toolchains/"
"XcodeDefault.xctoolchain/usr/lib/clang"
};
TRYDIR2("/../lib/clang");
for (auto intrindir : OSXIntrinDirs) {
dir << intrindir;
if (check()) {
break;
}
clear(dir);
}
#ifdef __linux__
#ifdef __x86_64__
// opensuse uses lib64 instead of lib on x86_64
TRYDIR2("/../lib64/clang");
#elif __i386__
TRYDIR2("/../lib32/clang");
#endif
#endif
if (!dir.rdbuf()->in_avail()) {
dir << clangbin << "/../include/clang";
#ifdef __APPLE__
constexpr const char *OSXIntrinDirs[] = {
"/Library/Developer/CommandLineTools/usr/lib/clang",
"/Applications/Contents/Developer/Toolchains/"
"XcodeDefault.xctoolchain/usr/lib/clang"
};
if (!check())
return false;
}
}
for (auto intrindir : OSXIntrinDirs)
TRYDIR3(intrindir);
#endif
path.swap(pathtmp);
return *clangversion != ClangVersion();
TRYDIR2("/../include/clang");
TRYDIR2("/usr/include/clang");
return false;
#undef TRYDIR
#undef TRYDIR2
#undef TRYDIR3
}
void Target::setupGCCLibs(Arch arch) {
@ -409,7 +418,7 @@ bool Target::setup() {
OSVersion SDKOSNum = getSDKOSNum();
if (!isKnownCompiler())
warn << "unknown compiler '" << compiler << "'" << warn.endl();
warn << "unknown compiler '" << compilername << "'" << warn.endl();
if (!getSDKPath(SDKPath)) {
err << "cannot find Mac OS X SDK (expected in: " << SDKPath << ")"
@ -439,6 +448,8 @@ bool Target::setup() {
otriple += "-";
otriple += target;
setCompilerPath();
if (!OSNum.Num()) {
if (haveArch(Arch::x86_64h)) {
OSNum = OSVersion(10, 8); // Default to 10.8 for x86_64h
@ -569,7 +580,7 @@ bool Target::setup() {
abort();
}
fargs.push_back(getFullCompilerName());
fargs.push_back(compilerexecname);
if (isClang()) {
std::string tmp;
@ -585,7 +596,7 @@ bool Target::setup() {
#ifndef __APPLE__
if (!findClangIntrinsicHeaders(tmp)) {
warn << "cannot find clang intrinsic headers, please report this "
warn << "cannot find clang intrinsic headers; please report this "
"issue to the OSXCross project" << warn.endl();
} else {
fargs.push_back("-isystem");

View File

@ -75,7 +75,7 @@ struct Target {
Target()
: vendor(getDefaultVendor()), target(getDefaultTarget()),
stdlib(StdLib::unset), usegcclibs(), nocodegen(),
compiler(getDefaultCompiler()), lang(), langstd(), sourcefile(),
compilername(getDefaultCompiler()), lang(), langstd(), sourcefile(),
outputname() {
if (!getExecutablePath(execpath, sizeof(execpath)))
abort();
@ -115,11 +115,11 @@ struct Target {
}
bool isClang() const {
return !strncmp(getFileName(compiler.c_str()), "clang", 5);
return !strncmp(getFileName(compilername.c_str()), "clang", 5);
}
bool isGCC() const {
const char *c = getFileName(compiler.c_str());
const char *c = getFileName(compilername.c_str());
return (!strncmp(c, "gcc", 3) || !strncmp(c, "g++", 3));
}
@ -133,7 +133,7 @@ struct Target {
const std::string &getTriple() const { return triple; }
const std::string getFullCompilerName() const;
void setCompilerPath();
bool findClangIntrinsicHeaders(std::string &path);
void setupGCCLibs(Arch arch);
@ -149,7 +149,9 @@ struct Target {
GCCVersion gccversion;
bool usegcclibs;
bool nocodegen;
std::string compiler;
std::string compilerpath; // /usr/bin/clang | [...]/target/bin/*-gcc
std::string compilername; // clang | gcc
std::string compilerexecname; // clang | *-apple-darwin-gcc
std::string triple;
std::string otriple;
const char *lang;

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

@ -144,7 +144,6 @@ const std::string &getParentProcessName() {
if (Process32First(h, &pe)) {
do {
std::cout << pe.szExeFile << " " << pe.th32ProcessID << std::endl;
if (pe.th32ProcessID == ppid) {
ppe = &pe;
break;
@ -336,54 +335,92 @@ 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) {
bool ignoreCCACHE(const char *f, const struct stat &) {
const char *name = getFileName(f);
return name && strstr(name, "ccache") != name;
}
bool realPath(const char *file, std::string &result,
realpathcmp cmp1, realpathcmp cmp2) {
char *PATH = getenv("PATH");
const char *p = PATH ? PATH : "";
std::string sfile;
struct stat st;
result.clear();
do {
if (*p == ':')
++p;
while (*p && *p != ':')
sfile += *p++;
result += *p++;
sfile += "/";
sfile += file;
if (!stat(sfile.c_str(), &st) && (!cmp || cmp(sfile.c_str(), st)))
break;
sfile.clear();
} while (*p);
result += "/";
result += file;
if (!stat(result.c_str(), &st)) {
#ifndef _WIN32
if (!sfile.empty()) {
char buf[PATH_MAX + 1];
ssize_t len;
char buf[PATH_MAX + 1];
if ((len = readlink(sfile.c_str(), buf, PATH_MAX)) != -1)
result.assign(buf, len);
}
if (realpath(result.c_str(), buf)) {
result.assign(buf);
} else {
ssize_t len;
char path[PATH_MAX];
size_t pathlen;
size_t n = 0;
pathlen = result.find_last_of(PATHDIV);
if (pathlen == std::string::npos)
pathlen = result.length();
else
++pathlen; // PATHDIV
memcpy(path, result.c_str(), pathlen); // not null terminated
while ((len = readlink(result.c_str(), buf, PATH_MAX)) != -1) {
if (buf[0] != PATHDIV) {
result.assign(path, pathlen);
result.append(buf, len);
} else {
result.assign(buf, len);
pathlen = strrchr(buf, PATHDIV) - buf + 1; // + 1: PATHDIV
memcpy(path, buf, pathlen);
}
if (++n >= 1000) {
err << result << ": too many levels of symbolic links"
<< err.endl();
result.clear();
break;
}
}
}
#endif
result.swap(sfile);
return result;
if ((!cmp1 || cmp1(result.c_str(), st)) &&
(!cmp2 || cmp2(result.c_str(), st)))
break;
}
result.clear();
} while (*p);
return !result.empty();
}
std::string &getPathOfCommand(const char *command, std::string &result) {
realPath(command, result, isExecutable);
bool getPathOfCommand(const char *command, std::string &result,
realpathcmp cmp) {
if (realPath(command, result, isExecutable, cmp))
stripFileName(result);
const size_t len = strlen(command) + 1;
return !result.empty();
}
if (result.size() < len) {
result.clear();
return result;
}
result.resize(result.size() - len);
return result;
void stripFileName(std::string &path) {
size_t lastpathdiv = path.find_last_of(PATHDIV);
if (lastpathdiv != 0 && lastpathdiv != std::string::npos)
path.resize(lastpathdiv);
}
const char *getFileName(const char *file) {

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

@ -19,6 +19,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***********************************************************************/
struct stat;
namespace tools {
//
@ -142,8 +144,13 @@ bool listFiles(const char *dir, std::vector<std::string> *files,
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);
bool ignoreCCACHE(const char *f, const struct stat &);
bool realPath(const char *file, std::string &result,
realpathcmp cmp1 = nullptr, realpathcmp cmp2 = nullptr);
bool getPathOfCommand(const char *command, std::string &result,
realpathcmp cmp = nullptr);
void stripFileName(std::string &path);
const char *getFileName(const char *file);
const char *getFileExtension(const char *file);