saleyn / erlexec

Execute and control OS processes from Erlang/OTP
https://hexdocs.pm/erlexec/readme.html
Other
523 stars 138 forks source link

Issue on ARM Mac #177

Closed akoutmos closed 1 week ago

akoutmos commented 3 weeks ago

First of all, thanks for the awesome library! This has been super handy in a number of my projects!

I am currently having an issue though on my ARM Mac when running Elixir projects that depend on erlexec. The problem I am seeing is:

$ mix test
Generated mjml_eex app

09:33:07.207 [notice] Application erlexec exited: :exec_app.start(:normal, []) returned an error: shutdown: failed to start child: :exec
    ** (EXIT) bad return value: ~c"Cannot find file ./_build/test/lib/erlexec/priv/false: no such file or directory"

09:33:07.217 [notice] Application telemetry exited: :stopped

09:33:07.217 [notice] Application phoenix_html exited: :stopped

09:33:07.217 [notice] Application eex exited: :stopped

09:33:07.217 [notice] Application mjml exited: :stopped

09:33:07.217 [notice] Application rustler_precompiled exited: :stopped

09:33:07.217 [notice] Application castore exited: :stopped
** (Mix) Could not start application erlexec: :exec_app.start(:normal, []) returned an error: shutdown: failed to start child: :exec
    ** (EXIT) bad return value: ~c"Cannot find file ./_build/test/lib/erlexec/priv/false: no such file or directory"

I think the problem is here:

https://github.com/saleyn/erlexec/blob/master/src/exec.erl#L721-L723

The call to os:find_executable/1 is returning false since Arch turns out to be aarch64-apple-darwin23.2.0 and not arm64-apple-darwin23.2.0 like what is actually in the erlexec priv dir. Would this require updates to the Makefile to write the artifact to the correct directory or an update to the call to os:find_executable/1 to find the executable?

Thank you in advance for any insight!

saleyn commented 3 weeks ago

What does erlang:system_info(system_architecture) return in your case? And also what's the output of ls -l priv

akoutmos commented 3 weeks ago
1> erlang:system_info(system_architecture).
"aarch64-apple-darwin23.2.0"
saleyn commented 3 weeks ago

Can you also run:

  1. make info
  2. echo $CXX
akoutmos commented 3 weeks ago

Here is the directory structure inside the Elixir _build directory for my open source project:

image

Here is the output from make info:

$ make info
SOURCES: ei++.cpp exec.cpp exec_impl.cpp
OBJECTS: ei++.o exec.o exec_impl.o
OUTPUT:  /Users/akoutmos/Documents/opensource/mjml_eex/deps/erlexec/priv/arm64-apple-darwin23.5.0/exec-port
OUT_DIR: /Users/akoutmos/Documents/opensource/mjml_eex/deps/erlexec/priv/arm64-apple-darwin23.5.0/

And echo $CXX returns nothing.

saleyn commented 3 weeks ago

This is strange - in the Makefile the target directory is constructed using the erlang:system_info(system_architecture) function call, yet when you run this function in the Erlang shell you get a different value. Can you investigate by putting some more echo lines in the info target of c_src/Makefile, as this doesn't make sense, and I can't reproduce it?

akoutmos commented 1 week ago

Sorry for the delay...finally got some time tonight to play around with this and investigate tonight. It looks like the problem is stemming from the MARCH variable. I added the following make target print-%: ; @echo $* = $($*) and printed out the following variables in the Makefile:

$ make print-MARCH
MARCH = arm64-apple-darwin23.5.0

$ make print-TARGET
TARGET = arm64-apple-darwin23.5.0

$ make print-CXX
CXX = c++

$ c++ -dumpmachine
arm64-apple-darwin23.5.0

$ make print-EXE_OUTPUT
EXE_OUTPUT = .../mjml_eex/deps/erlexec/priv/arm64-apple-darwin23.5.0/exec-port

It looks like the else branch is being taken below and that is setting the TARGET variable to the result of c++ -dumpmachine which is arm64-apple-darwin23.5.0.

ifeq ($(CXX),)
  CXX     := g++
  TARGET  := $(shell erl -noshell -noinput -eval "io:format("~s\n", [erlang:system_info(system_architecture)]), halt(0).")
else
  TARGET  := $(shell $(CXX) -dumpmachine)
endif

I am able to get my project to work again by removing that whole if-else block and replacing it with TARGET := $(shell erl -noshell -noinput -eval 'io:format("~s\n", [erlang:system_info(system_architecture)]), halt(0).'). Not sure if that breaks other things down stream so I'll defer to you on that one heh.

capitalist commented 1 week ago

Can confirm this edit worked for me as well.

saleyn commented 1 week ago

Committed the fix.

akoutmos commented 5 days ago

Thank you for incorporating the fix so quickly! Appreciate it :).