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 * improved and colorized wrapper error/warning/debug/info messages
added: added:
* support for ccache symlinks
* darling-dmg sdk packaging script * darling-dmg sdk packaging script
* include path warnings for /usr/include and /usr/local/include * include path warnings for /usr/include and /usr/local/include
(can be switched off via 'OSXCROSS_NO_INCLUDE_PATH_WARNINGS=1') (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: ### ### 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:** **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). default target to 10.6 (better 10.7, or later).
To achive this, add the following to your bashrc (or similar): To achive this, add the following to your bashrc (or similar):
@ -35,7 +35,7 @@ Then run `osxcross-macports <cmd>`.
**pkg-config:** **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. is automatically aware of MacPorts packages.
If you want `pkg-config` to be unaware 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; int unittest = 0;
//
// detectTarget():
// detect target and setup invocation command
//
void checkIncludePath(const char *opt, const char *path) { void checkIncludePath(const char *opt, const char *path) {
#ifndef __APPLE__ #ifndef __APPLE__
constexpr const char *DangerousIncludePaths[] = { "/usr/include", constexpr const char *DangerousIncludePaths[] = { "/usr/include",
"/usr/local/include" }; "/usr/local/include" };
if (!path) if (!path)
return; return;
@ -108,6 +104,11 @@ void warnExtension(const char *extension) {
<< "'OSXCROSS_NO_EXTENSION_WARNINGS=1' (env)" << warninfo.endl(); << "'OSXCROSS_NO_EXTENSION_WARNINGS=1' (env)" << warninfo.endl();
} }
//
// detectTarget():
// detect target and setup invocation command
//
#define PABREAK \ #define PABREAK \
else target.args.push_back(arg); \ else target.args.push_back(arg); \
break break
@ -409,16 +410,17 @@ bool detectTarget(int argc, char **argv, Target &target) {
}; };
auto checkCXXLib = [&]() { auto checkCXXLib = [&]() {
if (target.compiler.size() <= 7) if (target.compilername.size() <= 7)
return; 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) { if (target.stdlib != StdLib::unset && target.stdlib != StdLib::libcxx) {
warn << "'-stdlib=" << getStdLibString(target.stdlib) warn << "'-stdlib=" << getStdLibString(target.stdlib)
<< "' will be ignored" << warn.endl(); << "' will be ignored" << warn.endl();
} }
target.compiler.resize(target.compiler.size() - 7); target.compilername.resize(target.compilername.size() - 7);
target.stdlib = StdLib::libcxx; target.stdlib = StdLib::libcxx;
} }
}; };
@ -452,13 +454,13 @@ bool detectTarget(int argc, char **argv, Target &target) {
return false; return false;
target.target = std::string(cmd, p - cmd); target.target = std::string(cmd, p - cmd);
target.compiler = &p[1]; target.compilername = &p[1];
if (target.compiler == "cc") if (target.compilername == "cc")
target.compiler = getDefaultCompiler(); target.compilername = getDefaultCompiler();
else if (target.compiler == "c++") else if (target.compilername == "c++")
target.compiler = getDefaultCXXCompiler(); target.compilername = getDefaultCXXCompiler();
else if (auto *prog = program::getprog(target.compiler)) else if (auto *prog = program::getprog(target.compilername))
(*prog)(argc, argv, target); (*prog)(argc, argv, target);
if (target.target != getDefaultTarget()) { if (target.target != getDefaultTarget()) {
@ -484,7 +486,7 @@ bool detectTarget(int argc, char **argv, Target &target) {
return false; return false;
if (const char *p = strchr(cmd, '-')) if (const char *p = strchr(cmd, '-'))
target.compiler = &cmd[p - cmd + 1]; target.compilername = &cmd[p - cmd + 1];
if (!parseArgs()) if (!parseArgs())
return false; return false;
@ -681,10 +683,10 @@ void generateMultiArchObjectFile(int &rc, int argc, char **argv, Target &target,
lipo += getDefaultTarget(); lipo += getDefaultTarget();
lipo += "-lipo"; lipo += "-lipo";
if (getPathOfCommand(lipo.c_str(), path).empty()) { if (!getPathOfCommand(lipo.c_str(), path)) {
lipo = "lipo"; lipo = "lipo";
if (getPathOfCommand(lipo.c_str(), path).empty()) { if (!getPathOfCommand(lipo.c_str(), path)) {
err << "cannot find lipo binary" << err.endl(); err << "cannot find lipo binary" << err.endl();
rc = 1; rc = 1;
} }
@ -759,7 +761,7 @@ int main(int argc, char **argv) {
if (debug >= 2) { if (debug >= 2) {
dbg << "detected target triple: " << target.getTriple() << dbg.endl(); 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 << "detected stdlib: " << getStdLibString(target.stdlib)
<< dbg.endl(); << dbg.endl();
@ -789,8 +791,18 @@ int main(int argc, char **argv) {
in += " "; in += " ";
} }
for (auto &arg : target.fargs) { out += target.compilerpath;
out += arg;
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 += " "; out += " ";
} }
@ -831,7 +843,7 @@ int main(int argc, char **argv) {
if (unittest == 2) if (unittest == 2)
return 0; return 0;
if (rc == -1 && execvp(cargs[0], cargs)) { if (rc == -1 && execvp(target.compilerpath.c_str(), cargs)) {
err << "invoking compiler failed" << err.endl(); err << "invoking compiler failed" << err.endl();
if (!debug) 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 true;
} }
return compiler.find("++") == std::string::npos && !isObjC(true); return compilername.find("++") == std::string::npos && !isObjC(true);
} }
bool Target::isCXX() { bool Target::isCXX() {
bool CXXCompiler = compiler.find("++") != std::string::npos; bool CXXCompiler = compilername.find("++") != std::string::npos;
if (!langGiven() && CXXCompiler && !isObjC(true)) if (!langGiven() && CXXCompiler && !isObjC(true))
return true; return true;
@ -229,34 +229,37 @@ bool Target::isCXX11orNewer() const {
return false; return false;
} }
const std::string Target::getFullCompilerName() const { void Target::setCompilerPath() {
std::string compiler;
if (isGCC()) { if (isGCC()) {
compiler = execpath; compilerpath = execpath;
compiler += "/"; compilerpath += "/";
compiler += getTriple(); compilerpath += getTriple();
compiler += "-"; 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) { bool Target::findClangIntrinsicHeaders(std::string &path) {
std::string clangbin;
static std::stringstream dir; static std::stringstream dir;
assert(isClang()); assert(isClang());
getPathOfCommand(compiler.c_str(), clangbin); if (compilerpath.empty())
if (clangbin.empty())
return false; return false;
std::string clangbindir = compilerpath;
stripFileName(clangbindir);
static ClangVersion *clangversion; static ClangVersion *clangversion;
static std::string pathtmp; static std::string pathtmp;
@ -266,10 +269,8 @@ bool Target::findClangIntrinsicHeaders(std::string &path) {
*clangversion = ClangVersion(); *clangversion = ClangVersion();
pathtmp.clear(); pathtmp.clear();
auto check = []()->bool { auto tryDir = [&]()->bool {
listFiles(dir.str().c_str(), nullptr, [](const char *file) { listFiles(dir.str().c_str(), nullptr, [](const char *file) {
if (file[0] != '.' && isDirectory(file, dir.str().c_str())) { if (file[0] != '.' && isDirectory(file, dir.str().c_str())) {
ClangVersion cv = parseClangVersion(file); ClangVersion cv = parseClangVersion(file);
@ -303,20 +304,36 @@ bool Target::findClangIntrinsicHeaders(std::string &path) {
checkDir(tmp); checkDir(tmp);
} }
} }
return true; return true;
} }
return true; return true;
}); });
return *clangversion != ClangVersion(); 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()) { #define TRYDIR2(libdir) TRYDIR(clangbindir, libdir)
clear(dir); #define TRYDIR3(libdir) TRYDIR(std::string(), libdir)
TRYDIR2("/../lib/clang");
#ifdef __linux__
#ifdef __x86_64__
// opensuse uses lib64 instead of lib on x86_64
TRYDIR2("/../lib64/clang");
#elif __i386__
TRYDIR2("/../lib32/clang");
#endif
#endif
#ifdef __APPLE__ #ifdef __APPLE__
constexpr const char *OSXIntrinDirs[] = { constexpr const char *OSXIntrinDirs[] = {
@ -325,25 +342,17 @@ bool Target::findClangIntrinsicHeaders(std::string &path) {
"XcodeDefault.xctoolchain/usr/lib/clang" "XcodeDefault.xctoolchain/usr/lib/clang"
}; };
for (auto intrindir : OSXIntrinDirs) { for (auto intrindir : OSXIntrinDirs)
dir << intrindir; TRYDIR3(intrindir);
if (check()) {
break;
}
clear(dir);
}
#endif #endif
if (!dir.rdbuf()->in_avail()) { TRYDIR2("/../include/clang");
dir << clangbin << "/../include/clang"; TRYDIR2("/usr/include/clang");
if (!check())
return false; return false;
} #undef TRYDIR
} #undef TRYDIR2
#undef TRYDIR3
path.swap(pathtmp);
return *clangversion != ClangVersion();
} }
void Target::setupGCCLibs(Arch arch) { void Target::setupGCCLibs(Arch arch) {
@ -409,7 +418,7 @@ bool Target::setup() {
OSVersion SDKOSNum = getSDKOSNum(); OSVersion SDKOSNum = getSDKOSNum();
if (!isKnownCompiler()) if (!isKnownCompiler())
warn << "unknown compiler '" << compiler << "'" << warn.endl(); warn << "unknown compiler '" << compilername << "'" << warn.endl();
if (!getSDKPath(SDKPath)) { if (!getSDKPath(SDKPath)) {
err << "cannot find Mac OS X SDK (expected in: " << SDKPath << ")" err << "cannot find Mac OS X SDK (expected in: " << SDKPath << ")"
@ -439,6 +448,8 @@ bool Target::setup() {
otriple += "-"; otriple += "-";
otriple += target; otriple += target;
setCompilerPath();
if (!OSNum.Num()) { if (!OSNum.Num()) {
if (haveArch(Arch::x86_64h)) { if (haveArch(Arch::x86_64h)) {
OSNum = OSVersion(10, 8); // Default to 10.8 for x86_64h OSNum = OSVersion(10, 8); // Default to 10.8 for x86_64h
@ -569,7 +580,7 @@ bool Target::setup() {
abort(); abort();
} }
fargs.push_back(getFullCompilerName()); fargs.push_back(compilerexecname);
if (isClang()) { if (isClang()) {
std::string tmp; std::string tmp;
@ -585,7 +596,7 @@ bool Target::setup() {
#ifndef __APPLE__ #ifndef __APPLE__
if (!findClangIntrinsicHeaders(tmp)) { 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(); "issue to the OSXCross project" << warn.endl();
} else { } else {
fargs.push_back("-isystem"); fargs.push_back("-isystem");

View File

@ -75,7 +75,7 @@ struct Target {
Target() Target()
: vendor(getDefaultVendor()), target(getDefaultTarget()), : vendor(getDefaultVendor()), target(getDefaultTarget()),
stdlib(StdLib::unset), usegcclibs(), nocodegen(), stdlib(StdLib::unset), usegcclibs(), nocodegen(),
compiler(getDefaultCompiler()), lang(), langstd(), sourcefile(), compilername(getDefaultCompiler()), lang(), langstd(), sourcefile(),
outputname() { outputname() {
if (!getExecutablePath(execpath, sizeof(execpath))) if (!getExecutablePath(execpath, sizeof(execpath)))
abort(); abort();
@ -115,11 +115,11 @@ struct Target {
} }
bool isClang() const { bool isClang() const {
return !strncmp(getFileName(compiler.c_str()), "clang", 5); return !strncmp(getFileName(compilername.c_str()), "clang", 5);
} }
bool isGCC() const { 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)); 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 &getTriple() const { return triple; }
const std::string getFullCompilerName() const; void setCompilerPath();
bool findClangIntrinsicHeaders(std::string &path); bool findClangIntrinsicHeaders(std::string &path);
void setupGCCLibs(Arch arch); void setupGCCLibs(Arch arch);
@ -149,7 +149,9 @@ struct Target {
GCCVersion gccversion; GCCVersion gccversion;
bool usegcclibs; bool usegcclibs;
bool nocodegen; 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 triple;
std::string otriple; std::string otriple;
const char *lang; const char *lang;

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

@ -144,7 +144,6 @@ const std::string &getParentProcessName() {
if (Process32First(h, &pe)) { if (Process32First(h, &pe)) {
do { do {
std::cout << pe.szExeFile << " " << pe.th32ProcessID << std::endl;
if (pe.th32ProcessID == ppid) { if (pe.th32ProcessID == ppid) {
ppe = &pe; ppe = &pe;
break; break;
@ -336,54 +335,92 @@ bool isExecutable(const char *f, const struct stat &) {
return !access(f, F_OK | X_OK); 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"); char *PATH = getenv("PATH");
const char *p = PATH ? PATH : ""; const char *p = PATH ? PATH : "";
std::string sfile;
struct stat st; struct stat st;
result.clear();
do { do {
if (*p == ':') if (*p == ':')
++p; ++p;
while (*p && *p != ':') while (*p && *p != ':')
sfile += *p++; result += *p++;
sfile += "/"; result += "/";
sfile += file; result += file;
if (!stat(sfile.c_str(), &st) && (!cmp || cmp(sfile.c_str(), st)))
break;
sfile.clear();
} while (*p);
if (!stat(result.c_str(), &st)) {
#ifndef _WIN32 #ifndef _WIN32
if (!sfile.empty()) {
char buf[PATH_MAX + 1]; char buf[PATH_MAX + 1];
ssize_t len;
if ((len = readlink(sfile.c_str(), buf, PATH_MAX)) != -1) 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); 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 #endif
result.swap(sfile); if ((!cmp1 || cmp1(result.c_str(), st)) &&
return result; (!cmp2 || cmp2(result.c_str(), st)))
break;
} }
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(); result.clear();
return result; } while (*p);
return !result.empty();
} }
result.resize(result.size() - len); bool getPathOfCommand(const char *command, std::string &result,
return result; realpathcmp cmp) {
if (realPath(command, result, isExecutable, cmp))
stripFileName(result);
return !result.empty();
}
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) { 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. * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***********************************************************************/ ***********************************************************************/
struct stat;
namespace tools { 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); typedef bool (*realpathcmp)(const char *file, const struct stat &st);
bool isExecutable(const char *f, const struct stat &); bool isExecutable(const char *f, const struct stat &);
std::string &realPath(const char *file, std::string &result, realpathcmp cmp); bool ignoreCCACHE(const char *f, const struct stat &);
std::string &getPathOfCommand(const char *command, std::string &result); 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 *getFileName(const char *file);
const char *getFileExtension(const char *file); const char *getFileExtension(const char *file);