Distributing a buildable executable

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Distributing a buildable executable

Р.С. Алиев
Hello list,

What I have is:
1. Pure Erlang part, a simple gen_server;
2. Several C++ source files + cmake file, intended to be build into a
standalone executable.

I need to distribute both components in a single package, as my
gen_server does open_port({spawn, my_executable}). Moreover, it uses an
environmental variable to find the executable, so I need a way to set it
too (I use the "QT5_EPORT_DIR=~/Path/to/executable rebar3 shell --apps
my_app" command now, but it obviously needs to be generalized somehow).

What is the standard way to distribute such a two-component Erlang package?
Thank you.


--
Regards,
R.S. Aliev
Reply | Threaded
Open this post in threaded view
|

Re: Distributing a buildable executable

Dave Cottlehuber-5
On Tue, 7 Jan 2020, at 16:04, Р.С. Алиев wrote:

> Hello list,
>
> What I have is:
> 1. Pure Erlang part, a simple gen_server;
> 2. Several C++ source files + cmake file, intended to be build into a
> standalone executable.
>
> I need to distribute both components in a single package, as my
> gen_server does open_port({spawn, my_executable}). Moreover, it uses an
> environmental variable to find the executable, so I need a way to set it
> too (I use the "QT5_EPORT_DIR=~/Path/to/executable rebar3 shell --apps
> my_app" command now, but it obviously needs to be generalized somehow).
>
> What is the standard way to distribute such a two-component Erlang package?
> Thank you.
>
>
> --
> Regards,
> R.S. Aliev

Hey RS,

Distribute the binary in your application priv directory, & then however you
deploy your app, you can check for & locate the binary at module load time:

```erl
-module(flux_capacitor).
-on_load(init/0).
...
init() ->
    PrivDir = case code:priv_dir(?MODULE) of
        {error, _} ->
            %% ENOIDEA so make a wild guess
            EbinDir = filename:dirname(code:which(?MODULE)),
            AppPath = filename:dirname(EbinDir),
            filename:join(AppPath, "priv");
        Path ->
            Path
    end,
    do_stuff(filename:join(PrivDir, "executable")).
```

Alternatively for a gen_server you might handle this in Module:init/1.
 
see jiffy and associated rebar.config for how this all gets assembled.

https://github.com/davisp/jiffy/blob/master/src/jiffy.erl#L181-L190

There's a bunch more useful stuff in Paul's nif-examples[1] repo,
albeit targeted for NIFs obviously. If you need to compile the exe,
enc[2] is the best rebar-ish extension I've used for this, but I don't
know off-hand of any cmake-driven builds.

[1]: https://github.com/davisp/nif-examples/tree/master/apps
[2]: https://github.com/davisp/erlang-native-compiler

A+
Dave
Reply | Threaded
Open this post in threaded view
|

Re: Distributing a buildable executable

Р.С. Алиев
08.01.2020 17:31, Dave Cottlehuber пишет:

> On Tue, 7 Jan 2020, at 16:04, Р.С. Алиев wrote:
>> Hello list,
>>
>> What I have is:
>> 1. Pure Erlang part, a simple gen_server;
>> 2. Several C++ source files + cmake file, intended to be build into a
>> standalone executable.
>>
>> I need to distribute both components in a single package, as my
>> gen_server does open_port({spawn, my_executable}). Moreover, it uses an
>> environmental variable to find the executable, so I need a way to set it
>> too (I use the "QT5_EPORT_DIR=~/Path/to/executable rebar3 shell --apps
>> my_app" command now, but it obviously needs to be generalized somehow).
>>
>> What is the standard way to distribute such a two-component Erlang package?
>> Thank you.
>>
>>
>> --
>> Regards,
>> R.S. Aliev
>
> Hey RS,
>
> Distribute the binary in your application priv directory, & then however you
> deploy your app, you can check for & locate the binary at module load time:
>
> ```erl
> -module(flux_capacitor).
> -on_load(init/0).
> ...
> init() ->
>      PrivDir = case code:priv_dir(?MODULE) of
>          {error, _} ->
>              %% ENOIDEA so make a wild guess
>              EbinDir = filename:dirname(code:which(?MODULE)),
>              AppPath = filename:dirname(EbinDir),
>              filename:join(AppPath, "priv");
>          Path ->
>              Path
>      end,
>      do_stuff(filename:join(PrivDir, "executable")).
> ```
>
> Alternatively for a gen_server you might handle this in Module:init/1.
>  
> see jiffy and associated rebar.config for how this all gets assembled.
>
> https://github.com/davisp/jiffy/blob/master/src/jiffy.erl#L181-L190
>
> There's a bunch more useful stuff in Paul's nif-examples[1] repo,
> albeit targeted for NIFs obviously. If you need to compile the exe,
> enc[2] is the best rebar-ish extension I've used for this, but I don't
> know off-hand of any cmake-driven builds.
>
> [1]: https://github.com/davisp/nif-examples/tree/master/apps
> [2]: https://github.com/davisp/erlang-native-compiler
>
> A+
> Dave
>

Hey Dave,

Thank you for the hints. I have no problem with NIFs and definitely
wouldn't want to go that way here. The binary in question is intended to
act as a server, without any knowledge of the client's particularities
(thence erlang:port_command/2 etc).

The idea i was toying in my head is to just run cmake && cp in the said
gen_server's init. But that seems kinda unholy. So, i'll try enc.

Thanks again. The source code is at https://bitbucket.org/r_s_o/epona,
if you are interested. It is Qt5 GUI builder tool, somewhat similar to
wxErlang, but simpler and much more declarative (see demo_gs.erl). Any
suggestions are greatly appreciated.


--
Regards,
R.S. Aliev