Created
May 27, 2015 20:08
-
-
Save tpoechtrager/b4a3d3f286bad519fb09 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/CHANGELOG b/CHANGELOG | |
index 755e084..2099196 100644 | |
--- a/CHANGELOG | |
+++ b/CHANGELOG | |
@@ -4,6 +4,7 @@ changed: | |
* improved and colorized wrapper error/warning/debug/info messages | |
added: | |
+* support for ccache symlinks (#34) | |
* include path warnings for /usr/include and /usr/local/include | |
(can be switched off via 'OSXCROSS_NO_INCLUDE_PATH_WARNINGS=1') | |
* an option to silence osxcross extension warnings | |
diff --git a/wrapper/main.cpp b/wrapper/main.cpp | |
old mode 100755 | |
new mode 100644 | |
index 4bd8b7b..d94661d | |
--- a/wrapper/main.cpp | |
+++ b/wrapper/main.cpp | |
@@ -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 | |
@@ -738,6 +739,7 @@ void generateMultiArchObjectFile(int &rc, int argc, char **argv, Target &target, | |
int main(int argc, char **argv) { | |
char bbuf[sizeof(benchmark)]; | |
auto b = new (bbuf) benchmark; | |
+ std::string program; | |
Target target; | |
char **cargs = nullptr; | |
int debug = 0; | |
@@ -789,8 +791,18 @@ int main(int argc, char **argv) { | |
in += " "; | |
} | |
- for (auto &arg : target.fargs) { | |
- out += arg; | |
+ out += program; | |
+ | |
+ if (program != 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 += " "; | |
} | |
@@ -809,6 +821,10 @@ int main(int argc, char **argv) { | |
cargs = new char *[target.fargs.size() + target.args.size() + 1]; | |
size_t i = 0; | |
+ if (!realPath(target.fargs[0].c_str(), program, isExecutable, | |
+ ignoreCCACHE)) | |
+ program = target.fargs[0]; | |
+ | |
for (auto &arg : target.fargs) | |
cargs[i++] = const_cast<char *>(arg.c_str()); | |
@@ -831,7 +847,7 @@ int main(int argc, char **argv) { | |
if (unittest == 2) | |
return 0; | |
- if (rc == -1 && execvp(cargs[0], cargs)) { | |
+ if (rc == -1 && execvp(program.c_str(), cargs)) { | |
err << "invoking compiler failed" << err.endl(); | |
if (!debug) | |
diff --git a/wrapper/programs/osxcross-env.cpp b/wrapper/programs/osxcross-env.cpp | |
old mode 100755 | |
new mode 100644 | |
diff --git a/wrapper/programs/osxcross-version.cpp b/wrapper/programs/osxcross-version.cpp | |
old mode 100755 | |
new mode 100644 | |
diff --git a/wrapper/programs/pkg-config.cpp b/wrapper/programs/pkg-config.cpp | |
old mode 100755 | |
new mode 100644 | |
diff --git a/wrapper/programs/sw_vers.cpp b/wrapper/programs/sw_vers.cpp | |
old mode 100755 | |
new mode 100644 | |
diff --git a/wrapper/target.cpp b/wrapper/target.cpp | |
index 1301ced..dba7e16 100644 | |
--- a/wrapper/target.cpp | |
+++ b/wrapper/target.cpp | |
@@ -247,14 +247,14 @@ const std::string Target::getFullCompilerName() const { | |
} | |
bool Target::findClangIntrinsicHeaders(std::string &path) { | |
- std::string clangbin; | |
+ std::string clangpath; | |
static std::stringstream dir; | |
assert(isClang()); | |
- getPathOfCommand(compiler.c_str(), clangbin); | |
+ getPathOfCommand(compiler.c_str(), clangpath, ignoreCCACHE); | |
- if (clangbin.empty()) | |
+ if (clangpath.empty()) | |
return false; | |
static ClangVersion *clangversion; | |
@@ -266,10 +266,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 +301,55 @@ bool Target::findClangIntrinsicHeaders(std::string &path) { | |
checkDir(tmp); | |
} | |
} | |
- | |
return true; | |
} | |
- | |
return true; | |
}); | |
- | |
return *clangversion != ClangVersion(); | |
}; | |
- dir << clangbin << "/../lib/clang"; | |
- | |
- if (!check()) { | |
- clear(dir); | |
+#define TRYDIR(basedir, subdir) \ | |
+do { \ | |
+ dir << basedir << subdir; \ | |
+ if (tryDir()) { \ | |
+ path.swap(pathtmp); \ | |
+ return true; \ | |
+ } \ | |
+ clear(dir); \ | |
+} while (0) | |
+ | |
+#define TRYDIR2(libdir) TRYDIR(clangpath, libdir) | |
+#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__ | |
- 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; | |
- } | |
- clear(dir); | |
- } | |
-#endif | |
+ constexpr const char *OSXIntrinDirs[] = { | |
+ "/Library/Developer/CommandLineTools/usr/lib/clang", | |
+ "/Applications/Contents/Developer/Toolchains/" | |
+ "XcodeDefault.xctoolchain/usr/lib/clang" | |
+ }; | |
- if (!dir.rdbuf()->in_avail()) { | |
- dir << clangbin << "/../include/clang"; | |
+ for (auto intrindir : OSXIntrinDirs) | |
+ TRYDIR3(intrindir); | |
+#endif | |
- if (!check()) | |
- return false; | |
- } | |
- } | |
+ TRYDIR2("/../include/clang"); | |
+ TRYDIR2("/usr/include/clang"); | |
- path.swap(pathtmp); | |
- return *clangversion != ClangVersion(); | |
+ return false; | |
+#undef TRYDIR | |
+#undef TRYDIR2 | |
+#undef TRYDIR3 | |
} | |
void Target::setupGCCLibs(Arch arch) { | |
diff --git a/wrapper/tools.cpp b/wrapper/tools.cpp | |
old mode 100755 | |
new mode 100644 | |
index 4b33515..5180b55 | |
--- a/wrapper/tools.cpp | |
+++ b/wrapper/tools.cpp | |
@@ -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,53 +335,88 @@ 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 *bin = getFileName(f); | |
+ return bin && strstr(bin, "ccache") != bin; | |
+} | |
+ | |
+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++; | |
- | |
- sfile += "/"; | |
- sfile += file; | |
- | |
- if (!stat(sfile.c_str(), &st) && (!cmp || cmp(sfile.c_str(), st))) | |
- break; | |
+ result += *p++; | |
- 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) { | |
+ std::cerr << result << ": too many levels of symbolic links" | |
+ << std::endl; | |
+ result.clear(); | |
+ break; | |
+ } | |
+ } | |
+ } | |
#endif | |
- result.swap(sfile); | |
- return result; | |
-} | |
+ if ((!cmp1 || cmp1(result.c_str(), st)) && | |
+ (!cmp2 || cmp2(result.c_str(), st))) | |
+ break; | |
+ } | |
-std::string &getPathOfCommand(const char *command, std::string &result) { | |
- realPath(command, result, isExecutable); | |
+ result.clear(); | |
+ } while (*p); | |
- const size_t len = strlen(command) + 1; | |
+ return !result.empty(); | |
+} | |
- if (result.size() < len) { | |
- result.clear(); | |
- return result; | |
+std::string &getPathOfCommand(const char *command, std::string &result, | |
+ realpathcmp cmp) { | |
+ if (realPath(command, result, isExecutable, cmp)) { | |
+ size_t lastpathdiv = result.find_last_of(PATHDIV); | |
+ if (lastpathdiv != 0 && lastpathdiv != std::string::npos) | |
+ result.resize(lastpathdiv); | |
} | |
- result.resize(result.size() - len); | |
return result; | |
} | |
diff --git a/wrapper/tools.h b/wrapper/tools.h | |
old mode 100755 | |
new mode 100644 | |
index 4316e06..ec526a6 | |
--- a/wrapper/tools.h | |
+++ b/wrapper/tools.h | |
@@ -19,6 +19,8 @@ | |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * | |
***********************************************************************/ | |
+struct stat; | |
+ | |
namespace tools { | |
// | |
@@ -142,8 +144,11 @@ 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); | |
+std::string &getPathOfCommand(const char *command, std::string &result, | |
+ realpathcmp cmp = nullptr); | |
const char *getFileName(const char *file); | |
const char *getFileExtension(const char *file); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment