Skip to content

Instantly share code, notes, and snippets.

@tpoechtrager
Created May 27, 2015 20:08
Show Gist options
  • Save tpoechtrager/b4a3d3f286bad519fb09 to your computer and use it in GitHub Desktop.
Save tpoechtrager/b4a3d3f286bad519fb09 to your computer and use it in GitHub Desktop.
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