Re: File locations for linux (and mostly other *nix too)

Christoph Thiede via Squeak-dev <[email protected]> Wed, 17 Jun 2026 00:41:36 +0200
Newsgroups gmane.comp.lang.smalltalk.squeak.general
Message-ID <fb1237ed-cb8e-473a-ba79-67a88f7798bb@MX2025-DAG1.hpi.uni-potsdam.de>
Hi Tim, all,

Thanks for your thoughts! I think it is important to separate the OS integration experience from the bundle experience. Both are frequently desired workflows:
- download a bundle, extract it, run it, change the image, save it
- install one or multiple vm versions, maintain multiple image versions, run any vm with any image, potentially save images as new versions by default
Currently we already support the first workflow quite well with our (all-in-one) bundles. Better support for the second workflow would also be great, especially for newcomers or less OS-experienced people who do not like to use the command line.
When making such changes, several concerns come to my mind:
- we should not break the first (bundle) workflow
- the system-wide directory may not exist or be write-only
- on windows, the path structure looks totally different
- on both linux and windows, installing applications as user-level instead of system-wide is becoming increasingly popular. This also avoids problems with windows uac or linux non-sudo rights (more on that below).
- proper shell integration might also be nice to display the vm/image files with a proper icon and description, find them in your launcher/start menu, or in your shell path...

When I was using Windows in a fortunately bygone time, I used to copy the VM folder (including .exe and .ini) and the sources to C:\Program Files and wrote a small .reg (registry) file so I could view and doube-click .image files in the file explorer.

For Ubuntu/Gnome, I have already started documenting similar attempts last year in this pull request:
https://github.com/squeak-smalltalk/squeak-app/pull/39
Unfortunately, we never moved forward with this because some people expressed that there was a need for a general vm launcher/multi version management solution first.

In the mean time, I have further enriched my bash shell workflow for squeak and built a small multi-version launcher:

	christoph@tuxedo-christoph:~$ squeak --wrapper-help
	Usage: squeak [WRAPPER OPTIONS] [--] [SQUEAK OPTIONS]
	
	Wrapper options:
	  --version                   Show selected Squeak version, then exit
	  --version=VERSION           Select Squeak version (defaults to $SQUEAK_VERSION or /home/christoph/.local/squeak/version file)
	  --all-versions              List all installed Squeak versions, then exit
	  --wrapper-help              Show this help
	
	All other arguments are passed through unchanged.
	christoph@tuxedo-christoph:~$ squeak squeak/FreshTrunk.image 
	pthread_setschedparam failed: Operation not permitted
	This VM uses a separate heartbeat thread to update its internal clock
	and handle events.  For best operation, this thread should run at a
	higher priority, however the VM was unable to change the priority.  The
	effect is that heavily loaded systems may experience some latency
	issues.  If this occurs, please create the appropriate configuration
	file in /etc/security/limits.d/ as shown below:
	
	cat <<END | sudo tee /etc/security/limits.d/squeak.conf
	*      hard    rtprio  2
	*      soft    rtprio  2
	END
	
	and report to the squeak mailing list whether this improves behaviour.
	
	You will need to log out and log back in for the limits to take effect.
	For more information please see
	https://github.com/OpenSmalltalk/opensmalltalk-vm/releases/tag/r3732#linux
	christoph@tuxedo-christoph:~$ squeak --version=202206021410 squeak/FreshTrunk.image 
	pthread_setschedparam failed: Operation not permitted
	This VM uses a separate heartbeat thread to update its internal clock
	and handle events.  For best operation, this thread should run at a
	higher priority, however the VM was unable to change the priority.  The
	effect is that heavily loaded systems may experience some latency
	issues.  If this occurs, please create the appropriate configuration
	file in /etc/security/limits.d/ as shown below:
	
	cat <<END | sudo tee /etc/security/limits.d/squeak.conf
	*      hard    rtprio  2
	*      soft    rtprio  2
	END
	
	and report to the squeak mailing list whether this improves behaviour.
	
	You will need to log out and log back in for the limits to take effect.
	For more information please see
	https://github.com/OpenSmalltalk/opensmalltalk-vm/releases/tag/r3732#linux
	christoph@tuxedo-christoph:~$ squeak --all-versions 
	202206021410
	202312181441
	202509300044
	202601200834
	202603271636
	202604252110

I have decided for a user-local setup which looks like this:

	christoph@tuxedo-christoph:~$ ls .local/
	bin/    share/  squeak/ state/  
	christoph@tuxedo-christoph:~$ ls .local/squeak/
	202206021410  202312181441  202509300044  202601200834  202603271636  202604252110  squeak.svg  version
	christoph@tuxedo-christoph:~$ cat .local/squeak/version 
	202604252110
	christoph@tuxedo-christoph:~$ tree -L 4 .local/squeak/202604252110/
	.local/squeak/202604252110/
	├── bin
	│   └── spur64
	├── lib
	│   └── squeak
	│       └── 7.0-202604252110-64bit
	│           ├── B3DAcceleratorPlugin.so
	│           ├── ClipboardExtendedPlugin.so
	│           ├── DESPlugin.so
	│           ├── FileAttributesPlugin.so
	│           ├── HelloExternalWorldPlugin.so
	│           ├── HelloWorldPlugin.so
	│           ├── ImmX11Plugin.so
	│           ├── LocalePlugin.so
	│           ├── MD5Plugin.so
	│           ├── MIDIPlugin.so
	│           ├── PseudoTTYPlugin.so
	│           ├── SHA2Plugin.so
	│           ├── squeak
	│           ├── Squeak3D.so
	│           ├── SqueakFFIPrims.so
	│           ├── SqueakSSL.so
	│           ├── UnicodePlugin.so
	│           ├── UnixOSProcessPlugin.so
	│           ├── UUIDPlugin.so
	│           ├── VectorEnginePlugin.so
	│           ├── vm-display-fbdev.so
	│           ├── vm-display-null.so
	│           ├── vm-display-X11.so
	│           ├── vm-sound-ALSA.so
	│           ├── vm-sound-NAS.so
	│           ├── vm-sound-null.so
	│           ├── vm-sound-OSS.so
	│           ├── vm-sound-pulse.so
	│           ├── vm-sound-sndio.so
	│           └── XDisplayControlPlugin.so
	└── squeak
	
	5 directories, 32 files

I also built a small autocompletion helper which I find quite convenient:

	christoph@tuxedo-christoph:~$ squeak --version=202<TAB>
	202206021410  202312181441  202509300044  202601200834  202603271636  202604252110  
	christoph@tuxedo-christoph:~$ squeak squeak/<TAB>
	2019-10 Squeak By Example/                   FreshTrunk-tests_segs/                       Spur64VMMaker.1.image
	bitbucket-cache/                             FreshTrunk-vmmakerready.image                Spur64VMMaker.image
	bootstrapping-demo.image                     FreshTrunk-YarosClient.image                 Squeak6.0-22148-64bit.image
	.DAP/                                        github-cache/                                squeak61-release-notes.image
	FreshTrunk-bootstrapping.image               package-cache/                               squeak-history/
	FreshTrunk-dnd4all.image                     prefs/                                       SqueakInboxTalk.image
	FreshTrunk-dragging.image                    Regex.image                                  test/
	FreshTrunk.image                             _release_notes/                              test555567/
	FreshTrunk-sbtext.image                      release-notes/                               testempty/
	FreshTrunk_segs/                             RichTrunk-sqh.autosave/                      TraceDebugger/
	FreshTrunk-SimulatorMorph refactoring.image  RichTrunk-sqh.image                          xnb-demo.image
	FreshTrunk-tests.image                       sm/                                          

Yahoo, this only shows me .image files, no gazillions of changesets and temp files!

This is my current implementation of both scripts:

	christoph@tuxedo-christoph:~$ cat .local/bin/squeak 
	#!/bin/sh
	set -e
	
	folder="$HOME/.local/squeak"
	
	version="$(cat "$folder/version" 2>/dev/null || true)"
	version="${SQUEAK_VERSION:-$version}"
	
	show_help() {
	  cat <<EOF
	Usage: squeak [WRAPPER OPTIONS] [--] [SQUEAK OPTIONS]
	
	Wrapper options:
	  --version                   Show selected Squeak version, then exit
	  --version=VERSION           Select Squeak version (defaults to \$SQUEAK_VERSION or ${folder}/version file)
	  --all-versions              List all installed Squeak versions, then exit
	  --wrapper-help              Show this help
	
	All other arguments are passed through unchanged.
	EOF
	}
	
	while [ $# -gt 0 ]; do
	  case "$1" in
	    --version)
	      echo "$version"
	      exit 0
	      ;;
	    --version=*)
	      version="${1#--version=}"
	      shift
	      ;;
	    --all-versions)
	      find "$folder" -maxdepth 1 -mindepth 1 -type d -not -name '.*' -exec basename {} \; | sort
	      exit 0
	      ;;
	    --wrapper-help)
	      show_help
	      exit 0
	      ;;
	    *)
	      break
	      ;;
	  esac
	done
	
	if [ -z "$version" ]; then
	  echo "Error: No Squeak version selected. Use --version=VERSION or set SQUEAK_VERSION." >&2
	  exit 1
	fi
	
	exec "$folder/$version/squeak" "$@"
	christoph@tuxedo-christoph:~$ cat .local/share/bash-completion/completions/squeak
	#!/usr/bin/env bash
	# install using:
	# mkdir -p ~/.local/share/bash-completion/completions && ln -s ~/.local/squeak/.completions/bash ~/.local/share/bash-completion/completions/squeak
	
	# TODO:
	# - this is vibe coded but has worked well for months
	# - redact commentary
	# - could we somehow simply integrate squeak completions itself? (--display etc.)
	# - automatic installation/docs?
	
	_squeak_wrapper_complete() {
	  local cur prev prev_prev
	  COMPREPLY=()
	  
	  # Standard Bash completion variables
	  cur="${COMP_WORDS[COMP_CWORD]}"
	  prev="${COMP_WORDS[COMP_CWORD-1]}"
	  
	  # Safely get the "grandparent" word (word before prev)
	  if [[ ${COMP_CWORD} -ge 2 ]]; then
	    prev_prev="${COMP_WORDS[COMP_CWORD-2]}"
	  fi
	
	  local script="$HOME/.local/bin/squeak"
	  local -a wrapper_opts="--version --version= --all-versions --wrapper-help --"
	  local versions
	  
	  # Only fetch versions if we are definitely in a version context to save processing
	  # You might want to cache this or valid checks to avoid running the script on every tab
	  
	  # -------------------------------------------------------------------------
	  # Case A: User typed "--version=202" (Bash split the string at '=')
	  # cur = "202", prev = "=", prev_prev = "--version"
	  # -------------------------------------------------------------------------
	  if [[ "$prev" == "=" && "$prev_prev" == "--version" ]]; then
	    versions="$("$script" --all-versions 2>/dev/null)"
	    mapfile -t COMPREPLY < <(compgen -W "$versions" -- "$cur")
	    # We do NOT add "=" prefix here, because the "=" is already on the command line (in 'prev')
	    return 0
	  fi
	
	  # -------------------------------------------------------------------------
	  # Case B: User typed "--version=" (Cursor is right at the equals)
	  # cur = "=", prev = "--version"
	  # -------------------------------------------------------------------------
	  if [[ "$prev" == "--version" && "$cur" == "=" ]]; then
	    versions="$("$script" --all-versions 2>/dev/null)"
	    # We complete against an empty string because the value hasn't started yet
	    mapfile -t COMPREPLY < <(compgen -W "$versions" -- "")
	    
	    # FORMATTING TRICK:
	    # If we return just "202", bash might overwrite "=" with "202" -> "squeak --version 202" (bad)
	    # If we return "=202", bash overwrites "=" with "=202" -> "squeak --version=202" (good)
	    COMPREPLY=( "${COMPREPLY[@]/#/}" )
	    compopt -o nospace 2>/dev/null || true
	    return 0
	  fi
	
	  # -------------------------------------------------------------------------
	  # Case C: '=' is NOT a wordbreak (e.g., inside quotes or specific shell settings)
	  # cur = "--version=202"
	  # -------------------------------------------------------------------------
	  if [[ "$cur" == --version=* ]]; then
	    versions="$("$script" --all-versions 2>/dev/null)"
	    local prefix="${cur#--version=}"
	    mapfile -t COMPREPLY < <(compgen -W "$versions" -- "$prefix")
	    COMPREPLY=( "${COMPREPLY[@]/#/--version=}" )
	    compopt -o nospace 2>/dev/null || true
	    return 0
	  fi
	
	  # -------------------------------------------------------------------------
	  # Standard Option Completion
	  # -------------------------------------------------------------------------
	  if [[ "$cur" == -* ]]; then
	    mapfile -t COMPREPLY < <(compgen -W "$wrapper_opts" -- "$cur")
	    
	    # If the user selected "--version=", ensure no space is added so they can type the ID immediately
	    if [[ "${COMPREPLY[*]}" == *"--version="* ]]; then
	      compopt -o nospace 2>/dev/null || true
	    fi
	    return 0
	  fi
	
	  # compopt -o default
	  # alternatively:
	  # 5. File Completion (suggest only *.image files and directories)
	  if [[ "$cur" != -* ]] || [[ "$prev" == "--" ]]; then
	    # -o filenames: Tells bash these are paths. 
	    # It will add a slash to dirs (without a space) and a space to files.
	    compopt -o filenames 2>/dev/null
	
	    # We combine directories and the filtered image files
	    mapfile -t COMPREPLY < <(
	      compgen -d -- "$cur"
	      compgen -f -X '!*.image' -- "$cur"
	    )
	    return 0
	  fi
	
	  return 0
	}
	
	complete -F _squeak_wrapper_complete squeak

What's still imperfect about my setup is that my sources files live in my ~/squeak folder next to most images, and (probably unrelated) I still get every time these pthread_setschedparam warnings I don't understand.

If anyone is interested in this I would be happy to further polish my launcher files and put them in the squeak-app repository. Extending them to support a system-wide installation should be quite straightforward. I am not an expert in these things, but my naive expectation would be that the entry point script (or a symlink to it) should be in /usr/bin in this case, image and changes files somewhere in /var, and for the single VM versions I'm honestly not sure. /usr/lib/squeak? Should we integrate with Linux' update-alternatives mechanism?

IMHO, the project "Squeak installation" consists of many different steps, and we should allow ourselves to make one of them at a time:

1. Document possible shell integration/installation ways for different systems
2. Ship them with the bundles so new users can easily find them and apply them on their system
3. Automate the installation steps
100. Extend the launchers to download new VM versions or remove older versions, provide a GUI, be bootstrapped in Squeak itself, etc.
1000. Register for different package managers such as apt, pacman, winget, brew, F-Droid, ... If we want to accept that extra maintenance burden.

But don't let the perfect be the enemy of the good. We can put some convenient launcher scripts and bash shell/GUI shell integrations into the repo at any time. I'd say let's do this!

Best,
Christoph

PS: Just btw, a much more urgent issue IMHO is that the squeak.sh script in our all-in-one bundle gets the high-dpi mode on Wayland wrong whereas the script version from the OpenSmalltalk VM just works right. We should get this fixed prior to the upcoming release. Open (stale) discussion, help welcome: https://github.com/squeak-smalltalk/squeak-object-memory/issues/151

-- 
Sent from Squeak Inbox Talk

On 2026-06-16T16:17:04-04:00, [email protected] wrote:

> Phil! Really good to hear from you :-) Thanks very much for your work and support on this topic in that past, and hopefully we can find ways to make some more progress.
> Tim, minor details aside I agree very much with what you said. You are probably aware (but others may not be) that Phil has done some important work on making opensmalltalk-vm and squeakvm be consistent with *nix standards and conventions, and our goal was (is?) to be able to support the rather stringent requirements of the Debian project (which in turn is the basis for many other derivative Linux distros). Vanessa was an important contributor as well.
> Many of the necessary pieces are already in place, but not well advertised. For example, if you are building opensmalltalk-vm for your Raspberry Pi, try doing a "sudo make install" right after you run the "mvm" the build directory. You will see /usr/local/bin/spur64 installed and pointing to a quite reasonable library location for the VM itself. I should put together some notes on the various pieces like this that are already sorted out, maybe next week because I'll need to dust off some old notes and tired memory cells.
> Dave
> 
> On 2026-06-16 14:40, Phil B wrote:
> I almost included a bit talking more about commercial software but decided I was already going on long enough. ;-)  Yes, commercial software definitely uses it mainly because that's the way they've always done it (i.e. the holdover from the commercial Unix days part)  But for open source applications running on open source operating systems, it's never really been a thing. (compare the two dozen vendors using your /opt directories against the thousands of applications installed on a typical Linux box... that's the point I was trying to make: it would appear quite bizarre for a project like Squeak to start using /opt)
> 
> On Tue, Jun 16, 2026 at 1:44 PM Tobias Pape via Squeak-dev <[email protected]> wrote:
> 
> 
> > On 16. Jun 2026, at 18:44, tim Rowledge <[email protected]> wrote:
> > 
> > 
> > 
> >> On Jun 15, 2026, at 8:55 PM, Phil B <[email protected]> wrote:
> >> 
> >> The /opt tree is a historical artifact of the commercial Unix days... it hasn't been widely used on Linux and is even less used by (open source) applications on Linux.
> > 
> > Really? Dang. I wish people would maybe update purported Serious Documents On Standards sometimes. It would be so useful for users trying to find out The Proper Way!
> 
> 
> /opt is still extremely popular, in particular on enterprise stuff.
> 
> Look at that:
> 
> srv1# ls -1 /opt 
> filepath
> fujitsu
> ibm
> IBM
> knem-1.1.4.90mlnx1
> mellanox
> QLogic_Corporation
> tivoli
> xcat
> Xilinx
> 
> Or that:
> 
> srv2# ls -1 /opt
> MegaRAID
> amsd
> hpe
> 
> Or that:
> 
> srv67# ls -1 /opt 
> at14.0
> at15.0
> ibm
> IBM
> nvidia
> oc-utils
> 
> 
> Just saying.
>         -t
> 
> > 
> > 
> >> For a directory-tree based install like Squeak, the options are generally to package it up for a given distro (which would spray files across the file system... another historical artifact and increasingly out of fashion for GUI apps) or distribute a tarball and let the user decide where to put it.
> > 
> > The latter is kind of how we are doing it right now and I claim it leaves a mess. Hence the suggestion to Not Do That. We also have the problem that there seem to be at least three different structures used for the vm file depending upon where you download from. Looks like a bad idea to me.
> > 
> > 
> >>  The 'modern' Linux approach to dealing with this is one of the packaged app formats (I like AppImage personally) which behave a lot more like OS X applications in that they hide the directory tree in an archive file that gets extracted transparently at runtime out of view of the user.
> > 
> > 
> > Oh, so they finally realized that the Acorn RISC OS application directory approach from *1985* was a good idea. Cool. I can certainly get behind that. Somewhere out there we could possibly find the Smalltalk code I wrote back then-ish for BrouHaHa to save images/changes as an application directory complete with suitable startup scripts etc.  40 year old ideas to the rescue :-)
> > 
> > Another approach someone suggested is dockerising things to make easy to handle packages. I kinda like that idea from my limited experience of Docker, but it may have problems I've not yet encountered?
> > 
> > tim
> > --
> > tim Rowledge; [email protected]; http://www.rowledge.org/tim
> > A)bort, R)etry, I)gnore, V)alium?
> > 
> > 
> > Squeak-dev mailing list -- [email protected]
> > To unsubscribe send an email to [email protected]
> 
> 
> Squeak-dev mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
> 
> 
> Squeak-dev mailing list -- [email protected]
> To unsubscribe send an email to [email protected]

Squeak-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]