Better PCH/GCH detection

This commit is contained in:
Thomas Pöchtrager 2015-08-23 22:45:53 +02:00
parent f22bebe442
commit bae2a4ad82
5 changed files with 97 additions and 27 deletions

41
KNOWN_BUGS.md Normal file
View File

@ -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<lang>-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<lang>-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
-------------

View File

@ -158,8 +158,8 @@ bool stdlib(Target &target, const char *, const char *val, char **) {
return true; return true;
} }
bool outputname(Target &target, const char *, const char *val, char **) { bool language(Target &target, const char *, const char *val, char **) {
target.outputname = val; target.language = val;
return true; return true;
} }
@ -250,7 +250,7 @@ constexpr struct Opt {
{"-m32", arch}, {"-m32", arch},
{"-mx32", arch}, {"-mx32", arch},
{"-m64", arch}, {"-m64", arch},
{"-o", outputname, true, true}, {"-x", language, true, true},
{"-foc-use-gcc-libstdc++", usegcclibstdcxx}, {"-foc-use-gcc-libstdc++", usegcclibstdcxx},
{"-foc-run-prog", runprog, true, false, "="}, // for internal use only {"-foc-run-prog", runprog, true, false, "="}, // for internal use only
{"-isystem", checkincludepath, true, true}, {"-isystem", checkincludepath, true, true},

View File

@ -173,6 +173,27 @@ bool Target::isCXX() {
return endsWith(compilername, "++"); 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 { const std::string &Target::getDefaultTriple(std::string &triple) const {
triple = getArchName(Arch::x86_64); triple = getArchName(Arch::x86_64);
triple += "-"; triple += "-";
@ -585,13 +606,13 @@ bool Target::setup() {
fargs.push_back("-Qunused-arguments"); 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 // Use libs from './build_gcc' installation
setupGCCLibs(targetarch[0]); setupGCCLibs(targetarch[0]);
} }
} }
} else if (isGCC()) { } else if (isGCC()) {
if (isCXX() && isLibCXX()) { if (isCXX() && isLibCXX()) {
fargs.push_back("-nostdinc++"); fargs.push_back("-nostdinc++");
fargs.push_back("-nodefaultlibs"); fargs.push_back("-nodefaultlibs");
@ -607,6 +628,7 @@ bool Target::setup() {
fargs.push_back("-static-libstdc++"); fargs.push_back("-static-libstdc++");
} }
if (!isGCH())
fargs.push_back("-Wl,-no_compact_unwind"); fargs.push_back("-Wl,-no_compact_unwind");
} }

View File

@ -70,7 +70,7 @@ struct Target {
: vendor(getDefaultVendor()), SDK(getenv("OSXCROSS_SDKROOT")), : vendor(getDefaultVendor()), SDK(getenv("OSXCROSS_SDKROOT")),
arch(Arch::x86_64), target(getDefaultTarget()), stdlib(StdLib::unset), arch(Arch::x86_64), target(getDefaultTarget()), stdlib(StdLib::unset),
usegcclibs(), nocodegen(), compilername(getDefaultCompiler()), usegcclibs(), nocodegen(), compilername(getDefaultCompiler()),
outputname() { language() {
if (!getExecutablePath(execpath, sizeof(execpath))) if (!getExecutablePath(execpath, sizeof(execpath)))
abort(); abort();
} }
@ -93,26 +93,11 @@ struct Target {
bool isLibCXX() const; bool isLibCXX() const;
bool isLibSTDCXX() const; bool isLibSTDCXX() const;
bool haveOutputName() { return outputname != nullptr; }
bool isCXX(); bool isCXX();
bool isGCH();
bool isGCH() { bool isClang() const;
if (haveOutputName()) { bool isGCC() const;
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 isKnownCompiler() const { return isClang() || isGCC(); } bool isKnownCompiler() const { return isClang() || isGCC(); }
@ -143,7 +128,7 @@ struct Target {
std::string otriple; std::string otriple;
string_vector fargs; string_vector fargs;
string_vector args; string_vector args;
const char *outputname; const char *language;
char execpath[PATH_MAX + 1]; char execpath[PATH_MAX + 1];
}; };

View File

@ -172,7 +172,9 @@ eval $(osxcross-conf)
} }
@test "command line parsing" { @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 ] [ "$status" -eq 0 ]
[[ "${lines[0]}" == *\ -mmacosx-version-min=10.4*\ * ]] [[ "${lines[0]}" == *\ -mmacosx-version-min=10.4*\ * ]]
[[ "${lines[0]}" == *\ -g\ *\ * ]] [[ "${lines[0]}" == *\ -g\ *\ * ]]
@ -180,6 +182,8 @@ eval $(osxcross-conf)
[[ "${lines[0]}" == *\ -march=native\ * ]] [[ "${lines[0]}" == *\ -march=native\ * ]]
[[ "${lines[0]}" == *\ -Itest2\ * ]] [[ "${lines[0]}" == *\ -Itest2\ * ]]
[[ "${lines[0]}" == *\ -O2\ * ]] [[ "${lines[0]}" == *\ -O2\ * ]]
[[ "${lines[0]}" == *\ -xc-header\ * ]]
[[ "${lines[0]}" == *\ -x\ c++-header\ * ]]
[[ "${lines[0]}" != *\ -stdlib=default\ * ]] [[ "${lines[0]}" != *\ -stdlib=default\ * ]]
[[ "${lines[0]}" == *\ -otest1\ * ]] [[ "${lines[0]}" == *\ -otest1\ * ]]
[[ "${lines[0]}" == *\ -o\ test2\ * ]] [[ "${lines[0]}" == *\ -o\ test2\ * ]]
@ -337,6 +341,24 @@ eval $(osxcross-conf)
[[ "${lines[0]}" == *error:\ value\ of\ \'-stdlib=\'\ must\ be\ \'default\',\ \'libc++\'\ or\ \'libstdc++\' ]] [[ "${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" { @test "-arch/-m32/-m64/-m16/-mx32" {
run o64-clang++ -arch x86_64 -arch i386 -arch x86_64 -arch i386 run o64-clang++ -arch x86_64 -arch i386 -arch x86_64 -arch i386
[ "$status" -eq 0 ] [ "$status" -eq 0 ]