atilaneves / dpp

Directly include C headers in D source code
Boost Software License 1.0
231 stars 31 forks source link

c standard library doesn't work on macOS #20

Open John-Colvin opened 6 years ago

John-Colvin commented 6 years ago

Everything complains about not being able to find the stdint types, e.g. Error parsing '/usr/local/include/nanomsg/nn.h': error: unknown type name 'uint64_t'

even a simple file that just does #include <stdlib.h> doesn't work: Error: object.Exception@../../.dub/packages/libclang-master/libclang/source/clang/package.d(61): Error parsing '/usr/include/stdlib.h': error: unknown type name 'uint8_t'

atilaneves commented 6 years ago

That has to be because of the system headers. I don't know how to find them on MacOS (nor can I try since I don't have access to a mac). On Linux this works (and is being used):

string[] systemPaths() @safe {
    import std.process: execute;
    import std.string: splitLines, stripLeft;
    import std.algorithm: map, countUntil;
    import std.array: array;

    const res = execute(["gcc", "-v", "-xc", "/dev/null", "-fsyntax-only"]);
    if(res.status != 0) throw new Exception("Failed to call gcc:\n" ~ res.output);

    auto lines = res.output.splitLines;

    const startIndex = lines.countUntil("#include <...> search starts here:") + 1;
    assert(startIndex > 0);
    const endIndex = lines.countUntil("End of search list.");
    assert(endIndex > 0);

    return lines[startIndex .. endIndex].map!stripLeft.array;
}
John-Colvin commented 6 years ago

that works fine, it gets /usr/include/stdlib.h it's just that clang can't seem to handle the header it finds.

John-Colvin commented 6 years ago

Hmm. This may be to do with incompatibilities between libclang and the system headers, because the system headers belong to an entirely different toolchain (still clang in this case, but not the same clang).

I tried modifying the libclang wrapper to look up the paths using the clang that came with my libclang installation, which avoided any libclang errors about failing to parse the headers, but then choked because the "block pointer" C extension stuff in the modern headers confuses dpp

e.g.

Could not translate cursor Cursor(FunctionDecl, "atexit_b", Type(FunctionProto, "int (void (^ _Nonnull)(void))"), Type(Int, "int")) sourceRange: SourceRange("/usr/include/stdlib.h", 281:1, 281:90) children: [Cursor(FirstAttr, "", Type(Invalid, "")), Cursor(ParmDecl, "", Type(BlockPointer, "void (^)(void)"))]
Error: Type kind BlockPointer not supported: Type(BlockPointer, "void (^)(void)")
Laeeth commented 6 years ago

General problem of precedence. For example imapfilter has a file called regexp.h and GCC standard library has a defunct stub with that name too. So using the -i flag it looks in the wrong order for problem at hand and fails to compile.

jacob-carlborg commented 6 years ago

Why are the system paths needed? DStep doesn't need them. The compiler will find them by itself.

jacob-carlborg commented 6 years ago

BTW, here's the result of the above command using Xcode 9.2.

$ gcc -v -xc /dev/null -fsyntax-only
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.12.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -fsyntax-only -disable-free -disable-llvm-verifier -discard-value-names -main-file-name null -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm-verbose -munwind-tables -target-cpu penryn -target-linker-version 305 -v -dwarf-column-info -debugger-tuning=lldb -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/9.0.0 -fdebug-compilation-dir /Users/jacobc/.dub/packages/libclang-master -ferror-limit 19 -fmessage-length 158 -stack-protector 1 -fblocks -fobjc-runtime=macosx-10.12.0 -fencode-extended-block-signature -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -x c /dev/null
clang -cc1 version 9.0.0 (clang-900.0.39.2) default target x86_64-apple-darwin16.7.0
ignoring nonexistent directory "/usr/local/include"
#include "..." search starts here:
#include <...> search starts here:
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/9.0.0/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.
atilaneves commented 6 years ago

System paths have always been needed with libclang in my experience. I don't know how dstep does it.

jacob-carlborg commented 6 years ago

For Clang, what's needed is the internal headers. DStep embeds these in the executable (so far only a few of them) [1]. If you use the standard C library of course that is needed as well, but the compiler will find that automatically.

Keep in mind that the internal headers might not be the same for GCC and for Clang. Invoking the system compiler to get the path to the internal headers might not be a good idea. There's a chance that it won't work for a specific combination of platform and the version of Clang that d++ is built against.

[1] https://github.com/jacob-carlborg/dstep/blob/master/clang/Compiler.d