From bae2a4ad82d0ce67a6b4b39c3b8c4948c27e5ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20P=C3=B6chtrager?= Date: Sun, 23 Aug 2015 22:45:53 +0200 Subject: [PATCH] Better PCH/GCH detection --- KNOWN_BUGS.md | 41 ++++++++++++++++++++++++++++++++++++++ wrapper/main.cpp | 6 +++--- wrapper/target.cpp | 28 +++++++++++++++++++++++--- wrapper/target.h | 25 +++++------------------ wrapper/unittests/run.bats | 24 +++++++++++++++++++++- 5 files changed, 97 insertions(+), 27 deletions(-) create mode 100644 KNOWN_BUGS.md diff --git a/KNOWN_BUGS.md b/KNOWN_BUGS.md new file mode 100644 index 0000000..1bf2f02 --- /dev/null +++ b/KNOWN_BUGS.md @@ -0,0 +1,41 @@ +### OSXCROSS BUGS ### + +------------- + +*** ISSUE: *** + +GCH generation does not work with `gcc` or `clang++-gstdc++`/`-foc-use-gcc-libstdc++` +if `-c` or `-x-header` is **not** passed to the compiler. + +Example: + + $ o64-gcc test.h + Undefined symbols for architecture x86_64: + "_main", referenced from: + start in crt1.10.6.o + +This is due to `-Wl,-no_compact_unwind` being passed to the compiler under the hood. + +Example: + + $ x86_64-apple-darwin14-base-gcc + x86_64-apple-darwin14-base-gcc: fatal error: no input files + + $ x86_64-apple-darwin14-base-gcc -Wl,-no_compact_unwind + Undefined symbols for architecture x86_64: + "_main", referenced from: + start in crt1.10.6.o + ld: symbol(s) not found for architecture x86_64 + +*** WORKAROUND: *** + +Add `-c` or `-x-header` to the compiler flags. + +Example: + + o64-clang++-gstdc++ test.hpp # BAD + o64-clang++-gstdc++ -xc++-header test.hpp # OK + o64-clang++-gstdc++ test.hpp -c # OK + o64-g++ test.hpp -c # OK + +------------- diff --git a/wrapper/main.cpp b/wrapper/main.cpp index 21586e0..ab56f60 100644 --- a/wrapper/main.cpp +++ b/wrapper/main.cpp @@ -158,8 +158,8 @@ bool stdlib(Target &target, const char *, const char *val, char **) { return true; } -bool outputname(Target &target, const char *, const char *val, char **) { - target.outputname = val; +bool language(Target &target, const char *, const char *val, char **) { + target.language = val; return true; } @@ -250,7 +250,7 @@ constexpr struct Opt { {"-m32", arch}, {"-mx32", arch}, {"-m64", arch}, - {"-o", outputname, true, true}, + {"-x", language, true, true}, {"-foc-use-gcc-libstdc++", usegcclibstdcxx}, {"-foc-run-prog", runprog, true, false, "="}, // for internal use only {"-isystem", checkincludepath, true, true}, diff --git a/wrapper/target.cpp b/wrapper/target.cpp index 78fab98..5ce8472 100644 --- a/wrapper/target.cpp +++ b/wrapper/target.cpp @@ -173,6 +173,27 @@ bool Target::isCXX() { return endsWith(compilername, "++"); } +bool Target::isGCH() { + if (!language) + return false; + + return !strcmp(language, "c-header") || + !strcmp(language, "c++-header") || + !strcmp(language, "objective-c-header") || + !strcmp(language, "objective-c++-header"); +} + + +bool Target::isClang() const { + return !strncmp(getFileName(compilername.c_str()), "clang", 5); +} + +bool Target::isGCC() const { + const char *c = getFileName(compilername.c_str()); + return (!strncmp(c, "gcc", 3) || !strncmp(c, "g++", 3)); +} + + const std::string &Target::getDefaultTriple(std::string &triple) const { triple = getArchName(Arch::x86_64); triple += "-"; @@ -585,13 +606,13 @@ bool Target::setup() { fargs.push_back("-Qunused-arguments"); } - if (stdlib == StdLib::libstdcxx && usegcclibs && targetarch.size() < 2) { + if (stdlib == StdLib::libstdcxx && usegcclibs && targetarch.size() < 2 && + !isGCH()) { // Use libs from './build_gcc' installation setupGCCLibs(targetarch[0]); } } } else if (isGCC()) { - if (isCXX() && isLibCXX()) { fargs.push_back("-nostdinc++"); fargs.push_back("-nodefaultlibs"); @@ -607,7 +628,8 @@ bool Target::setup() { fargs.push_back("-static-libstdc++"); } - fargs.push_back("-Wl,-no_compact_unwind"); + if (!isGCH()) + fargs.push_back("-Wl,-no_compact_unwind"); } auto addCXXHeaderPath = [&](const std::string &path) { diff --git a/wrapper/target.h b/wrapper/target.h index 6d16e54..92fd381 100644 --- a/wrapper/target.h +++ b/wrapper/target.h @@ -70,7 +70,7 @@ struct Target { : vendor(getDefaultVendor()), SDK(getenv("OSXCROSS_SDKROOT")), arch(Arch::x86_64), target(getDefaultTarget()), stdlib(StdLib::unset), usegcclibs(), nocodegen(), compilername(getDefaultCompiler()), - outputname() { + language() { if (!getExecutablePath(execpath, sizeof(execpath))) abort(); } @@ -93,26 +93,11 @@ struct Target { bool isLibCXX() const; bool isLibSTDCXX() const; - bool haveOutputName() { return outputname != nullptr; } - bool isCXX(); + bool isGCH(); - bool isGCH() { - if (haveOutputName()) { - const char *ext = getFileExtension(outputname); - return !strcmp(ext, ".gch"); - } - return false; - } - - bool isClang() const { - return !strncmp(getFileName(compilername.c_str()), "clang", 5); - } - - bool isGCC() const { - const char *c = getFileName(compilername.c_str()); - return (!strncmp(c, "gcc", 3) || !strncmp(c, "g++", 3)); - } + bool isClang() const; + bool isGCC() const; bool isKnownCompiler() const { return isClang() || isGCC(); } @@ -143,7 +128,7 @@ struct Target { std::string otriple; string_vector fargs; string_vector args; - const char *outputname; + const char *language; char execpath[PATH_MAX + 1]; }; diff --git a/wrapper/unittests/run.bats b/wrapper/unittests/run.bats index 5e77618..b04c8a7 100755 --- a/wrapper/unittests/run.bats +++ b/wrapper/unittests/run.bats @@ -172,7 +172,9 @@ eval $(osxcross-conf) } @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 + run o64-clang++ -mmacosx-version-min=10.4 -g -I test1 -march=native -Itest2 -O2 \ + -xc-header -x c++-header -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\ *\ * ]] @@ -180,6 +182,8 @@ eval $(osxcross-conf) [[ "${lines[0]}" == *\ -march=native\ * ]] [[ "${lines[0]}" == *\ -Itest2\ * ]] [[ "${lines[0]}" == *\ -O2\ * ]] + [[ "${lines[0]}" == *\ -xc-header\ * ]] + [[ "${lines[0]}" == *\ -x\ c++-header\ * ]] [[ "${lines[0]}" != *\ -stdlib=default\ * ]] [[ "${lines[0]}" == *\ -otest1\ * ]] [[ "${lines[0]}" == *\ -o\ test2\ * ]] @@ -337,6 +341,24 @@ eval $(osxcross-conf) [[ "${lines[0]}" == *error:\ value\ of\ \'-stdlib=\'\ must\ be\ \'default\',\ \'libc++\'\ or\ \'libstdc++\' ]] } +@test "precompiled headers" { + function gch() + { + run $@ + [ "$status" -eq 0 ] + [[ "${lines[0]}" != *\ -l* ]] + [[ "${lines[0]}" != *\ -Wl,* ]] + [[ "${lines[0]}" != *\ *.a ]] + } + + gch o64-clang -x c-header + gch o64-clang++-gstdc++ -xc++-header + + if [ $GCC_INSTALLED -eq 1 ]; then + gch o64-g++ -xc++-header + fi +} + @test "-arch/-m32/-m64/-m16/-mx32" { run o64-clang++ -arch x86_64 -arch i386 -arch x86_64 -arch i386 [ "$status" -eq 0 ]