Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fuse-t: init at 1.0.42 #348804

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions pkgs/by-name/fu/fuse-t/fuse-t.pc.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
prefix=@out@
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include/fuse

Name: fuse-t
Description: Userspace FUSE implementation for macOS
Version: @version@
Libs: -L${libdir} -Wl,-rpath,${libdir} -lfuse-t
Cflags: -I${includedir} -D_FILE_OFFSET_BITS=64
20 changes: 20 additions & 0 deletions pkgs/by-name/fu/fuse-t/no-universal-binaries.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt
index e1184cb..9989d0b 100644
--- a/example/CMakeLists.txt
+++ b/example/CMakeLists.txt
@@ -1,5 +1,3 @@
-set(CMAKE_OSX_ARCHITECTURES arm64;x86_64)
-
add_executable (hello hello.c)
add_executable (hello_ll hello_ll.c)
add_executable (cusexmp cusexmp.c)
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index db6f2ac..70592cd 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -1,5 +1,3 @@
-set(CMAKE_OSX_ARCHITECTURES arm64;x86_64)
-
set(SRC
buffer.c
fuse_darwin.c
185 changes: 185 additions & 0 deletions pkgs/by-name/fu/fuse-t/package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
{
lib,
stdenv,
fetchurl,
libarchive,
p7zip,
libtapi,
fetchFromGitHub,
cmake,
libiconv,
DiskArbitration,
}:

let
version = "1.0.42";

# This can be used instead of fuse-t however downstream programs
# will need to be run with the environment variable `FUSE_NFSSRV_PATH`
# set to `<fuse-t.binaryDistribution>/bin/go-nfsv4`
binaryDistribution = stdenv.mkDerivation {
pname = "fuse-t-binary-dist";
inherit version;

src = fetchurl {
url = "https://github.com/macos-fuse-t/fuse-t/releases/download/${version}/fuse-t-macos-installer-${version}.pkg";
hash = "sha256-pYrQT05hGDcTPYXebTftvd3xGS8ozGTCa47FvWVZQ68=";
};

nativeBuildInputs = [
libarchive
p7zip
libtapi
];
propagatedBuildInputs = [ DiskArbitration ];

unpackPhase = ''
7z x $src
bsdtar -xf Payload~
'';

buildPhase = ''
fuseDir="Library/Application Support/fuse-t"
sed -i "s|^prefix=.*|prefix=$out|" "$fuseDir/pkgconfig/fuse-t.pc"
sed -i "s|^\(Cflags: .*\)|\1 -D_FILE_OFFSET_BITS=64|" "$fuseDir/pkgconfig/fuse-t.pc"
ln -s libfuse-t-${version}.a "$fuseDir/lib/libfuse-t.a"
ln -s libfuse-t-${version}.dylib "$fuseDir/lib/libfuse-t.dylib"
rm "$fuseDir/uninstall.sh"
'';

installPhase = ''
runHook preInstall
mkdir -p $out/lib
mv "$fuseDir/bin" $out
mv "$fuseDir/include" $out
mv "$fuseDir/lib" $out
mv "$fuseDir/pkgconfig" $out/lib
mv Library $out/Library
runHook postInstall
'';

meta = {
description = "FUSE-T is a kext-less implementation of FUSE for macOS that uses NFS v4 local server instead of a kernel extension.";
homepage = "https://www.fuse-t.org/";
# free for non-commercial use, see: https://github.com/macos-fuse-t/fuse-t/blob/main/License.txt
license = [ lib.licenses.unfreeRedistributable ];
sourceProvenance = [ lib.sourceTypes.binaryNativeCode ];
platforms = lib.platforms.darwin;
};
};

stubs = stdenv.mkDerivation {
pname = "fuse-t-stubs";
inherit version;

src = fetchFromGitHub {
owner = "macos-fuse-t";
repo = "libfuse";
rev = "da72c8b60eb929d86c4594fc1792ae49865cd659";
hash = "sha256-++edBetY+Xfvp5X4i+mL+FJgJXeV43toDRRKhLHlMhw=";
};

patches = [
./no-universal-binaries.patch
./use-correct-path.patch
];

postPatch = ''
substituteAllInPlace lib/fuse_darwin_private.h
'';

nativeBuildInputs = [
cmake
libtapi
];

# TODO: remove `.out` after https://github.com/NixOS/nixpkgs/pull/346043 is merged to `master`
buildInputs = [
libiconv.out
DiskArbitration
];

propagatedBuildInputs = [ DiskArbitration ];

# Removes a lot of warning spam
# `warning: 'pthread_setugid_np' is deprecated: Use of per-thread security contexts is error-prone and discouraged.`
env.NIX_CFLAGS_COMPILE = "-Wno-deprecated-declarations";

postBuild = ''
mkdir -p lib/pkgconfig
tapi stubify --filetype=tbd-v2 lib/libfuse-t.dylib -o lib/libfuse-t.tbd
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of creating a TBD stub from a source-built package? I'm confused because I recognize TBD stubs as substitutes for actual dylib files, yet the built dylib is included in this package.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just copied it from the macFUSE derivation, I didn't actually know what they were for

Copy link
Member

@midchildan midchildan Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. So here's the background. macFUSE consists of a kernel extension, preference pane, and the userspace libfuse library. This created a few challenges.

  1. Everything except libfuse is unfree which disqualifies it from being the on binary cache
  2. Preference panes and kernel extensions can't be installed with Nix
  3. libfuse works closely with the kernel extension, so version mismatches could break things

So I took the approach of making users install macFUSE outside of Nix and have packages link to the out-of-store libfuse. To achieve this, the macfuse-stub package creates a stub of libfuse using the actual macFUSE release so that compilers can link to it without it being actually present in /usr/local/lib.

With FUSE-T, problem No. 1 remains. And if we drop the NFS server but build libfuse from source, we'll have problem No. 3 as well. So I think the FUSE-T package should take the same approach to avoid these problems.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of FUSE-T, the location for the NFS server is compiled in a header https://github.com/NixOS/nixpkgs/pull/348804/files#diff-542ad4d614512f9a215eaba4a723df42cc4a1fdc6f1d339f73a35818a50b043e but can be overridden with the environment variable FUSE_NFSSRV_PATH

So we could change it from directly pointing to the unfree NFS server to /run/current-system/sw/bin and then nix-darwin users can install the unfree NFS server using environment.systemPackages

In addition we could create wrappers (living under different attributes, so the downstream packages still get cached) that set FUSE_NFSSRV_PATH so that users can still use the packages from Nixpkgs without needing to manually install the unfree NFS server

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t suppose there’s any chance of using the same stubs for both macFUSE and FUSE-T?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. FUSE-T changed the filename to libfuse-t.dylib for one thing.

Copy link
Member

@midchildan midchildan Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we could change it from directly pointing to the unfree NFS server to /run/current-system/sw/bin and then nix-darwin users can install the unfree NFS server using environment.systemPackages

For maximum compatibility, I guess we can use the header as is and introduce a nix-darwin module that makes FUSE_NFSSRV_PATH point to the Nix store. This would allow both Nix and non-Nix applications to use FUSE-T.

It should be noted though, that some applications use libraries that bypass libfuse and talk to the NFS server directly. Those aren't guaranteed to respect FUSE_NFSSRV_PATH. This is likely not an exhaustive list, but I found one case where the path is hardcoded.

https://grep.app/search?q=FUSE_NFSSRV_PATH

There are also cases like cgofuse, which uses dlopen() to load libfuse from a hardcoded path.

https://github.com/winfsp/cgofuse/blob/f87f5db493b56c5f4ebe482a1b7d02c7e5d572fa/fuse/host_cgo.go#L176

In addition we could create wrappers (living under different attributes, so the downstream packages still get cached) that set FUSE_NFSSRV_PATH so that users can still use the packages from Nixpkgs without needing to manually install the unfree NFS server

You mean like steam-run? That sounds nice, though I think we'd need to check that two different instances of the NFS server can run at the same time. Nix being Nix, users may have multiple FUSE-T NFS servers in their Nix store.

From what I've seen in FUSE-T libfuse's code, it does appear to be okay. libfuse creates a socket pair using socketpair(), forks and launches the NFS server, and uses the created socket to communicate with the newly launched server. It's probably a good idea to check though, because we don't know exactly what happens in the NFS server.

substituteAll ${./fuse-t.pc.in} lib/pkgconfig/fuse-t.pc
'';

installPhase = ''
runHook preInstall
frameworkDir=$out/Library/Frameworks/fuse_t.framework
frameworkADir=$frameworkDir/Versions/A
mkdir -p $out/lib/pkgconfig $out/include/fuse $frameworkADir/Headers $frameworkADir/PrivateHeaders
cp lib/libfuse-t.a lib/libfuse-t.dylib lib/libfuse-t.tbd $out/lib
cp lib/pkgconfig/fuse-t.pc $out/lib/pkgconfig
cd ..
cp include/fuse* $out/include/fuse
cp include/fuse* $frameworkADir/Headers
cp include/fuse* $frameworkADir/PrivateHeaders
ln -s A $out/Library/Frameworks/fuse_t.framework/Versions/Current
ln -s Versions/Current/Headers $frameworkDir
ln -s Versions/Current/PrivateHeaders $frameworkDir
cp include/config.h include/cuse_*.h lib/fuse_*.h $frameworkADir/PrivateHeaders
cp include/cuse_*.h $frameworkADir/PrivateHeaders
cp lib/fuse_*.h $frameworkADir/PrivateHeaders
runHook postInstall
'';

doCheck = false;

meta = with lib; {
description = "Library that allows filesystems to be implemented in user space";
longDescription = ''
FUSE (Filesystem in Userspace) is an interface for userspace programs to
export a filesystem to the Linux kernel. The FUSE project consists of two
components: The fuse kernel module (maintained in the regular kernel
repositories) and the libfuse userspace library (this package). libfuse
provides the reference implementation for communicating with the FUSE
kernel module.
'';
homepage = "https://github.com/macos-fuse-t/libfuse";
platforms = platforms.darwin;
license = licenses.lgpl21Only;
};
};
in
stubs.overrideAttrs {
pname = "fuse-t";

postInstall = ''
cp -RHnv ${binaryDistribution}/. $out
rm $out/lib/libfuse-t-${version}.a $out/lib/libfuse-t-${version}.dylib
'';

passthru = {
inherit binaryDistribution stubs;
};

meta = {
description = "FUSE-T is a kext-less implementation of FUSE for macOS that uses NFS v4 local server instead of a kernel extension.";
homepage = "https://www.fuse-t.org/";
license = [
# libfuse/stubs
lib.licenses.lgpl21Only

# NFS server
# free for non-commercial use, see: https://github.com/macos-fuse-t/fuse-t/blob/main/License.txt
lib.licenses.unfreeRedistributable
Comment on lines +171 to +173
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit concerned about including the unfree NFS server. I believe Hydra doesn't build unfreeRedistributable packages. Wouldn't this cause more popular packages to be dropped from the Darwin binary cache as more packages switch to FUSE-T?

#83884

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AIUI packages will only link to the stubs, which are FOSS (as they have to be, because FUSE is LGPL).

(Will try to find the time to review the rest of this soon.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears that the fuse-t package isn't a stub, but rather a mixture of a source-built libfuse and the unfree NFS server. So in this case, I believe sshfs-fuse will be dropped from the binary cache.

];
sourceProvenance = [
# libfuse/stubs
lib.sourceTypes.fromSource

# NFS server
lib.sourceTypes.binaryNativeCode
];
maintainers = [ lib.maintainers.Enzime ];
platforms = lib.platforms.darwin;
};
}
13 changes: 13 additions & 0 deletions pkgs/by-name/fu/fuse-t/use-correct-path.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/lib/fuse_darwin_private.h b/lib/fuse_darwin_private.h
index 4d4cc68..840b06f 100644
--- a/lib/fuse_darwin_private.h
+++ b/lib/fuse_darwin_private.h
@@ -38,7 +38,7 @@ extern "C" {
#endif

#ifndef FUSE_NFSSRV_PROG
-# define FUSE_NFSSRV_PROG "/usr/local/bin/go-nfsv4"
+# define FUSE_NFSSRV_PROG "@out@/bin/go-nfsv4"
#endif

#ifndef OSXFUSE_VOLUME_ICON
10 changes: 3 additions & 7 deletions pkgs/tools/filesystems/sshfs-fuse/common.nix
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
{ version, sha256, platforms, patches ? [ ] }:
{ version, sha256, platforms, patches ? [ ], fuse }:

{ lib, stdenv, fetchFromGitHub
, meson, pkg-config, ninja, docutils, makeWrapper
, fuse3, macfuse-stubs, glib
, which, python3Packages
, glib, which, python3Packages
, openssh
}:

let
fuse = if stdenv.hostPlatform.isDarwin then macfuse-stubs else fuse3;
in stdenv.mkDerivation rec {
stdenv.mkDerivation {
pname = "sshfs-fuse";
inherit version;

Expand Down Expand Up @@ -53,7 +50,6 @@ in stdenv.mkDerivation rec {
meta = with lib; {
inherit platforms;
description = "FUSE-based filesystem that allows remote filesystems to be mounted over SSH";
longDescription = macfuse-stubs.warning;
homepage = "https://github.com/libfuse/sshfs";
license = licenses.gpl2Plus;
mainProgram = "sshfs";
Expand Down
10 changes: 7 additions & 3 deletions pkgs/tools/filesystems/sshfs-fuse/default.nix
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
{ lib, stdenv, callPackage, fetchpatch }:
{ lib, stdenv, callPackage, fuse-t, fetchpatch, fuse3 }:

let mkSSHFS = args: callPackage (import ./common.nix args) { };
in if stdenv.hostPlatform.isDarwin then
mkSSHFS {
version = "2.10"; # macFUSE isn't yet compatible with libfuse 3.x
version = "2.10"; # FUSE-T isn't yet compatible with libfuse 3.x
sha256 = "1dmw4kx6vyawcywiv8drrajnam0m29mxfswcp4209qafzx3mjlp1";
fuse = fuse-t;
patches = [
# remove reference to fuse_darwin.h which doens't exist on recent macFUSE
# remove reference to fuse_darwin.h which doesn't exist on newer macFUSE or FUSE-T
./fix-fuse-darwin-h.patch

# From https://github.com/libfuse/sshfs/pull/185:
Expand All @@ -17,12 +18,15 @@ in if stdenv.hostPlatform.isDarwin then
url = "https://github.com/libfuse/sshfs/commit/667cf34622e2e873db776791df275c7a582d6295.patch";
sha256 = "0d65lawd2g2aisk1rw2vl65dgxywf4vqgv765n9zj9zysyya8a54";
})

./support-fuse-t.patch
];
platforms = lib.platforms.darwin;
}
else
mkSSHFS {
version = "3.7.3";
sha256 = "0s2hilqixjmv4y8n67zaq374sgnbscp95lgz5ignp69g3p1vmhwz";
fuse = fuse3;
platforms = lib.platforms.linux;
}
13 changes: 13 additions & 0 deletions pkgs/tools/filesystems/sshfs-fuse/support-fuse-t.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/meson.build b/meson.build
index 5bbba54..736e3e2 100644
--- a/meson.build
+++ b/meson.build
@@ -45,7 +45,7 @@ configure_file(input: 'sshfs.1.in',
configure_file(output: 'config.h',
configuration : cfg)

-sshfs_deps = [ dependency('fuse', version: '>= 2.3'),
+sshfs_deps = [ dependency('fuse-t'),
dependency('glib-2.0'),
dependency('gthread-2.0') ]

4 changes: 4 additions & 0 deletions pkgs/top-level/all-packages.nix
Original file line number Diff line number Diff line change
Expand Up @@ -25661,6 +25661,10 @@ with pkgs;
fuse3 = fusePackages.fuse_3;
fuse-common = hiPrio fusePackages.fuse_3.common;

fuse-t = callPackage ../by-name/fu/fuse-t/package.nix {
inherit (darwin.apple_sdk.frameworks) DiskArbitration;
};

fxload = callPackage ../os-specific/linux/fxload { };

gfxtablet = callPackage ../os-specific/linux/gfxtablet { };
Expand Down