111 lines
3.7 KiB
Diff
111 lines
3.7 KiB
Diff
iig-port: Darwin parsing and Clang resource headers
|
|
|
|
Against Nyktis/iig-port @ ea6d147.
|
|
|
|
On Linux, use --target=arm64-apple-darwin when the caller supplies no target.
|
|
The setup script defines UNIXNU_CLANG_RESOURCE_DIR from the selected clang's
|
|
-print-resource-dir output. Standalone builds derive the resource directory
|
|
from the loaded libclang library and its version. An explicit -resource-dir
|
|
argument takes priority.
|
|
|
|
--- a/iig.cpp
|
|
+++ b/iig.cpp
|
|
@@ -22,6 +22,11 @@
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
+#if !defined(__APPLE__)
|
|
+#include <dlfcn.h>
|
|
+#include <sys/stat.h>
|
|
+#endif
|
|
+
|
|
namespace {
|
|
|
|
const char kIIGVersion[] = "DriverKit-440";
|
|
@@ -1375,6 +1380,54 @@ void add_direct_iig_includes(const Options &opt, ParseState *state)
|
|
|
|
void resolve_parameter_facts(ParseState *state);
|
|
|
|
+#if !defined(__APPLE__)
|
|
+// clang's builtin headers (the stdint.h that xnu's EXTERNAL_HEADERS/stdint.h
|
|
+// #include_next's) for the libclang this process loaded. libclang works the
|
|
+// directory out for itself only relative to an empty driver path, which
|
|
+// resolves from some working directories and not from make's. Its C API has
|
|
+// no call for the directory, so start from the library file dladdr() names
|
|
+// and the major version clang_getClangVersion() reports, and take the first
|
|
+// layout whose include/stdint.h exists: <prefix>/lib/libclang.so with
|
|
+// <prefix>/lib/clang/N (an upstream install), or a multiarch
|
|
+// /usr/lib/<triple>/libclang-N.so.N with /usr/lib/clang/N (Debian and
|
|
+// apt.llvm.org). Empty when neither exists.
|
|
+static std::string libclang_resource_dir()
|
|
+{
|
|
+#ifdef UNIXNU_CLANG_RESOURCE_DIR
|
|
+ return UNIXNU_CLANG_RESOURCE_DIR;
|
|
+#endif
|
|
+ Dl_info info;
|
|
+ if (dladdr((void *)&clang_createIndex, &info) == 0 || info.dli_fname == nullptr) {
|
|
+ return "";
|
|
+ }
|
|
+ std::string lib = info.dli_fname;
|
|
+ std::string libdir = lib.substr(0, lib.rfind('/'));
|
|
+ std::string parent = libdir.substr(0, libdir.rfind('/'));
|
|
+
|
|
+ CXString cxversion = clang_getClangVersion();
|
|
+ std::string version = clang_getCString(cxversion);
|
|
+ clang_disposeString(cxversion);
|
|
+ std::string major;
|
|
+ size_t at = version.find("version ");
|
|
+ if (at != std::string::npos) {
|
|
+ for (size_t i = at + 8; i < version.size() && isdigit((unsigned char)version[i]); ++i) {
|
|
+ major += version[i];
|
|
+ }
|
|
+ }
|
|
+ if (major.empty()) {
|
|
+ return "";
|
|
+ }
|
|
+
|
|
+ for (const std::string &dir : {parent + "/lib/clang/" + major, parent + "/clang/" + major}) {
|
|
+ struct stat st;
|
|
+ if (stat((dir + "/include/stdint.h").c_str(), &st) == 0) {
|
|
+ return dir;
|
|
+ }
|
|
+ }
|
|
+ return "";
|
|
+}
|
|
+#endif
|
|
+
|
|
int parse_iig(const Options &opt, ParseState *state)
|
|
{
|
|
for (std::size_t i = 0; i < opt.clang_args.size(); ++i) {
|
|
@@ -1395,6 +1448,30 @@ int parse_iig(const Options &opt, ParseState *state)
|
|
|
|
CXIndex index = clang_createIndex(0, 0);
|
|
std::vector<const char *> args;
|
|
+#if !defined(__APPLE__)
|
|
+ // libclang parses for its default triple. On a Mac that is the host's
|
|
+ // Darwin triple, which is what Apple's iig gets; on any other host it is
|
|
+ // that host's, where xnu's mach/machine/*.h stop with "architecture not
|
|
+ // supported". Default to Darwin unless the caller passed --target=.
|
|
+ bool have_target = false;
|
|
+ bool have_resource_dir = false;
|
|
+ for (const std::string &arg : opt.clang_args) {
|
|
+ if (arg.rfind("--target=", 0) == 0) {
|
|
+ have_target = true;
|
|
+ }
|
|
+ if (arg == "-resource-dir" || arg.rfind("-resource-dir=", 0) == 0) {
|
|
+ have_resource_dir = true;
|
|
+ }
|
|
+ }
|
|
+ if (!have_target) {
|
|
+ args.push_back("--target=arm64-apple-darwin");
|
|
+ }
|
|
+ static const std::string resource_dir = libclang_resource_dir();
|
|
+ if (!have_resource_dir && !resource_dir.empty()) {
|
|
+ args.push_back("-resource-dir");
|
|
+ args.push_back(resource_dir.c_str());
|
|
+ }
|
|
+#endif
|
|
for (const std::string &arg : opt.clang_args) {
|
|
args.push_back(arg.c_str());
|
|
}
|