[MacPorts] #74309: macfuse: new PortGroup for FUSE3 support, avoid misresolving fuse.h to FUSE2 API

MacPorts noreply at macports.org
Mon Aug 10 05:22:46 UTC 2026


#74309: macfuse: new PortGroup for FUSE3 support, avoid misresolving fuse.h to
FUSE2 API
------------------------------------------------+------------------------
 Reporter:  trodemaster                         |      Owner:  mohd-akram
     Type:  enhancement                         |     Status:  assigned
 Priority:  Normal                              |  Milestone:
Component:  ports                               |    Version:
 Keywords:  fuse fuse3 macfuse meson portgroup  |       Port:  macfuse
------------------------------------------------+------------------------
 Hey, I have been trying to sort out some issues with ports that depend on
 macfuse and bumped into this issue. Here is one option I generated to
 address the issue with assistance from Claude. If this seems viable, I can
 refine it into a PR, and if not, I can just stick to per port workaround.
 Seems like it would be nice to make a break from the pre-macfuse versions
 of fuse and move on from there.

 == Problem ==

 macFUSE ships two userspace API generations side by side under the same
 MacPorts prefix: a legacy FUSE 2.x-compatible `fuse.h` (a shim, per its
 own header comment: `"This header is for compatibility with older
 software using FUSE. Please use 'pkg-config --cflags fuse' to set
 include path."`) and the modern FUSE 3.x API at `fuse3/fuse.h`. Both are
 genuinely part of upstream macFUSE's own package layout, per the project
 wiki: *"macFUSE ships with patched versions of libfuse 2 and
 libfuse 3."* [https://github.com/macfuse/macfuse/wiki/FUSE-User-Space-
 Libraries]

 MacPorts' `macfuse` port installs both into the single shared
 `${prefix}/include`. Because MacPorts base unconditionally adds
 `-I${prefix}/include` to every build (so any port's headers are
 findable without per-dependency wiring), a consumer that writes a bare
 `#include <fuse.h>`, instead of the fully-qualified `#include
 <fuse3/fuse.h>`, silently resolves to the **FUSE 2.x** struct layout
 even when it links against `libfuse3` and intends to use the FUSE 3
 API. This is not usually a build failure at all. It's a silent ABI
 mismatch: function pointers get assigned with the old 2.x signatures
 (e.g. `chmod(path, mode)` instead of `chmod(path, mode, fuse_file_info
 *)`), which the compiler correctly flags as
 `-Wincompatible-function-pointer-types`, but which several ports
 currently silence rather than fix. This is specific to
 MacPorts' shared-prefix convention; it doesn't reproduce on Homebrew or
 a native `/usr/local` install, since neither of those blanket-inject the
 parent include dir the way MacPorts does.

 This is easy to miss because the *actual* build failure, when it does
 surface, points nowhere near the real cause. It shows up as e.g.:

 {{{
 In file included from fuse2fs.c:29:
 In file included from /opt/local/include/fuse.h:9:
 In file included from /opt/local/include/fuse/fuse.h:31:
 /opt/local/include/fuse/fuse_common.h:52:2: error: Please add
 -D_FILE_OFFSET_BITS=64 to your compile flags!
 }}}

 == Root cause in the existing `fuse` PortGroup ==

 `_resources/port1.0/group/fuse-1.0.tcl`'s modern branch (macfuse4 /
 macfuse, i.e. `os.major >= 16`) still targets the **FUSE 2.x**
 pkg-config identity and include directory, not FUSE 3:

 {{{
 } else {
     set fuse_port "macfuse"
     set fuse_path "lib/pkgconfig/fuse.pc"
     if {${os.platform} eq "darwin" && ${os.major} < 21} {
         set fuse_port "macfuse4"
     }
     configure.cflags-append -I${prefix}/include/fuse
     configure.cppflags-append -I${prefix}/include/fuse
 }
 }}}

 `fuse.pc` and `include/fuse` are the FUSE 2.x pkg-config file and
 include dir. The group was written for osxfuse (FUSE2-only), and this
 branch was never updated when macfuse4/macfuse (FUSE3-capable) support
 was added; it still wires consumers to the legacy API surface even
 though modern macfuse's headline capability is FUSE3.

 == Proposed fix: a new `macfuse` PortGroup ==

 Rather than rev the existing `fuse` group in place, I'd propose a new,
 separate group. `fuse-1.0` is generically named for a real reason: it
 genuinely dispatches between three vendored implementations (osxfuse,
 macfuse4, macfuse) depending on macOS version. A FUSE3-only group
 wouldn't do any of that dispatching. No other FUSE3-capable
 implementation is currently packaged in MacPorts (fuse-t exists as a
 project but isn't in the tree), so it would just be a fixed dependency
 on the `macfuse` port. Naming it for what it actually depends on,
 rather than the API version (which explains why the group exists, not
 what it targets), better reflects its current scope, and matches the
 precedent of narrowly-scoped, literally-named groups like
 `qt5_variables`/`qt5_version_info`. It's also not a good fit for a
 `fuse-1.1` bump: FUSE2 and FUSE3 are different, non-drop-in-compatible
 APIs with a different consumer contract (the `#include` path itself),
 so treating this as an additive/backward-compatible extension of
 `fuse-1.0` (the way `legacysupport-1.1` is a strict superset of
 `legacysupport-1.0`) would be misleading.

 Sketch:

 {{{
 #!tcl
 # Provides FUSE 3.x (libfuse3 API) support via macFUSE only. No
 # osxfuse, no macfuse4; those predate FUSE3 support in macFUSE and
 # require the legacy 2.x struct layout, which this group does not
 # target. Requires macOS 12 (Monterey, darwin 21)+, matching macfuse's
 # own platform floor.
 #
 # Usage:
 #
 #   PortGroup           macfuse 1.0
 #
 # IMPORTANT: consumer source must #include <fuse3/fuse.h> explicitly,
 # never bare #include <fuse.h>. See macfuse's own compatibility shim
 # note in include/fuse.h. This group cannot force header resolution
 # order for meson-based ports (environment CPPFLAGS are applied ahead
 # of per-dependency cflags in meson's own compile invocations), so it
 # can only catch the mistake, not silently correct it.

 if {${os.platform} eq "darwin" && ${os.major} < 21} {
     pre-fetch {
         return -code error "macfuse PortGroup requires macOS 12 (Monterey)
 or later (darwin >= 21); this system is darwin ${os.major}"
     }
 }

 depends_build-append   path:bin/pkg-config:pkgconfig
 depends_lib-append     path:lib/pkgconfig/fuse3.pc:macfuse

 pre-configure {
     set offenders [split [exec find ${worksrcpath} -type f \
         \( -name *.c -o -name *.h -o -name *.cpp -o -name *.cc \) \
         -exec grep -lE {^#include <fuse\.h>} {} +] "\n"]
     if {[llength ${offenders}] > 0} {
         return -code error "macfuse PortGroup: bare '#include <fuse.h>'
 found in:\n[join ${offenders} \n]\n\nThis resolves to macFUSE's FUSE 2.x
 compatibility header, not fuse3/fuse.h, and will misbuild against
 libfuse3. Patch these includes to <fuse3/fuse.h>."
     }
 }
 }}}

 Notes on the sketch:

 * It's deliberately narrow: macfuse only, macOS 12+. Ports needing
   osxfuse/macfuse4 for older macOS keep using `fuse-1.0` unchanged;
   nothing about this proposal touches that group or its consumers.
 * It can't magically fix header resolution order for every build
   system (confirmed empirically for meson: environment CPPFLAGS beat
   per-dependency cflags in the actual compile invocation, so no
   `configure.cflags` ordering trick reliably wins). Its value is
   turning a silent ABI mismatch into a build-time error with an
   actionable message, at the one place (`pre-configure`, after patches
   are applied) where the real include is knowable.
 * Existing consumers (`sshfs`, `bindfs`) could migrate to it and drop
   their `-Wno-error=incompatible-function-pointer-types` workarounds
   once actually fixed at the source level. Happy to help with those
   patches once the group exists, since I'd guess they're silently
   building the wrong ABI today too.

 I'm happy to submit this as a PR against `macports-ports` if the
 approach sounds right. Wanted to raise it here first since it touches
 shared infrastructure (a new PortGroup) rather than a single port.

-- 
Ticket URL: <https://trac.macports.org/ticket/74309>
MacPorts <https://www.macports.org/>
Ports system for macOS


More information about the macports-tickets mailing list