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;
}
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},

View File

@ -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) {

View File

@ -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];
};

View File

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