Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

erlang.mk bug #50

Closed
OvermindDL1 opened this issue Oct 11, 2018 · 14 comments
Closed

erlang.mk bug #50

OvermindDL1 opened this issue Oct 11, 2018 · 14 comments

Comments

@OvermindDL1
Copy link

Attempting to run make escript on RedHat linux (which is locked to make version GNU Make 3.82 with no alternatives on the main installs), and running make escript gives this:

╰─➤  make escript
erlang.mk:30: Please upgrade to GNU Make 4 or later: https://erlang.mk/guide/installation.html
erlang.mk:30: Please upgrade to GNU Make 4 or later: https://erlang.mk/guide/installation.html
 GEN    escript-zip

WARNING: No more files
gradualizer

make: *** [escript-zip] Error 1

And the supplied link is useless as it says nothing about how to workaround the issue on modern RedHat installs (which regulate what can and cannot be installed).

@OvermindDL1
Copy link
Author

Perhaps switching to rebar3 (or even Elixir's mix, which works quite well for erlang projects as well) would be better?

@OvermindDL1
Copy link
Author

Found a verbosity switch:

╰─➤  V=2 make escript-zip
erlang.mk:30: Please upgrade to GNU Make 4 or later: https://erlang.mk/guide/installation.html
set -x; rm -f /home/username/tools/Gradualizer/.erlang.mk/deps.log
+ rm -f /home/username/tools/Gradualizer/.erlang.mk/deps.log
set -x; rm -f /home/username/tools/Gradualizer/.erlang.mk/apps.log
+ rm -f /home/username/tools/Gradualizer/.erlang.mk/apps.log
set -x; mkdir -p /home/username/tools/Gradualizer/.erlang.mk
+ mkdir -p /home/username/tools/Gradualizer/.erlang.mk
set -x; set -e; for dep in  ; do \
        mkdir -p $dep/ebin; \
done
+ set -e
set -x; set -e; for dep in  ; do \
        if grep -qs ^$dep$ /home/username/tools/Gradualizer/.erlang.mk/apps.log; then \
                :; \
        else \
                echo $dep >> /home/username/tools/Gradualizer/.erlang.mk/apps.log; \
                make -C $dep IS_APP=1; \
        fi \
done
+ set -e
set -x; mkdir -p /home/username/tools/Gradualizer/.erlang.mk
+ mkdir -p /home/username/tools/Gradualizer/.erlang.mk
set -x; set -e; for dep in  ; do \
        if grep -qs ^$dep$ /home/username/tools/Gradualizer/.erlang.mk/deps.log; then \
                :; \
        else \
                echo $dep >> /home/username/tools/Gradualizer/.erlang.mk/deps.log; \
                if [ -f $dep/GNUmakefile ] || [ -f $dep/makefile ] || [ -f $dep/Makefile ]; then \
                        make -C $dep IS_DEP=1; \
                else \
                        echo "Error: No Makefile to build dependency $dep." >&2; \
                        exit 2; \
                fi \
        fi \
done
+ set -e
set -x; erl +A0 -noinput -boot start_clean  -pz /home/username/tools/Gradualizer/.erlang.mk/rebar/ebin -eval "        E = ets:new(makedep, [bag]),  G = digraph:new([acyclic]),     ErlFiles = lists:usort(string:tokens(\"src/absform.erl src/constraints.erl src/gradualizer.erl src/gradualizer_cli.erl src/gradualizer_db.erl src/gradualizer_file_utils.erl src/gradualizer_lib.erl src/rebar_prv_gradualizer.erl src/ty.erl src/typechecker.erl src/typelib.erl  \", \" \")),     DepsDir = \"/home/username/tools/Gradualizer/deps\",  AppsDir = \"/home/username/tools/Gradualizer/apps\",        DepsDirsSrc = \"\",     DepsDirsInc = \"\",     AppsDirsSrc = \"\",     AppsDirsInc = \"\",   DepsDirs = lists:usort(string:tokens(DepsDirsSrc++DepsDirsInc, \" \")), AppsDirs = lists:usort(string:tokens(AppsDirsSrc++AppsDirsInc, \" \")),       Modules = [{list_to_atom(filename:basename(F, \".erl\")), F} || F <- ErlFiles], Add = fun (Mod, Dep) ->               case lists:keyfind(Dep, 1, Modules) of                  false -> ok;                    {_, DepFile} ->              {_, ModFile} = lists:keyfind(Mod, 1, Modules),                           ets:insert(E, {ModFile, DepFile}),                           digraph:add_vertex(G, Mod),                              digraph:add_vertex(G, Dep),                             digraph:add_edge(G, Mod, Dep)         end     end,    AddHd = fun (F, Mod, DepFile) ->                case file:open(DepFile, [read]) of                   {error, enoent} ->                               ok;                     {ok, Fd} ->                             {_, ModFile} = lists:keyfind(Mod, 1, Modules),                                case ets:match(E, {ModFile, DepFile}) of                                     [] ->                                            ets:insert(E, {ModFile, DepFile}),                                              F(F, Fd, Mod,0);                                      _ -> ok                         end             end     end,    SearchHrl = fun      F(_Hrl, []) -> {error,enoent};           F(Hrl, [Dir|Dirs]) ->                   HrlF = filename:join([Dir,Hrl]),                     case filelib:is_file(HrlF) of                            true  ->                                {ok, HrlF};                          false -> F(Hrl,Dirs)                     end     end,    Attr = fun              (_F, Mod, behavior, Dep) ->                     Add(Mod, Dep);                (_F, Mod, behaviour, Dep) ->                    Add(Mod, Dep);          (_F, Mod, compile, {parse_transform, Dep}) ->                 Add(Mod, Dep);          (_F, Mod, compile, Opts) when is_list(Opts) ->                  case proplists:get_value(parse_transform, Opts) of                            undefined -> ok;                                Dep -> Add(Mod, Dep)         end;             (F, Mod, include, Hrl) ->                       case SearchHrl(Hrl, [\"src\", \"include\",AppsDir,DepsDir]++AppsDirs++DepsDirs) of                            {ok, FoundHrl} -> AddHd(F, Mod, FoundHrl);                              {error, _} -> false  end;             (F, Mod, include_lib, Hrl) ->                   case SearchHrl(Hrl, [\"src\", \"include\",AppsDir,DepsDir]++AppsDirs++DepsDirs) of                            {ok, FoundHrl} -> AddHd(F, Mod, FoundHrl);                              {error, _} -> false  end;             (F, Mod, import, {Imp, _}) ->                   IsFile =                                case lists:keyfind(Imp, 1, Modules) of                                        false -> false;                                 {_, FilePath} -> filelib:is_file(FilePath)                            end,                    case IsFile of                          false -> ok;                         true -> Add(Mod, Imp)                    end;            (_, _, _, _) -> ok      end,    MakeDepend = fun                (F, Fd, Mod, StartLocation) ->                        {ok, Filename} = file:pid2name(Fd),                     case io:parse_erl_form(Fd, undefined, StartLocation) of                               {ok, AbsData, EndLocation} ->                                   case AbsData of      {attribute, _, Key, Value} ->                                                    Attr(F, Mod, Key, Value),                            F(F, Fd, Mod, EndLocation);                                              _ -> F(F, Fd, Mod, EndLocation)                              end;                             {eof, _ } -> file:close(Fd);                            {error, ErrorDescription } ->                file:close(Fd);                          {error, ErrorInfo, ErrorLocation} ->                                    F(F, Fd, Mod, ErrorLocation)                  end,                    ok      end,    [begin          Mod = list_to_atom(filename:basename(F, \".erl\")),  {ok, Fd} = file:open(F, [read]),         MakeDepend(MakeDepend, Fd, Mod,0)       end || F <- ErlFiles],  Depend = sofs:to_external(sofs:relation_to_family(sofs:relation(ets:tab2list(E)))),   CompileFirst = [X || X <- lists:reverse(digraph_utils:topsort(G)), [] =/= digraph:in_neighbours(G, X)],       TargetPath = fun(Target) ->             case lists:keyfind(Target, 1, Modules) of                    false -> \"\";                   {_, DepFile} ->                         DirSubname = tl(string:tokens(filename:dirname(DepFile), \"/\")),                             string:join(DirSubname ++ [atom_to_list(Target)], \"/\")                end     end,    ok = file:write_file(\"gradualizer.d\", [             [[F, \"::\", [[\" \", D] || D <- Deps], \"; @touch \$@\n\"] || {F, Deps} <- Depend],         \"\nCOMPILE_FIRST +=\", [[\" \", TargetPath(CF)] || CF <- CompileFirst], \"\n\"  ]),     halt()" -- erlang.mk
+ erl +A0 -noinput -boot start_clean -pz /home/username/tools/Gradualizer/.erlang.mk/rebar/ebin -eval '       E = ets:new(makedep, [bag]),  G = digraph:new([acyclic]),     ErlFiles = lists:usort(string:tokens("src/absform.erl src/constraints.erl src/gradualizer.erl src/gradualizer_cli.erl src/gradualizer_db.erl src/gradualizer_file_utils.erl src/gradualizer_lib.erl src/rebar_prv_gradualizer.erl src/ty.erl src/typechecker.erl src/typelib.erl  ", " ")), DepsDir = "/home/username/tools/Gradualizer/deps",    AppsDir = "/home/username/tools/Gradualizer/apps",  DepsDirsSrc = "",       DepsDirsInc = "",       AppsDirsSrc = "",       AppsDirsInc = "",       DepsDirs = lists:usort(string:tokens(DepsDirsSrc++DepsDirsInc, " ")), AppsDirs = lists:usort(string:tokens(AppsDirsSrc++AppsDirsInc, " ")),Modules = [{list_to_atom(filename:basename(F, ".erl")), F} || F <- ErlFiles],    Add = fun (Mod, Dep) ->         case lists:keyfind(Dep, 1, Modules) of                        false -> ok;                    {_, DepFile} ->                         {_, ModFile} = lists:keyfind(Mod, 1, Modules),                                ets:insert(E, {ModFile, DepFile}),                              digraph:add_vertex(G, Mod),                           digraph:add_vertex(G, Dep),                             digraph:add_edge(G, Mod, Dep)        end      end,    AddHd = fun (F, Mod, DepFile) ->                case file:open(DepFile, [read]) of                      {error, enoent} ->                            ok;                     {ok, Fd} ->                             {_, ModFile} = lists:keyfind(Mod, 1, Modules),                                case ets:match(E, {ModFile, DepFile}) of                                        [] ->        ets:insert(E, {ModFile, DepFile}),                                               F(F, Fd, Mod,0);                                     _ -> ok                          end             end     end,    SearchHrl = fun         F(_Hrl, []) -> {error,enoent};          F(Hrl, [Dir|Dirs]) ->                 HrlF = filename:join([Dir,Hrl]),                        case filelib:is_file(HrlF) of                true  ->                         {ok, HrlF};                             false -> F(Hrl,Dirs)                    end     end,    Attr = fun            (_F, Mod, behavior, Dep) ->                     Add(Mod, Dep);          (_F, Mod, behaviour, Dep) ->                 Add(Mod, Dep);           (_F, Mod, compile, {parse_transform, Dep}) ->                   Add(Mod, Dep);          (_F, Mod, compile, Opts) when is_list(Opts) ->                        case proplists:get_value(parse_transform, Opts) of                              undefined -> ok;                              Dep -> Add(Mod, Dep)                    end;            (F, Mod, include, Hrl) ->            case SearchHrl(Hrl, ["src", "include",AppsDir,DepsDir]++AppsDirs++DepsDirs) of                           {ok, FoundHrl} -> AddHd(F, Mod, FoundHrl);                            {error, _} -> false                     end;            (F, Mod, include_lib, Hrl) ->        case SearchHrl(Hrl, ["src", "include",AppsDir,DepsDir]++AppsDirs++DepsDirs) of                           {ok, FoundHrl} -> AddHd(F, Mod, FoundHrl);                            {error, _} -> false                     end;            (F, Mod, import, {Imp, _}) ->        IsFile =                         case lists:keyfind(Imp, 1, Modules) of                                  false -> false;              {_, FilePath} -> filelib:is_file(FilePath)                               end,                    case IsFile of                       false -> ok;                             true -> Add(Mod, Imp)                   end;            (_, _, _, _) -> ok      end,    MakeDepend = fun              (F, Fd, Mod, StartLocation) ->                  {ok, Filename} = file:pid2name(Fd),                     case io:parse_erl_form(Fd, undefined, StartLocation) of                               {ok, AbsData, EndLocation} ->                        case AbsData of                                          {attribute, _, Key, Value} ->                                                Attr(F, Mod, Key, Value),                                                        F(F, Fd, Mod, EndLocation);                          _ -> F(F, Fd, Mod, EndLocation)                                  end;                            {eof, _ } -> file:close(Fd);         {error, ErrorDescription } ->                                    file:close(Fd);                         {error, ErrorInfo, ErrorLocation} ->                                  F(F, Fd, Mod, ErrorLocation)                    end,                    ok      end,    [beginMod = list_to_atom(filename:basename(F, ".erl")),               {ok, Fd} = file:open(F, [read]),                MakeDepend(MakeDepend, Fd, Mod,0)     end || F <- ErlFiles],  Depend = sofs:to_external(sofs:relation_to_family(sofs:relation(ets:tab2list(E)))),     CompileFirst = [X || X <- lists:reverse(digraph_utils:topsort(G)), [] =/= digraph:in_neighbours(G, X)],       TargetPath = fun(Target) ->  case lists:keyfind(Target, 1, Modules) of                        false -> "";                    {_, DepFile} ->                      DirSubname = tl(string:tokens(filename:dirname(DepFile), "/")),                          string:join(DirSubname ++ [atom_to_list(Target)], "/")                end     end,    ok = file:write_file("gradualizer.d", [         [[F, "::", [[" ", D] || D <- Deps], "; @touch $@\n"] || {F, Deps} <- Depend],         "\nCOMPILE_FIRST +=", [[" ", TargetPath(CF)] || CF <- CompileFirst], "\n"       ]),     halt()' -- erlang.mk
set -x; make --no-print-directory app-build
+ make --no-print-directory app-build
erlang.mk:30: Please upgrade to GNU Make 4 or later: https://erlang.mk/guide/installation.html
set -x; mkdir -p ebin/
+ mkdir -p ebin/
set -x; erlc -v +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard -o ebin/ -pa ebin/ -I include/ src/absform.erl src/constraints.erl src/gradualizer.erl src/gradualizer_cli.erl src/gradualizer_db.erl src/gradualizer_file_utils.erl src/gradualizer_lib.erl src/rebar_prv_gradualizer.erl src/ty.erl src/typechecker.erl src/typelib.erl
+ erlc -v +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard -o ebin/ -pa ebin/ -I include/ src/absform.erl src/constraints.erl src/gradualizer.erl src/gradualizer_cli.erl src/gradualizer_db.erl src/gradualizer_file_utils.erl src/gradualizer_lib.erl src/rebar_prv_gradualizer.erl src/ty.erl src/typechecker.erl src/typelib.erl
src/ty.erl:6: Warning: export_all flag enabled - all functions will be exported
src/typechecker.erl:23: Warning: export_all flag enabled - all functions will be exported
set -x; if [ -z "$(grep -e '^[^%]*{\s*modules\s*,' src/gradualizer.app.src)" ]; then \
        echo "Empty modules entry not found in gradualizer.app.src. Please consult the erlang.mk README for instructions." >&2; \
        exit 1; \
fi
++ grep -e '^[^%]*{\s*modules\s*,' src/gradualizer.app.src
+ '[' -z '  {modules, []}' ']'
set -x; cat src/gradualizer.app.src \
        | sed "s/{[[:space:]]*modules[[:space:]]*,[[:space:]]*\[\]}/{modules, \['absform','constraints','gradualizer','gradualizer_cli','gradualizer_db','gradualizer_file_utils','gradualizer_lib','rebar_prv_gradualizer','ty','typechecker','typelib'\]}/" \
        | sed "s/{id,[[:space:]]*\"git\"}/{id, \"\"}/" \
        > ebin/gradualizer.app
+ cat src/gradualizer.app.src
+ sed 's/{id,[[:space:]]*"git"}/{id, ""}/'
+ sed 's/{[[:space:]]*modules[[:space:]]*,[[:space:]]*\[\]}/{modules, \['\''absform'\'','\''constraints'\'','\''gradualizer'\'','\''gradualizer_cli'\'','\''gradualizer_db'\'','\''gradualizer_file_utils'\'','\''gradualizer_lib'\'','\''rebar_prv_gradualizer'\'','\''ty'\'','\''typechecker'\'','\''typelib'\''\]}/'
set -x; :
+ :
set -x; mkdir -p ./ ./ ./ ./ ./
+ mkdir -p ./ ./ ./ ./ ./
set -x; rm -f /home/username/tools/Gradualizer/.erlang.mk/escript.zip
+ rm -f /home/username/tools/Gradualizer/.erlang.mk/escript.zip
set -x; cd .. && 7z a -tzip -mx=9 -mtc=off  /home/username/tools/Gradualizer/.erlang.mk/escript.zip gradualizer/ebin/*
+ cd ..
+ 7z a -tzip -mx=9 -mtc=off /home/username/tools/Gradualizer/.erlang.mk/escript.zip 'gradualizer/ebin/*'

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz (306F2),ASM,AES-NI)

Scanning the drive:
          
WARNING: No more files
gradualizer

0 files, 0 bytes

Creating archive: /home/username/tools/Gradualizer/.erlang.mk/escript.zip

Items to compress: 0

    
Files read from disk: 0
Archive size: 22 bytes (1 KiB)

Scan WARNINGS for files and folders:

gradualizer : No more files
----------------
Scan WARNINGS: 1
make: *** [escript-zip] Error 1

@OvermindDL1
Copy link
Author

Been following the makefile at:
https://github.com/josefs/Gradualizer/blob/master/erlang.mk#L2634

And I ran across something interesting. It is going UP out of the directory, then trying to pack gradualizer as per the line at: https://github.com/josefs/Gradualizer/blob/master/Makefile#L29

PROJECT = gradualizer

However, this git repository is named Gradualizer, thus meaning it clones out as Gradualizer, and not gradualizer.

Now, renaming the directory as gradualizer (which does not follow the naming conventions of this repository) gets it to compile:

╰─➤  make escript
erlang.mk:30: Please upgrade to GNU Make 4 or later: https://erlang.mk/guide/installation.html
erlang.mk:30: Please upgrade to GNU Make 4 or later: https://erlang.mk/guide/installation.html
 GEN    escript-zip
 GEN    escript

╰─➤  ls -lah g*
-rwxrwxr-x. 1 username username 144K Oct 11 11:44 gradualizer
-rw-rw-r--. 1 username username   67 Oct 11 11:41 gradualizer.d

╰─➤  ./gradualizer 
Usage: gradualizer [options] [PATH...]
A type checker for Erlang/Elixir

       PATH                      Files or directories to type check
  -h,  --help                    display this help and exit
  -pa, --path-add                Add the specified directory to the beginning of
                                 the code path; see erl -pa             [string]
       --print-file              prefix error printouts with the file name the
                                 error is from
       --no-print-file           inverse of --print-file
                                  - the default behaviour
       --stop-on-first-error     stop type checking at the first error
       --no-stop-on-first-error  inverse of --stop-on-first-error
                                  - the default behaviour

So it compiled and seems to work.

So immediately that means that the erlang.mk file at https://github.com/josefs/Gradualizer/blob/master/erlang.mk is broken because it absolutely should not ever be stepping outside of the repository directory, but a greater question is how does it work for anyone else with a default clone when the repository name is Gradualizer since the clone uri is https://github.com/josefs/Gradualizer.git thus defaulting the directory name to be Gradualizer...

@OvermindDL1 OvermindDL1 changed the title erlang.mk:30: Please upgrade to GNU Make 4 or later erlang.mk bug Oct 11, 2018
@Zalastax
Copy link
Collaborator

@OvermindDL1 I got it to work by changing the name of the directory too. I agree that it's a strange way of doing it.

Deciding on a build system is often controversial. What we have now seems to work decently so I don't think people are too keen of changing unless there is a real benefit.

@josefs
Copy link
Owner

josefs commented Oct 11, 2018

@gomoripeti, I'd like to hear your take on this.

@OvermindDL1
Copy link
Author

Deciding on a build system is often controversial. What we have now seems to work decently so I don't think people are too keen of changing unless there is a real benefit.

Yeah I don't really care what's used as long as it works. Although that erlang.mk file is rather hairy and that is definitely a bug regardless that will break the ability to, for example, use this repository as a dependency for, say, an Elixir Gradualizer mix integrator.

@OvermindDL1
Copy link
Author

Actually I don't think this repo could be used like that anyway as make does not come on Windows so I don't think erlang.mk could be the build system anyway, hmm...

Well, a rebar3 or a mix version of the build system would be just a couple of lines as it stands (unlike the rather huge erlang.mk file...), it's fairly simple to compile as-is.

@KennethL
Copy link

I would prefer the use of rebar3 in this project, definitely not mix since that creates an unnecessary dependency to Elixir. It should be trivial to use rebar3 for this. Using rebar3 would also get reid of the dependency to 7z that came up when I tried to 'make escript'.

@gomoripeti
Copy link
Collaborator

hello all,

I also hit this problem, and renaming the parent dir was the ultimate solution. Strangely enough if I used zip and not 7z to create the escript (ESCRIPT_ZIP env var) it worked so I thought initially it's an OS X/7z issue.

Anyway I just introduced erlang.mk because the project already used custom make rules, and I've never used erlang.mk before, so it was a good chance to try - rather subjective choice. So I have no objection in converting to rebar3.

(To be fair you can look at the erlang.mk file is just a blackbox library, peeking into rebar3 itself could be just as hairy)

@josefs
Copy link
Owner

josefs commented Oct 12, 2018

It sounds like we have a consensus to start to use rebar3 and I don't have any objection to that. Is anyone willing to submit a PR?

@zuiderkwast
Copy link
Collaborator

zuiderkwast commented Oct 12, 2018

The problem concerns only when used as a dependency for another project, right?

It should definitely be possible to use this repo as a dependency for projects using rebar3. Do we even need a rebar config file to make it work? I guess it works already, but if not, we should add a small rebar config file. Has anyone tried?

It would be nice however if the Makefile would work as well, when used as a dependency for projects using the erlang.mk dependency way (i.e. download the dependency and run make inside). If possible, it would be nice to not require a dependency to rebar in this case. A simple rule just running erlc would be enough for this.

Regardless of build system, how about renaming the repo to lowercase gradualizer? It doesn't hurt that the repo has the same name as the application.

When not used as a dependency, I don't mind using rebar, but I think the make file works fine as it is for this.

@OvermindDL1
Copy link
Author

The problem concerns only when used as a dependency for another project, right?

No, it happens when you try to build it straight from a fresh git clone into the default named directory on any filesystem that is case-sensitive.

Using something like rebar3 'would' make it significantly easier to distribute this via packaging systems like hex as well as using it as a dependency to integrate it into build tools, but that's just a bonus around the overall issue.

If possible, it would be nice to not require a dependency to rebar in this case.

As I recall you can include a rebar thunk/wrapper file to just download-and-run, but in general if someone is doing some BEAM language work (erlang/elixir/lfe/alpaca/whatever) then they probably have rebar anyway (and considering windows as well they more likely have rebar3 than make regardless).

Regardless of build system, how about renaming the repo to lowercase gradualizer? It doesn't hurt that the repo has the same name as the application.

This would be an immediate fix and I'm all for it, regardless the erlang.mk file is bugged anyway, but that would at least make clone-and-compile work.

When not used as a dependency, I don't mind using rebar, but I think the make file works fine as it is for this.

It still prevents windows users from compiling it. Multi-platform is important.

@gomoripeti
Copy link
Collaborator

Actually as Gradualizer has no dependencies it should already work perfectly with rebar3 too (without a rebar.config).

So if you are on windows and you don't have make, but you have rebar3, you can just use it

rebar3 compile
rebar3 escriptize
rebar3 eunit

Also this is why Gradualizer works perfectly as a rebar3 dependency/plugin.

But I am absolutely not against converting to rebar3 "officially", this mostly consists of updating the README (and removing the huge erlang.mk file)

One con of erlang.mk is that I dont think it supports creating a hex package.

@OvermindDL1
Copy link
Author

One con of erlang.mk is that I dont think it supports creating a hex package.

It doesn't? That seems odd considering how well hex dependencies are used in the BEAM world across a variety of languages now. Rebar3 has native support so that would be a definite boon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants