Skip to content

Conversation

mszabo-wikia
Copy link
Owner

As facebook#9564, but with an attempt to get it to build on a plain GH Actions runner.

@mszabo-wikia mszabo-wikia force-pushed the fix-oss-build-mirror branch 4 times, most recently from 34b6dda to cb5455f Compare June 3, 2025 13:36
@hershel-theodore-layton
Copy link

hershel-theodore-layton commented Jun 5, 2025

Hi @mszabo-wikia, I have been following the developments of your branches closely. I want to thank you for fixing the bit rot on hhvm@next. I have given you a shout out on my GH.

I have built hhvm from source, with your branch as a base, for my OSS CI and for use deployed projects.

I have a change that might be good to include in your upstream, added support for ext_mysql and ext_async_mysql. These are two native extensions I rely upon. How would you like to receive patches? I have linked my commits below. Do with them what you please in any way.

These commit links might become invalid when I rebase on a later change of yours and force push, so hereby also a textual description of the changes made.

The first two remove -DENABLE_EXTENSION_MYSQL=Off and -DENABLE_EXTENSION_ASYNC_MYSQL=Off respectively. I cannot build MYSQL without ASYNC_MYSQL. The build flag of ASYNC_MYSQL is responsible for building SSLOptionsProviderBase.h, which is required by MYSQL. The last one removes third-party/squangle/src/squangle/util/tests/StorageRowTest.cpp, which is a test file that fails to compile due to the error message in the commit (missing gtest). Removing this file is an inelegant solution to that problem, but the file is not needed to enjoy these extensions from Hack.

I hereby give you, and anymore else reading this, permission to use these diffs, in whole or in part, with or without attribution, for any purpose. My employer is aware I contribute to open source and has carved out an explicit permission for me to contribute in my personal capacity.

@mszabo-wikia
Copy link
Owner Author

@hershel-theodore-layton Thank you, I appreciate it. There's indeed no need to exclude these extensions now that the squangle maintainer has fixed the OSS build issues that were blocking it a few months back :)

Thanks for your patches. Strangely the stray test file didn't cause any build errors locally for me, but you're correct that it shouldn't be part of a production build either way. I opted to remove it from the source list so it should no longer cause issues.

As for the failing CI here... my sources say that GitHub Actions was disabled over at the main repo due to my overly enthusiastic rebasing causing a budget overrun, which certainly was not part of the plan. Sadly the default actions runners don't have enough free disk space to accommodate an HHVM build by default, but there should be ways to fix this by removing cruft from the default runner (which however also requires containerizing only the package build step instead of the entire job, else any attempt at cleanup won't be able to remove anything from the runner proper). It'll take some fiddling, but should be doable.

LMK if you have any questions.

@mszabo-wikia mszabo-wikia force-pushed the fix-oss-build-mirror branch 4 times, most recently from 7055206 to d575db5 Compare June 5, 2025 23:13
@mszabo-wikia mszabo-wikia mentioned this pull request Jun 6, 2025
5 tasks
mszabo-wikia pushed a commit that referenced this pull request Jun 16, 2025
Summary:
The `MicroLock` tests fail under libc++ with asan-abort `stack-buffer-overflow`.

Example:
```
SCARINESS: 32 (4-byte-read-stack-buffer-overflow)
    #0 unsigned int std::__2::__cxx_atomic_load[abi:ue170004]<unsigned int>(std::__2::__cxx_atomic_base_impl<unsigned int> const*, std::__2::memory_order) libcxx/include/c++/v1/__atomic/cxx_atomic_impl.h:375
    #1 std::__2::__atomic_base<unsigned int, false>::load[abi:ue170004](std::__2::memory_order) const libcxx/include/c++/v1/__atomic/atomic_base.h:60
    facebook#2 folly::MicroLockBase<1000u, 0u>::try_lock() folly/MicroLock.h:319
    facebook#3 SmallLocks_MicroLockTryLock_Test::TestBody() folly/synchronization/test/SmallLocksTest.cpp:314
```

The trouble is accessing the lock state as a 4-byte word, where the asan stack has allocated only 1 byte for the lock object - asan tracks this and aborts.

It is UB for `MicroLock` to perform atomic stores or atomic read-modify-write operations on the entire 4-byte aligned word containing the `MicroLock` which may be concurrent with other accesses to other bytes in the word. The 4-byte aligned word accesses are necessary in order to support using the `MicroLock` itself as a futex, on Linux platforms. The trouble is that Linux does not provide futex operations on all sizes of integer, only on 32-bit (4-byte) integers. If Linux were to provide futex operations on all sizes of integer, we would immediately switch to 8-bit (1-byte) integers here.

This diff fixes the UB and gets the tests passing under libc++ by switching to the `folly::ParkingLot`, as wrapped by `folly::atomic_notify_one` and `folly::atomic_wait` over `std::atomic<uint8_t>`, which indirects the 32-bit (4-byte) futex behind a sharded hashtable.

Alternatives are possible for getting the tests passing, although these alternatives would not fix the UB.
* We can disable sanitizers on even more functions, as well as switch to atomic builtins since the members of `std::atomic` are not marked as disabling the sanitizers.
* We can workaround just in the unit-tests by padding the on-stack `MicroLock` instances.

Reviewed By: praihan, ot, aary

Differential Revision: D76612658

fbshipit-source-id: 75e9f03e63c85c30c6201b9bce5cd303c9a2b530
@mszabo-wikia mszabo-wikia force-pushed the fix-oss-build-mirror branch from d575db5 to 539ffa8 Compare June 18, 2025 02:02
mszabo-wikia pushed a commit that referenced this pull request Jun 18, 2025
Summary:
After recent Python 3.12 rollout we started seeing crashes, e.g. T223049180.

Crash stack from core dumps points to tstate being null when `_PyErr_GetRaisedException` is called

```
* thread #1, name = 'server#native-m', stop reason = SIGSEGV: address not mapped to object (fault address=0x60)
  * frame #0: 0x00007f94039e0197 libpython3.12.so.1.0`_PyFrame_MakeAndSetFrameObject [inlined] _PyErr_GetRaisedException(tstate=0x0000000000000000) at errors.c:490
    frame #1: 0x00007f94039e0197 libpython3.12.so.1.0`_PyFrame_MakeAndSetFrameObject [inlined] PyErr_GetRaisedException at errors.c:499
    frame facebook#2: 0x00007f94039e0184 libpython3.12.so.1.0`_PyFrame_MakeAndSetFrameObject(frame=0x00007f940977f340) at frame.c:32
    frame facebook#3: 0x00007f9403b9d3de libpython3.12.so.1.0`PyThreadState_GetFrame [inlined] _PyFrame_GetFrameObject(frame=<unavailable>) (.__uniq.305758459065587366612134685926705492046) at pycore_frame.h:213
    frame facebook#4: 0x00007f9403b9d3d0 libpython3.12.so.1.0`PyThreadState_GetFrame(tstate=<unavailable>) at pystate.c:1754
```

The problem happens when this code is called (https://fburl.com/26dhwv4v)

```
PyObject *
PyErr_GetRaisedException(void)
{
    PyThreadState *tstate = _PyThreadState_GET();
    return _PyErr_GetRaisedException(tstate);
}
```

Where `_PyThreadState_GET` is implemented as follows https://fburl.com/92hrrluf
```

/* Get the current Python thread state.

   This function is unsafe: it does not check for error and it can return NULL.

   The caller must hold the GIL

   See also PyThreadState_Get() and _PyThreadState_UncheckedGet(). */

static inline PyThreadState*
_PyThreadState_GET(void)
{
#if defined(HAVE_THREAD_LOCAL) && !defined(Py_BUILD_CORE_MODULE)
    return _Py_tss_tstate;
#else
    return _PyThreadState_GetCurrent();
#endif
```
**The caller must hold the GIL** is a problem for us, since the whole idea behind implementing this hook this way is to get the stack when we **don't** have the GIL. This code implements a copy of the current

To work around the issue we are copying the Python runtime code, but WITHOUT the GIL checks

[_PyFrame_MakeAndSetFrameObject](https://github.com/python/cpython/blob/3.12/Python/frame.c#L28C1-L64C1) is reimplemented to skip the `PyErr_GetRaisedException` call, e.g.

[_PyFrame_New_NoTrack](https://github.com/python/cpython/blob/main/Objects/frameobject.c#L2107C1-L2125C2) Changes from

```
PyFrameObject*
_PyFrame_New_NoTrack(PyCodeObject *code)
{
    CALL_STAT_INC(frame_objects_created);
    int slots = code->co_nlocalsplus + code->co_stacksize;
    PyFrameObject *f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, slots);
    if (f == NULL) {
        return NULL;
    }
    f->f_back = NULL;
    f->f_trace = NULL;
    f->f_trace_lines = 1;
    f->f_trace_opcodes = 0;
    f->f_lineno = 0;
    f->f_extra_locals = NULL;
    f->f_locals_cache = NULL;
    f->f_overwritten_fast_locals = NULL;
    return f;
}
```

to
```
thread_local PyFrameObject my_frame;
PyFrameObject* MyPyFrame_New_NoTrack(_PyInterpreterFrame* frame) {
  PyFrameObject* f = &my_frame;
  if (f == NULL) {
    return NULL;
  }
  f->f_back = NULL;
  f->f_trace = NULL;
  f->f_trace_lines = 1;
  f->f_trace_opcodes = 0;
  f->f_fast_as_locals = 0;
  f->f_lineno = 0;
  f->f_frame = frame;
  frame->frame_obj = f;
  Py_SET_TYPE(reinterpret_cast<PyObject*>(frame->frame_obj), &PyFrame_Type);
  return f;
}
```

A thread local variable is being reused since we don't want to keep allocating and deallocating on the heap while doing heap profiling.

Reviewed By: fried

Differential Revision: D74118996

fbshipit-source-id: 65b9a9a10d6aa26f9c1cd93e30486333f20f4b24
mszabo-wikia pushed a commit that referenced this pull request Jun 18, 2025
Summary:
This diff addresses a problem affecting the interaction of the OCaml runtime, Tokio, and Folly:

- Our own `ocamlrep` crate allows us to register finalizers for the `Custom<>` types owned by OCaml. Usually, these just call `drop` on the Rust side.
- When an OCaml program terminates, it does not call the finalizers of the objects that are alive at that point (see https://ocaml.org/docs/garbage-collection#finalisation-and-the-weak-module)
- When running Hack with `edenfs_file_watcher_enabled`, the server env contains an (opaque) `Custom<EdenfsWatcherInstanceHandle>`, which owns the Tokio runtime executing a worker thread. Due to the points above, when calling `Exit.exit` in the server, the Tokio runtime and worker thread continue running.
- Folly registers a low-level hook that is run when the program actually terminates (after the OCaml runtime has finished its own shutdown logic)
- This low-level hook can deadlock when the `EdenfsWatcherInstance` is still running. I'm not sure what exactly is causing the deadlock (the fact that the worker thread is still running or the mere existence of the Tokio runtime, ...)

Concretely, this problems manifests itself by the server sometimes getting stuck when calling `Exit.exit`.
This diff changes the initialization code for `Edenfs_watcher` instances such that whenever we create an instance, we call `Exit.add_hook_upon_clean_exit` to register a hook that will properly shut down the instance. Note that this hook mechanism is part of our own code, and is run before the lower-level exit handler installed by Folly.

## Alternatives considered:
OCaml has a "cleanup_on_exit mode, which among other things should call all finalizers (see https://ocaml.org/manual/5.3/runtime.html#s:ocamlrun-options). However, it seems to be buggy in OCaml 5.x (see ocaml/ocaml#10865 (comment)) and running hh_server with `OCAMLRUNPARAM=c` doesn't fix our problem.
I'm not sure if we would want to use it anyway, as it may slow down server restarts.

# Facebook

Here's a stack trace where we get stuck. I've obtained it by attaching gdb to the server process:

```
#0  __futex_abstimed_wait_common64 (private=<optimized out>, cancel=true, abstime=0x0, op=265, expected=3432193, futex_word=0x7fffb4000910) at futex-internal.c:57
#1  __futex_abstimed_wait_common (cancel=true, private=<optimized out>, abstime=0x0, clockid=<optimized out>, expected=3432193, futex_word=0x7fffb4000910) at futex-internal.c:87
facebook#2  __GI___futex_abstimed_wait_cancelable64 (futex_word=0x7fffb4000910, expected=3432193, clockid=<optimized out>, abstime=0x0, private=<optimized out>) at futex-internal.c:139
facebook#3  0x00007ffff729c793 in __pthread_clockjoin_ex (threadid=140736213288512, thread_return=0x0, clockid=0, abstime=0x0, block=<optimized out>) at pthread_join_common.c:105
facebook#4  0x00007ffff7cdf84f in __gthread_join (__value_ptr=0x0, __threadid=<optimized out>) at /home/engshare/third-party2/libgcc/11.x/src/gcc-11.x/x86_64-facebook-linux/libstdc++-v3/include/x86_64-facebook-linux/bits/gthr-default.h:669
facebook#5  std::thread::join (this=0x7fffbe209110) at ../../../.././libstdc++-v3/src/c++11/thread.cc:112
facebook#6  0x00000000062a810d in folly::ThreadPoolExecutor::joinStoppedThreads(unsigned long) ()
facebook#7  0x00000000062a89ca in folly::ThreadPoolExecutor::stopAndJoinAllThreads(bool) ()
facebook#8  0x00000000062a395b in folly::IOThreadPoolExecutor::~IOThreadPoolExecutor() ()
facebook#9  0x00000000062a1975 in folly::IOThreadPoolExecutor::~IOThreadPoolExecutor() ()
facebook#10 0x0000000006452c09 in folly::detail::SingletonHolder<folly::IOThreadPoolExecutor>::destroyInstance() ()
facebook#11 0x0000000006fa3c0c in folly::SingletonVault::destroyInstances() ()
facebook#12 0x00007ffff72478b8 in __run_exit_handlers (status=4, listp=0x7ffff7412658 <__exit_funcs>, run_list_atexit=<optimized out>, run_dtors=<optimized out>) at exit.c:113
facebook#13 0x00007ffff72479ca in __GI_exit (status=<optimized out>) at exit.c:143
facebook#14 0x000000001f401e62 in caml_do_exit (retcode=4) at runtime/sys.c:200
facebook#15 0x000000001f4020dc in caml_sys_exit (retcode=<optimized out>) at runtime/sys.c:205
facebook#16 <signal handler called>
facebook#17 0x000000001f33c3f8 in camlStdlib.exit_1534 () at stdlib.ml:580
facebook#18 0x000000001f030ec0 in camlExit.exit_24 () at fbcode/hphp/hack/src/utils/exit.ml:66
facebook#19 0x000000001c2bb13b in camlServerMain.exit_if_critical_update_249 () at fbcode/hphp/hack/src/server/serverMain.ml:108
facebook#20 0x000000001c2bb885 in camlServerMain.query_notifier_549 () at fbcode/hphp/hack/src/server/serverMain.ml:225
facebook#21 0x000000001c2bbe32 in camlServerMain.recheck_until_no_changes_left_916 () at fbcode/hphp/hack/src/server/serverMain.ml:331
```

So we are shutting down the `folly::IOThreadPoolExecutor`, which then gets stuck waiting for something.

A comment inside `__pthread_clockjoin_ex` at the point where we get stucks reads
says
```
 /* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via
	    futex wake-up when the clone terminates.  The memory location
	    contains the thread ID while the clone is running and is reset to
	    zero by the kernel afterwards.  The kernel up to version 3.16.3
	    does not use the private futex operations for futex wake-up when
	    the clone terminates.  */
```

Differential Revision: D76737597

fbshipit-source-id: 979b4e9b3ae88a07fcf62f0958fe41372624d00b
@mszabo-wikia mszabo-wikia force-pushed the fix-oss-build-mirror branch 4 times, most recently from d3e01b9 to 8e3b901 Compare June 25, 2025 01:07
@mszabo-wikia mszabo-wikia force-pushed the fix-oss-build-mirror branch from 8e3b901 to 3e5305a Compare June 25, 2025 11:04
@hershel-theodore-layton

@mszabo-wikia

Thank you for fixing toString__FOR_DEBUGGING_ONLY() in f425e60. I have been working around that bug for a while. You have just made my documentation for my workaround obsolete, and I love it!

Same goes for including MCRouter in your branch with 423e8b1. This means I can remove this workaround too:

if (!\extension_loaded('mcrouter')) {
  return new ApcCache(); // cache-like wrapper around apcu
}
// Code below initializes cache-like wrapper around MCRouter, like I do on hhvm 4.168

I also wanted to let you know I am publishing ready-to-use images to Docker Hub, based on your branch. I use them to run my CI. I am going to write about this on my GH page in July. I want to give you all the credit for doing the hard C++ and CMake work. I would like to include a quote of yours about the building of hhvm@next. I can accommodate anything from a single sentence to an entire above-the-fold section, if you'd want to.

Here is a quick unrelated Bonus Tip. I don't know if you have already skip Lintian locally. This single threaded part might make up a significant part of your build time. You can disable lintian with this one-line change in make-debianish-package or with this ENV var from debuild. 🙂

mszabo-wikia pushed a commit that referenced this pull request Jun 28, 2025
Summary:
Updates typing of function references to polymorphic static methods so that we obtain a polymorphic function type. In particular the typing deals with the following:

- Use of method-level generics
- Use of class-level generics
- `where` constraints
- Use of `this`
- Use of abstract type constants

## Method-level generics

The current type of function references will not return a polymorphic function type. Instead, when referencing a polymorphic method the typing introduces type variables and adds bounds corresponding to any constraints on the generic it replaces. Given the declaration of `bar`:

```[hack]
class Wibble<Tclasslevel as arraykey> {
  public static function bar<Tmethodlevel as arraykey>(
    Tmethodlevel $y,
  ): void {}
}

function refEm(): void {
  $fptr = Wibble::bar<>;
}
```

a fresh type variable will be created with an upper bound of `arraykey` and `$fptr` will be given the type

```
readonly function(#1 $x): #1
```

where the type variable `#1` has an upper-bound of `arraykey`. Using `$fptr` will be introduce additional constraints on the type variables so the following is currently ill-typed:

```[hack]
function expect_int_int((function(int): int) $f): void {}

function refEm(): (function(string): string) {
  $fptr = Wibble::bar<>;
  expect_int_int($fptr);
  return $fptr;
}
```

After passing `$fptr` to `expect_int_int` the type variable will be solved to `int` so at the return expression we encounter

```
(function(int): int </: function(string): string)
```

With the new typing contained in this diff the function reference will instead be given a polymorphic function type:

```
HH\FunctionRef<(readonly function<Tmethodlevel as arraykey>(Tmethodlevel): Tmethodlevel)>
```

Subtyping of polymorphic function types permits us to pass this function where an expression of type `(function(int): int)` is expected. Doing so does not change the type and we are free to return `$fptr` where an expression of type `(function(string): string)` is expected.

Note that this typing is consistent with the already landed typing of generic top-level functions.

## Class-level generics

If a static method signature makes use of a generic declared in its enclosing class, it must be moved to the function type. For example:

```[hack]
class Wibble<Tclasslevel as arraykey> {
  public static function foo(Tclasslevel $x): Tclasslevel {
    return $x;
  }
}

function refEm(): (function(string): string) {
  $fptr = Wibble::foo<>;
  return $fptr;
}
```

The expression `$fptr` will be given the polymorphic function type:

```
HH\FunctionRef<(readonly function<Tclasslevel as arraykey>(Tclasslevel $x): Tclasslevel)>
```

## `where` constraints

A `where` constraint expresses a restriction on a type parameter which may not be defined at the method level e.g.

```
class C<T> {
  public static function foo(): void where T as arraykey {}
}

function refEm(): void {
  $fptr = C::foo<>;
}
```

Since `where ` constraints aren't part of the function type, we simplify then discharge any such contraints onto type parameters. This is always possible since we have closed over any required class-level type parameters; in the example we then have:

```
$fptr:  HH\FunctionRef<(readonly function<T as arraykey>(): void)>
```

`where` constraints can also relate method-level generics to class-level generics and is further complicated by inheritance.

```
class Base<T> {
  public static function foo<Tu>(Tu $arg): T where T super vec<Tu> {
    return vec[$arg];
  }
}

final class Derived<Ta> extends Base<vec<Ta>> {}

function refEm(): void {
  $fptr = Derived::foo<>;
}
```

```
$fptr:  HH\FunctionRef<(readonly function<Ta super Tu, Tu as Ta>(Tu $arg): vec<Ta>)>
```

Note that this typing is consistent with the already landed typing of generic top-level functions.

## `this`

The type identifier `this` is used to refer to instance types of the lexically enclosing class. The type of function references to static methods which have `this` in their method signature will depend on the variance at which `this` occurs in the method signature. If `this` appears only contravariantly or covariantly, we can directly substitute the
`this` for the instance type of the enclosing class, for example

```[hack]
class Wibble<Tclasslevel as arraykey> {
  public static function contra_only(this $_): void{}
  public static function co_only(): this { ... }
}

function refEm(): void {
  $fptr = Wibble::contra_only<>;
  $gptr = Wibble::co_only<>;
}
```

```
$fptr : HH\FunctionRef<(readonly function<Tclasslevel as arraykey>(Wibble<Tclasslevel> $_): void)>
$gptr : HH\FunctionRef<(readonly function<Tclasslevel as arraykey>(): Wibble<Tclasslevel>)>
```

Where `this` occurs invariantly we introduce a type parameter:
```[hack]
class Wibble<Tclasslevel as arraykey> {
  public static function invariantly(this $_): this { ... }
}

function refEm(): void {
  $fptr = Wibble::invariantly<>;
}
```

```
$fptr: HH\FunctionRef<(readonly function<Tthis as Wibble<Tclasslevel>, Tclasslevel as arraykey>(Tthis $x): Tthis)>
```

Note that the variance of occurrences of `this` is determined by an analysis of the function signature and is 'aware' of the variance of type parameters in class declarations. In this example,
- `this` appears invariantly in the signature of `fizz` since `Box` is invariant in its type parameter
- `this` appears covariantly in the signature of `buzz` since `Contra` is contravariant  in its type parameter but occurs in a contravariant position whilst `Co` is covariant in its type parameter and occurs in a covariant position.

```[hack]
class Box<T> {}

class Contra<-T> {}

class Co<+T> {}

class Wibble<Tclasslevel as arraykey> {
  public static function fizz(Box<this> $_): void {}

  public static function buzz(Contra<this> $_): ?Co<this>{
    return null;
  }
}
```

The logic for this part of typing is contained in the module `Typing_extract_method.This_variance`.

## Type constants

Abstract type constants and concrete type constant aliasing abstract type constants significantly complicate the typing of function references to static methods. The logic for this part of typing is contained in the module `Typing_extract_method.Typeconst_analysis`.

In order to 'extract' a method signature involving one of these constants from its containing class we make use of the following equivalence:

```
(exist T. U<T>) -> V === all T. (U<T> -> V)
```
To see how this applies, it's useful to think about the declaration of a class as being implicitly existentially quantified over all abstract type constants it contains. Moving these existentially quantified to type parameters and using class refinements to equate them allows us to be polymorphic in the type constant. For example:

```[hack]
abstract class Wibble {
  abstract const type T as arraykey;
  public static function foo(this $_, this::T $_, Wibble $_): void {}
}

function refEm(): void {
  $fptr = Wibble::foo<>;
}
```

```
 HH\FunctionRef<(readonly function<T#0 as arraykey>(Wibble with { type T = T#0 }, T#0,  Wibble): void)>
```

Note that in this example, we are only refining the first parameter type (`this`), not the third (`Wibble`).

The refinement works for arbitrary access paths, for example

```[hack]
abstract class AbstractA {
  abstract const type TA as arraykey;
}
abstract class AbstractLeft {
  abstract const type TLeft as AbstractA;
}

abstract class AbstractRight {
  abstract const type TRight as AbstractA;
}

abstract class AbstractB {
  abstract const type TL as AbstractLeft;
  abstract const type TR as AbstractRight;
}

abstract class AbstractC {
  abstract const type TC as AbstractB;
  public static function tickle(
    this $_,
    this::TC $_,
    this::TC::TL $_,
    this::TC::TR $_,
    this::TC::TR::TRight $_,
    this::TC::TL::TLeft $_,
    this::TC::TR::TRight::TA $_,
    this::TC::TL::TLeft::TA $_,
  ): void {}
}

function refEm(): void {
  $fptr = AbstractC::tickle<>;
}
```

```
$fptr :
     HH\FunctionRef<(readonly
       function<
         TA0 as arraykey,
         TA1 as arraykey,
         TC0 as AbstractB with { type TL = TL0; type TR = TR0 },
         TL0 as AbstractLeft with { type TLeft = TLeft0 },
         TLeft0 as AbstractA with { type TA = TA0 },
         TR0 as AbstractRight with { type TRight = TRight0 },
         TRight0 as AbstractA with { type TA = TA1 }
       >(
        AbstractC with { type TC = TC0 },
        TC0,
        TL0,
        TR0,
        TRight0,
        TLeft0,
        TA1,
        TA0
      ): void)>
```

The analysis is also able to correctly type methods with abstract constants containing fix-point refinements:

```
abstract class AbstractA {
  abstract const type T as AbstractA with { type T = this::T; };
  public static function foo(this $_): this::T { throw new Exception(); }
}

function refEm(): void {
  $fptr = AbstractA::foo<>;
  hh_show($fptr);
}
```

```
$fptr:
  HH\FunctionRef<(readonly
    function<
      T#0 as AbstractA with { type T = T#0 }
    >(
     AbstractA with { type T = T#0 }
     ): T#0)>
```

Reviewed By: andrewjkennedy

Differential Revision: D74076920

fbshipit-source-id: e4304f2680ac4b3b5d23c42759a867d2ee84b3f0
@mszabo-wikia mszabo-wikia force-pushed the fix-oss-build-mirror branch from 3e5305a to 84e2b01 Compare June 28, 2025 20:09
@mszabo-wikia
Copy link
Owner Author

@hershel-theodore-layton Thank you, I'm glad you find this useful :)

I'm honestly not sure what to share about the actual build process. Maybe the single most thing I'm curious about is—who else is out there? AFAIK the largest HHVM users outside Meta are Slack (who have already reached out on the original PR and have been very helpful in hunting down IDE integration issues and other problems), Quizlet and Baidu, but the latter two might well have migrated to Zend at some point, so that leaves me wondering who else stayed on HHVM/Hack.

Here follows an assortment of random notes that might be useful for others trying to build HHVM from scratch:

  • LLVM (i.e. clang + libcxx) 18 is used in CI, but >= 18 is fine too (I'm using LLVM 20 via my distro locally). v20 had some issues with folly recently, but those should be fixed now.
  • I recommend getting ccache as well, since a 50-60% hit ratio is attainable with a 5 GiB cache dir, which can be very helpful when iterating locally.
  • If possible, use a system with good thermals, because a laptop with a high core count CPU will likely have dissipation issues when doing sustained concurrent compilation. Using a desktop in comparison will noticeably improve compile times because you won't go to minclock just from utilizing all available cores.

And some aspirational goals/improvements for the build system:

  • Dependency tracking doesn't really work yet for some of the Rust targets that get linked into HHVM targets, so incremental rebuilds can eventually fail when the underlying Rust code changes, which then requires manually removing their outputs from the build dir.
  • A lot of the MSVS/GCC/Intel C++-related configuration cruft could be removed, alongside various now-obsolete options (e.g. toggling XeD, which is now a required dependency).
  • There are undocumented features in the repo that have never been integrated into the OSS build, even before the end of OSS support, which could be interesting to explore in the future.
  • It might be worth it to revive the Nix-based universal deb/rpm builds, but that seems like a whole new adventure :)

I'm very grateful to the folks from Meta who have been reviewing/landing my PRs split out from the original monstre PR when they find the time for it, so hopefully with time the main PR should get smaller and smaller. Once it's reasonably small, it might be interesting to setup some unofficial periodic OCI image build + publish workflow in a fork or dedicated repo so that people don't have to build their own if they don't want to.

As always let me know if you have any questions/suggestions.

@hershel-theodore-layton
Copy link

hershel-theodore-layton commented Jun 28, 2025

Maybe the single most thing I'm curious about is—who else is out there?

You don't happen to have access to the old hacklang.slack.com Slack instance, right? This used to be the place that both enthusiasts and people who use HHVM at work could join. This is what the Google form at https://hhvm.com/slack was set up for. This Slack is inactive, but it hasn't been removed (yet).

@mszabo-wikia
Copy link
Owner Author

@hershel-theodore-layton Yeah, I came across the form but I never was in that Slack sadly

mszabo-wikia pushed a commit that referenced this pull request Jul 17, 2025
Summary:
Fix for issue #1 in Post [Truncation of UserMetric::Time](https://fb.workplace.com/groups/560979627394613/permalink/3320975644728317/)

Our team uses [BENCHMARK_IMPL_COUNTERS](https://www.internalfb.com/code/fbsource/[f51516f2368d]/fbcode/folly/Benchmark.h?lines=379) to measure custom metrics during Folly::benchmarks execution. While working on updates to NodeAPI::SlaBenchmark in D77320464 I noticed Folly `UserMetric` accepts integer(Long) type values which works great for `UserMetric::Type::Custom` and `UserMetric::Type::Metric`, but causes issues for `UserMetric::Type::Time` values.

When [time metrics](https://www.internalfb.com/code/fbsource/[f51516f2368d8097604a13de292824a7d85d7de1]/fbcode/folly/Benchmark.cpp?lines=529) are formated for display the value is implicitly cast(`Long` -> `Double`) resulting in loss of precision. This results in any value smaller than 1s being displayed as 0.00fs due to the truncation making it impossible to display small time values.

~~This diff adds support for users to provide floating point values as input to `UserMetric` allowing precision to be retained through a new `time_value` field, while remaining backward compatible with existing usage that relies on the existing `value` field.~~ See discussion below

Reviewed By: yfeldblum

Differential Revision: D77319941

fbshipit-source-id: a4d55165b5429fa602ea357764db03a81b9ac760
@mszabo-wikia mszabo-wikia force-pushed the fix-oss-build-mirror branch from 84e2b01 to bafab28 Compare July 17, 2025 21:35
@mszabo-wikia mszabo-wikia force-pushed the fix-oss-build-mirror branch 2 times, most recently from 1594e91 to 40dbaaf Compare July 28, 2025 22:48
ROAR is specific to HHVM @ Meta, so do not include it in the OSS build.
@mszabo-wikia mszabo-wikia force-pushed the fix-oss-build-mirror branch 2 times, most recently from b15ab01 to d0ba8c6 Compare October 10, 2025 11:56
@IngwiePhoenix
Copy link

ARM? I am on ARM - on Alpine, in fact. Here's the flags I had to set - and I installed basically all the -dev packages I came across. But I lost track of that particular list...

-DEDITLINE_LIBRARIES=/usr/lib/libeditline.so.1
-DEDITLINE_INCLUDE_DIRS=/usr/include/
-DMYSQL_UNIX_SOCK_ADDR=/dev/null
-DUSE_BUNDLED_TZDATA=yes
-Wno-dev

But, I am running into an issue...

-- Using third-party bundled gflags
-- Download name: v2.2.2.tar.gz
CMake Error at third-party/gflags/CMakeLists.txt:48 (add_library):
  add_library cannot create target "gflags" because an imported target with
  the same name already exists.

The gflags-dev gets installed due to glog-dev - so I can't exactly get rid of it. Perhaps you can bundle glog as well?

This seems to partially be due to:

root@mobileboi ~/w/h/out (fix-oss-build-mirror)# cat CMakeCache.txt |grep -i gflags
//The directory containing a CMake configuration file for gflags.
gflags_DIR:PATH=/usr/lib/cmake/gflags

Here is all the CMake files the package provides:

root@mobileboi ~/w/h/out (fix-oss-build-mirror)# apk info -L gflags-dev | grep -i cmake
usr/lib/cmake/gflags/gflags-config-version.cmake
usr/lib/cmake/gflags/gflags-config.cmake
usr/lib/cmake/gflags/gflags-nonamespace-targets-none.cmake
usr/lib/cmake/gflags/gflags-nonamespace-targets.cmake
usr/lib/cmake/gflags/gflags-targets-none.cmake
usr/lib/cmake/gflags/gflags-targets.cmake

As for -Wno-dev:

root@mobileboi ~/w/h/out (fix-oss-build-mirror)# cmake --version
cmake version 3.31.7

CMake suite maintained and supported by Kitware (kitware.com/cmake).

...it might be too new, I'sppose. :)

@mszabo-wikia
Copy link
Owner Author

@IngwiePhoenix I think that might be because you're building without CLANG_FORCE_LIBCPP, so the build system tries to use the system versions of glog/gflags and fails. I've pushed two commits that should fix both the gflags issue and add various includes that would be missing when building with libstdc++ rather than libc++.

Note that if you do choose to use CLANG_FORCE_LIBCPP, the mechanism by which the build system tries to override search paths for vendored dependencies like glog/gflags is presently somewhat broken, which leads to folly etc. being built against system glog/gflags headers but HHVM gets linked against the vendored glog/gflags staticlibs. The quick & dirty fix for that is to simply bump the vendored glog/gflags version so that it's ABI-compatible with the system version. The proper fix will involve facebook/folly#2509 (and its counterparts in other repos) to actually get the overrides to work. I can push a commit that applies these to the mirrored folly etc. directories on this brnahc if you prefer.

@IngwiePhoenix
Copy link

@IngwiePhoenix I think that might be because you're building without CLANG_FORCE_LIBCPP, so the build system tries to use the system versions of glog/gflags and fails. I've pushed two commits that should fix both the gflags issue and add various includes that would be missing when building with libstdc++ rather than libc++.

CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
LBER_LIBRARIES (ADVANCED)
    linked by target "jit_sort" in directory /root/work/hhvm-oss/hphp/tools/hfsort
    linked by target "hfsort" in directory /root/work/hhvm-oss/hphp/tools/hfsort
    linked by target "hphp_runtime_static" in directory /root/work/hhvm-oss/hphp/runtime
    linked by target "hphp_runtime_ext" in directory /root/work/hhvm-oss/hphp/runtime/ext
    linked by target "hhvm" in directory /root/work/hhvm-oss/hphp/hhvm

-- Generating done (0.5s)
CMake Generate step failed.  Build files cannot be regenerated correctly.

Never, ever heared of LBER. Here's a filtered run, perhaps I am overlooking another error?

root@mobileboi ~/w/h/out (fix-oss-build-mirror) [1]# cmake . | grep NOT
-- Could NOT find PCRE (missing: SYSTEM_PCRE_LIBRARY SYSTEM_PCRE_INCLUDE_DIR)
-- Could NOT find FastLZ (missing: FASTLZ_LIBRARY FASTLZ_INCLUDE_DIR)
-- Could NOT find ONIGURUMA (missing: ONIGURUMA_LIBRARY ONIGURUMA_INCLUDE_DIR)
-- Could NOT find DOUBLE_CONVERSION (missing: DOUBLE_CONVERSION_LIBRARY DOUBLE_CONVERSION_INCLUDE_DIR)
-- Could NOT find Boost (missing: Boost_INCLUDE_DIR chrono context date_time fiber filesystem iostreams program_options regex system thread) (Required is at least version "1.69.0")
-- Could NOT find fmt (missing: fmt_DIR)
-- Could NOT find libsodium (missing: LIBSODIUM_LIBRARIES LIBSODIUM_INCLUDEDIR)
-- Could NOT find LIBIBERTY (missing: LIBIBERTY_LIBRARY LIBIBERTY_INCLUDE_DIR)
-- Could NOT find LibUnwind (missing: LibUnwind_DIR)
-- Could NOT find liboqs (missing: liboqs_DIR)
-- Could NOT find PCRE (missing: SYSTEM_PCRE_LIBRARY SYSTEM_PCRE_INCLUDE_DIR)
-- Could NOT find LIBZIP (missing: LIBZIP_LIBRARY LIBZIP_INCLUDE_DIR_ZIP LIBZIP_INCLUDE_DIR_ZIPCONF)
-- Could NOT find libWatchmanClient (missing: WATCHMANCLIENT_LIBRARIES WATCHMANCLIENT_INCLUDE_DIRS)
Not building the fribidi extension.
-- Could NOT find Freetype (missing: FREETYPE_LIBRARIES FREETYPE_INCLUDE_DIRS)
-- Could NOT find LibJpeg (missing: LIBJPEG_LIBRARIES LIBJPEG_INCLUDE_DIRS)
-- Could NOT find LibPng (missing: LIBPNG_LIBRARIES LIBPNG_INCLUDE_DIRS)
-- Could NOT find LibVPX (missing: LIBVPX_LIBRARIES LIBVPX_INCLUDE_DIRS)
-- Could NOT find Freetype (missing: FREETYPE_LIBRARIES FREETYPE_INCLUDE_DIRS)
-- Could NOT find LibJpeg (missing: LIBJPEG_LIBRARIES LIBJPEG_INCLUDE_DIRS)
-- Could NOT find LibPng (missing: LIBPNG_LIBRARIES LIBPNG_INCLUDE_DIRS)
-- Could NOT find LibVPX (missing: LIBVPX_LIBRARIES LIBVPX_INCLUDE_DIRS)
Not building the ldap extension.
Not building the mcrouter extension.
Not building the snappy extension.
-- Could NOT find PCRE (missing: SYSTEM_PCRE_LIBRARY SYSTEM_PCRE_INCLUDE_DIR)
-- Could NOT find FastLZ (missing: FASTLZ_LIBRARY FASTLZ_INCLUDE_DIR)
Generating Release build
-- Could NOT find PCRE (missing: SYSTEM_PCRE_LIBRARY SYSTEM_PCRE_INCLUDE_DIR)
-- Could NOT find FastLZ (missing: FASTLZ_LIBRARY FASTLZ_INCLUDE_DIR)
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
LBER_LIBRARIES (ADVANCED)
    linked by target "jit_sort" in directory /root/work/hhvm-oss/hphp/tools/hfsort
    linked by target "hfsort" in directory /root/work/hhvm-oss/hphp/tools/hfsort
    linked by target "hphp_runtime_static" in directory /root/work/hhvm-oss/hphp/runtime
    linked by target "hphp_runtime_ext" in directory /root/work/hhvm-oss/hphp/runtime/ext
    linked by target "hhvm" in directory /root/work/hhvm-oss/hphp/hhvm

CMake Generate step failed.  Build files cannot be regenerated correctly.

Note that if you do choose to use CLANG_FORCE_LIBCPP(...)

I honestly am not sure if all the extra hassle you describe is "worth it" x). This flag might be useful in certain environments - but luckily, not in mine. Besides, if a couple other projects have tickets open, might as well let them do their stuff for now and this part will effectively work itself out eventually?
What I mean to say is, nah, no need to spend time trying to make this bit work :)

@mszabo-wikia
Copy link
Owner Author

mszabo-wikia commented Oct 11, 2025

LBER comes from libldap, so the equivalent of libldap2-dev on alpine (probably libldap?). It seems you might be missing some other package dependencies too from the second log.

Yeah ideally CLANG_FORCE_LIBCPP will go away once the few incompatibilities with libstdc++ are resolved.

@IngwiePhoenix
Copy link

Wanna like... facedesk real good? apk add libldap openldap-dev. Yep, it was not in fact libldap-dev as one would expect - and yes, that is also v2. Oh well...only took me way too long lol.

I had to switch from Ninja to Make, because of "bad $-expression". Not a big deal, but here is the error if you are curious:

CMake Error:
  Running

   '/usr/bin/ninja' '-C' '/root/work/hhvm-oss/out' '-t' 'recompact'

  failed with:

   ninja: error: build.ninja:1491: bad $-escape (literal $ must be written as $$)
`` 

But... I have Makefiles now! So I'll `make -j$(nproc)` and see where it stops.

@mszabo-wikia
Copy link
Owner Author

Wanna like... facedesk real good? apk add libldap openldap-dev. Yep, it was not in fact libldap-dev as one would expect - and yes, that is also v2. Oh well...only took me way too long lol.

I had to switch from Ninja to Make, because of "bad $-expression". Not a big deal, but here is the error if you are curious:

CMake Error:
  Running

   '/usr/bin/ninja' '-C' '/root/work/hhvm-oss/out' '-t' 'recompact'

  failed with:

   ninja: error: build.ninja:1491: bad $-escape (literal $ must be written as $$)
`` 

But... I have Makefiles now! So I'll `make -j$(nproc)` and see where it stops.

Yeah, even if that was fixed using Ninja would be problematic, because it has no job server, so it would overload the system while building the ExternalProjects under third-party/ as each subproject would try to utilize all cores. Better to stick with Unix Makefiles as the generator.

@IngwiePhoenix
Copy link

root@mobileboi ~/w/h/out (fix-oss-build-mirror)# make VERBOSE=1
/usr/bin/cmake -S/root/work/hhvm-oss -B/root/work/hhvm-oss/out --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /root/work/hhvm-oss/out/CMakeFiles /root/work/hhvm-oss/out//CMakeFiles/progress.marks
make  -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/root/work/hhvm-oss/out'
make  -f third-party/double-conversion/CMakeFiles/bundled_double-conversion.dir/build.make third-party/double-conversion/CMakeFiles/bundled_double-conversion.dir/depend
make[2]: Entering directory '/root/work/hhvm-oss/out'
cd /root/work/hhvm-oss/out && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /root/work/hhvm-oss /root/work/hhvm-oss/third-party/double-conversion /root/work/hhvm-oss/out /root/work/hhvm-oss/out/third-party/double-conversion /root/work/hhvm-oss/out/third-party/double-conversion/CMakeFiles/bundled_double-conversion.dir/DependInfo.cmake "--color="
make[2]: Leaving directory '/root/work/hhvm-oss/out'
make  -f third-party/double-conversion/CMakeFiles/bundled_double-conversion.dir/build.make third-party/double-conversion/CMakeFiles/bundled_double-conversion.dir/build
make[2]: Entering directory '/root/work/hhvm-oss/out'
make[2]: Nothing to be done for 'third-party/double-conversion/CMakeFiles/bundled_double-conversion.dir/build'.
make[2]: Leaving directory '/root/work/hhvm-oss/out'
[  1%] Built target bundled_double-conversion
make  -f third-party/rustc/CMakeFiles/bundled_rust.dir/build.make third-party/rustc/CMakeFiles/bundled_rust.dir/depend
make[2]: Entering directory '/root/work/hhvm-oss/out'
cd /root/work/hhvm-oss/out && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /root/work/hhvm-oss /root/work/hhvm-oss/third-party/rustc /root/work/hhvm-oss/out /root/work/hhvm-oss/out/third-party/rustc /root/work/hhvm-oss/out/third-party/rustc/CMakeFiles/bundled_rust.dir/DependInfo.cmake "--color="
make[2]: Leaving directory '/root/work/hhvm-oss/out'
make  -f third-party/rustc/CMakeFiles/bundled_rust.dir/build.make third-party/rustc/CMakeFiles/bundled_rust.dir/build
make[2]: Entering directory '/root/work/hhvm-oss/out'
make[2]: Nothing to be done for 'third-party/rustc/CMakeFiles/bundled_rust.dir/build'.
make[2]: Leaving directory '/root/work/hhvm-oss/out'
[  1%] Built target bundled_rust
make  -f hphp/util/CMakeFiles/hhvm_render_config_section_defs.dir/build.make hphp/util/CMakeFiles/hhvm_render_config_section_defs.dir/depend
make[2]: Entering directory '/root/work/hhvm-oss/out'
cd /root/work/hhvm-oss/out && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /root/work/hhvm-oss /root/work/hhvm-oss/hphp/util /root/work/hhvm-oss/out /root/work/hhvm-oss/out/hphp/util /root/work/hhvm-oss/out/hphp/util/CMakeFiles/hhvm_render_config_section_defs.dir/DependInfo.cmake "--color="
make[2]: Leaving directory '/root/work/hhvm-oss/out'
make  -f hphp/util/CMakeFiles/hhvm_render_config_section_defs.dir/build.make hphp/util/CMakeFiles/hhvm_render_config_section_defs.dir/build
make[2]: Entering directory '/root/work/hhvm-oss/out'
[  1%] Generating configs/adminserver.cpp, configs/autoload.cpp, configs/codecache.cpp, configs/configerator.cpp, configs/debug.cpp, configs/debugger.cpp, configs/errorhandling.cpp, configs/eval.cpp, configs/gc.cpp, configs/hacklang.cpp, configs/hhir.cpp, configs/http.cpp, configs/jit.cpp, configs/log.cpp, configs/mail.cpp, configs/pageletserver.cpp, configs/pcre.cpp, configs/php7.cpp, configs/proxy.cpp, configs/repo.cpp, configs/sandbox.cpp, configs/server.cpp, configs/setprofile.cpp, configs/simplexml.cpp, configs/stats.cpp, configs/strobelight.cpp, configs/watchman.cpp, configs/xbox.cpp, configs/xenon.cpp, configs/adminserver.h, configs/autoload.h, configs/codecache.h, configs/configerator.h, configs/debug.h, configs/debugger.h, configs/errorhandling.h, configs/eval.h, configs/gc.h, configs/hacklang.h, configs/hhir.h, configs/http.h, configs/jit.h, configs/log.h, configs/mail.h, configs/pageletserver.h, configs/pcre.h, configs/php7.h, configs/proxy.h, configs/repo.h, configs/sandbox.h, configs/server.h, configs/setprofile.h, configs/simplexml.h, configs/stats.h, configs/strobelight.h, configs/watchman.h, configs/xbox.h, configs/xenon.h
cd /root/work/hhvm-oss/hphp/tools/configs && /usr/bin/cmake -E make_directory /root/work/hhvm-oss/out/hphp/util/configs
cd /root/work/hhvm-oss/hphp/tools/configs && /usr/bin/cmake -E env RUSTC=/root/work/hhvm-oss/out/third-party/rustc/bundled_rust-prefix/bin/rustc CARGO_HOME=/root/work/hhvm-oss/out/hphp/tools/configs/.cargo /root/work/hhvm-oss/out/third-party/rustc/bundled_rust-prefix/bin/cargo run --quiet -- defs /root/work/hhvm-oss/out/hphp/util/configs /root/work/hhvm-oss/hphp/doc/configs.specification
exec format error
make[2]: *** [hphp/util/CMakeFiles/hhvm_render_config_section_defs.dir/build.make:133: hphp/util/configs/adminserver.cpp] Error 1
make[2]: Leaving directory '/root/work/hhvm-oss/out'
make[1]: *** [CMakeFiles/Makefile2:3401: hphp/util/CMakeFiles/hhvm_render_config_section_defs.dir/all] Error 2
make[1]: Leaving directory '/root/work/hhvm-oss/out'
make: *** [Makefile:136: all] Error 2

It downloaded/installed the wrong architecture. o.o I'll wipe and just install one via APK.

@mszabo-wikia
Copy link
Owner Author

@IngwiePhoenix yup the bundled rustc listfile needs an update to support arm, but you can also grab the September 1st nightly from rustup and pass in -DRUSTC_EXECUTABLE=... -DCARGO_EXECUTABLE... to the build to use those instead of the bundled one

@IngwiePhoenix
Copy link

Alright - had to set RUST/CARGO_EXECUTABLE and that was that.

This is as far as I got so far:

[  0%] Building CXX object CMakeFiles/folly_base.dir/folly/CancellationToken.cpp.o
/usr/bin/c++ -DFOLLY_XLOG_STRIP_PREFIXES=\"/root/work/hhvm-oss/third-party/folly/src:/root/work/hhvm-oss/out/third-party/folly/bundled_folly-prefix/src/bundled_folly-build\" -DGFLAGS_IS_A_DLL=0 -D_GNU_SOURCE -D_REENTRANT -I/root/work/hhvm-oss/third-party/folly/src -I/root/work/hhvm-oss/out/third-party/folly/bundled_folly-prefix/src/bundled_folly-build -I/root/work/hhvm-oss/out/third-party/boost/bundled_boost-prefix/include -I/root/work/hhvm-oss/out/third-party/double-conversion/bundled_double-conversion-prefix/include -I/root/work/hhvm-oss/third-party/fast_float -I/root/work/hhvm-oss/out/third-party/zstd/bundled_zstd-prefix/include -I/usr/include/libdwarf-0 -I/root/work/hhvm-oss/out/third-party/fmt/bundled_fmt-prefix/include -Wno-error=array-bounds -Wno-error=switch -Wno-attributes -Wno-deprecated -Wno-invalid-offsetof -Wno-register -Wno-sign-compare -Wno-strict-aliasing -Wno-unused-function -Wno-unused-local-typedefs -Wno-unused-result -Wno-write-strings -Wno-deprecated-declarations -Wno-maybe-uninitialized -Wno-bool-compare -no-pie -ffunction-sections -fno-delete-null-pointer-checks -DFOLLY_HAVE_MALLOC_H -fsigned-char -std=gnu++1z -fno-omit-frame-pointer -Wall -Werror=format-security -Wno-unused-variable -Wno-unused-value -Wno-comment -Wno-class-memaccess -Wno-adress -Wno-error=stringop-overflow -march=armv8.2-a -fdata-sections -fno-gcse -fno-canonical-system-headers -Wvla -Wno-misleading-indentation -I/root/work/hhvm-oss/out/third-party/jemalloc/bundled_jemalloc-prefix/include -I/root/work/hhvm-oss/third-party/folly/include -O3 -DNDEBUG -g -Wall -Wextra -O3 -std=gnu++20 -fcoroutines -g -finput-charset=UTF-8 -fsigned-char -Wall -Wno-deprecated -Wno-deprecated-declarations -Wno-sign-compare -Wno-unused -Wuninitialized -Wunused-label -Wunused-result -Wno-psabi -Wshadow-compatible-local -Wno-noexcept-type -faligned-new -fopenmp -MD -MT CMakeFiles/folly_base.dir/folly/CancellationToken.cpp.o -MF CMakeFiles/folly_base.dir/folly/CancellationToken.cpp.o.d -o CMakeFiles/folly_base.dir/folly/CancellationToken.cpp.o -c /root/work/hhvm-oss/third-party/folly/src/folly/CancellationToken.cpp
In file included from /root/work/hhvm-oss/third-party/folly/src/folly/CancellationToken-inl.h:24,
                 from /root/work/hhvm-oss/third-party/folly/src/folly/CancellationToken.h:370,
                 from /root/work/hhvm-oss/third-party/folly/src/folly/CancellationToken.cpp:17:
/usr/include/glog/logging.h:60:4: error: #error <glog/logging.h> was not included correctly. See the documentation for how to consume the library.
   60 | #  error <glog/logging.h> was not included correctly. See the documentation for how to consume the library.
      |    ^~~~~

(Saw the error and then did make -j1 VERBOSE=1 to see whats up.)

Thoughts?

@IngwiePhoenix
Copy link

Also here's the bottom of the absurd onslaught of errors (good thing my terminal buffer is high xD)

cc1plus: note: unrecognized command-line option '-Wno-adress' may have been intended to silence earlier diagnostics
make[6]: *** [CMakeFiles/folly_base.dir/build.make:79: CMakeFiles/folly_base.dir/folly/CancellationToken.cpp.o] Error 1
make[6]: Leaving directory '/root/work/hhvm-oss/out/third-party/folly/bundled_folly-prefix/src/bundled_folly-build'
make[5]: *** [CMakeFiles/Makefile2:169: CMakeFiles/folly_base.dir/all] Error 2
make[5]: Leaving directory '/root/work/hhvm-oss/out/third-party/folly/bundled_folly-prefix/src/bundled_folly-build'
make[4]: *** [CMakeFiles/Makefile2:208: CMakeFiles/folly.dir/rule] Error 2
make[4]: Leaving directory '/root/work/hhvm-oss/out/third-party/folly/bundled_folly-prefix/src/bundled_folly-build'
make[3]: *** [Makefile:182: folly] Error 2
make[3]: Leaving directory '/root/work/hhvm-oss/out/third-party/folly/bundled_folly-prefix/src/bundled_folly-build'
make[2]: *** [third-party/folly/CMakeFiles/bundled_folly.dir/build.make:86: third-party/folly/bundled_folly-prefix/src/bundled_folly-stamp/bundled_folly-build] Error 2
make[2]: Leaving directory '/root/work/hhvm-oss/out'
make[1]: *** [CMakeFiles/Makefile2:1508: third-party/folly/CMakeFiles/bundled_folly.dir/all] Error 2
make[1]: Leaving directory '/root/work/hhvm-oss/out'
make: *** [Makefile:136: all] Error 2

I spot a cute typo: adress -> address. x)

@mszabo-wikia
Copy link
Owner Author

Hmm that looks like a glog >= 0.7 incompatibility (facebook/folly#2171). Probably both third-party/glog and folly will need to do what the AUR patch there is mentioning and look for the CMake config file of glog first before using the find module. I guess I didn't run into this because none of the systems that I was building on packaged glog newer than 0.6.0.

@IngwiePhoenix
Copy link

Notfixed it with CMAKE_(C/CXX)_FLAGS=-DGLOG_USE_GLOG_EXPORT for the time being.

And, this is where I am now:

[  9%] Building CXX object CMakeFiles/folly_base.dir/folly/memcpy_select_aarch64.cpp.o
/usr/bin/c++ -DFOLLY_XLOG_STRIP_PREFIXES=\"/root/work/hhvm-oss/third-party/folly/src:/root/work/hhvm-oss/out/third-party/folly/bundled_folly-prefix/src/bundled_folly-build\" -DGFLAGS_IS_A_DLL=0 -D_GNU_SOURCE -D_REENTRANT -I/root/work/hhvm-oss/third-party/folly/src -I/root/work/hhvm-oss/out/third-party/folly/bundled_folly-prefix/src/bundled_folly-build -I/root/work/hhvm-oss/out/third-party/boost/bundled_boost-prefix/include -I/root/work/hhvm-oss/out/third-party/double-conversion/bundled_double-conversion-prefix/include -I/root/work/hhvm-oss/third-party/fast_float -I/root/work/hhvm-oss/out/third-party/zstd/bundled_zstd-prefix/include -I/usr/include/libdwarf-0 -I/root/work/hhvm-oss/out/third-party/fmt/bundled_fmt-prefix/include -DGLOG_USE_GLOG_EXPORT -Wno-error=array-bounds -Wno-error=switch -Wno-attributes -Wno-deprecated -Wno-invalid-offsetof -Wno-register -Wno-sign-compare -Wno-strict-aliasing -Wno-unused-function -Wno-unused-local-typedefs -Wno-unused-result -Wno-write-strings -Wno-deprecated-declarations -Wno-maybe-uninitialized -Wno-bool-compare -no-pie -ffunction-sections -fno-delete-null-pointer-checks -DFOLLY_HAVE_MALLOC_H -fsigned-char -std=gnu++1z -fno-omit-frame-pointer -Wall -Werror=format-security -Wno-unused-variable -Wno-unused-value -Wno-comment -Wno-class-memaccess -Wno-adress -Wno-error=stringop-overflow -march=armv8.2-a -fdata-sections -fno-gcse -fno-canonical-system-headers -Wvla -Wno-misleading-indentation -I/root/work/hhvm-oss/out/third-party/jemalloc/bundled_jemalloc-prefix/include -I/root/work/hhvm-oss/third-party/folly/include -O3 -DNDEBUG -g -Wall -Wextra -O3 -std=gnu++20 -fcoroutines -g -finput-charset=UTF-8 -fsigned-char -Wall -Wno-deprecated -Wno-deprecated-declarations -Wno-sign-compare -Wno-unused -Wuninitialized -Wunused-label -Wunused-result -Wno-psabi -Wshadow-compatible-local -Wno-noexcept-type -faligned-new -fopenmp -MD -MT CMakeFiles/folly_base.dir/folly/memcpy_select_aarch64.cpp.o -MF CMakeFiles/folly_base.dir/folly/memcpy_select_aarch64.cpp.o.d -o CMakeFiles/folly_base.dir/folly/memcpy_select_aarch64.cpp.o -c /root/work/hhvm-oss/third-party/folly/src/folly/memcpy_select_aarch64.cpp
/root/work/hhvm-oss/third-party/folly/src/folly/memcpy_select_aarch64.cpp:126:7: error: 'ifunc' is not supported on this target
  126 | void* __folly_memcpy(void* dst, const void* src, std::size_t size);
      |       ^~~~~~~~~~~~~~
/root/work/hhvm-oss/third-party/folly/src/folly/memcpy_select_aarch64.cpp:129:7: error: 'ifunc' is not supported on this target
  129 | void* __folly_memmove(void* dst, const void* src, std::size_t size);
      |       ^~~~~~~~~~~~~~~
cc1plus: note: unrecognized command-line option '-Wno-adress' may have been intended to silence earlier diagnostics
make[6]: *** [CMakeFiles/folly_base.dir/build.make:527: CMakeFiles/folly_base.dir/folly/memcpy_select_aarch64.cpp.o] Error 1
make[6]: Leaving directory '/root/work/hhvm-oss/out/third-party/folly/bundled_folly-prefix/src/bundled_folly-build'
make[5]: *** [CMakeFiles/Makefile2:169: CMakeFiles/folly_base.dir/all] Error 2
make[5]: Leaving directory '/root/work/hhvm-oss/out/third-party/folly/bundled_folly-prefix/src/bundled_folly-build'
make[4]: *** [CMakeFiles/Makefile2:208: CMakeFiles/folly.dir/rule] Error 2
make[4]: Leaving directory '/root/work/hhvm-oss/out/third-party/folly/bundled_folly-prefix/src/bundled_folly-build'
make[3]: *** [Makefile:182: folly] Error 2
make[3]: Leaving directory '/root/work/hhvm-oss/out/third-party/folly/bundled_folly-prefix/src/bundled_folly-build'
make[2]: *** [third-party/folly/CMakeFiles/bundled_folly.dir/build.make:86: third-party/folly/bundled_folly-prefix/src/bundled_folly-stamp/bundled_folly-build] Error 2
make[2]: Leaving directory '/root/work/hhvm-oss/out'
make[1]: *** [CMakeFiles/Makefile2:1508: third-party/folly/CMakeFiles/bundled_folly.dir/all] Error 2
make[1]: Leaving directory '/root/work/hhvm-oss/out'
make: *** [Makefile:136: all] Error 2

Time to find out what exactly ifunc is. o.o...

@IngwiePhoenix
Copy link

Oh, speaking of versions:

# apk list -I | grep -E "glog|gflags"
gflags-2.2.2-r2 aarch64 {gflags} (BSD-3-Clause) [installed]
gflags-dev-2.2.2-r2 aarch64 {gflags} (BSD-3-Clause) [installed]
glog-0.7.1-r2 aarch64 {glog} (BSD-3-Clause) [installed]
glog-dev-0.7.1-r2 aarch64 {glog} (BSD-3-Clause) [installed]

@IngwiePhoenix
Copy link

Ohhhh so, ifunc is a GCC extension that works on Clang - and is basically a GlibC thing. Well, I use musl. Gonna figure something out. :)

@IngwiePhoenix
Copy link

Welp, I'll work out a different build system (probably an Incus container for the time being).

Meanwhile, that's certainly something that should go somewhere in the docs - that glibc is basically a hard-requirement. o.o

@IngwiePhoenix
Copy link

Stood up Debian 13 in an Incus container, mounted my host rootfs into it and then went installing stuff.

Here is where it's currently stuck:

[  0%] Building CXX object CMakeFiles/folly_base.dir/folly/net/NetOps.cpp.o
/usr/bin/c++ -DFOLLY_XLOG_STRIP_PREFIXES=\"/host/root/work/hhvm-oss/third-party/folly/src:/host/root/work/hhvm-oss/out2/third-party/folly/bundled_folly-prefix/src/bundled_folly-build\" -DGFLAGS_IS_A_DLL=0 -D_GNU_SOURCE -D_REENTRANT -I/host/root/work/hhvm-oss/third-party/folly/src -I/host/root/work/hhvm-oss/out2/third-party/folly/bundled_folly-prefix/src/bundled_folly-build -I/host/root/work/hhvm-oss/out2/third-party/double-conversion/bundled_double-conversion-prefix/include -I/host/root/work/hhvm-oss/third-party/fast_float -I/host/root/work/hhvm-oss/out2/third-party/zstd/bundled_zstd-prefix/include -I/usr/include/libdwarf -I/usr/include/libiberty -I/host/root/work/hhvm-oss/out2/third-party/fmt/bundled_fmt-prefix/include -Wno-error=array-bounds -Wno-error=switch -Wno-attributes -Wno-deprecated -Wno-invalid-offsetof -Wno-register -Wno-sign-compare -Wno-strict-aliasing -Wno-unused-function -Wno-unused-local-typedefs -Wno-unused-result -Wno-write-strings -Wno-deprecated-declarations -Wno-maybe-uninitialized -Wno-bool-compare -no-pie -ffunction-sections -fno-delete-null-pointer-checks -DFOLLY_HAVE_MALLOC_H -fsigned-char -std=gnu++1z -fno-omit-frame-pointer -Wall -Werror=format-security -Wno-unused-variable -Wno-unused-value -Wno-comment -Wno-class-memaccess -Wno-adress -Wno-error=stringop-overflow -march=armv8.2-a -fdata-sections -fno-gcse -fno-canonical-system-headers -Wvla -Wno-misleading-indentation -I/usr/include -I/host/root/work/hhvm-oss/third-party/folly/include -O3 -DNDEBUG -g -Wall -Wextra -O3 -std=gnu++20 -fcoroutines -g -finput-charset=UTF-8 -fsigned-char -Wall -Wno-deprecated -Wno-deprecated-declarations -Wno-sign-compare -Wno-unused -Wuninitialized -Wunused-label -Wunused-result -Wno-psabi -Wshadow-compatible-local -Wno-noexcept-type -faligned-new -fopenmp -MD -MT CMakeFiles/folly_base.dir/folly/net/NetOps.cpp.o -MF CMakeFiles/folly_base.dir/folly/net/NetOps.cpp.o.d -o CMakeFiles/folly_base.dir/folly/net/NetOps.cpp.o -c /host/root/work/hhvm-oss/third-party/folly/src/folly/net/NetOps.cpp
/host/root/work/hhvm-oss/third-party/folly/src/folly/net/NetOps.cpp:41:29: error: non-constant condition for static assertion
   41 | static_assert(folly::to_bool(::recvmmsg));
      |               ~~~~~~~~~~~~~~^~~~~~~~~~~~
In file included from /host/root/work/hhvm-oss/third-party/folly/src/folly/ScopeGuard.h:86,
                 from /host/root/work/hhvm-oss/third-party/folly/src/folly/net/NetOps.cpp:30:
/host/root/work/hhvm-oss/third-party/folly/src/folly/Utility.h:537:12: error: ‘(recvmmsg != 0)’ is not a constant expression
  537 |     return static_cast<bool>(t);
      |            ^~~~~~~~~~~~~~~~~~~~
/host/root/work/hhvm-oss/third-party/folly/src/folly/net/NetOps.cpp:42:29: error: non-constant condition for static assertion
   42 | static_assert(folly::to_bool(::sendmmsg));
      |               ~~~~~~~~~~~~~~^~~~~~~~~~~~
/host/root/work/hhvm-oss/third-party/folly/src/folly/Utility.h:537:12: error: ‘(sendmmsg != 0)’ is not a constant expression
  537 |     return static_cast<bool>(t);
      |            ^~~~~~~~~~~~~~~~~~~~
cc1plus: note: unrecognized command-line option ‘-Wno-adress’ may have been intended to silence earlier diagnostics
make[6]: *** [CMakeFiles/folly_base.dir/build.make:3859: CMakeFiles/folly_base.dir/folly/net/NetOps.cpp.o] Error 1
make[6]: Leaving directory '/host/root/work/hhvm-oss/out2/third-party/folly/bundled_folly-prefix/src/bundled_folly-build'
make[5]: *** [CMakeFiles/Makefile2:169: CMakeFiles/folly_base.dir/all] Error 2
make[5]: Leaving directory '/host/root/work/hhvm-oss/out2/third-party/folly/bundled_folly-prefix/src/bundled_folly-build'
make[4]: *** [CMakeFiles/Makefile2:208: CMakeFiles/folly.dir/rule] Error 2
make[4]: Leaving directory '/host/root/work/hhvm-oss/out2/third-party/folly/bundled_folly-prefix/src/bundled_folly-build'
make[3]: *** [Makefile:182: folly] Error 2
make[3]: Leaving directory '/host/root/work/hhvm-oss/out2/third-party/folly/bundled_folly-prefix/src/bundled_folly-build'
make[2]: *** [third-party/folly/CMakeFiles/bundled_folly.dir/build.make:86: third-party/folly/bundled_folly-prefix/src/bundled_folly-stamp/bundled_folly-build] Error 2
make[2]: Leaving directory '/host/root/work/hhvm-oss/out2'
make[1]: *** [CMakeFiles/Makefile2:1442: third-party/folly/CMakeFiles/bundled_folly.dir/all] Error 2
make[1]: Leaving directory '/host/root/work/hhvm-oss/out2'
make: *** [Makefile:136: all] Error 2

And here is all the packages I installed:

aspcud
autoconf
automake
binutils-dev
bison
build-essential
cmake
curl
debhelper
(>=
9)
flex
g++
gawk
git
gperf
libboost-all-dev
libbz2-dev
libc-client-dev
libc-client2007e-dev
libcap-dev
libcurl4-openssl-dev
libdwarf-dev
libedit-dev
libelf-dev
libevent-dev
libexpat-dev
libgd-dev
libgmp3-dev
libgoogle-glog-dev
libgoogle-perftools-dev
libiberty-dev
libiconv-hook-dev
libicu-dev
libinotifytools0-dev
libjemalloc-dev
libkrb5-dev
libldap2-dev
libmagickwand-dev
libmcrypt-dev
libmemcached-dev
libncurses-dev
libnotify-dev
libnuma-dev
libonig-dev
libpcre3-dev
libpq-dev
libre2-dev
libsodium-dev
libsqlite3-dev
libssl-dev
libtbb-dev
libtool
libxml2-dev
libxslt1-dev
libyaml-dev
python3
re2c
rsync
tzdata
unzip
wget
zlib1g-dev

# Those came up as I tried to configure:
libxxhash-dev libxxhash0
liblmdb0 liblmdb-dev
cargo rustc

@mszabo-wikia
Copy link
Owner Author

Was this with GCC or clang? What options did you pass to CMake?

@IngwiePhoenix
Copy link

CMake selected GCC:

root@hhvm:/host/root/work/hhvm-oss/out2# cat CMakeCache.txt |grep "CMAKE_C_COMPILER:"
CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc
root@hhvm:/host/root/work/hhvm-oss/out2# /usr/bin/cc --version
cc (Debian 14.2.0-19) 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

As for options, only the RUSTC/CARGO_EXECUTABLE ones. I didn't even add the previous CMAKE_C/CXX_FLAGS one for glog - because I forgot, but it seems to have ... just worked?

root@hhvm:/host/root/work/hhvm-oss/out2# cat ~/.bash_history |grep cmake
apt install build-essential make cmake git curl
cmake ..
cmake .
cmake . -DMYSQL_UNIX_SOCK_ADDR=/path/to/mysql.socket -Wno-dev
cmake .
cmake . -DRUSTC_EXECUTABLE=$(which rustc) -DCARGO_EXECUTABLE=$(which cargo)

@mszabo-wikia
Copy link
Owner Author

Yeah, Debian Trixie packages glog 0.6.0 so it doesn't require that added definition / use of the CMake config file.

Can you try with -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++. I was able to reproduce your error on Debian when compiling with -DCMAKE_CXX_COMPILER=clang++ without also setting CMAKE_C_COMPILER, so it could be an issue with GCC on Debian.

@IngwiePhoenix
Copy link

root@hhvm:/host/root/work/hhvm-oss/out2# cat CMakeCache.txt |grep "CMAKE_C_COMPILER:"
CMAKE_C_COMPILER:STRING=/usr/bin/clang
root@hhvm:/host/root/work/hhvm-oss/out2# cat CMakeCache.txt |grep "CMAKE_CXX_COMPILER:"
CMAKE_CXX_COMPILER:STRING=/usr/bin/clang++

And after some time...

<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><>
⬇ retrieved pcre.7.5.0  (cached)
[ERROR] The compilation of conf-libpcre.2 failed at "pkg-config --print-errors --exists libpcre".

#=== ERROR while compiling conf-libpcre.2 =====================================#
# context     2.1.0 | linux/arm64 | ocaml-variants.5.2.0+options | https://opam.ocaml.org#1abfcdbf14f12a32c14d0d6e078d94634fdcc07a
# path        /host/root/work/hhvm-oss/out2/hphp/hack/opam/hack-switch/.opam-switch/build/conf-libpcre.2
# command     /usr/bin/pkg-config --print-errors --exists libpcre
# exit-code   1
# env-file    /host/root/work/hhvm-oss/out2/hphp/hack/opam/log/conf-libpcre-74493-a67be6.env
# output-file /host/root/work/hhvm-oss/out2/hphp/hack/opam/log/conf-libpcre-74493-a67be6.out
### output ###
# Package libpcre was not found in the pkg-config search path.
# Perhaps you should add the directory containing `libpcre.pc'
# to the PKG_CONFIG_PATH environment variable
# Package 'libpcre', required by 'virtual:world', not found



<><> Error report <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
┌─ The following actions failed
│ λ build conf-libpcre 2
└─
╶─ No changes have been performed
make[2]: *** [hphp/hack/CMakeFiles/opam_setup.dir/build.make:75: hphp/hack/opam.stamp] Error 31
make[1]: *** [CMakeFiles/Makefile2:2417: hphp/hack/CMakeFiles/opam_setup.dir/all] Error 2

Apply anyway? [n] y
Hunk #1 FAILED at 22.
1 out of 1 hunk FAILED -- saving rejects to file build/linux.gcc.inc.rej
make[2]: *** [third-party/tbb/CMakeFiles/bundled_tbb.dir/build.make:114: third-party/tbb/bundled_tbb-prefix/src/bundled_tbb-stamp/bundled_tbb-patch] Error 1
make[1]: *** [CMakeFiles/Makefile2:2099: third-party/tbb/CMakeFiles/bundled_tbb.dir/all] Error 2
make: *** [Makefile:136: all] Error 2

I looked out for what package I could install, but all I see is libpcre2 - not the "non-2" version that ocaml tries to look up with pkg-config.

root@hhvm:/host/root/work/hhvm-oss/out2# apt-cache search libpcre | sort
libpcre2-16-0 - New Perl Compatible Regular Expression Library - 16 bit runtime files
libpcre2-32-0 - New Perl Compatible Regular Expression Library - 32 bit runtime files
libpcre2-8-0 - New Perl Compatible Regular Expression Library- 8 bit runtime files
libpcre2-dev - New Perl Compatible Regular Expression Library - development files
libpcre2-ocaml - OCaml bindings for PCRE2 (runtime)
libpcre2-ocaml-dev - OCaml bindings for PCRE2 (Perl Compatible Regular Expression)
libpcre2-posix3 - New Perl Compatible Regular Expression Library - posix-compatible runtime files
libvectorscan5 - Portable fork of Intel's Hyperscan library
pcre2-utils - New Perl Compatible Regular Expression Library - utilities

@mszabo-wikia
Copy link
Owner Author

Looks like bookworm was the last version of Debian to include pcre < v2: https://packages.debian.org/bookworm/libpcre3-dev.

Probably the typechecker needs migrating to https://opam.ocaml.org/packages/pcre2/; until then you could try building libpcre from source or build on bookworm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants