aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2017-12-20 20:03:16 +0100
committerLoïc Hoguin <[email protected]>2017-12-20 20:03:16 +0100
commitb0950785e72d9d59c6fd816c01d203ecb083c663 (patch)
tree38cfae31a019ffe7b90d60dea2f6f01c3830e4b3
parente4f6a3c1f1032f83b25210dea21bbacf4552f8f0 (diff)
downloadesdl2-b0950785e72d9d59c6fd816c01d203ecb083c663.tar.gz
esdl2-b0950785e72d9d59c6fd816c01d203ecb083c663.tar.bz2
esdl2-b0950785e72d9d59c6fd816c01d203ecb083c663.zip
Add the sdl_mouse module implementing half of sdl_mouse.h
The latter half will be part of sdl_cursor. This depends on some changes to nif_helper. The sdl_gl part of the code is probably slithly broken now, the dependency on the window is gone. This will be resolved later on.
-rw-r--r--Makefile4
-rw-r--r--c_src/esdl2.c4
-rw-r--r--c_src/esdl2.h37
-rw-r--r--c_src/esdl2_renderers.c104
-rw-r--r--c_src/esdl2_windows.c97
-rw-r--r--c_src/sdl_gl.c5
-rw-r--r--c_src/sdl_mouse.c224
-rw-r--r--c_src/sdl_renderer.c12
-rw-r--r--c_src/sdl_window.c14
-rw-r--r--ebin/esdl2.app2
-rw-r--r--erlang.mk509
-rw-r--r--examples/hello_sdl/hello_sdl.erl2
-rw-r--r--src/esdl2.erl40
-rw-r--r--src/sdl_mouse.erl72
14 files changed, 953 insertions, 173 deletions
diff --git a/Makefile b/Makefile
index 89fca3b..4fd1595 100644
--- a/Makefile
+++ b/Makefile
@@ -39,6 +39,10 @@ scan-build:
make clean
scan-build make
+hello_sdl:: all
+ erlc -o examples/hello_sdl examples/hello_sdl/*.erl
+ cd examples/hello_sdl && ./start.sh
+
bullet_engine:: all
erlc -o examples/bullet_engine examples/bullet_engine/*.erl
cd examples/bullet_engine && ./start.sh
diff --git a/c_src/esdl2.c b/c_src/esdl2.c
index 1790dd7..82bea2d 100644
--- a/c_src/esdl2.c
+++ b/c_src/esdl2.c
@@ -27,6 +27,8 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
*priv_data = nif_create_main_thread("esdl2");
+ esdl2_windows_init();
+
loads++;
return 0;
@@ -46,6 +48,8 @@ static void unload(ErlNifEnv* env, void* priv_data)
if (loads == 1)
nif_destroy_main_thread(priv_data);
+ esdl2_windows_free();
+
loads--;
}
diff --git a/c_src/esdl2.h b/c_src/esdl2.h
index 10508ff..ca9a424 100644
--- a/c_src/esdl2.h
+++ b/c_src/esdl2.h
@@ -23,6 +23,7 @@
A(accelerated) \
A(add) \
A(allow_high_dpi) \
+ A(arrow) \
A(audio) \
A(blend) \
A(borderless) \
@@ -34,6 +35,7 @@
A(charging) \
A(clicks) \
A(close) \
+ A(crosshair) \
A(data) \
A(enter) \
A(error) \
@@ -42,6 +44,7 @@
A(everything) \
A(exposed) \
A(false) \
+ A(flipped) \
A(focus_gained) \
A(focus_lost) \
A(foreign) \
@@ -49,9 +52,11 @@
A(fullscreen_desktop) \
A(game_controller) \
A(h) \
+ A(hand) \
A(haptic) \
A(hidden) \
A(horizontal) \
+ A(ibeam) \
A(input_focus) \
A(input_grabbed) \
A(joystick) \
@@ -69,14 +74,17 @@
A(minimized) \
A(mod) \
A(mode) \
+ A(mouse_capture) \
A(mouse_down) \
A(mouse_focus) \
A(mouse_motion) \
A(mouse_up) \
A(mouse_wheel) \
A(moved) \
+ A(no) \
A(no_battery) \
A(none) \
+ A(normal) \
A(num) \
A(on_battery) \
A(opengl) \
@@ -93,7 +101,12 @@
A(right_shift) \
A(scancode) \
A(shown) \
+ A(size_all) \
A(size_changed) \
+ A(size_nesw) \
+ A(size_ns) \
+ A(size_nwse) \
+ A(size_we) \
A(software) \
A(state) \
A(sym) \
@@ -108,6 +121,8 @@
A(vertical) \
A(video) \
A(w) \
+ A(wait) \
+ A(wait_arrow) \
A(which) \
A(window) \
A(window_id) \
@@ -175,6 +190,16 @@
F(is_text_input_active, 0) \
F(start_text_input, 0) \
F(stop_text_input, 0) \
+ /* sdl_mouse */ \
+ F(capture_mouse, 1) \
+ F(get_global_mouse_state, 0) \
+ F(get_mouse_focus, 0) \
+ F(get_mouse_state, 0) \
+ F(get_relative_mouse_mode, 0) \
+ F(get_relative_mouse_state, 0) \
+ F(set_relative_mouse_mode, 1) \
+ F(warp_mouse_global, 2) \
+ F(warp_mouse_in_window, 3) \
/* sdl_power */ \
F(get_power_info, 0) \
/* sdl_renderer */ \
@@ -265,6 +290,18 @@ NIF_ENUM_TO_ATOM_FUNCTION_DECL(blend_mode_to_atom, SDL_BlendMode)
// --
+void esdl2_windows_init(void);
+void esdl2_windows_insert(SDL_Window*, obj_Window*);
+ERL_NIF_TERM esdl2_windows_find(ErlNifEnv*, SDL_Window*);
+void esdl2_windows_remove(SDL_Window*);
+void esdl2_windows_free(void);
+
+void esdl2_renderers_init(void);
+void esdl2_renderers_insert(SDL_Renderer*, obj_Renderer*, obj_Window*);
+ERL_NIF_TERM esdl2_renderers_find(ErlNifEnv*, SDL_Renderer*);
+void esdl2_renderers_remove(SDL_Renderer*);
+void esdl2_renderers_free(void);
+
ErlNifPid* get_callback_process(void);
#define sdl_error_tuple(env) \
diff --git a/c_src/esdl2_renderers.c b/c_src/esdl2_renderers.c
new file mode 100644
index 0000000..281079c
--- /dev/null
+++ b/c_src/esdl2_renderers.c
@@ -0,0 +1,104 @@
+// Copyright (c) 2017, 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 "esdl2.h"
+#include <sys/queue.h>
+
+struct esdl2_renderer {
+ LIST_ENTRY(esdl2_renderer) entries;
+
+ SDL_Renderer* renderer;
+ obj_Renderer* res;
+ obj_Window* window_res;
+};
+
+static LIST_HEAD(esdl2_renderer_list, esdl2_renderer) renderers;
+
+void esdl2_renderers_init()
+{
+ LIST_INIT(&renderers);
+}
+
+void esdl2_renderers_insert(SDL_Renderer* renderer, obj_Renderer* res, obj_Window* window_res)
+{
+ struct esdl2_renderer* item;
+
+ item = malloc(sizeof(struct esdl2_renderer));
+ item->renderer = renderer;
+ item->res = res;
+ item->window_res = window_res;
+
+ enif_keep_resource(window_res);
+
+ LIST_INSERT_HEAD(&renderers, item, entries);
+}
+
+struct esdl2_renderer* esdl2_renderers_find_entry(SDL_Renderer* renderer);
+
+struct esdl2_renderer* esdl2_renderers_find_entry(SDL_Renderer* renderer)
+{
+ struct esdl2_renderer* head;
+
+ head = LIST_FIRST(&renderers);
+ while (head != NULL) {
+ if (head->renderer == renderer)
+ return head;
+
+ head = LIST_NEXT(head, entries);
+ }
+
+ return NULL;
+}
+
+ERL_NIF_TERM esdl2_renderers_find(ErlNifEnv* env, SDL_Renderer* renderer)
+{
+ struct esdl2_renderer* entry;
+ ERL_NIF_TERM term;
+
+ entry = esdl2_renderers_find_entry(renderer);
+
+ if (entry == NULL)
+ return atom_undefined;
+
+ term = enif_make_resource(env, entry->res);
+
+ return term;
+}
+
+void esdl2_renderers_remove(SDL_Renderer* renderer)
+{
+ struct esdl2_renderer* entry;
+
+ entry = esdl2_renderers_find_entry(renderer);
+
+ if (entry == NULL)
+ return;
+
+ enif_release_resource(entry->window_res);
+
+ LIST_REMOVE(entry, entries);
+}
+
+void esdl2_renderers_free()
+{
+ struct esdl2_renderer *head, *next;
+
+ head = LIST_FIRST(&renderers);
+ while (head != NULL) {
+ next = LIST_NEXT(head, entries);
+ free(head);
+ head = next;
+ }
+}
+
diff --git a/c_src/esdl2_windows.c b/c_src/esdl2_windows.c
new file mode 100644
index 0000000..8855987
--- /dev/null
+++ b/c_src/esdl2_windows.c
@@ -0,0 +1,97 @@
+// Copyright (c) 2017, 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 "esdl2.h"
+#include <sys/queue.h>
+
+struct esdl2_window {
+ LIST_ENTRY(esdl2_window) entries;
+
+ SDL_Window* window;
+ obj_Window* res;
+};
+
+static LIST_HEAD(esdl2_window_list, esdl2_window) windows;
+
+void esdl2_windows_init()
+{
+ LIST_INIT(&windows);
+}
+
+void esdl2_windows_insert(SDL_Window* window, obj_Window* res)
+{
+ struct esdl2_window* item;
+
+ item = malloc(sizeof(struct esdl2_window));
+ item->window = window;
+ item->res = res;
+
+ LIST_INSERT_HEAD(&windows, item, entries);
+}
+
+struct esdl2_window* esdl2_windows_find_entry(SDL_Window* window);
+
+struct esdl2_window* esdl2_windows_find_entry(SDL_Window* window)
+{
+ struct esdl2_window* head;
+
+ head = LIST_FIRST(&windows);
+ while (head != NULL) {
+ if (head->window == window)
+ return head;
+
+ head = LIST_NEXT(head, entries);
+ }
+
+ return NULL;
+}
+
+ERL_NIF_TERM esdl2_windows_find(ErlNifEnv* env, SDL_Window* window)
+{
+ struct esdl2_window* entry;
+ ERL_NIF_TERM term;
+
+ entry = esdl2_windows_find_entry(window);
+
+ if (entry == NULL)
+ return atom_undefined;
+
+ term = enif_make_resource(env, entry->res);
+
+ return term;
+}
+
+void esdl2_windows_remove(SDL_Window* window)
+{
+ struct esdl2_window* entry;
+
+ entry = esdl2_windows_find_entry(window);
+
+ if (entry == NULL)
+ return;
+
+ LIST_REMOVE(entry, entries);
+}
+
+void esdl2_windows_free()
+{
+ struct esdl2_window *head, *next;
+
+ head = LIST_FIRST(&windows);
+ while (head != NULL) {
+ next = LIST_NEXT(head, entries);
+ free(head);
+ head = next;
+ }
+}
diff --git a/c_src/sdl_gl.c b/c_src/sdl_gl.c
index febd49f..71fef6a 100644
--- a/c_src/sdl_gl.c
+++ b/c_src/sdl_gl.c
@@ -17,7 +17,7 @@
void dtor_GLContext(ErlNifEnv* env, void* obj)
{
SDL_GL_DeleteContext(NIF_RES_GET(GLContext, obj));
- enif_release_resource(NIF_RES_DEP(GLContext, obj));
+// @todo enif_release_resource(NIF_RES_DEP(GLContext, obj));
}
// gl_create_context
@@ -33,7 +33,8 @@ NIF_CALL_HANDLER(thread_gl_create_context)
enif_keep_resource(args[0]);
- NIF_RES_TO_TERM_WITH_DEP(GLContext, context, term, args[0]);
+// @todo NIF_RES_TO_TERM_WITH_DEP(GLContext, context, term, args[0]);
+ NIF_RES_TO_TERM(GLContext, context, term);
return enif_make_tuple2(env,
atom_ok,
diff --git a/c_src/sdl_mouse.c b/c_src/sdl_mouse.c
new file mode 100644
index 0000000..b74d088
--- /dev/null
+++ b/c_src/sdl_mouse.c
@@ -0,0 +1,224 @@
+// Copyright (c) 2017, 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 "esdl2.h"
+
+#define SYSTEM_CURSOR_ENUM(E) \
+ E(arrow, SDL_SYSTEM_CURSOR_ARROW) \
+ E(ibeam, SDL_SYSTEM_CURSOR_IBEAM) \
+ E(wait, SDL_SYSTEM_CURSOR_WAIT) \
+ E(crosshair, SDL_SYSTEM_CURSOR_CROSSHAIR) \
+ E(wait_arrow, SDL_SYSTEM_CURSOR_WAITARROW) \
+ E(size_nwse, SDL_SYSTEM_CURSOR_SIZENWSE) \
+ E(size_nesw, SDL_SYSTEM_CURSOR_SIZENESW) \
+ E(size_we, SDL_SYSTEM_CURSOR_SIZEWE) \
+ E(size_ns, SDL_SYSTEM_CURSOR_SIZENS) \
+ E(size_all, SDL_SYSTEM_CURSOR_SIZEALL) \
+ E(no, SDL_SYSTEM_CURSOR_NO) \
+ E(hand, SDL_SYSTEM_CURSOR_HAND)
+
+static NIF_ATOM_TO_ENUM_FUNCTION(atom_to_system_cursor, int, SYSTEM_CURSOR_ENUM)
+
+#define MOUSEWHEEL_DIRECTION_ENUM(E) \
+ E(normal, SDL_MOUSEWHEEL_NORMAL) \
+ E(flipped, SDL_MOUSEWHEEL_FLIPPED)
+
+static NIF_ATOM_TO_ENUM_FUNCTION(atom_to_mousewheel_direction, int, MOUSEWHEEL_DIRECTION_ENUM)
+
+static ERL_NIF_TERM get_mouse_state_common(ErlNifEnv* env, int x, int y, Uint32 state)
+{
+ ERL_NIF_TERM list;
+
+ list = enif_make_list(env, 0);
+
+ if (state & SDL_BUTTON_LMASK)
+ list = enif_make_list_cell(env, atom_left, list);
+ if (state & SDL_BUTTON_MMASK)
+ list = enif_make_list_cell(env, atom_middle, list);
+ if (state & SDL_BUTTON_RMASK)
+ list = enif_make_list_cell(env, atom_right, list);
+ if (state & SDL_BUTTON_X1MASK)
+ list = enif_make_list_cell(env, atom_x1, list);
+ if (state & SDL_BUTTON_X2MASK)
+ list = enif_make_list_cell(env, atom_x2, list);
+
+ return enif_make_tuple3(env,
+ enif_make_int(env, x),
+ enif_make_int(env, y),
+ list
+ );
+}
+
+// capture_mouse
+
+NIF_CALL_HANDLER(thread_capture_mouse)
+{
+ if (SDL_CaptureMouse((long)args[0]))
+ return sdl_error_tuple(env);
+
+ return atom_ok;
+}
+
+NIF_FUNCTION(capture_mouse)
+{
+ SDL_bool b;
+
+ BADARG_IF(!atom_to_bool(env, argv[0], &b));
+
+ return nif_thread_call(env, thread_capture_mouse, 1, b);
+}
+
+// get_global_mouse_state
+
+NIF_CALL_HANDLER(thread_get_global_mouse_state)
+{
+ Uint32 state;
+ int x, y;
+
+ state = SDL_GetGlobalMouseState(&x, &y);
+
+ return get_mouse_state_common(env, x, y, state);
+}
+
+NIF_FUNCTION(get_global_mouse_state)
+{
+ return nif_thread_call(env, thread_get_global_mouse_state, 0);
+}
+
+// get_mouse_focus
+
+NIF_CALL_HANDLER(thread_get_mouse_focus)
+{
+ SDL_Window* window;
+
+ window = SDL_GetMouseFocus();
+
+ if (!window)
+ return atom_undefined;
+
+ return esdl2_windows_find(env, window);
+}
+
+NIF_FUNCTION(get_mouse_focus)
+{
+ return nif_thread_call(env, thread_get_mouse_focus, 0);
+}
+
+// get_mouse_state
+
+NIF_CALL_HANDLER(thread_get_mouse_state)
+{
+ Uint32 state;
+ int x, y;
+
+ state = SDL_GetMouseState(&x, &y);
+
+ return get_mouse_state_common(env, x, y, state);
+}
+
+NIF_FUNCTION(get_mouse_state)
+{
+ return nif_thread_call(env, thread_get_mouse_state, 0);
+}
+
+// get_relative_mouse_mode
+
+NIF_CALL_HANDLER(thread_get_relative_mouse_mode)
+{
+ if (SDL_GetRelativeMouseMode())
+ return atom_true;
+
+ return atom_false;
+}
+
+NIF_FUNCTION(get_relative_mouse_mode)
+{
+ return nif_thread_call(env, thread_get_relative_mouse_mode, 0);
+}
+
+// get_relative_mouse_state
+
+NIF_CALL_HANDLER(thread_get_relative_mouse_state)
+{
+ Uint32 state;
+ int x, y;
+
+ state = SDL_GetRelativeMouseState(&x, &y);
+
+ return get_mouse_state_common(env, x, y, state);
+}
+
+NIF_FUNCTION(get_relative_mouse_state)
+{
+ return nif_thread_call(env, thread_get_relative_mouse_state, 0);
+}
+
+// set_relative_mouse_mode
+
+NIF_CALL_HANDLER(thread_set_relative_mouse_mode)
+{
+ if (SDL_SetRelativeMouseMode((long)args[0]))
+ return sdl_error_tuple(env);
+
+ return atom_ok;
+}
+
+NIF_FUNCTION(set_relative_mouse_mode)
+{
+ SDL_bool b;
+
+ BADARG_IF(!atom_to_bool(env, argv[0], &b));
+
+ return nif_thread_call(env, thread_set_relative_mouse_mode, 1, b);
+}
+
+// warp_mouse_global
+
+NIF_CALL_HANDLER(thread_warp_mouse_global)
+{
+ if (SDL_WarpMouseGlobal((long)args[0], (long)args[1]))
+ return sdl_error_tuple(env);
+
+ return atom_ok;
+}
+
+NIF_FUNCTION(warp_mouse_global)
+{
+ int x, y;
+
+ BADARG_IF(!enif_get_int(env, argv[0], &x));
+ BADARG_IF(!enif_get_int(env, argv[1], &y));
+
+ return nif_thread_call(env, thread_warp_mouse_global, 2, x, y);
+}
+
+// warp_mouse_in_window
+
+NIF_CAST_HANDLER(thread_warp_mouse_in_window)
+{
+ SDL_WarpMouseInWindow(args[0], (long)args[1], (long)args[2]);
+}
+
+NIF_FUNCTION(warp_mouse_in_window)
+{
+ void* window_res;
+ int x, y;
+
+ BADARG_IF(!enif_get_resource(env, argv[0], res_Window, &window_res));
+ BADARG_IF(!enif_get_int(env, argv[1], &x));
+ BADARG_IF(!enif_get_int(env, argv[2], &y));
+
+ return nif_thread_cast(env, thread_warp_mouse_in_window, 3,
+ NIF_RES_GET(Window, window_res), x, y);
+}
diff --git a/c_src/sdl_renderer.c b/c_src/sdl_renderer.c
index 5344199..81e60c4 100644
--- a/c_src/sdl_renderer.c
+++ b/c_src/sdl_renderer.c
@@ -16,8 +16,10 @@
void dtor_Renderer(ErlNifEnv* env, void* obj)
{
- SDL_DestroyRenderer(NIF_RES_GET(Renderer, obj));
- enif_release_resource(NIF_RES_DEP(Renderer, obj));
+ SDL_Renderer* renderer = NIF_RES_GET(Renderer, obj);
+
+ SDL_DestroyRenderer(renderer);
+ esdl2_renderers_remove(renderer);
}
#define RENDERER_FLAGS(F) \
@@ -91,14 +93,16 @@ static int map_to_rect(ErlNifEnv* env, ERL_NIF_TERM map, SDL_Rect* rect)
NIF_CALL_HANDLER(thread_create_renderer)
{
SDL_Renderer* renderer;
+ obj_Renderer* res;
ERL_NIF_TERM term;
renderer = SDL_CreateRenderer(NIF_RES_GET(Window, args[0]), (long)args[1], (long)args[2]);
if (!renderer)
return sdl_error_tuple(env);
- enif_keep_resource(args[0]);
- NIF_RES_TO_TERM_WITH_DEP(Renderer, renderer, term, args[0]);
+ NIF_RES_TO_PTR_AND_TERM(Renderer, renderer, res, term);
+
+ esdl2_renderers_insert(renderer, res, args[0]);
return enif_make_tuple2(env,
atom_ok,
diff --git a/c_src/sdl_window.c b/c_src/sdl_window.c
index ef3647b..c286da0 100644
--- a/c_src/sdl_window.c
+++ b/c_src/sdl_window.c
@@ -14,9 +14,13 @@
#include "esdl2.h"
+// @todo These operations should probably occur in the thread.
void dtor_Window(ErlNifEnv* env, void* obj)
{
- SDL_DestroyWindow(NIF_RES_GET(Window, obj));
+ SDL_Window* window = NIF_RES_GET(Window, obj);
+
+ SDL_DestroyWindow(window);
+ esdl2_windows_remove(window);
}
#define WINDOW_FLAGS(F) \
@@ -33,7 +37,8 @@ void dtor_Window(ErlNifEnv* env, void* obj)
F(input_focus, SDL_WINDOW_INPUT_FOCUS) \
F(mouse_focus, SDL_WINDOW_MOUSE_FOCUS) \
F(foreign, SDL_WINDOW_FOREIGN) \
- F(allow_high_dpi, SDL_WINDOW_ALLOW_HIGHDPI)
+ F(allow_high_dpi, SDL_WINDOW_ALLOW_HIGHDPI) \
+ F(mouse_capture, SDL_WINDOW_MOUSE_CAPTURE)
static NIF_LIST_TO_FLAGS_FUNCTION(list_to_window_flags, Uint32, WINDOW_FLAGS)
static NIF_FLAGS_TO_LIST_FUNCTION(window_flags_to_list, Uint32, WINDOW_FLAGS)
@@ -56,6 +61,7 @@ static NIF_ATOM_TO_ENUM_FUNCTION(atom_to_window_fullscreen, Uint32, WINDOW_FULLS
NIF_CALL_HANDLER(thread_create_window)
{
SDL_Window* window;
+ obj_Window* res;
ERL_NIF_TERM term;
window = SDL_CreateWindow(args[0], (long)args[1], (long)args[2], (long)args[3], (long)args[4], (long)args[5]);
@@ -65,7 +71,9 @@ NIF_CALL_HANDLER(thread_create_window)
if (!window)
return sdl_error_tuple(env);
- NIF_RES_TO_TERM(Window, window, term);
+ NIF_RES_TO_PTR_AND_TERM(Window, window, res, term);
+
+ esdl2_windows_insert(window, res);
return enif_make_tuple2(env,
atom_ok,
diff --git a/ebin/esdl2.app b/ebin/esdl2.app
index c794a76..7439c29 100644
--- a/ebin/esdl2.app
+++ b/ebin/esdl2.app
@@ -1,7 +1,7 @@
{application, 'esdl2', [
{description, "SDL2 Erlang NIF."},
{vsn, "0.1.0"},
- {modules, ['esdl2','esdl2_app','esdl2_callbacks','esdl2_sup','sdl','sdl_clipboard','sdl_cpu_info','sdl_events','sdl_filesystem','sdl_gl','sdl_hints','sdl_keyboard','sdl_power','sdl_renderer','sdl_surface','sdl_texture','sdl_version','sdl_window']},
+ {modules, ['esdl2','esdl2_app','esdl2_callbacks','esdl2_sup','sdl','sdl_clipboard','sdl_cpu_info','sdl_events','sdl_filesystem','sdl_gl','sdl_hints','sdl_keyboard','sdl_mouse','sdl_power','sdl_renderer','sdl_surface','sdl_texture','sdl_version','sdl_window']},
{registered, [esdl2_sup]},
{applications, [kernel,stdlib]},
{mod, {esdl2_app, []}},
diff --git a/erlang.mk b/erlang.mk
index 64aaa4e..e3b4664 100644
--- a/erlang.mk
+++ b/erlang.mk
@@ -15,8 +15,10 @@
.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)))
+export ERLANG_MK_FILENAME
-ERLANG_MK_VERSION = 2017.04.25-6-g5922969
+ERLANG_MK_VERSION = 2017.08.28-22-gf545564
+ERLANG_MK_WITHOUT =
# Make 3.81 and 3.82 are deprecated.
@@ -183,19 +185,101 @@ ERLANG_MK_COMMIT ?=
ERLANG_MK_BUILD_CONFIG ?= build.config
ERLANG_MK_BUILD_DIR ?= .erlang.mk.build
+erlang-mk: WITHOUT ?= $(ERLANG_MK_WITHOUT)
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)
+ $(MAKE) -C $(ERLANG_MK_BUILD_DIR) WITHOUT='$(strip $(WITHOUT))'
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.
+# Copyright (c) 2015-2017, Loïc Hoguin <[email protected]>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: distclean-kerl
+
+KERL_INSTALL_DIR ?= $(HOME)/erlang
+
+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
+
+define kerl_otp_target
+ifeq ($(wildcard $(KERL_INSTALL_DIR)/$(1)),)
+$(KERL_INSTALL_DIR)/$(1): $(KERL)
+ MAKEFLAGS="$(KERL_MAKEFLAGS)" $(KERL) build git $(OTP_GIT) $(1) $(1)
+ $(KERL) install $(1) $(KERL_INSTALL_DIR)/$(1)
+endif
+endef
+
+define kerl_hipe_target
+ifeq ($(wildcard $(KERL_INSTALL_DIR)/$1-native),)
+$(KERL_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 $(KERL_INSTALL_DIR)/$1-native
+endif
+endef
+
+$(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)
+
+distclean:: distclean-kerl
+
+distclean-kerl:
+ $(gen_verbose) rm -rf $(KERL)
+
+# Allow users to select which version of Erlang/OTP to use for a project.
+
+ERLANG_OTP ?=
+ERLANG_HIPE ?=
+
+# Use kerl to enforce a specific Erlang/OTP version for a project.
+ifneq ($(strip $(ERLANG_OTP)),)
+export PATH := $(KERL_INSTALL_DIR)/$(ERLANG_OTP)/bin:$(PATH)
+SHELL := env PATH=$(PATH) $(SHELL)
+$(eval $(call kerl_otp_target,$(ERLANG_OTP)))
+
+# Build Erlang/OTP only if it doesn't already exist.
+ifeq ($(wildcard $(KERL_INSTALL_DIR)/$(ERLANG_OTP))$(BUILD_ERLANG_OTP),)
+$(info Building Erlang/OTP $(ERLANG_OTP)... Please wait...)
+$(shell $(MAKE) $(KERL_INSTALL_DIR)/$(ERLANG_OTP) ERLANG_OTP=$(ERLANG_OTP) BUILD_ERLANG_OTP=1 >&2)
+endif
+
+else
+# Same for a HiPE enabled VM.
+ifneq ($(strip $(ERLANG_HIPE)),)
+export PATH := $(KERL_INSTALL_DIR)/$(ERLANG_HIPE)-native/bin:$(PATH)
+SHELL := env PATH=$(PATH) $(SHELL)
+$(eval $(call kerl_hipe_target,$(ERLANG_HIPE)))
+
+# Build Erlang/OTP only if it doesn't already exist.
+ifeq ($(wildcard $(KERL_INSTALL_DIR)/$(ERLANG_HIPE))$(BUILD_ERLANG_OTP),)
+$(info Building HiPE-enabled Erlang/OTP $(ERLANG_OTP)... Please wait...)
+$(shell $(MAKE) $(KERL_INSTALL_DIR)/$(ERLANG_HIPE) ERLANG_HIPE=$(ERLANG_HIPE) BUILD_ERLANG_OTP=1 >&2)
+endif
+
+endif
+endif
+
PACKAGES += aberth
pkg_aberth_name = aberth
pkg_aberth_description = Generic BERT-RPC server in Erlang
@@ -532,14 +616,6 @@ 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
@@ -940,14 +1016,6 @@ 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
@@ -1516,6 +1584,14 @@ pkg_erwa_fetch = git
pkg_erwa_repo = https://github.com/bwegh/erwa
pkg_erwa_commit = master
+PACKAGES += escalus
+pkg_escalus_name = escalus
+pkg_escalus_description = An XMPP client library in Erlang for conveniently testing XMPP servers
+pkg_escalus_homepage = https://github.com/esl/escalus
+pkg_escalus_fetch = git
+pkg_escalus_repo = https://github.com/esl/escalus
+pkg_escalus_commit = master
+
PACKAGES += espec
pkg_espec_name = espec
pkg_espec_description = ESpec: Behaviour driven development framework for Erlang
@@ -1908,14 +1984,6 @@ 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
@@ -1940,6 +2008,22 @@ pkg_grapherl_fetch = git
pkg_grapherl_repo = https://github.com/eproxus/grapherl
pkg_grapherl_commit = master
+PACKAGES += grpc
+pkg_grpc_name = grpc
+pkg_grpc_description = gRPC server in Erlang
+pkg_grpc_homepage = https://github.com/Bluehouse-Technology/grpc
+pkg_grpc_fetch = git
+pkg_grpc_repo = https://github.com/Bluehouse-Technology/grpc
+pkg_grpc_commit = master
+
+PACKAGES += grpc_client
+pkg_grpc_client_name = grpc_client
+pkg_grpc_client_description = gRPC client in Erlang
+pkg_grpc_client_homepage = https://github.com/Bluehouse-Technology/grpc_client
+pkg_grpc_client_fetch = git
+pkg_grpc_client_repo = https://github.com/Bluehouse-Technology/grpc_client
+pkg_grpc_client_commit = master
+
PACKAGES += gun
pkg_gun_name = gun
pkg_gun_description = Asynchronous SPDY, HTTP and Websocket client written in Erlang.
@@ -2020,6 +2104,14 @@ pkg_ibrowse_fetch = git
pkg_ibrowse_repo = https://github.com/cmullaparthi/ibrowse
pkg_ibrowse_commit = master
+PACKAGES += idna
+pkg_idna_name = idna
+pkg_idna_description = Erlang IDNA lib
+pkg_idna_homepage = https://github.com/benoitc/erlang-idna
+pkg_idna_fetch = git
+pkg_idna_repo = https://github.com/benoitc/erlang-idna
+pkg_idna_commit = master
+
PACKAGES += ierlang
pkg_ierlang_name = ierlang
pkg_ierlang_description = An Erlang language kernel for IPython.
@@ -2295,9 +2387,9 @@ 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_homepage = https://github.com/erlang-lager/lager
pkg_lager_fetch = git
-pkg_lager_repo = https://github.com/basho/lager
+pkg_lager_repo = https://github.com/erlang-lager/lager
pkg_lager_commit = master
PACKAGES += lager_amqp_backend
@@ -2311,9 +2403,9 @@ 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_homepage = https://github.com/erlang-lager/lager_syslog
pkg_lager_syslog_fetch = git
-pkg_lager_syslog_repo = https://github.com/basho/lager_syslog
+pkg_lager_syslog_repo = https://github.com/erlang-lager/lager_syslog
pkg_lager_syslog_commit = master
PACKAGES += lambdapad
@@ -3604,6 +3696,14 @@ pkg_stripe_fetch = git
pkg_stripe_repo = https://github.com/mattsta/stripe-erlang
pkg_stripe_commit = v1
+PACKAGES += subproc
+pkg_subproc_name = subproc
+pkg_subproc_description = unix subprocess manager with {active,once|false} modes
+pkg_subproc_homepage = http://dozzie.jarowit.net/trac/wiki/subproc
+pkg_subproc_fetch = git
+pkg_subproc_repo = https://github.com/dozzie/subproc
+pkg_subproc_commit = v0.1.0
+
PACKAGES += supervisor3
pkg_supervisor3_name = supervisor3
pkg_supervisor3_description = OTP supervisor with additional strategies
@@ -3732,6 +3832,14 @@ pkg_tirerl_fetch = git
pkg_tirerl_repo = https://github.com/inaka/tirerl
pkg_tirerl_commit = master
+PACKAGES += toml
+pkg_toml_name = toml
+pkg_toml_description = TOML (0.4.0) config parser
+pkg_toml_homepage = http://dozzie.jarowit.net/trac/wiki/TOML
+pkg_toml_fetch = git
+pkg_toml_repo = https://github.com/dozzie/toml
+pkg_toml_commit = v0.2.0
+
PACKAGES += traffic_tools
pkg_traffic_tools_name = traffic_tools
pkg_traffic_tools_description = Simple traffic limiting library
@@ -3775,9 +3883,9 @@ 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_homepage = https://github.com/triqng/triq
pkg_triq_fetch = git
-pkg_triq_repo = https://github.com/krestenkrab/triq
+pkg_triq_repo = https://github.com/triqng/triq.git
pkg_triq_commit = master
PACKAGES += tunctl
@@ -4118,6 +4226,26 @@ export DEPS_DIR
REBAR_DEPS_DIR = $(DEPS_DIR)
export REBAR_DEPS_DIR
+# External "early" plugins (see core/plugins.mk for regular plugins).
+# They both use the core_dep_plugin macro.
+
+define core_dep_plugin
+ifeq ($(2),$(PROJECT))
+-include $$(patsubst $(PROJECT)/%,%,$(1))
+else
+-include $(DEPS_DIR)/$(1)
+
+$(DEPS_DIR)/$(1): $(DEPS_DIR)/$(2) ;
+endif
+endef
+
+DEP_EARLY_PLUGINS ?=
+
+$(foreach p,$(DEP_EARLY_PLUGINS),\
+ $(eval $(if $(findstring /,$p),\
+ $(call core_dep_plugin,$p,$(firstword $(subst /, ,$p))),\
+ $(call core_dep_plugin,$p/early-plugins.mk,$p))))
+
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)))
@@ -4155,19 +4283,19 @@ endif
# 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 $$?; \
+ $(verbose) set -e; for dep in $(ALL_APPS_DIRS) ; do \
+ mkdir -p $$dep/ebin; \
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 \
+ $(verbose) set -e; 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 $$?; \
+ $(MAKE) -C $$dep IS_APP=1; \
fi \
done
@@ -4181,15 +4309,15 @@ 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 \
+ $(verbose) set -e; 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 $$?; \
+ $(MAKE) -C $$dep IS_DEP=1; \
else \
- echo "Error: No Makefile to build dependency $$dep."; \
+ echo "Error: No Makefile to build dependency $$dep." >&2; \
exit 2; \
fi \
fi \
@@ -4226,6 +4354,7 @@ define dep_autopatch
endef
define dep_autopatch2
+ ! test -f $(DEPS_DIR)/$1/ebin/$1.app || \
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 \
@@ -4244,11 +4373,15 @@ define dep_autopatch_noop
printf "noop:\n" > $(DEPS_DIR)/$(1)/Makefile
endef
-# Overwrite erlang.mk with the current file by default.
+# Replace "include erlang.mk" with a line that will load the parent Erlang.mk
+# if given. Do it for all 3 possible Makefile file names.
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
+ for f in Makefile makefile GNUmakefile; do \
+ if [ -f $(DEPS_DIR)/$1/$$f ]; then \
+ sed -i.bak s/'include *erlang.mk'/'include $$(if $$(ERLANG_MK_FILENAME),$$(ERLANG_MK_FILENAME),erlang.mk)'/ $(DEPS_DIR)/$1/$$f; \
+ fi \
+ done
endef
else
define dep_autopatch_erlang_mk
@@ -4313,6 +4446,10 @@ define dep_autopatch_rebar.erl
Write("C_SRC_TYPE = rebar\n"),
Write("DRV_CFLAGS = -fPIC\nexport DRV_CFLAGS\n"),
Write(["ERLANG_ARCH = ", rebar_utils:wordsize(), "\nexport ERLANG_ARCH\n"]),
+ ToList = fun
+ (V) when is_atom(V) -> atom_to_list(V);
+ (V) when is_list(V) -> "'\\"" ++ V ++ "\\"'"
+ end,
fun() ->
Write("ERLC_OPTS = +debug_info\nexport ERLC_OPTS\n"),
case lists:keyfind(erl_opts, 1, Conf) of
@@ -4320,16 +4457,18 @@ define dep_autopatch_rebar.erl
{_, ErlOpts} ->
lists:foreach(fun
({d, D}) ->
- Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n");
+ Write("ERLC_OPTS += -D" ++ ToList(D) ++ "=1\n");
+ ({d, DKey, DVal}) ->
+ Write("ERLC_OPTS += -D" ++ ToList(DKey) ++ "=" ++ ToList(DVal) ++ "\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");
+ true -> Write("ERLC_OPTS += -D" ++ ToList(D) ++ "=1\n");
false -> ok
end;
({parse_transform, PT}) ->
- Write("ERLC_OPTS += +'{parse_transform, " ++ atom_to_list(PT) ++ "}'\n");
+ Write("ERLC_OPTS += +'{parse_transform, " ++ ToList(PT) ++ "}'\n");
(_) -> ok
end, ErlOpts)
end,
@@ -4491,7 +4630,7 @@ define dep_autopatch_rebar.erl
end,
[PortSpec(S) || S <- PortSpecs]
end,
- Write("\ninclude $(call core_relpath,$(dir $(ERLANG_MK_FILENAME)),$(DEPS_DIR)/app)/erlang.mk"),
+ Write("\ninclude $$\(if $$\(ERLANG_MK_FILENAME),$$\(ERLANG_MK_FILENAME),erlang.mk)"),
RunPlugin = fun(Plugin, Step) ->
case erlang:function_exported(Plugin, Step, 2) of
false -> ok;
@@ -4542,8 +4681,11 @@ 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, Conf0} = file:consult(AppSrc),
+ Bindings0 = erl_eval:new_bindings(),
+ Bindings1 = erl_eval:add_binding('CONFIG', Conf0, Bindings0),
+ Bindings = erl_eval:add_binding('SCRIPT', AppSrcScript, Bindings1),
+ {ok, [Conf]} = file:script(AppSrcScript, Bindings),
ok = file:write_file(AppSrc, io_lib:format("~p.~n", [Conf])),
halt()
endef
@@ -4556,7 +4698,11 @@ define dep_autopatch_appsrc.erl
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,
+ L2 = case lists:keyfind(vsn, 1, L1) of
+ {_, git} -> lists:keyreplace(vsn, 1, L1, {vsn, "git"});
+ {_, {cmd, _}} -> lists:keyreplace(vsn, 1, L1, {vsn, "cmd"});
+ _ -> 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
@@ -4586,6 +4732,10 @@ define dep_fetch_cp
cp -R $(call dep_repo,$(1)) $(DEPS_DIR)/$(call dep_name,$(1));
endef
+define dep_fetch_ln
+ ln -s $(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; \
@@ -4621,7 +4771,7 @@ $(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)."; \
+ echo "Error: Dependency" $(DEP_STR) "conflicts with application found in $(APPS_DIR)/$(DEP_NAME)." >&2; \
exit 17; \
fi
$(verbose) mkdir -p $(DEPS_DIR)
@@ -4663,15 +4813,15 @@ ifndef IS_APP
clean:: clean-apps
clean-apps:
- $(verbose) for dep in $(ALL_APPS_DIRS) ; do \
- $(MAKE) -C $$dep clean IS_APP=1 || exit $$?; \
+ $(verbose) set -e; for dep in $(ALL_APPS_DIRS) ; do \
+ $(MAKE) -C $$dep clean IS_APP=1; \
done
distclean:: distclean-apps
distclean-apps:
- $(verbose) for dep in $(ALL_APPS_DIRS) ; do \
- $(MAKE) -C $$dep distclean IS_APP=1 || exit $$?; \
+ $(verbose) set -e; for dep in $(ALL_APPS_DIRS) ; do \
+ $(MAKE) -C $$dep distclean IS_APP=1; \
done
endif
@@ -4710,10 +4860,9 @@ 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"}])
+ [{output_include_dir, "./include"},
+ {output_src_dir, "./ebin"}])
end || F <- string:tokens("$(1)", " ")],
halt().
endef
@@ -4794,7 +4943,7 @@ define app_file
{id$(comma)$(space)"$(1)"}$(comma))
{modules, [$(call comma_list,$(2))]},
{registered, []},
- {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(DEPS))]},
+ {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(foreach dep,$(DEPS),$(call dep_name,$(dep))))]},
{env, $(subst \,\\,$(PROJECT_ENV))}$(if $(findstring {,$(PROJECT_APP_EXTRA_KEYS)),$(comma)$(newline)$(tab)$(subst \,\\,$(PROJECT_APP_EXTRA_KEYS)),)
]}.
endef
@@ -4806,7 +4955,7 @@ define app_file
{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))]},
+ {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(foreach dep,$(DEPS),$(call dep_name,$(dep))))]},
{mod, {$(PROJECT_MOD), []}},
{env, $(subst \,\\,$(PROJECT_ENV))}$(if $(findstring {,$(PROJECT_APP_EXTRA_KEYS)),$(comma)$(newline)$(tab)$(subst \,\\,$(PROJECT_APP_EXTRA_KEYS)),)
]}.
@@ -5037,7 +5186,7 @@ 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
+ $(verbose) set -e; for dep in $(ALL_DOC_DEPS_DIRS) ; do $(MAKE) -C $$dep; done
endif
# Copyright (c) 2015-2016, Loïc Hoguin <[email protected]>
@@ -5057,7 +5206,7 @@ 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
+ $(verbose) set -e; for dep in $(ALL_REL_DEPS_DIRS) ; do $(MAKE) -C $$dep; done
endif
# Copyright (c) 2015-2016, Loïc Hoguin <[email protected]>
@@ -5082,7 +5231,7 @@ 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
+ $(verbose) set -e; for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep IS_DEP=1; done
endif
ifneq ($(wildcard $(TEST_DIR)),)
@@ -5227,7 +5376,7 @@ 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/;)
+ install -g `id -g` -o `id -u` -m 0644 doc/man$s/*.gz $(MAN_INSTALL_PATH)/man$s/;)
distclean-asciidoc-manual:
$(gen_verbose) rm -rf $(addprefix doc/man,$(MAN_SECTIONS))
@@ -5927,10 +6076,10 @@ else
$(call render_template,bs_erl_nif,src/$n.erl)
endif
-# Copyright (c) 2015-2016, Loïc Hoguin <[email protected]>
+# Copyright (c) 2015-2017, Loïc Hoguin <[email protected]>
# This file is part of erlang.mk and subject to the terms of the ISC License.
-.PHONY: ci ci-prepare ci-setup distclean-kerl
+.PHONY: ci ci-prepare ci-setup
CI_OTP ?=
CI_HIPE ?=
@@ -5948,24 +6097,9 @@ 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-prepare: $(addprefix $(KERL_INSTALL_DIR)/,$(CI_OTP) $(addsuffix -native,$(CI_HIPE)))
ci-setup::
@@ -5975,10 +6109,10 @@ ci_verbose_0 = @echo " CI " $(1);
ci_verbose = $(ci_verbose_$(V))
define ci_target
-ci-$1: $(CI_INSTALL_DIR)/$2
+ci-$1: $(KERL_INSTALL_DIR)/$2
$(verbose) $(MAKE) --no-print-directory clean
$(ci_verbose) \
- PATH="$(CI_INSTALL_DIR)/$2/bin:$(PATH)" \
+ PATH="$(KERL_INSTALL_DIR)/$2/bin:$(PATH)" \
CI_OTP_RELEASE="$1" \
CT_OPTS="-label $1" \
CI_VM="$3" \
@@ -5990,32 +6124,8 @@ $(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)
+$(foreach otp,$(CI_OTP),$(eval $(call kerl_otp_target,$(otp))))
+$(foreach otp,$(sort $(CI_HIPE) $(CI_ERLLLVM)),$(eval $(call kerl_hipe_target,$(otp))))
help::
$(verbose) printf "%s\n" "" \
@@ -6025,10 +6135,6 @@ help::
"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 <[email protected]>
@@ -6074,10 +6180,13 @@ CT_RUN = ct_run \
ifeq ($(CT_SUITES),)
ct: $(if $(IS_APP),,apps-ct)
else
+# We do not run tests if we are in an apps/* with no test directory.
+ifneq ($(IS_APP)$(wildcard $(TEST_DIR)),1)
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
+endif
ifneq ($(ALL_APPS_DIRS),)
define ct_app_target
@@ -6181,10 +6290,21 @@ endif
# Configuration.
EDOC_OPTS ?=
+EDOC_SRC_DIRS ?=
+EDOC_OUTPUT ?= doc
+
+define edoc.erl
+ SrcPaths = lists:foldl(fun(P, Acc) ->
+ filelib:wildcard(atom_to_list(P) ++ "/{src,c_src}") ++ Acc
+ end, [], [$(call comma_list,$(patsubst %,'%',$(EDOC_SRC_DIRS)))]),
+ DefaultOpts = [{dir, "$(EDOC_OUTPUT)"}, {source_path, SrcPaths}, {subpackages, false}],
+ edoc:application($(1), ".", [$(2)] ++ DefaultOpts),
+ halt(0).
+endef
# Core targets.
-ifneq ($(wildcard doc/overview.edoc),)
+ifneq ($(strip $(EDOC_SRC_DIRS)$(wildcard doc/overview.edoc)),)
docs:: edoc
endif
@@ -6193,10 +6313,10 @@ distclean:: distclean-edoc
# Plugin-specific targets.
edoc: distclean-edoc doc-deps
- $(gen_verbose) $(ERL) -eval 'edoc:application($(PROJECT), ".", [$(EDOC_OPTS)]), halt().'
+ $(gen_verbose) $(call erlang,$(call edoc.erl,$(PROJECT),$(EDOC_OPTS)))
distclean-edoc:
- $(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info
+ $(gen_verbose) rm -f $(EDOC_OUTPUT)/*.css $(EDOC_OUTPUT)/*.html $(EDOC_OUTPUT)/*.png $(EDOC_OUTPUT)/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.
@@ -6348,7 +6468,7 @@ define eunit.erl
case "$(COVER)" of
"" -> ok;
_ ->
- cover:export("eunit.coverdata")
+ cover:export("$(COVER_DATA_DIR)/eunit.coverdata")
end,
halt()
endef
@@ -6357,10 +6477,10 @@ EUNIT_ERL_OPTS += -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin $(APPS_DIR)/*/ebin $(CURDIR
ifdef t
ifeq (,$(findstring :,$(t)))
-eunit: test-build
+eunit: test-build cover-data-dir
$(gen_verbose) $(call erlang,$(call eunit.erl,['$(t)']),$(EUNIT_ERL_OPTS))
else
-eunit: test-build
+eunit: test-build cover-data-dir
$(gen_verbose) $(call erlang,$(call eunit.erl,fun $(t)/0),$(EUNIT_ERL_OPTS))
endif
else
@@ -6370,7 +6490,7 @@ 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)
+eunit: test-build $(if $(IS_APP),,apps-eunit) cover-data-dir
$(gen_verbose) $(call erlang,$(call eunit.erl,[$(call comma_list,$(EUNIT_MODS))]),$(EUNIT_ERL_OPTS))
ifneq ($(ALL_APPS_DIRS),)
@@ -6381,6 +6501,60 @@ apps-eunit:
endif
endif
+# Copyright (c) 2015-2017, Loïc Hoguin <[email protected]>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+ifeq ($(filter proper,$(DEPS) $(TEST_DEPS)),proper)
+.PHONY: proper
+
+# Targets.
+
+tests:: proper
+
+define proper_check.erl
+ code:add_pathsa(["$(call core_native_path,$(CURDIR)/ebin)", "$(call core_native_path,$(DEPS_DIR)/*/ebin)"]),
+ Module = fun(M) ->
+ [true] =:= lists:usort([
+ case atom_to_list(F) of
+ "prop_" ++ _ ->
+ io:format("Testing ~p:~p/0~n", [M, F]),
+ proper:quickcheck(M:F(), nocolors);
+ _ ->
+ true
+ end
+ || {F, 0} <- M:module_info(exports)])
+ end,
+ try
+ case $(1) of
+ all -> [true] =:= lists:usort([Module(M) || M <- [$(call comma_list,$(3))]]);
+ module -> Module($(2));
+ function -> proper:quickcheck($(2), nocolors)
+ end
+ of
+ true -> halt(0);
+ _ -> halt(1)
+ catch error:undef ->
+ io:format("Undefined property or module?~n~p~n", [erlang:get_stacktrace()]),
+ halt(0)
+ end.
+endef
+
+ifdef t
+ifeq (,$(findstring :,$(t)))
+proper: test-build
+ $(verbose) $(call erlang,$(call proper_check.erl,module,$(t)))
+else
+proper: test-build
+ $(verbose) echo Testing $(t)/0
+ $(verbose) $(call erlang,$(call proper_check.erl,function,$(t)()))
+endif
+else
+proper: test-build
+ $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename $(wildcard ebin/*.beam))))))
+ $(gen_verbose) $(call erlang,$(call proper_check.erl,all,undefined,$(MODULES)))
+endif
+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.
@@ -6391,9 +6565,10 @@ endif
RELX ?= $(ERLANG_MK_TMP)/relx
RELX_CONFIG ?= $(CURDIR)/relx.config
-RELX_URL ?= https://github.com/erlware/relx/releases/download/v3.19.0/relx
+RELX_URL ?= https://github.com/erlware/relx/releases/download/v3.23.0/relx
RELX_OPTS ?=
RELX_OUTPUT_DIR ?= _rel
+RELX_REL_EXT ?=
RELX_TAR ?= 1
ifdef SFX
@@ -6436,7 +6611,7 @@ distclean-relx-rel:
# Run target.
ifeq ($(wildcard $(RELX_CONFIG)),)
-run:
+run::
else
define get_relx_release.erl
@@ -6456,8 +6631,12 @@ 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
+ifeq ($(PLATFORM),msys2)
+RELX_REL_EXT := .cmd
+endif
+
+run:: all
+ $(verbose) $(RELX_OUTPUT_DIR)/$(RELX_REL_NAME)/bin/$(RELX_REL_NAME)$(RELX_REL_EXT) console
help::
$(verbose) printf "%s\n" "" \
@@ -6492,7 +6671,7 @@ help::
$(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
+ $(verbose) set -e; 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)
@@ -6522,7 +6701,10 @@ ifeq ($(filter triq,$(DEPS) $(TEST_DEPS)),triq)
tests:: triq
define triq_check.erl
- code:add_pathsa(["$(call core_native_path,$(CURDIR)/ebin)", "$(call core_native_path,$(DEPS_DIR)/*/ebin)"]),
+ code:add_pathsa([
+ "$(call core_native_path,$(CURDIR)/ebin)",
+ "$(call core_native_path,$(DEPS_DIR)/*/ebin)",
+ "$(call core_native_path,$(TEST_DIR))"]),
try
case $(1) of
all -> [true] =:= lists:usort([triq:check(M) || M <- [$(call comma_list,$(3))]]);
@@ -6533,7 +6715,7 @@ define triq_check.erl
true -> halt(0);
_ -> halt(1)
catch error:undef ->
- io:format("Undefined property or module~n"),
+ io:format("Undefined property or module?~n~p~n", [erlang:get_stacktrace()]),
halt(0)
end.
endef
@@ -6549,7 +6731,8 @@ triq: test-build
endif
else
triq: test-build
- $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename $(wildcard ebin/*.beam))))))
+ $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename \
+ $(wildcard ebin/*.beam) $(call core_find,$(TEST_DIR)/,*.beam))))))
$(gen_verbose) $(call erlang,$(call triq_check.erl,all,undefined,$(MODULES)))
endif
endif
@@ -6571,14 +6754,14 @@ endif
XREFR ?= $(CURDIR)/xrefr
export XREFR
-XREFR_URL ?= https://github.com/inaka/xref_runner/releases/download/0.2.2/xrefr
+XREFR_URL ?= https://github.com/inaka/xref_runner/releases/download/1.1.0/xrefr
# Core targets.
help::
- $(verbose) printf "%s\n" "" \
- "Xref targets:" \
- " xref Run Xrefr using $XREF_CONFIG as config file if defined"
+ $(verbose) printf '%s\n' '' \
+ 'Xref targets:' \
+ ' xref Run Xrefr using $$XREF_CONFIG as config file if defined'
distclean:: distclean-xref
@@ -6598,26 +6781,25 @@ distclean-xref:
# Copyright (c) 2015, Viktor Söderqvist <[email protected]>
# This file is part of erlang.mk and subject to the terms of the ISC License.
-COVER_REPORT_DIR = cover
+COVER_REPORT_DIR ?= cover
+COVER_DATA_DIR ?= $(CURDIR)
# Hook in coverage to ct
ifdef COVER
ifdef CT_RUN
-# All modules in 'ebin'
-COVER_MODS = $(notdir $(basename $(call core_ls,ebin/*.beam)))
-
+ifneq ($(wildcard $(TEST_DIR)),)
test-build:: $(TEST_DIR)/ct.cover.spec
-$(TEST_DIR)/ct.cover.spec:
- $(verbose) echo Cover mods: $(COVER_MODS)
+$(TEST_DIR)/ct.cover.spec: cover-data-dir
$(gen_verbose) printf "%s\n" \
- '{incl_mods,[$(subst $(space),$(comma),$(COVER_MODS))]}.' \
- '{export,"$(CURDIR)/ct.coverdata"}.' > $@
+ "{incl_app, '$(PROJECT)', details}." \
+ '{export,"$(abspath $(COVER_DATA_DIR))/ct.coverdata"}.' > $@
CT_RUN += -cover $(TEST_DIR)/ct.cover.spec
endif
endif
+endif
# Core targets
@@ -6626,6 +6808,13 @@ ifneq ($(COVER_REPORT_DIR),)
tests::
$(verbose) $(MAKE) --no-print-directory cover-report
endif
+
+cover-data-dir: | $(COVER_DATA_DIR)
+
+$(COVER_DATA_DIR):
+ $(verbose) mkdir -p $(COVER_DATA_DIR)
+else
+cover-data-dir:
endif
clean:: coverdata-clean
@@ -6639,7 +6828,7 @@ help::
"Cover targets:" \
" cover-report Generate a HTML coverage report from previously collected" \
" cover data." \
- " all.coverdata Merge {eunit,ct}.coverdata into one coverdata file." \
+ " all.coverdata Merge all coverdata files into all.coverdata." \
"" \
"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" \
@@ -6648,17 +6837,20 @@ help::
# Plugin specific targets
-COVERDATA = $(filter-out all.coverdata,$(wildcard *.coverdata))
+COVERDATA = $(filter-out $(COVER_DATA_DIR)/all.coverdata,$(wildcard $(COVER_DATA_DIR)/*.coverdata))
.PHONY: coverdata-clean
coverdata-clean:
- $(gen_verbose) rm -f *.coverdata ct.cover.spec
+ $(gen_verbose) rm -f $(COVER_DATA_DIR)/*.coverdata $(TEST_DIR)/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).'
+define cover_export.erl
+ $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),)
+ cover:export("$(COVER_DATA_DIR)/$@"), halt(0).
+endef
+
+all.coverdata: $(COVERDATA) cover-data-dir
+ $(gen_verbose) $(call erlang,$(cover_export.erl))
# 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.
@@ -6668,6 +6860,7 @@ ifneq ($(COVER_REPORT_DIR),)
cover-report-clean:
$(gen_verbose) rm -rf $(COVER_REPORT_DIR)
+ $(if $(shell ls -A $(COVER_DATA_DIR)/),,$(verbose) rmdir $(COVER_DATA_DIR))
ifeq ($(COVERDATA),)
cover-report:
@@ -6676,7 +6869,7 @@ 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 \
+ grep -H -e '^\s*-include.*include/eunit\.hrl"' src/*.erl \
| sed "s/^src\/\(.*\)\.erl:.*/'\1'/" | uniq))
define cover_report.erl
@@ -6711,7 +6904,7 @@ define cover_report.erl
endef
cover-report:
- $(gen_verbose) mkdir -p $(COVER_REPORT_DIR)
+ $(verbose) mkdir -p $(COVER_REPORT_DIR)
$(gen_verbose) $(call erlang,$(cover_report.erl))
endif
@@ -6771,12 +6964,6 @@ endif
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))),\
@@ -6849,22 +7036,20 @@ ifeq ($(IS_APP)$(IS_DEP),)
$(verbose) rm -f $(ERLANG_MK_RECURSIVE_TMP_LIST)
endif
ifndef IS_APP
- $(verbose) for dep in $(ALL_APPS_DIRS) ; do \
+ $(verbose) set -e; for dep in $(ALL_APPS_DIRS) ; do \
$(MAKE) -C $$dep $@ \
IS_APP=1 \
- ERLANG_MK_RECURSIVE_TMP_LIST=$(ERLANG_MK_RECURSIVE_TMP_LIST) \
- || exit $$?; \
+ ERLANG_MK_RECURSIVE_TMP_LIST=$(ERLANG_MK_RECURSIVE_TMP_LIST); \
done
endif
- $(verbose) for dep in $^ ; do \
+ $(verbose) set -e; 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)$$" \
+ if grep -qs -E "^[[:blank:]]*include[[:blank:]]+(erlang\.mk|.*/erlang\.mk|.*ERLANG_MK_FILENAME.*)$$" \
$$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 $$?; \
+ ERLANG_MK_RECURSIVE_TMP_LIST=$(ERLANG_MK_RECURSIVE_TMP_LIST); \
fi \
fi \
done
diff --git a/examples/hello_sdl/hello_sdl.erl b/examples/hello_sdl/hello_sdl.erl
index 4e06baf..54e0f36 100644
--- a/examples/hello_sdl/hello_sdl.erl
+++ b/examples/hello_sdl/hello_sdl.erl
@@ -4,7 +4,7 @@
-export([run/0]).
run() ->
- spawn_opt(fun init/0, [{scheduler, 0}]).
+ spawn(fun init/0).
init() ->
ok = sdl:start([video]),
diff --git a/src/esdl2.erl b/src/esdl2.erl
index 7bacb71..0b1b456 100644
--- a/src/esdl2.erl
+++ b/src/esdl2.erl
@@ -64,6 +64,17 @@
-export([start_text_input/0]).
-export([stop_text_input/0]).
+%% sdl_mouse
+-export([capture_mouse/1]).
+-export([get_global_mouse_state/0]).
+-export([get_mouse_focus/0]).
+-export([get_mouse_state/0]).
+-export([get_relative_mouse_mode/0]).
+-export([get_relative_mouse_state/0]).
+-export([set_relative_mouse_mode/1]).
+-export([warp_mouse_global/2]).
+-export([warp_mouse_in_window/3]).
+
%% sdl_power
-export([get_power_info/0]).
@@ -269,6 +280,35 @@ start_text_input() ->
stop_text_input() ->
erlang:nif_error({not_loaded, ?MODULE}).
+%% sdl_mouse
+
+capture_mouse(_) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+get_global_mouse_state() ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+get_mouse_focus() ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+get_mouse_state() ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+get_relative_mouse_mode() ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+get_relative_mouse_state() ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+set_relative_mouse_mode(_) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+warp_mouse_global(_, _) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+warp_mouse_in_window(_, _, _) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
%% sdl_power
get_power_info() ->
diff --git a/src/sdl_mouse.erl b/src/sdl_mouse.erl
new file mode 100644
index 0000000..d6c3815
--- /dev/null
+++ b/src/sdl_mouse.erl
@@ -0,0 +1,72 @@
+%% Copyright (c) 2017, 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.
+
+-module(sdl_mouse).
+
+-export([capture/1]).
+-export([get_focused_window/0]).
+-export([get_global_state/0]).
+-export([get_relative_mode/0]).
+-export([get_relative_state/0]).
+-export([get_state/0]).
+-export([set_relative_mode/1]).
+-export([warp/2]).
+-export([warp/3]).
+
+-spec capture(boolean()) -> ok | sdl:error().
+capture(Bool) ->
+ esdl2:capture_mouse(Bool),
+ receive {'_nif_thread_ret_', Ret} -> Ret end.
+
+-spec get_focused_window() -> sdl_window:window() | undefined.
+get_focused_window() ->
+ esdl2:get_mouse_focus(),
+ receive {'_nif_thread_ret_', Ret} -> Ret end.
+
+-spec get_global_state()
+ -> {integer(), integer(), [left | middle | right | x1 | x2]}.
+get_global_state() ->
+ esdl2:get_global_mouse_state(),
+ receive {'_nif_thread_ret_', Ret} -> Ret end.
+
+-spec get_relative_mode() -> boolean().
+get_relative_mode() ->
+ esdl2:get_relative_mouse_mode(),
+ receive {'_nif_thread_ret_', Ret} -> Ret end.
+
+-spec get_relative_state()
+ -> {integer(), integer(), [left | middle | right | x1 | x2]}.
+get_relative_state() ->
+ esdl2:get_relative_mouse_state(),
+ receive {'_nif_thread_ret_', Ret} -> Ret end.
+
+-spec get_state()
+ -> {integer(), integer(), [left | middle | right | x1 | x2]}.
+get_state() ->
+ esdl2:get_mouse_state(),
+ receive {'_nif_thread_ret_', Ret} -> Ret end.
+
+-spec set_relative_mode(boolean()) -> ok | sdl:error().
+set_relative_mode(Bool) ->
+ esdl2:set_relative_mouse_mode(Bool),
+ receive {'_nif_thread_ret_', Ret} -> Ret end.
+
+-spec warp(integer(), integer()) -> ok | sdl:error().
+warp(X, Y) ->
+ esdl2:warp_mouse_global(X, Y),
+ receive {'_nif_thread_ret_', Ret} -> Ret end.
+
+-spec warp(sdl_window:window(), integer(), integer()) -> ok.
+warp(Window, X, Y) ->
+ esdl2:warp_mouse_in_window(Window, X, Y).