dirs includes only user directories.
Now I need a system-wide install_dir() that returns /usr/local/share on Linux and X:/Program Files (note the driver letter; or maybe even UNC) on Windows.
dirs includes only user directories.
Now I need a system-wide install_dir() that returns /usr/local/share on Linux and X:/Program Files (note the driver letter; or maybe even UNC) on Windows.
The easiest would be to use conditional compilation with #[cfg(target_os = "linux")] and #[cfg(target_os = "windows")].
On Windows, you can find the Program Files path with the ProgramFiles environment variable.
(If that was the question?).
Damn... The AI gave me that:
pub fn system_wide_apps_dir() -> PathBuf {
cfg_if! {
if #[cfg(target_os = "windows")] {
use windows::Win32::UI::Shell::{FOLDERID_ProgramFiles, KNOWN_FOLDER_FLAG, SHGetKnownFolderPath};
unsafe {
let path_ptr = SHGetKnownFolderPath(&FOLDERID_ProgramFiles, KNOWN_FOLDER_FLAG(0), None).unwrap();
PathBuf::from(path_ptr.to_string().unwrap())
}
} else if #[cfg(target_os = "macos")] {
PathBuf::from("/Applications")
} else {
PathBuf::from("/usr/local/share")
}
}
}
So that env var is fine?
I'm not sure what your question is.
The environment variable I gave you should work, yes. As for what an LLM outputs, I personally don't trust it implicitly, so better check out first.
Both work.
I'm not sure why the AI version is so complicated or requires unsafe code. I see it also requires at least one crate for that cfg_if, apparently. I'd rather use the cfg! macro than using attributes like that inside the code, but it's the syntax required by that crate... Hum. ![]()
That doesn't make sense. Share is for data files. Bin would be for the binary, etc.
The standar dis theoretically Filesystem Hierarchy Standard, but that is relatively outdated, and I recently read about recent efforts to make a new standard that reflect the current status quo. Plus of course distros like NixOS work differently.
In my framework, app: identifies application's installation assets/data (in general, resources you wouldn't want to embed directly into the program, like certain large images and videos). There might be a possibility a creator may use it to store something atypical though.
I'm not sure, but will there ever be a case where I'll need to store a .so for the app? Like libffmpeg.so? Not sure. If that's the case, I'd just need to make creator's installers more complex.
If you are distributing binary programs for Linux I recommend AppImage or Flatpak. AppImage is standalone, no need to install, and Flatpak handles installation and sanaboxing for you.
Don't roll your own install (especially without a reliable uninstaller).
But I somewhat rely on knowing the path where the assets will go ![]()
Hard coding that isn't great, AppImage for example is basically a file system image that gets mounted into a temporary directory and the program ka executed from there, no installation required. Using relative paths from your binary to find your assets would theb work (but check the docs, there may be a differnt preferred way).
You can (on Linux, other Unixes vary) find the path to your own binary by following the symlink /proc/self/exe.
The problem I see around using the executable's directory as a basis is that maybe the executable itself might be in an unstructured directory like /usr/bin/, where all programs are spreaded out together. It might just not work.
I suppose .deb packages (or .rpm, depending on the distro) with preinst/postinst scripts might be safer...
If I optionally produce AppImages for packaging, then there's inconsistency of where app resources will go.
For an AppImage the executable is always embedded in the AppImage itself. The AppImage is basically a small shell script with a compressed file system image appended to it. The shell script mounts the image and executes the binary inside. Inside you would bundle all your data files, shared libraries you depend on, etc.
It is the way to produce a portable Linux executable when you need more than one file. It is not unlike the idea of bundles on Mac, but with a diffrent mechanism.
I appreciate your input. I have a few concerns, organizing by topic.
There are Steam games that periodically update their installation files (assets), usually gigabytes (e.g. PSO2). I don't know what magic Steam makes to make games know their installation directory right; perhaps they determine that by the executable's path, indeed? If that's the case, then I definitely have to change something in my framework, otherwise I won't support Steam. (I'm currently retrieving "Program Files" on Windows and using &'static str for Linux and Mac)
I'm wondering if it's efficient to update a whole AppImage rather than updating just the specific files that changed on an update.
If I change my architecture to use AppImage and also allow installing an app either at the user home or /usr/bin + /usr/local/share, then I'm going to have inconsistencies, again.
(e.g. /usr/bin will yield a exec directory without assets)
std::env::current_exe().unwrap().parent()
// yields the application's installation directory
I suppose this will also work for both Windows ("Install for this user") and Windows ("Install for all users"). For the former, the .exe probably gets inside C:/Users/{user}/AppData/Local/Apps/{application-id} along with its assets.
On Mac it's a bit different, but the exe's dir already helps.
Is that correct?
Thank you for the advise, I also implemented it in my crate.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.