mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-05-28 15:55:20 +00:00
pkg/highway: Darwin builds don't rely on Apple headers
This uses a custom fork of `hwy/targtes.cpp` that uses an extern function written in Zig to use Zig's standard CPU detection to avoid a dependency on Apple SDK headers. This is on the path to removing Apple SDK requirements to build libghostty-vt, but will require a lot more work outside of this. The goal is to get this out of our external dependencies first and then we can work on removing the internal side.
This commit is contained in:
60
pkg/highway/src/cpp/bridge.cpp
Normal file
60
pkg/highway/src/cpp/bridge.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include <hwy/abort.h>
|
||||
#include <hwy/base.h>
|
||||
#include <hwy/targets.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace hwy {
|
||||
namespace {
|
||||
|
||||
// Highway's upstream abort.cc pulls in libc++ even when the rest of the
|
||||
// library is compiled with HWY_NO_LIBCXX. Ghostty only needs Highway's dynamic
|
||||
// dispatch/runtime target selection, so we provide the tiny Warn/Abort surface
|
||||
// that targets.cc/per_target.cc expect and keep the package free of libc++.
|
||||
WarnFunc g_warn_func = nullptr;
|
||||
AbortFunc g_abort_func = nullptr;
|
||||
|
||||
} // namespace
|
||||
|
||||
WarnFunc& GetWarnFunc() {
|
||||
return g_warn_func;
|
||||
}
|
||||
|
||||
AbortFunc& GetAbortFunc() {
|
||||
return g_abort_func;
|
||||
}
|
||||
|
||||
WarnFunc SetWarnFunc(WarnFunc func) {
|
||||
// Highway documents these setters as thread-safe. Using the compiler builtin
|
||||
// keeps that guarantee without depending on std::atomic.
|
||||
return __atomic_exchange_n(&g_warn_func, func, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
AbortFunc SetAbortFunc(AbortFunc func) {
|
||||
return __atomic_exchange_n(&g_abort_func, func, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
void Warn(const char* file, int line, const char* format, ...) {
|
||||
if (WarnFunc func = __atomic_load_n(&g_warn_func, __ATOMIC_SEQ_CST)) {
|
||||
func(file, line, format);
|
||||
}
|
||||
}
|
||||
|
||||
HWY_NORETURN void Abort(const char* file, int line, const char* format, ...) {
|
||||
if (AbortFunc func = __atomic_load_n(&g_abort_func, __ATOMIC_SEQ_CST)) {
|
||||
func(file, line, format);
|
||||
}
|
||||
|
||||
__builtin_trap();
|
||||
}
|
||||
|
||||
} // namespace hwy
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Zig reads HWY_SUPPORTED_TARGETS via this C shim so it can keep its target
|
||||
// enum in sync with the vendored Highway build without parsing C++ headers.
|
||||
int64_t hwy_supported_targets() {
|
||||
return HWY_SUPPORTED_TARGETS;
|
||||
}
|
||||
}
|
||||
61
pkg/highway/src/cpp/targets_darwin.cpp
Normal file
61
pkg/highway/src/cpp/targets_darwin.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include <hwy/base.h>
|
||||
#include <hwy/detect_targets.h>
|
||||
#include <hwy/highway.h>
|
||||
#include <hwy/targets.h>
|
||||
|
||||
namespace hwy {
|
||||
|
||||
extern "C" int64_t ghostty_hwy_detect_targets();
|
||||
|
||||
static int64_t DetectTargets() {
|
||||
int64_t bits = HWY_SCALAR | HWY_EMU128;
|
||||
|
||||
#if (HWY_ARCH_X86 || HWY_ARCH_ARM) && HWY_HAVE_RUNTIME_DISPATCH
|
||||
bits |= ghostty_hwy_detect_targets();
|
||||
#else
|
||||
bits |= HWY_ENABLED_BASELINE;
|
||||
#endif
|
||||
|
||||
if ((bits & HWY_ENABLED_BASELINE) != HWY_ENABLED_BASELINE) {
|
||||
const uint64_t bits_u = static_cast<uint64_t>(bits);
|
||||
const uint64_t enabled = static_cast<uint64_t>(HWY_ENABLED_BASELINE);
|
||||
HWY_WARN("CPU supports 0x%08x%08x, software requires 0x%08x%08x\n",
|
||||
static_cast<uint32_t>(bits_u >> 32),
|
||||
static_cast<uint32_t>(bits_u & 0xFFFFFFFF),
|
||||
static_cast<uint32_t>(enabled >> 32),
|
||||
static_cast<uint32_t>(enabled & 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
static int64_t supported_targets_for_test_ = 0;
|
||||
static int64_t supported_mask_ = LimitsMax<int64_t>();
|
||||
|
||||
HWY_DLLEXPORT void DisableTargets(int64_t disabled_targets) {
|
||||
supported_mask_ = static_cast<int64_t>(~disabled_targets);
|
||||
GetChosenTarget().DeInit();
|
||||
}
|
||||
|
||||
HWY_DLLEXPORT void SetSupportedTargetsForTest(int64_t targets) {
|
||||
supported_targets_for_test_ = targets;
|
||||
GetChosenTarget().DeInit();
|
||||
}
|
||||
|
||||
HWY_DLLEXPORT int64_t SupportedTargets() {
|
||||
int64_t targets = supported_targets_for_test_;
|
||||
if (HWY_LIKELY(targets == 0)) {
|
||||
targets = DetectTargets();
|
||||
GetChosenTarget().Update(targets);
|
||||
}
|
||||
|
||||
targets &= supported_mask_;
|
||||
return targets == 0 ? HWY_STATIC_TARGET : targets;
|
||||
}
|
||||
|
||||
HWY_DLLEXPORT ChosenTarget& GetChosenTarget() {
|
||||
static ChosenTarget chosen_target;
|
||||
return chosen_target;
|
||||
}
|
||||
|
||||
} // namespace hwy
|
||||
Reference in New Issue
Block a user