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

brew install: Error: tup has been disabled because it requires closed-source macFUSE #427

Open
petemoore opened this issue Jul 14, 2021 · 10 comments

Comments

@petemoore
Copy link
Contributor

When attempting to install on a Mac, I hit this issue. I'll try on some other Macs to see if it is specific to my version of macOS or brew etc.

petermoore@Peter-Moores-MacBook-Pro-2:~ $ brew cask install osxfuse
Error: Unknown command: cask
petermoore@Peter-Moores-MacBook-Pro-2:~ $ brew install --cask osxfuse
==> Caveats
`osxfuse` has been succeeded by `macfuse` as of version 4.0.0.

To update to a newer version, do:
  brew uninstall osxfuse
  brew install macfuse

osxfuse requires a kernel extension to work.
If the installation fails, retry after you enable it in:
  System Preferences → Security & Privacy → General

For more information, refer to vendor documentation or this Apple Technical Note:
  https://developer.apple.com/library/content/technotes/tn2459/_index.html

You must reboot for the installation of osxfuse to take effect.

==> Downloading https://github.com/osxfuse/osxfuse/releases/download/osxfuse-3.11.2/osxfuse-3.11.2.dmg
==> Downloading from https://github-releases.githubusercontent.com/1867347/ab8d9600-06f1-11eb-9e31-17e04b5951ce?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credent
######################################################################## 100.0%
==> Installing Cask osxfuse
==> Creating Caskroom directory: /usr/local/Caskroom
We'll set permissions properly so we won't need sudo in the future.
Password:
==> Running installer for osxfuse; your password may be necessary.
Package installers may write to any location; options such as `--appdir` are ignored.
installer: Package name is FUSE for macOS
installer: Installing at base path /
installer: The install was successful.
==> Changing ownership of paths required by osxfuse; your password may be necessary.
🍺  osxfuse was successfully installed!
petermoore@Peter-Moores-MacBook-Pro-2:~ $ brew install tup
Error: tup has been disabled because it requires closed-source macFUSE!
@maparent
Copy link

see https://github.com/gromgit/homebrew-fuse

@gittup
Copy link
Owner

gittup commented Jul 31, 2021

One possibility I was considering is trying to revitalize the ldpreload shim for MacOS. That was how tup originally supported macs, but I believe there was a concern that SIP would prevent ldpreload from working with system binaries (like clang, or tools like cp/python/etc), so tup wouldn't be able to get dependencies that way. I tried ldpreload on my current mac (10.15) and it seems to work though. If it does work, we could remove the FUSE requirement and re-enable tup in Homebrew.

Does anyone know more about SIP and what issues we would have by moving from FUSE to a DYLD_INSERT_LIBRARIES for MacOS?

@petemoore
Copy link
Contributor Author

petemoore commented Aug 8, 2021

Does anyone know more about SIP and what issues we would have by moving from FUSE to a DYLD_INSERT_LIBRARIES for MacOS?

I believe this may be an issue for software which uses a hardened runtime, where I think this type of runtime injection is probably disabled. Note that notarized software has to enable the Hardened Runtime capability. Although it sounds like if you were able to do it, perhaps your clang wasn't built with a hardened runtime?

If fuse isn't a requirement, it may remove some complexity when building a docker image containing tup, and also when launching a docker container that runs tup. Note, I was able to get tup running under docker with these measures:

  1. When running tup inside docker, I needed to call docker run with additional options:
docker run -t --cap-add SYS_ADMIN --device /dev/fuse --security-opt apparmor:unconfined ...
  1. Somewhat unfortunately, docker build does not seem to offer the same provisions as docker run for enabling capabilities, and therefore I believe it isn't possible to run the tup bootstrap.sh script as part of a docker build command. However, there are several workarounds, such as building tup outside of docker build and simply ADD-ing or COPY-ing the tup binary in the docker image, or instead building tup without calling tup itself (e.g. calling build.sh directly rather than bootstrap.sh), which was my chosen path:
RUN curl -L 'https://github.com/gittup/tup/archive/df26484cf223288d31c248a3d50407f2a336df2b.zip' > tup.zip && unzip tup.zip && cd tup-* && CFLAGS="-g" ./build.sh && mv build/tup /usr/local/bin && cd ..

I'm not sure if any of this would be simpler when using the runtime library injection technique, but if it is, that might be a good reason to use it.

BTW, let me know if you'd like me to make a PR adding details about how to call tup in a docker container, if you think it might be useful to others.

@ryandesign
Copy link

So since the use of closed-source fuse is undesirable and using DYLD_INSERT_LIBRARIES may not work due to Apple's increasing restrictions, where does that leave tup? Does it work at all?

@petemoore
Copy link
Contributor Author

I've forgotten the context from this thread (sorry!), but this is how i am currently installing tup on mac, and I think it was working last time I tried.

@ryandesign
Copy link

Ok, so... using fuse.

@ryandesign
Copy link

So again: how can tup be built on macOS without macFUSE?

@petemoore
Copy link
Contributor Author

petemoore commented Dec 25, 2024

I checked, I am again hitting issues on my M1 mac...

When I checkout tup source, and run ./bootstrap.sh tup gets built, and then it attempts to rebuild tup using tup itself, and this fails at the last link stage. Curiously if I modify the last line of bootstrap.sh:

diff --git a/bootstrap.sh b/bootstrap.sh
index be9198c4..8616b91e 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -4,5 +4,5 @@ CFLAGS="-g" ./build.sh
 if [ ! -d .tup ]; then
        ./build/tup init
 fi
-./build/tup
+./build/tup --verbose
 echo "Build complete. If ./tup works, you can remove the 'build' directory."

then I can see the command that is failing:

* 0) ./src/tup/link.sh "clang" "-Os -g -W -Wall -Wbad-function-cast -Wcast-align -Wcast-qual -Wchar-subscripts -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wredundant-decls -Wshadow -Wstrict-prototypes -Wwrite-strings -Wswitch-enum -D_FILE_OFFSET_BITS=64 -fno-common -I./src -I./src -include compat/macosx.h `pcre2-config --cflags` -I./src/inih" "`pcre2-config --libs8` `pkg-config fuse --libs` -lm -lpthread" "tup" "tup-version.o" "src/tup/bin.o src/tup/ccache.o src/tup/colors.o src/tup/config.o src/tup/create_name_file.o src/tup/db.o src/tup/debug.o src/tup/delete_name_file.o src/tup/dircache.o src/tup/entry.o src/tup/environ.o src/tup/estring.o src/tup/file.o src/tup/fslurp.o src/tup/graph.o src/tup/if_stmt.o src/tup/init.o src/tup/lock.o src/tup/logging.o src/tup/luaparser.o src/tup/mempool.o src/tup/option.o src/tup/parser.o src/tup/path.o src/tup/pel_group.o src/tup/platform.o src/tup/progress.o src/tup/send_event.o src/tup/string_tree.o src/tup/tent_list.o src/tup/tent_tree.o src/tup/thread_tree.o src/tup/timespan.o src/tup/tupid_list.o src/tup/tupid_tree.o src/tup/updater.o src/tup/vardb.o src/tup/vardict.o src/tup/variant.o src/tup/varsed.o src/tup/tup/main.o src/tup/monitor/null.o src/tup/flock/fcntl.o src/tup/server/fuse_fs.o src/tup/server/fuse_server.o src/tup/server/master_fork.o src/tup/server/symlink.o src/inih/ini.o src/compat/clearenv.o src/compat/dummy.o src/sqlite3/sqlite3.o src/lua/liblua.a" 
Package fuse was not found in the pkg-config search path.
Perhaps you should add the directory containing `fuse.pc'
to the PKG_CONFIG_PATH environment variable
No package 'fuse' found
Undefined symbols for architecture arm64:
  "_fuse_get_context", referenced from:
      _tup_fs_readlink in fuse_fs.o
      _context_check in fuse_fs.o
      _context_check in fuse_fs.o
      _context_check in fuse_fs.o
      _context_check in fuse_fs.o
  "_fuse_main_real", referenced from:
      _fuse_thread in fuse_server.o
  "_fuse_opt_add_arg", referenced from:
      _fuse_thread in fuse_server.o
      _fuse_thread in fuse_server.o
      _fuse_thread in fuse_server.o
      _fuse_thread in fuse_server.o
      _fuse_thread in fuse_server.o
      _fuse_thread in fuse_server.o
      _fuse_thread in fuse_server.o
      ...
  "_fuse_opt_free_args", referenced from:
      _fuse_thread in fuse_server.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
 *** tup messages ***
 *** Command ID=1839 failed with return value 1
 [ ] 100%
 *** tup: 1 job failed.

However, if I run that exact command, it runs without problems:

pmoore@Peters-MacBook-Pro-2:~/git/tup master $ ./src/tup/link.sh "clang" "-Os -g -W -Wall -Wbad-function-cast -Wcast-align -Wcast-qual -Wchar-subscripts -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wredundant-decls -Wshadow -Wstrict-prototypes -Wwrite-strings -Wswitch-enum -D_FILE_OFFSET_BITS=64 -fno-common -I./src -I./src -include compat/macosx.h `pcre2-config --cflags` -I./src/inih" "`pcre2-config --libs8` `pkg-config fuse --libs` -lm -lpthread" "tup" "tup-version.o" "src/tup/bin.o src/tup/ccache.o src/tup/colors.o src/tup/config.o src/tup/create_name_file.o src/tup/db.o src/tup/debug.o src/tup/delete_name_file.o src/tup/dircache.o src/tup/entry.o src/tup/environ.o src/tup/estring.o src/tup/file.o src/tup/fslurp.o src/tup/graph.o src/tup/if_stmt.o src/tup/init.o src/tup/lock.o src/tup/logging.o src/tup/luaparser.o src/tup/mempool.o src/tup/option.o src/tup/parser.o src/tup/path.o src/tup/pel_group.o src/tup/platform.o src/tup/progress.o src/tup/send_event.o src/tup/string_tree.o src/tup/tent_list.o src/tup/tent_tree.o src/tup/thread_tree.o src/tup/timespan.o src/tup/tupid_list.o src/tup/tupid_tree.o src/tup/updater.o src/tup/vardb.o src/tup/vardict.o src/tup/variant.o src/tup/varsed.o src/tup/tup/main.o src/tup/monitor/null.o src/tup/flock/fcntl.o src/tup/server/fuse_fs.o src/tup/server/fuse_server.o src/tup/server/master_fork.o src/tup/server/symlink.o src/inih/ini.o src/compat/clearenv.o src/compat/dummy.o src/sqlite3/sqlite3.o src/lua/liblua.a" 
pmoore@Peters-MacBook-Pro-2:~/git/tup master $ echo $?
0
pmoore@Peters-MacBook-Pro-2:~/git/tup master $ 

Checking my system, fuse seems to have the correct architecture support and symbols, e.g.

pmoore@Peters-MacBook-Pro-2:~/git/tup master $ file /usr/local/lib/libfuse.dylib
/usr/local/lib/libfuse.dylib: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit dynamically linked shared library x86_64] [arm64:Mach-O 64-bit dynamically linked shared library arm64]
/usr/local/lib/libfuse.dylib (for architecture x86_64):	Mach-O 64-bit dynamically linked shared library x86_64
/usr/local/lib/libfuse.dylib (for architecture arm64):	Mach-O 64-bit dynamically linked shared library arm64
pmoore@Peters-MacBook-Pro-2:~/git/tup master $ nm -g /usr/local/lib/libfuse.dylib | grep _fuse_get_context
0000000000002210 T _fuse_get_context
0000000000004efc T _fuse_get_context_compat22
pmoore@Peters-MacBook-Pro-2:~/git/tup master $ 

I explicitly added /usr/local/lib/pkgconfig to PKG_CONFIG_PATH to get the initial build of tup to work...

pmoore@Peters-MacBook-Pro-2:~/git/tup master $ env | grep PKG_CONFIG_PATH
PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/opt/homebrew/opt/ruby/lib/pkgconfig
pmoore@Peters-MacBook-Pro-2:~/git/tup master $ 

@petemoore
Copy link
Contributor Author

I figured it is probably due to pkg-config running inside the tup build of tup itself, so hacked it explicitly for my env, and that fixed it for me:

pmoore@Peters-MacBook-Pro-2:~/git/tup master $ git diff
diff --git a/Tupfile b/Tupfile
index 6a7da8d1..4397bf22 100644
--- a/Tupfile
+++ b/Tupfile
@@ -45,7 +45,7 @@ suid = ; chown root:$(TUP_SUID_GROUP) tup; chmod u+s tup
 endif
 
 ifeq ($(TUP_SERVER),fuse)
-LDFLAGS += `pkg-config fuse --libs`
+LDFLAGS += -L/usr/local/lib -lfuse -pthread
 endif
 
 ifeq ($(TUP_SERVER),fuse3)
diff --git a/bootstrap.sh b/bootstrap.sh
index be9198c4..8616b91e 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -4,5 +4,5 @@ CFLAGS="-g" ./build.sh
 if [ ! -d .tup ]; then
        ./build/tup init
 fi
-./build/tup
+./build/tup --verbose
 echo "Build complete. If ./tup works, you can remove the 'build' directory."
pmoore@Peters-MacBook-Pro-2:~/git/tup master $ 

Now I can build tup from source again.

@petemoore
Copy link
Contributor Author

I made a fix for the above issue in #511.

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

No branches or pull requests

4 participants