Erlang: Location of *.hrl files in multiple applications - erlang

I'm developing a series of related applications that will eventually be integrated into a single release. Several of the applications share identical record structures.
Should I:
a) Duplicate the *.hrl files that define the record structure in the include directory of each of the applications?
b) Put a single file somewhere else in my application tree--- and, if so where?
Here's my current tree:
zpt$
apps
app1
ebin
include
myrecords.hrl
priv
src
app2
ebin
include
myrecords.hrl
priv
src
etc
Many thanks,
LRP

One approach I tried was to create an application which doesn't do anything, but contains the record definitions common to multiple projects. Then I used rebar to include it as a dependency. When including the hrl files, I use the include_lib syntax. That syntax allows you to include hrl files from another application.
app
ebin
include
priv
src
some_src.erl
deps
common_hrl_app
include
common_records.hrl
src
ebin
other_dep_app
src
other_src.erl
.
.
.
include_lib example which could appear in either some_src.erl or other_src.erl:
-include_lib("common_hrl_app/include/common_records.hrl").
I like this approach because:
It plays nicely with the rebar dependency system
It allows me to track the hrls in one place in version control
I can version this application, which allows me to pull specific versions if I want a new application to be compatible with another using the same records.
Answering questions from the comments:
I have a skeleton app file in the ebin directory which specifies the name and version of the application so rebar can verify the version. Here's an example
{application,common_hrl_app,
[{description,[]},
{vsn,"1"},
{registered,[]},
{applications,[kernel,stdlib]},
{env,[]},
{modules,[]}]}.
With rebar, you have the top level application, which can have multiple applications as dependencies. When rebar fetches these dependencies, it places them in the deps directory. If any of those applications has their own dependencies, those are also fetched to the deps directory, and so on. There isn't an infinitely nested hierarchy of deps directories.

Related

Can you use Java JPackage to create own Windows installer without using its way of running application

Background, I currently use Izpack for my Windows installer, I bundle a java runtime and use winrun4j as a wrapper both for the installation and the actual program once installed. It worked for a long time but there are a number of problems with the installer that I have not been able to solve and have been looking to replace it.
Oracle now provide the JPackage installer so it seems like a sensible choice. But the folder structure created by the installer is different to what I currently have, I have a number of config and non java files and I have not been able to get the .exe that JPackage creates to do anything.
So is it possible to use JPackage to create the installer but in a strcuture better matching my existing structure, and use continue to use WInRun4j to actyally run my application
Existing Folder Structure
ROOT
---App.exe
---Config Files
---lib
-------jar files
---JVM64
------- Java runtime
---help
JPackage structure
ROOT
---App.exe
---Runtime Dlls
---app
----- jar files
Config files
--runtime
------Java runtime
------Runtime Dlls (again)
The structure of directories generated by jpackage is mainly set up for you and does not seem possible to change, and makes installation of Java app dependencies very easy with self contained JRE. The basic structure for Windows is as you say:
ROOT
---App.exe (for --main-class parameter)
---xyz.exe (for each --add-launcher parameter)
---Runtime Dlls (these appear to be unused except for applauncher.dll, see SO 62607300)
---app/
------App.cfg (for --main-class)
------xyz.cfg (for per --add-launcher)
---runtime/
------Java runtime
------Runtime Dlls
With --input and --main-jar params you are free to setup additional directory structure under app/ folder for anything else you want for your application. So if you used lib/myappjar.jar it would add:
---app/
-------lib/
----------myappjar.jar
If you used --input build\mypath it would copy the entire tree of files under that folder, so if build\mypath dir contained
bin/
---Scripts
---xyz.properties
README.txt
Then app would also contain:
---app/
------bin/
---------Scripts
---------xyz.properties
------README.txt
By the way the Runtime DLLs placed at top level appear to be copies of some of the DLLs under runtime/bin
[https://stackoverflow.com/questions/62607300/why-is-java-jpackage-installing-windows-dll-files-in-two-places]

How to execute an application with nested module loading in Erlang?

I am creating an erlang application named (app_main) that will be initializing two other erlang applications ( app_1 and app_2 ):
Following is the structure of the code. Notice that app_1 and app_2 are under the deps directory and each have their own deps directory, which expand into further other nested references to other code directory structures, etc...
/app_main
/ebin
/main.erl
/deps
/app_1
/ebin
/deps
/...
/app_2
/ebin
/deps
/...
To start my app_main application, I am issuing the following command:
erl -pa ./ebin ./deps/*/ebin ./deps/*/deps/*/ebin -s app_main
The problem is that I need to know how many levels of nested deps references I may have... This sounds a bit illogical to me and I am wondering if there are better ways to achieve this.
For instance, would rebar be useful identifying nested rebar configs and add all dependencies to the app_main's deps directory automatically ?
Rebar is very useful for managing dependencies. You can define app 1 and 2 as dependencies for your main app and, assuming app 1 and 2 have their dependencies defined in Rebar, it will install them and their dependencies in your deps folder
See Rebar's documentation here: https://github.com/basho/rebar/wiki/Dependency-management
How are you specifying these dependencies, where do they come from, and how are you compiling them? When you're using 3rd party applications they will, in general, manage their own dependencies. Therefore, you should only ever to have start the shell like this:
erl -pa ebin deps/*/ebin
Both Rebar and erlang.mk are great tools for managing your applications and their dependencies.

How to properly use the deps folder in an Erlang project?

I am coming from the assumption that the deps folder of an erlang project should include symbolic links that point to other projects and applications, so all modules from that project can be accessed/visible.
For example, My project named project_final should access modules from project_a and application_b. The directory structure of them is as follows:
NOTICE: because I am using GIT, the projects have a double structure, so they are not direct siblings to each other, but instead they are placed under /projects/project_X/projectX/etc... I believe this is a problem. Any better suggestions how to manage this ?
/projects/project_a/project_a : contains ( ebin, include, src )
/projects/application_b/application_b : contains ( ebin, include, src )
/project/pro_final:
deps : has symbolic links that point to project_a and application_b
ebin
include
src : contain modules that use project_a and applicabion_b module's functions, but gives exception error: undefined function.
How I am executing the project_final test module is by:
cd /projects
erl -env ERL_LIBS "."
myprojectfinalmodule:test().
** exception error: undefined function project_a:test/0
The project_a:test module is exported and correct.
The deps directory is a Rebar convention, and should probably not be managed in any other way except through Rebar. If you're not using Rebar, don't put dependencies in a subdirectory of the application, put your individual applications under a common lib/ directory instead and use the ERL_LIBS environment variable (see http://erlang.org/doc/man/code.html) to tell Erlang where to look for applications.

Is there a convention for placing rebar in the search path?

I'm attempting to understand how to build a multiple-application Erlang OTP release using Rebar.
My applications include Webmachine, Riak, and a few applications of my own devising. So far, I have been running Rebar successfully in the application root directory. But the Rebar bootstrap program suggests that there may be a better way. E.g.:
"You now have a self-contained script called "rebar" in
your current working directory. Place this script anywhere in your path
and you can use rebar to build OTP-compliant apps."
I can think of several ways to do this. But I'm wondering:
Is there is a preferred convention: e.g., placing Rebar in an .erlang file, /usr/local/bin, etc., etc.?
Many thanks,
LRP
I keep a copy in /usr/local/bin, which I use when creating new apps. For example:
$ rebar create-app appid=myapp
All of my projects are built with rebar by placing the binary in the root directory of my project and referencing it locally in my Makefile as seen here. As of this writing, this seems to be the convention the community has adopted. For example, nitrogen, mochiweb, ibrowse, and erlydtl are all built this way.
Personally, I'm not a big fan of including the rebar binary with every project but I don't see a good alternative. It makes life easier for people that either don't have rebar in their path, or don't have an updated version in their path.
I suspect this is a temporary situation. Eventually the rebar project will start to have fewer commits, and we'll all agree to keep a copy in our path. At that point we can all stop including it. Of course, if your projects are only going to be used by you, this is a non-issue.

"Bundling" external libraries in Erlang?

I have an erlang application I have been writing which uses the erldis library for communicating with redis.
Being a bit of a newbie with actually deploying erlang applications to production, I wanted to know if there was anyway to 'bundle' these external libraries with the application rather than installing into my system wide /usr/lib/erlang/lib/ folder.
Currently my directory structure looks like...
\
--\conf
--\ebin
--\src
I have a basic Makefile that I stole from a friend's project, but I am unsure how to write them properly.
I suspect this answer could involve telling me how to write my Makefile properly rather than just which directory to plonk some external library code into.
You should really try to avoid project nesting whenever possible. It can lead to all sorts of problems because of how module/application version is structured within Erlang.
In my development environment, I do a few things to simplify dependancies and multiple developed projects. Specifically, I keep most of my projects sourced in a dev directory and create symlinks into an elibs dir that is set in the ERL_LIBS environmental variables.
~/dev/ngerakines-etap
~/dev/jacobvorreuter-log_roller
~/dev/elib/etap -> ~/dev/ngerakines-etap
~/dev/elib/log_roller -> ~/dev/jacobvorreuter-log_roller
For projects that are deployed, I've either had package-rpm or package-apt make targets that create individual packages per project. Applications get boot scripts and init.d scripts for easy start/stop controls but libraries and dependancy projects just get listed as package dependencies.
I use mochiweb-inspired style. To see example of this get your copy of mochiweb:
svn checkout http://mochiweb.googlecode.com/svn/trunk/ mochiweb
and use
path/to/mochiweb/scripts/new_mochiweb.erl new_project_name
to create sample project of the structure (feel free to delete everything inside src afterwards and use it for your project).
It looks like this:
/
/ebin/
/deps/
/src/
/include/
/support/
/support/include.mk
Makefile
start.sh
ebin contains *.beam files
src contains ***.erl files and local *.hrl files
include contains global *.hrl files
deps contains symlinks to root directories of dependencies
Makefile and include.mk takes care of including appropriate paths when project is built.
start.sh takes care of including appropriate paths when project is run.
So using symlinks in deps directory you are able to fine tune the versions of libraries you use for every project. It is advised to use relative paths, so afterwards it is enough to rsync this structure to the production server and run it.
On more global scale I use the following structure:
~/code/erlang/libs/*/
~/code/category/project/*/
~/code/category/project/*/deps/*/
Where every symlink in deps points to the library in ~/code/erlang/libs/ or to another project in the same category.
The simplest way to do this would be to just create a folder named erldir and put the beams you need into it and then in your start script just use the -pa flag to the erlang runtime to point out where it should fetch the beams.
The correct way (at least if you buy into the OTP distribution model) would be to create a release using reltool (http://www.erlang.org/doc/man/reltool.html) or systools (http://www.erlang.org/doc/man/systools.html) which includes both your application and erldis.
Add the external libraries that you need, anywhere you want them, and add them to your ERL_LIBS environment variable. Separate the paths with colon in unix or semicolon in dos.
Erlang will add the "ebin"-named subdirs to its code loading path.
Have your *.app file point out the other applications it depends on.
This is a good halfway-there approach for setting up larger applications.
Another way is put your lib path in ~/.erlang.
code:add_pathz("/Users/brucexin/sources/mochiweb/ebin").
code:add_pathz("/Users/brucexin/sources/webnesia/ebin").
code:add_pathz("./ebin").
code:add_pathz("/Users/brucexin/sources/erlang-history/ebin/2.15.2").

Resources