[erlang-patches] Make Erlang compile on recent FreeBSD releases (long)

Giacomo Olgeni <>
Sat Nov 1 23:49:07 CET 2008


(I'm reposting as the first attempt didn't show up on the list...)

Hello,

I'm following up to a previous post (http://tinyurl.com/5dtkfb) about 
FreeBSD support.

The FreeBSD port of Erlang has been collecting patches for a while. 
Some of them are critical build fixes without which it is not possible 
to compile Erlang on a recent FreeBSD installation (I'm using 7.0 
here), so I thought it would be useful to sort out all the patches by 
running through an unpatched build of R12B-4 and checking what happens 
without them. Most of the patches were actually obtained from 
erlang-patches.

All the patches may be downloaded from here:

http://www.freebsd.org/cgi/cvsweb.cgi/ports/lang/erlang/files/

The port sets --enable-threads and --enable-dynamic-ssl-lib as 
arguments for running the configure tool.

The first thing to go wrong is the PCRE library. Apparently, Erlang 
ships with its own version of PCRE which is not compatible to the PCRE 
version from the FreeBSD ports (7.8 as of today). Thus, erl_bif_re.c 
will fail to compile:

beam/erl_bif_re.c: In function 'cleanup_restart_context':
beam/erl_bif_re.c:498: warning: implicit declaration of function 
'pcre_free_restart_data'
beam/erl_bif_re.c: In function 're_run_3':
beam/erl_bif_re.c:921: error: 'PCRE_EXTRA_LOOP_LIMIT' undeclared (first use in 
this function)
beam/erl_bif_re.c:921: error: (Each undeclared identifier is reported only once
beam/erl_bif_re.c:921: error: for each function it appears in.)
beam/erl_bif_re.c:923: error: 'pcre_extra' has no member named 'loop_limit'
beam/erl_bif_re.c:926: error: 'pcre_extra' has no member named 'loop_limit'
beam/erl_bif_re.c:927: error: 'pcre_extra' has no member named 'loop_limit'
beam/erl_bif_re.c:930: error: 'pcre_extra' has no member named 'restart_data'
beam/erl_bif_re.c:931: error: 'pcre_extra' has no member named 'restart_flags'
beam/erl_bif_re.c:932: error: 'pcre_extra' has no member named 
'loop_counter_return'
beam/erl_bif_re.c:972: error: 'PCRE_ERROR_LOOP_LIMIT' undeclared (first use in 
this function)
beam/erl_bif_re.c: In function 're_exec_trap':
beam/erl_bif_re.c:1023: error: 'pcre_extra' has no member named 'loop_limit'
beam/erl_bif_re.c:1026: error: 'pcre_extra' has no member named 'loop_limit'
beam/erl_bif_re.c:1027: error: 'pcre_extra' has no member named 'loop_limit'
beam/erl_bif_re.c:1029: error: 'pcre_extra' has no member named 
'loop_counter_return'
beam/erl_bif_re.c:1030: error: 'pcre_extra' has no member named 'restart_data'
beam/erl_bif_re.c:1031: error: 'pcre_extra' has no member named 'restart_flags'
beam/erl_bif_re.c:1039: error: 'PCRE_ERROR_LOOP_LIMIT' undeclared (first use in 
this function)
gmake[3]: *** [obj/i386-portbld-freebsd7.0/opt/plain/erl_bif_re.o] Error 1
gmake[3]: Leaving directory `/usr/storage/erlang/work/otp_src_R12B-4/erts/emulator'

Part of patch-erts-emulator-Makefile.in deals with this by sorting the 
$(CC) command line flag so that the local $(INCLUDES) show up as the 
first option.

--- erts/emulator/Makefile.in.orig
+++ erts/emulator/Makefile.in
@@ -544,7 +546,7 @@
  endif

  $(OBJDIR)/%.o: beam/%.c
-       $(CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@
+       $(CC) $(INCLUDES) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) -c $< -o $@

  else

This allows to get past the PCRE issue.

Then you will probably bump into gethostbyname_r, which is called using
incompatible parameters.

connect/ei_resolve.c: In function 'ei_gethostbyname_r':
connect/ei_resolve.c:629: warning: passing argument 5 of 'gethostbyname_r' from 
incompatible pointer type
connect/ei_resolve.c:629: error: too few arguments to function 
'gethostbyname_r'
gmake[4]: *** 
[/usr/storage/erlang/work/otp_src_R12B-4/lib/erl_interface/obj.mt/i386-portbld-freebsd7.0/ei_resolve.o] 
Error 1
gmake[4]: Leaving directory 
`/usr/storage/erlang/work/otp_src_R12B-4/lib/erl_interface/src'
gmake[3]: *** [opt] Error 2
gmake[3]: Leaving directory 
`/usr/storage/erlang/work/otp_src_R12B-4/lib/erl_interface/src'
gmake[2]: *** [opt] Error 2
gmake[2]: Leaving directory 
`/usr/storage/erlang/work/otp_src_R12B-4/lib/erl_interface'
gmake[1]: *** [opt] Error 2
gmake[1]: Leaving directory `/usr/storage/erlang/work/otp_src_R12B-4/lib'
gmake: *** [libs] Error 2
*** Error code 2

The patch in patch-lib_erl__interface_src_connect_ei__resolve.c sorts this out.

--- lib/erl_interface/src/connect/ei_resolve.c.orig
+++ lib/erl_interface/src/connect/ei_resolve.c
@@ -621,7 +621,8 @@

    return result;
  #else
-  return gethostbyname_r(name,hostp,buffer,buflen,h_errnop);
+  struct hostent *dummy;
+  return gethostbyname_r(name,hostp,buffer,buflen,&dummy,h_errnop);
  #endif
  #endif
  #endif

If you rebuild with these patches, memsup.c hits you next:

memsup.c: In function 'get_extended_mem':
memsup.c:456: error: void value not ignored as it ought to be

patch-lib_os__mon_c__src_memsup.c will fix it:

--- lib/os_mon/c_src/memsup.c.orig
+++ lib/os_mon/c_src/memsup.c
@@ -404,7 +404,7 @@
  #endif

  #if defined(BSD4_4)
-static void
+static int
  get_extended_mem_bsd4(memory_ext *me) {
      struct vmtotal vt;
      long pgsz;

The next issue is about odbcserver.c:

odbcserver.c: In function 'connect_to_erlang':
odbcserver.c:1625: error: storage size of 'sin' isn't known

patch-lib_odbc_c_src_odbcserver.c includes the missing header:

--- lib/odbc/c_src/odbcserver.c.orig    Sat Jun 25 17:34:20 2005
+++ lib/odbc/c_src/odbcserver.c Sat Jun 25 17:34:33 2005
@@ -107,6 +107,7 @@
  #include <sys/socket.h>
  #include <sys/uio.h>
  #include <netdb.h>
+#include <netinet/in.h>
  #endif

  #include "ei.h"

These patches will at least get you through the build.

Now, let's try to run "gmake install".

gmake[6]: Entering directory 
`/usr/storage/erlang/work/otp_src_R12B-4/lib/crypto/c_src'
/usr/bin/install -c -o root -g wheel -d 
/usr/local/lib/erlang/lib/crypto-1.5.2.1/priv/obj
/usr/bin/install -c -o root -g wheel -d 
/usr/local/lib/erlang/lib/crypto-1.5.2.1/priv/lib
install  -s -o root -g wheel -m 555 ../priv/Makefile 
/usr/local/lib/erlang/lib/crypto-1.5.2.1/priv/obj
strip: /usr/local/lib/erlang/lib/crypto-1.5.2.1/priv/obj/Makefile: File format 
not recognized
install: wait: No such file or directory
gmake[6]: *** [release_spec] Error 70

The problem here is that Makefile is treated like an executable, so
INSTALL_PROGRAM tries to run the strip command on it, which fails because
there's no executable to strip.

patch-lib_crypto_c__src_Makefile.in switches INSTALL_PROGRAM to INSTALL_DATA:

--- lib/crypto/c_src/Makefile.in.orig   Thu Oct  7 12:11:06 2004
+++ lib/crypto/c_src/Makefile.in        Thu Oct  7 12:11:07 2004
@@ -121,7 +121,7 @@
  release_spec: opt
         $(INSTALL_DIR) $(RELSYSDIR)/priv/obj
         $(INSTALL_DIR) $(RELSYSDIR)/priv/lib
-       $(INSTALL_PROGRAM) $(DRV_MAKEFILE) $(RELSYSDIR)/priv/obj
+       $(INSTALL_DATA) $(DRV_MAKEFILE) $(RELSYSDIR)/priv/obj
         $(INSTALL_PROGRAM) $(OBJS) $(RELSYSDIR)/priv/obj
         $(INSTALL_PROGRAM) $(DYN_DRIVER) $(RELSYSDIR)/priv/lib

With this last patch you will be able to install a working Erlang.

However, there are still some issues with SCTP support.

I added "--enable-sctp" to the configure parameters, but then...

configure: configuring in erts
configure: running /bin/sh 
'/usr/storage/erlang/work/otp_src_R12B-4/erts/configure' --prefix=/usr/local 
'--enable-threads' '--enable-dynamic-ssl-lib' '--enable-sctp' 
'--prefix=/usr/local' '--mandir=/usr/local/man' '--infodir=/usr/local/info/' 
'--build=i386-portbld-freebsd7.0' 'CC=cc' 'CFLAGS=-O2 -fno-strict-aliasing 
-pipe -I/usr/local/include' 'LDFLAGS= -L/usr/local/lib' 
'build_alias=i386-portbld-freebsd7.0' --cache-file=/dev/null 
--srcdir=/usr/storage/erlang/work/otp_src_R12B-4/erts
[...]
checking for sys/devpoll.h... no
test: xyes: unexpected operator
checking valgrind/valgrind.h usability... no
[...]

If you look into erts/configure, you'll see that the test for enable_sctp
lies exactly between the devpoll and valgrind checks:

if test "x$enable_sctp" == "xyes" ; then
     echo "$as_me:$LINENO: checking for netinet/sctp.h" >&5
echo $ECHO_N "checking for netinet/sctp.h... $ECHO_C" >&6
if test "${ac_cv_header_netinet_sctp_h+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
else
   cat >conftest.$ac_ext <<_ACEOF

Notice the "==" operator, which should actually be "=".

Let's patch it in patch-erts_configure:

--- erts/configure.orig
+++ erts/configure
@@ -10620,7 +10620,7 @@



-if test "x$enable_sctp" == "xyes" ; then
+if test "x$enable_sctp" = "xyes" ; then
      echo "$as_me:$LINENO: checking for netinet/sctp.h" >&5
  echo $ECHO_N "checking for netinet/sctp.h... $ECHO_C" >&6
  if test "${ac_cv_header_netinet_sctp_h+set}" = set; then

...and retry:

checking for sys/devpoll.h... no
checking for netinet/sctp.h... yes
checking for sctp_bindx in -lsctp... no
checking whether SCTP_UNORDERED is declared... yes
checking whether SCTP_ADDR_OVER is declared... yes
checking whether SCTP_ABORT is declared... yes
checking whether SCTP_EOF is declared... yes
checking whether SCTP_SENDALL is declared... yes
checking whether SCTP_ADDR_CONFIRMED is declared... yes
checking for struct sctp_paddrparams.spp_pathmtu... yes
checking for struct sctp_paddrparams.spp_sackdelay... no
checking for struct sctp_paddrparams.spp_flags... yes
checking for struct sctp_remote_error.sre_data... yes
checking for struct sctp_send_failed.ssh_data... no
checking valgrind/valgrind.h usability... no
checking valgrind/valgrind.h presence... no

Here we made some progress, however the check for sctp_bindx in -lsctp
causes "WITH_SCTP=" to be written in 
erts/emulator/i386-portbld-freebsd7.0/Makefile,
thus disabling SCTP entirely.

According to SCTP_BINDX(3), sctp_bindx is found in -lc rather than -lsctp
on FreeBSD.

So, the following patch is added to patch-erts_configure:

--- erts/configure.orig
+++ erts/configure
@@ -10679,7 +10679,6 @@
    echo $ECHO_N "(cached) $ECHO_C" >&6
  else
    ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsctp  $LIBS"
  cat >conftest.$ac_ext <<_ACEOF
  /* confdefs.h.  */
  _ACEOF

However this should probably be fixed in configure.in, together with the
(now incorrect) log message.

This time we get the correct result:

checking for netinet/sctp.h... yes
>>> checking for sctp_bindx in -lsctp... yes <<<
checking whether SCTP_UNORDERED is declared... yes

If we rebuild, we are stopped again here:

[...] obj/i386-portbld-freebsd7.0/opt/plain/efile_drv.o 
obj/i386-portbld-freebsd7.0/opt/plain/inet_drv.o 
obj/i386-portbld-freebsd7.0/opt/plain/zlib_drv.o 
obj/i386-portbld-freebsd7.0/opt/plain/ram_file_drv.o 
obj/i386-portbld-freebsd7.0/opt/plain/ttsl_drv.o -lutil -lm   -lncurses 
-L../lib/internal/i386-portbld-freebsd7.0 
/usr/storage/erlang/work/otp_src_R12B-4/erts/emulator/zlib/obj/i386-portbld-freebsd7.0/opt/libz.a 
/usr/storage/erlang/work/otp_src_R12B-4/erts/emulator/pcre/obj/i386-portbld-freebsd7.0/opt/libepcre.a 
-lsctp -lethread -lpthread -lerts_internal_r
/usr/bin/ld: cannot find -lsctp

patch-erts-emulator-Makefile.in is then modified to avoid looking for
libsctp on FreeBSD.

--- erts/emulator/Makefile.in.orig
+++ erts/emulator/Makefile.in
@@ -265,8 +265,10 @@
  endif
  WITH_SCTP=@WITH_SCTP@
  ifdef WITH_SCTP
+ifneq ($(findstring freebsd,$(TARGET)),freebsd)
  LIBS += -lsctp
  endif
+endif

  ORG_THR_LIBS=@EMU_THR_LIBS@
  THR_LIB_NAME=@EMU_THR_LIB_NAME@

After the last patch, it appears that SCTP is working.

Erlang (BEAM) emulator version 5.6.4 [source] [async-threads:0] [hipe] 
[kernel-poll:false]

Eshell V5.6.4  (abort with ^G)
1> gen_sctp:open ().
{ok,#Port<0.96>}
2>

On the website above you will find more patches which are not critical to
the build. Specifically, there's a patch named for erl_process_dump.c
(which was obtained from this mailing list - credits due to whoever posted
it!) that fixes a potential crash, so I was wondering if it would be
suitable for inclusion in the next release.

--- erts/emulator/beam/erl_process_dump.c.orig
+++ erts/emulator/beam/erl_process_dump.c
@@ -399,9 +399,11 @@
  static void
  dump_externally(int to, void *to_arg, Eterm term)
  {
-    byte sbuf[1024]; /* encode and hope for the best ... */
-    byte* s;
-    byte* p;
+    byte *sbuf, *s, *p;
+    unsigned size;
+
+    size = encode_size_struct(term, TERM_TO_BINARY_DFLAGS);
+    sbuf = (byte *) erts_alloc(ERTS_ALC_T_TMP, size);

      s = p = sbuf;
      erts_to_external_format(NULL, term, &p, NULL, NULL);
@@ -409,4 +411,6 @@
      while (s < p) {
  	erts_print(to, to_arg, "%02X", *s++);
      }
+
+    erts_free(ERTS_ALC_T_TMP, (void *) sbuf);
  }

I would also suggest that the next Erlang releases are tested on a supported 
FreeBSD version (today 6.x should be fine) so as to make life easier for users 
who are following a customized release process and do not rely on the ports 
system to install Erlang.

Kind regards,

   Jimmy



More information about the erlang-patches mailing list