From 912920a53cf6adf288679b6fce8d7dabdf368acf Mon Sep 17 00:00:00 2001 From: Martin Sumner Date: Fri, 3 Nov 2017 11:47:00 +0000 Subject: [PATCH] Failed attempt to hack in LZ4 --- .erlang.mk/deps.log | 2 + .erlang.mk/last-makefile-change | 0 Makefile | 41 + c_src/env.mk | 3 + c_src/lz4.c | 47 + c_src/lz4.o | Bin 0 -> 3272 bytes c_src/lz4_erlang.h | 58 + c_src/lz4f.c | 286 ++ c_src/lz4f.o | Bin 0 -> 5868 bytes ebin/lz4.app | 8 + erlang.mk | 6889 +++++++++++++++++++++++++++++++ lz4.d | 2 + priv/lz4_nif.so | Bin 0 -> 104132 bytes rebar.config | 7 + src/leveled_cdb.erl | 15 +- src/lz4_nif.erl | 64 + src/lz4f.erl | 107 + test/lz4f_SUITE.erl | 82 + 18 files changed, 7603 insertions(+), 8 deletions(-) create mode 100644 .erlang.mk/deps.log create mode 100644 .erlang.mk/last-makefile-change create mode 100644 Makefile create mode 100644 c_src/env.mk create mode 100644 c_src/lz4.c create mode 100644 c_src/lz4.o create mode 100644 c_src/lz4_erlang.h create mode 100644 c_src/lz4f.c create mode 100644 c_src/lz4f.o create mode 100644 ebin/lz4.app create mode 100644 erlang.mk create mode 100644 lz4.d create mode 100755 priv/lz4_nif.so create mode 100644 src/lz4_nif.erl create mode 100644 src/lz4f.erl create mode 100644 test/lz4f_SUITE.erl diff --git a/.erlang.mk/deps.log b/.erlang.mk/deps.log new file mode 100644 index 0000000..4d0d282 --- /dev/null +++ b/.erlang.mk/deps.log @@ -0,0 +1,2 @@ +/Users/martinsumner/dbroot/leveled/deps/lz4_src +/Users/martinsumner/dbroot/leveled/deps/nif_helpers diff --git a/.erlang.mk/last-makefile-change b/.erlang.mk/last-makefile-change new file mode 100644 index 0000000..e69de29 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..340db88 --- /dev/null +++ b/Makefile @@ -0,0 +1,41 @@ +PROJECT = lz4 +PROJECT_DESCRIPTION = New project +PROJECT_VERSION = 0.1.0 + +BUILD_DEPS = lz4_src nif_helpers +dep_lz4_src = git https://github.com/lz4/lz4 v1.8.0 +dep_nif_helpers = git https://github.com/ninenines/nif_helpers master +DEP_PLUGINS = nif_helpers + +C_SRC_OUTPUT = $(CURDIR)/priv/lz4_nif + +TEST_DEPS = ct_helper +dep_ct_helper = git https://github.com/extend/ct_helper master + +include erlang.mk + +CFLAGS += -I $(DEPS_DIR)/lz4_src/lib +# This is required in order to build a liblz4.a that we can +# include in our shared library. +export CPPFLAGS += -shared -fPIC +LDLIBS += $(DEPS_DIR)/lz4_src/lib/liblz4.a + +-include c_src/env.mk + +cppcheck: + cppcheck -f --quiet --error-exitcode=2 --enable=all --inconclusive --std=posix \ + -Ideps/lz4_src/lib/ -Ideps/nif_helpers/ -I$(ERTS_INCLUDE_DIR) c_src/ + +scan-build: + make clean + scan-build make + +# Download a large file for use in compression tests. + +PDF_REFERENCE = http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/pdf_reference_1-7.pdf + +test-build:: $(TEST_DIR)/lz4f_SUITE_data/pdf_reference_1-7.pdf + +$(TEST_DIR)/lz4f_SUITE_data/pdf_reference_1-7.pdf: + $(verbose) mkdir -p $(TEST_DIR)/lz4f_SUITE_data/ + $(gen_verbose) $(call core_http_get,$@,$(PDF_REFERENCE)) diff --git a/c_src/env.mk b/c_src/env.mk new file mode 100644 index 0000000..429d36e --- /dev/null +++ b/c_src/env.mk @@ -0,0 +1,3 @@ +ERTS_INCLUDE_DIR ?= /Users/martinsumner/erlang/18.3/erts-7.3/include/ +ERL_INTERFACE_INCLUDE_DIR ?= /Users/martinsumner/erlang/18.3/lib/erl_interface-3.8.2/include +ERL_INTERFACE_LIB_DIR ?= /Users/martinsumner/erlang/18.3/lib/erl_interface-3.8.2/lib diff --git a/c_src/lz4.c b/c_src/lz4.c new file mode 100644 index 0000000..80b0948 --- /dev/null +++ b/c_src/lz4.c @@ -0,0 +1,47 @@ +// Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. +// +// This package, the LZ4 binding for Erlang, is double-licensed under the Mozilla +// Public License 1.1 ("MPL") and the Apache License version 2 +// ("ASL"). For the MPL, please see LICENSE-MPL-RabbitMQ. For the ASL, +// please see LICENSE-APACHE2. +// +// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, +// either express or implied. See the LICENSE file for specific language governing +// rights and limitations of this software. +// +// If you have any questions regarding licensing, please contact us at +// info@rabbitmq.com. + +#include "lz4_erlang.h" + +NIF_ATOMS(NIF_ATOM_DECL) +NIF_RESOURCES(NIF_RES_DECL) + +int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); +int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info); +void unload(ErlNifEnv* env, void* priv_data); + +int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + NIF_ATOMS(NIF_ATOM_INIT) + NIF_RESOURCES(NIF_RES_INIT) + + return 0; +} + +int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) +{ + *priv_data = *old_priv_data; + + return 0; +} + +void unload(ErlNifEnv* env, void* priv_data) +{ +} + +static ErlNifFunc nif_funcs[] = { + NIF_FUNCTIONS(NIF_FUNCTION_ARRAY) +}; + +ERL_NIF_INIT(lz4_nif, nif_funcs, load, NULL, upgrade, unload) diff --git a/c_src/lz4.o b/c_src/lz4.o new file mode 100644 index 0000000000000000000000000000000000000000..913c5e50ba277e0092c05a32747899d726b18742 GIT binary patch literal 3272 zcmb7GUuauZ7(eN{v}$`BbyX)0%TSnul@ulpB$&E(L>U^kh=0rJU2>9!CHID#8|?-{ zp*jhpQo$$jVZQk1t)LG@_Yl~8@IfjFKJ3MU2*WAV7a5ycf8ROZP11W4>OOMvo!|HW z+}j{v8q`wnyL(V-Vxg0RAR0K>INc5$;1b$pO@2o9m1bQ_zT$5+tRs7JV}} zI5+!Bu7iWwC=~&scogb$1Q{p6pjaXnkd%41T6LWco|(=~2S|vZjzmW!XpI4JngF7{ zeBJlTPKhN_?yN7U>v4AczB?Fv!jDMGg6-Sw@QA;&zBD`3f zw)|vfW&E@MWxRYdw!d{_@A@_oW(B#;o?@%y7>&sjm$TZ_qEvQxrgYVR@ z=)`kZ+_R$KI!Y+Vt*WY!PPr)k1y9)p=_y}|7oIyIPtBf|xmUBZhfcnB^n}dk{lzDG z$O~FtIe(O5h%?HrPQGb7=L^@WgLIR%!OECm&m5Xn=*QuWT3WvA#Gua3EXs+~XDf3#!g_#9%p-Vv$b z{IZwFnBw-L3nBZk&8NHgf4z%-gZ2H=T-!zedp}1m)Z&HpTi?N5^uc<6#3UwSk!+hm z9>XL0E!J~iiRg6`gN^V789|=$k6aAqR{v25sbClbP~6>sXk59 zR^r0I@zMCR%lZpTb~6|Ye;Yf?SP2o>F($hTMwack-kx?J!tNN`aorKSA+yp0-@q29 z{lHh?V?rGH1ROr8kHAsj`1|04(7(reAAAJ*D(my$_|~T007vadax8xy9Ooc)oaIlm zdPV+wBV7$us1`Ni?i0KP(jaf$d$6y=WPw4p(-a<^G zU)X=kKyjJzCgVSW@!Lc75`7TDhePF)c&jXStV`X z#chE8Av9M54RBwGL@~`bB5nugMs1?IHRaF)cN<<_N&j3;aT + +// List of atoms used by this NIF. +// +// @todo We don't use threads so perhaps we should make nif_helpers +// better by splitting concerns into threads/not and have nif_helpers +// decide when to create the _nif_thread_ret atom or not. + +#define NIF_ATOMS(A) \ + A(ok) \ + A(done) \ + A(enomem) \ + A(_nif_thread_ret_) + +// List of resources used by this NIF. + +#define NIF_RESOURCES(R) \ + R(LZ4F_cctx) \ + R(LZ4F_dctx) + +// List of functions defined in this NIF. + +#define NIF_FUNCTION_NAME(f) lz4_erlang_ ## f +#define NIF_FUNCTIONS(F) \ + F(lz4f_compress_frame, 2) \ + F(lz4f_create_compression_context, 0) \ + F(lz4f_compress_begin, 2) \ + F(lz4f_compress_update, 2) \ + F(lz4f_flush, 1) \ + F(lz4f_compress_end, 1) \ + F(lz4f_create_decompression_context, 0) \ + F(lz4f_get_frame_info, 2) \ + F(lz4f_decompress, 2) + +#include "nif_helpers.h" + +NIF_ATOMS(NIF_ATOM_H_DECL) +NIF_RESOURCES(NIF_RES_H_DECL) +NIF_FUNCTIONS(NIF_FUNCTION_H_DECL) + +#endif diff --git a/c_src/lz4f.c b/c_src/lz4f.c new file mode 100644 index 0000000..c4dd41e --- /dev/null +++ b/c_src/lz4f.c @@ -0,0 +1,286 @@ +// Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. +// +// This package, the LZ4 binding for Erlang, is double-licensed under the Mozilla +// Public License 1.1 ("MPL") and the Apache License version 2 +// ("ASL"). For the MPL, please see LICENSE-MPL-RabbitMQ. For the ASL, +// please see LICENSE-APACHE2. +// +// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, +// either express or implied. See the LICENSE file for specific language governing +// rights and limitations of this software. +// +// If you have any questions regarding licensing, please contact us at +// info@rabbitmq.com. + +#include "lz4_erlang.h" +#include + +void dtor_LZ4F_cctx(ErlNifEnv* env, void* obj) +{ + LZ4F_freeCompressionContext(NIF_RES_GET(LZ4F_cctx, obj)); +} + +void dtor_LZ4F_dctx(ErlNifEnv* env, void* obj) +{ + LZ4F_freeDecompressionContext(NIF_RES_GET(LZ4F_dctx, obj)); +} + +NIF_FUNCTION(lz4f_compress_frame) +{ + LZ4F_preferences_t preferences; + size_t dstCapacity, dstSize; + ErlNifBinary srcBin, dstBin; + + BADARG_IF(!enif_inspect_binary(env, argv[0], &srcBin)); + + memset(&preferences, 0, sizeof(preferences)); + + // @todo prefs + + dstCapacity = LZ4F_compressFrameBound(srcBin.size, &preferences); + + if (!enif_alloc_binary(dstCapacity, &dstBin)) + return enif_raise_exception(env, atom_enomem); + + dstSize = LZ4F_compressFrame(dstBin.data, dstCapacity, srcBin.data, srcBin.size, &preferences); + + if (LZ4F_isError(dstSize)) { + enif_release_binary(&dstBin); + return enif_raise_exception(env, enif_make_atom(env, LZ4F_getErrorName(dstSize))); + } + + if (!enif_realloc_binary(&dstBin, dstSize)) { + enif_release_binary(&dstBin); + return enif_raise_exception(env, atom_enomem); + } + + return enif_make_binary(env, &dstBin); +} + +NIF_FUNCTION(lz4f_create_compression_context) +{ + LZ4F_cctx* cctx; + LZ4F_errorCode_t result; + ERL_NIF_TERM term; + + result = LZ4F_createCompressionContext(&cctx, LZ4F_VERSION); + + if (LZ4F_isError(result)) + return enif_raise_exception(env, enif_make_atom(env, LZ4F_getErrorName(result))); + + NIF_RES_TO_TERM(LZ4F_cctx, cctx, term); + + return term; +} + +NIF_FUNCTION(lz4f_compress_begin) +{ + void* cctx_res; + LZ4F_preferences_t preferences; + size_t dstSize; + ErlNifBinary dstBin; + + BADARG_IF(!enif_get_resource(env, argv[0], res_LZ4F_cctx, &cctx_res)); + + memset(&preferences, 0, sizeof(preferences)); + + // @todo prefs + + if (!enif_alloc_binary(LZ4F_HEADER_SIZE_MAX, &dstBin)) + return enif_raise_exception(env, atom_enomem); + + dstSize = LZ4F_compressBegin(NIF_RES_GET(LZ4F_cctx, cctx_res), + dstBin.data, LZ4F_HEADER_SIZE_MAX, &preferences); + + if (LZ4F_isError(dstSize)) { + enif_release_binary(&dstBin); + return enif_raise_exception(env, enif_make_atom(env, LZ4F_getErrorName(dstSize))); + } + + if (!enif_realloc_binary(&dstBin, dstSize)) { + enif_release_binary(&dstBin); + return enif_raise_exception(env, atom_enomem); + } + + return enif_make_binary(env, &dstBin); +} + +NIF_FUNCTION(lz4f_compress_update) +{ + void* cctx_res; + size_t dstCapacity, dstSize; + ErlNifBinary srcBin, dstBin; + + BADARG_IF(!enif_get_resource(env, argv[0], res_LZ4F_cctx, &cctx_res)); + BADARG_IF(!enif_inspect_binary(env, argv[1], &srcBin)); + + // @todo We pass NULL because we don't currently keep the preferences + // setup when the user began the compression. It might be done later + // as an optimization. + dstCapacity = LZ4F_compressBound(srcBin.size, NULL); + + if (!enif_alloc_binary(dstCapacity, &dstBin)) + return enif_raise_exception(env, atom_enomem); + + // We pass NULL because we can't guarantee that the source binary + // data will remain for future calls. It may be garbage collected. + dstSize = LZ4F_compressUpdate(NIF_RES_GET(LZ4F_cctx, cctx_res), + dstBin.data, dstCapacity, srcBin.data, srcBin.size, NULL); + + if (LZ4F_isError(dstSize)) { + enif_release_binary(&dstBin); + return enif_raise_exception(env, enif_make_atom(env, LZ4F_getErrorName(dstSize))); + } + + if (!enif_realloc_binary(&dstBin, dstSize)) { + enif_release_binary(&dstBin); + return enif_raise_exception(env, atom_enomem); + } + + return enif_make_binary(env, &dstBin); +} + +NIF_FUNCTION(lz4f_flush) +{ + void* cctx_res; + size_t dstCapacity, dstSize; + ErlNifBinary dstBin; + + BADARG_IF(!enif_get_resource(env, argv[0], res_LZ4F_cctx, &cctx_res)); + + // We pass 0 to get the upper bound for this operation. + // + // @todo We pass NULL because we don't currently keep the preferences + // setup when the user began the compression. It might be done later + // as an optimization. + dstCapacity = LZ4F_compressBound(0, NULL); + + if (!enif_alloc_binary(dstCapacity, &dstBin)) + return enif_raise_exception(env, atom_enomem); + + // We pass NULL because we can't guarantee that the source binary + // data will remain for future calls. It may be garbage collected. + dstSize = LZ4F_flush(NIF_RES_GET(LZ4F_cctx, cctx_res), + dstBin.data, dstCapacity, NULL); + + if (LZ4F_isError(dstSize)) { + enif_release_binary(&dstBin); + return enif_raise_exception(env, enif_make_atom(env, LZ4F_getErrorName(dstSize))); + } + + if (!enif_realloc_binary(&dstBin, dstSize)) { + enif_release_binary(&dstBin); + return enif_raise_exception(env, atom_enomem); + } + + return enif_make_binary(env, &dstBin); +} + +NIF_FUNCTION(lz4f_compress_end) +{ + void* cctx_res; + size_t dstCapacity, dstSize; + ErlNifBinary dstBin; + + BADARG_IF(!enif_get_resource(env, argv[0], res_LZ4F_cctx, &cctx_res)); + + // We pass 0 to get the upper bound for this operation. + // + // @todo We pass NULL because we don't currently keep the preferences + // setup when the user began the compression. It might be done later + // as an optimization. + dstCapacity = LZ4F_compressBound(0, NULL); + + if (!enif_alloc_binary(dstCapacity, &dstBin)) + return enif_raise_exception(env, atom_enomem); + + // We pass NULL because we can't guarantee that the source binary + // data will remain for future calls. It may be garbage collected. + dstSize = LZ4F_compressEnd(NIF_RES_GET(LZ4F_cctx, cctx_res), + dstBin.data, dstCapacity, NULL); + + if (LZ4F_isError(dstSize)) { + enif_release_binary(&dstBin); + return enif_raise_exception(env, enif_make_atom(env, LZ4F_getErrorName(dstSize))); + } + + if (!enif_realloc_binary(&dstBin, dstSize)) { + enif_release_binary(&dstBin); + return enif_raise_exception(env, atom_enomem); + } + + return enif_make_binary(env, &dstBin); +} + +NIF_FUNCTION(lz4f_create_decompression_context) +{ + LZ4F_dctx* dctx; + LZ4F_errorCode_t result; + ERL_NIF_TERM term; + + result = LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION); + + if (LZ4F_isError(result)) + return enif_raise_exception(env, enif_make_atom(env, LZ4F_getErrorName(result))); + + NIF_RES_TO_TERM(LZ4F_dctx, dctx, term); + + return term; +} + +NIF_FUNCTION(lz4f_get_frame_info) +{ + // @todo + + return atom_ok; +} + +NIF_FUNCTION(lz4f_decompress) +{ + void* dctx_res; + ERL_NIF_TERM head, reversed; + size_t dstSize, srcRead, srcSize; + ErlNifBinary srcBin, dstBin; + + BADARG_IF(!enif_get_resource(env, argv[0], res_LZ4F_dctx, &dctx_res)); + BADARG_IF(!enif_inspect_binary(env, argv[1], &srcBin)); + + srcRead = 0; + srcSize = srcBin.size; + + head = enif_make_list(env, 0); + + while (srcSize) { + dstSize = 65536; // Arbitrary maximum size of chunk. + + if (!enif_alloc_binary(dstSize, &dstBin)) { + return enif_raise_exception(env, atom_enomem); + } + + LZ4F_decompress(NIF_RES_GET(LZ4F_dctx, dctx_res), + dstBin.data, &dstSize, + srcBin.data + srcRead, &srcSize, + NULL); + + if (LZ4F_isError(dstSize)) { + enif_release_binary(&dstBin); + return enif_raise_exception(env, atom_enomem); + } + + if (!enif_realloc_binary(&dstBin, dstSize)) { + enif_release_binary(&dstBin); + return enif_raise_exception(env, atom_enomem); + } + + head = enif_make_list_cell(env, enif_make_binary(env, &dstBin), head); + + srcRead += srcSize; + srcSize = srcBin.size - srcRead; + } + + // We don't check the return value because no error can occur + // according to the function's source code. + enif_make_reverse_list(env, head, &reversed); + + return reversed; +} diff --git a/c_src/lz4f.o b/c_src/lz4f.o new file mode 100644 index 0000000000000000000000000000000000000000..be8228e18fa3f82e3e7c17744bac147715ec54fa GIT binary patch literal 5868 zcmds*e{5S<6~|xNq)lm7oAG0evDIa5SqnzZ)`?Kjsc!4+Wpbu%ZPwB)yt?*tW7V-U z$7X4#pcE%XPo77BO)C|Gpmoxa_J=2as35voO0>EXKTl?v&g0@1Nw4d3tm z;UCXQhr}Nsp7Q*8_nvdlIrp4<-+Ot#eCzeA%MGJxsevDy%{Ys^@ZrR9BhC)C7deXW zlY(ibqua1)@T6THmX)!GGV)rscL(?GuD12n5C`F)J;pN9W*A9!G#ev?J}fJe>K_P4 zGFCSEXgnFUtk6y^Bek9VDlT({jODV&Fjh*%CAIpNW%pUJbhzJ^y_QuU-%P9QpHcRn z!@Tv}D1psBsUd&Y0$yIW$pq2aM{t_x{1n*w0mC>C1B~T9oV5r0c&@4K{5P+AOy`1` zzpM98)c3457HS6`++`lUGy;V#=c<{%-7NGJFH(Q3jJ?7tO*C*(FAp&ZJq$PMgl}m4VD-P?<6F-9;!a3AMh7@mDG3b~46vSuE)>T4NEO;B2S?sKO0*YP52Ed*W888aW8?Q)iP zow>Uey#@?~oU3|N$kCabF>_O`h%8|BPR2Z|N2x30Lw$0W_N(G(A6~Q2eNk9J2C}k5 zMU-fQr9yp59FD}4U&7Lou|V-Kg1KnsJIp+)ROlZ6Nkz!gRf|#nkBU*&`JQ7j%5ttc z@MtCR7r#GgrDk~M`P`JL%RVmFqnQ1sYt=j2KCdPycU)PQ4xY0$C2l`!IxB6?o+C7gKLZ>4dZ>P=V{2pO-mc(CDn6bk?}?KwsUon@kRAA!l>&h4wYZS2(0oRTe9OiWmf3zgx=*V@2!`B-i*>?J;b5y-IHs60=c5!Cvg^) zU(Q<`TCX$L@^vn8)L+jmLwRawZ%Sw-R5{K67s@iMAyvuJ&d#p#D zUX8uY&>MN{z4ac3UdP)~?^^R1gGkZ+Gv95Whu(3e$9mSq*PUDb__Bh?4f}1p z@2@uu|2`1^Yi!*G-iEdb`oJyVI?xN=3N8WHfPY6}KLP#`#Cx^>RS>T>{ujWTz#RB- zFbduRc7Zp8TftAl&kf*5!GB=gZb1K^LDb6sa}evvUjnK318_as-vd{J-v)00zYfyx zSHSDRJs|Z$AmZ3*0TR+Am?)$#J@uR zBFK511UJIZqaghzK>D>o`rQZ8?>!*>ZUgCe6G*@7K>EEIq`nuV-xd&i&3_4NoPK`? z((g1#zf&Oneg~xACqeoxfVA^vkbcu3{q}+MyBDP2ZjgS1AoV*y`t^fYQ~s48{l0_y z75%;rvVOk?>HjQ9|Hnc4FM#xa45YosK>9xf(tjAF|NBAu?*!@pE|B`|ApNfgSAr`* z`k!r*{$2s;?^%%R+a^m8vrKifgt{|xwka3x4R17zH98ZwT* zfNRkI8pyc0uYKSYNP9m9Y3~J)ai0Wf_nY7<@CeAb4}tg>*Z*0NdAkw(Ft`Hz5V#F~ z@wd#U$OhZ9kdr0F3B?h`{fgTZeTsk>_YKek1Nz9Qw!TkXkGxV|Qaay9o!K78dgF0P z$$g?_7(Y^N{oFc-e(L+w_-9mGKX<;1ej#5b4II_u;fKd>m0UlEZiif%67plvt8Jfi zwcA|n6R!4eT=urYSgpNx;ia~H+9l_Du9fqiT-(0I)%Lmk|H37I&}DDP)qcPg&m%5- zcevV&r8XY!quTaKR~z@vI{DXJ@kLzvy)J);UHb31+FM=rvBvBCb-L`0y5zR2ZCG|P z9<$=f!2uf|l@7#{;q+nEnYI&lc+jrz><=Gu^`z}^B9V&JtJQaQy9h$##2dr7E6jRZB$uEdqG_h zlQg%p*4hqjOenES-6tM>~NMz$EojL1(eJ~EWOq!bRcG*{* zOgNM3H!S{QWu^LUG^#?*$cosBgwjYIYIGM%WC#0{7j<1Va3CBFrw=v`s>GNbh+=KH zg6vV9?o?Jr$q%6QGwT!|MP(lnCsKMZzmv-OFqc?+scbr;yYzl>b*mcJsmkq9Rjkix XDw~YDrXZr(E(MED!)_QBM33<=#HL_z literal 0 HcmV?d00001 diff --git a/ebin/lz4.app b/ebin/lz4.app new file mode 100644 index 0000000..6afd72c --- /dev/null +++ b/ebin/lz4.app @@ -0,0 +1,8 @@ +{application, 'lz4', [ + {description, "New project"}, + {vsn, "0.1.0"}, + {modules, ['leveled_app','leveled_bookie','leveled_cdb','leveled_codec','leveled_iclerk','leveled_imanifest','leveled_inker','leveled_log','leveled_pclerk','leveled_penciller','leveled_pmanifest','leveled_pmem','leveled_rand','leveled_runner','leveled_sst','leveled_sup','leveled_tictac','leveled_tinybloom','leveled_tree','lz4_nif','lz4f']}, + {registered, []}, + {applications, [kernel,stdlib]}, + {env, []} +]}. \ No newline at end of file diff --git a/erlang.mk b/erlang.mk new file mode 100644 index 0000000..64aaa4e --- /dev/null +++ b/erlang.mk @@ -0,0 +1,6889 @@ +# Copyright (c) 2013-2016, Loïc Hoguin +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +.PHONY: all app apps deps search rel relup docs install-docs check tests clean distclean help erlang-mk + +ERLANG_MK_FILENAME := $(realpath $(lastword $(MAKEFILE_LIST))) + +ERLANG_MK_VERSION = 2017.04.25-6-g5922969 + +# Make 3.81 and 3.82 are deprecated. + +ifeq ($(MAKE_VERSION),3.81) +$(warning Please upgrade to GNU Make 4 or later: https://erlang.mk/guide/installation.html) +endif + +ifeq ($(MAKE_VERSION),3.82) +$(warning Please upgrade to GNU Make 4 or later: https://erlang.mk/guide/installation.html) +endif + +# Core configuration. + +PROJECT ?= $(notdir $(CURDIR)) +PROJECT := $(strip $(PROJECT)) + +PROJECT_VERSION ?= rolling +PROJECT_MOD ?= $(PROJECT)_app +PROJECT_ENV ?= [] + +# Verbosity. + +V ?= 0 + +verbose_0 = @ +verbose_2 = set -x; +verbose = $(verbose_$(V)) + +gen_verbose_0 = @echo " GEN " $@; +gen_verbose_2 = set -x; +gen_verbose = $(gen_verbose_$(V)) + +# Temporary files directory. + +ERLANG_MK_TMP ?= $(CURDIR)/.erlang.mk +export ERLANG_MK_TMP + +# "erl" command. + +ERL = erl +A0 -noinput -boot start_clean + +# Platform detection. + +ifeq ($(PLATFORM),) +UNAME_S := $(shell uname -s) + +ifeq ($(UNAME_S),Linux) +PLATFORM = linux +else ifeq ($(UNAME_S),Darwin) +PLATFORM = darwin +else ifeq ($(UNAME_S),SunOS) +PLATFORM = solaris +else ifeq ($(UNAME_S),GNU) +PLATFORM = gnu +else ifeq ($(UNAME_S),FreeBSD) +PLATFORM = freebsd +else ifeq ($(UNAME_S),NetBSD) +PLATFORM = netbsd +else ifeq ($(UNAME_S),OpenBSD) +PLATFORM = openbsd +else ifeq ($(UNAME_S),DragonFly) +PLATFORM = dragonfly +else ifeq ($(shell uname -o),Msys) +PLATFORM = msys2 +else +$(error Unable to detect platform. Please open a ticket with the output of uname -a.) +endif + +export PLATFORM +endif + +# Core targets. + +all:: deps app rel + +# Noop to avoid a Make warning when there's nothing to do. +rel:: + $(verbose) : + +relup:: deps app + +check:: tests + +clean:: clean-crashdump + +clean-crashdump: +ifneq ($(wildcard erl_crash.dump),) + $(gen_verbose) rm -f erl_crash.dump +endif + +distclean:: clean distclean-tmp + +distclean-tmp: + $(gen_verbose) rm -rf $(ERLANG_MK_TMP) + +help:: + $(verbose) printf "%s\n" \ + "erlang.mk (version $(ERLANG_MK_VERSION)) is distributed under the terms of the ISC License." \ + "Copyright (c) 2013-2016 Loïc Hoguin " \ + "" \ + "Usage: [V=1] $(MAKE) [target]..." \ + "" \ + "Core targets:" \ + " all Run deps, app and rel targets in that order" \ + " app Compile the project" \ + " deps Fetch dependencies (if needed) and compile them" \ + " fetch-deps Fetch dependencies recursively (if needed) without compiling them" \ + " list-deps List dependencies recursively on stdout" \ + " search q=... Search for a package in the built-in index" \ + " rel Build a release for this project, if applicable" \ + " docs Build the documentation for this project" \ + " install-docs Install the man pages for this project" \ + " check Compile and run all tests and analysis for this project" \ + " tests Run the tests for this project" \ + " clean Delete temporary and output files from most targets" \ + " distclean Delete all temporary and output files" \ + " help Display this help and exit" \ + " erlang-mk Update erlang.mk to the latest version" + +# Core functions. + +empty := +space := $(empty) $(empty) +tab := $(empty) $(empty) +comma := , + +define newline + + +endef + +define comma_list +$(subst $(space),$(comma),$(strip $(1))) +endef + +# Adding erlang.mk to make Erlang scripts who call init:get_plain_arguments() happy. +define erlang +$(ERL) $(2) -pz $(ERLANG_MK_TMP)/rebar/ebin -eval "$(subst $(newline),,$(subst ",\",$(1)))" -- erlang.mk +endef + +ifeq ($(PLATFORM),msys2) +core_native_path = $(subst \,\\\\,$(shell cygpath -w $1)) +else +core_native_path = $1 +endif + +core_http_get = curl -Lf$(if $(filter-out 0,$(V)),,s)o $(call core_native_path,$1) $2 + +core_eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1))) + +core_find = $(if $(wildcard $1),$(shell find $(1:%/=%) -type f -name $(subst *,\*,$2))) + +core_lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$(1))))))))))))))))))))))))))) + +core_ls = $(filter-out $(1),$(shell echo $(1))) + +# @todo Use a solution that does not require using perl. +core_relpath = $(shell perl -e 'use File::Spec; print File::Spec->abs2rel(@ARGV) . "\n"' $1 $2) + +# Automated update. + +ERLANG_MK_REPO ?= https://github.com/ninenines/erlang.mk +ERLANG_MK_COMMIT ?= +ERLANG_MK_BUILD_CONFIG ?= build.config +ERLANG_MK_BUILD_DIR ?= .erlang.mk.build + +erlang-mk: + git clone $(ERLANG_MK_REPO) $(ERLANG_MK_BUILD_DIR) +ifdef ERLANG_MK_COMMIT + cd $(ERLANG_MK_BUILD_DIR) && git checkout $(ERLANG_MK_COMMIT) +endif + if [ -f $(ERLANG_MK_BUILD_CONFIG) ]; then cp $(ERLANG_MK_BUILD_CONFIG) $(ERLANG_MK_BUILD_DIR)/build.config; fi + $(MAKE) -C $(ERLANG_MK_BUILD_DIR) + cp $(ERLANG_MK_BUILD_DIR)/erlang.mk ./erlang.mk + rm -rf $(ERLANG_MK_BUILD_DIR) + +# The erlang.mk package index is bundled in the default erlang.mk build. +# Search for the string "copyright" to skip to the rest of the code. + +PACKAGES += aberth +pkg_aberth_name = aberth +pkg_aberth_description = Generic BERT-RPC server in Erlang +pkg_aberth_homepage = https://github.com/a13x/aberth +pkg_aberth_fetch = git +pkg_aberth_repo = https://github.com/a13x/aberth +pkg_aberth_commit = master + +PACKAGES += active +pkg_active_name = active +pkg_active_description = Active development for Erlang: rebuild and reload source/binary files while the VM is running +pkg_active_homepage = https://github.com/proger/active +pkg_active_fetch = git +pkg_active_repo = https://github.com/proger/active +pkg_active_commit = master + +PACKAGES += actordb_core +pkg_actordb_core_name = actordb_core +pkg_actordb_core_description = ActorDB main source +pkg_actordb_core_homepage = http://www.actordb.com/ +pkg_actordb_core_fetch = git +pkg_actordb_core_repo = https://github.com/biokoda/actordb_core +pkg_actordb_core_commit = master + +PACKAGES += actordb_thrift +pkg_actordb_thrift_name = actordb_thrift +pkg_actordb_thrift_description = Thrift API for ActorDB +pkg_actordb_thrift_homepage = http://www.actordb.com/ +pkg_actordb_thrift_fetch = git +pkg_actordb_thrift_repo = https://github.com/biokoda/actordb_thrift +pkg_actordb_thrift_commit = master + +PACKAGES += aleppo +pkg_aleppo_name = aleppo +pkg_aleppo_description = Alternative Erlang Pre-Processor +pkg_aleppo_homepage = https://github.com/ErlyORM/aleppo +pkg_aleppo_fetch = git +pkg_aleppo_repo = https://github.com/ErlyORM/aleppo +pkg_aleppo_commit = master + +PACKAGES += alog +pkg_alog_name = alog +pkg_alog_description = Simply the best logging framework for Erlang +pkg_alog_homepage = https://github.com/siberian-fast-food/alogger +pkg_alog_fetch = git +pkg_alog_repo = https://github.com/siberian-fast-food/alogger +pkg_alog_commit = master + +PACKAGES += amqp_client +pkg_amqp_client_name = amqp_client +pkg_amqp_client_description = RabbitMQ Erlang AMQP client +pkg_amqp_client_homepage = https://www.rabbitmq.com/erlang-client-user-guide.html +pkg_amqp_client_fetch = git +pkg_amqp_client_repo = https://github.com/rabbitmq/rabbitmq-erlang-client.git +pkg_amqp_client_commit = master + +PACKAGES += annotations +pkg_annotations_name = annotations +pkg_annotations_description = Simple code instrumentation utilities +pkg_annotations_homepage = https://github.com/hyperthunk/annotations +pkg_annotations_fetch = git +pkg_annotations_repo = https://github.com/hyperthunk/annotations +pkg_annotations_commit = master + +PACKAGES += antidote +pkg_antidote_name = antidote +pkg_antidote_description = Large-scale computation without synchronisation +pkg_antidote_homepage = https://syncfree.lip6.fr/ +pkg_antidote_fetch = git +pkg_antidote_repo = https://github.com/SyncFree/antidote +pkg_antidote_commit = master + +PACKAGES += apns +pkg_apns_name = apns +pkg_apns_description = Apple Push Notification Server for Erlang +pkg_apns_homepage = http://inaka.github.com/apns4erl +pkg_apns_fetch = git +pkg_apns_repo = https://github.com/inaka/apns4erl +pkg_apns_commit = master + +PACKAGES += asciideck +pkg_asciideck_name = asciideck +pkg_asciideck_description = Asciidoc for Erlang. +pkg_asciideck_homepage = https://ninenines.eu +pkg_asciideck_fetch = git +pkg_asciideck_repo = https://github.com/ninenines/asciideck +pkg_asciideck_commit = master + +PACKAGES += azdht +pkg_azdht_name = azdht +pkg_azdht_description = Azureus Distributed Hash Table (DHT) in Erlang +pkg_azdht_homepage = https://github.com/arcusfelis/azdht +pkg_azdht_fetch = git +pkg_azdht_repo = https://github.com/arcusfelis/azdht +pkg_azdht_commit = master + +PACKAGES += backoff +pkg_backoff_name = backoff +pkg_backoff_description = Simple exponential backoffs in Erlang +pkg_backoff_homepage = https://github.com/ferd/backoff +pkg_backoff_fetch = git +pkg_backoff_repo = https://github.com/ferd/backoff +pkg_backoff_commit = master + +PACKAGES += barrel_tcp +pkg_barrel_tcp_name = barrel_tcp +pkg_barrel_tcp_description = barrel is a generic TCP acceptor pool with low latency in Erlang. +pkg_barrel_tcp_homepage = https://github.com/benoitc-attic/barrel_tcp +pkg_barrel_tcp_fetch = git +pkg_barrel_tcp_repo = https://github.com/benoitc-attic/barrel_tcp +pkg_barrel_tcp_commit = master + +PACKAGES += basho_bench +pkg_basho_bench_name = basho_bench +pkg_basho_bench_description = A load-generation and testing tool for basically whatever you can write a returning Erlang function for. +pkg_basho_bench_homepage = https://github.com/basho/basho_bench +pkg_basho_bench_fetch = git +pkg_basho_bench_repo = https://github.com/basho/basho_bench +pkg_basho_bench_commit = master + +PACKAGES += bcrypt +pkg_bcrypt_name = bcrypt +pkg_bcrypt_description = Bcrypt Erlang / C library +pkg_bcrypt_homepage = https://github.com/riverrun/branglecrypt +pkg_bcrypt_fetch = git +pkg_bcrypt_repo = https://github.com/riverrun/branglecrypt +pkg_bcrypt_commit = master + +PACKAGES += beam +pkg_beam_name = beam +pkg_beam_description = BEAM emulator written in Erlang +pkg_beam_homepage = https://github.com/tonyrog/beam +pkg_beam_fetch = git +pkg_beam_repo = https://github.com/tonyrog/beam +pkg_beam_commit = master + +PACKAGES += beanstalk +pkg_beanstalk_name = beanstalk +pkg_beanstalk_description = An Erlang client for beanstalkd +pkg_beanstalk_homepage = https://github.com/tim/erlang-beanstalk +pkg_beanstalk_fetch = git +pkg_beanstalk_repo = https://github.com/tim/erlang-beanstalk +pkg_beanstalk_commit = master + +PACKAGES += bear +pkg_bear_name = bear +pkg_bear_description = a set of statistics functions for erlang +pkg_bear_homepage = https://github.com/boundary/bear +pkg_bear_fetch = git +pkg_bear_repo = https://github.com/boundary/bear +pkg_bear_commit = master + +PACKAGES += bertconf +pkg_bertconf_name = bertconf +pkg_bertconf_description = Make ETS tables out of statc BERT files that are auto-reloaded +pkg_bertconf_homepage = https://github.com/ferd/bertconf +pkg_bertconf_fetch = git +pkg_bertconf_repo = https://github.com/ferd/bertconf +pkg_bertconf_commit = master + +PACKAGES += bifrost +pkg_bifrost_name = bifrost +pkg_bifrost_description = Erlang FTP Server Framework +pkg_bifrost_homepage = https://github.com/thorstadt/bifrost +pkg_bifrost_fetch = git +pkg_bifrost_repo = https://github.com/thorstadt/bifrost +pkg_bifrost_commit = master + +PACKAGES += binpp +pkg_binpp_name = binpp +pkg_binpp_description = Erlang Binary Pretty Printer +pkg_binpp_homepage = https://github.com/jtendo/binpp +pkg_binpp_fetch = git +pkg_binpp_repo = https://github.com/jtendo/binpp +pkg_binpp_commit = master + +PACKAGES += bisect +pkg_bisect_name = bisect +pkg_bisect_description = Ordered fixed-size binary dictionary in Erlang +pkg_bisect_homepage = https://github.com/knutin/bisect +pkg_bisect_fetch = git +pkg_bisect_repo = https://github.com/knutin/bisect +pkg_bisect_commit = master + +PACKAGES += bitcask +pkg_bitcask_name = bitcask +pkg_bitcask_description = because you need another a key/value storage engine +pkg_bitcask_homepage = https://github.com/basho/bitcask +pkg_bitcask_fetch = git +pkg_bitcask_repo = https://github.com/basho/bitcask +pkg_bitcask_commit = develop + +PACKAGES += bitstore +pkg_bitstore_name = bitstore +pkg_bitstore_description = A document based ontology development environment +pkg_bitstore_homepage = https://github.com/bdionne/bitstore +pkg_bitstore_fetch = git +pkg_bitstore_repo = https://github.com/bdionne/bitstore +pkg_bitstore_commit = master + +PACKAGES += bootstrap +pkg_bootstrap_name = bootstrap +pkg_bootstrap_description = A simple, yet powerful Erlang cluster bootstrapping application. +pkg_bootstrap_homepage = https://github.com/schlagert/bootstrap +pkg_bootstrap_fetch = git +pkg_bootstrap_repo = https://github.com/schlagert/bootstrap +pkg_bootstrap_commit = master + +PACKAGES += boss +pkg_boss_name = boss +pkg_boss_description = Erlang web MVC, now featuring Comet +pkg_boss_homepage = https://github.com/ChicagoBoss/ChicagoBoss +pkg_boss_fetch = git +pkg_boss_repo = https://github.com/ChicagoBoss/ChicagoBoss +pkg_boss_commit = master + +PACKAGES += boss_db +pkg_boss_db_name = boss_db +pkg_boss_db_description = BossDB: a sharded, caching, pooling, evented ORM for Erlang +pkg_boss_db_homepage = https://github.com/ErlyORM/boss_db +pkg_boss_db_fetch = git +pkg_boss_db_repo = https://github.com/ErlyORM/boss_db +pkg_boss_db_commit = master + +PACKAGES += brod +pkg_brod_name = brod +pkg_brod_description = Kafka client in Erlang +pkg_brod_homepage = https://github.com/klarna/brod +pkg_brod_fetch = git +pkg_brod_repo = https://github.com/klarna/brod.git +pkg_brod_commit = master + +PACKAGES += bson +pkg_bson_name = bson +pkg_bson_description = BSON documents in Erlang, see bsonspec.org +pkg_bson_homepage = https://github.com/comtihon/bson-erlang +pkg_bson_fetch = git +pkg_bson_repo = https://github.com/comtihon/bson-erlang +pkg_bson_commit = master + +PACKAGES += bullet +pkg_bullet_name = bullet +pkg_bullet_description = Simple, reliable, efficient streaming for Cowboy. +pkg_bullet_homepage = http://ninenines.eu +pkg_bullet_fetch = git +pkg_bullet_repo = https://github.com/ninenines/bullet +pkg_bullet_commit = master + +PACKAGES += cache +pkg_cache_name = cache +pkg_cache_description = Erlang in-memory cache +pkg_cache_homepage = https://github.com/fogfish/cache +pkg_cache_fetch = git +pkg_cache_repo = https://github.com/fogfish/cache +pkg_cache_commit = master + +PACKAGES += cake +pkg_cake_name = cake +pkg_cake_description = Really simple terminal colorization +pkg_cake_homepage = https://github.com/darach/cake-erl +pkg_cake_fetch = git +pkg_cake_repo = https://github.com/darach/cake-erl +pkg_cake_commit = master + +PACKAGES += carotene +pkg_carotene_name = carotene +pkg_carotene_description = Real-time server +pkg_carotene_homepage = https://github.com/carotene/carotene +pkg_carotene_fetch = git +pkg_carotene_repo = https://github.com/carotene/carotene +pkg_carotene_commit = master + +PACKAGES += cberl +pkg_cberl_name = cberl +pkg_cberl_description = NIF based Erlang bindings for Couchbase +pkg_cberl_homepage = https://github.com/chitika/cberl +pkg_cberl_fetch = git +pkg_cberl_repo = https://github.com/chitika/cberl +pkg_cberl_commit = master + +PACKAGES += cecho +pkg_cecho_name = cecho +pkg_cecho_description = An ncurses library for Erlang +pkg_cecho_homepage = https://github.com/mazenharake/cecho +pkg_cecho_fetch = git +pkg_cecho_repo = https://github.com/mazenharake/cecho +pkg_cecho_commit = master + +PACKAGES += cferl +pkg_cferl_name = cferl +pkg_cferl_description = Rackspace / Open Stack Cloud Files Erlang Client +pkg_cferl_homepage = https://github.com/ddossot/cferl +pkg_cferl_fetch = git +pkg_cferl_repo = https://github.com/ddossot/cferl +pkg_cferl_commit = master + +PACKAGES += chaos_monkey +pkg_chaos_monkey_name = chaos_monkey +pkg_chaos_monkey_description = This is The CHAOS MONKEY. It will kill your processes. +pkg_chaos_monkey_homepage = https://github.com/dLuna/chaos_monkey +pkg_chaos_monkey_fetch = git +pkg_chaos_monkey_repo = https://github.com/dLuna/chaos_monkey +pkg_chaos_monkey_commit = master + +PACKAGES += check_node +pkg_check_node_name = check_node +pkg_check_node_description = Nagios Scripts for monitoring Riak +pkg_check_node_homepage = https://github.com/basho-labs/riak_nagios +pkg_check_node_fetch = git +pkg_check_node_repo = https://github.com/basho-labs/riak_nagios +pkg_check_node_commit = master + +PACKAGES += chronos +pkg_chronos_name = chronos +pkg_chronos_description = Timer module for Erlang that makes it easy to abstact time out of the tests. +pkg_chronos_homepage = https://github.com/lehoff/chronos +pkg_chronos_fetch = git +pkg_chronos_repo = https://github.com/lehoff/chronos +pkg_chronos_commit = master + +PACKAGES += chumak +pkg_chumak_name = chumak +pkg_chumak_description = Pure Erlang implementation of ZeroMQ Message Transport Protocol. +pkg_chumak_homepage = http://choven.ca +pkg_chumak_fetch = git +pkg_chumak_repo = https://github.com/chovencorp/chumak +pkg_chumak_commit = master + +PACKAGES += cl +pkg_cl_name = cl +pkg_cl_description = OpenCL binding for Erlang +pkg_cl_homepage = https://github.com/tonyrog/cl +pkg_cl_fetch = git +pkg_cl_repo = https://github.com/tonyrog/cl +pkg_cl_commit = master + +PACKAGES += classifier +pkg_classifier_name = classifier +pkg_classifier_description = An Erlang Bayesian Filter and Text Classifier +pkg_classifier_homepage = https://github.com/inaka/classifier +pkg_classifier_fetch = git +pkg_classifier_repo = https://github.com/inaka/classifier +pkg_classifier_commit = master + +PACKAGES += clique +pkg_clique_name = clique +pkg_clique_description = CLI Framework for Erlang +pkg_clique_homepage = https://github.com/basho/clique +pkg_clique_fetch = git +pkg_clique_repo = https://github.com/basho/clique +pkg_clique_commit = develop + +PACKAGES += cloudi_core +pkg_cloudi_core_name = cloudi_core +pkg_cloudi_core_description = CloudI internal service runtime +pkg_cloudi_core_homepage = http://cloudi.org/ +pkg_cloudi_core_fetch = git +pkg_cloudi_core_repo = https://github.com/CloudI/cloudi_core +pkg_cloudi_core_commit = master + +PACKAGES += cloudi_service_api_requests +pkg_cloudi_service_api_requests_name = cloudi_service_api_requests +pkg_cloudi_service_api_requests_description = CloudI Service API requests (JSON-RPC/Erlang-term support) +pkg_cloudi_service_api_requests_homepage = http://cloudi.org/ +pkg_cloudi_service_api_requests_fetch = git +pkg_cloudi_service_api_requests_repo = https://github.com/CloudI/cloudi_service_api_requests +pkg_cloudi_service_api_requests_commit = master + +PACKAGES += cloudi_service_db +pkg_cloudi_service_db_name = cloudi_service_db +pkg_cloudi_service_db_description = CloudI Database (in-memory/testing/generic) +pkg_cloudi_service_db_homepage = http://cloudi.org/ +pkg_cloudi_service_db_fetch = git +pkg_cloudi_service_db_repo = https://github.com/CloudI/cloudi_service_db +pkg_cloudi_service_db_commit = master + +PACKAGES += cloudi_service_db_cassandra +pkg_cloudi_service_db_cassandra_name = cloudi_service_db_cassandra +pkg_cloudi_service_db_cassandra_description = Cassandra CloudI Service +pkg_cloudi_service_db_cassandra_homepage = http://cloudi.org/ +pkg_cloudi_service_db_cassandra_fetch = git +pkg_cloudi_service_db_cassandra_repo = https://github.com/CloudI/cloudi_service_db_cassandra +pkg_cloudi_service_db_cassandra_commit = master + +PACKAGES += cloudi_service_db_cassandra_cql +pkg_cloudi_service_db_cassandra_cql_name = cloudi_service_db_cassandra_cql +pkg_cloudi_service_db_cassandra_cql_description = Cassandra CQL CloudI Service +pkg_cloudi_service_db_cassandra_cql_homepage = http://cloudi.org/ +pkg_cloudi_service_db_cassandra_cql_fetch = git +pkg_cloudi_service_db_cassandra_cql_repo = https://github.com/CloudI/cloudi_service_db_cassandra_cql +pkg_cloudi_service_db_cassandra_cql_commit = master + +PACKAGES += cloudi_service_db_couchdb +pkg_cloudi_service_db_couchdb_name = cloudi_service_db_couchdb +pkg_cloudi_service_db_couchdb_description = CouchDB CloudI Service +pkg_cloudi_service_db_couchdb_homepage = http://cloudi.org/ +pkg_cloudi_service_db_couchdb_fetch = git +pkg_cloudi_service_db_couchdb_repo = https://github.com/CloudI/cloudi_service_db_couchdb +pkg_cloudi_service_db_couchdb_commit = master + +PACKAGES += cloudi_service_db_elasticsearch +pkg_cloudi_service_db_elasticsearch_name = cloudi_service_db_elasticsearch +pkg_cloudi_service_db_elasticsearch_description = elasticsearch CloudI Service +pkg_cloudi_service_db_elasticsearch_homepage = http://cloudi.org/ +pkg_cloudi_service_db_elasticsearch_fetch = git +pkg_cloudi_service_db_elasticsearch_repo = https://github.com/CloudI/cloudi_service_db_elasticsearch +pkg_cloudi_service_db_elasticsearch_commit = master + +PACKAGES += cloudi_service_db_memcached +pkg_cloudi_service_db_memcached_name = cloudi_service_db_memcached +pkg_cloudi_service_db_memcached_description = memcached CloudI Service +pkg_cloudi_service_db_memcached_homepage = http://cloudi.org/ +pkg_cloudi_service_db_memcached_fetch = git +pkg_cloudi_service_db_memcached_repo = https://github.com/CloudI/cloudi_service_db_memcached +pkg_cloudi_service_db_memcached_commit = master + +PACKAGES += cloudi_service_db_mysql +pkg_cloudi_service_db_mysql_name = cloudi_service_db_mysql +pkg_cloudi_service_db_mysql_description = MySQL CloudI Service +pkg_cloudi_service_db_mysql_homepage = http://cloudi.org/ +pkg_cloudi_service_db_mysql_fetch = git +pkg_cloudi_service_db_mysql_repo = https://github.com/CloudI/cloudi_service_db_mysql +pkg_cloudi_service_db_mysql_commit = master + +PACKAGES += cloudi_service_db_pgsql +pkg_cloudi_service_db_pgsql_name = cloudi_service_db_pgsql +pkg_cloudi_service_db_pgsql_description = PostgreSQL CloudI Service +pkg_cloudi_service_db_pgsql_homepage = http://cloudi.org/ +pkg_cloudi_service_db_pgsql_fetch = git +pkg_cloudi_service_db_pgsql_repo = https://github.com/CloudI/cloudi_service_db_pgsql +pkg_cloudi_service_db_pgsql_commit = master + +PACKAGES += cloudi_service_db_riak +pkg_cloudi_service_db_riak_name = cloudi_service_db_riak +pkg_cloudi_service_db_riak_description = Riak CloudI Service +pkg_cloudi_service_db_riak_homepage = http://cloudi.org/ +pkg_cloudi_service_db_riak_fetch = git +pkg_cloudi_service_db_riak_repo = https://github.com/CloudI/cloudi_service_db_riak +pkg_cloudi_service_db_riak_commit = master + +PACKAGES += cloudi_service_db_tokyotyrant +pkg_cloudi_service_db_tokyotyrant_name = cloudi_service_db_tokyotyrant +pkg_cloudi_service_db_tokyotyrant_description = Tokyo Tyrant CloudI Service +pkg_cloudi_service_db_tokyotyrant_homepage = http://cloudi.org/ +pkg_cloudi_service_db_tokyotyrant_fetch = git +pkg_cloudi_service_db_tokyotyrant_repo = https://github.com/CloudI/cloudi_service_db_tokyotyrant +pkg_cloudi_service_db_tokyotyrant_commit = master + +PACKAGES += cloudi_service_filesystem +pkg_cloudi_service_filesystem_name = cloudi_service_filesystem +pkg_cloudi_service_filesystem_description = Filesystem CloudI Service +pkg_cloudi_service_filesystem_homepage = http://cloudi.org/ +pkg_cloudi_service_filesystem_fetch = git +pkg_cloudi_service_filesystem_repo = https://github.com/CloudI/cloudi_service_filesystem +pkg_cloudi_service_filesystem_commit = master + +PACKAGES += cloudi_service_http_client +pkg_cloudi_service_http_client_name = cloudi_service_http_client +pkg_cloudi_service_http_client_description = HTTP client CloudI Service +pkg_cloudi_service_http_client_homepage = http://cloudi.org/ +pkg_cloudi_service_http_client_fetch = git +pkg_cloudi_service_http_client_repo = https://github.com/CloudI/cloudi_service_http_client +pkg_cloudi_service_http_client_commit = master + +PACKAGES += cloudi_service_http_cowboy +pkg_cloudi_service_http_cowboy_name = cloudi_service_http_cowboy +pkg_cloudi_service_http_cowboy_description = cowboy HTTP/HTTPS CloudI Service +pkg_cloudi_service_http_cowboy_homepage = http://cloudi.org/ +pkg_cloudi_service_http_cowboy_fetch = git +pkg_cloudi_service_http_cowboy_repo = https://github.com/CloudI/cloudi_service_http_cowboy +pkg_cloudi_service_http_cowboy_commit = master + +PACKAGES += cloudi_service_http_elli +pkg_cloudi_service_http_elli_name = cloudi_service_http_elli +pkg_cloudi_service_http_elli_description = elli HTTP CloudI Service +pkg_cloudi_service_http_elli_homepage = http://cloudi.org/ +pkg_cloudi_service_http_elli_fetch = git +pkg_cloudi_service_http_elli_repo = https://github.com/CloudI/cloudi_service_http_elli +pkg_cloudi_service_http_elli_commit = master + +PACKAGES += cloudi_service_map_reduce +pkg_cloudi_service_map_reduce_name = cloudi_service_map_reduce +pkg_cloudi_service_map_reduce_description = Map/Reduce CloudI Service +pkg_cloudi_service_map_reduce_homepage = http://cloudi.org/ +pkg_cloudi_service_map_reduce_fetch = git +pkg_cloudi_service_map_reduce_repo = https://github.com/CloudI/cloudi_service_map_reduce +pkg_cloudi_service_map_reduce_commit = master + +PACKAGES += cloudi_service_oauth1 +pkg_cloudi_service_oauth1_name = cloudi_service_oauth1 +pkg_cloudi_service_oauth1_description = OAuth v1.0 CloudI Service +pkg_cloudi_service_oauth1_homepage = http://cloudi.org/ +pkg_cloudi_service_oauth1_fetch = git +pkg_cloudi_service_oauth1_repo = https://github.com/CloudI/cloudi_service_oauth1 +pkg_cloudi_service_oauth1_commit = master + +PACKAGES += cloudi_service_queue +pkg_cloudi_service_queue_name = cloudi_service_queue +pkg_cloudi_service_queue_description = Persistent Queue Service +pkg_cloudi_service_queue_homepage = http://cloudi.org/ +pkg_cloudi_service_queue_fetch = git +pkg_cloudi_service_queue_repo = https://github.com/CloudI/cloudi_service_queue +pkg_cloudi_service_queue_commit = master + +PACKAGES += cloudi_service_quorum +pkg_cloudi_service_quorum_name = cloudi_service_quorum +pkg_cloudi_service_quorum_description = CloudI Quorum Service +pkg_cloudi_service_quorum_homepage = http://cloudi.org/ +pkg_cloudi_service_quorum_fetch = git +pkg_cloudi_service_quorum_repo = https://github.com/CloudI/cloudi_service_quorum +pkg_cloudi_service_quorum_commit = master + +PACKAGES += cloudi_service_router +pkg_cloudi_service_router_name = cloudi_service_router +pkg_cloudi_service_router_description = CloudI Router Service +pkg_cloudi_service_router_homepage = http://cloudi.org/ +pkg_cloudi_service_router_fetch = git +pkg_cloudi_service_router_repo = https://github.com/CloudI/cloudi_service_router +pkg_cloudi_service_router_commit = master + +PACKAGES += cloudi_service_tcp +pkg_cloudi_service_tcp_name = cloudi_service_tcp +pkg_cloudi_service_tcp_description = TCP CloudI Service +pkg_cloudi_service_tcp_homepage = http://cloudi.org/ +pkg_cloudi_service_tcp_fetch = git +pkg_cloudi_service_tcp_repo = https://github.com/CloudI/cloudi_service_tcp +pkg_cloudi_service_tcp_commit = master + +PACKAGES += cloudi_service_timers +pkg_cloudi_service_timers_name = cloudi_service_timers +pkg_cloudi_service_timers_description = Timers CloudI Service +pkg_cloudi_service_timers_homepage = http://cloudi.org/ +pkg_cloudi_service_timers_fetch = git +pkg_cloudi_service_timers_repo = https://github.com/CloudI/cloudi_service_timers +pkg_cloudi_service_timers_commit = master + +PACKAGES += cloudi_service_udp +pkg_cloudi_service_udp_name = cloudi_service_udp +pkg_cloudi_service_udp_description = UDP CloudI Service +pkg_cloudi_service_udp_homepage = http://cloudi.org/ +pkg_cloudi_service_udp_fetch = git +pkg_cloudi_service_udp_repo = https://github.com/CloudI/cloudi_service_udp +pkg_cloudi_service_udp_commit = master + +PACKAGES += cloudi_service_validate +pkg_cloudi_service_validate_name = cloudi_service_validate +pkg_cloudi_service_validate_description = CloudI Validate Service +pkg_cloudi_service_validate_homepage = http://cloudi.org/ +pkg_cloudi_service_validate_fetch = git +pkg_cloudi_service_validate_repo = https://github.com/CloudI/cloudi_service_validate +pkg_cloudi_service_validate_commit = master + +PACKAGES += cloudi_service_zeromq +pkg_cloudi_service_zeromq_name = cloudi_service_zeromq +pkg_cloudi_service_zeromq_description = ZeroMQ CloudI Service +pkg_cloudi_service_zeromq_homepage = http://cloudi.org/ +pkg_cloudi_service_zeromq_fetch = git +pkg_cloudi_service_zeromq_repo = https://github.com/CloudI/cloudi_service_zeromq +pkg_cloudi_service_zeromq_commit = master + +PACKAGES += cluster_info +pkg_cluster_info_name = cluster_info +pkg_cluster_info_description = Fork of Hibari's nifty cluster_info OTP app +pkg_cluster_info_homepage = https://github.com/basho/cluster_info +pkg_cluster_info_fetch = git +pkg_cluster_info_repo = https://github.com/basho/cluster_info +pkg_cluster_info_commit = master + +PACKAGES += color +pkg_color_name = color +pkg_color_description = ANSI colors for your Erlang +pkg_color_homepage = https://github.com/julianduque/erlang-color +pkg_color_fetch = git +pkg_color_repo = https://github.com/julianduque/erlang-color +pkg_color_commit = master + +PACKAGES += confetti +pkg_confetti_name = confetti +pkg_confetti_description = Erlang configuration provider / application:get_env/2 on steroids +pkg_confetti_homepage = https://github.com/jtendo/confetti +pkg_confetti_fetch = git +pkg_confetti_repo = https://github.com/jtendo/confetti +pkg_confetti_commit = master + +PACKAGES += couchbeam +pkg_couchbeam_name = couchbeam +pkg_couchbeam_description = Apache CouchDB client in Erlang +pkg_couchbeam_homepage = https://github.com/benoitc/couchbeam +pkg_couchbeam_fetch = git +pkg_couchbeam_repo = https://github.com/benoitc/couchbeam +pkg_couchbeam_commit = master + +PACKAGES += covertool +pkg_covertool_name = covertool +pkg_covertool_description = Tool to convert Erlang cover data files into Cobertura XML reports +pkg_covertool_homepage = https://github.com/idubrov/covertool +pkg_covertool_fetch = git +pkg_covertool_repo = https://github.com/idubrov/covertool +pkg_covertool_commit = master + +PACKAGES += cowboy +pkg_cowboy_name = cowboy +pkg_cowboy_description = Small, fast and modular HTTP server. +pkg_cowboy_homepage = http://ninenines.eu +pkg_cowboy_fetch = git +pkg_cowboy_repo = https://github.com/ninenines/cowboy +pkg_cowboy_commit = 1.0.4 + +PACKAGES += cowdb +pkg_cowdb_name = cowdb +pkg_cowdb_description = Pure Key/Value database library for Erlang Applications +pkg_cowdb_homepage = https://github.com/refuge/cowdb +pkg_cowdb_fetch = git +pkg_cowdb_repo = https://github.com/refuge/cowdb +pkg_cowdb_commit = master + +PACKAGES += cowlib +pkg_cowlib_name = cowlib +pkg_cowlib_description = Support library for manipulating Web protocols. +pkg_cowlib_homepage = http://ninenines.eu +pkg_cowlib_fetch = git +pkg_cowlib_repo = https://github.com/ninenines/cowlib +pkg_cowlib_commit = 1.0.2 + +PACKAGES += cpg +pkg_cpg_name = cpg +pkg_cpg_description = CloudI Process Groups +pkg_cpg_homepage = https://github.com/okeuday/cpg +pkg_cpg_fetch = git +pkg_cpg_repo = https://github.com/okeuday/cpg +pkg_cpg_commit = master + +PACKAGES += cqerl +pkg_cqerl_name = cqerl +pkg_cqerl_description = Native Erlang CQL client for Cassandra +pkg_cqerl_homepage = https://matehat.github.io/cqerl/ +pkg_cqerl_fetch = git +pkg_cqerl_repo = https://github.com/matehat/cqerl +pkg_cqerl_commit = master + +PACKAGES += cr +pkg_cr_name = cr +pkg_cr_description = Chain Replication +pkg_cr_homepage = https://synrc.com/apps/cr/doc/cr.htm +pkg_cr_fetch = git +pkg_cr_repo = https://github.com/spawnproc/cr +pkg_cr_commit = master + +PACKAGES += cuttlefish +pkg_cuttlefish_name = cuttlefish +pkg_cuttlefish_description = never lose your childlike sense of wonder baby cuttlefish, promise me? +pkg_cuttlefish_homepage = https://github.com/basho/cuttlefish +pkg_cuttlefish_fetch = git +pkg_cuttlefish_repo = https://github.com/basho/cuttlefish +pkg_cuttlefish_commit = master + +PACKAGES += damocles +pkg_damocles_name = damocles +pkg_damocles_description = Erlang library for generating adversarial network conditions for QAing distributed applications/systems on a single Linux box. +pkg_damocles_homepage = https://github.com/lostcolony/damocles +pkg_damocles_fetch = git +pkg_damocles_repo = https://github.com/lostcolony/damocles +pkg_damocles_commit = master + +PACKAGES += debbie +pkg_debbie_name = debbie +pkg_debbie_description = .DEB Built In Erlang +pkg_debbie_homepage = https://github.com/crownedgrouse/debbie +pkg_debbie_fetch = git +pkg_debbie_repo = https://github.com/crownedgrouse/debbie +pkg_debbie_commit = master + +PACKAGES += decimal +pkg_decimal_name = decimal +pkg_decimal_description = An Erlang decimal arithmetic library +pkg_decimal_homepage = https://github.com/tim/erlang-decimal +pkg_decimal_fetch = git +pkg_decimal_repo = https://github.com/tim/erlang-decimal +pkg_decimal_commit = master + +PACKAGES += detergent +pkg_detergent_name = detergent +pkg_detergent_description = An emulsifying Erlang SOAP library +pkg_detergent_homepage = https://github.com/devinus/detergent +pkg_detergent_fetch = git +pkg_detergent_repo = https://github.com/devinus/detergent +pkg_detergent_commit = master + +PACKAGES += detest +pkg_detest_name = detest +pkg_detest_description = Tool for running tests on a cluster of erlang nodes +pkg_detest_homepage = https://github.com/biokoda/detest +pkg_detest_fetch = git +pkg_detest_repo = https://github.com/biokoda/detest +pkg_detest_commit = master + +PACKAGES += dh_date +pkg_dh_date_name = dh_date +pkg_dh_date_description = Date formatting / parsing library for erlang +pkg_dh_date_homepage = https://github.com/daleharvey/dh_date +pkg_dh_date_fetch = git +pkg_dh_date_repo = https://github.com/daleharvey/dh_date +pkg_dh_date_commit = master + +PACKAGES += dirbusterl +pkg_dirbusterl_name = dirbusterl +pkg_dirbusterl_description = DirBuster successor in Erlang +pkg_dirbusterl_homepage = https://github.com/silentsignal/DirBustErl +pkg_dirbusterl_fetch = git +pkg_dirbusterl_repo = https://github.com/silentsignal/DirBustErl +pkg_dirbusterl_commit = master + +PACKAGES += dispcount +pkg_dispcount_name = dispcount +pkg_dispcount_description = Erlang task dispatcher based on ETS counters. +pkg_dispcount_homepage = https://github.com/ferd/dispcount +pkg_dispcount_fetch = git +pkg_dispcount_repo = https://github.com/ferd/dispcount +pkg_dispcount_commit = master + +PACKAGES += dlhttpc +pkg_dlhttpc_name = dlhttpc +pkg_dlhttpc_description = dispcount-based lhttpc fork for massive amounts of requests to limited endpoints +pkg_dlhttpc_homepage = https://github.com/ferd/dlhttpc +pkg_dlhttpc_fetch = git +pkg_dlhttpc_repo = https://github.com/ferd/dlhttpc +pkg_dlhttpc_commit = master + +PACKAGES += dns +pkg_dns_name = dns +pkg_dns_description = Erlang DNS library +pkg_dns_homepage = https://github.com/aetrion/dns_erlang +pkg_dns_fetch = git +pkg_dns_repo = https://github.com/aetrion/dns_erlang +pkg_dns_commit = master + +PACKAGES += dnssd +pkg_dnssd_name = dnssd +pkg_dnssd_description = Erlang interface to Apple's Bonjour D NS Service Discovery implementation +pkg_dnssd_homepage = https://github.com/benoitc/dnssd_erlang +pkg_dnssd_fetch = git +pkg_dnssd_repo = https://github.com/benoitc/dnssd_erlang +pkg_dnssd_commit = master + +PACKAGES += dtl +pkg_dtl_name = dtl +pkg_dtl_description = Django Template Language: A full-featured port of the Django template engine to Erlang. +pkg_dtl_homepage = https://github.com/oinksoft/dtl +pkg_dtl_fetch = git +pkg_dtl_repo = https://github.com/oinksoft/dtl +pkg_dtl_commit = master + +PACKAGES += dynamic_compile +pkg_dynamic_compile_name = dynamic_compile +pkg_dynamic_compile_description = compile and load erlang modules from string input +pkg_dynamic_compile_homepage = https://github.com/jkvor/dynamic_compile +pkg_dynamic_compile_fetch = git +pkg_dynamic_compile_repo = https://github.com/jkvor/dynamic_compile +pkg_dynamic_compile_commit = master + +PACKAGES += e2 +pkg_e2_name = e2 +pkg_e2_description = Library to simply writing correct OTP applications. +pkg_e2_homepage = http://e2project.org +pkg_e2_fetch = git +pkg_e2_repo = https://github.com/gar1t/e2 +pkg_e2_commit = master + +PACKAGES += eamf +pkg_eamf_name = eamf +pkg_eamf_description = eAMF provides Action Message Format (AMF) support for Erlang +pkg_eamf_homepage = https://github.com/mrinalwadhwa/eamf +pkg_eamf_fetch = git +pkg_eamf_repo = https://github.com/mrinalwadhwa/eamf +pkg_eamf_commit = master + +PACKAGES += eavro +pkg_eavro_name = eavro +pkg_eavro_description = Apache Avro encoder/decoder +pkg_eavro_homepage = https://github.com/SIfoxDevTeam/eavro +pkg_eavro_fetch = git +pkg_eavro_repo = https://github.com/SIfoxDevTeam/eavro +pkg_eavro_commit = master + +PACKAGES += ecapnp +pkg_ecapnp_name = ecapnp +pkg_ecapnp_description = Cap'n Proto library for Erlang +pkg_ecapnp_homepage = https://github.com/kaos/ecapnp +pkg_ecapnp_fetch = git +pkg_ecapnp_repo = https://github.com/kaos/ecapnp +pkg_ecapnp_commit = master + +PACKAGES += econfig +pkg_econfig_name = econfig +pkg_econfig_description = simple Erlang config handler using INI files +pkg_econfig_homepage = https://github.com/benoitc/econfig +pkg_econfig_fetch = git +pkg_econfig_repo = https://github.com/benoitc/econfig +pkg_econfig_commit = master + +PACKAGES += edate +pkg_edate_name = edate +pkg_edate_description = date manipulation library for erlang +pkg_edate_homepage = https://github.com/dweldon/edate +pkg_edate_fetch = git +pkg_edate_repo = https://github.com/dweldon/edate +pkg_edate_commit = master + +PACKAGES += edgar +pkg_edgar_name = edgar +pkg_edgar_description = Erlang Does GNU AR +pkg_edgar_homepage = https://github.com/crownedgrouse/edgar +pkg_edgar_fetch = git +pkg_edgar_repo = https://github.com/crownedgrouse/edgar +pkg_edgar_commit = master + +PACKAGES += edis +pkg_edis_name = edis +pkg_edis_description = An Erlang implementation of Redis KV Store +pkg_edis_homepage = http://inaka.github.com/edis/ +pkg_edis_fetch = git +pkg_edis_repo = https://github.com/inaka/edis +pkg_edis_commit = master + +PACKAGES += edns +pkg_edns_name = edns +pkg_edns_description = Erlang/OTP DNS server +pkg_edns_homepage = https://github.com/hcvst/erlang-dns +pkg_edns_fetch = git +pkg_edns_repo = https://github.com/hcvst/erlang-dns +pkg_edns_commit = master + +PACKAGES += edown +pkg_edown_name = edown +pkg_edown_description = EDoc extension for generating Github-flavored Markdown +pkg_edown_homepage = https://github.com/uwiger/edown +pkg_edown_fetch = git +pkg_edown_repo = https://github.com/uwiger/edown +pkg_edown_commit = master + +PACKAGES += eep +pkg_eep_name = eep +pkg_eep_description = Erlang Easy Profiling (eep) application provides a way to analyze application performance and call hierarchy +pkg_eep_homepage = https://github.com/virtan/eep +pkg_eep_fetch = git +pkg_eep_repo = https://github.com/virtan/eep +pkg_eep_commit = master + +PACKAGES += eep_app +pkg_eep_app_name = eep_app +pkg_eep_app_description = Embedded Event Processing +pkg_eep_app_homepage = https://github.com/darach/eep-erl +pkg_eep_app_fetch = git +pkg_eep_app_repo = https://github.com/darach/eep-erl +pkg_eep_app_commit = master + +PACKAGES += efene +pkg_efene_name = efene +pkg_efene_description = Alternative syntax for the Erlang Programming Language focusing on simplicity, ease of use and programmer UX +pkg_efene_homepage = https://github.com/efene/efene +pkg_efene_fetch = git +pkg_efene_repo = https://github.com/efene/efene +pkg_efene_commit = master + +PACKAGES += egeoip +pkg_egeoip_name = egeoip +pkg_egeoip_description = Erlang IP Geolocation module, currently supporting the MaxMind GeoLite City Database. +pkg_egeoip_homepage = https://github.com/mochi/egeoip +pkg_egeoip_fetch = git +pkg_egeoip_repo = https://github.com/mochi/egeoip +pkg_egeoip_commit = master + +PACKAGES += ehsa +pkg_ehsa_name = ehsa +pkg_ehsa_description = Erlang HTTP server basic and digest authentication modules +pkg_ehsa_homepage = https://bitbucket.org/a12n/ehsa +pkg_ehsa_fetch = hg +pkg_ehsa_repo = https://bitbucket.org/a12n/ehsa +pkg_ehsa_commit = default + +PACKAGES += ej +pkg_ej_name = ej +pkg_ej_description = Helper module for working with Erlang terms representing JSON +pkg_ej_homepage = https://github.com/seth/ej +pkg_ej_fetch = git +pkg_ej_repo = https://github.com/seth/ej +pkg_ej_commit = master + +PACKAGES += ejabberd +pkg_ejabberd_name = ejabberd +pkg_ejabberd_description = Robust, ubiquitous and massively scalable Jabber / XMPP Instant Messaging platform +pkg_ejabberd_homepage = https://github.com/processone/ejabberd +pkg_ejabberd_fetch = git +pkg_ejabberd_repo = https://github.com/processone/ejabberd +pkg_ejabberd_commit = master + +PACKAGES += ejwt +pkg_ejwt_name = ejwt +pkg_ejwt_description = erlang library for JSON Web Token +pkg_ejwt_homepage = https://github.com/artefactop/ejwt +pkg_ejwt_fetch = git +pkg_ejwt_repo = https://github.com/artefactop/ejwt +pkg_ejwt_commit = master + +PACKAGES += ekaf +pkg_ekaf_name = ekaf +pkg_ekaf_description = A minimal, high-performance Kafka client in Erlang. +pkg_ekaf_homepage = https://github.com/helpshift/ekaf +pkg_ekaf_fetch = git +pkg_ekaf_repo = https://github.com/helpshift/ekaf +pkg_ekaf_commit = master + +PACKAGES += elarm +pkg_elarm_name = elarm +pkg_elarm_description = Alarm Manager for Erlang. +pkg_elarm_homepage = https://github.com/esl/elarm +pkg_elarm_fetch = git +pkg_elarm_repo = https://github.com/esl/elarm +pkg_elarm_commit = master + +PACKAGES += eleveldb +pkg_eleveldb_name = eleveldb +pkg_eleveldb_description = Erlang LevelDB API +pkg_eleveldb_homepage = https://github.com/basho/eleveldb +pkg_eleveldb_fetch = git +pkg_eleveldb_repo = https://github.com/basho/eleveldb +pkg_eleveldb_commit = master + +PACKAGES += elli +pkg_elli_name = elli +pkg_elli_description = Simple, robust and performant Erlang web server +pkg_elli_homepage = https://github.com/knutin/elli +pkg_elli_fetch = git +pkg_elli_repo = https://github.com/knutin/elli +pkg_elli_commit = master + +PACKAGES += elvis +pkg_elvis_name = elvis +pkg_elvis_description = Erlang Style Reviewer +pkg_elvis_homepage = https://github.com/inaka/elvis +pkg_elvis_fetch = git +pkg_elvis_repo = https://github.com/inaka/elvis +pkg_elvis_commit = master + +PACKAGES += emagick +pkg_emagick_name = emagick +pkg_emagick_description = Wrapper for Graphics/ImageMagick command line tool. +pkg_emagick_homepage = https://github.com/kivra/emagick +pkg_emagick_fetch = git +pkg_emagick_repo = https://github.com/kivra/emagick +pkg_emagick_commit = master + +PACKAGES += emysql +pkg_emysql_name = emysql +pkg_emysql_description = Stable, pure Erlang MySQL driver. +pkg_emysql_homepage = https://github.com/Eonblast/Emysql +pkg_emysql_fetch = git +pkg_emysql_repo = https://github.com/Eonblast/Emysql +pkg_emysql_commit = master + +PACKAGES += enm +pkg_enm_name = enm +pkg_enm_description = Erlang driver for nanomsg +pkg_enm_homepage = https://github.com/basho/enm +pkg_enm_fetch = git +pkg_enm_repo = https://github.com/basho/enm +pkg_enm_commit = master + +PACKAGES += entop +pkg_entop_name = entop +pkg_entop_description = A top-like tool for monitoring an Erlang node +pkg_entop_homepage = https://github.com/mazenharake/entop +pkg_entop_fetch = git +pkg_entop_repo = https://github.com/mazenharake/entop +pkg_entop_commit = master + +PACKAGES += epcap +pkg_epcap_name = epcap +pkg_epcap_description = Erlang packet capture interface using pcap +pkg_epcap_homepage = https://github.com/msantos/epcap +pkg_epcap_fetch = git +pkg_epcap_repo = https://github.com/msantos/epcap +pkg_epcap_commit = master + +PACKAGES += eper +pkg_eper_name = eper +pkg_eper_description = Erlang performance and debugging tools. +pkg_eper_homepage = https://github.com/massemanet/eper +pkg_eper_fetch = git +pkg_eper_repo = https://github.com/massemanet/eper +pkg_eper_commit = master + +PACKAGES += epgsql +pkg_epgsql_name = epgsql +pkg_epgsql_description = Erlang PostgreSQL client library. +pkg_epgsql_homepage = https://github.com/epgsql/epgsql +pkg_epgsql_fetch = git +pkg_epgsql_repo = https://github.com/epgsql/epgsql +pkg_epgsql_commit = master + +PACKAGES += episcina +pkg_episcina_name = episcina +pkg_episcina_description = A simple non intrusive resource pool for connections +pkg_episcina_homepage = https://github.com/erlware/episcina +pkg_episcina_fetch = git +pkg_episcina_repo = https://github.com/erlware/episcina +pkg_episcina_commit = master + +PACKAGES += eplot +pkg_eplot_name = eplot +pkg_eplot_description = A plot engine written in erlang. +pkg_eplot_homepage = https://github.com/psyeugenic/eplot +pkg_eplot_fetch = git +pkg_eplot_repo = https://github.com/psyeugenic/eplot +pkg_eplot_commit = master + +PACKAGES += epocxy +pkg_epocxy_name = epocxy +pkg_epocxy_description = Erlang Patterns of Concurrency +pkg_epocxy_homepage = https://github.com/duomark/epocxy +pkg_epocxy_fetch = git +pkg_epocxy_repo = https://github.com/duomark/epocxy +pkg_epocxy_commit = master + +PACKAGES += epubnub +pkg_epubnub_name = epubnub +pkg_epubnub_description = Erlang PubNub API +pkg_epubnub_homepage = https://github.com/tsloughter/epubnub +pkg_epubnub_fetch = git +pkg_epubnub_repo = https://github.com/tsloughter/epubnub +pkg_epubnub_commit = master + +PACKAGES += eqm +pkg_eqm_name = eqm +pkg_eqm_description = Erlang pub sub with supply-demand channels +pkg_eqm_homepage = https://github.com/loucash/eqm +pkg_eqm_fetch = git +pkg_eqm_repo = https://github.com/loucash/eqm +pkg_eqm_commit = master + +PACKAGES += eredis +pkg_eredis_name = eredis +pkg_eredis_description = Erlang Redis client +pkg_eredis_homepage = https://github.com/wooga/eredis +pkg_eredis_fetch = git +pkg_eredis_repo = https://github.com/wooga/eredis +pkg_eredis_commit = master + +PACKAGES += eredis_pool +pkg_eredis_pool_name = eredis_pool +pkg_eredis_pool_description = eredis_pool is Pool of Redis clients, using eredis and poolboy. +pkg_eredis_pool_homepage = https://github.com/hiroeorz/eredis_pool +pkg_eredis_pool_fetch = git +pkg_eredis_pool_repo = https://github.com/hiroeorz/eredis_pool +pkg_eredis_pool_commit = master + +PACKAGES += erl_streams +pkg_erl_streams_name = erl_streams +pkg_erl_streams_description = Streams in Erlang +pkg_erl_streams_homepage = https://github.com/epappas/erl_streams +pkg_erl_streams_fetch = git +pkg_erl_streams_repo = https://github.com/epappas/erl_streams +pkg_erl_streams_commit = master + +PACKAGES += erlang_cep +pkg_erlang_cep_name = erlang_cep +pkg_erlang_cep_description = A basic CEP package written in erlang +pkg_erlang_cep_homepage = https://github.com/danmacklin/erlang_cep +pkg_erlang_cep_fetch = git +pkg_erlang_cep_repo = https://github.com/danmacklin/erlang_cep +pkg_erlang_cep_commit = master + +PACKAGES += erlang_js +pkg_erlang_js_name = erlang_js +pkg_erlang_js_description = A linked-in driver for Erlang to Mozilla's Spidermonkey Javascript runtime. +pkg_erlang_js_homepage = https://github.com/basho/erlang_js +pkg_erlang_js_fetch = git +pkg_erlang_js_repo = https://github.com/basho/erlang_js +pkg_erlang_js_commit = master + +PACKAGES += erlang_localtime +pkg_erlang_localtime_name = erlang_localtime +pkg_erlang_localtime_description = Erlang library for conversion from one local time to another +pkg_erlang_localtime_homepage = https://github.com/dmitryme/erlang_localtime +pkg_erlang_localtime_fetch = git +pkg_erlang_localtime_repo = https://github.com/dmitryme/erlang_localtime +pkg_erlang_localtime_commit = master + +PACKAGES += erlang_smtp +pkg_erlang_smtp_name = erlang_smtp +pkg_erlang_smtp_description = Erlang SMTP and POP3 server code. +pkg_erlang_smtp_homepage = https://github.com/tonyg/erlang-smtp +pkg_erlang_smtp_fetch = git +pkg_erlang_smtp_repo = https://github.com/tonyg/erlang-smtp +pkg_erlang_smtp_commit = master + +PACKAGES += erlang_term +pkg_erlang_term_name = erlang_term +pkg_erlang_term_description = Erlang Term Info +pkg_erlang_term_homepage = https://github.com/okeuday/erlang_term +pkg_erlang_term_fetch = git +pkg_erlang_term_repo = https://github.com/okeuday/erlang_term +pkg_erlang_term_commit = master + +PACKAGES += erlastic_search +pkg_erlastic_search_name = erlastic_search +pkg_erlastic_search_description = An Erlang app for communicating with Elastic Search's rest interface. +pkg_erlastic_search_homepage = https://github.com/tsloughter/erlastic_search +pkg_erlastic_search_fetch = git +pkg_erlastic_search_repo = https://github.com/tsloughter/erlastic_search +pkg_erlastic_search_commit = master + +PACKAGES += erlasticsearch +pkg_erlasticsearch_name = erlasticsearch +pkg_erlasticsearch_description = Erlang thrift interface to elastic_search +pkg_erlasticsearch_homepage = https://github.com/dieswaytoofast/erlasticsearch +pkg_erlasticsearch_fetch = git +pkg_erlasticsearch_repo = https://github.com/dieswaytoofast/erlasticsearch +pkg_erlasticsearch_commit = master + +PACKAGES += erlbrake +pkg_erlbrake_name = erlbrake +pkg_erlbrake_description = Erlang Airbrake notification client +pkg_erlbrake_homepage = https://github.com/kenpratt/erlbrake +pkg_erlbrake_fetch = git +pkg_erlbrake_repo = https://github.com/kenpratt/erlbrake +pkg_erlbrake_commit = master + +PACKAGES += erlcloud +pkg_erlcloud_name = erlcloud +pkg_erlcloud_description = Cloud Computing library for erlang (Amazon EC2, S3, SQS, SimpleDB, Mechanical Turk, ELB) +pkg_erlcloud_homepage = https://github.com/gleber/erlcloud +pkg_erlcloud_fetch = git +pkg_erlcloud_repo = https://github.com/gleber/erlcloud +pkg_erlcloud_commit = master + +PACKAGES += erlcron +pkg_erlcron_name = erlcron +pkg_erlcron_description = Erlang cronish system +pkg_erlcron_homepage = https://github.com/erlware/erlcron +pkg_erlcron_fetch = git +pkg_erlcron_repo = https://github.com/erlware/erlcron +pkg_erlcron_commit = master + +PACKAGES += erldb +pkg_erldb_name = erldb +pkg_erldb_description = ORM (Object-relational mapping) application implemented in Erlang +pkg_erldb_homepage = http://erldb.org +pkg_erldb_fetch = git +pkg_erldb_repo = https://github.com/erldb/erldb +pkg_erldb_commit = master + +PACKAGES += erldis +pkg_erldis_name = erldis +pkg_erldis_description = redis erlang client library +pkg_erldis_homepage = https://github.com/cstar/erldis +pkg_erldis_fetch = git +pkg_erldis_repo = https://github.com/cstar/erldis +pkg_erldis_commit = master + +PACKAGES += erldns +pkg_erldns_name = erldns +pkg_erldns_description = DNS server, in erlang. +pkg_erldns_homepage = https://github.com/aetrion/erl-dns +pkg_erldns_fetch = git +pkg_erldns_repo = https://github.com/aetrion/erl-dns +pkg_erldns_commit = master + +PACKAGES += erldocker +pkg_erldocker_name = erldocker +pkg_erldocker_description = Docker Remote API client for Erlang +pkg_erldocker_homepage = https://github.com/proger/erldocker +pkg_erldocker_fetch = git +pkg_erldocker_repo = https://github.com/proger/erldocker +pkg_erldocker_commit = master + +PACKAGES += erlfsmon +pkg_erlfsmon_name = erlfsmon +pkg_erlfsmon_description = Erlang filesystem event watcher for Linux and OSX +pkg_erlfsmon_homepage = https://github.com/proger/erlfsmon +pkg_erlfsmon_fetch = git +pkg_erlfsmon_repo = https://github.com/proger/erlfsmon +pkg_erlfsmon_commit = master + +PACKAGES += erlgit +pkg_erlgit_name = erlgit +pkg_erlgit_description = Erlang convenience wrapper around git executable +pkg_erlgit_homepage = https://github.com/gleber/erlgit +pkg_erlgit_fetch = git +pkg_erlgit_repo = https://github.com/gleber/erlgit +pkg_erlgit_commit = master + +PACKAGES += erlguten +pkg_erlguten_name = erlguten +pkg_erlguten_description = ErlGuten is a system for high-quality typesetting, written purely in Erlang. +pkg_erlguten_homepage = https://github.com/richcarl/erlguten +pkg_erlguten_fetch = git +pkg_erlguten_repo = https://github.com/richcarl/erlguten +pkg_erlguten_commit = master + +PACKAGES += erlmc +pkg_erlmc_name = erlmc +pkg_erlmc_description = Erlang memcached binary protocol client +pkg_erlmc_homepage = https://github.com/jkvor/erlmc +pkg_erlmc_fetch = git +pkg_erlmc_repo = https://github.com/jkvor/erlmc +pkg_erlmc_commit = master + +PACKAGES += erlmongo +pkg_erlmongo_name = erlmongo +pkg_erlmongo_description = Record based Erlang driver for MongoDB with gridfs support +pkg_erlmongo_homepage = https://github.com/SergejJurecko/erlmongo +pkg_erlmongo_fetch = git +pkg_erlmongo_repo = https://github.com/SergejJurecko/erlmongo +pkg_erlmongo_commit = master + +PACKAGES += erlog +pkg_erlog_name = erlog +pkg_erlog_description = Prolog interpreter in and for Erlang +pkg_erlog_homepage = https://github.com/rvirding/erlog +pkg_erlog_fetch = git +pkg_erlog_repo = https://github.com/rvirding/erlog +pkg_erlog_commit = master + +PACKAGES += erlpass +pkg_erlpass_name = erlpass +pkg_erlpass_description = A library to handle password hashing and changing in a safe manner, independent from any kind of storage whatsoever. +pkg_erlpass_homepage = https://github.com/ferd/erlpass +pkg_erlpass_fetch = git +pkg_erlpass_repo = https://github.com/ferd/erlpass +pkg_erlpass_commit = master + +PACKAGES += erlport +pkg_erlport_name = erlport +pkg_erlport_description = ErlPort - connect Erlang to other languages +pkg_erlport_homepage = https://github.com/hdima/erlport +pkg_erlport_fetch = git +pkg_erlport_repo = https://github.com/hdima/erlport +pkg_erlport_commit = master + +PACKAGES += erlsh +pkg_erlsh_name = erlsh +pkg_erlsh_description = Erlang shell tools +pkg_erlsh_homepage = https://github.com/proger/erlsh +pkg_erlsh_fetch = git +pkg_erlsh_repo = https://github.com/proger/erlsh +pkg_erlsh_commit = master + +PACKAGES += erlsha2 +pkg_erlsha2_name = erlsha2 +pkg_erlsha2_description = SHA-224, SHA-256, SHA-384, SHA-512 implemented in Erlang NIFs. +pkg_erlsha2_homepage = https://github.com/vinoski/erlsha2 +pkg_erlsha2_fetch = git +pkg_erlsha2_repo = https://github.com/vinoski/erlsha2 +pkg_erlsha2_commit = master + +PACKAGES += erlsom +pkg_erlsom_name = erlsom +pkg_erlsom_description = XML parser for Erlang +pkg_erlsom_homepage = https://github.com/willemdj/erlsom +pkg_erlsom_fetch = git +pkg_erlsom_repo = https://github.com/willemdj/erlsom +pkg_erlsom_commit = master + +PACKAGES += erlubi +pkg_erlubi_name = erlubi +pkg_erlubi_description = Ubigraph Erlang Client (and Process Visualizer) +pkg_erlubi_homepage = https://github.com/krestenkrab/erlubi +pkg_erlubi_fetch = git +pkg_erlubi_repo = https://github.com/krestenkrab/erlubi +pkg_erlubi_commit = master + +PACKAGES += erlvolt +pkg_erlvolt_name = erlvolt +pkg_erlvolt_description = VoltDB Erlang Client Driver +pkg_erlvolt_homepage = https://github.com/VoltDB/voltdb-client-erlang +pkg_erlvolt_fetch = git +pkg_erlvolt_repo = https://github.com/VoltDB/voltdb-client-erlang +pkg_erlvolt_commit = master + +PACKAGES += erlware_commons +pkg_erlware_commons_name = erlware_commons +pkg_erlware_commons_description = Erlware Commons is an Erlware project focused on all aspects of reusable Erlang components. +pkg_erlware_commons_homepage = https://github.com/erlware/erlware_commons +pkg_erlware_commons_fetch = git +pkg_erlware_commons_repo = https://github.com/erlware/erlware_commons +pkg_erlware_commons_commit = master + +PACKAGES += erlydtl +pkg_erlydtl_name = erlydtl +pkg_erlydtl_description = Django Template Language for Erlang. +pkg_erlydtl_homepage = https://github.com/erlydtl/erlydtl +pkg_erlydtl_fetch = git +pkg_erlydtl_repo = https://github.com/erlydtl/erlydtl +pkg_erlydtl_commit = master + +PACKAGES += errd +pkg_errd_name = errd +pkg_errd_description = Erlang RRDTool library +pkg_errd_homepage = https://github.com/archaelus/errd +pkg_errd_fetch = git +pkg_errd_repo = https://github.com/archaelus/errd +pkg_errd_commit = master + +PACKAGES += erserve +pkg_erserve_name = erserve +pkg_erserve_description = Erlang/Rserve communication interface +pkg_erserve_homepage = https://github.com/del/erserve +pkg_erserve_fetch = git +pkg_erserve_repo = https://github.com/del/erserve +pkg_erserve_commit = master + +PACKAGES += erwa +pkg_erwa_name = erwa +pkg_erwa_description = A WAMP router and client written in Erlang. +pkg_erwa_homepage = https://github.com/bwegh/erwa +pkg_erwa_fetch = git +pkg_erwa_repo = https://github.com/bwegh/erwa +pkg_erwa_commit = master + +PACKAGES += espec +pkg_espec_name = espec +pkg_espec_description = ESpec: Behaviour driven development framework for Erlang +pkg_espec_homepage = https://github.com/lucaspiller/espec +pkg_espec_fetch = git +pkg_espec_repo = https://github.com/lucaspiller/espec +pkg_espec_commit = master + +PACKAGES += estatsd +pkg_estatsd_name = estatsd +pkg_estatsd_description = Erlang stats aggregation app that periodically flushes data to graphite +pkg_estatsd_homepage = https://github.com/RJ/estatsd +pkg_estatsd_fetch = git +pkg_estatsd_repo = https://github.com/RJ/estatsd +pkg_estatsd_commit = master + +PACKAGES += etap +pkg_etap_name = etap +pkg_etap_description = etap is a simple erlang testing library that provides TAP compliant output. +pkg_etap_homepage = https://github.com/ngerakines/etap +pkg_etap_fetch = git +pkg_etap_repo = https://github.com/ngerakines/etap +pkg_etap_commit = master + +PACKAGES += etest +pkg_etest_name = etest +pkg_etest_description = A lightweight, convention over configuration test framework for Erlang +pkg_etest_homepage = https://github.com/wooga/etest +pkg_etest_fetch = git +pkg_etest_repo = https://github.com/wooga/etest +pkg_etest_commit = master + +PACKAGES += etest_http +pkg_etest_http_name = etest_http +pkg_etest_http_description = etest Assertions around HTTP (client-side) +pkg_etest_http_homepage = https://github.com/wooga/etest_http +pkg_etest_http_fetch = git +pkg_etest_http_repo = https://github.com/wooga/etest_http +pkg_etest_http_commit = master + +PACKAGES += etoml +pkg_etoml_name = etoml +pkg_etoml_description = TOML language erlang parser +pkg_etoml_homepage = https://github.com/kalta/etoml +pkg_etoml_fetch = git +pkg_etoml_repo = https://github.com/kalta/etoml +pkg_etoml_commit = master + +PACKAGES += eunit +pkg_eunit_name = eunit +pkg_eunit_description = The EUnit lightweight unit testing framework for Erlang - this is the canonical development repository. +pkg_eunit_homepage = https://github.com/richcarl/eunit +pkg_eunit_fetch = git +pkg_eunit_repo = https://github.com/richcarl/eunit +pkg_eunit_commit = master + +PACKAGES += eunit_formatters +pkg_eunit_formatters_name = eunit_formatters +pkg_eunit_formatters_description = Because eunit's output sucks. Let's make it better. +pkg_eunit_formatters_homepage = https://github.com/seancribbs/eunit_formatters +pkg_eunit_formatters_fetch = git +pkg_eunit_formatters_repo = https://github.com/seancribbs/eunit_formatters +pkg_eunit_formatters_commit = master + +PACKAGES += euthanasia +pkg_euthanasia_name = euthanasia +pkg_euthanasia_description = Merciful killer for your Erlang processes +pkg_euthanasia_homepage = https://github.com/doubleyou/euthanasia +pkg_euthanasia_fetch = git +pkg_euthanasia_repo = https://github.com/doubleyou/euthanasia +pkg_euthanasia_commit = master + +PACKAGES += evum +pkg_evum_name = evum +pkg_evum_description = Spawn Linux VMs as Erlang processes in the Erlang VM +pkg_evum_homepage = https://github.com/msantos/evum +pkg_evum_fetch = git +pkg_evum_repo = https://github.com/msantos/evum +pkg_evum_commit = master + +PACKAGES += exec +pkg_exec_name = erlexec +pkg_exec_description = Execute and control OS processes from Erlang/OTP. +pkg_exec_homepage = http://saleyn.github.com/erlexec +pkg_exec_fetch = git +pkg_exec_repo = https://github.com/saleyn/erlexec +pkg_exec_commit = master + +PACKAGES += exml +pkg_exml_name = exml +pkg_exml_description = XML parsing library in Erlang +pkg_exml_homepage = https://github.com/paulgray/exml +pkg_exml_fetch = git +pkg_exml_repo = https://github.com/paulgray/exml +pkg_exml_commit = master + +PACKAGES += exometer +pkg_exometer_name = exometer +pkg_exometer_description = Basic measurement objects and probe behavior +pkg_exometer_homepage = https://github.com/Feuerlabs/exometer +pkg_exometer_fetch = git +pkg_exometer_repo = https://github.com/Feuerlabs/exometer +pkg_exometer_commit = master + +PACKAGES += exs1024 +pkg_exs1024_name = exs1024 +pkg_exs1024_description = Xorshift1024star pseudo random number generator for Erlang. +pkg_exs1024_homepage = https://github.com/jj1bdx/exs1024 +pkg_exs1024_fetch = git +pkg_exs1024_repo = https://github.com/jj1bdx/exs1024 +pkg_exs1024_commit = master + +PACKAGES += exs64 +pkg_exs64_name = exs64 +pkg_exs64_description = Xorshift64star pseudo random number generator for Erlang. +pkg_exs64_homepage = https://github.com/jj1bdx/exs64 +pkg_exs64_fetch = git +pkg_exs64_repo = https://github.com/jj1bdx/exs64 +pkg_exs64_commit = master + +PACKAGES += exsplus116 +pkg_exsplus116_name = exsplus116 +pkg_exsplus116_description = Xorshift116plus for Erlang +pkg_exsplus116_homepage = https://github.com/jj1bdx/exsplus116 +pkg_exsplus116_fetch = git +pkg_exsplus116_repo = https://github.com/jj1bdx/exsplus116 +pkg_exsplus116_commit = master + +PACKAGES += exsplus128 +pkg_exsplus128_name = exsplus128 +pkg_exsplus128_description = Xorshift128plus pseudo random number generator for Erlang. +pkg_exsplus128_homepage = https://github.com/jj1bdx/exsplus128 +pkg_exsplus128_fetch = git +pkg_exsplus128_repo = https://github.com/jj1bdx/exsplus128 +pkg_exsplus128_commit = master + +PACKAGES += ezmq +pkg_ezmq_name = ezmq +pkg_ezmq_description = zMQ implemented in Erlang +pkg_ezmq_homepage = https://github.com/RoadRunnr/ezmq +pkg_ezmq_fetch = git +pkg_ezmq_repo = https://github.com/RoadRunnr/ezmq +pkg_ezmq_commit = master + +PACKAGES += ezmtp +pkg_ezmtp_name = ezmtp +pkg_ezmtp_description = ZMTP protocol in pure Erlang. +pkg_ezmtp_homepage = https://github.com/a13x/ezmtp +pkg_ezmtp_fetch = git +pkg_ezmtp_repo = https://github.com/a13x/ezmtp +pkg_ezmtp_commit = master + +PACKAGES += fast_disk_log +pkg_fast_disk_log_name = fast_disk_log +pkg_fast_disk_log_description = Pool-based asynchronous Erlang disk logger +pkg_fast_disk_log_homepage = https://github.com/lpgauth/fast_disk_log +pkg_fast_disk_log_fetch = git +pkg_fast_disk_log_repo = https://github.com/lpgauth/fast_disk_log +pkg_fast_disk_log_commit = master + +PACKAGES += feeder +pkg_feeder_name = feeder +pkg_feeder_description = Stream parse RSS and Atom formatted XML feeds. +pkg_feeder_homepage = https://github.com/michaelnisi/feeder +pkg_feeder_fetch = git +pkg_feeder_repo = https://github.com/michaelnisi/feeder +pkg_feeder_commit = master + +PACKAGES += find_crate +pkg_find_crate_name = find_crate +pkg_find_crate_description = Find Rust libs and exes in Erlang application priv directory +pkg_find_crate_homepage = https://github.com/goertzenator/find_crate +pkg_find_crate_fetch = git +pkg_find_crate_repo = https://github.com/goertzenator/find_crate +pkg_find_crate_commit = master + +PACKAGES += fix +pkg_fix_name = fix +pkg_fix_description = http://fixprotocol.org/ implementation. +pkg_fix_homepage = https://github.com/maxlapshin/fix +pkg_fix_fetch = git +pkg_fix_repo = https://github.com/maxlapshin/fix +pkg_fix_commit = master + +PACKAGES += flower +pkg_flower_name = flower +pkg_flower_description = FlowER - a Erlang OpenFlow development platform +pkg_flower_homepage = https://github.com/travelping/flower +pkg_flower_fetch = git +pkg_flower_repo = https://github.com/travelping/flower +pkg_flower_commit = master + +PACKAGES += fn +pkg_fn_name = fn +pkg_fn_description = Function utilities for Erlang +pkg_fn_homepage = https://github.com/reiddraper/fn +pkg_fn_fetch = git +pkg_fn_repo = https://github.com/reiddraper/fn +pkg_fn_commit = master + +PACKAGES += folsom +pkg_folsom_name = folsom +pkg_folsom_description = Expose Erlang Events and Metrics +pkg_folsom_homepage = https://github.com/boundary/folsom +pkg_folsom_fetch = git +pkg_folsom_repo = https://github.com/boundary/folsom +pkg_folsom_commit = master + +PACKAGES += folsom_cowboy +pkg_folsom_cowboy_name = folsom_cowboy +pkg_folsom_cowboy_description = A Cowboy based Folsom HTTP Wrapper. +pkg_folsom_cowboy_homepage = https://github.com/boundary/folsom_cowboy +pkg_folsom_cowboy_fetch = git +pkg_folsom_cowboy_repo = https://github.com/boundary/folsom_cowboy +pkg_folsom_cowboy_commit = master + +PACKAGES += folsomite +pkg_folsomite_name = folsomite +pkg_folsomite_description = blow up your graphite / riemann server with folsom metrics +pkg_folsomite_homepage = https://github.com/campanja/folsomite +pkg_folsomite_fetch = git +pkg_folsomite_repo = https://github.com/campanja/folsomite +pkg_folsomite_commit = master + +PACKAGES += fs +pkg_fs_name = fs +pkg_fs_description = Erlang FileSystem Listener +pkg_fs_homepage = https://github.com/synrc/fs +pkg_fs_fetch = git +pkg_fs_repo = https://github.com/synrc/fs +pkg_fs_commit = master + +PACKAGES += fuse +pkg_fuse_name = fuse +pkg_fuse_description = A Circuit Breaker for Erlang +pkg_fuse_homepage = https://github.com/jlouis/fuse +pkg_fuse_fetch = git +pkg_fuse_repo = https://github.com/jlouis/fuse +pkg_fuse_commit = master + +PACKAGES += gcm +pkg_gcm_name = gcm +pkg_gcm_description = An Erlang application for Google Cloud Messaging +pkg_gcm_homepage = https://github.com/pdincau/gcm-erlang +pkg_gcm_fetch = git +pkg_gcm_repo = https://github.com/pdincau/gcm-erlang +pkg_gcm_commit = master + +PACKAGES += gcprof +pkg_gcprof_name = gcprof +pkg_gcprof_description = Garbage Collection profiler for Erlang +pkg_gcprof_homepage = https://github.com/knutin/gcprof +pkg_gcprof_fetch = git +pkg_gcprof_repo = https://github.com/knutin/gcprof +pkg_gcprof_commit = master + +PACKAGES += geas +pkg_geas_name = geas +pkg_geas_description = Guess Erlang Application Scattering +pkg_geas_homepage = https://github.com/crownedgrouse/geas +pkg_geas_fetch = git +pkg_geas_repo = https://github.com/crownedgrouse/geas +pkg_geas_commit = master + +PACKAGES += geef +pkg_geef_name = geef +pkg_geef_description = Git NEEEEF (Erlang NIF) +pkg_geef_homepage = https://github.com/carlosmn/geef +pkg_geef_fetch = git +pkg_geef_repo = https://github.com/carlosmn/geef +pkg_geef_commit = master + +PACKAGES += gen_coap +pkg_gen_coap_name = gen_coap +pkg_gen_coap_description = Generic Erlang CoAP Client/Server +pkg_gen_coap_homepage = https://github.com/gotthardp/gen_coap +pkg_gen_coap_fetch = git +pkg_gen_coap_repo = https://github.com/gotthardp/gen_coap +pkg_gen_coap_commit = master + +PACKAGES += gen_cycle +pkg_gen_cycle_name = gen_cycle +pkg_gen_cycle_description = Simple, generic OTP behaviour for recurring tasks +pkg_gen_cycle_homepage = https://github.com/aerosol/gen_cycle +pkg_gen_cycle_fetch = git +pkg_gen_cycle_repo = https://github.com/aerosol/gen_cycle +pkg_gen_cycle_commit = develop + +PACKAGES += gen_icmp +pkg_gen_icmp_name = gen_icmp +pkg_gen_icmp_description = Erlang interface to ICMP sockets +pkg_gen_icmp_homepage = https://github.com/msantos/gen_icmp +pkg_gen_icmp_fetch = git +pkg_gen_icmp_repo = https://github.com/msantos/gen_icmp +pkg_gen_icmp_commit = master + +PACKAGES += gen_nb_server +pkg_gen_nb_server_name = gen_nb_server +pkg_gen_nb_server_description = OTP behavior for writing non-blocking servers +pkg_gen_nb_server_homepage = https://github.com/kevsmith/gen_nb_server +pkg_gen_nb_server_fetch = git +pkg_gen_nb_server_repo = https://github.com/kevsmith/gen_nb_server +pkg_gen_nb_server_commit = master + +PACKAGES += gen_paxos +pkg_gen_paxos_name = gen_paxos +pkg_gen_paxos_description = An Erlang/OTP-style implementation of the PAXOS distributed consensus protocol +pkg_gen_paxos_homepage = https://github.com/gburd/gen_paxos +pkg_gen_paxos_fetch = git +pkg_gen_paxos_repo = https://github.com/gburd/gen_paxos +pkg_gen_paxos_commit = master + +PACKAGES += gen_smtp +pkg_gen_smtp_name = gen_smtp +pkg_gen_smtp_description = A generic Erlang SMTP server and client that can be extended via callback modules +pkg_gen_smtp_homepage = https://github.com/Vagabond/gen_smtp +pkg_gen_smtp_fetch = git +pkg_gen_smtp_repo = https://github.com/Vagabond/gen_smtp +pkg_gen_smtp_commit = master + +PACKAGES += gen_tracker +pkg_gen_tracker_name = gen_tracker +pkg_gen_tracker_description = supervisor with ets handling of children and their metadata +pkg_gen_tracker_homepage = https://github.com/erlyvideo/gen_tracker +pkg_gen_tracker_fetch = git +pkg_gen_tracker_repo = https://github.com/erlyvideo/gen_tracker +pkg_gen_tracker_commit = master + +PACKAGES += gen_unix +pkg_gen_unix_name = gen_unix +pkg_gen_unix_description = Erlang Unix socket interface +pkg_gen_unix_homepage = https://github.com/msantos/gen_unix +pkg_gen_unix_fetch = git +pkg_gen_unix_repo = https://github.com/msantos/gen_unix +pkg_gen_unix_commit = master + +PACKAGES += geode +pkg_geode_name = geode +pkg_geode_description = geohash/proximity lookup in pure, uncut erlang. +pkg_geode_homepage = https://github.com/bradfordw/geode +pkg_geode_fetch = git +pkg_geode_repo = https://github.com/bradfordw/geode +pkg_geode_commit = master + +PACKAGES += getopt +pkg_getopt_name = getopt +pkg_getopt_description = Module to parse command line arguments using the GNU getopt syntax +pkg_getopt_homepage = https://github.com/jcomellas/getopt +pkg_getopt_fetch = git +pkg_getopt_repo = https://github.com/jcomellas/getopt +pkg_getopt_commit = master + +PACKAGES += gettext +pkg_gettext_name = gettext +pkg_gettext_description = Erlang internationalization library. +pkg_gettext_homepage = https://github.com/etnt/gettext +pkg_gettext_fetch = git +pkg_gettext_repo = https://github.com/etnt/gettext +pkg_gettext_commit = master + +PACKAGES += giallo +pkg_giallo_name = giallo +pkg_giallo_description = Small and flexible web framework on top of Cowboy +pkg_giallo_homepage = https://github.com/kivra/giallo +pkg_giallo_fetch = git +pkg_giallo_repo = https://github.com/kivra/giallo +pkg_giallo_commit = master + +PACKAGES += gin +pkg_gin_name = gin +pkg_gin_description = The guards and for Erlang parse_transform +pkg_gin_homepage = https://github.com/mad-cocktail/gin +pkg_gin_fetch = git +pkg_gin_repo = https://github.com/mad-cocktail/gin +pkg_gin_commit = master + +PACKAGES += gitty +pkg_gitty_name = gitty +pkg_gitty_description = Git access in erlang +pkg_gitty_homepage = https://github.com/maxlapshin/gitty +pkg_gitty_fetch = git +pkg_gitty_repo = https://github.com/maxlapshin/gitty +pkg_gitty_commit = master + +PACKAGES += gold_fever +pkg_gold_fever_name = gold_fever +pkg_gold_fever_description = A Treasure Hunt for Erlangers +pkg_gold_fever_homepage = https://github.com/inaka/gold_fever +pkg_gold_fever_fetch = git +pkg_gold_fever_repo = https://github.com/inaka/gold_fever +pkg_gold_fever_commit = master + +PACKAGES += gossiperl +pkg_gossiperl_name = gossiperl +pkg_gossiperl_description = Gossip middleware in Erlang +pkg_gossiperl_homepage = http://gossiperl.com/ +pkg_gossiperl_fetch = git +pkg_gossiperl_repo = https://github.com/gossiperl/gossiperl +pkg_gossiperl_commit = master + +PACKAGES += gpb +pkg_gpb_name = gpb +pkg_gpb_description = A Google Protobuf implementation for Erlang +pkg_gpb_homepage = https://github.com/tomas-abrahamsson/gpb +pkg_gpb_fetch = git +pkg_gpb_repo = https://github.com/tomas-abrahamsson/gpb +pkg_gpb_commit = master + +PACKAGES += gproc +pkg_gproc_name = gproc +pkg_gproc_description = Extended process registry for Erlang +pkg_gproc_homepage = https://github.com/uwiger/gproc +pkg_gproc_fetch = git +pkg_gproc_repo = https://github.com/uwiger/gproc +pkg_gproc_commit = master + +PACKAGES += grapherl +pkg_grapherl_name = grapherl +pkg_grapherl_description = Create graphs of Erlang systems and programs +pkg_grapherl_homepage = https://github.com/eproxus/grapherl +pkg_grapherl_fetch = git +pkg_grapherl_repo = https://github.com/eproxus/grapherl +pkg_grapherl_commit = master + +PACKAGES += gun +pkg_gun_name = gun +pkg_gun_description = Asynchronous SPDY, HTTP and Websocket client written in Erlang. +pkg_gun_homepage = http//ninenines.eu +pkg_gun_fetch = git +pkg_gun_repo = https://github.com/ninenines/gun +pkg_gun_commit = master + +PACKAGES += gut +pkg_gut_name = gut +pkg_gut_description = gut is a template printing, aka scaffolding, tool for Erlang. Like rails generate or yeoman +pkg_gut_homepage = https://github.com/unbalancedparentheses/gut +pkg_gut_fetch = git +pkg_gut_repo = https://github.com/unbalancedparentheses/gut +pkg_gut_commit = master + +PACKAGES += hackney +pkg_hackney_name = hackney +pkg_hackney_description = simple HTTP client in Erlang +pkg_hackney_homepage = https://github.com/benoitc/hackney +pkg_hackney_fetch = git +pkg_hackney_repo = https://github.com/benoitc/hackney +pkg_hackney_commit = master + +PACKAGES += hamcrest +pkg_hamcrest_name = hamcrest +pkg_hamcrest_description = Erlang port of Hamcrest +pkg_hamcrest_homepage = https://github.com/hyperthunk/hamcrest-erlang +pkg_hamcrest_fetch = git +pkg_hamcrest_repo = https://github.com/hyperthunk/hamcrest-erlang +pkg_hamcrest_commit = master + +PACKAGES += hanoidb +pkg_hanoidb_name = hanoidb +pkg_hanoidb_description = Erlang LSM BTree Storage +pkg_hanoidb_homepage = https://github.com/krestenkrab/hanoidb +pkg_hanoidb_fetch = git +pkg_hanoidb_repo = https://github.com/krestenkrab/hanoidb +pkg_hanoidb_commit = master + +PACKAGES += hottub +pkg_hottub_name = hottub +pkg_hottub_description = Permanent Erlang Worker Pool +pkg_hottub_homepage = https://github.com/bfrog/hottub +pkg_hottub_fetch = git +pkg_hottub_repo = https://github.com/bfrog/hottub +pkg_hottub_commit = master + +PACKAGES += hpack +pkg_hpack_name = hpack +pkg_hpack_description = HPACK Implementation for Erlang +pkg_hpack_homepage = https://github.com/joedevivo/hpack +pkg_hpack_fetch = git +pkg_hpack_repo = https://github.com/joedevivo/hpack +pkg_hpack_commit = master + +PACKAGES += hyper +pkg_hyper_name = hyper +pkg_hyper_description = Erlang implementation of HyperLogLog +pkg_hyper_homepage = https://github.com/GameAnalytics/hyper +pkg_hyper_fetch = git +pkg_hyper_repo = https://github.com/GameAnalytics/hyper +pkg_hyper_commit = master + +PACKAGES += i18n +pkg_i18n_name = i18n +pkg_i18n_description = International components for unicode from Erlang (unicode, date, string, number, format, locale, localization, transliteration, icu4e) +pkg_i18n_homepage = https://github.com/erlang-unicode/i18n +pkg_i18n_fetch = git +pkg_i18n_repo = https://github.com/erlang-unicode/i18n +pkg_i18n_commit = master + +PACKAGES += ibrowse +pkg_ibrowse_name = ibrowse +pkg_ibrowse_description = Erlang HTTP client +pkg_ibrowse_homepage = https://github.com/cmullaparthi/ibrowse +pkg_ibrowse_fetch = git +pkg_ibrowse_repo = https://github.com/cmullaparthi/ibrowse +pkg_ibrowse_commit = master + +PACKAGES += ierlang +pkg_ierlang_name = ierlang +pkg_ierlang_description = An Erlang language kernel for IPython. +pkg_ierlang_homepage = https://github.com/robbielynch/ierlang +pkg_ierlang_fetch = git +pkg_ierlang_repo = https://github.com/robbielynch/ierlang +pkg_ierlang_commit = master + +PACKAGES += iota +pkg_iota_name = iota +pkg_iota_description = iota (Inter-dependency Objective Testing Apparatus) - a tool to enforce clean separation of responsibilities in Erlang code +pkg_iota_homepage = https://github.com/jpgneves/iota +pkg_iota_fetch = git +pkg_iota_repo = https://github.com/jpgneves/iota +pkg_iota_commit = master + +PACKAGES += irc_lib +pkg_irc_lib_name = irc_lib +pkg_irc_lib_description = Erlang irc client library +pkg_irc_lib_homepage = https://github.com/OtpChatBot/irc_lib +pkg_irc_lib_fetch = git +pkg_irc_lib_repo = https://github.com/OtpChatBot/irc_lib +pkg_irc_lib_commit = master + +PACKAGES += ircd +pkg_ircd_name = ircd +pkg_ircd_description = A pluggable IRC daemon application/library for Erlang. +pkg_ircd_homepage = https://github.com/tonyg/erlang-ircd +pkg_ircd_fetch = git +pkg_ircd_repo = https://github.com/tonyg/erlang-ircd +pkg_ircd_commit = master + +PACKAGES += iris +pkg_iris_name = iris +pkg_iris_description = Iris Erlang binding +pkg_iris_homepage = https://github.com/project-iris/iris-erl +pkg_iris_fetch = git +pkg_iris_repo = https://github.com/project-iris/iris-erl +pkg_iris_commit = master + +PACKAGES += iso8601 +pkg_iso8601_name = iso8601 +pkg_iso8601_description = Erlang ISO 8601 date formatter/parser +pkg_iso8601_homepage = https://github.com/seansawyer/erlang_iso8601 +pkg_iso8601_fetch = git +pkg_iso8601_repo = https://github.com/seansawyer/erlang_iso8601 +pkg_iso8601_commit = master + +PACKAGES += jamdb_sybase +pkg_jamdb_sybase_name = jamdb_sybase +pkg_jamdb_sybase_description = Erlang driver for SAP Sybase ASE +pkg_jamdb_sybase_homepage = https://github.com/erlangbureau/jamdb_sybase +pkg_jamdb_sybase_fetch = git +pkg_jamdb_sybase_repo = https://github.com/erlangbureau/jamdb_sybase +pkg_jamdb_sybase_commit = master + +PACKAGES += jerg +pkg_jerg_name = jerg +pkg_jerg_description = JSON Schema to Erlang Records Generator +pkg_jerg_homepage = https://github.com/ddossot/jerg +pkg_jerg_fetch = git +pkg_jerg_repo = https://github.com/ddossot/jerg +pkg_jerg_commit = master + +PACKAGES += jesse +pkg_jesse_name = jesse +pkg_jesse_description = jesse (JSon Schema Erlang) is an implementation of a json schema validator for Erlang. +pkg_jesse_homepage = https://github.com/for-GET/jesse +pkg_jesse_fetch = git +pkg_jesse_repo = https://github.com/for-GET/jesse +pkg_jesse_commit = master + +PACKAGES += jiffy +pkg_jiffy_name = jiffy +pkg_jiffy_description = JSON NIFs for Erlang. +pkg_jiffy_homepage = https://github.com/davisp/jiffy +pkg_jiffy_fetch = git +pkg_jiffy_repo = https://github.com/davisp/jiffy +pkg_jiffy_commit = master + +PACKAGES += jiffy_v +pkg_jiffy_v_name = jiffy_v +pkg_jiffy_v_description = JSON validation utility +pkg_jiffy_v_homepage = https://github.com/shizzard/jiffy-v +pkg_jiffy_v_fetch = git +pkg_jiffy_v_repo = https://github.com/shizzard/jiffy-v +pkg_jiffy_v_commit = master + +PACKAGES += jobs +pkg_jobs_name = jobs +pkg_jobs_description = a Job scheduler for load regulation +pkg_jobs_homepage = https://github.com/esl/jobs +pkg_jobs_fetch = git +pkg_jobs_repo = https://github.com/esl/jobs +pkg_jobs_commit = master + +PACKAGES += joxa +pkg_joxa_name = joxa +pkg_joxa_description = A Modern Lisp for the Erlang VM +pkg_joxa_homepage = https://github.com/joxa/joxa +pkg_joxa_fetch = git +pkg_joxa_repo = https://github.com/joxa/joxa +pkg_joxa_commit = master + +PACKAGES += json +pkg_json_name = json +pkg_json_description = a high level json library for erlang (17.0+) +pkg_json_homepage = https://github.com/talentdeficit/json +pkg_json_fetch = git +pkg_json_repo = https://github.com/talentdeficit/json +pkg_json_commit = master + +PACKAGES += json_rec +pkg_json_rec_name = json_rec +pkg_json_rec_description = JSON to erlang record +pkg_json_rec_homepage = https://github.com/justinkirby/json_rec +pkg_json_rec_fetch = git +pkg_json_rec_repo = https://github.com/justinkirby/json_rec +pkg_json_rec_commit = master + +PACKAGES += jsone +pkg_jsone_name = jsone +pkg_jsone_description = An Erlang library for encoding, decoding JSON data. +pkg_jsone_homepage = https://github.com/sile/jsone.git +pkg_jsone_fetch = git +pkg_jsone_repo = https://github.com/sile/jsone.git +pkg_jsone_commit = master + +PACKAGES += jsonerl +pkg_jsonerl_name = jsonerl +pkg_jsonerl_description = yet another but slightly different erlang <-> json encoder/decoder +pkg_jsonerl_homepage = https://github.com/lambder/jsonerl +pkg_jsonerl_fetch = git +pkg_jsonerl_repo = https://github.com/lambder/jsonerl +pkg_jsonerl_commit = master + +PACKAGES += jsonpath +pkg_jsonpath_name = jsonpath +pkg_jsonpath_description = Fast Erlang JSON data retrieval and updates via javascript-like notation +pkg_jsonpath_homepage = https://github.com/GeneStevens/jsonpath +pkg_jsonpath_fetch = git +pkg_jsonpath_repo = https://github.com/GeneStevens/jsonpath +pkg_jsonpath_commit = master + +PACKAGES += jsonx +pkg_jsonx_name = jsonx +pkg_jsonx_description = JSONX is an Erlang library for efficient decode and encode JSON, written in C. +pkg_jsonx_homepage = https://github.com/iskra/jsonx +pkg_jsonx_fetch = git +pkg_jsonx_repo = https://github.com/iskra/jsonx +pkg_jsonx_commit = master + +PACKAGES += jsx +pkg_jsx_name = jsx +pkg_jsx_description = An Erlang application for consuming, producing and manipulating JSON. +pkg_jsx_homepage = https://github.com/talentdeficit/jsx +pkg_jsx_fetch = git +pkg_jsx_repo = https://github.com/talentdeficit/jsx +pkg_jsx_commit = master + +PACKAGES += kafka +pkg_kafka_name = kafka +pkg_kafka_description = Kafka consumer and producer in Erlang +pkg_kafka_homepage = https://github.com/wooga/kafka-erlang +pkg_kafka_fetch = git +pkg_kafka_repo = https://github.com/wooga/kafka-erlang +pkg_kafka_commit = master + +PACKAGES += kafka_protocol +pkg_kafka_protocol_name = kafka_protocol +pkg_kafka_protocol_description = Kafka protocol Erlang library +pkg_kafka_protocol_homepage = https://github.com/klarna/kafka_protocol +pkg_kafka_protocol_fetch = git +pkg_kafka_protocol_repo = https://github.com/klarna/kafka_protocol.git +pkg_kafka_protocol_commit = master + +PACKAGES += kai +pkg_kai_name = kai +pkg_kai_description = DHT storage by Takeshi Inoue +pkg_kai_homepage = https://github.com/synrc/kai +pkg_kai_fetch = git +pkg_kai_repo = https://github.com/synrc/kai +pkg_kai_commit = master + +PACKAGES += katja +pkg_katja_name = katja +pkg_katja_description = A simple Riemann client written in Erlang. +pkg_katja_homepage = https://github.com/nifoc/katja +pkg_katja_fetch = git +pkg_katja_repo = https://github.com/nifoc/katja +pkg_katja_commit = master + +PACKAGES += kdht +pkg_kdht_name = kdht +pkg_kdht_description = kdht is an erlang DHT implementation +pkg_kdht_homepage = https://github.com/kevinlynx/kdht +pkg_kdht_fetch = git +pkg_kdht_repo = https://github.com/kevinlynx/kdht +pkg_kdht_commit = master + +PACKAGES += key2value +pkg_key2value_name = key2value +pkg_key2value_description = Erlang 2-way map +pkg_key2value_homepage = https://github.com/okeuday/key2value +pkg_key2value_fetch = git +pkg_key2value_repo = https://github.com/okeuday/key2value +pkg_key2value_commit = master + +PACKAGES += keys1value +pkg_keys1value_name = keys1value +pkg_keys1value_description = Erlang set associative map for key lists +pkg_keys1value_homepage = https://github.com/okeuday/keys1value +pkg_keys1value_fetch = git +pkg_keys1value_repo = https://github.com/okeuday/keys1value +pkg_keys1value_commit = master + +PACKAGES += kinetic +pkg_kinetic_name = kinetic +pkg_kinetic_description = Erlang Kinesis Client +pkg_kinetic_homepage = https://github.com/AdRoll/kinetic +pkg_kinetic_fetch = git +pkg_kinetic_repo = https://github.com/AdRoll/kinetic +pkg_kinetic_commit = master + +PACKAGES += kjell +pkg_kjell_name = kjell +pkg_kjell_description = Erlang Shell +pkg_kjell_homepage = https://github.com/karlll/kjell +pkg_kjell_fetch = git +pkg_kjell_repo = https://github.com/karlll/kjell +pkg_kjell_commit = master + +PACKAGES += kraken +pkg_kraken_name = kraken +pkg_kraken_description = Distributed Pubsub Server for Realtime Apps +pkg_kraken_homepage = https://github.com/Asana/kraken +pkg_kraken_fetch = git +pkg_kraken_repo = https://github.com/Asana/kraken +pkg_kraken_commit = master + +PACKAGES += kucumberl +pkg_kucumberl_name = kucumberl +pkg_kucumberl_description = A pure-erlang, open-source, implementation of Cucumber +pkg_kucumberl_homepage = https://github.com/openshine/kucumberl +pkg_kucumberl_fetch = git +pkg_kucumberl_repo = https://github.com/openshine/kucumberl +pkg_kucumberl_commit = master + +PACKAGES += kvc +pkg_kvc_name = kvc +pkg_kvc_description = KVC - Key Value Coding for Erlang data structures +pkg_kvc_homepage = https://github.com/etrepum/kvc +pkg_kvc_fetch = git +pkg_kvc_repo = https://github.com/etrepum/kvc +pkg_kvc_commit = master + +PACKAGES += kvlists +pkg_kvlists_name = kvlists +pkg_kvlists_description = Lists of key-value pairs (decoded JSON) in Erlang +pkg_kvlists_homepage = https://github.com/jcomellas/kvlists +pkg_kvlists_fetch = git +pkg_kvlists_repo = https://github.com/jcomellas/kvlists +pkg_kvlists_commit = master + +PACKAGES += kvs +pkg_kvs_name = kvs +pkg_kvs_description = Container and Iterator +pkg_kvs_homepage = https://github.com/synrc/kvs +pkg_kvs_fetch = git +pkg_kvs_repo = https://github.com/synrc/kvs +pkg_kvs_commit = master + +PACKAGES += lager +pkg_lager_name = lager +pkg_lager_description = A logging framework for Erlang/OTP. +pkg_lager_homepage = https://github.com/basho/lager +pkg_lager_fetch = git +pkg_lager_repo = https://github.com/basho/lager +pkg_lager_commit = master + +PACKAGES += lager_amqp_backend +pkg_lager_amqp_backend_name = lager_amqp_backend +pkg_lager_amqp_backend_description = AMQP RabbitMQ Lager backend +pkg_lager_amqp_backend_homepage = https://github.com/jbrisbin/lager_amqp_backend +pkg_lager_amqp_backend_fetch = git +pkg_lager_amqp_backend_repo = https://github.com/jbrisbin/lager_amqp_backend +pkg_lager_amqp_backend_commit = master + +PACKAGES += lager_syslog +pkg_lager_syslog_name = lager_syslog +pkg_lager_syslog_description = Syslog backend for lager +pkg_lager_syslog_homepage = https://github.com/basho/lager_syslog +pkg_lager_syslog_fetch = git +pkg_lager_syslog_repo = https://github.com/basho/lager_syslog +pkg_lager_syslog_commit = master + +PACKAGES += lambdapad +pkg_lambdapad_name = lambdapad +pkg_lambdapad_description = Static site generator using Erlang. Yes, Erlang. +pkg_lambdapad_homepage = https://github.com/gar1t/lambdapad +pkg_lambdapad_fetch = git +pkg_lambdapad_repo = https://github.com/gar1t/lambdapad +pkg_lambdapad_commit = master + +PACKAGES += lasp +pkg_lasp_name = lasp +pkg_lasp_description = A Language for Distributed, Eventually Consistent Computations +pkg_lasp_homepage = http://lasp-lang.org/ +pkg_lasp_fetch = git +pkg_lasp_repo = https://github.com/lasp-lang/lasp +pkg_lasp_commit = master + +PACKAGES += lasse +pkg_lasse_name = lasse +pkg_lasse_description = SSE handler for Cowboy +pkg_lasse_homepage = https://github.com/inaka/lasse +pkg_lasse_fetch = git +pkg_lasse_repo = https://github.com/inaka/lasse +pkg_lasse_commit = master + +PACKAGES += ldap +pkg_ldap_name = ldap +pkg_ldap_description = LDAP server written in Erlang +pkg_ldap_homepage = https://github.com/spawnproc/ldap +pkg_ldap_fetch = git +pkg_ldap_repo = https://github.com/spawnproc/ldap +pkg_ldap_commit = master + +PACKAGES += lethink +pkg_lethink_name = lethink +pkg_lethink_description = erlang driver for rethinkdb +pkg_lethink_homepage = https://github.com/taybin/lethink +pkg_lethink_fetch = git +pkg_lethink_repo = https://github.com/taybin/lethink +pkg_lethink_commit = master + +PACKAGES += lfe +pkg_lfe_name = lfe +pkg_lfe_description = Lisp Flavoured Erlang (LFE) +pkg_lfe_homepage = https://github.com/rvirding/lfe +pkg_lfe_fetch = git +pkg_lfe_repo = https://github.com/rvirding/lfe +pkg_lfe_commit = master + +PACKAGES += ling +pkg_ling_name = ling +pkg_ling_description = Erlang on Xen +pkg_ling_homepage = https://github.com/cloudozer/ling +pkg_ling_fetch = git +pkg_ling_repo = https://github.com/cloudozer/ling +pkg_ling_commit = master + +PACKAGES += live +pkg_live_name = live +pkg_live_description = Automated module and configuration reloader. +pkg_live_homepage = http://ninenines.eu +pkg_live_fetch = git +pkg_live_repo = https://github.com/ninenines/live +pkg_live_commit = master + +PACKAGES += lmq +pkg_lmq_name = lmq +pkg_lmq_description = Lightweight Message Queue +pkg_lmq_homepage = https://github.com/iij/lmq +pkg_lmq_fetch = git +pkg_lmq_repo = https://github.com/iij/lmq +pkg_lmq_commit = master + +PACKAGES += locker +pkg_locker_name = locker +pkg_locker_description = Atomic distributed 'check and set' for short-lived keys +pkg_locker_homepage = https://github.com/wooga/locker +pkg_locker_fetch = git +pkg_locker_repo = https://github.com/wooga/locker +pkg_locker_commit = master + +PACKAGES += locks +pkg_locks_name = locks +pkg_locks_description = A scalable, deadlock-resolving resource locker +pkg_locks_homepage = https://github.com/uwiger/locks +pkg_locks_fetch = git +pkg_locks_repo = https://github.com/uwiger/locks +pkg_locks_commit = master + +PACKAGES += log4erl +pkg_log4erl_name = log4erl +pkg_log4erl_description = A logger for erlang in the spirit of Log4J. +pkg_log4erl_homepage = https://github.com/ahmednawras/log4erl +pkg_log4erl_fetch = git +pkg_log4erl_repo = https://github.com/ahmednawras/log4erl +pkg_log4erl_commit = master + +PACKAGES += lol +pkg_lol_name = lol +pkg_lol_description = Lisp on erLang, and programming is fun again +pkg_lol_homepage = https://github.com/b0oh/lol +pkg_lol_fetch = git +pkg_lol_repo = https://github.com/b0oh/lol +pkg_lol_commit = master + +PACKAGES += lucid +pkg_lucid_name = lucid +pkg_lucid_description = HTTP/2 server written in Erlang +pkg_lucid_homepage = https://github.com/tatsuhiro-t/lucid +pkg_lucid_fetch = git +pkg_lucid_repo = https://github.com/tatsuhiro-t/lucid +pkg_lucid_commit = master + +PACKAGES += luerl +pkg_luerl_name = luerl +pkg_luerl_description = Lua in Erlang +pkg_luerl_homepage = https://github.com/rvirding/luerl +pkg_luerl_fetch = git +pkg_luerl_repo = https://github.com/rvirding/luerl +pkg_luerl_commit = develop + +PACKAGES += luwak +pkg_luwak_name = luwak +pkg_luwak_description = Large-object storage interface for Riak +pkg_luwak_homepage = https://github.com/basho/luwak +pkg_luwak_fetch = git +pkg_luwak_repo = https://github.com/basho/luwak +pkg_luwak_commit = master + +PACKAGES += lux +pkg_lux_name = lux +pkg_lux_description = Lux (LUcid eXpect scripting) simplifies test automation and provides an Expect-style execution of commands +pkg_lux_homepage = https://github.com/hawk/lux +pkg_lux_fetch = git +pkg_lux_repo = https://github.com/hawk/lux +pkg_lux_commit = master + +PACKAGES += machi +pkg_machi_name = machi +pkg_machi_description = Machi file store +pkg_machi_homepage = https://github.com/basho/machi +pkg_machi_fetch = git +pkg_machi_repo = https://github.com/basho/machi +pkg_machi_commit = master + +PACKAGES += mad +pkg_mad_name = mad +pkg_mad_description = Small and Fast Rebar Replacement +pkg_mad_homepage = https://github.com/synrc/mad +pkg_mad_fetch = git +pkg_mad_repo = https://github.com/synrc/mad +pkg_mad_commit = master + +PACKAGES += marina +pkg_marina_name = marina +pkg_marina_description = Non-blocking Erlang Cassandra CQL3 client +pkg_marina_homepage = https://github.com/lpgauth/marina +pkg_marina_fetch = git +pkg_marina_repo = https://github.com/lpgauth/marina +pkg_marina_commit = master + +PACKAGES += mavg +pkg_mavg_name = mavg +pkg_mavg_description = Erlang :: Exponential moving average library +pkg_mavg_homepage = https://github.com/EchoTeam/mavg +pkg_mavg_fetch = git +pkg_mavg_repo = https://github.com/EchoTeam/mavg +pkg_mavg_commit = master + +PACKAGES += mc_erl +pkg_mc_erl_name = mc_erl +pkg_mc_erl_description = mc-erl is a server for Minecraft 1.4.7 written in Erlang. +pkg_mc_erl_homepage = https://github.com/clonejo/mc-erl +pkg_mc_erl_fetch = git +pkg_mc_erl_repo = https://github.com/clonejo/mc-erl +pkg_mc_erl_commit = master + +PACKAGES += mcd +pkg_mcd_name = mcd +pkg_mcd_description = Fast memcached protocol client in pure Erlang +pkg_mcd_homepage = https://github.com/EchoTeam/mcd +pkg_mcd_fetch = git +pkg_mcd_repo = https://github.com/EchoTeam/mcd +pkg_mcd_commit = master + +PACKAGES += mcerlang +pkg_mcerlang_name = mcerlang +pkg_mcerlang_description = The McErlang model checker for Erlang +pkg_mcerlang_homepage = https://github.com/fredlund/McErlang +pkg_mcerlang_fetch = git +pkg_mcerlang_repo = https://github.com/fredlund/McErlang +pkg_mcerlang_commit = master + +PACKAGES += meck +pkg_meck_name = meck +pkg_meck_description = A mocking library for Erlang +pkg_meck_homepage = https://github.com/eproxus/meck +pkg_meck_fetch = git +pkg_meck_repo = https://github.com/eproxus/meck +pkg_meck_commit = master + +PACKAGES += mekao +pkg_mekao_name = mekao +pkg_mekao_description = SQL constructor +pkg_mekao_homepage = https://github.com/ddosia/mekao +pkg_mekao_fetch = git +pkg_mekao_repo = https://github.com/ddosia/mekao +pkg_mekao_commit = master + +PACKAGES += memo +pkg_memo_name = memo +pkg_memo_description = Erlang memoization server +pkg_memo_homepage = https://github.com/tuncer/memo +pkg_memo_fetch = git +pkg_memo_repo = https://github.com/tuncer/memo +pkg_memo_commit = master + +PACKAGES += merge_index +pkg_merge_index_name = merge_index +pkg_merge_index_description = MergeIndex is an Erlang library for storing ordered sets on disk. It is very similar to an SSTable (in Google's Bigtable) or an HFile (in Hadoop). +pkg_merge_index_homepage = https://github.com/basho/merge_index +pkg_merge_index_fetch = git +pkg_merge_index_repo = https://github.com/basho/merge_index +pkg_merge_index_commit = master + +PACKAGES += merl +pkg_merl_name = merl +pkg_merl_description = Metaprogramming in Erlang +pkg_merl_homepage = https://github.com/richcarl/merl +pkg_merl_fetch = git +pkg_merl_repo = https://github.com/richcarl/merl +pkg_merl_commit = master + +PACKAGES += mimerl +pkg_mimerl_name = mimerl +pkg_mimerl_description = library to handle mimetypes +pkg_mimerl_homepage = https://github.com/benoitc/mimerl +pkg_mimerl_fetch = git +pkg_mimerl_repo = https://github.com/benoitc/mimerl +pkg_mimerl_commit = master + +PACKAGES += mimetypes +pkg_mimetypes_name = mimetypes +pkg_mimetypes_description = Erlang MIME types library +pkg_mimetypes_homepage = https://github.com/spawngrid/mimetypes +pkg_mimetypes_fetch = git +pkg_mimetypes_repo = https://github.com/spawngrid/mimetypes +pkg_mimetypes_commit = master + +PACKAGES += mixer +pkg_mixer_name = mixer +pkg_mixer_description = Mix in functions from other modules +pkg_mixer_homepage = https://github.com/chef/mixer +pkg_mixer_fetch = git +pkg_mixer_repo = https://github.com/chef/mixer +pkg_mixer_commit = master + +PACKAGES += mochiweb +pkg_mochiweb_name = mochiweb +pkg_mochiweb_description = MochiWeb is an Erlang library for building lightweight HTTP servers. +pkg_mochiweb_homepage = https://github.com/mochi/mochiweb +pkg_mochiweb_fetch = git +pkg_mochiweb_repo = https://github.com/mochi/mochiweb +pkg_mochiweb_commit = master + +PACKAGES += mochiweb_xpath +pkg_mochiweb_xpath_name = mochiweb_xpath +pkg_mochiweb_xpath_description = XPath support for mochiweb's html parser +pkg_mochiweb_xpath_homepage = https://github.com/retnuh/mochiweb_xpath +pkg_mochiweb_xpath_fetch = git +pkg_mochiweb_xpath_repo = https://github.com/retnuh/mochiweb_xpath +pkg_mochiweb_xpath_commit = master + +PACKAGES += mockgyver +pkg_mockgyver_name = mockgyver +pkg_mockgyver_description = A mocking library for Erlang +pkg_mockgyver_homepage = https://github.com/klajo/mockgyver +pkg_mockgyver_fetch = git +pkg_mockgyver_repo = https://github.com/klajo/mockgyver +pkg_mockgyver_commit = master + +PACKAGES += modlib +pkg_modlib_name = modlib +pkg_modlib_description = Web framework based on Erlang's inets httpd +pkg_modlib_homepage = https://github.com/gar1t/modlib +pkg_modlib_fetch = git +pkg_modlib_repo = https://github.com/gar1t/modlib +pkg_modlib_commit = master + +PACKAGES += mongodb +pkg_mongodb_name = mongodb +pkg_mongodb_description = MongoDB driver for Erlang +pkg_mongodb_homepage = https://github.com/comtihon/mongodb-erlang +pkg_mongodb_fetch = git +pkg_mongodb_repo = https://github.com/comtihon/mongodb-erlang +pkg_mongodb_commit = master + +PACKAGES += mongooseim +pkg_mongooseim_name = mongooseim +pkg_mongooseim_description = Jabber / XMPP server with focus on performance and scalability, by Erlang Solutions +pkg_mongooseim_homepage = https://www.erlang-solutions.com/products/mongooseim-massively-scalable-ejabberd-platform +pkg_mongooseim_fetch = git +pkg_mongooseim_repo = https://github.com/esl/MongooseIM +pkg_mongooseim_commit = master + +PACKAGES += moyo +pkg_moyo_name = moyo +pkg_moyo_description = Erlang utility functions library +pkg_moyo_homepage = https://github.com/dwango/moyo +pkg_moyo_fetch = git +pkg_moyo_repo = https://github.com/dwango/moyo +pkg_moyo_commit = master + +PACKAGES += msgpack +pkg_msgpack_name = msgpack +pkg_msgpack_description = MessagePack (de)serializer implementation for Erlang +pkg_msgpack_homepage = https://github.com/msgpack/msgpack-erlang +pkg_msgpack_fetch = git +pkg_msgpack_repo = https://github.com/msgpack/msgpack-erlang +pkg_msgpack_commit = master + +PACKAGES += mu2 +pkg_mu2_name = mu2 +pkg_mu2_description = Erlang mutation testing tool +pkg_mu2_homepage = https://github.com/ramsay-t/mu2 +pkg_mu2_fetch = git +pkg_mu2_repo = https://github.com/ramsay-t/mu2 +pkg_mu2_commit = master + +PACKAGES += mustache +pkg_mustache_name = mustache +pkg_mustache_description = Mustache template engine for Erlang. +pkg_mustache_homepage = https://github.com/mojombo/mustache.erl +pkg_mustache_fetch = git +pkg_mustache_repo = https://github.com/mojombo/mustache.erl +pkg_mustache_commit = master + +PACKAGES += myproto +pkg_myproto_name = myproto +pkg_myproto_description = MySQL Server Protocol in Erlang +pkg_myproto_homepage = https://github.com/altenwald/myproto +pkg_myproto_fetch = git +pkg_myproto_repo = https://github.com/altenwald/myproto +pkg_myproto_commit = master + +PACKAGES += mysql +pkg_mysql_name = mysql +pkg_mysql_description = Erlang MySQL Driver (from code.google.com) +pkg_mysql_homepage = https://github.com/dizzyd/erlang-mysql-driver +pkg_mysql_fetch = git +pkg_mysql_repo = https://github.com/dizzyd/erlang-mysql-driver +pkg_mysql_commit = master + +PACKAGES += n2o +pkg_n2o_name = n2o +pkg_n2o_description = WebSocket Application Server +pkg_n2o_homepage = https://github.com/5HT/n2o +pkg_n2o_fetch = git +pkg_n2o_repo = https://github.com/5HT/n2o +pkg_n2o_commit = master + +PACKAGES += nat_upnp +pkg_nat_upnp_name = nat_upnp +pkg_nat_upnp_description = Erlang library to map your internal port to an external using UNP IGD +pkg_nat_upnp_homepage = https://github.com/benoitc/nat_upnp +pkg_nat_upnp_fetch = git +pkg_nat_upnp_repo = https://github.com/benoitc/nat_upnp +pkg_nat_upnp_commit = master + +PACKAGES += neo4j +pkg_neo4j_name = neo4j +pkg_neo4j_description = Erlang client library for Neo4J. +pkg_neo4j_homepage = https://github.com/dmitriid/neo4j-erlang +pkg_neo4j_fetch = git +pkg_neo4j_repo = https://github.com/dmitriid/neo4j-erlang +pkg_neo4j_commit = master + +PACKAGES += neotoma +pkg_neotoma_name = neotoma +pkg_neotoma_description = Erlang library and packrat parser-generator for parsing expression grammars. +pkg_neotoma_homepage = https://github.com/seancribbs/neotoma +pkg_neotoma_fetch = git +pkg_neotoma_repo = https://github.com/seancribbs/neotoma +pkg_neotoma_commit = master + +PACKAGES += newrelic +pkg_newrelic_name = newrelic +pkg_newrelic_description = Erlang library for sending metrics to New Relic +pkg_newrelic_homepage = https://github.com/wooga/newrelic-erlang +pkg_newrelic_fetch = git +pkg_newrelic_repo = https://github.com/wooga/newrelic-erlang +pkg_newrelic_commit = master + +PACKAGES += nifty +pkg_nifty_name = nifty +pkg_nifty_description = Erlang NIF wrapper generator +pkg_nifty_homepage = https://github.com/parapluu/nifty +pkg_nifty_fetch = git +pkg_nifty_repo = https://github.com/parapluu/nifty +pkg_nifty_commit = master + +PACKAGES += nitrogen_core +pkg_nitrogen_core_name = nitrogen_core +pkg_nitrogen_core_description = The core Nitrogen library. +pkg_nitrogen_core_homepage = http://nitrogenproject.com/ +pkg_nitrogen_core_fetch = git +pkg_nitrogen_core_repo = https://github.com/nitrogen/nitrogen_core +pkg_nitrogen_core_commit = master + +PACKAGES += nkbase +pkg_nkbase_name = nkbase +pkg_nkbase_description = NkBASE distributed database +pkg_nkbase_homepage = https://github.com/Nekso/nkbase +pkg_nkbase_fetch = git +pkg_nkbase_repo = https://github.com/Nekso/nkbase +pkg_nkbase_commit = develop + +PACKAGES += nkdocker +pkg_nkdocker_name = nkdocker +pkg_nkdocker_description = Erlang Docker client +pkg_nkdocker_homepage = https://github.com/Nekso/nkdocker +pkg_nkdocker_fetch = git +pkg_nkdocker_repo = https://github.com/Nekso/nkdocker +pkg_nkdocker_commit = master + +PACKAGES += nkpacket +pkg_nkpacket_name = nkpacket +pkg_nkpacket_description = Generic Erlang transport layer +pkg_nkpacket_homepage = https://github.com/Nekso/nkpacket +pkg_nkpacket_fetch = git +pkg_nkpacket_repo = https://github.com/Nekso/nkpacket +pkg_nkpacket_commit = master + +PACKAGES += nksip +pkg_nksip_name = nksip +pkg_nksip_description = Erlang SIP application server +pkg_nksip_homepage = https://github.com/kalta/nksip +pkg_nksip_fetch = git +pkg_nksip_repo = https://github.com/kalta/nksip +pkg_nksip_commit = master + +PACKAGES += nodefinder +pkg_nodefinder_name = nodefinder +pkg_nodefinder_description = automatic node discovery via UDP multicast +pkg_nodefinder_homepage = https://github.com/erlanger/nodefinder +pkg_nodefinder_fetch = git +pkg_nodefinder_repo = https://github.com/okeuday/nodefinder +pkg_nodefinder_commit = master + +PACKAGES += nprocreg +pkg_nprocreg_name = nprocreg +pkg_nprocreg_description = Minimal Distributed Erlang Process Registry +pkg_nprocreg_homepage = http://nitrogenproject.com/ +pkg_nprocreg_fetch = git +pkg_nprocreg_repo = https://github.com/nitrogen/nprocreg +pkg_nprocreg_commit = master + +PACKAGES += oauth +pkg_oauth_name = oauth +pkg_oauth_description = An Erlang OAuth 1.0 implementation +pkg_oauth_homepage = https://github.com/tim/erlang-oauth +pkg_oauth_fetch = git +pkg_oauth_repo = https://github.com/tim/erlang-oauth +pkg_oauth_commit = master + +PACKAGES += oauth2 +pkg_oauth2_name = oauth2 +pkg_oauth2_description = Erlang Oauth2 implementation +pkg_oauth2_homepage = https://github.com/kivra/oauth2 +pkg_oauth2_fetch = git +pkg_oauth2_repo = https://github.com/kivra/oauth2 +pkg_oauth2_commit = master + +PACKAGES += octopus +pkg_octopus_name = octopus +pkg_octopus_description = Small and flexible pool manager written in Erlang +pkg_octopus_homepage = https://github.com/erlangbureau/octopus +pkg_octopus_fetch = git +pkg_octopus_repo = https://github.com/erlangbureau/octopus +pkg_octopus_commit = master + +PACKAGES += of_protocol +pkg_of_protocol_name = of_protocol +pkg_of_protocol_description = OpenFlow Protocol Library for Erlang +pkg_of_protocol_homepage = https://github.com/FlowForwarding/of_protocol +pkg_of_protocol_fetch = git +pkg_of_protocol_repo = https://github.com/FlowForwarding/of_protocol +pkg_of_protocol_commit = master + +PACKAGES += opencouch +pkg_opencouch_name = couch +pkg_opencouch_description = A embeddable document oriented database compatible with Apache CouchDB +pkg_opencouch_homepage = https://github.com/benoitc/opencouch +pkg_opencouch_fetch = git +pkg_opencouch_repo = https://github.com/benoitc/opencouch +pkg_opencouch_commit = master + +PACKAGES += openflow +pkg_openflow_name = openflow +pkg_openflow_description = An OpenFlow controller written in pure erlang +pkg_openflow_homepage = https://github.com/renatoaguiar/erlang-openflow +pkg_openflow_fetch = git +pkg_openflow_repo = https://github.com/renatoaguiar/erlang-openflow +pkg_openflow_commit = master + +PACKAGES += openid +pkg_openid_name = openid +pkg_openid_description = Erlang OpenID +pkg_openid_homepage = https://github.com/brendonh/erl_openid +pkg_openid_fetch = git +pkg_openid_repo = https://github.com/brendonh/erl_openid +pkg_openid_commit = master + +PACKAGES += openpoker +pkg_openpoker_name = openpoker +pkg_openpoker_description = Genesis Texas hold'em Game Server +pkg_openpoker_homepage = https://github.com/hpyhacking/openpoker +pkg_openpoker_fetch = git +pkg_openpoker_repo = https://github.com/hpyhacking/openpoker +pkg_openpoker_commit = master + +PACKAGES += pal +pkg_pal_name = pal +pkg_pal_description = Pragmatic Authentication Library +pkg_pal_homepage = https://github.com/manifest/pal +pkg_pal_fetch = git +pkg_pal_repo = https://github.com/manifest/pal +pkg_pal_commit = master + +PACKAGES += parse_trans +pkg_parse_trans_name = parse_trans +pkg_parse_trans_description = Parse transform utilities for Erlang +pkg_parse_trans_homepage = https://github.com/uwiger/parse_trans +pkg_parse_trans_fetch = git +pkg_parse_trans_repo = https://github.com/uwiger/parse_trans +pkg_parse_trans_commit = master + +PACKAGES += parsexml +pkg_parsexml_name = parsexml +pkg_parsexml_description = Simple DOM XML parser with convenient and very simple API +pkg_parsexml_homepage = https://github.com/maxlapshin/parsexml +pkg_parsexml_fetch = git +pkg_parsexml_repo = https://github.com/maxlapshin/parsexml +pkg_parsexml_commit = master + +PACKAGES += pegjs +pkg_pegjs_name = pegjs +pkg_pegjs_description = An implementation of PEG.js grammar for Erlang. +pkg_pegjs_homepage = https://github.com/dmitriid/pegjs +pkg_pegjs_fetch = git +pkg_pegjs_repo = https://github.com/dmitriid/pegjs +pkg_pegjs_commit = master + +PACKAGES += percept2 +pkg_percept2_name = percept2 +pkg_percept2_description = Concurrent profiling tool for Erlang +pkg_percept2_homepage = https://github.com/huiqing/percept2 +pkg_percept2_fetch = git +pkg_percept2_repo = https://github.com/huiqing/percept2 +pkg_percept2_commit = master + +PACKAGES += pgsql +pkg_pgsql_name = pgsql +pkg_pgsql_description = Erlang PostgreSQL driver +pkg_pgsql_homepage = https://github.com/semiocast/pgsql +pkg_pgsql_fetch = git +pkg_pgsql_repo = https://github.com/semiocast/pgsql +pkg_pgsql_commit = master + +PACKAGES += pkgx +pkg_pkgx_name = pkgx +pkg_pkgx_description = Build .deb packages from Erlang releases +pkg_pkgx_homepage = https://github.com/arjan/pkgx +pkg_pkgx_fetch = git +pkg_pkgx_repo = https://github.com/arjan/pkgx +pkg_pkgx_commit = master + +PACKAGES += pkt +pkg_pkt_name = pkt +pkg_pkt_description = Erlang network protocol library +pkg_pkt_homepage = https://github.com/msantos/pkt +pkg_pkt_fetch = git +pkg_pkt_repo = https://github.com/msantos/pkt +pkg_pkt_commit = master + +PACKAGES += plain_fsm +pkg_plain_fsm_name = plain_fsm +pkg_plain_fsm_description = A behaviour/support library for writing plain Erlang FSMs. +pkg_plain_fsm_homepage = https://github.com/uwiger/plain_fsm +pkg_plain_fsm_fetch = git +pkg_plain_fsm_repo = https://github.com/uwiger/plain_fsm +pkg_plain_fsm_commit = master + +PACKAGES += plumtree +pkg_plumtree_name = plumtree +pkg_plumtree_description = Epidemic Broadcast Trees +pkg_plumtree_homepage = https://github.com/helium/plumtree +pkg_plumtree_fetch = git +pkg_plumtree_repo = https://github.com/helium/plumtree +pkg_plumtree_commit = master + +PACKAGES += pmod_transform +pkg_pmod_transform_name = pmod_transform +pkg_pmod_transform_description = Parse transform for parameterized modules +pkg_pmod_transform_homepage = https://github.com/erlang/pmod_transform +pkg_pmod_transform_fetch = git +pkg_pmod_transform_repo = https://github.com/erlang/pmod_transform +pkg_pmod_transform_commit = master + +PACKAGES += pobox +pkg_pobox_name = pobox +pkg_pobox_description = External buffer processes to protect against mailbox overflow in Erlang +pkg_pobox_homepage = https://github.com/ferd/pobox +pkg_pobox_fetch = git +pkg_pobox_repo = https://github.com/ferd/pobox +pkg_pobox_commit = master + +PACKAGES += ponos +pkg_ponos_name = ponos +pkg_ponos_description = ponos is a simple yet powerful load generator written in erlang +pkg_ponos_homepage = https://github.com/klarna/ponos +pkg_ponos_fetch = git +pkg_ponos_repo = https://github.com/klarna/ponos +pkg_ponos_commit = master + +PACKAGES += poolboy +pkg_poolboy_name = poolboy +pkg_poolboy_description = A hunky Erlang worker pool factory +pkg_poolboy_homepage = https://github.com/devinus/poolboy +pkg_poolboy_fetch = git +pkg_poolboy_repo = https://github.com/devinus/poolboy +pkg_poolboy_commit = master + +PACKAGES += pooler +pkg_pooler_name = pooler +pkg_pooler_description = An OTP Process Pool Application +pkg_pooler_homepage = https://github.com/seth/pooler +pkg_pooler_fetch = git +pkg_pooler_repo = https://github.com/seth/pooler +pkg_pooler_commit = master + +PACKAGES += pqueue +pkg_pqueue_name = pqueue +pkg_pqueue_description = Erlang Priority Queues +pkg_pqueue_homepage = https://github.com/okeuday/pqueue +pkg_pqueue_fetch = git +pkg_pqueue_repo = https://github.com/okeuday/pqueue +pkg_pqueue_commit = master + +PACKAGES += procket +pkg_procket_name = procket +pkg_procket_description = Erlang interface to low level socket operations +pkg_procket_homepage = http://blog.listincomprehension.com/search/label/procket +pkg_procket_fetch = git +pkg_procket_repo = https://github.com/msantos/procket +pkg_procket_commit = master + +PACKAGES += prop +pkg_prop_name = prop +pkg_prop_description = An Erlang code scaffolding and generator system. +pkg_prop_homepage = https://github.com/nuex/prop +pkg_prop_fetch = git +pkg_prop_repo = https://github.com/nuex/prop +pkg_prop_commit = master + +PACKAGES += proper +pkg_proper_name = proper +pkg_proper_description = PropEr: a QuickCheck-inspired property-based testing tool for Erlang. +pkg_proper_homepage = http://proper.softlab.ntua.gr +pkg_proper_fetch = git +pkg_proper_repo = https://github.com/manopapad/proper +pkg_proper_commit = master + +PACKAGES += props +pkg_props_name = props +pkg_props_description = Property structure library +pkg_props_homepage = https://github.com/greyarea/props +pkg_props_fetch = git +pkg_props_repo = https://github.com/greyarea/props +pkg_props_commit = master + +PACKAGES += protobuffs +pkg_protobuffs_name = protobuffs +pkg_protobuffs_description = An implementation of Google's Protocol Buffers for Erlang, based on ngerakines/erlang_protobuffs. +pkg_protobuffs_homepage = https://github.com/basho/erlang_protobuffs +pkg_protobuffs_fetch = git +pkg_protobuffs_repo = https://github.com/basho/erlang_protobuffs +pkg_protobuffs_commit = master + +PACKAGES += psycho +pkg_psycho_name = psycho +pkg_psycho_description = HTTP server that provides a WSGI-like interface for applications and middleware. +pkg_psycho_homepage = https://github.com/gar1t/psycho +pkg_psycho_fetch = git +pkg_psycho_repo = https://github.com/gar1t/psycho +pkg_psycho_commit = master + +PACKAGES += purity +pkg_purity_name = purity +pkg_purity_description = A side-effect analyzer for Erlang +pkg_purity_homepage = https://github.com/mpitid/purity +pkg_purity_fetch = git +pkg_purity_repo = https://github.com/mpitid/purity +pkg_purity_commit = master + +PACKAGES += push_service +pkg_push_service_name = push_service +pkg_push_service_description = Push service +pkg_push_service_homepage = https://github.com/hairyhum/push_service +pkg_push_service_fetch = git +pkg_push_service_repo = https://github.com/hairyhum/push_service +pkg_push_service_commit = master + +PACKAGES += qdate +pkg_qdate_name = qdate +pkg_qdate_description = Date, time, and timezone parsing, formatting, and conversion for Erlang. +pkg_qdate_homepage = https://github.com/choptastic/qdate +pkg_qdate_fetch = git +pkg_qdate_repo = https://github.com/choptastic/qdate +pkg_qdate_commit = master + +PACKAGES += qrcode +pkg_qrcode_name = qrcode +pkg_qrcode_description = QR Code encoder in Erlang +pkg_qrcode_homepage = https://github.com/komone/qrcode +pkg_qrcode_fetch = git +pkg_qrcode_repo = https://github.com/komone/qrcode +pkg_qrcode_commit = master + +PACKAGES += quest +pkg_quest_name = quest +pkg_quest_description = Learn Erlang through this set of challenges. An interactive system for getting to know Erlang. +pkg_quest_homepage = https://github.com/eriksoe/ErlangQuest +pkg_quest_fetch = git +pkg_quest_repo = https://github.com/eriksoe/ErlangQuest +pkg_quest_commit = master + +PACKAGES += quickrand +pkg_quickrand_name = quickrand +pkg_quickrand_description = Quick Erlang Random Number Generation +pkg_quickrand_homepage = https://github.com/okeuday/quickrand +pkg_quickrand_fetch = git +pkg_quickrand_repo = https://github.com/okeuday/quickrand +pkg_quickrand_commit = master + +PACKAGES += rabbit +pkg_rabbit_name = rabbit +pkg_rabbit_description = RabbitMQ Server +pkg_rabbit_homepage = https://www.rabbitmq.com/ +pkg_rabbit_fetch = git +pkg_rabbit_repo = https://github.com/rabbitmq/rabbitmq-server.git +pkg_rabbit_commit = master + +PACKAGES += rabbit_exchange_type_riak +pkg_rabbit_exchange_type_riak_name = rabbit_exchange_type_riak +pkg_rabbit_exchange_type_riak_description = Custom RabbitMQ exchange type for sticking messages in Riak +pkg_rabbit_exchange_type_riak_homepage = https://github.com/jbrisbin/riak-exchange +pkg_rabbit_exchange_type_riak_fetch = git +pkg_rabbit_exchange_type_riak_repo = https://github.com/jbrisbin/riak-exchange +pkg_rabbit_exchange_type_riak_commit = master + +PACKAGES += rack +pkg_rack_name = rack +pkg_rack_description = Rack handler for erlang +pkg_rack_homepage = https://github.com/erlyvideo/rack +pkg_rack_fetch = git +pkg_rack_repo = https://github.com/erlyvideo/rack +pkg_rack_commit = master + +PACKAGES += radierl +pkg_radierl_name = radierl +pkg_radierl_description = RADIUS protocol stack implemented in Erlang. +pkg_radierl_homepage = https://github.com/vances/radierl +pkg_radierl_fetch = git +pkg_radierl_repo = https://github.com/vances/radierl +pkg_radierl_commit = master + +PACKAGES += rafter +pkg_rafter_name = rafter +pkg_rafter_description = An Erlang library application which implements the Raft consensus protocol +pkg_rafter_homepage = https://github.com/andrewjstone/rafter +pkg_rafter_fetch = git +pkg_rafter_repo = https://github.com/andrewjstone/rafter +pkg_rafter_commit = master + +PACKAGES += ranch +pkg_ranch_name = ranch +pkg_ranch_description = Socket acceptor pool for TCP protocols. +pkg_ranch_homepage = http://ninenines.eu +pkg_ranch_fetch = git +pkg_ranch_repo = https://github.com/ninenines/ranch +pkg_ranch_commit = 1.2.1 + +PACKAGES += rbeacon +pkg_rbeacon_name = rbeacon +pkg_rbeacon_description = LAN discovery and presence in Erlang. +pkg_rbeacon_homepage = https://github.com/refuge/rbeacon +pkg_rbeacon_fetch = git +pkg_rbeacon_repo = https://github.com/refuge/rbeacon +pkg_rbeacon_commit = master + +PACKAGES += rebar +pkg_rebar_name = rebar +pkg_rebar_description = Erlang build tool that makes it easy to compile and test Erlang applications, port drivers and releases. +pkg_rebar_homepage = http://www.rebar3.org +pkg_rebar_fetch = git +pkg_rebar_repo = https://github.com/rebar/rebar3 +pkg_rebar_commit = master + +PACKAGES += rebus +pkg_rebus_name = rebus +pkg_rebus_description = A stupid simple, internal, pub/sub event bus written in- and for Erlang. +pkg_rebus_homepage = https://github.com/olle/rebus +pkg_rebus_fetch = git +pkg_rebus_repo = https://github.com/olle/rebus +pkg_rebus_commit = master + +PACKAGES += rec2json +pkg_rec2json_name = rec2json +pkg_rec2json_description = Compile erlang record definitions into modules to convert them to/from json easily. +pkg_rec2json_homepage = https://github.com/lordnull/rec2json +pkg_rec2json_fetch = git +pkg_rec2json_repo = https://github.com/lordnull/rec2json +pkg_rec2json_commit = master + +PACKAGES += recon +pkg_recon_name = recon +pkg_recon_description = Collection of functions and scripts to debug Erlang in production. +pkg_recon_homepage = https://github.com/ferd/recon +pkg_recon_fetch = git +pkg_recon_repo = https://github.com/ferd/recon +pkg_recon_commit = master + +PACKAGES += record_info +pkg_record_info_name = record_info +pkg_record_info_description = Convert between record and proplist +pkg_record_info_homepage = https://github.com/bipthelin/erlang-record_info +pkg_record_info_fetch = git +pkg_record_info_repo = https://github.com/bipthelin/erlang-record_info +pkg_record_info_commit = master + +PACKAGES += redgrid +pkg_redgrid_name = redgrid +pkg_redgrid_description = automatic Erlang node discovery via redis +pkg_redgrid_homepage = https://github.com/jkvor/redgrid +pkg_redgrid_fetch = git +pkg_redgrid_repo = https://github.com/jkvor/redgrid +pkg_redgrid_commit = master + +PACKAGES += redo +pkg_redo_name = redo +pkg_redo_description = pipelined erlang redis client +pkg_redo_homepage = https://github.com/jkvor/redo +pkg_redo_fetch = git +pkg_redo_repo = https://github.com/jkvor/redo +pkg_redo_commit = master + +PACKAGES += reload_mk +pkg_reload_mk_name = reload_mk +pkg_reload_mk_description = Live reload plugin for erlang.mk. +pkg_reload_mk_homepage = https://github.com/bullno1/reload.mk +pkg_reload_mk_fetch = git +pkg_reload_mk_repo = https://github.com/bullno1/reload.mk +pkg_reload_mk_commit = master + +PACKAGES += reltool_util +pkg_reltool_util_name = reltool_util +pkg_reltool_util_description = Erlang reltool utility functionality application +pkg_reltool_util_homepage = https://github.com/okeuday/reltool_util +pkg_reltool_util_fetch = git +pkg_reltool_util_repo = https://github.com/okeuday/reltool_util +pkg_reltool_util_commit = master + +PACKAGES += relx +pkg_relx_name = relx +pkg_relx_description = Sane, simple release creation for Erlang +pkg_relx_homepage = https://github.com/erlware/relx +pkg_relx_fetch = git +pkg_relx_repo = https://github.com/erlware/relx +pkg_relx_commit = master + +PACKAGES += resource_discovery +pkg_resource_discovery_name = resource_discovery +pkg_resource_discovery_description = An application used to dynamically discover resources present in an Erlang node cluster. +pkg_resource_discovery_homepage = http://erlware.org/ +pkg_resource_discovery_fetch = git +pkg_resource_discovery_repo = https://github.com/erlware/resource_discovery +pkg_resource_discovery_commit = master + +PACKAGES += restc +pkg_restc_name = restc +pkg_restc_description = Erlang Rest Client +pkg_restc_homepage = https://github.com/kivra/restclient +pkg_restc_fetch = git +pkg_restc_repo = https://github.com/kivra/restclient +pkg_restc_commit = master + +PACKAGES += rfc4627_jsonrpc +pkg_rfc4627_jsonrpc_name = rfc4627_jsonrpc +pkg_rfc4627_jsonrpc_description = Erlang RFC4627 (JSON) codec and JSON-RPC server implementation. +pkg_rfc4627_jsonrpc_homepage = https://github.com/tonyg/erlang-rfc4627 +pkg_rfc4627_jsonrpc_fetch = git +pkg_rfc4627_jsonrpc_repo = https://github.com/tonyg/erlang-rfc4627 +pkg_rfc4627_jsonrpc_commit = master + +PACKAGES += riak_control +pkg_riak_control_name = riak_control +pkg_riak_control_description = Webmachine-based administration interface for Riak. +pkg_riak_control_homepage = https://github.com/basho/riak_control +pkg_riak_control_fetch = git +pkg_riak_control_repo = https://github.com/basho/riak_control +pkg_riak_control_commit = master + +PACKAGES += riak_core +pkg_riak_core_name = riak_core +pkg_riak_core_description = Distributed systems infrastructure used by Riak. +pkg_riak_core_homepage = https://github.com/basho/riak_core +pkg_riak_core_fetch = git +pkg_riak_core_repo = https://github.com/basho/riak_core +pkg_riak_core_commit = master + +PACKAGES += riak_dt +pkg_riak_dt_name = riak_dt +pkg_riak_dt_description = Convergent replicated datatypes in Erlang +pkg_riak_dt_homepage = https://github.com/basho/riak_dt +pkg_riak_dt_fetch = git +pkg_riak_dt_repo = https://github.com/basho/riak_dt +pkg_riak_dt_commit = master + +PACKAGES += riak_ensemble +pkg_riak_ensemble_name = riak_ensemble +pkg_riak_ensemble_description = Multi-Paxos framework in Erlang +pkg_riak_ensemble_homepage = https://github.com/basho/riak_ensemble +pkg_riak_ensemble_fetch = git +pkg_riak_ensemble_repo = https://github.com/basho/riak_ensemble +pkg_riak_ensemble_commit = master + +PACKAGES += riak_kv +pkg_riak_kv_name = riak_kv +pkg_riak_kv_description = Riak Key/Value Store +pkg_riak_kv_homepage = https://github.com/basho/riak_kv +pkg_riak_kv_fetch = git +pkg_riak_kv_repo = https://github.com/basho/riak_kv +pkg_riak_kv_commit = master + +PACKAGES += riak_pg +pkg_riak_pg_name = riak_pg +pkg_riak_pg_description = Distributed process groups with riak_core. +pkg_riak_pg_homepage = https://github.com/cmeiklejohn/riak_pg +pkg_riak_pg_fetch = git +pkg_riak_pg_repo = https://github.com/cmeiklejohn/riak_pg +pkg_riak_pg_commit = master + +PACKAGES += riak_pipe +pkg_riak_pipe_name = riak_pipe +pkg_riak_pipe_description = Riak Pipelines +pkg_riak_pipe_homepage = https://github.com/basho/riak_pipe +pkg_riak_pipe_fetch = git +pkg_riak_pipe_repo = https://github.com/basho/riak_pipe +pkg_riak_pipe_commit = master + +PACKAGES += riak_sysmon +pkg_riak_sysmon_name = riak_sysmon +pkg_riak_sysmon_description = Simple OTP app for managing Erlang VM system_monitor event messages +pkg_riak_sysmon_homepage = https://github.com/basho/riak_sysmon +pkg_riak_sysmon_fetch = git +pkg_riak_sysmon_repo = https://github.com/basho/riak_sysmon +pkg_riak_sysmon_commit = master + +PACKAGES += riak_test +pkg_riak_test_name = riak_test +pkg_riak_test_description = I'm in your cluster, testing your riaks +pkg_riak_test_homepage = https://github.com/basho/riak_test +pkg_riak_test_fetch = git +pkg_riak_test_repo = https://github.com/basho/riak_test +pkg_riak_test_commit = master + +PACKAGES += riakc +pkg_riakc_name = riakc +pkg_riakc_description = Erlang clients for Riak. +pkg_riakc_homepage = https://github.com/basho/riak-erlang-client +pkg_riakc_fetch = git +pkg_riakc_repo = https://github.com/basho/riak-erlang-client +pkg_riakc_commit = master + +PACKAGES += riakhttpc +pkg_riakhttpc_name = riakhttpc +pkg_riakhttpc_description = Riak Erlang client using the HTTP interface +pkg_riakhttpc_homepage = https://github.com/basho/riak-erlang-http-client +pkg_riakhttpc_fetch = git +pkg_riakhttpc_repo = https://github.com/basho/riak-erlang-http-client +pkg_riakhttpc_commit = master + +PACKAGES += riaknostic +pkg_riaknostic_name = riaknostic +pkg_riaknostic_description = A diagnostic tool for Riak installations, to find common errors asap +pkg_riaknostic_homepage = https://github.com/basho/riaknostic +pkg_riaknostic_fetch = git +pkg_riaknostic_repo = https://github.com/basho/riaknostic +pkg_riaknostic_commit = master + +PACKAGES += riakpool +pkg_riakpool_name = riakpool +pkg_riakpool_description = erlang riak client pool +pkg_riakpool_homepage = https://github.com/dweldon/riakpool +pkg_riakpool_fetch = git +pkg_riakpool_repo = https://github.com/dweldon/riakpool +pkg_riakpool_commit = master + +PACKAGES += rivus_cep +pkg_rivus_cep_name = rivus_cep +pkg_rivus_cep_description = Complex event processing in Erlang +pkg_rivus_cep_homepage = https://github.com/vascokk/rivus_cep +pkg_rivus_cep_fetch = git +pkg_rivus_cep_repo = https://github.com/vascokk/rivus_cep +pkg_rivus_cep_commit = master + +PACKAGES += rlimit +pkg_rlimit_name = rlimit +pkg_rlimit_description = Magnus Klaar's rate limiter code from etorrent +pkg_rlimit_homepage = https://github.com/jlouis/rlimit +pkg_rlimit_fetch = git +pkg_rlimit_repo = https://github.com/jlouis/rlimit +pkg_rlimit_commit = master + +PACKAGES += rust_mk +pkg_rust_mk_name = rust_mk +pkg_rust_mk_description = Build Rust crates in an Erlang application +pkg_rust_mk_homepage = https://github.com/goertzenator/rust.mk +pkg_rust_mk_fetch = git +pkg_rust_mk_repo = https://github.com/goertzenator/rust.mk +pkg_rust_mk_commit = master + +PACKAGES += safetyvalve +pkg_safetyvalve_name = safetyvalve +pkg_safetyvalve_description = A safety valve for your erlang node +pkg_safetyvalve_homepage = https://github.com/jlouis/safetyvalve +pkg_safetyvalve_fetch = git +pkg_safetyvalve_repo = https://github.com/jlouis/safetyvalve +pkg_safetyvalve_commit = master + +PACKAGES += seestar +pkg_seestar_name = seestar +pkg_seestar_description = The Erlang client for Cassandra 1.2+ binary protocol +pkg_seestar_homepage = https://github.com/iamaleksey/seestar +pkg_seestar_fetch = git +pkg_seestar_repo = https://github.com/iamaleksey/seestar +pkg_seestar_commit = master + +PACKAGES += service +pkg_service_name = service +pkg_service_description = A minimal Erlang behavior for creating CloudI internal services +pkg_service_homepage = http://cloudi.org/ +pkg_service_fetch = git +pkg_service_repo = https://github.com/CloudI/service +pkg_service_commit = master + +PACKAGES += setup +pkg_setup_name = setup +pkg_setup_description = Generic setup utility for Erlang-based systems +pkg_setup_homepage = https://github.com/uwiger/setup +pkg_setup_fetch = git +pkg_setup_repo = https://github.com/uwiger/setup +pkg_setup_commit = master + +PACKAGES += sext +pkg_sext_name = sext +pkg_sext_description = Sortable Erlang Term Serialization +pkg_sext_homepage = https://github.com/uwiger/sext +pkg_sext_fetch = git +pkg_sext_repo = https://github.com/uwiger/sext +pkg_sext_commit = master + +PACKAGES += sfmt +pkg_sfmt_name = sfmt +pkg_sfmt_description = SFMT pseudo random number generator for Erlang. +pkg_sfmt_homepage = https://github.com/jj1bdx/sfmt-erlang +pkg_sfmt_fetch = git +pkg_sfmt_repo = https://github.com/jj1bdx/sfmt-erlang +pkg_sfmt_commit = master + +PACKAGES += sgte +pkg_sgte_name = sgte +pkg_sgte_description = A simple Erlang Template Engine +pkg_sgte_homepage = https://github.com/filippo/sgte +pkg_sgte_fetch = git +pkg_sgte_repo = https://github.com/filippo/sgte +pkg_sgte_commit = master + +PACKAGES += sheriff +pkg_sheriff_name = sheriff +pkg_sheriff_description = Parse transform for type based validation. +pkg_sheriff_homepage = http://ninenines.eu +pkg_sheriff_fetch = git +pkg_sheriff_repo = https://github.com/extend/sheriff +pkg_sheriff_commit = master + +PACKAGES += shotgun +pkg_shotgun_name = shotgun +pkg_shotgun_description = better than just a gun +pkg_shotgun_homepage = https://github.com/inaka/shotgun +pkg_shotgun_fetch = git +pkg_shotgun_repo = https://github.com/inaka/shotgun +pkg_shotgun_commit = master + +PACKAGES += sidejob +pkg_sidejob_name = sidejob +pkg_sidejob_description = Parallel worker and capacity limiting library for Erlang +pkg_sidejob_homepage = https://github.com/basho/sidejob +pkg_sidejob_fetch = git +pkg_sidejob_repo = https://github.com/basho/sidejob +pkg_sidejob_commit = master + +PACKAGES += sieve +pkg_sieve_name = sieve +pkg_sieve_description = sieve is a simple TCP routing proxy (layer 7) in erlang +pkg_sieve_homepage = https://github.com/benoitc/sieve +pkg_sieve_fetch = git +pkg_sieve_repo = https://github.com/benoitc/sieve +pkg_sieve_commit = master + +PACKAGES += sighandler +pkg_sighandler_name = sighandler +pkg_sighandler_description = Handle UNIX signals in Er lang +pkg_sighandler_homepage = https://github.com/jkingsbery/sighandler +pkg_sighandler_fetch = git +pkg_sighandler_repo = https://github.com/jkingsbery/sighandler +pkg_sighandler_commit = master + +PACKAGES += simhash +pkg_simhash_name = simhash +pkg_simhash_description = Simhashing for Erlang -- hashing algorithm to find near-duplicates in binary data. +pkg_simhash_homepage = https://github.com/ferd/simhash +pkg_simhash_fetch = git +pkg_simhash_repo = https://github.com/ferd/simhash +pkg_simhash_commit = master + +PACKAGES += simple_bridge +pkg_simple_bridge_name = simple_bridge +pkg_simple_bridge_description = A simple, standardized interface library to Erlang HTTP Servers. +pkg_simple_bridge_homepage = https://github.com/nitrogen/simple_bridge +pkg_simple_bridge_fetch = git +pkg_simple_bridge_repo = https://github.com/nitrogen/simple_bridge +pkg_simple_bridge_commit = master + +PACKAGES += simple_oauth2 +pkg_simple_oauth2_name = simple_oauth2 +pkg_simple_oauth2_description = Simple erlang OAuth2 client module for any http server framework (Google, Facebook, Yandex, Vkontakte are preconfigured) +pkg_simple_oauth2_homepage = https://github.com/virtan/simple_oauth2 +pkg_simple_oauth2_fetch = git +pkg_simple_oauth2_repo = https://github.com/virtan/simple_oauth2 +pkg_simple_oauth2_commit = master + +PACKAGES += skel +pkg_skel_name = skel +pkg_skel_description = A Streaming Process-based Skeleton Library for Erlang +pkg_skel_homepage = https://github.com/ParaPhrase/skel +pkg_skel_fetch = git +pkg_skel_repo = https://github.com/ParaPhrase/skel +pkg_skel_commit = master + +PACKAGES += slack +pkg_slack_name = slack +pkg_slack_description = Minimal slack notification OTP library. +pkg_slack_homepage = https://github.com/DonBranson/slack +pkg_slack_fetch = git +pkg_slack_repo = https://github.com/DonBranson/slack.git +pkg_slack_commit = master + +PACKAGES += smother +pkg_smother_name = smother +pkg_smother_description = Extended code coverage metrics for Erlang. +pkg_smother_homepage = https://ramsay-t.github.io/Smother/ +pkg_smother_fetch = git +pkg_smother_repo = https://github.com/ramsay-t/Smother +pkg_smother_commit = master + +PACKAGES += snappyer +pkg_snappyer_name = snappyer +pkg_snappyer_description = Snappy as nif for Erlang +pkg_snappyer_homepage = https://github.com/zmstone/snappyer +pkg_snappyer_fetch = git +pkg_snappyer_repo = https://github.com/zmstone/snappyer.git +pkg_snappyer_commit = master + +PACKAGES += social +pkg_social_name = social +pkg_social_description = Cowboy handler for social login via OAuth2 providers +pkg_social_homepage = https://github.com/dvv/social +pkg_social_fetch = git +pkg_social_repo = https://github.com/dvv/social +pkg_social_commit = master + +PACKAGES += spapi_router +pkg_spapi_router_name = spapi_router +pkg_spapi_router_description = Partially-connected Erlang clustering +pkg_spapi_router_homepage = https://github.com/spilgames/spapi-router +pkg_spapi_router_fetch = git +pkg_spapi_router_repo = https://github.com/spilgames/spapi-router +pkg_spapi_router_commit = master + +PACKAGES += sqerl +pkg_sqerl_name = sqerl +pkg_sqerl_description = An Erlang-flavoured SQL DSL +pkg_sqerl_homepage = https://github.com/hairyhum/sqerl +pkg_sqerl_fetch = git +pkg_sqerl_repo = https://github.com/hairyhum/sqerl +pkg_sqerl_commit = master + +PACKAGES += srly +pkg_srly_name = srly +pkg_srly_description = Native Erlang Unix serial interface +pkg_srly_homepage = https://github.com/msantos/srly +pkg_srly_fetch = git +pkg_srly_repo = https://github.com/msantos/srly +pkg_srly_commit = master + +PACKAGES += sshrpc +pkg_sshrpc_name = sshrpc +pkg_sshrpc_description = Erlang SSH RPC module (experimental) +pkg_sshrpc_homepage = https://github.com/jj1bdx/sshrpc +pkg_sshrpc_fetch = git +pkg_sshrpc_repo = https://github.com/jj1bdx/sshrpc +pkg_sshrpc_commit = master + +PACKAGES += stable +pkg_stable_name = stable +pkg_stable_description = Library of assorted helpers for Cowboy web server. +pkg_stable_homepage = https://github.com/dvv/stable +pkg_stable_fetch = git +pkg_stable_repo = https://github.com/dvv/stable +pkg_stable_commit = master + +PACKAGES += statebox +pkg_statebox_name = statebox +pkg_statebox_description = Erlang state monad with merge/conflict-resolution capabilities. Useful for Riak. +pkg_statebox_homepage = https://github.com/mochi/statebox +pkg_statebox_fetch = git +pkg_statebox_repo = https://github.com/mochi/statebox +pkg_statebox_commit = master + +PACKAGES += statebox_riak +pkg_statebox_riak_name = statebox_riak +pkg_statebox_riak_description = Convenience library that makes it easier to use statebox with riak, extracted from best practices in our production code at Mochi Media. +pkg_statebox_riak_homepage = https://github.com/mochi/statebox_riak +pkg_statebox_riak_fetch = git +pkg_statebox_riak_repo = https://github.com/mochi/statebox_riak +pkg_statebox_riak_commit = master + +PACKAGES += statman +pkg_statman_name = statman +pkg_statman_description = Efficiently collect massive volumes of metrics inside the Erlang VM +pkg_statman_homepage = https://github.com/knutin/statman +pkg_statman_fetch = git +pkg_statman_repo = https://github.com/knutin/statman +pkg_statman_commit = master + +PACKAGES += statsderl +pkg_statsderl_name = statsderl +pkg_statsderl_description = StatsD client (erlang) +pkg_statsderl_homepage = https://github.com/lpgauth/statsderl +pkg_statsderl_fetch = git +pkg_statsderl_repo = https://github.com/lpgauth/statsderl +pkg_statsderl_commit = master + +PACKAGES += stdinout_pool +pkg_stdinout_pool_name = stdinout_pool +pkg_stdinout_pool_description = stdinout_pool : stuff goes in, stuff goes out. there's never any miscommunication. +pkg_stdinout_pool_homepage = https://github.com/mattsta/erlang-stdinout-pool +pkg_stdinout_pool_fetch = git +pkg_stdinout_pool_repo = https://github.com/mattsta/erlang-stdinout-pool +pkg_stdinout_pool_commit = master + +PACKAGES += stockdb +pkg_stockdb_name = stockdb +pkg_stockdb_description = Database for storing Stock Exchange quotes in erlang +pkg_stockdb_homepage = https://github.com/maxlapshin/stockdb +pkg_stockdb_fetch = git +pkg_stockdb_repo = https://github.com/maxlapshin/stockdb +pkg_stockdb_commit = master + +PACKAGES += stripe +pkg_stripe_name = stripe +pkg_stripe_description = Erlang interface to the stripe.com API +pkg_stripe_homepage = https://github.com/mattsta/stripe-erlang +pkg_stripe_fetch = git +pkg_stripe_repo = https://github.com/mattsta/stripe-erlang +pkg_stripe_commit = v1 + +PACKAGES += supervisor3 +pkg_supervisor3_name = supervisor3 +pkg_supervisor3_description = OTP supervisor with additional strategies +pkg_supervisor3_homepage = https://github.com/klarna/supervisor3 +pkg_supervisor3_fetch = git +pkg_supervisor3_repo = https://github.com/klarna/supervisor3.git +pkg_supervisor3_commit = master + +PACKAGES += surrogate +pkg_surrogate_name = surrogate +pkg_surrogate_description = Proxy server written in erlang. Supports reverse proxy load balancing and forward proxy with http (including CONNECT), socks4, socks5, and transparent proxy modes. +pkg_surrogate_homepage = https://github.com/skruger/Surrogate +pkg_surrogate_fetch = git +pkg_surrogate_repo = https://github.com/skruger/Surrogate +pkg_surrogate_commit = master + +PACKAGES += swab +pkg_swab_name = swab +pkg_swab_description = General purpose buffer handling module +pkg_swab_homepage = https://github.com/crownedgrouse/swab +pkg_swab_fetch = git +pkg_swab_repo = https://github.com/crownedgrouse/swab +pkg_swab_commit = master + +PACKAGES += swarm +pkg_swarm_name = swarm +pkg_swarm_description = Fast and simple acceptor pool for Erlang +pkg_swarm_homepage = https://github.com/jeremey/swarm +pkg_swarm_fetch = git +pkg_swarm_repo = https://github.com/jeremey/swarm +pkg_swarm_commit = master + +PACKAGES += switchboard +pkg_switchboard_name = switchboard +pkg_switchboard_description = A framework for processing email using worker plugins. +pkg_switchboard_homepage = https://github.com/thusfresh/switchboard +pkg_switchboard_fetch = git +pkg_switchboard_repo = https://github.com/thusfresh/switchboard +pkg_switchboard_commit = master + +PACKAGES += syn +pkg_syn_name = syn +pkg_syn_description = A global Process Registry and Process Group manager for Erlang. +pkg_syn_homepage = https://github.com/ostinelli/syn +pkg_syn_fetch = git +pkg_syn_repo = https://github.com/ostinelli/syn +pkg_syn_commit = master + +PACKAGES += sync +pkg_sync_name = sync +pkg_sync_description = On-the-fly recompiling and reloading in Erlang. +pkg_sync_homepage = https://github.com/rustyio/sync +pkg_sync_fetch = git +pkg_sync_repo = https://github.com/rustyio/sync +pkg_sync_commit = master + +PACKAGES += syntaxerl +pkg_syntaxerl_name = syntaxerl +pkg_syntaxerl_description = Syntax checker for Erlang +pkg_syntaxerl_homepage = https://github.com/ten0s/syntaxerl +pkg_syntaxerl_fetch = git +pkg_syntaxerl_repo = https://github.com/ten0s/syntaxerl +pkg_syntaxerl_commit = master + +PACKAGES += syslog +pkg_syslog_name = syslog +pkg_syslog_description = Erlang port driver for interacting with syslog via syslog(3) +pkg_syslog_homepage = https://github.com/Vagabond/erlang-syslog +pkg_syslog_fetch = git +pkg_syslog_repo = https://github.com/Vagabond/erlang-syslog +pkg_syslog_commit = master + +PACKAGES += taskforce +pkg_taskforce_name = taskforce +pkg_taskforce_description = Erlang worker pools for controlled parallelisation of arbitrary tasks. +pkg_taskforce_homepage = https://github.com/g-andrade/taskforce +pkg_taskforce_fetch = git +pkg_taskforce_repo = https://github.com/g-andrade/taskforce +pkg_taskforce_commit = master + +PACKAGES += tddreloader +pkg_tddreloader_name = tddreloader +pkg_tddreloader_description = Shell utility for recompiling, reloading, and testing code as it changes +pkg_tddreloader_homepage = https://github.com/version2beta/tddreloader +pkg_tddreloader_fetch = git +pkg_tddreloader_repo = https://github.com/version2beta/tddreloader +pkg_tddreloader_commit = master + +PACKAGES += tempo +pkg_tempo_name = tempo +pkg_tempo_description = NIF-based date and time parsing and formatting for Erlang. +pkg_tempo_homepage = https://github.com/selectel/tempo +pkg_tempo_fetch = git +pkg_tempo_repo = https://github.com/selectel/tempo +pkg_tempo_commit = master + +PACKAGES += ticktick +pkg_ticktick_name = ticktick +pkg_ticktick_description = Ticktick is an id generator for message service. +pkg_ticktick_homepage = https://github.com/ericliang/ticktick +pkg_ticktick_fetch = git +pkg_ticktick_repo = https://github.com/ericliang/ticktick +pkg_ticktick_commit = master + +PACKAGES += tinymq +pkg_tinymq_name = tinymq +pkg_tinymq_description = TinyMQ - a diminutive, in-memory message queue +pkg_tinymq_homepage = https://github.com/ChicagoBoss/tinymq +pkg_tinymq_fetch = git +pkg_tinymq_repo = https://github.com/ChicagoBoss/tinymq +pkg_tinymq_commit = master + +PACKAGES += tinymt +pkg_tinymt_name = tinymt +pkg_tinymt_description = TinyMT pseudo random number generator for Erlang. +pkg_tinymt_homepage = https://github.com/jj1bdx/tinymt-erlang +pkg_tinymt_fetch = git +pkg_tinymt_repo = https://github.com/jj1bdx/tinymt-erlang +pkg_tinymt_commit = master + +PACKAGES += tirerl +pkg_tirerl_name = tirerl +pkg_tirerl_description = Erlang interface to Elastic Search +pkg_tirerl_homepage = https://github.com/inaka/tirerl +pkg_tirerl_fetch = git +pkg_tirerl_repo = https://github.com/inaka/tirerl +pkg_tirerl_commit = master + +PACKAGES += traffic_tools +pkg_traffic_tools_name = traffic_tools +pkg_traffic_tools_description = Simple traffic limiting library +pkg_traffic_tools_homepage = https://github.com/systra/traffic_tools +pkg_traffic_tools_fetch = git +pkg_traffic_tools_repo = https://github.com/systra/traffic_tools +pkg_traffic_tools_commit = master + +PACKAGES += trails +pkg_trails_name = trails +pkg_trails_description = A couple of improvements over Cowboy Routes +pkg_trails_homepage = http://inaka.github.io/cowboy-trails/ +pkg_trails_fetch = git +pkg_trails_repo = https://github.com/inaka/cowboy-trails +pkg_trails_commit = master + +PACKAGES += trane +pkg_trane_name = trane +pkg_trane_description = SAX style broken HTML parser in Erlang +pkg_trane_homepage = https://github.com/massemanet/trane +pkg_trane_fetch = git +pkg_trane_repo = https://github.com/massemanet/trane +pkg_trane_commit = master + +PACKAGES += transit +pkg_transit_name = transit +pkg_transit_description = transit format for erlang +pkg_transit_homepage = https://github.com/isaiah/transit-erlang +pkg_transit_fetch = git +pkg_transit_repo = https://github.com/isaiah/transit-erlang +pkg_transit_commit = master + +PACKAGES += trie +pkg_trie_name = trie +pkg_trie_description = Erlang Trie Implementation +pkg_trie_homepage = https://github.com/okeuday/trie +pkg_trie_fetch = git +pkg_trie_repo = https://github.com/okeuday/trie +pkg_trie_commit = master + +PACKAGES += triq +pkg_triq_name = triq +pkg_triq_description = Trifork QuickCheck +pkg_triq_homepage = https://github.com/krestenkrab/triq +pkg_triq_fetch = git +pkg_triq_repo = https://github.com/krestenkrab/triq +pkg_triq_commit = master + +PACKAGES += tunctl +pkg_tunctl_name = tunctl +pkg_tunctl_description = Erlang TUN/TAP interface +pkg_tunctl_homepage = https://github.com/msantos/tunctl +pkg_tunctl_fetch = git +pkg_tunctl_repo = https://github.com/msantos/tunctl +pkg_tunctl_commit = master + +PACKAGES += twerl +pkg_twerl_name = twerl +pkg_twerl_description = Erlang client for the Twitter Streaming API +pkg_twerl_homepage = https://github.com/lucaspiller/twerl +pkg_twerl_fetch = git +pkg_twerl_repo = https://github.com/lucaspiller/twerl +pkg_twerl_commit = oauth + +PACKAGES += twitter_erlang +pkg_twitter_erlang_name = twitter_erlang +pkg_twitter_erlang_description = An Erlang twitter client +pkg_twitter_erlang_homepage = https://github.com/ngerakines/erlang_twitter +pkg_twitter_erlang_fetch = git +pkg_twitter_erlang_repo = https://github.com/ngerakines/erlang_twitter +pkg_twitter_erlang_commit = master + +PACKAGES += ucol_nif +pkg_ucol_nif_name = ucol_nif +pkg_ucol_nif_description = ICU based collation Erlang module +pkg_ucol_nif_homepage = https://github.com/refuge/ucol_nif +pkg_ucol_nif_fetch = git +pkg_ucol_nif_repo = https://github.com/refuge/ucol_nif +pkg_ucol_nif_commit = master + +PACKAGES += unicorn +pkg_unicorn_name = unicorn +pkg_unicorn_description = Generic configuration server +pkg_unicorn_homepage = https://github.com/shizzard/unicorn +pkg_unicorn_fetch = git +pkg_unicorn_repo = https://github.com/shizzard/unicorn +pkg_unicorn_commit = master + +PACKAGES += unsplit +pkg_unsplit_name = unsplit +pkg_unsplit_description = Resolves conflicts in Mnesia after network splits +pkg_unsplit_homepage = https://github.com/uwiger/unsplit +pkg_unsplit_fetch = git +pkg_unsplit_repo = https://github.com/uwiger/unsplit +pkg_unsplit_commit = master + +PACKAGES += uuid +pkg_uuid_name = uuid +pkg_uuid_description = Erlang UUID Implementation +pkg_uuid_homepage = https://github.com/okeuday/uuid +pkg_uuid_fetch = git +pkg_uuid_repo = https://github.com/okeuday/uuid +pkg_uuid_commit = master + +PACKAGES += ux +pkg_ux_name = ux +pkg_ux_description = Unicode eXtention for Erlang (Strings, Collation) +pkg_ux_homepage = https://github.com/erlang-unicode/ux +pkg_ux_fetch = git +pkg_ux_repo = https://github.com/erlang-unicode/ux +pkg_ux_commit = master + +PACKAGES += vert +pkg_vert_name = vert +pkg_vert_description = Erlang binding to libvirt virtualization API +pkg_vert_homepage = https://github.com/msantos/erlang-libvirt +pkg_vert_fetch = git +pkg_vert_repo = https://github.com/msantos/erlang-libvirt +pkg_vert_commit = master + +PACKAGES += verx +pkg_verx_name = verx +pkg_verx_description = Erlang implementation of the libvirtd remote protocol +pkg_verx_homepage = https://github.com/msantos/verx +pkg_verx_fetch = git +pkg_verx_repo = https://github.com/msantos/verx +pkg_verx_commit = master + +PACKAGES += vmq_acl +pkg_vmq_acl_name = vmq_acl +pkg_vmq_acl_description = Component of VerneMQ: A distributed MQTT message broker +pkg_vmq_acl_homepage = https://verne.mq/ +pkg_vmq_acl_fetch = git +pkg_vmq_acl_repo = https://github.com/erlio/vmq_acl +pkg_vmq_acl_commit = master + +PACKAGES += vmq_bridge +pkg_vmq_bridge_name = vmq_bridge +pkg_vmq_bridge_description = Component of VerneMQ: A distributed MQTT message broker +pkg_vmq_bridge_homepage = https://verne.mq/ +pkg_vmq_bridge_fetch = git +pkg_vmq_bridge_repo = https://github.com/erlio/vmq_bridge +pkg_vmq_bridge_commit = master + +PACKAGES += vmq_graphite +pkg_vmq_graphite_name = vmq_graphite +pkg_vmq_graphite_description = Component of VerneMQ: A distributed MQTT message broker +pkg_vmq_graphite_homepage = https://verne.mq/ +pkg_vmq_graphite_fetch = git +pkg_vmq_graphite_repo = https://github.com/erlio/vmq_graphite +pkg_vmq_graphite_commit = master + +PACKAGES += vmq_passwd +pkg_vmq_passwd_name = vmq_passwd +pkg_vmq_passwd_description = Component of VerneMQ: A distributed MQTT message broker +pkg_vmq_passwd_homepage = https://verne.mq/ +pkg_vmq_passwd_fetch = git +pkg_vmq_passwd_repo = https://github.com/erlio/vmq_passwd +pkg_vmq_passwd_commit = master + +PACKAGES += vmq_server +pkg_vmq_server_name = vmq_server +pkg_vmq_server_description = Component of VerneMQ: A distributed MQTT message broker +pkg_vmq_server_homepage = https://verne.mq/ +pkg_vmq_server_fetch = git +pkg_vmq_server_repo = https://github.com/erlio/vmq_server +pkg_vmq_server_commit = master + +PACKAGES += vmq_snmp +pkg_vmq_snmp_name = vmq_snmp +pkg_vmq_snmp_description = Component of VerneMQ: A distributed MQTT message broker +pkg_vmq_snmp_homepage = https://verne.mq/ +pkg_vmq_snmp_fetch = git +pkg_vmq_snmp_repo = https://github.com/erlio/vmq_snmp +pkg_vmq_snmp_commit = master + +PACKAGES += vmq_systree +pkg_vmq_systree_name = vmq_systree +pkg_vmq_systree_description = Component of VerneMQ: A distributed MQTT message broker +pkg_vmq_systree_homepage = https://verne.mq/ +pkg_vmq_systree_fetch = git +pkg_vmq_systree_repo = https://github.com/erlio/vmq_systree +pkg_vmq_systree_commit = master + +PACKAGES += vmstats +pkg_vmstats_name = vmstats +pkg_vmstats_description = tiny Erlang app that works in conjunction with statsderl in order to generate information on the Erlang VM for graphite logs. +pkg_vmstats_homepage = https://github.com/ferd/vmstats +pkg_vmstats_fetch = git +pkg_vmstats_repo = https://github.com/ferd/vmstats +pkg_vmstats_commit = master + +PACKAGES += walrus +pkg_walrus_name = walrus +pkg_walrus_description = Walrus - Mustache-like Templating +pkg_walrus_homepage = https://github.com/devinus/walrus +pkg_walrus_fetch = git +pkg_walrus_repo = https://github.com/devinus/walrus +pkg_walrus_commit = master + +PACKAGES += webmachine +pkg_webmachine_name = webmachine +pkg_webmachine_description = A REST-based system for building web applications. +pkg_webmachine_homepage = https://github.com/basho/webmachine +pkg_webmachine_fetch = git +pkg_webmachine_repo = https://github.com/basho/webmachine +pkg_webmachine_commit = master + +PACKAGES += websocket_client +pkg_websocket_client_name = websocket_client +pkg_websocket_client_description = Erlang websocket client (ws and wss supported) +pkg_websocket_client_homepage = https://github.com/jeremyong/websocket_client +pkg_websocket_client_fetch = git +pkg_websocket_client_repo = https://github.com/jeremyong/websocket_client +pkg_websocket_client_commit = master + +PACKAGES += worker_pool +pkg_worker_pool_name = worker_pool +pkg_worker_pool_description = a simple erlang worker pool +pkg_worker_pool_homepage = https://github.com/inaka/worker_pool +pkg_worker_pool_fetch = git +pkg_worker_pool_repo = https://github.com/inaka/worker_pool +pkg_worker_pool_commit = master + +PACKAGES += wrangler +pkg_wrangler_name = wrangler +pkg_wrangler_description = Import of the Wrangler svn repository. +pkg_wrangler_homepage = http://www.cs.kent.ac.uk/projects/wrangler/Home.html +pkg_wrangler_fetch = git +pkg_wrangler_repo = https://github.com/RefactoringTools/wrangler +pkg_wrangler_commit = master + +PACKAGES += wsock +pkg_wsock_name = wsock +pkg_wsock_description = Erlang library to build WebSocket clients and servers +pkg_wsock_homepage = https://github.com/madtrick/wsock +pkg_wsock_fetch = git +pkg_wsock_repo = https://github.com/madtrick/wsock +pkg_wsock_commit = master + +PACKAGES += xhttpc +pkg_xhttpc_name = xhttpc +pkg_xhttpc_description = Extensible HTTP Client for Erlang +pkg_xhttpc_homepage = https://github.com/seriyps/xhttpc +pkg_xhttpc_fetch = git +pkg_xhttpc_repo = https://github.com/seriyps/xhttpc +pkg_xhttpc_commit = master + +PACKAGES += xref_runner +pkg_xref_runner_name = xref_runner +pkg_xref_runner_description = Erlang Xref Runner (inspired in rebar xref) +pkg_xref_runner_homepage = https://github.com/inaka/xref_runner +pkg_xref_runner_fetch = git +pkg_xref_runner_repo = https://github.com/inaka/xref_runner +pkg_xref_runner_commit = master + +PACKAGES += yamerl +pkg_yamerl_name = yamerl +pkg_yamerl_description = YAML 1.2 parser in pure Erlang +pkg_yamerl_homepage = https://github.com/yakaz/yamerl +pkg_yamerl_fetch = git +pkg_yamerl_repo = https://github.com/yakaz/yamerl +pkg_yamerl_commit = master + +PACKAGES += yamler +pkg_yamler_name = yamler +pkg_yamler_description = libyaml-based yaml loader for Erlang +pkg_yamler_homepage = https://github.com/goertzenator/yamler +pkg_yamler_fetch = git +pkg_yamler_repo = https://github.com/goertzenator/yamler +pkg_yamler_commit = master + +PACKAGES += yaws +pkg_yaws_name = yaws +pkg_yaws_description = Yaws webserver +pkg_yaws_homepage = http://yaws.hyber.org +pkg_yaws_fetch = git +pkg_yaws_repo = https://github.com/klacke/yaws +pkg_yaws_commit = master + +PACKAGES += zab_engine +pkg_zab_engine_name = zab_engine +pkg_zab_engine_description = zab propotocol implement by erlang +pkg_zab_engine_homepage = https://github.com/xinmingyao/zab_engine +pkg_zab_engine_fetch = git +pkg_zab_engine_repo = https://github.com/xinmingyao/zab_engine +pkg_zab_engine_commit = master + +PACKAGES += zabbix_sender +pkg_zabbix_sender_name = zabbix_sender +pkg_zabbix_sender_description = Zabbix trapper for sending data to Zabbix in pure Erlang +pkg_zabbix_sender_homepage = https://github.com/stalkermn/zabbix_sender +pkg_zabbix_sender_fetch = git +pkg_zabbix_sender_repo = https://github.com/stalkermn/zabbix_sender.git +pkg_zabbix_sender_commit = master + +PACKAGES += zeta +pkg_zeta_name = zeta +pkg_zeta_description = HTTP access log parser in Erlang +pkg_zeta_homepage = https://github.com/s1n4/zeta +pkg_zeta_fetch = git +pkg_zeta_repo = https://github.com/s1n4/zeta +pkg_zeta_commit = master + +PACKAGES += zippers +pkg_zippers_name = zippers +pkg_zippers_description = A library for functional zipper data structures in Erlang. Read more on zippers +pkg_zippers_homepage = https://github.com/ferd/zippers +pkg_zippers_fetch = git +pkg_zippers_repo = https://github.com/ferd/zippers +pkg_zippers_commit = master + +PACKAGES += zlists +pkg_zlists_name = zlists +pkg_zlists_description = Erlang lazy lists library. +pkg_zlists_homepage = https://github.com/vjache/erlang-zlists +pkg_zlists_fetch = git +pkg_zlists_repo = https://github.com/vjache/erlang-zlists +pkg_zlists_commit = master + +PACKAGES += zraft_lib +pkg_zraft_lib_name = zraft_lib +pkg_zraft_lib_description = Erlang raft consensus protocol implementation +pkg_zraft_lib_homepage = https://github.com/dreyk/zraft_lib +pkg_zraft_lib_fetch = git +pkg_zraft_lib_repo = https://github.com/dreyk/zraft_lib +pkg_zraft_lib_commit = master + +PACKAGES += zucchini +pkg_zucchini_name = zucchini +pkg_zucchini_description = An Erlang INI parser +pkg_zucchini_homepage = https://github.com/devinus/zucchini +pkg_zucchini_fetch = git +pkg_zucchini_repo = https://github.com/devinus/zucchini +pkg_zucchini_commit = master + +# Copyright (c) 2015-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: search + +define pkg_print + $(verbose) printf "%s\n" \ + $(if $(call core_eq,$(1),$(pkg_$(1)_name)),,"Pkg name: $(1)") \ + "App name: $(pkg_$(1)_name)" \ + "Description: $(pkg_$(1)_description)" \ + "Home page: $(pkg_$(1)_homepage)" \ + "Fetch with: $(pkg_$(1)_fetch)" \ + "Repository: $(pkg_$(1)_repo)" \ + "Commit: $(pkg_$(1)_commit)" \ + "" + +endef + +search: +ifdef q + $(foreach p,$(PACKAGES), \ + $(if $(findstring $(call core_lc,$(q)),$(call core_lc,$(pkg_$(p)_name) $(pkg_$(p)_description))), \ + $(call pkg_print,$(p)))) +else + $(foreach p,$(PACKAGES),$(call pkg_print,$(p))) +endif + +# Copyright (c) 2013-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: distclean-deps clean-tmp-deps.log + +# Configuration. + +ifdef OTP_DEPS +$(warning The variable OTP_DEPS is deprecated in favor of LOCAL_DEPS.) +endif + +IGNORE_DEPS ?= +export IGNORE_DEPS + +APPS_DIR ?= $(CURDIR)/apps +export APPS_DIR + +DEPS_DIR ?= $(CURDIR)/deps +export DEPS_DIR + +REBAR_DEPS_DIR = $(DEPS_DIR) +export REBAR_DEPS_DIR + +dep_name = $(if $(dep_$(1)),$(1),$(if $(pkg_$(1)_name),$(pkg_$(1)_name),$(1))) +dep_repo = $(patsubst git://github.com/%,https://github.com/%, \ + $(if $(dep_$(1)),$(word 2,$(dep_$(1))),$(pkg_$(1)_repo))) +dep_commit = $(if $(dep_$(1)_commit),$(dep_$(1)_commit),$(if $(dep_$(1)),$(word 3,$(dep_$(1))),$(pkg_$(1)_commit))) + +LOCAL_DEPS_DIRS = $(foreach a,$(LOCAL_DEPS),$(if $(wildcard $(APPS_DIR)/$(a)),$(APPS_DIR)/$(a))) +ALL_APPS_DIRS = $(if $(wildcard $(APPS_DIR)/),$(filter-out $(APPS_DIR),$(shell find $(APPS_DIR) -maxdepth 1 -type d))) +ALL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(foreach dep,$(filter-out $(IGNORE_DEPS),$(BUILD_DEPS) $(DEPS)),$(call dep_name,$(dep)))) + +ifeq ($(filter $(APPS_DIR) $(DEPS_DIR),$(subst :, ,$(ERL_LIBS))),) +ifeq ($(ERL_LIBS),) + ERL_LIBS = $(APPS_DIR):$(DEPS_DIR) +else + ERL_LIBS := $(ERL_LIBS):$(APPS_DIR):$(DEPS_DIR) +endif +endif +export ERL_LIBS + +export NO_AUTOPATCH + +# Verbosity. + +dep_verbose_0 = @echo " DEP " $(1); +dep_verbose_2 = set -x; +dep_verbose = $(dep_verbose_$(V)) + +# Core targets. + +apps:: $(ALL_APPS_DIRS) clean-tmp-deps.log +ifeq ($(IS_APP)$(IS_DEP),) + $(verbose) rm -f $(ERLANG_MK_TMP)/apps.log +endif + $(verbose) mkdir -p $(ERLANG_MK_TMP) +# Create ebin directory for all apps to make sure Erlang recognizes them +# as proper OTP applications when using -include_lib. This is a temporary +# fix, a proper fix would be to compile apps/* in the right order. +ifndef IS_APP + $(verbose) for dep in $(ALL_APPS_DIRS) ; do \ + mkdir -p $$dep/ebin || exit $$?; \ + done +endif +# at the toplevel: if LOCAL_DEPS is defined with at least one local app, only +# compile that list of apps. otherwise, compile everything. +# within an app: compile all LOCAL_DEPS that are (uncompiled) local apps + $(verbose) for dep in $(if $(LOCAL_DEPS_DIRS)$(IS_APP),$(LOCAL_DEPS_DIRS),$(ALL_APPS_DIRS)) ; do \ + if grep -qs ^$$dep$$ $(ERLANG_MK_TMP)/apps.log; then \ + :; \ + else \ + echo $$dep >> $(ERLANG_MK_TMP)/apps.log; \ + $(MAKE) -C $$dep IS_APP=1 || exit $$?; \ + fi \ + done + +clean-tmp-deps.log: +ifeq ($(IS_APP)$(IS_DEP),) + $(verbose) rm -f $(ERLANG_MK_TMP)/deps.log +endif + +ifneq ($(SKIP_DEPS),) +deps:: +else +deps:: $(ALL_DEPS_DIRS) apps clean-tmp-deps.log + $(verbose) mkdir -p $(ERLANG_MK_TMP) + $(verbose) for dep in $(ALL_DEPS_DIRS) ; do \ + if grep -qs ^$$dep$$ $(ERLANG_MK_TMP)/deps.log; then \ + :; \ + else \ + echo $$dep >> $(ERLANG_MK_TMP)/deps.log; \ + if [ -f $$dep/GNUmakefile ] || [ -f $$dep/makefile ] || [ -f $$dep/Makefile ]; then \ + $(MAKE) -C $$dep IS_DEP=1 || exit $$?; \ + else \ + echo "Error: No Makefile to build dependency $$dep."; \ + exit 2; \ + fi \ + fi \ + done +endif + +# Deps related targets. + +# @todo rename GNUmakefile and makefile into Makefile first, if they exist +# While Makefile file could be GNUmakefile or makefile, +# in practice only Makefile is needed so far. +define dep_autopatch + if [ -f $(DEPS_DIR)/$(1)/erlang.mk ]; then \ + rm -rf $(DEPS_DIR)/$1/ebin/; \ + $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \ + $(call dep_autopatch_erlang_mk,$(1)); \ + elif [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \ + if [ -f $(DEPS_DIR)/$1/rebar.lock ]; then \ + $(call dep_autopatch2,$1); \ + elif [ 0 != `grep -c "include ../\w*\.mk" $(DEPS_DIR)/$(1)/Makefile` ]; then \ + $(call dep_autopatch2,$(1)); \ + elif [ 0 != `grep -ci "^[^#].*rebar" $(DEPS_DIR)/$(1)/Makefile` ]; then \ + $(call dep_autopatch2,$(1)); \ + elif [ -n "`find $(DEPS_DIR)/$(1)/ -type f -name \*.mk -not -name erlang.mk -exec grep -i "^[^#].*rebar" '{}' \;`" ]; then \ + $(call dep_autopatch2,$(1)); \ + fi \ + else \ + if [ ! -d $(DEPS_DIR)/$(1)/src/ ]; then \ + $(call dep_autopatch_noop,$(1)); \ + else \ + $(call dep_autopatch2,$(1)); \ + fi \ + fi +endef + +define dep_autopatch2 + mv -n $(DEPS_DIR)/$1/ebin/$1.app $(DEPS_DIR)/$1/src/$1.app.src; \ + rm -f $(DEPS_DIR)/$1/ebin/$1.app; \ + if [ -f $(DEPS_DIR)/$1/src/$1.app.src.script ]; then \ + $(call erlang,$(call dep_autopatch_appsrc_script.erl,$(1))); \ + fi; \ + $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \ + if [ -f $(DEPS_DIR)/$(1)/rebar -o -f $(DEPS_DIR)/$(1)/rebar.config -o -f $(DEPS_DIR)/$(1)/rebar.config.script -o -f $(DEPS_DIR)/$1/rebar.lock ]; then \ + $(call dep_autopatch_fetch_rebar); \ + $(call dep_autopatch_rebar,$(1)); \ + else \ + $(call dep_autopatch_gen,$(1)); \ + fi +endef + +define dep_autopatch_noop + printf "noop:\n" > $(DEPS_DIR)/$(1)/Makefile +endef + +# Overwrite erlang.mk with the current file by default. +ifeq ($(NO_AUTOPATCH_ERLANG_MK),) +define dep_autopatch_erlang_mk + echo "include $(call core_relpath,$(dir $(ERLANG_MK_FILENAME)),$(DEPS_DIR)/app)/erlang.mk" \ + > $(DEPS_DIR)/$1/erlang.mk +endef +else +define dep_autopatch_erlang_mk + : +endef +endif + +define dep_autopatch_gen + printf "%s\n" \ + "ERLC_OPTS = +debug_info" \ + "include ../../erlang.mk" > $(DEPS_DIR)/$(1)/Makefile +endef + +define dep_autopatch_fetch_rebar + mkdir -p $(ERLANG_MK_TMP); \ + if [ ! -d $(ERLANG_MK_TMP)/rebar ]; then \ + git clone -q -n -- https://github.com/rebar/rebar $(ERLANG_MK_TMP)/rebar; \ + cd $(ERLANG_MK_TMP)/rebar; \ + git checkout -q 576e12171ab8d69b048b827b92aa65d067deea01; \ + $(MAKE); \ + cd -; \ + fi +endef + +define dep_autopatch_rebar + if [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \ + mv $(DEPS_DIR)/$(1)/Makefile $(DEPS_DIR)/$(1)/Makefile.orig.mk; \ + fi; \ + $(call erlang,$(call dep_autopatch_rebar.erl,$(1))); \ + rm -f $(DEPS_DIR)/$(1)/ebin/$(1).app +endef + +define dep_autopatch_rebar.erl + application:load(rebar), + application:set_env(rebar, log_level, debug), + rmemo:start(), + Conf1 = case file:consult("$(call core_native_path,$(DEPS_DIR)/$1/rebar.config)") of + {ok, Conf0} -> Conf0; + _ -> [] + end, + {Conf, OsEnv} = fun() -> + case filelib:is_file("$(call core_native_path,$(DEPS_DIR)/$1/rebar.config.script)") of + false -> {Conf1, []}; + true -> + Bindings0 = erl_eval:new_bindings(), + Bindings1 = erl_eval:add_binding('CONFIG', Conf1, Bindings0), + Bindings = erl_eval:add_binding('SCRIPT', "$(call core_native_path,$(DEPS_DIR)/$1/rebar.config.script)", Bindings1), + Before = os:getenv(), + {ok, Conf2} = file:script("$(call core_native_path,$(DEPS_DIR)/$1/rebar.config.script)", Bindings), + {Conf2, lists:foldl(fun(E, Acc) -> lists:delete(E, Acc) end, os:getenv(), Before)} + end + end(), + Write = fun (Text) -> + file:write_file("$(call core_native_path,$(DEPS_DIR)/$1/Makefile)", Text, [append]) + end, + Escape = fun (Text) -> + re:replace(Text, "\\\\$$", "\$$$$", [global, {return, list}]) + end, + Write("IGNORE_DEPS += edown eper eunit_formatters meck node_package " + "rebar_lock_deps_plugin rebar_vsn_plugin reltool_util\n"), + Write("C_SRC_DIR = /path/do/not/exist\n"), + Write("C_SRC_TYPE = rebar\n"), + Write("DRV_CFLAGS = -fPIC\nexport DRV_CFLAGS\n"), + Write(["ERLANG_ARCH = ", rebar_utils:wordsize(), "\nexport ERLANG_ARCH\n"]), + fun() -> + Write("ERLC_OPTS = +debug_info\nexport ERLC_OPTS\n"), + case lists:keyfind(erl_opts, 1, Conf) of + false -> ok; + {_, ErlOpts} -> + lists:foreach(fun + ({d, D}) -> + Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n"); + ({i, I}) -> + Write(["ERLC_OPTS += -I ", I, "\n"]); + ({platform_define, Regex, D}) -> + case rebar_utils:is_arch(Regex) of + true -> Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n"); + false -> ok + end; + ({parse_transform, PT}) -> + Write("ERLC_OPTS += +'{parse_transform, " ++ atom_to_list(PT) ++ "}'\n"); + (_) -> ok + end, ErlOpts) + end, + Write("\n") + end(), + fun() -> + File = case lists:keyfind(deps, 1, Conf) of + false -> []; + {_, Deps} -> + [begin case case Dep of + {N, S} when is_atom(N), is_list(S) -> {N, {hex, S}}; + {N, S} when is_tuple(S) -> {N, S}; + {N, _, S} -> {N, S}; + {N, _, S, _} -> {N, S}; + _ -> false + end of + false -> ok; + {Name, Source} -> + {Method, Repo, Commit} = case Source of + {hex, V} -> {hex, V, undefined}; + {git, R} -> {git, R, master}; + {M, R, {branch, C}} -> {M, R, C}; + {M, R, {ref, C}} -> {M, R, C}; + {M, R, {tag, C}} -> {M, R, C}; + {M, R, C} -> {M, R, C} + end, + Write(io_lib:format("DEPS += ~s\ndep_~s = ~s ~s ~s~n", [Name, Name, Method, Repo, Commit])) + end end || Dep <- Deps] + end + end(), + fun() -> + case lists:keyfind(erl_first_files, 1, Conf) of + false -> ok; + {_, Files} -> + Names = [[" ", case lists:reverse(F) of + "lre." ++ Elif -> lists:reverse(Elif); + Elif -> lists:reverse(Elif) + end] || "src/" ++ F <- Files], + Write(io_lib:format("COMPILE_FIRST +=~s\n", [Names])) + end + end(), + Write("\n\nrebar_dep: preprocess pre-deps deps pre-app app\n"), + Write("\npreprocess::\n"), + Write("\npre-deps::\n"), + Write("\npre-app::\n"), + PatchHook = fun(Cmd) -> + case Cmd of + "make -C" ++ Cmd1 -> "$$\(MAKE) -C" ++ Escape(Cmd1); + "gmake -C" ++ Cmd1 -> "$$\(MAKE) -C" ++ Escape(Cmd1); + "make " ++ Cmd1 -> "$$\(MAKE) -f Makefile.orig.mk " ++ Escape(Cmd1); + "gmake " ++ Cmd1 -> "$$\(MAKE) -f Makefile.orig.mk " ++ Escape(Cmd1); + _ -> Escape(Cmd) + end + end, + fun() -> + case lists:keyfind(pre_hooks, 1, Conf) of + false -> ok; + {_, Hooks} -> + [case H of + {'get-deps', Cmd} -> + Write("\npre-deps::\n\t" ++ PatchHook(Cmd) ++ "\n"); + {compile, Cmd} -> + Write("\npre-app::\n\tCC=$$\(CC) " ++ PatchHook(Cmd) ++ "\n"); + {Regex, compile, Cmd} -> + case rebar_utils:is_arch(Regex) of + true -> Write("\npre-app::\n\tCC=$$\(CC) " ++ PatchHook(Cmd) ++ "\n"); + false -> ok + end; + _ -> ok + end || H <- Hooks] + end + end(), + ShellToMk = fun(V) -> + re:replace(re:replace(V, "(\\\\$$)(\\\\w*)", "\\\\1(\\\\2)", [global]), + "-Werror\\\\b", "", [{return, list}, global]) + end, + PortSpecs = fun() -> + case lists:keyfind(port_specs, 1, Conf) of + false -> + case filelib:is_dir("$(call core_native_path,$(DEPS_DIR)/$1/c_src)") of + false -> []; + true -> + [{"priv/" ++ proplists:get_value(so_name, Conf, "$(1)_drv.so"), + proplists:get_value(port_sources, Conf, ["c_src/*.c"]), []}] + end; + {_, Specs} -> + lists:flatten([case S of + {Output, Input} -> {ShellToMk(Output), Input, []}; + {Regex, Output, Input} -> + case rebar_utils:is_arch(Regex) of + true -> {ShellToMk(Output), Input, []}; + false -> [] + end; + {Regex, Output, Input, [{env, Env}]} -> + case rebar_utils:is_arch(Regex) of + true -> {ShellToMk(Output), Input, Env}; + false -> [] + end + end || S <- Specs]) + end + end(), + PortSpecWrite = fun (Text) -> + file:write_file("$(call core_native_path,$(DEPS_DIR)/$1/c_src/Makefile.erlang.mk)", Text, [append]) + end, + case PortSpecs of + [] -> ok; + _ -> + Write("\npre-app::\n\t$$\(MAKE) -f c_src/Makefile.erlang.mk\n"), + PortSpecWrite(io_lib:format("ERL_CFLAGS ?= -finline-functions -Wall -fPIC -I \\"~s/erts-~s/include\\" -I \\"~s\\"\n", + [code:root_dir(), erlang:system_info(version), code:lib_dir(erl_interface, include)])), + PortSpecWrite(io_lib:format("ERL_LDFLAGS ?= -L \\"~s\\" -lerl_interface -lei\n", + [code:lib_dir(erl_interface, lib)])), + [PortSpecWrite(["\n", E, "\n"]) || E <- OsEnv], + FilterEnv = fun(Env) -> + lists:flatten([case E of + {_, _} -> E; + {Regex, K, V} -> + case rebar_utils:is_arch(Regex) of + true -> {K, V}; + false -> [] + end + end || E <- Env]) + end, + MergeEnv = fun(Env) -> + lists:foldl(fun ({K, V}, Acc) -> + case lists:keyfind(K, 1, Acc) of + false -> [{K, rebar_utils:expand_env_variable(V, K, "")}|Acc]; + {_, V0} -> [{K, rebar_utils:expand_env_variable(V, K, V0)}|Acc] + end + end, [], Env) + end, + PortEnv = case lists:keyfind(port_env, 1, Conf) of + false -> []; + {_, PortEnv0} -> FilterEnv(PortEnv0) + end, + PortSpec = fun ({Output, Input0, Env}) -> + filelib:ensure_dir("$(call core_native_path,$(DEPS_DIR)/$1/)" ++ Output), + Input = [[" ", I] || I <- Input0], + PortSpecWrite([ + [["\n", K, " = ", ShellToMk(V)] || {K, V} <- lists:reverse(MergeEnv(PortEnv))], + case $(PLATFORM) of + darwin -> "\n\nLDFLAGS += -flat_namespace -undefined suppress"; + _ -> "" + end, + "\n\nall:: ", Output, "\n\n", + "%.o: %.c\n\t$$\(CC) -c -o $$\@ $$\< $$\(CFLAGS) $$\(ERL_CFLAGS) $$\(DRV_CFLAGS) $$\(EXE_CFLAGS)\n\n", + "%.o: %.C\n\t$$\(CXX) -c -o $$\@ $$\< $$\(CXXFLAGS) $$\(ERL_CFLAGS) $$\(DRV_CFLAGS) $$\(EXE_CFLAGS)\n\n", + "%.o: %.cc\n\t$$\(CXX) -c -o $$\@ $$\< $$\(CXXFLAGS) $$\(ERL_CFLAGS) $$\(DRV_CFLAGS) $$\(EXE_CFLAGS)\n\n", + "%.o: %.cpp\n\t$$\(CXX) -c -o $$\@ $$\< $$\(CXXFLAGS) $$\(ERL_CFLAGS) $$\(DRV_CFLAGS) $$\(EXE_CFLAGS)\n\n", + [[Output, ": ", K, " += ", ShellToMk(V), "\n"] || {K, V} <- lists:reverse(MergeEnv(FilterEnv(Env)))], + Output, ": $$\(foreach ext,.c .C .cc .cpp,", + "$$\(patsubst %$$\(ext),%.o,$$\(filter %$$\(ext),$$\(wildcard", Input, "))))\n", + "\t$$\(CC) -o $$\@ $$\? $$\(LDFLAGS) $$\(ERL_LDFLAGS) $$\(DRV_LDFLAGS) $$\(EXE_LDFLAGS)", + case {filename:extension(Output), $(PLATFORM)} of + {[], _} -> "\n"; + {_, darwin} -> "\n"; + _ -> " -shared\n" + end]) + end, + [PortSpec(S) || S <- PortSpecs] + end, + Write("\ninclude $(call core_relpath,$(dir $(ERLANG_MK_FILENAME)),$(DEPS_DIR)/app)/erlang.mk"), + RunPlugin = fun(Plugin, Step) -> + case erlang:function_exported(Plugin, Step, 2) of + false -> ok; + true -> + c:cd("$(call core_native_path,$(DEPS_DIR)/$1/)"), + Ret = Plugin:Step({config, "", Conf, dict:new(), dict:new(), dict:new(), + dict:store(base_dir, "", dict:new())}, undefined), + io:format("rebar plugin ~p step ~p ret ~p~n", [Plugin, Step, Ret]) + end + end, + fun() -> + case lists:keyfind(plugins, 1, Conf) of + false -> ok; + {_, Plugins} -> + [begin + case lists:keyfind(deps, 1, Conf) of + false -> ok; + {_, Deps} -> + case lists:keyfind(P, 1, Deps) of + false -> ok; + _ -> + Path = "$(call core_native_path,$(DEPS_DIR)/)" ++ atom_to_list(P), + io:format("~s", [os:cmd("$(MAKE) -C $(call core_native_path,$(DEPS_DIR)/$1) " ++ Path)]), + io:format("~s", [os:cmd("$(MAKE) -C " ++ Path ++ " IS_DEP=1")]), + code:add_patha(Path ++ "/ebin") + end + end + end || P <- Plugins], + [case code:load_file(P) of + {module, P} -> ok; + _ -> + case lists:keyfind(plugin_dir, 1, Conf) of + false -> ok; + {_, PluginsDir} -> + ErlFile = "$(call core_native_path,$(DEPS_DIR)/$1/)" ++ PluginsDir ++ "/" ++ atom_to_list(P) ++ ".erl", + {ok, P, Bin} = compile:file(ErlFile, [binary]), + {module, P} = code:load_binary(P, ErlFile, Bin) + end + end || P <- Plugins], + [RunPlugin(P, preprocess) || P <- Plugins], + [RunPlugin(P, pre_compile) || P <- Plugins], + [RunPlugin(P, compile) || P <- Plugins] + end + end(), + halt() +endef + +define dep_autopatch_appsrc_script.erl + AppSrc = "$(call core_native_path,$(DEPS_DIR)/$1/src/$1.app.src)", + AppSrcScript = AppSrc ++ ".script", + Bindings = erl_eval:new_bindings(), + {ok, Conf} = file:script(AppSrcScript, Bindings), + ok = file:write_file(AppSrc, io_lib:format("~p.~n", [Conf])), + halt() +endef + +define dep_autopatch_appsrc.erl + AppSrcOut = "$(call core_native_path,$(DEPS_DIR)/$1/src/$1.app.src)", + AppSrcIn = case filelib:is_regular(AppSrcOut) of false -> "$(call core_native_path,$(DEPS_DIR)/$1/ebin/$1.app)"; true -> AppSrcOut end, + case filelib:is_regular(AppSrcIn) of + false -> ok; + true -> + {ok, [{application, $(1), L0}]} = file:consult(AppSrcIn), + L1 = lists:keystore(modules, 1, L0, {modules, []}), + L2 = case lists:keyfind(vsn, 1, L1) of {_, git} -> lists:keyreplace(vsn, 1, L1, {vsn, "git"}); _ -> L1 end, + L3 = case lists:keyfind(registered, 1, L2) of false -> [{registered, []}|L2]; _ -> L2 end, + ok = file:write_file(AppSrcOut, io_lib:format("~p.~n", [{application, $(1), L3}])), + case AppSrcOut of AppSrcIn -> ok; _ -> ok = file:delete(AppSrcIn) end + end, + halt() +endef + +define dep_fetch_git + git clone -q -n -- $(call dep_repo,$(1)) $(DEPS_DIR)/$(call dep_name,$(1)); \ + cd $(DEPS_DIR)/$(call dep_name,$(1)) && git checkout -q $(call dep_commit,$(1)); +endef + +define dep_fetch_git-submodule + git submodule update --init -- $(DEPS_DIR)/$1; +endef + +define dep_fetch_hg + hg clone -q -U $(call dep_repo,$(1)) $(DEPS_DIR)/$(call dep_name,$(1)); \ + cd $(DEPS_DIR)/$(call dep_name,$(1)) && hg update -q $(call dep_commit,$(1)); +endef + +define dep_fetch_svn + svn checkout -q $(call dep_repo,$(1)) $(DEPS_DIR)/$(call dep_name,$(1)); +endef + +define dep_fetch_cp + cp -R $(call dep_repo,$(1)) $(DEPS_DIR)/$(call dep_name,$(1)); +endef + +# Hex only has a package version. No need to look in the Erlang.mk packages. +define dep_fetch_hex + mkdir -p $(ERLANG_MK_TMP)/hex $(DEPS_DIR)/$1; \ + $(call core_http_get,$(ERLANG_MK_TMP)/hex/$1.tar,\ + https://s3.amazonaws.com/s3.hex.pm/tarballs/$1-$(strip $(word 2,$(dep_$1))).tar); \ + tar -xOf $(ERLANG_MK_TMP)/hex/$1.tar contents.tar.gz | tar -C $(DEPS_DIR)/$1 -xzf -; +endef + +define dep_fetch_fail + echo "Error: Unknown or invalid dependency: $(1)." >&2; \ + exit 78; +endef + +# Kept for compatibility purposes with older Erlang.mk configuration. +define dep_fetch_legacy + $(warning WARNING: '$(1)' dependency configuration uses deprecated format.) \ + git clone -q -n -- $(word 1,$(dep_$(1))) $(DEPS_DIR)/$(1); \ + cd $(DEPS_DIR)/$(1) && git checkout -q $(if $(word 2,$(dep_$(1))),$(word 2,$(dep_$(1))),master); +endef + +define dep_fetch + $(if $(dep_$(1)), \ + $(if $(dep_fetch_$(word 1,$(dep_$(1)))), \ + $(word 1,$(dep_$(1))), \ + $(if $(IS_DEP),legacy,fail)), \ + $(if $(filter $(1),$(PACKAGES)), \ + $(pkg_$(1)_fetch), \ + fail)) +endef + +define dep_target +$(DEPS_DIR)/$(call dep_name,$1): + $(eval DEP_NAME := $(call dep_name,$1)) + $(eval DEP_STR := $(if $(filter-out $1,$(DEP_NAME)),$1,"$1 ($(DEP_NAME))")) + $(verbose) if test -d $(APPS_DIR)/$(DEP_NAME); then \ + echo "Error: Dependency" $(DEP_STR) "conflicts with application found in $(APPS_DIR)/$(DEP_NAME)."; \ + exit 17; \ + fi + $(verbose) mkdir -p $(DEPS_DIR) + $(dep_verbose) $(call dep_fetch_$(strip $(call dep_fetch,$(1))),$(1)) + $(verbose) if [ -f $(DEPS_DIR)/$(1)/configure.ac -o -f $(DEPS_DIR)/$(1)/configure.in ] \ + && [ ! -f $(DEPS_DIR)/$(1)/configure ]; then \ + echo " AUTO " $(1); \ + cd $(DEPS_DIR)/$(1) && autoreconf -Wall -vif -I m4; \ + fi + - $(verbose) if [ -f $(DEPS_DIR)/$(DEP_NAME)/configure ]; then \ + echo " CONF " $(DEP_STR); \ + cd $(DEPS_DIR)/$(DEP_NAME) && ./configure; \ + fi +ifeq ($(filter $(1),$(NO_AUTOPATCH)),) + $(verbose) if [ "$(1)" = "amqp_client" -a "$(RABBITMQ_CLIENT_PATCH)" ]; then \ + if [ ! -d $(DEPS_DIR)/rabbitmq-codegen ]; then \ + echo " PATCH Downloading rabbitmq-codegen"; \ + git clone https://github.com/rabbitmq/rabbitmq-codegen.git $(DEPS_DIR)/rabbitmq-codegen; \ + fi; \ + if [ ! -d $(DEPS_DIR)/rabbitmq-server ]; then \ + echo " PATCH Downloading rabbitmq-server"; \ + git clone https://github.com/rabbitmq/rabbitmq-server.git $(DEPS_DIR)/rabbitmq-server; \ + fi; \ + ln -s $(DEPS_DIR)/amqp_client/deps/rabbit_common-0.0.0 $(DEPS_DIR)/rabbit_common; \ + elif [ "$(1)" = "rabbit" -a "$(RABBITMQ_SERVER_PATCH)" ]; then \ + if [ ! -d $(DEPS_DIR)/rabbitmq-codegen ]; then \ + echo " PATCH Downloading rabbitmq-codegen"; \ + git clone https://github.com/rabbitmq/rabbitmq-codegen.git $(DEPS_DIR)/rabbitmq-codegen; \ + fi \ + else \ + $$(call dep_autopatch,$(DEP_NAME)) \ + fi +endif +endef + +$(foreach dep,$(BUILD_DEPS) $(DEPS),$(eval $(call dep_target,$(dep)))) + +ifndef IS_APP +clean:: clean-apps + +clean-apps: + $(verbose) for dep in $(ALL_APPS_DIRS) ; do \ + $(MAKE) -C $$dep clean IS_APP=1 || exit $$?; \ + done + +distclean:: distclean-apps + +distclean-apps: + $(verbose) for dep in $(ALL_APPS_DIRS) ; do \ + $(MAKE) -C $$dep distclean IS_APP=1 || exit $$?; \ + done +endif + +ifndef SKIP_DEPS +distclean:: distclean-deps + +distclean-deps: + $(gen_verbose) rm -rf $(DEPS_DIR) +endif + +# Forward-declare variables used in core/deps-tools.mk. This is required +# in case plugins use them. + +ERLANG_MK_RECURSIVE_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-deps-list.log +ERLANG_MK_RECURSIVE_DOC_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-doc-deps-list.log +ERLANG_MK_RECURSIVE_REL_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-rel-deps-list.log +ERLANG_MK_RECURSIVE_TEST_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-test-deps-list.log +ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-shell-deps-list.log + +# Copyright (c) 2015-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +# Verbosity. + +proto_verbose_0 = @echo " PROTO " $(filter %.proto,$(?F)); +proto_verbose = $(proto_verbose_$(V)) + +# Core targets. + +define compile_proto + $(verbose) mkdir -p ebin/ include/ + $(proto_verbose) $(call erlang,$(call compile_proto.erl,$(1))) + $(proto_verbose) erlc +debug_info -o ebin/ ebin/*.erl + $(verbose) rm ebin/*.erl +endef + +define compile_proto.erl + [begin + Dir = filename:dirname(filename:dirname(F)), + protobuffs_compile:generate_source(F, + [{output_include_dir, Dir ++ "/include"}, + {output_src_dir, Dir ++ "/ebin"}]) + end || F <- string:tokens("$(1)", " ")], + halt(). +endef + +ifneq ($(wildcard src/),) +ebin/$(PROJECT).app:: $(sort $(call core_find,src/,*.proto)) + $(if $(strip $?),$(call compile_proto,$?)) +endif + +# Copyright (c) 2013-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: clean-app + +# Configuration. + +ERLC_OPTS ?= -Werror +debug_info +warn_export_vars +warn_shadow_vars \ + +warn_obsolete_guard # +bin_opt_info +warn_export_all +warn_missing_spec +COMPILE_FIRST ?= +COMPILE_FIRST_PATHS = $(addprefix src/,$(addsuffix .erl,$(COMPILE_FIRST))) +ERLC_EXCLUDE ?= +ERLC_EXCLUDE_PATHS = $(addprefix src/,$(addsuffix .erl,$(ERLC_EXCLUDE))) + +ERLC_ASN1_OPTS ?= + +ERLC_MIB_OPTS ?= +COMPILE_MIB_FIRST ?= +COMPILE_MIB_FIRST_PATHS = $(addprefix mibs/,$(addsuffix .mib,$(COMPILE_MIB_FIRST))) + +# Verbosity. + +app_verbose_0 = @echo " APP " $(PROJECT); +app_verbose_2 = set -x; +app_verbose = $(app_verbose_$(V)) + +appsrc_verbose_0 = @echo " APP " $(PROJECT).app.src; +appsrc_verbose_2 = set -x; +appsrc_verbose = $(appsrc_verbose_$(V)) + +makedep_verbose_0 = @echo " DEPEND" $(PROJECT).d; +makedep_verbose_2 = set -x; +makedep_verbose = $(makedep_verbose_$(V)) + +erlc_verbose_0 = @echo " ERLC " $(filter-out $(patsubst %,%.erl,$(ERLC_EXCLUDE)),\ + $(filter %.erl %.core,$(?F))); +erlc_verbose_2 = set -x; +erlc_verbose = $(erlc_verbose_$(V)) + +xyrl_verbose_0 = @echo " XYRL " $(filter %.xrl %.yrl,$(?F)); +xyrl_verbose_2 = set -x; +xyrl_verbose = $(xyrl_verbose_$(V)) + +asn1_verbose_0 = @echo " ASN1 " $(filter %.asn1,$(?F)); +asn1_verbose_2 = set -x; +asn1_verbose = $(asn1_verbose_$(V)) + +mib_verbose_0 = @echo " MIB " $(filter %.bin %.mib,$(?F)); +mib_verbose_2 = set -x; +mib_verbose = $(mib_verbose_$(V)) + +ifneq ($(wildcard src/),) + +# Targets. + +ifeq ($(wildcard ebin/test),) +app:: deps $(PROJECT).d + $(verbose) $(MAKE) --no-print-directory app-build +else +app:: clean deps $(PROJECT).d + $(verbose) $(MAKE) --no-print-directory app-build +endif + +ifeq ($(wildcard src/$(PROJECT_MOD).erl),) +define app_file +{application, '$(PROJECT)', [ + {description, "$(PROJECT_DESCRIPTION)"}, + {vsn, "$(PROJECT_VERSION)"},$(if $(IS_DEP), + {id$(comma)$(space)"$(1)"}$(comma)) + {modules, [$(call comma_list,$(2))]}, + {registered, []}, + {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(DEPS))]}, + {env, $(subst \,\\,$(PROJECT_ENV))}$(if $(findstring {,$(PROJECT_APP_EXTRA_KEYS)),$(comma)$(newline)$(tab)$(subst \,\\,$(PROJECT_APP_EXTRA_KEYS)),) +]}. +endef +else +define app_file +{application, '$(PROJECT)', [ + {description, "$(PROJECT_DESCRIPTION)"}, + {vsn, "$(PROJECT_VERSION)"},$(if $(IS_DEP), + {id$(comma)$(space)"$(1)"}$(comma)) + {modules, [$(call comma_list,$(2))]}, + {registered, [$(call comma_list,$(PROJECT)_sup $(PROJECT_REGISTERED))]}, + {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(DEPS))]}, + {mod, {$(PROJECT_MOD), []}}, + {env, $(subst \,\\,$(PROJECT_ENV))}$(if $(findstring {,$(PROJECT_APP_EXTRA_KEYS)),$(comma)$(newline)$(tab)$(subst \,\\,$(PROJECT_APP_EXTRA_KEYS)),) +]}. +endef +endif + +app-build: ebin/$(PROJECT).app + $(verbose) : + +# Source files. + +ALL_SRC_FILES := $(sort $(call core_find,src/,*)) + +ERL_FILES := $(filter %.erl,$(ALL_SRC_FILES)) +CORE_FILES := $(filter %.core,$(ALL_SRC_FILES)) + +# ASN.1 files. + +ifneq ($(wildcard asn1/),) +ASN1_FILES = $(sort $(call core_find,asn1/,*.asn1)) +ERL_FILES += $(addprefix src/,$(patsubst %.asn1,%.erl,$(notdir $(ASN1_FILES)))) + +define compile_asn1 + $(verbose) mkdir -p include/ + $(asn1_verbose) erlc -v -I include/ -o asn1/ +noobj $(ERLC_ASN1_OPTS) $(1) + $(verbose) mv asn1/*.erl src/ + $(verbose) mv asn1/*.hrl include/ + $(verbose) mv asn1/*.asn1db include/ +endef + +$(PROJECT).d:: $(ASN1_FILES) + $(if $(strip $?),$(call compile_asn1,$?)) +endif + +# SNMP MIB files. + +ifneq ($(wildcard mibs/),) +MIB_FILES = $(sort $(call core_find,mibs/,*.mib)) + +$(PROJECT).d:: $(COMPILE_MIB_FIRST_PATHS) $(MIB_FILES) + $(verbose) mkdir -p include/ priv/mibs/ + $(mib_verbose) erlc -v $(ERLC_MIB_OPTS) -o priv/mibs/ -I priv/mibs/ $? + $(mib_verbose) erlc -o include/ -- $(addprefix priv/mibs/,$(patsubst %.mib,%.bin,$(notdir $?))) +endif + +# Leex and Yecc files. + +XRL_FILES := $(filter %.xrl,$(ALL_SRC_FILES)) +XRL_ERL_FILES = $(addprefix src/,$(patsubst %.xrl,%.erl,$(notdir $(XRL_FILES)))) +ERL_FILES += $(XRL_ERL_FILES) + +YRL_FILES := $(filter %.yrl,$(ALL_SRC_FILES)) +YRL_ERL_FILES = $(addprefix src/,$(patsubst %.yrl,%.erl,$(notdir $(YRL_FILES)))) +ERL_FILES += $(YRL_ERL_FILES) + +$(PROJECT).d:: $(XRL_FILES) $(YRL_FILES) + $(if $(strip $?),$(xyrl_verbose) erlc -v -o src/ $(YRL_ERLC_OPTS) $?) + +# Erlang and Core Erlang files. + +define makedep.erl + E = ets:new(makedep, [bag]), + G = digraph:new([acyclic]), + ErlFiles = lists:usort(string:tokens("$(ERL_FILES)", " ")), + 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} -> + F(F, Fd, Mod), + {_, ModFile} = lists:keyfind(Mod, 1, Modules), + ets:insert(E, {ModFile, DepFile}) + 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 filelib:is_file("include/" ++ Hrl) of + true -> AddHd(F, Mod, "include/" ++ Hrl); + false -> + case filelib:is_file("src/" ++ Hrl) of + true -> AddHd(F, Mod, "src/" ++ Hrl); + false -> false + end + end; + (F, Mod, include_lib, "$1/include/" ++ Hrl) -> AddHd(F, Mod, "include/" ++ Hrl); + (F, Mod, include_lib, Hrl) -> AddHd(F, Mod, "include/" ++ Hrl); + (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) -> + case io:parse_erl_form(Fd, undefined) of + {ok, {attribute, _, Key, Value}, _} -> + Attr(F, Mod, Key, Value), + F(F, Fd, Mod); + {eof, _} -> + file:close(Fd); + _ -> + F(F, Fd, Mod) + end + end, + [begin + Mod = list_to_atom(filename:basename(F, ".erl")), + {ok, Fd} = file:open(F, [read]), + MakeDepend(MakeDepend, Fd, Mod) + 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("$(1)", [ + [[F, "::", [[" ", D] || D <- Deps], "; @touch \$$@\n"] || {F, Deps} <- Depend], + "\nCOMPILE_FIRST +=", [[" ", TargetPath(CF)] || CF <- CompileFirst], "\n" + ]), + halt() +endef + +ifeq ($(if $(NO_MAKEDEP),$(wildcard $(PROJECT).d),),) +$(PROJECT).d:: $(ERL_FILES) $(call core_find,include/,*.hrl) $(MAKEFILE_LIST) + $(makedep_verbose) $(call erlang,$(call makedep.erl,$@)) +endif + +ifneq ($(words $(ERL_FILES) $(CORE_FILES) $(ASN1_FILES) $(MIB_FILES) $(XRL_FILES) $(YRL_FILES)),0) +# Rebuild everything when the Makefile changes. +$(ERLANG_MK_TMP)/last-makefile-change: $(MAKEFILE_LIST) + $(verbose) mkdir -p $(ERLANG_MK_TMP) + $(verbose) if test -f $@; then \ + touch $(ERL_FILES) $(CORE_FILES) $(ASN1_FILES) $(MIB_FILES) $(XRL_FILES) $(YRL_FILES); \ + touch -c $(PROJECT).d; \ + fi + $(verbose) touch $@ + +$(ERL_FILES) $(CORE_FILES) $(ASN1_FILES) $(MIB_FILES) $(XRL_FILES) $(YRL_FILES):: $(ERLANG_MK_TMP)/last-makefile-change +ebin/$(PROJECT).app:: $(ERLANG_MK_TMP)/last-makefile-change +endif + +include $(wildcard $(PROJECT).d) + +ebin/$(PROJECT).app:: ebin/ + +ebin/: + $(verbose) mkdir -p ebin/ + +define compile_erl + $(erlc_verbose) erlc -v $(if $(IS_DEP),$(filter-out -Werror,$(ERLC_OPTS)),$(ERLC_OPTS)) -o ebin/ \ + -pa ebin/ -I include/ $(filter-out $(ERLC_EXCLUDE_PATHS),$(COMPILE_FIRST_PATHS) $(1)) +endef + +ebin/$(PROJECT).app:: $(ERL_FILES) $(CORE_FILES) $(wildcard src/$(PROJECT).app.src) + $(eval FILES_TO_COMPILE := $(filter-out src/$(PROJECT).app.src,$?)) + $(if $(strip $(FILES_TO_COMPILE)),$(call compile_erl,$(FILES_TO_COMPILE))) + $(eval GITDESCRIBE := $(shell git describe --dirty --abbrev=7 --tags --always --first-parent 2>/dev/null || true)) + $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename \ + $(filter-out $(ERLC_EXCLUDE_PATHS),$(ERL_FILES) $(CORE_FILES) $(BEAM_FILES))))))) +ifeq ($(wildcard src/$(PROJECT).app.src),) + $(app_verbose) printf '$(subst %,%%,$(subst $(newline),\n,$(subst ','\'',$(call app_file,$(GITDESCRIBE),$(MODULES)))))' \ + > ebin/$(PROJECT).app +else + $(verbose) if [ -z "$$(grep -e '^[^%]*{\s*modules\s*,' src/$(PROJECT).app.src)" ]; then \ + echo "Empty modules entry not found in $(PROJECT).app.src. Please consult the erlang.mk README for instructions." >&2; \ + exit 1; \ + fi + $(appsrc_verbose) cat src/$(PROJECT).app.src \ + | sed "s/{[[:space:]]*modules[[:space:]]*,[[:space:]]*\[\]}/{modules, \[$(call comma_list,$(MODULES))\]}/" \ + | sed "s/{id,[[:space:]]*\"git\"}/{id, \"$(subst /,\/,$(GITDESCRIBE))\"}/" \ + > ebin/$(PROJECT).app +endif + +clean:: clean-app + +clean-app: + $(gen_verbose) rm -rf $(PROJECT).d ebin/ priv/mibs/ $(XRL_ERL_FILES) $(YRL_ERL_FILES) \ + $(addprefix include/,$(patsubst %.mib,%.hrl,$(notdir $(MIB_FILES)))) \ + $(addprefix include/,$(patsubst %.asn1,%.hrl,$(notdir $(ASN1_FILES)))) \ + $(addprefix include/,$(patsubst %.asn1,%.asn1db,$(notdir $(ASN1_FILES)))) \ + $(addprefix src/,$(patsubst %.asn1,%.erl,$(notdir $(ASN1_FILES)))) + +endif + +# Copyright (c) 2016, Loïc Hoguin +# Copyright (c) 2015, Viktor Söderqvist +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: docs-deps + +# Configuration. + +ALL_DOC_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(DOC_DEPS)) + +# Targets. + +$(foreach dep,$(DOC_DEPS),$(eval $(call dep_target,$(dep)))) + +ifneq ($(SKIP_DEPS),) +doc-deps: +else +doc-deps: $(ALL_DOC_DEPS_DIRS) + $(verbose) for dep in $(ALL_DOC_DEPS_DIRS) ; do $(MAKE) -C $$dep; done +endif + +# Copyright (c) 2015-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: rel-deps + +# Configuration. + +ALL_REL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(REL_DEPS)) + +# Targets. + +$(foreach dep,$(REL_DEPS),$(eval $(call dep_target,$(dep)))) + +ifneq ($(SKIP_DEPS),) +rel-deps: +else +rel-deps: $(ALL_REL_DEPS_DIRS) + $(verbose) for dep in $(ALL_REL_DEPS_DIRS) ; do $(MAKE) -C $$dep; done +endif + +# Copyright (c) 2015-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: test-deps test-dir test-build clean-test-dir + +# Configuration. + +TEST_DIR ?= $(CURDIR)/test + +ALL_TEST_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(TEST_DEPS)) + +TEST_ERLC_OPTS ?= +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard +TEST_ERLC_OPTS += -DTEST=1 + +# Targets. + +$(foreach dep,$(TEST_DEPS),$(eval $(call dep_target,$(dep)))) + +ifneq ($(SKIP_DEPS),) +test-deps: +else +test-deps: $(ALL_TEST_DEPS_DIRS) + $(verbose) for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep IS_DEP=1; done +endif + +ifneq ($(wildcard $(TEST_DIR)),) +test-dir: + $(gen_verbose) erlc -v $(TEST_ERLC_OPTS) -I include/ -o $(TEST_DIR) \ + $(call core_find,$(TEST_DIR)/,*.erl) -pa ebin/ +endif + +ifeq ($(wildcard src),) +test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS) +test-build:: clean deps test-deps + $(verbose) $(MAKE) --no-print-directory test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" +else +ifeq ($(wildcard ebin/test),) +test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS) +test-build:: clean deps test-deps $(PROJECT).d + $(verbose) $(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" + $(gen_verbose) touch ebin/test +else +test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS) +test-build:: deps test-deps $(PROJECT).d + $(verbose) $(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" +endif + +clean:: clean-test-dir + +clean-test-dir: +ifneq ($(wildcard $(TEST_DIR)/*.beam),) + $(gen_verbose) rm -f $(TEST_DIR)/*.beam +endif +endif + +# Copyright (c) 2015-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: rebar.config + +# We strip out -Werror because we don't want to fail due to +# warnings when used as a dependency. + +compat_prepare_erlc_opts = $(shell echo "$1" | sed 's/, */,/g') + +define compat_convert_erlc_opts +$(if $(filter-out -Werror,$1),\ + $(if $(findstring +,$1),\ + $(shell echo $1 | cut -b 2-))) +endef + +define compat_erlc_opts_to_list +[$(call comma_list,$(foreach o,$(call compat_prepare_erlc_opts,$1),$(call compat_convert_erlc_opts,$o)))] +endef + +define compat_rebar_config +{deps, [ +$(call comma_list,$(foreach d,$(DEPS),\ + $(if $(filter hex,$(call dep_fetch,$d)),\ + {$(call dep_name,$d)$(comma)"$(call dep_repo,$d)"},\ + {$(call dep_name,$d)$(comma)".*"$(comma){git,"$(call dep_repo,$d)"$(comma)"$(call dep_commit,$d)"}}))) +]}. +{erl_opts, $(call compat_erlc_opts_to_list,$(ERLC_OPTS))}. +endef + +$(eval _compat_rebar_config = $$(compat_rebar_config)) +$(eval export _compat_rebar_config) + +rebar.config: + $(gen_verbose) echo "$${_compat_rebar_config}" > rebar.config + +# Copyright (c) 2015-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +ifeq ($(filter asciideck,$(DEPS) $(DOC_DEPS)),asciideck) + +.PHONY: asciidoc asciidoc-guide asciidoc-manual install-asciidoc distclean-asciidoc-guide distclean-asciidoc-manual + +# Core targets. + +docs:: asciidoc + +distclean:: distclean-asciidoc-guide distclean-asciidoc-manual + +# Plugin-specific targets. + +asciidoc: asciidoc-guide asciidoc-manual + +# User guide. + +ifeq ($(wildcard doc/src/guide/book.asciidoc),) +asciidoc-guide: +else +asciidoc-guide: distclean-asciidoc-guide doc-deps + a2x -v -f pdf doc/src/guide/book.asciidoc && mv doc/src/guide/book.pdf doc/guide.pdf + a2x -v -f chunked doc/src/guide/book.asciidoc && mv doc/src/guide/book.chunked/ doc/html/ + +distclean-asciidoc-guide: + $(gen_verbose) rm -rf doc/html/ doc/guide.pdf +endif + +# Man pages. + +ASCIIDOC_MANUAL_FILES := $(wildcard doc/src/manual/*.asciidoc) + +ifeq ($(ASCIIDOC_MANUAL_FILES),) +asciidoc-manual: +else + +# Configuration. + +MAN_INSTALL_PATH ?= /usr/local/share/man +MAN_SECTIONS ?= 3 7 +MAN_PROJECT ?= $(shell echo $(PROJECT) | sed 's/^./\U&\E/') +MAN_VERSION ?= $(PROJECT_VERSION) + +# Plugin-specific targets. + +define asciidoc2man.erl +try + [begin + io:format(" ADOC ~s~n", [F]), + ok = asciideck:to_manpage(asciideck:parse_file(F), #{ + compress => gzip, + outdir => filename:dirname(F), + extra2 => "$(MAN_PROJECT) $(MAN_VERSION)", + extra3 => "$(MAN_PROJECT) Function Reference" + }) + end || F <- [$(shell echo $(addprefix $(comma)\",$(addsuffix \",$1)) | sed 's/^.//')]], + halt(0) +catch C:E -> + io:format("Exception ~p:~p~nStacktrace: ~p~n", [C, E, erlang:get_stacktrace()]), + halt(1) +end. +endef + +asciidoc-manual:: doc-deps + +asciidoc-manual:: $(ASCIIDOC_MANUAL_FILES) + $(call erlang,$(call asciidoc2man.erl,$?)) + $(foreach s,$(MAN_SECTIONS),mkdir -p doc/man$s/ && mv doc/src/manual/*.$s.gz doc/man$s/;) + +install-docs:: install-asciidoc + +install-asciidoc: asciidoc-manual + $(foreach s,$(MAN_SECTIONS),\ + mkdir -p $(MAN_INSTALL_PATH)/man$s/ && \ + install -g `id -u` -o `id -g` -m 0644 doc/man$s/*.gz $(MAN_INSTALL_PATH)/man$s/;) + +distclean-asciidoc-manual: + $(gen_verbose) rm -rf $(addprefix doc/man,$(MAN_SECTIONS)) +endif +endif + +# Copyright (c) 2014-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: bootstrap bootstrap-lib bootstrap-rel new list-templates + +# Core targets. + +help:: + $(verbose) printf "%s\n" "" \ + "Bootstrap targets:" \ + " bootstrap Generate a skeleton of an OTP application" \ + " bootstrap-lib Generate a skeleton of an OTP library" \ + " bootstrap-rel Generate the files needed to build a release" \ + " new-app in=NAME Create a new local OTP application NAME" \ + " new-lib in=NAME Create a new local OTP library NAME" \ + " new t=TPL n=NAME Generate a module NAME based on the template TPL" \ + " new t=T n=N in=APP Generate a module NAME based on the template TPL in APP" \ + " list-templates List available templates" + +# Bootstrap templates. + +define bs_appsrc +{application, $p, [ + {description, ""}, + {vsn, "0.1.0"}, + {id, "git"}, + {modules, []}, + {registered, []}, + {applications, [ + kernel, + stdlib + ]}, + {mod, {$p_app, []}}, + {env, []} +]}. +endef + +define bs_appsrc_lib +{application, $p, [ + {description, ""}, + {vsn, "0.1.0"}, + {id, "git"}, + {modules, []}, + {registered, []}, + {applications, [ + kernel, + stdlib + ]} +]}. +endef + +# To prevent autocompletion issues with ZSH, we add "include erlang.mk" +# separately during the actual bootstrap. +ifdef SP +define bs_Makefile +PROJECT = $p +PROJECT_DESCRIPTION = New project +PROJECT_VERSION = 0.1.0 + +# Whitespace to be used when creating files from templates. +SP = $(SP) + +endef +else +define bs_Makefile +PROJECT = $p +PROJECT_DESCRIPTION = New project +PROJECT_VERSION = 0.1.0 + +endef +endif + +define bs_apps_Makefile +PROJECT = $p +PROJECT_DESCRIPTION = New project +PROJECT_VERSION = 0.1.0 + +include $(call core_relpath,$(dir $(ERLANG_MK_FILENAME)),$(APPS_DIR)/app)/erlang.mk +endef + +define bs_app +-module($p_app). +-behaviour(application). + +-export([start/2]). +-export([stop/1]). + +start(_Type, _Args) -> + $p_sup:start_link(). + +stop(_State) -> + ok. +endef + +define bs_relx_config +{release, {$p_release, "1"}, [$p, sasl, runtime_tools]}. +{extended_start_script, true}. +{sys_config, "rel/sys.config"}. +{vm_args, "rel/vm.args"}. +endef + +define bs_sys_config +[ +]. +endef + +define bs_vm_args +-name $p@127.0.0.1 +-setcookie $p +-heart +endef + +# Normal templates. + +define tpl_supervisor +-module($(n)). +-behaviour(supervisor). + +-export([start_link/0]). +-export([init/1]). + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +init([]) -> + Procs = [], + {ok, {{one_for_one, 1, 5}, Procs}}. +endef + +define tpl_gen_server +-module($(n)). +-behaviour(gen_server). + +%% API. +-export([start_link/0]). + +%% gen_server. +-export([init/1]). +-export([handle_call/3]). +-export([handle_cast/2]). +-export([handle_info/2]). +-export([terminate/2]). +-export([code_change/3]). + +-record(state, { +}). + +%% API. + +-spec start_link() -> {ok, pid()}. +start_link() -> + gen_server:start_link(?MODULE, [], []). + +%% gen_server. + +init([]) -> + {ok, #state{}}. + +handle_call(_Request, _From, State) -> + {reply, ignored, State}. + +handle_cast(_Msg, State) -> + {noreply, State}. + +handle_info(_Info, State) -> + {noreply, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. +endef + +define tpl_module +-module($(n)). +-export([]). +endef + +define tpl_cowboy_http +-module($(n)). +-behaviour(cowboy_http_handler). + +-export([init/3]). +-export([handle/2]). +-export([terminate/3]). + +-record(state, { +}). + +init(_, Req, _Opts) -> + {ok, Req, #state{}}. + +handle(Req, State=#state{}) -> + {ok, Req2} = cowboy_req:reply(200, Req), + {ok, Req2, State}. + +terminate(_Reason, _Req, _State) -> + ok. +endef + +define tpl_gen_fsm +-module($(n)). +-behaviour(gen_fsm). + +%% API. +-export([start_link/0]). + +%% gen_fsm. +-export([init/1]). +-export([state_name/2]). +-export([handle_event/3]). +-export([state_name/3]). +-export([handle_sync_event/4]). +-export([handle_info/3]). +-export([terminate/3]). +-export([code_change/4]). + +-record(state, { +}). + +%% API. + +-spec start_link() -> {ok, pid()}. +start_link() -> + gen_fsm:start_link(?MODULE, [], []). + +%% gen_fsm. + +init([]) -> + {ok, state_name, #state{}}. + +state_name(_Event, StateData) -> + {next_state, state_name, StateData}. + +handle_event(_Event, StateName, StateData) -> + {next_state, StateName, StateData}. + +state_name(_Event, _From, StateData) -> + {reply, ignored, state_name, StateData}. + +handle_sync_event(_Event, _From, StateName, StateData) -> + {reply, ignored, StateName, StateData}. + +handle_info(_Info, StateName, StateData) -> + {next_state, StateName, StateData}. + +terminate(_Reason, _StateName, _StateData) -> + ok. + +code_change(_OldVsn, StateName, StateData, _Extra) -> + {ok, StateName, StateData}. +endef + +define tpl_cowboy_loop +-module($(n)). +-behaviour(cowboy_loop_handler). + +-export([init/3]). +-export([info/3]). +-export([terminate/3]). + +-record(state, { +}). + +init(_, Req, _Opts) -> + {loop, Req, #state{}, 5000, hibernate}. + +info(_Info, Req, State) -> + {loop, Req, State, hibernate}. + +terminate(_Reason, _Req, _State) -> + ok. +endef + +define tpl_cowboy_rest +-module($(n)). + +-export([init/3]). +-export([content_types_provided/2]). +-export([get_html/2]). + +init(_, _Req, _Opts) -> + {upgrade, protocol, cowboy_rest}. + +content_types_provided(Req, State) -> + {[{{<<"text">>, <<"html">>, '*'}, get_html}], Req, State}. + +get_html(Req, State) -> + {<<"This is REST!">>, Req, State}. +endef + +define tpl_cowboy_ws +-module($(n)). +-behaviour(cowboy_websocket_handler). + +-export([init/3]). +-export([websocket_init/3]). +-export([websocket_handle/3]). +-export([websocket_info/3]). +-export([websocket_terminate/3]). + +-record(state, { +}). + +init(_, _, _) -> + {upgrade, protocol, cowboy_websocket}. + +websocket_init(_, Req, _Opts) -> + Req2 = cowboy_req:compact(Req), + {ok, Req2, #state{}}. + +websocket_handle({text, Data}, Req, State) -> + {reply, {text, Data}, Req, State}; +websocket_handle({binary, Data}, Req, State) -> + {reply, {binary, Data}, Req, State}; +websocket_handle(_Frame, Req, State) -> + {ok, Req, State}. + +websocket_info(_Info, Req, State) -> + {ok, Req, State}. + +websocket_terminate(_Reason, _Req, _State) -> + ok. +endef + +define tpl_ranch_protocol +-module($(n)). +-behaviour(ranch_protocol). + +-export([start_link/4]). +-export([init/4]). + +-type opts() :: []. +-export_type([opts/0]). + +-record(state, { + socket :: inet:socket(), + transport :: module() +}). + +start_link(Ref, Socket, Transport, Opts) -> + Pid = spawn_link(?MODULE, init, [Ref, Socket, Transport, Opts]), + {ok, Pid}. + +-spec init(ranch:ref(), inet:socket(), module(), opts()) -> ok. +init(Ref, Socket, Transport, _Opts) -> + ok = ranch:accept_ack(Ref), + loop(#state{socket=Socket, transport=Transport}). + +loop(State) -> + loop(State). +endef + +# Plugin-specific targets. + +define render_template + $(verbose) printf -- '$(subst $(newline),\n,$(subst %,%%,$(subst ','\'',$(subst $(tab),$(WS),$(call $(1))))))\n' > $(2) +endef + +ifndef WS +ifdef SP +WS = $(subst a,,a $(wordlist 1,$(SP),a a a a a a a a a a a a a a a a a a a a)) +else +WS = $(tab) +endif +endif + +bootstrap: +ifneq ($(wildcard src/),) + $(error Error: src/ directory already exists) +endif + $(eval p := $(PROJECT)) + $(eval n := $(PROJECT)_sup) + $(call render_template,bs_Makefile,Makefile) + $(verbose) echo "include erlang.mk" >> Makefile + $(verbose) mkdir src/ +ifdef LEGACY + $(call render_template,bs_appsrc,src/$(PROJECT).app.src) +endif + $(call render_template,bs_app,src/$(PROJECT)_app.erl) + $(call render_template,tpl_supervisor,src/$(PROJECT)_sup.erl) + +bootstrap-lib: +ifneq ($(wildcard src/),) + $(error Error: src/ directory already exists) +endif + $(eval p := $(PROJECT)) + $(call render_template,bs_Makefile,Makefile) + $(verbose) echo "include erlang.mk" >> Makefile + $(verbose) mkdir src/ +ifdef LEGACY + $(call render_template,bs_appsrc_lib,src/$(PROJECT).app.src) +endif + +bootstrap-rel: +ifneq ($(wildcard relx.config),) + $(error Error: relx.config already exists) +endif +ifneq ($(wildcard rel/),) + $(error Error: rel/ directory already exists) +endif + $(eval p := $(PROJECT)) + $(call render_template,bs_relx_config,relx.config) + $(verbose) mkdir rel/ + $(call render_template,bs_sys_config,rel/sys.config) + $(call render_template,bs_vm_args,rel/vm.args) + +new-app: +ifndef in + $(error Usage: $(MAKE) new-app in=APP) +endif +ifneq ($(wildcard $(APPS_DIR)/$in),) + $(error Error: Application $in already exists) +endif + $(eval p := $(in)) + $(eval n := $(in)_sup) + $(verbose) mkdir -p $(APPS_DIR)/$p/src/ + $(call render_template,bs_apps_Makefile,$(APPS_DIR)/$p/Makefile) +ifdef LEGACY + $(call render_template,bs_appsrc,$(APPS_DIR)/$p/src/$p.app.src) +endif + $(call render_template,bs_app,$(APPS_DIR)/$p/src/$p_app.erl) + $(call render_template,tpl_supervisor,$(APPS_DIR)/$p/src/$p_sup.erl) + +new-lib: +ifndef in + $(error Usage: $(MAKE) new-lib in=APP) +endif +ifneq ($(wildcard $(APPS_DIR)/$in),) + $(error Error: Application $in already exists) +endif + $(eval p := $(in)) + $(verbose) mkdir -p $(APPS_DIR)/$p/src/ + $(call render_template,bs_apps_Makefile,$(APPS_DIR)/$p/Makefile) +ifdef LEGACY + $(call render_template,bs_appsrc_lib,$(APPS_DIR)/$p/src/$p.app.src) +endif + +new: +ifeq ($(wildcard src/)$(in),) + $(error Error: src/ directory does not exist) +endif +ifndef t + $(error Usage: $(MAKE) new t=TEMPLATE n=NAME [in=APP]) +endif +ifndef n + $(error Usage: $(MAKE) new t=TEMPLATE n=NAME [in=APP]) +endif +ifdef in + $(verbose) $(MAKE) -C $(APPS_DIR)/$(in)/ new t=$t n=$n in= +else + $(call render_template,tpl_$(t),src/$(n).erl) +endif + +list-templates: + $(verbose) echo Available templates: $(sort $(patsubst tpl_%,%,$(filter tpl_%,$(.VARIABLES)))) + +# Copyright (c) 2014-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: clean-c_src distclean-c_src-env + +# Configuration. + +C_SRC_DIR ?= $(CURDIR)/c_src +C_SRC_ENV ?= $(C_SRC_DIR)/env.mk +C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT) +C_SRC_TYPE ?= shared + +# System type and C compiler/flags. + +ifeq ($(PLATFORM),msys2) + C_SRC_OUTPUT_EXECUTABLE_EXTENSION ?= .exe + C_SRC_OUTPUT_SHARED_EXTENSION ?= .dll +else + C_SRC_OUTPUT_EXECUTABLE_EXTENSION ?= + C_SRC_OUTPUT_SHARED_EXTENSION ?= .so +endif + +ifeq ($(C_SRC_TYPE),shared) + C_SRC_OUTPUT_FILE = $(C_SRC_OUTPUT)$(C_SRC_OUTPUT_SHARED_EXTENSION) +else + C_SRC_OUTPUT_FILE = $(C_SRC_OUTPUT)$(C_SRC_OUTPUT_EXECUTABLE_EXTENSION) +endif + +ifeq ($(PLATFORM),msys2) +# We hardcode the compiler used on MSYS2. The default CC=cc does +# not produce working code. The "gcc" MSYS2 package also doesn't. + CC = /mingw64/bin/gcc + export CC + CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes + CXXFLAGS ?= -O3 -finline-functions -Wall +else ifeq ($(PLATFORM),darwin) + CC ?= cc + CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes + CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall + LDFLAGS ?= -arch x86_64 -flat_namespace -undefined suppress +else ifeq ($(PLATFORM),freebsd) + CC ?= cc + CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes + CXXFLAGS ?= -O3 -finline-functions -Wall +else ifeq ($(PLATFORM),linux) + CC ?= gcc + CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes + CXXFLAGS ?= -O3 -finline-functions -Wall +endif + +ifneq ($(PLATFORM),msys2) + CFLAGS += -fPIC + CXXFLAGS += -fPIC +endif + +CFLAGS += -I"$(ERTS_INCLUDE_DIR)" -I"$(ERL_INTERFACE_INCLUDE_DIR)" +CXXFLAGS += -I"$(ERTS_INCLUDE_DIR)" -I"$(ERL_INTERFACE_INCLUDE_DIR)" + +LDLIBS += -L"$(ERL_INTERFACE_LIB_DIR)" -lerl_interface -lei + +# Verbosity. + +c_verbose_0 = @echo " C " $(?F); +c_verbose = $(c_verbose_$(V)) + +cpp_verbose_0 = @echo " CPP " $(?F); +cpp_verbose = $(cpp_verbose_$(V)) + +link_verbose_0 = @echo " LD " $(@F); +link_verbose = $(link_verbose_$(V)) + +# Targets. + +ifeq ($(wildcard $(C_SRC_DIR)),) +else ifneq ($(wildcard $(C_SRC_DIR)/Makefile),) +app:: app-c_src + +test-build:: app-c_src + +app-c_src: + $(MAKE) -C $(C_SRC_DIR) + +clean:: + $(MAKE) -C $(C_SRC_DIR) clean + +else + +ifeq ($(SOURCES),) +SOURCES := $(sort $(foreach pat,*.c *.C *.cc *.cpp,$(call core_find,$(C_SRC_DIR)/,$(pat)))) +endif +OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) + +COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c +COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c + +app:: $(C_SRC_ENV) $(C_SRC_OUTPUT_FILE) + +test-build:: $(C_SRC_ENV) $(C_SRC_OUTPUT_FILE) + +$(C_SRC_OUTPUT_FILE): $(OBJECTS) + $(verbose) mkdir -p priv/ + $(link_verbose) $(CC) $(OBJECTS) \ + $(LDFLAGS) $(if $(filter $(C_SRC_TYPE),shared),-shared) $(LDLIBS) \ + -o $(C_SRC_OUTPUT_FILE) + +%.o: %.c + $(COMPILE_C) $(OUTPUT_OPTION) $< + +%.o: %.cc + $(COMPILE_CPP) $(OUTPUT_OPTION) $< + +%.o: %.C + $(COMPILE_CPP) $(OUTPUT_OPTION) $< + +%.o: %.cpp + $(COMPILE_CPP) $(OUTPUT_OPTION) $< + +clean:: clean-c_src + +clean-c_src: + $(gen_verbose) rm -f $(C_SRC_OUTPUT_FILE) $(OBJECTS) + +endif + +ifneq ($(wildcard $(C_SRC_DIR)),) +$(C_SRC_ENV): + $(verbose) $(ERL) -eval "file:write_file(\"$(call core_native_path,$(C_SRC_ENV))\", \ + io_lib:format( \ + \"ERTS_INCLUDE_DIR ?= ~s/erts-~s/include/~n\" \ + \"ERL_INTERFACE_INCLUDE_DIR ?= ~s~n\" \ + \"ERL_INTERFACE_LIB_DIR ?= ~s~n\", \ + [code:root_dir(), erlang:system_info(version), \ + code:lib_dir(erl_interface, include), \ + code:lib_dir(erl_interface, lib)])), \ + halt()." + +distclean:: distclean-c_src-env + +distclean-c_src-env: + $(gen_verbose) rm -f $(C_SRC_ENV) + +-include $(C_SRC_ENV) +endif + +# Templates. + +define bs_c_nif +#include "erl_nif.h" + +static int loads = 0; + +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + /* Initialize private data. */ + *priv_data = NULL; + + loads++; + + return 0; +} + +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) +{ + /* Convert the private data to the new version. */ + *priv_data = *old_priv_data; + + loads++; + + return 0; +} + +static void unload(ErlNifEnv* env, void* priv_data) +{ + if (loads == 1) { + /* Destroy the private data. */ + } + + loads--; +} + +static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + if (enif_is_atom(env, argv[0])) { + return enif_make_tuple2(env, + enif_make_atom(env, "hello"), + argv[0]); + } + + return enif_make_tuple2(env, + enif_make_atom(env, "error"), + enif_make_atom(env, "badarg")); +} + +static ErlNifFunc nif_funcs[] = { + {"hello", 1, hello} +}; + +ERL_NIF_INIT($n, nif_funcs, load, NULL, upgrade, unload) +endef + +define bs_erl_nif +-module($n). + +-export([hello/1]). + +-on_load(on_load/0). +on_load() -> + PrivDir = case code:priv_dir(?MODULE) of + {error, _} -> + AppPath = filename:dirname(filename:dirname(code:which(?MODULE))), + filename:join(AppPath, "priv"); + Path -> + Path + end, + erlang:load_nif(filename:join(PrivDir, atom_to_list(?MODULE)), 0). + +hello(_) -> + erlang:nif_error({not_loaded, ?MODULE}). +endef + +new-nif: +ifneq ($(wildcard $(C_SRC_DIR)/$n.c),) + $(error Error: $(C_SRC_DIR)/$n.c already exists) +endif +ifneq ($(wildcard src/$n.erl),) + $(error Error: src/$n.erl already exists) +endif +ifdef in + $(verbose) $(MAKE) -C $(APPS_DIR)/$(in)/ new-nif n=$n in= +else + $(verbose) mkdir -p $(C_SRC_DIR) src/ + $(call render_template,bs_c_nif,$(C_SRC_DIR)/$n.c) + $(call render_template,bs_erl_nif,src/$n.erl) +endif + +# Copyright (c) 2015-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: ci ci-prepare ci-setup distclean-kerl + +CI_OTP ?= +CI_HIPE ?= +CI_ERLLVM ?= + +ifeq ($(CI_VM),native) +ERLC_OPTS += +native +TEST_ERLC_OPTS += +native +else ifeq ($(CI_VM),erllvm) +ERLC_OPTS += +native +'{hipe, [to_llvm]}' +TEST_ERLC_OPTS += +native +'{hipe, [to_llvm]}' +endif + +ifeq ($(strip $(CI_OTP) $(CI_HIPE) $(CI_ERLLVM)),) +ci:: +else + +ifeq ($(strip $(KERL)),) +KERL := $(ERLANG_MK_TMP)/kerl/kerl +endif + +export KERL + +KERL_GIT ?= https://github.com/kerl/kerl +KERL_COMMIT ?= master + +KERL_MAKEFLAGS ?= + +OTP_GIT ?= https://github.com/erlang/otp + +CI_INSTALL_DIR ?= $(HOME)/erlang + +ci:: $(addprefix ci-,$(CI_OTP) $(addsuffix -native,$(CI_HIPE)) $(addsuffix -erllvm,$(CI_ERLLVM))) + +ci-prepare: $(addprefix $(CI_INSTALL_DIR)/,$(CI_OTP) $(addsuffix -native,$(CI_HIPE))) + +ci-setup:: + +ci-extra:: + +ci_verbose_0 = @echo " CI " $(1); +ci_verbose = $(ci_verbose_$(V)) + +define ci_target +ci-$1: $(CI_INSTALL_DIR)/$2 + $(verbose) $(MAKE) --no-print-directory clean + $(ci_verbose) \ + PATH="$(CI_INSTALL_DIR)/$2/bin:$(PATH)" \ + CI_OTP_RELEASE="$1" \ + CT_OPTS="-label $1" \ + CI_VM="$3" \ + $(MAKE) ci-setup tests + $(verbose) $(MAKE) --no-print-directory ci-extra +endef + +$(foreach otp,$(CI_OTP),$(eval $(call ci_target,$(otp),$(otp),otp))) +$(foreach otp,$(CI_HIPE),$(eval $(call ci_target,$(otp)-native,$(otp)-native,native))) +$(foreach otp,$(CI_ERLLVM),$(eval $(call ci_target,$(otp)-erllvm,$(otp)-native,erllvm))) + +define ci_otp_target +ifeq ($(wildcard $(CI_INSTALL_DIR)/$(1)),) +$(CI_INSTALL_DIR)/$(1): $(KERL) + MAKEFLAGS="$(KERL_MAKEFLAGS)" $(KERL) build git $(OTP_GIT) $(1) $(1) + $(KERL) install $(1) $(CI_INSTALL_DIR)/$(1) +endif +endef + +$(foreach otp,$(CI_OTP),$(eval $(call ci_otp_target,$(otp)))) + +define ci_hipe_target +ifeq ($(wildcard $(CI_INSTALL_DIR)/$1-native),) +$(CI_INSTALL_DIR)/$1-native: $(KERL) + KERL_CONFIGURE_OPTIONS=--enable-native-libs \ + MAKEFLAGS="$(KERL_MAKEFLAGS)" $(KERL) build git $(OTP_GIT) $1 $1-native + $(KERL) install $1-native $(CI_INSTALL_DIR)/$1-native +endif +endef + +$(foreach otp,$(sort $(CI_HIPE) $(CI_ERLLLVM)),$(eval $(call ci_hipe_target,$(otp)))) + +$(KERL): + $(verbose) mkdir -p $(ERLANG_MK_TMP) + $(gen_verbose) git clone --depth 1 $(KERL_GIT) $(ERLANG_MK_TMP)/kerl + $(verbose) cd $(ERLANG_MK_TMP)/kerl && git checkout $(KERL_COMMIT) + $(verbose) chmod +x $(KERL) + +help:: + $(verbose) printf "%s\n" "" \ + "Continuous Integration targets:" \ + " ci Run '$(MAKE) tests' on all configured Erlang versions." \ + "" \ + "The CI_OTP variable must be defined with the Erlang versions" \ + "that must be tested. For example: CI_OTP = OTP-17.3.4 OTP-17.5.3" + +distclean:: distclean-kerl + +distclean-kerl: + $(gen_verbose) rm -rf $(KERL) +endif + +# Copyright (c) 2013-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: ct apps-ct distclean-ct + +# Configuration. + +CT_OPTS ?= + +ifneq ($(wildcard $(TEST_DIR)),) +ifndef CT_SUITES +CT_SUITES := $(sort $(subst _SUITE.erl,,$(notdir $(call core_find,$(TEST_DIR)/,*_SUITE.erl)))) +endif +endif +CT_SUITES ?= +CT_LOGS_DIR ?= $(CURDIR)/logs + +# Core targets. + +tests:: ct + +distclean:: distclean-ct + +help:: + $(verbose) printf "%s\n" "" \ + "Common_test targets:" \ + " ct Run all the common_test suites for this project" \ + "" \ + "All your common_test suites have their associated targets." \ + "A suite named http_SUITE can be ran using the ct-http target." + +# Plugin-specific targets. + +CT_RUN = ct_run \ + -no_auto_compile \ + -noinput \ + -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin $(APPS_DIR)/*/ebin $(TEST_DIR) \ + -dir $(TEST_DIR) \ + -logdir $(CT_LOGS_DIR) + +ifeq ($(CT_SUITES),) +ct: $(if $(IS_APP),,apps-ct) +else +ct: test-build $(if $(IS_APP),,apps-ct) + $(verbose) mkdir -p $(CT_LOGS_DIR) + $(gen_verbose) $(CT_RUN) -sname ct_$(PROJECT) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS) +endif + +ifneq ($(ALL_APPS_DIRS),) +define ct_app_target +apps-ct-$1: + $(MAKE) -C $1 ct IS_APP=1 +endef + +$(foreach app,$(ALL_APPS_DIRS),$(eval $(call ct_app_target,$(app)))) + +apps-ct: test-build $(addprefix apps-ct-,$(ALL_APPS_DIRS)) +endif + +ifndef t +CT_EXTRA = +else +ifeq (,$(findstring :,$t)) +CT_EXTRA = -group $t +else +t_words = $(subst :, ,$t) +CT_EXTRA = -group $(firstword $(t_words)) -case $(lastword $(t_words)) +endif +endif + +define ct_suite_target +ct-$(1): test-build + $(verbose) mkdir -p $(CT_LOGS_DIR) + $(gen_verbose) $(CT_RUN) -sname ct_$(PROJECT) -suite $(addsuffix _SUITE,$(1)) $(CT_EXTRA) $(CT_OPTS) +endef + +$(foreach test,$(CT_SUITES),$(eval $(call ct_suite_target,$(test)))) + +distclean-ct: + $(gen_verbose) rm -rf $(CT_LOGS_DIR) + +# Copyright (c) 2013-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: plt distclean-plt dialyze + +# Configuration. + +DIALYZER_PLT ?= $(CURDIR)/.$(PROJECT).plt +export DIALYZER_PLT + +PLT_APPS ?= +DIALYZER_DIRS ?= --src -r $(wildcard src) $(ALL_APPS_DIRS) +DIALYZER_OPTS ?= -Werror_handling -Wrace_conditions -Wunmatched_returns # -Wunderspecs + +# Core targets. + +check:: dialyze + +distclean:: distclean-plt + +help:: + $(verbose) printf "%s\n" "" \ + "Dialyzer targets:" \ + " plt Build a PLT file for this project" \ + " dialyze Analyze the project using Dialyzer" + +# Plugin-specific targets. + +define filter_opts.erl + Opts = init:get_plain_arguments(), + {Filtered, _} = lists:foldl(fun + (O, {Os, true}) -> {[O|Os], false}; + (O = "-D", {Os, _}) -> {[O|Os], true}; + (O = [\\$$-, \\$$D, _ | _], {Os, _}) -> {[O|Os], false}; + (O = "-I", {Os, _}) -> {[O|Os], true}; + (O = [\\$$-, \\$$I, _ | _], {Os, _}) -> {[O|Os], false}; + (O = "-pa", {Os, _}) -> {[O|Os], true}; + (_, Acc) -> Acc + end, {[], false}, Opts), + io:format("~s~n", [string:join(lists:reverse(Filtered), " ")]), + halt(). +endef + +$(DIALYZER_PLT): deps app + $(eval DEPS_LOG := $(shell test -f $(ERLANG_MK_TMP)/deps.log && \ + while read p; do test -d $$p/ebin && echo $$p/ebin; done <$(ERLANG_MK_TMP)/deps.log)) + $(verbose) dialyzer --build_plt --apps erts kernel stdlib \ + $(PLT_APPS) $(OTP_DEPS) $(LOCAL_DEPS) $(DEPS_LOG) + +plt: $(DIALYZER_PLT) + +distclean-plt: + $(gen_verbose) rm -f $(DIALYZER_PLT) + +ifneq ($(wildcard $(DIALYZER_PLT)),) +dialyze: +else +dialyze: $(DIALYZER_PLT) +endif + $(verbose) dialyzer --no_native `$(ERL) -eval "$(subst $(newline),,$(subst ",\",$(call filter_opts.erl)))" -extra $(ERLC_OPTS)` $(DIALYZER_DIRS) $(DIALYZER_OPTS) + +# Copyright (c) 2013-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: distclean-edoc edoc + +# Configuration. + +EDOC_OPTS ?= + +# Core targets. + +ifneq ($(wildcard doc/overview.edoc),) +docs:: edoc +endif + +distclean:: distclean-edoc + +# Plugin-specific targets. + +edoc: distclean-edoc doc-deps + $(gen_verbose) $(ERL) -eval 'edoc:application($(PROJECT), ".", [$(EDOC_OPTS)]), halt().' + +distclean-edoc: + $(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info + +# Copyright (c) 2013-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +# Configuration. + +DTL_FULL_PATH ?= +DTL_PATH ?= templates/ +DTL_SUFFIX ?= _dtl +DTL_OPTS ?= + +# Verbosity. + +dtl_verbose_0 = @echo " DTL " $(filter %.dtl,$(?F)); +dtl_verbose = $(dtl_verbose_$(V)) + +# Core targets. + +DTL_PATH := $(abspath $(DTL_PATH)) +DTL_FILES := $(sort $(call core_find,$(DTL_PATH),*.dtl)) + +ifneq ($(DTL_FILES),) + +DTL_NAMES = $(addsuffix $(DTL_SUFFIX),$(DTL_FILES:$(DTL_PATH)/%.dtl=%)) +DTL_MODULES = $(if $(DTL_FULL_PATH),$(subst /,_,$(DTL_NAMES)),$(notdir $(DTL_NAMES))) +BEAM_FILES += $(addsuffix .beam,$(addprefix ebin/,$(DTL_MODULES))) + +ifneq ($(words $(DTL_FILES)),0) +# Rebuild templates when the Makefile changes. +$(ERLANG_MK_TMP)/last-makefile-change-erlydtl: $(MAKEFILE_LIST) + @mkdir -p $(ERLANG_MK_TMP) + @if test -f $@; then \ + touch $(DTL_FILES); \ + fi + @touch $@ + +ebin/$(PROJECT).app:: $(ERLANG_MK_TMP)/last-makefile-change-erlydtl +endif + +define erlydtl_compile.erl + [begin + Module0 = case "$(strip $(DTL_FULL_PATH))" of + "" -> + filename:basename(F, ".dtl"); + _ -> + "$(DTL_PATH)/" ++ F2 = filename:rootname(F, ".dtl"), + re:replace(F2, "/", "_", [{return, list}, global]) + end, + Module = list_to_atom(string:to_lower(Module0) ++ "$(DTL_SUFFIX)"), + case erlydtl:compile(F, Module, [$(DTL_OPTS)] ++ [{out_dir, "ebin/"}, return_errors]) of + ok -> ok; + {ok, _} -> ok + end + end || F <- string:tokens("$(1)", " ")], + halt(). +endef + +ebin/$(PROJECT).app:: $(DTL_FILES) | ebin/ + $(if $(strip $?),\ + $(dtl_verbose) $(call erlang,$(call erlydtl_compile.erl,$(call core_native_path,$?)),\ + -pa ebin/ $(DEPS_DIR)/erlydtl/ebin/)) + +endif + +# Copyright (c) 2016, Loïc Hoguin +# Copyright (c) 2014, Dave Cottlehuber +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: distclean-escript escript escript-zip + +# Configuration. + +ESCRIPT_NAME ?= $(PROJECT) +ESCRIPT_FILE ?= $(ESCRIPT_NAME) + +ESCRIPT_SHEBANG ?= /usr/bin/env escript +ESCRIPT_COMMENT ?= This is an -*- erlang -*- file +ESCRIPT_EMU_ARGS ?= -escript main $(ESCRIPT_NAME) + +ESCRIPT_ZIP ?= 7z a -tzip -mx=9 -mtc=off $(if $(filter-out 0,$(V)),,> /dev/null) +ESCRIPT_ZIP_FILE ?= $(ERLANG_MK_TMP)/escript.zip + +# Core targets. + +distclean:: distclean-escript + +help:: + $(verbose) printf "%s\n" "" \ + "Escript targets:" \ + " escript Build an executable escript archive" \ + +# Plugin-specific targets. + +escript-zip:: deps app + $(verbose) mkdir -p $(dir $(ESCRIPT_ZIP)) + $(verbose) rm -f $(ESCRIPT_ZIP_FILE) + $(gen_verbose) cd .. && $(ESCRIPT_ZIP) $(ESCRIPT_ZIP_FILE) $(PROJECT)/ebin/* +ifneq ($(DEPS),) + $(verbose) cd $(DEPS_DIR) && $(ESCRIPT_ZIP) $(ESCRIPT_ZIP_FILE) \ + `cat $(ERLANG_MK_TMP)/deps.log | sed 's/^$(subst /,\/,$(DEPS_DIR))\///' | sed 's/$$/\/ebin\/\*/'` +endif + +escript:: escript-zip + $(gen_verbose) printf "%s\n" \ + "#!$(ESCRIPT_SHEBANG)" \ + "%% $(ESCRIPT_COMMENT)" \ + "%%! $(ESCRIPT_EMU_ARGS)" > $(ESCRIPT_FILE) + $(verbose) cat $(ESCRIPT_ZIP_FILE) >> $(ESCRIPT_FILE) + $(verbose) chmod +x $(ESCRIPT_FILE) + +distclean-escript: + $(gen_verbose) rm -f $(ESCRIPT_FILE) + +# Copyright (c) 2015-2016, Loïc Hoguin +# Copyright (c) 2014, Enrique Fernandez +# This file is contributed to erlang.mk and subject to the terms of the ISC License. + +.PHONY: eunit apps-eunit + +# Configuration + +EUNIT_OPTS ?= +EUNIT_ERL_OPTS ?= + +# Core targets. + +tests:: eunit + +help:: + $(verbose) printf "%s\n" "" \ + "EUnit targets:" \ + " eunit Run all the EUnit tests for this project" + +# Plugin-specific targets. + +define eunit.erl + case "$(COVER)" of + "" -> ok; + _ -> + case cover:compile_beam_directory("ebin") of + {error, _} -> halt(1); + _ -> ok + end + end, + case eunit:test($1, [$(EUNIT_OPTS)]) of + ok -> ok; + error -> halt(2) + end, + case "$(COVER)" of + "" -> ok; + _ -> + cover:export("eunit.coverdata") + end, + halt() +endef + +EUNIT_ERL_OPTS += -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin $(APPS_DIR)/*/ebin $(CURDIR)/ebin + +ifdef t +ifeq (,$(findstring :,$(t))) +eunit: test-build + $(gen_verbose) $(call erlang,$(call eunit.erl,['$(t)']),$(EUNIT_ERL_OPTS)) +else +eunit: test-build + $(gen_verbose) $(call erlang,$(call eunit.erl,fun $(t)/0),$(EUNIT_ERL_OPTS)) +endif +else +EUNIT_EBIN_MODS = $(notdir $(basename $(ERL_FILES) $(BEAM_FILES))) +EUNIT_TEST_MODS = $(notdir $(basename $(call core_find,$(TEST_DIR)/,*.erl))) + +EUNIT_MODS = $(foreach mod,$(EUNIT_EBIN_MODS) $(filter-out \ + $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(EUNIT_TEST_MODS)),'$(mod)') + +eunit: test-build $(if $(IS_APP),,apps-eunit) + $(gen_verbose) $(call erlang,$(call eunit.erl,[$(call comma_list,$(EUNIT_MODS))]),$(EUNIT_ERL_OPTS)) + +ifneq ($(ALL_APPS_DIRS),) +apps-eunit: + $(verbose) eunit_retcode=0 ; for app in $(ALL_APPS_DIRS); do $(MAKE) -C $$app eunit IS_APP=1; \ + [ $$? -ne 0 ] && eunit_retcode=1 ; done ; \ + exit $$eunit_retcode +endif +endif + +# Copyright (c) 2013-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: relx-rel relx-relup distclean-relx-rel run + +# Configuration. + +RELX ?= $(ERLANG_MK_TMP)/relx +RELX_CONFIG ?= $(CURDIR)/relx.config + +RELX_URL ?= https://github.com/erlware/relx/releases/download/v3.19.0/relx +RELX_OPTS ?= +RELX_OUTPUT_DIR ?= _rel +RELX_TAR ?= 1 + +ifdef SFX + RELX_TAR = 1 +endif + +ifeq ($(firstword $(RELX_OPTS)),-o) + RELX_OUTPUT_DIR = $(word 2,$(RELX_OPTS)) +else + RELX_OPTS += -o $(RELX_OUTPUT_DIR) +endif + +# Core targets. + +ifeq ($(IS_DEP),) +ifneq ($(wildcard $(RELX_CONFIG)),) +rel:: relx-rel + +relup:: relx-relup +endif +endif + +distclean:: distclean-relx-rel + +# Plugin-specific targets. + +$(RELX): + $(gen_verbose) $(call core_http_get,$(RELX),$(RELX_URL)) + $(verbose) chmod +x $(RELX) + +relx-rel: $(RELX) rel-deps app + $(verbose) $(RELX) -c $(RELX_CONFIG) $(RELX_OPTS) release $(if $(filter 1,$(RELX_TAR)),tar) + +relx-relup: $(RELX) rel-deps app + $(verbose) $(RELX) -c $(RELX_CONFIG) $(RELX_OPTS) release relup $(if $(filter 1,$(RELX_TAR)),tar) + +distclean-relx-rel: + $(gen_verbose) rm -rf $(RELX_OUTPUT_DIR) + +# Run target. + +ifeq ($(wildcard $(RELX_CONFIG)),) +run: +else + +define get_relx_release.erl + {ok, Config} = file:consult("$(call core_native_path,$(RELX_CONFIG))"), + {release, {Name, Vsn0}, _} = lists:keyfind(release, 1, Config), + Vsn = case Vsn0 of + {cmd, Cmd} -> os:cmd(Cmd); + semver -> ""; + {semver, _} -> ""; + VsnStr -> Vsn0 + end, + io:format("~s ~s", [Name, Vsn]), + halt(0). +endef + +RELX_REL := $(shell $(call erlang,$(get_relx_release.erl))) +RELX_REL_NAME := $(word 1,$(RELX_REL)) +RELX_REL_VSN := $(word 2,$(RELX_REL)) + +run: all + $(verbose) $(RELX_OUTPUT_DIR)/$(RELX_REL_NAME)/bin/$(RELX_REL_NAME) console + +help:: + $(verbose) printf "%s\n" "" \ + "Relx targets:" \ + " run Compile the project, build the release and run it" + +endif + +# Copyright (c) 2015-2016, Loïc Hoguin +# Copyright (c) 2014, M Robert Martin +# This file is contributed to erlang.mk and subject to the terms of the ISC License. + +.PHONY: shell + +# Configuration. + +SHELL_ERL ?= erl +SHELL_PATHS ?= $(CURDIR)/ebin $(APPS_DIR)/*/ebin $(DEPS_DIR)/*/ebin +SHELL_OPTS ?= + +ALL_SHELL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(SHELL_DEPS)) + +# Core targets + +help:: + $(verbose) printf "%s\n" "" \ + "Shell targets:" \ + " shell Run an erlang shell with SHELL_OPTS or reasonable default" + +# Plugin-specific targets. + +$(foreach dep,$(SHELL_DEPS),$(eval $(call dep_target,$(dep)))) + +build-shell-deps: $(ALL_SHELL_DEPS_DIRS) + $(verbose) for dep in $(ALL_SHELL_DEPS_DIRS) ; do $(MAKE) -C $$dep ; done + +shell: build-shell-deps + $(gen_verbose) $(SHELL_ERL) -pa $(SHELL_PATHS) $(SHELL_OPTS) + +# Copyright (c) 2017, Jean-Sébastien Pédron +# This file is contributed to erlang.mk and subject to the terms of the ISC License. + +.PHONY: show-ERL_LIBS show-ERLC_OPTS show-TEST_ERLC_OPTS + +show-ERL_LIBS: + @echo $(ERL_LIBS) + +show-ERLC_OPTS: + @$(foreach opt,$(ERLC_OPTS) -pa ebin -I include,echo "$(opt)";) + +show-TEST_ERLC_OPTS: + @$(foreach opt,$(TEST_ERLC_OPTS) -pa ebin -I include,echo "$(opt)";) + +# Copyright (c) 2015-2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +ifeq ($(filter triq,$(DEPS) $(TEST_DEPS)),triq) +.PHONY: triq + +# Targets. + +tests:: triq + +define triq_check.erl + code:add_pathsa(["$(call core_native_path,$(CURDIR)/ebin)", "$(call core_native_path,$(DEPS_DIR)/*/ebin)"]), + try + case $(1) of + all -> [true] =:= lists:usort([triq:check(M) || M <- [$(call comma_list,$(3))]]); + module -> triq:check($(2)); + function -> triq:check($(2)) + end + of + true -> halt(0); + _ -> halt(1) + catch error:undef -> + io:format("Undefined property or module~n"), + halt(0) + end. +endef + +ifdef t +ifeq (,$(findstring :,$(t))) +triq: test-build + $(verbose) $(call erlang,$(call triq_check.erl,module,$(t))) +else +triq: test-build + $(verbose) echo Testing $(t)/0 + $(verbose) $(call erlang,$(call triq_check.erl,function,$(t)())) +endif +else +triq: test-build + $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename $(wildcard ebin/*.beam)))))) + $(gen_verbose) $(call erlang,$(call triq_check.erl,all,undefined,$(MODULES))) +endif +endif + +# Copyright (c) 2016, Loïc Hoguin +# Copyright (c) 2015, Erlang Solutions Ltd. +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: xref distclean-xref + +# Configuration. + +ifeq ($(XREF_CONFIG),) + XREFR_ARGS := +else + XREFR_ARGS := -c $(XREF_CONFIG) +endif + +XREFR ?= $(CURDIR)/xrefr +export XREFR + +XREFR_URL ?= https://github.com/inaka/xref_runner/releases/download/0.2.2/xrefr + +# Core targets. + +help:: + $(verbose) printf "%s\n" "" \ + "Xref targets:" \ + " xref Run Xrefr using $XREF_CONFIG as config file if defined" + +distclean:: distclean-xref + +# Plugin-specific targets. + +$(XREFR): + $(gen_verbose) $(call core_http_get,$(XREFR),$(XREFR_URL)) + $(verbose) chmod +x $(XREFR) + +xref: deps app $(XREFR) + $(gen_verbose) $(XREFR) $(XREFR_ARGS) + +distclean-xref: + $(gen_verbose) rm -rf $(XREFR) + +# Copyright (c) 2016, Loïc Hoguin +# Copyright (c) 2015, Viktor Söderqvist +# This file is part of erlang.mk and subject to the terms of the ISC License. + +COVER_REPORT_DIR = cover + +# Hook in coverage to ct + +ifdef COVER +ifdef CT_RUN +# All modules in 'ebin' +COVER_MODS = $(notdir $(basename $(call core_ls,ebin/*.beam))) + +test-build:: $(TEST_DIR)/ct.cover.spec + +$(TEST_DIR)/ct.cover.spec: + $(verbose) echo Cover mods: $(COVER_MODS) + $(gen_verbose) printf "%s\n" \ + '{incl_mods,[$(subst $(space),$(comma),$(COVER_MODS))]}.' \ + '{export,"$(CURDIR)/ct.coverdata"}.' > $@ + +CT_RUN += -cover $(TEST_DIR)/ct.cover.spec +endif +endif + +# Core targets + +ifdef COVER +ifneq ($(COVER_REPORT_DIR),) +tests:: + $(verbose) $(MAKE) --no-print-directory cover-report +endif +endif + +clean:: coverdata-clean + +ifneq ($(COVER_REPORT_DIR),) +distclean:: cover-report-clean +endif + +help:: + $(verbose) printf "%s\n" "" \ + "Cover targets:" \ + " cover-report Generate a HTML coverage report from previously collected" \ + " cover data." \ + " all.coverdata Merge {eunit,ct}.coverdata into one coverdata file." \ + "" \ + "If COVER=1 is set, coverage data is generated by the targets eunit and ct. The" \ + "target tests additionally generates a HTML coverage report from the combined" \ + "coverdata files from each of these testing tools. HTML reports can be disabled" \ + "by setting COVER_REPORT_DIR to empty." + +# Plugin specific targets + +COVERDATA = $(filter-out all.coverdata,$(wildcard *.coverdata)) + +.PHONY: coverdata-clean +coverdata-clean: + $(gen_verbose) rm -f *.coverdata ct.cover.spec + +# Merge all coverdata files into one. +all.coverdata: $(COVERDATA) + $(gen_verbose) $(ERL) -eval ' \ + $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) \ + cover:export("$@"), halt(0).' + +# These are only defined if COVER_REPORT_DIR is non-empty. Set COVER_REPORT_DIR to +# empty if you want the coverdata files but not the HTML report. +ifneq ($(COVER_REPORT_DIR),) + +.PHONY: cover-report-clean cover-report + +cover-report-clean: + $(gen_verbose) rm -rf $(COVER_REPORT_DIR) + +ifeq ($(COVERDATA),) +cover-report: +else + +# Modules which include eunit.hrl always contain one line without coverage +# because eunit defines test/0 which is never called. We compensate for this. +EUNIT_HRL_MODS = $(subst $(space),$(comma),$(shell \ + grep -e '^\s*-include.*include/eunit\.hrl"' src/*.erl \ + | sed "s/^src\/\(.*\)\.erl:.*/'\1'/" | uniq)) + +define cover_report.erl + $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) + Ms = cover:imported_modules(), + [cover:analyse_to_file(M, "$(COVER_REPORT_DIR)/" ++ atom_to_list(M) + ++ ".COVER.html", [html]) || M <- Ms], + Report = [begin {ok, R} = cover:analyse(M, module), R end || M <- Ms], + EunitHrlMods = [$(EUNIT_HRL_MODS)], + Report1 = [{M, {Y, case lists:member(M, EunitHrlMods) of + true -> N - 1; false -> N end}} || {M, {Y, N}} <- Report], + TotalY = lists:sum([Y || {_, {Y, _}} <- Report1]), + TotalN = lists:sum([N || {_, {_, N}} <- Report1]), + Perc = fun(Y, N) -> case Y + N of 0 -> 100; S -> round(100 * Y / S) end end, + TotalPerc = Perc(TotalY, TotalN), + {ok, F} = file:open("$(COVER_REPORT_DIR)/index.html", [write]), + io:format(F, "~n" + "~n" + "Coverage report~n" + "~n", []), + io:format(F, "

Coverage

~n

Total: ~p%

~n", [TotalPerc]), + io:format(F, "~n", []), + [io:format(F, "" + "~n", + [M, M, Perc(Y, N)]) || {M, {Y, N}} <- Report1], + How = "$(subst $(space),$(comma)$(space),$(basename $(COVERDATA)))", + Date = "$(shell date -u "+%Y-%m-%dT%H:%M:%SZ")", + io:format(F, "
ModuleCoverage
~p~p%
~n" + "

Generated using ~s and erlang.mk on ~s.

~n" + "", [How, Date]), + halt(). +endef + +cover-report: + $(gen_verbose) mkdir -p $(COVER_REPORT_DIR) + $(gen_verbose) $(call erlang,$(cover_report.erl)) + +endif +endif # ifneq ($(COVER_REPORT_DIR),) + +# Copyright (c) 2016, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: sfx + +ifdef RELX_REL +ifdef SFX + +# Configuration. + +SFX_ARCHIVE ?= $(RELX_OUTPUT_DIR)/$(RELX_REL_NAME)/$(RELX_REL_NAME)-$(RELX_REL_VSN).tar.gz +SFX_OUTPUT_FILE ?= $(RELX_OUTPUT_DIR)/$(RELX_REL_NAME).run + +# Core targets. + +rel:: sfx + +# Plugin-specific targets. + +define sfx_stub +#!/bin/sh + +TMPDIR=`mktemp -d` +ARCHIVE=`awk '/^__ARCHIVE_BELOW__$$/ {print NR + 1; exit 0;}' $$0` +FILENAME=$$(basename $$0) +REL=$${FILENAME%.*} + +tail -n+$$ARCHIVE $$0 | tar -xzf - -C $$TMPDIR + +$$TMPDIR/bin/$$REL console +RET=$$? + +rm -rf $$TMPDIR + +exit $$RET + +__ARCHIVE_BELOW__ +endef + +sfx: + $(call render_template,sfx_stub,$(SFX_OUTPUT_FILE)) + $(gen_verbose) cat $(SFX_ARCHIVE) >> $(SFX_OUTPUT_FILE) + $(verbose) chmod +x $(SFX_OUTPUT_FILE) + +endif +endif + +# Copyright (c) 2013-2017, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +# External plugins. + +DEP_PLUGINS ?= + +define core_dep_plugin +-include $(DEPS_DIR)/$(1) + +$(DEPS_DIR)/$(1): $(DEPS_DIR)/$(2) ; +endef + +$(foreach p,$(DEP_PLUGINS),\ + $(eval $(if $(findstring /,$p),\ + $(call core_dep_plugin,$p,$(firstword $(subst /, ,$p))),\ + $(call core_dep_plugin,$p/plugins.mk,$p)))) + +# Copyright (c) 2013-2015, Loïc Hoguin +# Copyright (c) 2015-2016, Jean-Sébastien Pédron +# This file is part of erlang.mk and subject to the terms of the ISC License. + +# Fetch dependencies recursively (without building them). + +.PHONY: fetch-deps fetch-doc-deps fetch-rel-deps fetch-test-deps \ + fetch-shell-deps + +.PHONY: $(ERLANG_MK_RECURSIVE_DEPS_LIST) \ + $(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) \ + $(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) \ + $(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) \ + $(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST) + +fetch-deps: $(ERLANG_MK_RECURSIVE_DEPS_LIST) +fetch-doc-deps: $(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) +fetch-rel-deps: $(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) +fetch-test-deps: $(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) +fetch-shell-deps: $(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST) + +ifneq ($(SKIP_DEPS),) +$(ERLANG_MK_RECURSIVE_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST): + $(verbose) :> $@ +else +# By default, we fetch "normal" dependencies. They are also included no +# matter the type of requested dependencies. +# +# $(ALL_DEPS_DIRS) includes $(BUILD_DEPS). + +$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_DEPS_DIRS) +$(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST): $(ALL_DEPS_DIRS) $(ALL_DOC_DEPS_DIRS) +$(ERLANG_MK_RECURSIVE_REL_DEPS_LIST): $(ALL_DEPS_DIRS) $(ALL_REL_DEPS_DIRS) +$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST): $(ALL_DEPS_DIRS) $(ALL_TEST_DEPS_DIRS) +$(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST): $(ALL_DEPS_DIRS) $(ALL_SHELL_DEPS_DIRS) + +# Allow to use fetch-deps and $(DEP_TYPES) to fetch multiple types of +# dependencies with a single target. +ifneq ($(filter doc,$(DEP_TYPES)),) +$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_DOC_DEPS_DIRS) +endif +ifneq ($(filter rel,$(DEP_TYPES)),) +$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_REL_DEPS_DIRS) +endif +ifneq ($(filter test,$(DEP_TYPES)),) +$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_TEST_DEPS_DIRS) +endif +ifneq ($(filter shell,$(DEP_TYPES)),) +$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_SHELL_DEPS_DIRS) +endif + +ERLANG_MK_RECURSIVE_TMP_LIST := $(abspath $(ERLANG_MK_TMP)/recursive-tmp-deps.log) + +$(ERLANG_MK_RECURSIVE_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) \ +$(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST): +ifeq ($(IS_APP)$(IS_DEP),) + $(verbose) mkdir -p $(ERLANG_MK_TMP) + $(verbose) rm -f $(ERLANG_MK_RECURSIVE_TMP_LIST) +endif +ifndef IS_APP + $(verbose) for dep in $(ALL_APPS_DIRS) ; do \ + $(MAKE) -C $$dep $@ \ + IS_APP=1 \ + ERLANG_MK_RECURSIVE_TMP_LIST=$(ERLANG_MK_RECURSIVE_TMP_LIST) \ + || exit $$?; \ + done +endif + $(verbose) for dep in $^ ; do \ + if ! grep -qs ^$$dep$$ $(ERLANG_MK_RECURSIVE_TMP_LIST); then \ + echo $$dep >> $(ERLANG_MK_RECURSIVE_TMP_LIST); \ + if grep -qs -E "^[[:blank:]]*include[[:blank:]]+(erlang\.mk|.*/erlang\.mk)$$" \ + $$dep/GNUmakefile $$dep/makefile $$dep/Makefile; then \ + $(MAKE) -C $$dep fetch-deps \ + IS_DEP=1 \ + ERLANG_MK_RECURSIVE_TMP_LIST=$(ERLANG_MK_RECURSIVE_TMP_LIST) \ + || exit $$?; \ + fi \ + fi \ + done +ifeq ($(IS_APP)$(IS_DEP),) + $(verbose) sort < $(ERLANG_MK_RECURSIVE_TMP_LIST) | uniq > $@ + $(verbose) rm $(ERLANG_MK_RECURSIVE_TMP_LIST) +endif +endif # ifneq ($(SKIP_DEPS),) + +# List dependencies recursively. + +.PHONY: list-deps list-doc-deps list-rel-deps list-test-deps \ + list-shell-deps + +list-deps: $(ERLANG_MK_RECURSIVE_DEPS_LIST) +list-doc-deps: $(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) +list-rel-deps: $(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) +list-test-deps: $(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) +list-shell-deps: $(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST) + +list-deps list-doc-deps list-rel-deps list-test-deps list-shell-deps: + $(verbose) cat $^ diff --git a/lz4.d b/lz4.d new file mode 100644 index 0000000..004e985 --- /dev/null +++ b/lz4.d @@ -0,0 +1,2 @@ + +COMPILE_FIRST += diff --git a/priv/lz4_nif.so b/priv/lz4_nif.so new file mode 100755 index 0000000000000000000000000000000000000000..08973fadd5667f0c81cc931b3c6883a24c9d9bdb GIT binary patch literal 104132 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 U+}yEslMvz?UV$s$1jd>E14|u literal 0 HcmV?d00001 diff --git a/rebar.config b/rebar.config index c849ed0..77e464a 100644 --- a/rebar.config +++ b/rebar.config @@ -9,3 +9,10 @@ {erl_opts, [debug_info, {parse_transform, lager_transform}, {parse_transform, eqc_cover}]}, {plugins, [rebar_eqc]}]} ]}. + +{pre_hooks, [ + {"(linux|darwin|solaris|win32)", clean, "make clean"}, + {"(freebsd|netbsd|openbsd)", clean, "gmake clean"}, + {"(linux|darwin|solaris|win32)", compile, "make"}, + {"(freebsd|netbsd|openbsd)", compile, "gmake"} +]}. \ No newline at end of file diff --git a/src/leveled_cdb.erl b/src/leveled_cdb.erl index 73959b1..2e286ae 100644 --- a/src/leveled_cdb.erl +++ b/src/leveled_cdb.erl @@ -1385,14 +1385,13 @@ perform_write_hash_tables(Handle, HashTreeBin, StartPos) -> %% The List passed in should be made up of {Index, Position, Count} tuples write_top_index_table(Handle, BasePos, IndexList) -> FnWriteIndex = fun({_Index, Pos, Count}, {AccBin, CurrPos}) -> - case Count == 0 of - true -> - PosLE = endian_flip(CurrPos), - NextPos = CurrPos; - false -> - PosLE = endian_flip(Pos), - NextPos = Pos + (Count * ?DWORD_SIZE) - end, + {PosLE, NextPos} = + case Count == 0 of + true -> + {endian_flip(CurrPos), CurrPos}; + false -> + {endian_flip(Pos), Pos + (Count * ?DWORD_SIZE)} + end, CountLE = endian_flip(Count), {<>, NextPos} end, diff --git a/src/lz4_nif.erl b/src/lz4_nif.erl new file mode 100644 index 0000000..c783cd1 --- /dev/null +++ b/src/lz4_nif.erl @@ -0,0 +1,64 @@ +%% Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. +%% +%% This package, the LZ4 binding for Erlang, is double-licensed under the Mozilla +%% Public License 1.1 ("MPL") and the Apache License version 2 +%% ("ASL"). For the MPL, please see LICENSE-MPL-RabbitMQ. For the ASL, +%% please see LICENSE-APACHE2. +%% +%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, +%% either express or implied. See the LICENSE file for specific language governing +%% rights and limitations of this software. +%% +%% If you have any questions regarding licensing, please contact us at +%% info@rabbitmq.com. + +-module(lz4_nif). + +%% lz4f. +-export([lz4f_compress_frame/2]). +-export([lz4f_create_compression_context/0]). +-export([lz4f_compress_begin/2]). +-export([lz4f_compress_update/2]). +-export([lz4f_flush/1]). +-export([lz4f_compress_end/1]). +-export([lz4f_create_decompression_context/0]). +-export([lz4f_get_frame_info/2]). +-export([lz4f_decompress/2]). + +-on_load(on_load/0). +on_load() -> + case code:priv_dir(leveled) of + {error, _} -> + {error, {load_failed, "Could not determine the leveled priv/ directory."}}; + Path -> + erlang:load_nif(filename:join(Path, atom_to_list(?MODULE)), 0) + end. + +%% lz4f. + +lz4f_compress_frame(_, _) -> + erlang:nif_error({not_loaded, ?MODULE}). + +lz4f_create_compression_context() -> + erlang:nif_error({not_loaded, ?MODULE}). + +lz4f_compress_begin(_, _) -> + erlang:nif_error({not_loaded, ?MODULE}). + +lz4f_compress_update(_, _) -> + erlang:nif_error({not_loaded, ?MODULE}). + +lz4f_flush(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +lz4f_compress_end(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +lz4f_create_decompression_context() -> + erlang:nif_error({not_loaded, ?MODULE}). + +lz4f_get_frame_info(_, _) -> + erlang:nif_error({not_loaded, ?MODULE}). + +lz4f_decompress(_, _) -> + erlang:nif_error({not_loaded, ?MODULE}). diff --git a/src/lz4f.erl b/src/lz4f.erl new file mode 100644 index 0000000..80a4a7d --- /dev/null +++ b/src/lz4f.erl @@ -0,0 +1,107 @@ +%% Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. +%% +%% This package, the LZ4 binding for Erlang, is double-licensed under the Mozilla +%% Public License 1.1 ("MPL") and the Apache License version 2 +%% ("ASL"). For the MPL, please see LICENSE-MPL-RabbitMQ. For the ASL, +%% please see LICENSE-APACHE2. +%% +%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, +%% either express or implied. See the LICENSE file for specific language governing +%% rights and limitations of this software. +%% +%% If you have any questions regarding licensing, please contact us at +%% info@rabbitmq.com. + +-module(lz4f). + +%% Simple compression. +-export([compress_frame/1]). +-export([compress_frame/2]). + +%% Advanced compression. +-export([create_compression_context/0]). +-export([compress_begin/1]). +-export([compress_begin/2]). +-export([compress_update/2]). +-export([flush/1]). +-export([compress_end/1]). + +%% Decompression. +-export([create_decompression_context/0]). +-export([get_frame_info/2]). +-export([decompress/1]). +-export([decompress/2]). + +-type block_size_id() :: default | max64KB | max256KB | max1MB | max4MB. +-type block_mode() :: linked | independent. +-type frame_type() :: frame | skippable_frame. + +-type frame_info() :: #{ + block_size_id => block_size_id(), + block_mode => block_mode(), + content_checksum => boolean(), + frame_type => frame_type(), + content_size => non_neg_integer() +}. + +-type opts() :: #{ + frame_info => frame_info(), + compression_level => 0..16, + auto_flush => boolean() +}. + +-opaque cctx() :: <<>>. %% Resource. +-export_type([cctx/0]). + +-opaque dctx() :: <<>>. %% Resource. +-export_type([dctx/0]). + +-spec compress_frame(binary()) -> binary(). +compress_frame(Data) -> + lz4_nif:lz4f_compress_frame(Data, #{}). + +-spec compress_frame(binary(), opts()) -> binary(). +compress_frame(Data, Opts) -> + lz4_nif:lz4f_compress_frame(Data, Opts). + +-spec create_compression_context() -> cctx(). +create_compression_context() -> + lz4_nif:lz4f_create_compression_context(). + +-spec compress_begin(cctx()) -> binary(). +compress_begin(Cctx) -> + compress_begin(Cctx, #{}). + +-spec compress_begin(cctx(), opts()) -> binary(). +compress_begin(Cctx, Opts) -> + lz4_nif:lz4f_compress_begin(Cctx, Opts). + +-spec compress_update(cctx(), binary()) -> binary(). +compress_update(Cctx, Data) -> + lz4_nif:lz4f_compress_update(Cctx, Data). + +-spec flush(cctx()) -> binary(). +flush(Cctx) -> + lz4_nif:lz4f_flush(Cctx). + +-spec compress_end(cctx()) -> binary(). +compress_end(Cctx) -> + lz4_nif:lz4f_compress_end(Cctx). + +-spec create_decompression_context() -> dctx(). +create_decompression_context() -> + lz4_nif:lz4f_create_decompression_context(). + +-spec get_frame_info(dctx(), binary()) -> {ok, frame_info(), non_neg_integer()}. +get_frame_info(Dctx, Data) -> + lz4_nif:lz4f_get_frame_info(Dctx, Data). + +-spec decompress(binary()) -> iolist(). +decompress(Data) -> + decompress(create_decompression_context(), Data). + +-spec decompress(dctx(), binary()) -> iolist(). +decompress(Dctx, Data) -> + lz4_nif:lz4f_decompress(Dctx, Data). + +%% @todo LZ4F_resetDecompressionContext diff --git a/test/lz4f_SUITE.erl b/test/lz4f_SUITE.erl new file mode 100644 index 0000000..2a9cfb5 --- /dev/null +++ b/test/lz4f_SUITE.erl @@ -0,0 +1,82 @@ +-module(lz4f_SUITE). +-compile(export_all). + +-import(ct_helper, [config/2]). +-import(ct_helper, [doc/1]). + +%% ct. + +all() -> + [{group, all}]. + +groups() -> + [{all, [parallel], ct_helper:all(?MODULE)}]. + +init_per_suite(Config) -> + [{test_file, config(data_dir, Config) ++ "/pdf_reference_1-7.pdf"}|Config]. + +end_per_suite(_) -> + ok. + +%% Tests. + +compress_frame1(Config) -> + doc("Use lz4f:compress_frame/1 and then decompress back."), + {ok, File} = file:read_file(config(test_file, Config)), + Compressed = lz4f:compress_frame(File), + File = iolist_to_binary(lz4f:decompress(Compressed)), + ok. + +compress_update(Config) -> + doc("Stream compress with lz4f:compress_update/2 and then decompress back."), + {ok, File} = file:read_file(config(test_file, Config)), + Chunks = do_slice(File), + Ctx = lz4f:create_compression_context(), + Begin = lz4f:compress_begin(Ctx), + CompressedChunks = [lz4f:compress_update(Ctx, C) || C <- Chunks], + End = lz4f:compress_end(Ctx), + Compressed = iolist_to_binary([Begin, CompressedChunks, End]), + File = iolist_to_binary(lz4f:decompress(Compressed)), + ok. + +compress_flush(Config) -> + doc("Stream compress with some lz4f:flush/1 and then decompress back."), + {ok, File} = file:read_file(config(test_file, Config)), + Chunks = do_insert_flush(do_slice(File)), + Ctx = lz4f:create_compression_context(), + Begin = lz4f:compress_begin(Ctx), + CompressedChunks = [case C of + flush -> lz4f:flush(Ctx); + _ -> lz4f:compress_update(Ctx, C) + end || C <- Chunks], + End = lz4f:compress_end(Ctx), + Compressed = iolist_to_binary([Begin, CompressedChunks, End]), + File = iolist_to_binary(lz4f:decompress(Compressed)), + ok. + +decompress(Config) -> + doc("Compress and then stream decompress with lz4f:decompress/2."), + {ok, File} = file:read_file(config(test_file, Config)), + Compressed = lz4f:compress_frame(File), + Chunks = do_slice(Compressed), + Ctx = lz4f:create_decompression_context(), + DecompressedChunks = [lz4f:decompress(Ctx, C) || C <- Chunks], + File = iolist_to_binary(DecompressedChunks), + ok. + +%% Internal. + +do_insert_flush(L) -> + do_insert_flush(L, 0). + +do_insert_flush([], _) -> + []; +do_insert_flush(L, 5) -> + [flush|do_insert_flush(L, 0)]; +do_insert_flush([H|T], N) -> + [H|do_insert_flush(T, N + 1)]. + +do_slice(<>) -> + [Bin|do_slice(R)]; +do_slice(Bin) -> + [Bin].