Encountering errors when compiling NIF using MinGW on Windows

I wrote a very simple example and tried to compile it using MinGW, but I encountered some errors. I understand that using VS (Visual Studio) can make things easier, but its installation size is too large.

nif_test.c

#include "erl_nif.h"

static ERL_NIF_TERM add_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    int a, b;

    if (!enif_get_int(env, argv[0], &a) || !enif_get_int(env, argv[1], &b)) {
        return enif_make_badarg(env);
    }

    return enif_make_int(env, a + b);
}

static ErlNifFunc nif_funcs[] = {
    {"add", 2, add_nif}
};

ERL_NIF_INIT(nif_test, nif_funcs, NULL, NULL, NULL, NULL)
$ gcc -shared -o nif_test.dll nif_test.c -I"$ERL_ROOT/usr/include"
In file included from nif_test.c:2:
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:34:81: error: 'enif_free' undeclared here (not in a function)
   34 | ERL_NIF_API_FUNC_DECL(void*,enif_alloc,(size_t size) ERL_NAPI_ATTR_MALLOC_USD(1,enif_free,1));
      |                                                                                 ^~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif.h:339:72: note: in definition of macro 'ERL_NIF_API_FUNC_DECL'
  339 | #  define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS
      |                                                                        ^~~~
C:/Program Files/Erlang OTP/usr/include/erl_drv_nif.h:221:8: note: in expansion of macro 'ERL_NAPI_ATTR_MALLOC_D'
  221 |        ERL_NAPI_ATTR_MALLOC_D(DTOR, PTRPOS)
      |        ^~~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:34:54: note: in expansion of macro 'ERL_NAPI_ATTR_MALLOC_USD'
   34 | ERL_NIF_API_FUNC_DECL(void*,enif_alloc,(size_t size) ERL_NAPI_ATTR_MALLOC_USD(1,enif_free,1));
      |                                                      ^~~~~~~~~~~~~~~~~~~~~~~~
In file included from C:/Program Files/Erlang OTP/usr/include/erl_nif.h:341:
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:34:1: warning: 'malloc' attribute ignored; valid only for functions [-Wattributes]
   34 | ERL_NIF_API_FUNC_DECL(void*,enif_alloc,(size_t size) ERL_NAPI_ATTR_MALLOC_USD(1,enif_free,1));
      | ^~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:34:1: warning: 'malloc' attribute ignored; valid only for functions [-Wattributes]
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:63:90: error: 'enif_mutex_destroy' undeclared here (not in a function)
   63 | ERL_NIF_API_FUNC_DECL(ErlNifMutex*,enif_mutex_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_mutex_destroy,1));
      |                                                                                          ^~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif.h:339:72: note: in definition of macro 'ERL_NIF_API_FUNC_DECL'
  339 | #  define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS
      |                                                                        ^~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:63:67: note: in expansion of macro 'ERL_NAPI_ATTR_MALLOC_D'
   63 | ERL_NIF_API_FUNC_DECL(ErlNifMutex*,enif_mutex_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_mutex_destroy,1));
      |                                                                   ^~~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:63:1: warning: 'malloc' attribute ignored; valid only for functions [-Wattributes]
   63 | ERL_NIF_API_FUNC_DECL(ErlNifMutex*,enif_mutex_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_mutex_destroy,1));
      | ^~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:68:88: error: 'enif_cond_destroy' undeclared here (not in a function)
   68 | ERL_NIF_API_FUNC_DECL(ErlNifCond*,enif_cond_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_cond_destroy,1));
      |                                                                                        ^~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif.h:339:72: note: in definition of macro 'ERL_NIF_API_FUNC_DECL'
  339 | #  define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS
      |                                                                        ^~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:68:65: note: in expansion of macro 'ERL_NAPI_ATTR_MALLOC_D'
   68 | ERL_NIF_API_FUNC_DECL(ErlNifCond*,enif_cond_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_cond_destroy,1));
      |                                                                 ^~~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:68:1: warning: 'malloc' attribute ignored; valid only for functions [-Wattributes]
   68 | ERL_NIF_API_FUNC_DECL(ErlNifCond*,enif_cond_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_cond_destroy,1));
      | ^~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:73:92: error: 'enif_rwlock_destroy' undeclared here (not in a function)
   73 | ERL_NIF_API_FUNC_DECL(ErlNifRWLock*,enif_rwlock_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_rwlock_destroy,1));
      |                                                                                            ^~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif.h:339:72: note: in definition of macro 'ERL_NIF_API_FUNC_DECL'
  339 | #  define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS
      |                                                                        ^~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:73:69: note: in expansion of macro 'ERL_NAPI_ATTR_MALLOC_D'
   73 | ERL_NIF_API_FUNC_DECL(ErlNifRWLock*,enif_rwlock_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_rwlock_destroy,1));
      |                                                                     ^~~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:73:1: warning: 'malloc' attribute ignored; valid only for functions [-Wattributes]
   73 | ERL_NIF_API_FUNC_DECL(ErlNifRWLock*,enif_rwlock_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_rwlock_destroy,1));
      | ^~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:85:101: error: 'enif_thread_opts_destroy' undeclared here (not in a function)
   85 | ERL_NIF_API_FUNC_DECL(ErlNifThreadOpts*,enif_thread_opts_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_thread_opts_destroy,1));
      |                                                                                                     ^~~~~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif.h:339:72: note: in definition of macro 'ERL_NIF_API_FUNC_DECL'
  339 | #  define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS
      |                                                                        ^~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:85:78: note: in expansion of macro 'ERL_NAPI_ATTR_MALLOC_D'
   85 | ERL_NIF_API_FUNC_DECL(ErlNifThreadOpts*,enif_thread_opts_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_thread_opts_destroy,1));
      |                                                                              ^~~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:85:1: warning: 'malloc' attribute ignored; valid only for functions [-Wattributes]
   85 | ERL_NIF_API_FUNC_DECL(ErlNifThreadOpts*,enif_thread_opts_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_thread_opts_destroy,1));
      | ^~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:111:1: warning: 'malloc' attribute ignored; valid only for functions [-Wattributes]
  111 | ERL_NIF_API_FUNC_DECL(void *, enif_alloc_resource, (ErlNifResourceType *type, size_t size) ERL_NAPI_ATTR_MALLOC_US(2));
      | ^~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:187:103: error: 'enif_ioq_destroy' undeclared here (not in a function)
  187 | ERL_NIF_API_FUNC_DECL(ErlNifIOQueue *,enif_ioq_create,(ErlNifIOQueueOpts opts) ERL_NAPI_ATTR_MALLOC_D(enif_ioq_destroy,1));
      |                                                                                                       ^~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif.h:339:72: note: in definition of macro 'ERL_NIF_API_FUNC_DECL'
  339 | #  define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS
      |                                                                        ^~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:187:80: note: in expansion of macro 'ERL_NAPI_ATTR_MALLOC_D'
  187 | ERL_NIF_API_FUNC_DECL(ErlNifIOQueue *,enif_ioq_create,(ErlNifIOQueueOpts opts) ERL_NAPI_ATTR_MALLOC_D(enif_ioq_destroy,1));
      |                                                                                ^~~~~~~~~~~~~~~~~~~~~~
C:/Program Files/Erlang OTP/usr/include/erl_nif_api_funcs.h:187:1: warning: 'malloc' attribute ignored; valid only for functions [-Wattributes]
  187 | ERL_NIF_API_FUNC_DECL(ErlNifIOQueue *,enif_ioq_create,(ErlNifIOQueueOpts opts) ERL_NAPI_ATTR_MALLOC_D(enif_ioq_destroy,1));
      | ^~~~~~~~~~~~~~~~~~~~~

What should I do to make it compile successfully?

I’m a little late, but just wanted to say that this is a bug which should be fixed by this pr: erts: Do not annotate nif API functions on windows by garazdawi · Pull Request #9016 · erlang/otp · GitHub.

As you say, using VS will solve the problem, without that you will have to use an Erlang version before Erlang/OTP 25. I suppose you can also manually apply the patch in the PR to the installed system.

Thank you for the work you put into this

1 Like