From 94d174949635cd4e641daaac0a7df98ea35f2c55 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 15 Aug 2013 17:04:52 +0200 Subject: erts: Add support for static linked-in drivers None of the OTP linked-in driver are supported --- erts/configure.in | 6 ++++++ erts/doc/src/driver_entry.xml | 2 ++ erts/emulator/Makefile.in | 42 ++++++++++++++++++++++++++++--------- erts/emulator/beam/erl_driver.h | 14 +++++++++---- erts/emulator/beam/global.h | 1 + erts/emulator/beam/io.c | 1 + erts/emulator/utils/make_driver_tab | 42 ++++++++++++++++++++++++++++++++----- 7 files changed, 89 insertions(+), 19 deletions(-) (limited to 'erts') diff --git a/erts/configure.in b/erts/configure.in index 3b4417d10e..4e60b27ee9 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -425,6 +425,12 @@ AS_HELP_STRING([--enable-static-nifs], [link nifs statically. If yes then all ni STATIC_NIFS=no) AC_SUBST(STATIC_NIFS) +AC_ARG_ENABLE(static-drivers, +AS_HELP_STRING([--enable-static-drivers], [comma seperated list of linked-in drivers to link statically with the main binary. The list should contain the absolute path to a .a archive for each driver that is to be statically linked. The name of the .a archive has to be the same as the name of the driver.]), + STATIC_DRIVERS="$enableval", + STATIC_DRIVERS=no) +AC_SUBST(STATIC_DRIVERS) + dnl ---------------------------------------------------------------------- dnl Checks for programs. dnl ---------------------------------------------------------------------- diff --git a/erts/doc/src/driver_entry.xml b/erts/doc/src/driver_entry.xml index 69a4dea466..48dfcb09b1 100644 --- a/erts/doc/src/driver_entry.xml +++ b/erts/doc/src/driver_entry.xml @@ -110,6 +110,8 @@

When the driver has passed the driver_entry over to the emulator, the driver is not allowed to modify the driver_entry.

+

If compiling a driver for static inclusion via --enable-static-drivers you + have to define STATIC_ERLANG_DRIVER before the DRIVER_INIT declaration.

Do not declare the driver_entry const. This since the emulator needs to modify the handle, and the handle2 diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index db5642b9c3..048e92baad 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -136,18 +136,27 @@ endif endif endif +comma:=, +space:= +space+= + STATIC_NIFS=@STATIC_NIFS@ ifneq ($(STATIC_NIFS),no) ifeq ($(STATIC_NIFS),yes) STATIC_NIFS=$(ERL_TOP)/lib/asn1/priv/lib/$(TARGET)/asn1rt_nif.a \ $(ERL_TOP)/lib/crypto/priv/lib/$(TARGET)/crypto$(TYPEMARKER).a endif -comma:=, -space:= -space+= STATIC_NIFS:=$(subst $(comma),$(space),$(STATIC_NIFS)) endif +STATIC_DRIVERS=@STATIC_DRIVERS@ +ifneq ($(STATIC_DRIVERS),no) +ifeq ($(STATIC_DRIVERS),yes) +STATIC_DRIVERS= +endif +STATIC_DRIVERS:=$(subst $(comma),$(space),$(STATIC_DRIVERS)) +endif + # # NOTE: When adding a new type update ERL_BUILD_TYPE_MARKER in sys/unix/sys.c @@ -571,7 +580,7 @@ GENERATE += $(TARGET)/erl_version.h # driver table $(TTF_DIR)/driver_tab.c: Makefile.in utils/make_driver_tab - $(gen_verbose)LANG=C $(PERL) utils/make_driver_tab -o $@ $(STATIC_NIF_LIBS) $(DRV_OBJS) + $(gen_verbose)LANG=C $(PERL) utils/make_driver_tab -o $@ -nifs $(STATIC_NIF_LIBS) -drivers $(DRV_OBJS) $(STATIC_DRIVER_LIBS) GENERATE += $(TTF_DIR)/driver_tab.c @@ -813,14 +822,25 @@ endif ifneq ($(STATIC_NIFS),no) STATIC_NIF_LIBS = $(STATIC_NIFS) DEPLIBS += $(STATIC_NIF_LIBS) - -$(STATIC_NIF_LIBS): - $(MAKE) BUILD_STATIC_LIBS=1 TYPE=$(TYPE) -C $(ERL_TOP)/lib/ static_lib - +COMPILE_STATIC_LIBS = yes else STATIC_NIF_LIBS= endif +ifneq ($(STATIC_DRIVERS),no) +STATIC_DRIVER_LIBS = $(STATIC_DRIVERS) +DEPLIBS += $(STATIC_DRIVER_LIBS) +COMPILE_STATIC_LIBS = yes +else +STATIC_DRIVER_LIBS= +endif + +ifeq ($(COMPILE_STATIC_LIBS),yes) + +$(STATIC_NIF_LIBS) $(STATIC_DRIVER_LIBS): + $(MAKE) BUILD_STATIC_LIBS=1 TYPE=$(TYPE) -C $(ERL_TOP)/lib/ static_lib +endif + ifeq ($(ERTS_ENABLE_KERNEL_POLL),yes) OS_OBJS += $(OBJDIR)/erl_poll.kp.o \ $(OBJDIR)/erl_check_io.kp.o \ @@ -965,12 +985,14 @@ ifeq ($(TARGET), win32) # Only the basic erlang to begin with eh? $(BINDIR)/$(EMULATOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS) $(ld_verbose)$(PURIFY) $(LD) -dll -def:sys/$(ERLANG_OSTYPE)/erl.def -implib:$(BINDIR)/erl_dll.lib -o $(BINDIR)/$(EMULATOR_EXECUTABLE) \ - $(LDFLAGS) $(DEXPORT) $(INIT_OBJS) $(OBJS) $(STATIC_NIF_LIBS) $(LIBS) + $(LDFLAGS) $(DEXPORT) $(INIT_OBJS) $(OBJS) $(STATIC_NIF_LIBS) \ + $(STATIC_DRIVER_LIBS) $(LIBS) else $(BINDIR)/$(EMULATOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS) + echo $(DEPLIBS) $(ld_verbose)$(PURIFY) $(LD) -o $(BINDIR)/$(EMULATOR_EXECUTABLE) \ $(HIPEBEAMLDFLAGS) $(LDFLAGS) $(DEXPORT) $(INIT_OBJS) $(OBJS) \ - $(STATIC_NIF_LIBS) $(LIBS) + $(STATIC_NIF_LIBS) $(STATIC_DRIVER_LIBS) $(LIBS) endif diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h index e280563de1..f43f5a766e 100644 --- a/erts/emulator/beam/erl_driver.h +++ b/erts/emulator/beam/erl_driver.h @@ -365,17 +365,23 @@ typedef struct erl_drv_entry { * It must initialize a ErlDrvEntry structure and return a pointer to it. */ +#ifdef STATIC_ERLANG_DRIVER +# define ERLANG_DRIVER_NAME(NAME) NAME ## _driver_init +#else +# define ERLANG_DRIVER_NAME(NAME) driver_init +#endif + /* For windows dynamic drivers */ #ifndef ERL_DRIVER_TYPES_ONLY #if defined(__WIN32__) # define DRIVER_INIT(DRIVER_NAME) \ - __declspec(dllexport) ErlDrvEntry* driver_init(void); \ - __declspec(dllexport) ErlDrvEntry* driver_init(void) + __declspec(dllexport) ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void); \ + __declspec(dllexport) ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void) #else # define DRIVER_INIT(DRIVER_NAME) \ - ErlDrvEntry* driver_init(void); \ - ErlDrvEntry* driver_init(void) + ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void); \ + ErlDrvEntry* ERLANG_DRIVER_NAME(DRIVER_NAME)(void) #endif #define ERL_DRV_BUSY_MSGQ_DISABLED (~((ErlDrvSizeT) 0)) diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 2acc86cf42..ef34f5b221 100755 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -856,6 +856,7 @@ void erts_lcnt_enable_io_lock_count(int enable); typedef void *(*ErtsStaticNifInitFPtr)(void); ErtsStaticNifInitFPtr erts_static_nif_get_nif_init(const char *name); int erts_is_static_nif(void *handle); +void erts_init_static_drivers(void); /* erl_drv_thread.c */ void erl_drv_thr_init(void); diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index c1e66b59af..fb39c18d9d 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -2765,6 +2765,7 @@ void erts_init_io(int port_tab_size, init_driver(&fd_driver, &fd_driver_entry, NULL); init_driver(&vanilla_driver, &vanilla_driver_entry, NULL); init_driver(&spawn_driver, &spawn_driver_entry, NULL); + erts_init_static_drivers(); for (dp = driver_tab; *dp != NULL; dp++) erts_add_driver_entry(*dp, NULL, 1); diff --git a/erts/emulator/utils/make_driver_tab b/erts/emulator/utils/make_driver_tab index 06928a3a4a..3eedef21a7 100755 --- a/erts/emulator/utils/make_driver_tab +++ b/erts/emulator/utils/make_driver_tab @@ -28,8 +28,10 @@ use File::Basename; my $file = ""; my $nif = ""; -my @drivers = (); +my @emu_drivers = (); +my @static_drivers = (); my @nifs = (); +my $mode = 1; while (@ARGV) { my $d = shift; @@ -37,15 +39,28 @@ while (@ARGV) { $file = shift or die("-o requires argument"); next; } + if ( $d =~ /^-nifs$/ ) { + $mode = 2; + next; + } + if ( $d =~ /^-drivers$/ ) { + $mode = 1; + next; + } if ( $d =~ /^.*\.a$/ ) { $d = basename $d; $d =~ s/\.a$//; # strip .a - push(@nifs, $d); + if ($mode == 1) { + push(@static_drivers, $d); + } + if ($mode == 2) { + push(@nifs, $d); + } next; } $d = basename $d; $d =~ s/drv(\..*|)$//; # strip drv.* or just drv - push(@drivers, $d); + push(@emu_drivers, $d); } # Did we want output to a file? @@ -64,19 +79,36 @@ print <