My app was just published on flathub (Install Password Safe on Linux | Flathub), and of course people have started finding issues, mainly related to files not being where they’re expected. Specifically:
The app expects to find a file under /usr/share/passwordsafe/xml/. Looking in the sandbox via ‘flatpak enter’, I see the file under /app/share/passwordsafe/xml. How is this mapped to /usr/share? What’s odd is that the app “sees” the help file under /app/share/passwordsafe/help. Why this but not the xml file?
Even stranger, the localized files are in a clearly incorrect location, e,g,
/app/share/runtime/locale/fr/share/fr/LC_MESSAGES/pwsafe.mo instead of
The project is built using a pretty standard cmake file, and .deb and rpm packages place these files correctly.
Any suggestions on how to approach this would be greatly appreciated.
In the sandbox, the app is mounted at /app, the runtime is mounted at /usr, and various extensions are mounted below those.
flatpak-builder just sets the CMake install prefix to /app. Instead of hardcoding the location of that directory, you should use a config header to get it from the buildsystem: configure_file — CMake 3.28.3 Documentation
Flatpak does set XDG_DATA_DIRS to include /app/share, which may be how the other directory is working.
I’m not an expert on the .Locale extension system, but this seems to match other apps. flatpak-builder defines the Locale extension point automatically with directory=share/runtime/locale and locale-subset=true. This requires that the locale extension contain top-level directories corresponding to each language code. The seemingly redundant path allows locale subsets to also include locale definitions for lib/locale. This is necessary for the platform locale extension at least.
The app gets access to these via symlinks in /app/share/locale. I notice those are mostly missing for your app; only ko is present. I’m not sure what layer creates them, but I’d guess that they’re created for each directory the app creates in /app/share/locale.
Thanks for the prompt reply. I’m still trying to understand what you & Alex wrote about locales. Regarding the help and xml directories:
For help, there’s an environment variable (PWS_HELPDIR) that’s used in the org.pwsafe.pwsafe.yml file to override the default (hardcoded) value of /usr/share/passwordsafe/help/ to /app/share/passwordsafe/help/
I can add the same logic for the xml directory (/usr/share/passwordsafe/xml/ → /app/share/passwordsafe/xml/), but surely there’s a more elegant way to do this?
For example, is there a way to instruct flatpak to install these directly under /usr?
No, this is a fundamental part of flatpak’s design. /usr is the runtime, and /app is the app.
As I mentioned before, the standard approach is to have the buildsystem generate a file containing constants for the install locations. For example you could have DATADIR, which would be set to /app/share for a flatpak build. Then in your code, simply reference DATADIR "/passwordsafe/xml", and you have it as a compile-time constant.
You could alternatively choose to follow the XDG basedir spec and search XDG_DATA_DIRS (with fallback as described in the spec). That depends on whether you want this to be extensible, or to only use the files shipped with the app.
I’ve looked into this a bit more. It is basically as I thought: whatever you install into /app/share/locale is relocated into the extension directory and replaced with a symlink. I’ve determined that the cleanup: /share directive in your wxwidgets module is removing those symlinks. This shouldn’t be possible according to the documentation (it should only apply to that module). I think what’s happening is that wxwidgets also creates directories in /app/share/locale, so it also ‘owns’ those symlinks.
I’m not sure that cleanup: /share is correct anyway though. I’d expect that wxwidgets should have message catalogs for its own strings as well.
flatpak-builder generates this extension automatically by default. You can disable that in your manifest (separate-locales), but you shouldn’t. Flatpak will automatically install the correct subset for the user’s locale.
If you want flatpak to install all languages for you, you can set languages to all or * using flatpak-config.