Make :wx an optional host extra_application - #80
Merged
Conversation
Only declare `:wx` in `extra_applications(:host)` when the Erlang/OTP
build that will load the release actually contains the `:wx` OTP
application. Without this guard, `mix release` aborts with
`Could not find application :wx` on hosts where OTP was configured
`--without-wx` (e.g. our macOS installer CI workflow, which switched
to `--without-wx` together with switching to `elixir-desktop/desktop_webview`
for the WebView backend).
The Erlang source `src/desktop_wx.erl` already adapts to missing wx
headers via `desktop_wx_stub.exs`, so a host build without `:wx` simply
compiles the header-free stub backend. No behavioral change for
existing users on OTP builds that ship `:wx`.
Tested locally:
- `mix compile --warnings-as-errors` passes on OTP that ships `:wx`
- `:code.lib_dir(:wx) |> is_list()` returns true on standard OTP
- it returns false on OTP built `--without-wx` (gives
`{:error, :bad_name}`, which is not a list)
Co-authored-by: Cursor <cursoragent@cursor.com>
dominicletz
added a commit
that referenced
this pull request
Aug 7, 2026
On some host installs (e.g. the erlef/setup-beam GHA Linux CI used by diode-drive), :code.lib_dir(:wx) reports a valid path AND wx.hrl exists on disk, yet the erlc that mix invokes fails with: can't find include lib "wx/include/wx.hrl" This is the root cause of diode-drive's Linux CI regressions after PR #80. The previous wx_headers_exist?/0 check (File.exists? on the reported lib path) was not strict enough — the file is present yet erlc's include_lib search path does not see it. Replace it with wx_headers_resolvable?/0, which actually invokes erlc against a throwaway module that includes wx.hrl. The probe is the only way to mirror the real compilation step that mix will run. When the probe fails we fall through to the integer-fallback stub, which is sufficient because every host wx call site is now guarded by Code.ensure_loaded?(:wx). The probe uses a stable module/filename pair so erlc's module-name check does not reject the throwaway source. Co-authored-by: Cursor <cursoragent@cursor.com>
dominicletz
added a commit
that referenced
this pull request
Aug 7, 2026
On some host installs (e.g. the erlef/setup-beam GHA Linux CI used by diode-drive), :code.lib_dir(:wx) reports a valid path AND wx.hrl exists on disk, yet the erlc that mix invokes fails with: can't find include lib "wx/include/wx.hrl" This is the root cause of diode-drive's Linux CI regressions after PR #80. The previous wx_headers_exist?/0 check (File.exists? on the reported lib path) was not strict enough — the file is present yet erlc's include_lib search path does not see it. Replace it with wx_headers_resolvable?/0, which actually invokes erlc against a throwaway module that includes wx.hrl. The probe is the only way to mirror the real compilation step that mix will run. When the probe fails we fall through to the integer-fallback stub, which is sufficient because every host wx call site is now guarded by Code.ensure_loaded?(:wx). The probe uses a stable module/filename pair so erlc's module-name check does not reject the throwaway source. Co-authored-by: Cursor <cursoragent@cursor.com>
3 tasks
dominicletz
added a commit
that referenced
this pull request
Aug 8, 2026
…#82) After PR #80 the `extra_applications(:host)` check uses `:code.lib_dir(:wx)` to decide whether to include `:wx` in the generated `desktop.app`. That call consults Erlang's `NameDb` ETS table, which only knows about apps that have been loaded into the running VM. `mix deps.compile` runs each dep's `compile.all` in sequence, and each `compile.all` prunes the code path to only the apps the dep declared (see `Code.delete_paths(current_paths -- loaded_paths)` in `Mix.Tasks.Compile.All`). After the first dep that does not list `:wx` in its apps finishes, `:wx` is removed from both the code path AND from `NameDb`. By the time `desktop.application/0` is evaluated for the `:desktop` dep itself, `code:lib_dir(:wx)` returns `{:error, :bad_name}`, so `:wx` is dropped from `desktop.app` even though the wx app is still on disk and `wx.hrl` is still resolvable. The concrete failure window this opens: 1. `ensure_desktop_wx_erl!/0` runs while `NameDb` is still populated (before `compile.all` prunes), so `wx_headers_resolvable?/0` is true and `src/desktop_wx.erl` is generated with `-include_lib("wx/include/wx.hrl")`. 2. `extra_applications(:host)` runs after pruning, so `:wx` is not added to the app file. 3. `compile.erlang` then fails with `can't find include lib "wx/include/wx.hrl"`. (Side note: `mix deps.compile` passes `--no-code-path-pruning` to disable pruning, but `Mix.Tasks.Compile.All` only honors `--no-prune-code-paths` — different strings — so pruning still happens regardless of the intent.) Fix: probe the filesystem directly, mirroring what `wx_headers_resolvable?/0` already does. The filesystem state is independent of `NameDb` and stays consistent across the build. Tested locally on diode-drive: a fresh `mix deps.compile` previously failed with `can't find include lib "wx/include/wx.hrl"`; after this patch it succeeds and `_build/dev/lib/desktop/ebin/desktop.app` lists `:wx` in its `applications` entry. The behavior on hosts without `:wx` is preserved — `wx_app_on_disk?/0` returns false and the stub backend is used. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On hosts whose Erlang/OTP was configured
--without-wx,mix release(and the higher-levelmix desktop.installer) aborts with:We hit this in
elixir-desktop/diode-drive's macOS installer workflow when we dropped the custom wxWidgets build and switched the WebView backend toelixir-desktop/desktop_webview. The OTP installed on the builder no longer provides the:wxOTP application, butdesktop'sextra_applications(:host)still declares[:wx], so every release validation step fails beforedesktop_wx_stub.exshas any chance to regeneratesrc/desktop_wx.erl.Fix
Only declare
:wxinextra_applications(:host)when:code.lib_dir(:wx)actually returns a chardir. That is the same OTP presence probedesktop_wx_stub.exsalready uses to decide whether to emit the header-free stub Erlang source vs. thewx.hrl-including real source. A host build on OTP built--without-wxnow compiles the stub backend; a host build on OTP that ships:wxkeeps the existing behavior.Diff
Verification
mix compile --warnings-as-errorsclean on OTP that ships:wx.:code.lib_dir(:wx) |> is_list()returnstrueon standard OTP andfalseon OTP built--without-wx(returns{:error, :bad_name}, which is not a list).Why not also remove
:wxfrommix.exsentirelyDesktop.Window.{Macos,Windows,Linux}andDesktop.Webview.wxstill real-call into:wx/wxWidgetswhen available, and the project still recommendsmix desktop.installerworkflows on Linux and Windows where wx is expected to be present. We only want to stop requiring it on platforms where the installer drops wx support.Out of scope
The macOS-side change that motivated this PR (the WebView switch + dropping the wxWidgets build in
binaries_macos.yml) lives inelixir-desktop/diode-drive, not here.