aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2017-05-02 12:57:12 +0200
committerLoïc Hoguin <[email protected]>2017-05-02 12:57:12 +0200
commite4f6a3c1f1032f83b25210dea21bbacf4552f8f0 (patch)
tree707b36c8098d32923b7b56154e76028b75d87f0d
parent6783a9aa8370c0d4e5d45462709f3f50557caab1 (diff)
downloadesdl2-e4f6a3c1f1032f83b25210dea21bbacf4552f8f0.tar.gz
esdl2-e4f6a3c1f1032f83b25210dea21bbacf4552f8f0.tar.bz2
esdl2-e4f6a3c1f1032f83b25210dea21bbacf4552f8f0.zip
Move nif_helpers into their own project
-rw-r--r--.gitignore1
-rw-r--r--Makefile8
-rw-r--r--c_src/compat/sys/queue.h574
-rw-r--r--c_src/nif_helpers.c195
-rw-r--r--c_src/nif_helpers.h139
-rw-r--r--erlang.mk238
6 files changed, 138 insertions, 1017 deletions
diff --git a/.gitignore b/.gitignore
index 0a9ec0b..a663a8e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
.esdl2.plt
c_src/env.mk
c_src/*.o
+deps
ebin
esdl2.d
examples/*/*.beam
diff --git a/Makefile b/Makefile
index f8d717b..89fca3b 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,10 @@ PROJECT = esdl2
PROJECT_DESCRIPTION = SDL2 Erlang NIF.
PROJECT_VERSION = 0.1.0
+BUILD_DEPS = nif_helpers
+dep_nif_helpers = git https://github.com/ninenines/nif_helpers master
+DEP_PLUGINS = nif_helpers
+
# SDL 2.0.3 has this option enabled that causes problems with NIF functions.
SDL2_LIBS_FILTER_OUT = -Wl,--no-undefined
SDL2_LIBS = $(filter-out $(SDL2_LIBS_FILTER_OUT),$(shell sdl2-config --static-libs))
@@ -26,10 +30,6 @@ CFLAGS += $(shell sdl2-config --cflags)
# @todo -undefined dynamic_lookup on OSX?
LDLIBS += $(SDL2_LIBS) -lSDL2_image
-ifeq ($(PLATFORM),msys2)
- CFLAGS += -I"$(C_SRC_DIR)/compat/"
-endif
-
check:: cppcheck scan-build
cppcheck:
diff --git a/c_src/compat/sys/queue.h b/c_src/compat/sys/queue.h
deleted file mode 100644
index daf4553..0000000
--- a/c_src/compat/sys/queue.h
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)queue.h 8.5 (Berkeley) 8/20/94
- */
-
-#ifndef _SYS_QUEUE_H_
-#define _SYS_QUEUE_H_
-
-/*
- * This file defines five types of data structures: singly-linked lists,
- * lists, simple queues, tail queues, and circular queues.
- *
- * A singly-linked list is headed by a single forward pointer. The
- * elements are singly linked for minimum space and pointer manipulation
- * overhead at the expense of O(n) removal for arbitrary elements. New
- * elements can be added to the list after an existing element or at the
- * head of the list. Elements being removed from the head of the list
- * should use the explicit macro for this purpose for optimum
- * efficiency. A singly-linked list may only be traversed in the forward
- * direction. Singly-linked lists are ideal for applications with large
- * datasets and few or no removals or for implementing a LIFO queue.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A simple queue is headed by a pair of pointers, one the head of the
- * list and the other to the tail of the list. The elements are singly
- * linked to save space, so elements can only be removed from the
- * head of the list. New elements can be added to the list after
- * an existing element, at the head of the list, or at the end of the
- * list. A simple queue may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
- *
- * A circle queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the list.
- * A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- */
-
-/*
- * List definitions.
- */
-#define LIST_HEAD(name, type) \
-struct name { \
- struct type *lh_first; /* first element */ \
-}
-
-#define LIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define LIST_ENTRY(type) \
-struct { \
- struct type *le_next; /* next element */ \
- struct type **le_prev; /* address of previous next element */ \
-}
-
-/*
- * List functions.
- */
-#define LIST_INIT(head) do { \
- (head)->lh_first = NULL; \
-} while (/*CONSTCOND*/0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do { \
- if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
- (listelm)->field.le_next->field.le_prev = \
- &(elm)->field.le_next; \
- (listelm)->field.le_next = (elm); \
- (elm)->field.le_prev = &(listelm)->field.le_next; \
-} while (/*CONSTCOND*/0)
-
-#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.le_prev = (listelm)->field.le_prev; \
- (elm)->field.le_next = (listelm); \
- *(listelm)->field.le_prev = (elm); \
- (listelm)->field.le_prev = &(elm)->field.le_next; \
-} while (/*CONSTCOND*/0)
-
-#define LIST_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.le_next = (head)->lh_first) != NULL) \
- (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
- (head)->lh_first = (elm); \
- (elm)->field.le_prev = &(head)->lh_first; \
-} while (/*CONSTCOND*/0)
-
-#define LIST_REMOVE(elm, field) do { \
- if ((elm)->field.le_next != NULL) \
- (elm)->field.le_next->field.le_prev = \
- (elm)->field.le_prev; \
- *(elm)->field.le_prev = (elm)->field.le_next; \
-} while (/*CONSTCOND*/0)
-
-#define LIST_FOREACH(var, head, field) \
- for ((var) = ((head)->lh_first); \
- (var); \
- (var) = ((var)->field.le_next))
-
-/*
- * List access methods.
- */
-#define LIST_EMPTY(head) ((head)->lh_first == NULL)
-#define LIST_FIRST(head) ((head)->lh_first)
-#define LIST_NEXT(elm, field) ((elm)->field.le_next)
-
-
-/*
- * Singly-linked List definitions.
- */
-#define SLIST_HEAD(name, type) \
-struct name { \
- struct type *slh_first; /* first element */ \
-}
-
-#define SLIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define SLIST_ENTRY(type) \
-struct { \
- struct type *sle_next; /* next element */ \
-}
-
-/*
- * Singly-linked List functions.
- */
-#define SLIST_INIT(head) do { \
- (head)->slh_first = NULL; \
-} while (/*CONSTCOND*/0)
-
-#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
- (elm)->field.sle_next = (slistelm)->field.sle_next; \
- (slistelm)->field.sle_next = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define SLIST_INSERT_HEAD(head, elm, field) do { \
- (elm)->field.sle_next = (head)->slh_first; \
- (head)->slh_first = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define SLIST_REMOVE_HEAD(head, field) do { \
- (head)->slh_first = (head)->slh_first->field.sle_next; \
-} while (/*CONSTCOND*/0)
-
-#define SLIST_REMOVE(head, elm, type, field) do { \
- if ((head)->slh_first == (elm)) { \
- SLIST_REMOVE_HEAD((head), field); \
- } \
- else { \
- struct type *curelm = (head)->slh_first; \
- while(curelm->field.sle_next != (elm)) \
- curelm = curelm->field.sle_next; \
- curelm->field.sle_next = \
- curelm->field.sle_next->field.sle_next; \
- } \
-} while (/*CONSTCOND*/0)
-
-#define SLIST_FOREACH(var, head, field) \
- for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
-
-/*
- * Singly-linked List access methods.
- */
-#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
-#define SLIST_FIRST(head) ((head)->slh_first)
-#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
-
-
-/*
- * Singly-linked Tail queue declarations.
- */
-#define STAILQ_HEAD(name, type) \
-struct name { \
- struct type *stqh_first; /* first element */ \
- struct type **stqh_last; /* addr of last next element */ \
-}
-
-#define STAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).stqh_first }
-
-#define STAILQ_ENTRY(type) \
-struct { \
- struct type *stqe_next; /* next element */ \
-}
-
-/*
- * Singly-linked Tail queue functions.
- */
-#define STAILQ_INIT(head) do { \
- (head)->stqh_first = NULL; \
- (head)->stqh_last = &(head)->stqh_first; \
-} while (/*CONSTCOND*/0)
-
-#define STAILQ_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
- (head)->stqh_last = &(elm)->field.stqe_next; \
- (head)->stqh_first = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define STAILQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.stqe_next = NULL; \
- *(head)->stqh_last = (elm); \
- (head)->stqh_last = &(elm)->field.stqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
- if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
- (head)->stqh_last = &(elm)->field.stqe_next; \
- (listelm)->field.stqe_next = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define STAILQ_REMOVE_HEAD(head, field) do { \
- if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
- (head)->stqh_last = &(head)->stqh_first; \
-} while (/*CONSTCOND*/0)
-
-#define STAILQ_REMOVE(head, elm, type, field) do { \
- if ((head)->stqh_first == (elm)) { \
- STAILQ_REMOVE_HEAD((head), field); \
- } else { \
- struct type *curelm = (head)->stqh_first; \
- while (curelm->field.stqe_next != (elm)) \
- curelm = curelm->field.stqe_next; \
- if ((curelm->field.stqe_next = \
- curelm->field.stqe_next->field.stqe_next) == NULL) \
- (head)->stqh_last = &(curelm)->field.stqe_next; \
- } \
-} while (/*CONSTCOND*/0)
-
-#define STAILQ_FOREACH(var, head, field) \
- for ((var) = ((head)->stqh_first); \
- (var); \
- (var) = ((var)->field.stqe_next))
-
-#define STAILQ_CONCAT(head1, head2) do { \
- if (!STAILQ_EMPTY((head2))) { \
- *(head1)->stqh_last = (head2)->stqh_first; \
- (head1)->stqh_last = (head2)->stqh_last; \
- STAILQ_INIT((head2)); \
- } \
-} while (/*CONSTCOND*/0)
-
-/*
- * Singly-linked Tail queue access methods.
- */
-#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
-#define STAILQ_FIRST(head) ((head)->stqh_first)
-#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
-
-
-/*
- * Simple queue definitions.
- */
-#define SIMPLEQ_HEAD(name, type) \
-struct name { \
- struct type *sqh_first; /* first element */ \
- struct type **sqh_last; /* addr of last next element */ \
-}
-
-#define SIMPLEQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).sqh_first }
-
-#define SIMPLEQ_ENTRY(type) \
-struct { \
- struct type *sqe_next; /* next element */ \
-}
-
-/*
- * Simple queue functions.
- */
-#define SIMPLEQ_INIT(head) do { \
- (head)->sqh_first = NULL; \
- (head)->sqh_last = &(head)->sqh_first; \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
- (head)->sqh_last = &(elm)->field.sqe_next; \
- (head)->sqh_first = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.sqe_next = NULL; \
- *(head)->sqh_last = (elm); \
- (head)->sqh_last = &(elm)->field.sqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
- (head)->sqh_last = &(elm)->field.sqe_next; \
- (listelm)->field.sqe_next = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
- if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
- (head)->sqh_last = &(head)->sqh_first; \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
- if ((head)->sqh_first == (elm)) { \
- SIMPLEQ_REMOVE_HEAD((head), field); \
- } else { \
- struct type *curelm = (head)->sqh_first; \
- while (curelm->field.sqe_next != (elm)) \
- curelm = curelm->field.sqe_next; \
- if ((curelm->field.sqe_next = \
- curelm->field.sqe_next->field.sqe_next) == NULL) \
- (head)->sqh_last = &(curelm)->field.sqe_next; \
- } \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_FOREACH(var, head, field) \
- for ((var) = ((head)->sqh_first); \
- (var); \
- (var) = ((var)->field.sqe_next))
-
-/*
- * Simple queue access methods.
- */
-#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
-#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
-#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
-
-
-/*
- * Tail queue definitions.
- */
-#define _TAILQ_HEAD(name, type, qual) \
-struct name { \
- qual type *tqh_first; /* first element */ \
- qual type *qual *tqh_last; /* addr of last next element */ \
-}
-#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
-
-#define TAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).tqh_first }
-
-#define _TAILQ_ENTRY(type, qual) \
-struct { \
- qual type *tqe_next; /* next element */ \
- qual type *qual *tqe_prev; /* address of previous next element */\
-}
-#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
-
-/*
- * Tail queue functions.
- */
-#define TAILQ_INIT(head) do { \
- (head)->tqh_first = NULL; \
- (head)->tqh_last = &(head)->tqh_first; \
-} while (/*CONSTCOND*/0)
-
-#define TAILQ_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
- (head)->tqh_first->field.tqe_prev = \
- &(elm)->field.tqe_next; \
- else \
- (head)->tqh_last = &(elm)->field.tqe_next; \
- (head)->tqh_first = (elm); \
- (elm)->field.tqe_prev = &(head)->tqh_first; \
-} while (/*CONSTCOND*/0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.tqe_next = NULL; \
- (elm)->field.tqe_prev = (head)->tqh_last; \
- *(head)->tqh_last = (elm); \
- (head)->tqh_last = &(elm)->field.tqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
- if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
- (elm)->field.tqe_next->field.tqe_prev = \
- &(elm)->field.tqe_next; \
- else \
- (head)->tqh_last = &(elm)->field.tqe_next; \
- (listelm)->field.tqe_next = (elm); \
- (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
- (elm)->field.tqe_next = (listelm); \
- *(listelm)->field.tqe_prev = (elm); \
- (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define TAILQ_REMOVE(head, elm, field) do { \
- if (((elm)->field.tqe_next) != NULL) \
- (elm)->field.tqe_next->field.tqe_prev = \
- (elm)->field.tqe_prev; \
- else \
- (head)->tqh_last = (elm)->field.tqe_prev; \
- *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define TAILQ_FOREACH(var, head, field) \
- for ((var) = ((head)->tqh_first); \
- (var); \
- (var) = ((var)->field.tqe_next))
-
-#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
- for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
- (var); \
- (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
-
-#define TAILQ_CONCAT(head1, head2, field) do { \
- if (!TAILQ_EMPTY(head2)) { \
- *(head1)->tqh_last = (head2)->tqh_first; \
- (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
- (head1)->tqh_last = (head2)->tqh_last; \
- TAILQ_INIT((head2)); \
- } \
-} while (/*CONSTCOND*/0)
-
-/*
- * Tail queue access methods.
- */
-#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
-#define TAILQ_FIRST(head) ((head)->tqh_first)
-#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-
-#define TAILQ_LAST(head, headname) \
- (*(((struct headname *)((head)->tqh_last))->tqh_last))
-#define TAILQ_PREV(elm, headname, field) \
- (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
-
-
-/*
- * Circular queue definitions.
- */
-#define CIRCLEQ_HEAD(name, type) \
-struct name { \
- struct type *cqh_first; /* first element */ \
- struct type *cqh_last; /* last element */ \
-}
-
-#define CIRCLEQ_HEAD_INITIALIZER(head) \
- { (void *)&head, (void *)&head }
-
-#define CIRCLEQ_ENTRY(type) \
-struct { \
- struct type *cqe_next; /* next element */ \
- struct type *cqe_prev; /* previous element */ \
-}
-
-/*
- * Circular queue functions.
- */
-#define CIRCLEQ_INIT(head) do { \
- (head)->cqh_first = (void *)(head); \
- (head)->cqh_last = (void *)(head); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm)->field.cqe_next; \
- (elm)->field.cqe_prev = (listelm); \
- if ((listelm)->field.cqe_next == (void *)(head)) \
- (head)->cqh_last = (elm); \
- else \
- (listelm)->field.cqe_next->field.cqe_prev = (elm); \
- (listelm)->field.cqe_next = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm); \
- (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
- if ((listelm)->field.cqe_prev == (void *)(head)) \
- (head)->cqh_first = (elm); \
- else \
- (listelm)->field.cqe_prev->field.cqe_next = (elm); \
- (listelm)->field.cqe_prev = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
- (elm)->field.cqe_next = (head)->cqh_first; \
- (elm)->field.cqe_prev = (void *)(head); \
- if ((head)->cqh_last == (void *)(head)) \
- (head)->cqh_last = (elm); \
- else \
- (head)->cqh_first->field.cqe_prev = (elm); \
- (head)->cqh_first = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.cqe_next = (void *)(head); \
- (elm)->field.cqe_prev = (head)->cqh_last; \
- if ((head)->cqh_first == (void *)(head)) \
- (head)->cqh_first = (elm); \
- else \
- (head)->cqh_last->field.cqe_next = (elm); \
- (head)->cqh_last = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_REMOVE(head, elm, field) do { \
- if ((elm)->field.cqe_next == (void *)(head)) \
- (head)->cqh_last = (elm)->field.cqe_prev; \
- else \
- (elm)->field.cqe_next->field.cqe_prev = \
- (elm)->field.cqe_prev; \
- if ((elm)->field.cqe_prev == (void *)(head)) \
- (head)->cqh_first = (elm)->field.cqe_next; \
- else \
- (elm)->field.cqe_prev->field.cqe_next = \
- (elm)->field.cqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_FOREACH(var, head, field) \
- for ((var) = ((head)->cqh_first); \
- (var) != (const void *)(head); \
- (var) = ((var)->field.cqe_next))
-
-#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
- for ((var) = ((head)->cqh_last); \
- (var) != (const void *)(head); \
- (var) = ((var)->field.cqe_prev))
-
-/*
- * Circular queue access methods.
- */
-#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
-#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
-#define CIRCLEQ_LAST(head) ((head)->cqh_last)
-#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
-#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
-
-#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
- (((elm)->field.cqe_next == (void *)(head)) \
- ? ((head)->cqh_first) \
- : (elm->field.cqe_next))
-#define CIRCLEQ_LOOP_PREV(head, elm, field) \
- (((elm)->field.cqe_prev == (void *)(head)) \
- ? ((head)->cqh_last) \
- : (elm->field.cqe_prev))
-
-#endif /* sys/queue.h */
diff --git a/c_src/nif_helpers.c b/c_src/nif_helpers.c
deleted file mode 100644
index f29d76d..0000000
--- a/c_src/nif_helpers.c
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright (c) 2014-2015, Loïc Hoguin <[email protected]>
-//
-// 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.
-
-#include "nif_helpers.h"
-#include <sys/queue.h>
-#include <stdarg.h>
-
-extern ERL_NIF_TERM atom_ok;
-extern ERL_NIF_TERM atom__nif_thread_ret_;
-
-typedef struct nif_thread_message {
- TAILQ_ENTRY(nif_thread_message) next_entry;
-
- ErlNifPid* from_pid;
- void* function;
- nif_thread_arg* args;
-} nif_thread_message;
-
-typedef TAILQ_HEAD(nif_thread_mailbox, nif_thread_message) nif_thread_mailbox;
-
-typedef struct {
- ErlNifTid tid;
- ErlNifMutex* lock;
- ErlNifCond* cond;
- nif_thread_mailbox* mailbox;
-} nif_thread_state;
-
-// Message.
-
-static nif_thread_message* nif_thread_message_alloc(void* f, nif_thread_arg* args, ErlNifPid* pid)
-{
- nif_thread_message* msg = (nif_thread_message*)enif_alloc(sizeof(nif_thread_message));
-
- msg->from_pid = pid;
- msg->function = f;
- msg->args = args;
-
- return msg;
-}
-
-static void nif_thread_message_free(nif_thread_message* msg)
-{
- enif_free(msg->from_pid);
- enif_free(msg->args);
- enif_free(msg);
-}
-
-// Calls and casts.
-
-static ERL_NIF_TERM nif_thread_send(nif_thread_state* st, nif_thread_message* msg)
-{
- enif_mutex_lock(st->lock);
-
- TAILQ_INSERT_TAIL(st->mailbox, msg, next_entry);
-
- enif_cond_signal(st->cond);
- enif_mutex_unlock(st->lock);
-
- return atom_ok;
-}
-
-ERL_NIF_TERM nif_thread_cast(ErlNifEnv* env, void (*f)(nif_thread_arg*), int a, ...)
-{
- va_list ap;
- int i;
-
- nif_thread_arg* args = (nif_thread_arg*)enif_alloc(a * sizeof(nif_thread_arg));
-
- va_start(ap, a);
- for (i = 0; i < a; i++)
- args[i] = va_arg(ap, void*);
- va_end(ap);
-
- nif_thread_message* msg = nif_thread_message_alloc(f, args, NULL);
-
- return nif_thread_send((nif_thread_state*)enif_priv_data(env), msg);
-}
-
-ERL_NIF_TERM nif_thread_call(ErlNifEnv* env, ERL_NIF_TERM (*f)(ErlNifEnv*, nif_thread_arg*), int a, ...)
-{
- va_list ap;
- int i;
-
- nif_thread_arg* args = (nif_thread_arg*)enif_alloc(a * sizeof(nif_thread_arg));
-
- va_start(ap, a);
- for (i = 0; i < a; i++)
- args[i] = va_arg(ap, void*);
- va_end(ap);
-
- ErlNifPid* pid = (ErlNifPid*)enif_alloc(sizeof(ErlNifPid));
- nif_thread_message* msg = nif_thread_message_alloc((void*)f, args, enif_self(env, pid));
-
- return nif_thread_send((nif_thread_state*)enif_priv_data(env), msg);
-}
-
-// Main thread loop.
-
-static int nif_thread_receive(nif_thread_state* st, nif_thread_message** msg)
-{
- enif_mutex_lock(st->lock);
-
- while (TAILQ_EMPTY(st->mailbox))
- enif_cond_wait(st->cond, st->lock);
-
- *msg = TAILQ_FIRST(st->mailbox);
- TAILQ_REMOVE(st->mailbox, TAILQ_FIRST(st->mailbox), next_entry);
-
- enif_mutex_unlock(st->lock);
-
- if ((*msg)->function == NULL)
- return 0;
-
- return 1;
-}
-
-static void nif_thread_handle(ErlNifEnv* env, nif_thread_state* st, nif_thread_message* msg)
-{
- if (msg->from_pid == NULL) {
- void (*cast)(nif_thread_arg*) = msg->function;
- cast(msg->args);
- } else {
- ERL_NIF_TERM (*call)(ErlNifEnv*, nif_thread_arg*) = msg->function;
- ERL_NIF_TERM ret = call(env, msg->args);
-
- enif_send(NULL, msg->from_pid, env,
- enif_make_tuple2(env, atom__nif_thread_ret_, ret));
-
- enif_clear_env(env);
- }
-
- nif_thread_message_free(msg);
-}
-
-static void* nif_main_thread(void* obj)
-{
- ErlNifEnv* env = enif_alloc_env();
- nif_thread_state* st = (nif_thread_state*)obj;
- nif_thread_message* msg;
-
- while (nif_thread_receive(st, &msg))
- nif_thread_handle(env, st, msg);
-
- enif_free_env(env);
-
- return NULL;
-}
-
-// Main thread creation/destruction.
-
-void* nif_create_main_thread(char* name)
-{
- nif_thread_state* st = (nif_thread_state*)enif_alloc(sizeof(nif_thread_state));
-
- st->lock = enif_mutex_create("nif_thread_mailbox_lock");
- st->cond = enif_cond_create("nif_thread_mailbox_cond");
- st->mailbox = (nif_thread_mailbox*)enif_alloc(sizeof(nif_thread_mailbox));
- TAILQ_INIT(st->mailbox);
-
-#if defined(__APPLE__) && defined(__MACH__)
- // On OSX we identify ourselves as the main thread to ensure that
- // we are compatible with libraries that require it. For example
- // this is necessary with SDL2 in order to receive input events.
- erl_drv_steal_main_thread(name, &(st->tid), nif_main_thread, st, NULL);
-#else
- enif_thread_create(name, &(st->tid), nif_main_thread, st, NULL);
-#endif
-
- return (void*)st;
-}
-
-void nif_destroy_main_thread(void* void_st)
-{
- nif_thread_state* st = (nif_thread_state*)void_st;
- nif_thread_message* msg = nif_thread_message_alloc(NULL, NULL, NULL);
-
- nif_thread_send(st, msg);
- enif_thread_join(st->tid, NULL);
-
- enif_cond_destroy(st->cond);
- enif_mutex_destroy(st->lock);
- enif_free(st->mailbox);
- enif_free(st);
-}
diff --git a/c_src/nif_helpers.h b/c_src/nif_helpers.h
deleted file mode 100644
index 2eefec6..0000000
--- a/c_src/nif_helpers.h
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) 2014-2015, Loïc Hoguin <[email protected]>
-//
-// 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.
-
-#ifndef __NIF_HELPERS_H__
-#define __NIF_HELPERS_H__
-
-#include "erl_nif.h"
-
-#define TO_STRING(i) #i
-
-// Atoms.
-
-#define MAX_ATOM_LENGTH 255
-
-#define NIF_ATOM_DECL(a) ERL_NIF_TERM atom_ ## a;
-#define NIF_ATOM_H_DECL(a) extern ERL_NIF_TERM atom_ ## a;
-#define NIF_ATOM_INIT(a) atom_ ## a = enif_make_atom(env, #a);
-
-// Functions.
-
-#ifndef NIF_FUNCTION_NAME
-#define NIF_FUNCTION_NAME(n) n
-#endif
-
-#define NIF_FUNCTION(f) \
- ERL_NIF_TERM NIF_FUNCTION_NAME(f)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-#define NIF_FUNCTION_ARRAY(f, a) {#f, a, NIF_FUNCTION_NAME(f)},
-#define NIF_FUNCTION_H_DECL(f, a) \
- ERL_NIF_TERM NIF_FUNCTION_NAME(f)(ErlNifEnv*, int, const ERL_NIF_TERM []);
-
-#define BADARG_IF(cond) if (cond) return enif_make_badarg(env)
-
-// Resources.
-
-#ifndef NIF_RES_TYPE
-#define NIF_RES_TYPE(t) t
-#endif
-
-#define NIF_RES_DECL(r) ErlNifResourceType* res_ ## r = NULL;
-#define NIF_RES_H_DECL(r) \
- extern ErlNifResourceType* res_ ## r; \
- void dtor_ ## r(ErlNifEnv*, void*); \
- typedef struct { \
- NIF_RES_TYPE(r)* v; \
- void* dep; \
- } obj_ ## r;
-#define NIF_RES_INIT(r) \
- res_ ## r = enif_open_resource_type(env, NULL, TO_STRING(NIF_RES_TYPE(r)), dtor_ ## r, ERL_NIF_RT_CREATE, NULL); \
- if (!res_ ## r) return -1;
-
-#define NIF_RES_GET(r, obj) (((obj_ ## r*)obj)->v)
-#define NIF_RES_DEP(r, obj) (((obj_ ## r*)obj)->dep)
-#define NIF_RES_TO_TERM(r, val, term) NIF_RES_TO_TERM_WITH_DEP(r, val, term, NULL)
-#define NIF_RES_TO_TERM_WITH_DEP(r, val, term, dep_res) { \
- obj_ ## r* res = enif_alloc_resource(res_ ## r, sizeof(obj_ ## r)); \
- res->v = val; \
- res->dep = dep_res; \
- term = enif_make_resource(env, res); \
- enif_release_resource(res); \
-}
-
-// Function generators.
-
-#define NIF_ATOM_TO_FLAG(a, f) if (enif_is_identical(atom_ ## a, head)) *flags |= f; else
-#define NIF_LIST_TO_FLAGS_FUNCTION(f, type, flags_list) \
- int f(ErlNifEnv* env, ERL_NIF_TERM list, type* flags) \
- { \
- ERL_NIF_TERM head; \
- \
- if (!enif_is_list(env, list)) \
- return 0; \
- \
- while (enif_get_list_cell(env, list, &head, &list)) { \
- flags_list(NIF_ATOM_TO_FLAG) /* else */ return 0; \
- } \
- \
- return 1; \
- }
-
-#define NIF_FLAG_CONS_LIST(a, f) if (flags & f) list = enif_make_list_cell(env, atom_ ## a, list);
-#define NIF_FLAGS_TO_LIST_FUNCTION(f, type, flags_list) \
- ERL_NIF_TERM f(ErlNifEnv* env, type flags) \
- { \
- ERL_NIF_TERM list = enif_make_list(env, 0); \
- flags_list(NIF_FLAG_CONS_LIST); \
- return list; \
- }
-
-#define NIF_ATOM_TO_ENUM(a, e) if (enif_is_identical(atom_ ## a, atom)) { *val = e; return 1; }
-#define NIF_ATOM_TO_ENUM_FUNCTION(f, type, enum_list) \
- int f(ErlNifEnv* env, ERL_NIF_TERM atom, type* val) \
- { \
- enum_list(NIF_ATOM_TO_ENUM) \
- \
- return 0; \
- }
-#define NIF_ATOM_TO_ENUM_FUNCTION_DECL(f, type) int f(ErlNifEnv*, ERL_NIF_TERM, type*);
-
-#define NIF_ENUM_TO_ATOM(a, e) if (id == e) return atom_ ## a;
-#define NIF_ENUM_TO_ATOM_FUNCTION(f, type, enum_list) \
- ERL_NIF_TERM f(type id) \
- { \
- enum_list(NIF_ENUM_TO_ATOM) \
- return atom_undefined; \
- }
-#define NIF_ENUM_TO_ATOM_FUNCTION_DECL(f, type) ERL_NIF_TERM f(type);
-
-// Threaded NIFs.
-
-typedef void* nif_thread_arg;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void* nif_create_main_thread(char*);
-void nif_destroy_main_thread(void*);
-ERL_NIF_TERM nif_thread_cast(ErlNifEnv*, void (*f)(nif_thread_arg*), int a, ...);
-ERL_NIF_TERM nif_thread_call(ErlNifEnv*, ERL_NIF_TERM (*f)(ErlNifEnv*, nif_thread_arg*), int a, ...);
-
-#ifdef __cplusplus
-}
-#endif
-
-#define NIF_CAST_HANDLER(f) static void f(nif_thread_arg* args)
-#define NIF_CALL_HANDLER(f) static ERL_NIF_TERM f(ErlNifEnv* env, nif_thread_arg* args)
-
-#endif
diff --git a/erlang.mk b/erlang.mk
index 724e7d4..64aaa4e 100644
--- a/erlang.mk
+++ b/erlang.mk
@@ -16,7 +16,7 @@
ERLANG_MK_FILENAME := $(realpath $(lastword $(MAKEFILE_LIST)))
-ERLANG_MK_VERSION = 2016.01.12-2-g7a200f5
+ERLANG_MK_VERSION = 2017.04.25-6-g5922969
# Make 3.81 and 3.82 are deprecated.
@@ -4098,7 +4098,7 @@ endif
# Copyright (c) 2013-2016, Loïc Hoguin <[email protected]>
# This file is part of erlang.mk and subject to the terms of the ISC License.
-.PHONY: distclean-deps
+.PHONY: distclean-deps clean-tmp-deps.log
# Configuration.
@@ -4123,6 +4123,7 @@ 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))))
@@ -4145,10 +4146,7 @@ dep_verbose = $(dep_verbose_$(V))
# Core targets.
-ifdef IS_APP
-apps::
-else
-apps:: $(ALL_APPS_DIRS)
+apps:: $(ALL_APPS_DIRS) clean-tmp-deps.log
ifeq ($(IS_APP)$(IS_DEP),)
$(verbose) rm -f $(ERLANG_MK_TMP)/apps.log
endif
@@ -4156,10 +4154,15 @@ endif
# 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
- $(verbose) for dep in $(ALL_APPS_DIRS) ; do \
+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 \
@@ -4167,18 +4170,16 @@ endif
$(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
-ifeq ($(ALL_DEPS_DIRS),)
-deps:: apps
-else
-deps:: $(ALL_DEPS_DIRS) apps
-ifeq ($(IS_APP)$(IS_DEP),)
- $(verbose) rm -f $(ERLANG_MK_TMP)/deps.log
-endif
+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 \
@@ -4194,7 +4195,6 @@ endif
fi \
done
endif
-endif
# Deps related targets.
@@ -4207,7 +4207,9 @@ define dep_autopatch
$(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \
$(call dep_autopatch_erlang_mk,$(1)); \
elif [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \
- if [ 0 != `grep -c "include ../\w*\.mk" $(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)); \
@@ -4230,7 +4232,7 @@ define dep_autopatch2
$(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 ]; then \
+ 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 \
@@ -4689,84 +4691,6 @@ 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
-# 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-2016, Loïc Hoguin <[email protected]>
-# 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) 2015-2016, Loïc Hoguin <[email protected]>
# This file is part of erlang.mk and subject to the terms of the ISC License.
@@ -4989,7 +4913,12 @@ define makedep.erl
(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, _}) ->
- case filelib:is_file("src/" ++ atom_to_list(Imp) ++ ".erl") of
+ 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;
@@ -5013,9 +4942,17 @@ define makedep.erl
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 +=", [[" ", atom_to_list(CF)] || CF <- CompileFirst], "\n"
+ "\nCOMPILE_FIRST +=", [[" ", TargetPath(CF)] || CF <- CompileFirst], "\n"
]),
halt()
endef
@@ -5743,9 +5680,6 @@ endif
ifndef t
$(error Usage: $(MAKE) new t=TEMPLATE n=NAME [in=APP])
endif
-ifndef tpl_$(t)
- $(error Unknown template)
-endif
ifndef n
$(error Usage: $(MAKE) new t=TEMPLATE n=NAME [in=APP])
endif
@@ -6264,6 +6198,69 @@ edoc: distclean-edoc doc-deps
distclean-edoc:
$(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info
+# Copyright (c) 2013-2016, Loïc Hoguin <[email protected]>
+# 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 <[email protected]>
# Copyright (c) 2014, Dave Cottlehuber <[email protected]>
# This file is part of erlang.mk and subject to the terms of the ISC License.
@@ -6378,7 +6375,9 @@ eunit: test-build $(if $(IS_APP),,apps-eunit)
ifneq ($(ALL_APPS_DIRS),)
apps-eunit:
- $(verbose) for app in $(ALL_APPS_DIRS); do $(MAKE) -C $$app eunit IS_APP=1; done
+ $(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
@@ -6395,6 +6394,11 @@ 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))
@@ -6421,10 +6425,10 @@ $(RELX):
$(verbose) chmod +x $(RELX)
relx-rel: $(RELX) rel-deps app
- $(verbose) $(RELX) -c $(RELX_CONFIG) $(RELX_OPTS) release tar
+ $(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 tar
+ $(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)
@@ -6436,8 +6440,14 @@ run:
else
define get_relx_release.erl
- {ok, Config} = file:consult("$(RELX_CONFIG)"),
- {release, {Name, Vsn}, _} = lists:keyfind(release, 1, Config),
+ {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
@@ -6754,6 +6764,24 @@ sfx:
endif
endif
+# Copyright (c) 2013-2017, Loïc Hoguin <[email protected]>
+# 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 <[email protected]>
# Copyright (c) 2015-2016, Jean-Sébastien Pédron <[email protected]>
# This file is part of erlang.mk and subject to the terms of the ISC License.