{"id":37987,"date":"2026-01-01T01:38:17","date_gmt":"2026-01-01T06:38:17","guid":{"rendered":"https:\/\/twiar.net\/?p=37987"},"modified":"2025-12-14T01:39:52","modified_gmt":"2025-12-14T06:39:52","slug":"via-hackaday-creating-user-friendly-installers-across-operating-systems","status":"publish","type":"post","link":"https:\/\/twiar.net\/2026\/01\/01\/via-hackaday-creating-user-friendly-installers-across-operating-systems\/","title":{"rendered":"via Hackaday: Creating User-Friendly Installers Across Operating Systems"},"content":{"rendered":"<div><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"484\" src=\"https:\/\/hackaday.com\/wp-content\/uploads\/2019\/09\/ProgrammingSystem.jpg?w=800\" class=\"attachment-large size-large wp-post-image\" alt=\"\" data-attachment-id=\"375786\" data-permalink=\"https:\/\/hackaday.com\/2019\/09\/10\/why-ada-is-the-language-you-want-to-be-programming-your-systems-with\/programmingsystem\/\" data-orig-file=\"https:\/\/hackaday.com\/wp-content\/uploads\/2019\/09\/ProgrammingSystem.jpg\" data-orig-size=\"3000,1815\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ProgrammingSystem\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/hackaday.com\/wp-content\/uploads\/2019\/09\/ProgrammingSystem.jpg?w=400\" data-large-file=\"https:\/\/hackaday.com\/wp-content\/uploads\/2019\/09\/ProgrammingSystem.jpg?w=800\" \/><\/div>\n<p>After you have written the code for some awesome application, you of course want other people to be able to use it. Although simply directing them to the source code on GitHub or similar is an option, not every project lends itself to the traditional <code>configure &amp;&amp; make &amp;&amp; make install<\/code>, with often dependencies being the sticking point.<\/p>\n<p>Asking the user to install dependencies and set up any filesystem links is an option, but having an installer of some type tackle all this is of course significantly easier. Typically this would contain the precompiled binaries, along with any other required files which the installer can then copy to their final location before tackling any remaining tasks, like updating configuration files, tweaking a registry, setting up filesystem links and so on.<\/p>\n<p>As simple as this sounds, it comes with a lot of gotchas, with Linux distributions in particular being a tough nut. Whereas on MacOS, Windows, Haiku and many other OSes you can provide a single installer file for the respective platform, for Linux things get interesting.<\/p>\n<p><span><\/span><\/p>\n<h2>Windows As Easy Mode<\/h2>\n<p>For all the flak directed at Windows, it is hard to deny that it is a stupidly easy platform to target with a binary installer, with equally flexible options available on the side of the end-user. Although Microsoft has nailed down some options over the years, such as enforcing the user\u2019s home folder for application data, it\u2019s still among the easiest to install an application on.<\/p>\n<p>While working on the <a href=\"https:\/\/github.com\/MayaPosch\/NymphCast\" target=\"_blank\">NymphCast project<\/a>, I found myself looking at a pleasant installer to wrap the binaries into, initially opting to use the <a href=\"https:\/\/nsis.sourceforge.io\/Main_Page\" target=\"_blank\">NSIS<\/a> (Nullsoft Scriptable Install System) installer as I had seen it around a lot. While this works decently enough, you do notice that it\u2019s a bit crusty and especially the more advanced features can be rather cumbersome.<\/p>\n<p>This is where a friend who was helping out with the project suggested using the more modern <a href=\"https:\/\/en.wikipedia.org\/wiki\/Inno_Setup\" target=\"_blank\">Inno Setup<\/a> instead, which is rather like the well-known <a href=\"https:\/\/en.wikipedia.org\/wiki\/InstallShield\" target=\"_blank\">InstallShield<\/a> utility, except OSS and thus significantly more accessible. Thus the pipeline on Windows became the following:<\/p>\n<ol>\n<li>Install dependencies using <a href=\"https:\/\/vcpkg.io\/\" target=\"_blank\">vcpkg<\/a>.<\/li>\n<li>Compile project using NMake and the MSVC toolchain.<\/li>\n<li>Run the Inno Setup script to build the <code>.exe<\/code> based installer.<\/li>\n<\/ol>\n<p>Installing applications on Windows is helped massively both by having a lot of freedom where to install the application, including on a partition or disk of choice, and by having the start menu structure be just a series of folders with shortcuts in them.<\/p>\n<p>The Qt-based NymphCast Player application\u2019s <a href=\"https:\/\/github.com\/MayaPosch\/NymphCast\/blob\/master\/player\/NymphCastPlayer\/installer\/Setup-NymphCastPlayer-dynamic.iss\" target=\"_blank\"><code>.iss<\/code> file<\/a> covers essentially such a basic installation process, while the one for NymphCast Server also adds the option to download a pack of wallpaper images, and asks for the type of server configuration to use.<\/p>\n<p>Uninstalling such an application basically reverses the process, with the uninstaller installed alongside the application and registered in the Windows registry together with the application\u2019s details.<\/p>\n<h2>MacOS As Proprietary Mode<\/h2>\n<p>Things get a <a href=\"https:\/\/developer.apple.com\/documentation\/xcode\/packaging-mac-software-for-distribution\" target=\"_blank\">bit weird<\/a> with MacOS, with many application installers coming inside a DMG image or PKG file. The former is just a disk image that can be used for <a href=\"https:\/\/stackoverflow.com\/questions\/96882\/how-do-i-create-a-nice-looking-dmg-for-mac-os-x-using-command-line-tools\" target=\"_blank\">distributing applications<\/a>, and the user is generally provided with a way to drag the application into the <code>Applications<\/code> folder. The PKG file is more of a typical installer as on Windows.<\/p>\n<p>Of course, the problem with anything MacOS is that Apple really doesn\u2019t want you to do anything with MacOS if you\u2019re not running MacOS already. This can <a href=\"https:\/\/stackoverflow.com\/questions\/283480\/how-to-build-native-mac-os-x-installer-on-a-non-mac-platform?rq=3\" target=\"_blank\">be worked around<\/a>, but just getting to the point of compiling for MacOS without running XCode on MacOS on real Apple hardware is a bit of a fool\u2019s errand. Not to mention Apple\u2019s insistence on signing these packages, if you don\u2019t want the end-user to have to jump through hoops.<\/p>\n<p>Although I have built both iOS and OS X\/MacOS applications in the past \u2013 mostly for commercial projects \u2013 I decided to not bother with compiling or testing my projects like NymphCast for Apple platforms without easy access to an Apple system. Of course, something like <a href=\"https:\/\/brew.sh\/\" target=\"_blank\">Homebrew<\/a> can be a viable alternative to the One True Apple Way<img decoding=\"async\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/72x72\/2122.png\" alt=\"\u2122\" class=\"wp-smiley\" \/> if you merely want to get OSS o MacOS. I did add basic support for Homebrew in NymphCast, but without a MacOS system to test it on, who knows whether it works.<\/p>\n<h2>Anything But Linux<\/h2>\n<p>The world of desktop systems is larger than just Windows, MacOS and Linux, of course. Even mobile OSes like iOS and Android can be considered to be \u2018desktop OSes\u2019 with the way that they\u2019re being used these days, also since many smartphones and tablets can be hooked up to to a larger display, keyboard and mouse.<\/p>\n<p>How to <a href=\"https:\/\/hackaday.com\/2025\/09\/04\/bootstrapping-android-development-a-survival-guide\/\">bootstrap Android<\/a> development, and how to develop <a href=\"https:\/\/hackaday.com\/2025\/09\/15\/going-native-with-androids-native-development-kit\/\">native Android<\/a> applications has been covered before, including putting APK files together. These are the typical Android installation files, akin to other package manager packages. Of course, if you wish to publish to something like the Google Play Store, you\u2019ll be forced into using app bundles, as well as various ways to signing the resulting package.<\/p>\n<p>The idea of using a package for a built-in package manager instead of an executable installer is a common one on many platforms, with iOS and kin being similar. On FreeBSD, which also got a NymphCast port, you\u2019d create a bundle for the <code>pkg<\/code> package manager, although you can also whip up an installer. In the case of NymphCast there is a \u2018universal installer\u2019 built into the <a href=\"https:\/\/github.com\/MayaPosch\/NymphCast\/blob\/master\/src\/server\/Makefile\" target=\"_blank\">Makefile<\/a> after compilation via the fully automated <code>setup.sh<\/code> shell script, using the fact that OSes like Linux, FreeBSD and even Haiku are quite similar on a folder level.<\/p>\n<p>That said, the Haiku port of NymphCast is still as much of a Beta as Haiku itself, as detailed <a href=\"https:\/\/mayaposch.wordpress.com\/2024\/01\/20\/porting-nymphcast-to-the-haiku-operating-system\/\" target=\"_blank\">in the write-up<\/a> which I did on the topic. Once Haiku is advanced enough I\u2019ll be creating packages for its <code>pkgman<\/code> package manager as well.<\/p>\n<h2>The Linux Chaos Vortex<\/h2>\n<p><a href=\"https:\/\/hackaday.com\/wp-content\/uploads\/2022\/09\/standards.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"555813\" data-permalink=\"https:\/\/hackaday.com\/2022\/10\/05\/the-state-of-the-sbc-interface-ecosystem-is-it-time-to-design-a-standard\/standards-3\/\" data-orig-file=\"https:\/\/hackaday.com\/wp-content\/uploads\/2022\/09\/standards.png\" data-orig-size=\"500,283\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"standards\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/hackaday.com\/wp-content\/uploads\/2022\/09\/standards.png?w=400\" data-large-file=\"https:\/\/hackaday.com\/wp-content\/uploads\/2022\/09\/standards.png?w=500\" class=\"size-medium wp-image-555813 alignright\" src=\"https:\/\/hackaday.com\/wp-content\/uploads\/2022\/09\/standards.png?w=400\" alt=\"\" width=\"400\" height=\"226\" \/><\/a>There is a simple, universal way to distribute software across Linux distributions, and it\u2019s called the \u2018tar.gz method\u2019, referring to the time-honored method of distributing source as a tarball, for local compilation. If this is not what you want, then there is the universal RPM installation format which died <a href=\"https:\/\/hackaday.com\/2025\/06\/03\/my-winter-of-99-the-year-of-the-linux-desktop-is-always-next-year\/\">along with the Linux Standard Base<\/a>. Fortunately many people in the Linux ecosystem have worked tirelessly to create new standards which will <a href=\"https:\/\/en.wikipedia.org\/wiki\/List_of_software_package_management_systems\" target=\"_blank\">definitely, absolutely, totally resolve<\/a> the annoying issue of having to package your applications into RPMs, DEBs, Snaps, Flatpaks, ZSTs, TBZ2s, DNFs, YUMs, and other easily remembered standards.<\/p>\n<p>It is this complete and utter chaos with Linux distros which has made me not even try to create packages for these, and instead offer only the universal <code>.tar.gz<\/code> installation method. After un-tar-ing the server code, simply run <code><a href=\"https:\/\/github.com\/MayaPosch\/NymphCast\/blob\/master\/setup.sh\" target=\"_blank\">setup.sh<\/a><\/code> and lean back while it compiles the thing. After that, run <code>install_linux.sh<\/code> and presto, the whole shebang is installed without further ado. I also provided an <code>uninstall_linux.sh<\/code> script to complete the experience.<\/p>\n<p>That said, at least one Linux distro has picked up NymphCast and its dependencies like Libnymphcast and NymphRPC into their repository: <a href=\"https:\/\/pkgs.alpinelinux.org\/package\/edge\/community\/x86_64\/nymphcast\" target=\"_blank\">Alpine Linux.<\/a> Incidentally FreeBSD also has <a href=\"https:\/\/www.freshports.org\/multimedia\/nymphcast\/\" target=\"_blank\">an up to date package<\/a> of NymphCast in its repository. I\u2019m much obliged to these maintainers for providing this service.<\/p>\n<p>Perhaps the lesson here is that if you want to get your neatly compiled and packaged application on all Linux distributions, you just need to make it popular enough that people want to use it, so that it ends up getting picked up by package repository contributors?<\/p>\n<h2>Wrapping Up<\/h2>\n<p>With so many details to cover, there\u2019s also the easily forgotten topic that was so prevalent in the Windows installer section: integration with the desktop environment. On Windows, the Start menu is populated via simple shortcut files, while one sort-of standard on Linux (and FreeBSD as corollary) are <a href=\"https:\/\/specifications.freedesktop.org\/desktop-entry\/latest-single\/\" target=\"_blank\">Freedesktop\u2019s<\/a> <a href=\"https:\/\/wiki.archlinux.org\/title\/Desktop_entries\" target=\"_blank\">XDC Desktop Entry<\/a> files. Or <code>.desktop<\/code> files for short, which purportedly should give you a similar effect.<\/p>\n<p>Only that\u2019s not how anything works with the Linux ecosystem, as every single desktop environment has its own ideas on how these files should be interpreted, where they should be located, or whether to ignore them completely. My own experiences there are that relying on them for more advanced features, such as auto-starting a graphical application on boot (which cannot be done with Systemd, natch) without something throwing an XDG error or not finding a display is basically a fool\u2019s errand. Perhaps that things are better here if you use KDE Plasma as DE, but this was an installer thing that I failed to solve after months of trial and error.<\/p>\n<p>Long story short, OSes like Windows are pretty darn easy to install applications on, MacOS is okay as long as you have bought into the Apple ecosystem and don\u2019t mind hanging out there, while FreeBSD is pretty simple until it touches the Linux chaos via X11 and graphical desktops. Meanwhile I\u2019d strongly advise to only distribute software on Linux as a tarball, for your sanity\u2019s sake.<\/p>\n<p> Blog \u2013 Hackaday <a href=\"https:\/\/hackaday.com\/2025\/12\/11\/creating-user-friendly-installers-across-operating-systems\/\" target=\"_blank\" class=\"feedzy-rss-link-icon\">Read More<\/a><\/p>\n<p>\u200b<\/p>","protected":false},"excerpt":{"rendered":"<p>After you have written the code for some awesome application, you of course want other&#8230;<\/p>\n","protected":false},"author":5,"featured_media":14636,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"rop_custom_images_group":[],"rop_custom_messages_group":[],"rop_publish_now":"initial","rop_publish_now_accounts":{"twitter_16139062_16139062":""},"rop_publish_now_history":[],"rop_publish_now_status":"pending","footnotes":""},"categories":[176,109],"tags":[5289,110,115,1438,1500],"class_list":["post-37987","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-computers","category-hackaday","tag-freebsd","tag-hackaday","tag-linux","tag-macos","tag-windows"],"_links":{"self":[{"href":"https:\/\/twiar.net\/wp-json\/wp\/v2\/posts\/37987","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/twiar.net\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/twiar.net\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/twiar.net\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/twiar.net\/wp-json\/wp\/v2\/comments?post=37987"}],"version-history":[{"count":1,"href":"https:\/\/twiar.net\/wp-json\/wp\/v2\/posts\/37987\/revisions"}],"predecessor-version":[{"id":38092,"href":"https:\/\/twiar.net\/wp-json\/wp\/v2\/posts\/37987\/revisions\/38092"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/twiar.net\/wp-json\/wp\/v2\/media\/14636"}],"wp:attachment":[{"href":"https:\/\/twiar.net\/wp-json\/wp\/v2\/media?parent=37987"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/twiar.net\/wp-json\/wp\/v2\/categories?post=37987"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/twiar.net\/wp-json\/wp\/v2\/tags?post=37987"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}