Difference between revisions of "OutOfTreeCompile"

From VideoLAN Wiki
Jump to navigation Jump to search
Line 1: Line 1:
==Aim==
+
This page outlines setting up a module for building outside of the main VLC source tree.
Being able to build a vlc module without needing to build the whole vlc source.
+
See also [[Hacker_Guide/How_To_Write_a_Module|how to write a module]].
It can be used if you develop a new module, if your module can't be distributed at the same time as VLC due to some IP issues or to reduce the number of build-dependancies for a source package
+
 
 +
==Source code==
 +
There are a few differences that need to be taken into account when writing a module out-of-tree:
 +
 
 +
* '''MODULE_STRING must be defined''' manually (in-tree, the VLC build system takes care of it).
 +
* The static import compatibility library (compat/libcompat.la) is not available. If a function is missing on the target platform, you will need to work around it yourself.
 +
* <config.h> is not available either, so none of the HAVE_* and CAN_* macros are defined out-of-the-box. You will need to ensure that your build system provides any such macro that the module source code depends on.
 +
* Similarly, the gettext functional macros N_(), _(), vlc_pgettext() and gettext_noop() are not defined automatically.
 +
* Some (few) parts of the VLC core API are unavailable. Their header files are provided externally.
  
==Preparation==
 
If you're taking a module from VLC source code, you may need to modify it slightly.
 
 
===Internationalization===
 
===Internationalization===
You can't use the main VLC internationalization (gettext) "domain".
+
The VLC build system cannot scan out-of-tree source code for text to be translated. If you want gettext translations, you need to setup gettext in the build system and maintain the PO files.
So you can either add your own domain declaration:
+
 
 +
However, the VLC core is able to load your module text domain into the process automatically. This is required for the plugins cache to operate correctly. You simply need to add one "set_text_domain" line in the module descriptor, e.g.:
  
 
<pre>
 
<pre>
Line 22: Line 29:
 
vlc_module_end()
 
vlc_module_end()
 
</pre>
 
</pre>
or disable internationalization completely:
+
 
<pre>
+
You might find it hard to maintain this, and ignore internationalization altogether.
#define _(str)  (str)
+
 
#define N_(str) (str)
 
</pre>
 
 
===Symbols===
 
===Symbols===
For your module to be loaded by VLC, you'll need to define the symbol '''__PLUGIN__'''. This should enable exported symbols similar to the following:
+
External VLC modules are run-time libraries. They need to expose some predefined symbols (functions). They all start with the prefix "vlc_entry_". In principles, the vlc_module_begin() macro ensures that those function are exported, so you should not worry about this.
<pre>
+
 
EXPORTS
+
==Installing the development files==
vlc_entry__1_1_0g
+
The VLC header files, the pkg-config files, and import libraries are required.
vlc_entry_license__1_1_0g
+
 
</pre>
+
On Debian/Ubuntu, you can simply install them:
Optionally, you can also define the '''__LIBVLC__''' symbol.
+
% sudo apt-get install libvlc-dev
 +
 
 +
On Windows, you can find those files within the vlc-*-win*.zip file, inside the sdk/ directory.
  
 
==Building==
 
==Building==
  
===With plain makefile===
+
Note that the following examples assume that the VLC development package is installed and configured correctly. In particular, these commands should work (results may vary though):
The following Makefile is an example based on the x264 module of VLC. You will need to adapt to your module.
 
  
 +
% pkg-config --modversion vlc-plugin
 +
1.1.13
 +
 +
% pkg-config --cflags vlc-plugin
 +
-D__PLUGIN__ -D_FILE_OFFSET_BITS=64 -D__USE_UNIX98 -D_REENTRANT -D_THREAD_SAFE -I/usr/include/vlc/plugins 
 +
 +
% pkg-config --libs vlc-plugin
 +
-lvlccore 
 +
 +
If cross-compiling, you will probably need to adjust the pkg-config environment variables.
 +
 +
===Makefile===
 +
This is an example plain makefile (using GNU/make syntax) for Linux/BSD/Solaris:
 
<pre>
 
<pre>
libdir = $(shell pkg-config --variable=libdir vlc-plugin )
+
PREFIX = /usr
vlclibdir = $(libdir)/vlc
+
LD = ld
 +
CC = cc
 +
INSTALL = install
 +
CFLAGS = -g -O2 -Wall -Wextra
 +
LDFLAGS =
 +
VLC_PLUGIN_CFLAGS := $(shell pkg-config --cflags vlc-plugin)
 +
VLC_PLUGIN_LIBS := $(shell pkg-config --libs vlc-plugin)
 +
 
 +
libdir = $(PREFIX)/lib
 +
plugindir = $(libdir)/vlc/plugins
 +
 
 +
override CC += -std=gnu99
 +
override CPPFLAGS += -DPIC -I. -Isrc
 +
override CFLAGS += -fPIC
 +
override LDFLAGS += -Wl,-no-undefined,-z,defs
 +
 
 +
override CPPFLAGS += -DMODULE_STRING=\"foo\"
 +
override CFLAGS += $(VLC_PLUGIN_CFLAGS)
 +
override LDFLAGS += $(VLC_PLUGIN_LIBS)
 +
 
 +
TARGETS = libfoo_plugin.so
  
all: libx264_plugin.so
+
all: libfoo_plugin.so
 
libx264_plugin.so: libx264_plugin.o
 
        gcc -shared -std=gnu99 $< `pkg-config  --libs vlc-plugin x264`  -Wl,-soname -Wl,$@ -o $@
 
 
libx264_plugin.o: x264.c
 
        gcc -c -std=gnu99  $< `pkg-config  --cflags vlc-plugin x264` -D__PLUGIN__  -DMODULE_STRING=\"x264\" -o $@ 
 
 
clean:
 
        rm -f libx264_plugin.o libx264_plugin.so
 
  
 
install: all
 
install: all
         mkdir -p $(DESTDIR)$(vlclibdir)/
+
         mkdir -p -- $(DESTDIR)$(plugindir)/misc
         install -m 0755 libx264_plugin.so $(DESTDIR)$(vlclibdir)/
+
         $(INSTALL) --mode 0755 libfoo_plugin.so $(DESTDIR)$(plugindir)/misc
  
install-strip: all
+
install-strip:
         mkdir -p $(DESTDIR)$(vlclibdir)/
+
         $(MAKE) install INSTALL="$(INSTALL) -s"
        install -s -m 0755 libx264_plugin.so $(DESTDIR)$(vlclibdir)/
 
  
 
uninstall:
 
uninstall:
         rm -f -- $(DESTDIR)$(vlclibdir)/libx264_plugin.so
+
         rm -f $(plugindir)/misc/libfoo_plugin.so
 +
 
 +
clean:
 +
        rm -f -- libfoo_plugin.so src/*.o
 +
 
 +
mostlyclean: clean
 +
 
 +
SOURCES = foo.c bar.c
 +
 
 +
$(SOURCES:%.c=src/%.o): %: src/foo.h
 +
 
 +
libfoo_plugin.so: $(SOURCES:%.c=src/%.o)
 +
        $(CC) $(LDFLAGS) -shared -o $@ $^
 +
 
 +
.PHONY: all install install-strip uninstall clean mostlyclean
 +
</pre>
 +
 
 +
===with GNU/autotools===
 +
If using automake and libtool, you can follow this instead:
 +
 
 +
====configure.ac====
 +
<pre>
 +
# ...
 +
 
 +
AC_PROG_CC_C99
 +
AM_PROG_CC_C_O
 +
AM_PROG_LIBTOOL
 +
PKG_PROG_PKG_CONFIG()
 +
 
 +
# ...
  
.PHONY: all clean install uninstall
+
PKG_CHECK_MODULES(VLC_PLUGIN, [vlc-plugin >= 1.1.0])
 
</pre>
 
</pre>
  
===With autotools===
 
If using automake and libtool, you can follow this example Makefile.am instead:
 
  
 +
====Makefile.am====
 
<pre>
 
<pre>
 
vlclibdir = $(libdir)/vlc
 
vlclibdir = $(libdir)/vlc
  
vlclib_libx264_plugin_la_SOURCES = x264.c
+
vlclib_libfoo_plugin_la_SOURCES = src/foo.c src/foo.h src/bar.c
vlclib_libx264_plugin_la_CFLAGS = $(VLC_PLUGIN_CFLAGS) $(X264_CFLAGS) \
+
vlclib_libfoo_plugin_la_CFLAGS = $(VLC_PLUGIN_CFLAGS) \
       -D__PLUGIN__ -DMODULE_STRING=\"x264\"
+
       -DMODULE_STRING=\"foo\"
vlclib_libx264_plugin_la_LIBADD = $(VLC_PLUGIN_LIBS) $(X264_LIBS)
+
vlclib_libfoo_plugin_la_LIBADD = $(VLC_PLUGIN_LIBS)
vlclib_libx264_plugin_la_LDFLAGS = \
+
vlclib_libfoo_plugin_la_LDFLAGS = \
 
       -avoid-version -module -export-symbol-regex ^vlc_entry
 
       -avoid-version -module -export-symbol-regex ^vlc_entry
 
</pre>
 
</pre>

Revision as of 19:17, 26 January 2012

This page outlines setting up a module for building outside of the main VLC source tree. See also how to write a module.

Source code

There are a few differences that need to be taken into account when writing a module out-of-tree:

  • MODULE_STRING must be defined manually (in-tree, the VLC build system takes care of it).
  • The static import compatibility library (compat/libcompat.la) is not available. If a function is missing on the target platform, you will need to work around it yourself.
  • <config.h> is not available either, so none of the HAVE_* and CAN_* macros are defined out-of-the-box. You will need to ensure that your build system provides any such macro that the module source code depends on.
  • Similarly, the gettext functional macros N_(), _(), vlc_pgettext() and gettext_noop() are not defined automatically.
  • Some (few) parts of the VLC core API are unavailable. Their header files are provided externally.

Internationalization

The VLC build system cannot scan out-of-tree source code for text to be translated. If you want gettext translations, you need to setup gettext in the build system and maintain the PO files.

However, the VLC core is able to load your module text domain into the process automatically. This is required for the plugins cache to operate correctly. You simply need to add one "set_text_domain" line in the module descriptor, e.g.:

#define DOMAIN  "vlc-myplugin"
#define _(str)  dgettext(DOMAIN, str)
#define N_(str) (str)

/* ... */

vlc_module_begin()
   set_text_domain (DOMAIN)
   set_description (N_("My plugin"))
   /* ... */
vlc_module_end()

You might find it hard to maintain this, and ignore internationalization altogether.

Symbols

External VLC modules are run-time libraries. They need to expose some predefined symbols (functions). They all start with the prefix "vlc_entry_". In principles, the vlc_module_begin() macro ensures that those function are exported, so you should not worry about this.

Installing the development files

The VLC header files, the pkg-config files, and import libraries are required.

On Debian/Ubuntu, you can simply install them:

% sudo apt-get install libvlc-dev

On Windows, you can find those files within the vlc-*-win*.zip file, inside the sdk/ directory.

Building

Note that the following examples assume that the VLC development package is installed and configured correctly. In particular, these commands should work (results may vary though):

% pkg-config --modversion vlc-plugin
1.1.13
% pkg-config --cflags vlc-plugin
-D__PLUGIN__ -D_FILE_OFFSET_BITS=64 -D__USE_UNIX98 -D_REENTRANT -D_THREAD_SAFE -I/usr/include/vlc/plugins  
% pkg-config --libs vlc-plugin
-lvlccore  

If cross-compiling, you will probably need to adjust the pkg-config environment variables.

Makefile

This is an example plain makefile (using GNU/make syntax) for Linux/BSD/Solaris:

PREFIX = /usr
LD = ld
CC = cc
INSTALL = install
CFLAGS = -g -O2 -Wall -Wextra
LDFLAGS =
VLC_PLUGIN_CFLAGS := $(shell pkg-config --cflags vlc-plugin)
VLC_PLUGIN_LIBS := $(shell pkg-config --libs vlc-plugin)

libdir = $(PREFIX)/lib
plugindir = $(libdir)/vlc/plugins

override CC += -std=gnu99
override CPPFLAGS += -DPIC -I. -Isrc
override CFLAGS += -fPIC
override LDFLAGS += -Wl,-no-undefined,-z,defs

override CPPFLAGS += -DMODULE_STRING=\"foo\"
override CFLAGS += $(VLC_PLUGIN_CFLAGS)
override LDFLAGS += $(VLC_PLUGIN_LIBS)

TARGETS = libfoo_plugin.so

all: libfoo_plugin.so

install: all
        mkdir -p -- $(DESTDIR)$(plugindir)/misc
        $(INSTALL) --mode 0755 libfoo_plugin.so $(DESTDIR)$(plugindir)/misc

install-strip:
        $(MAKE) install INSTALL="$(INSTALL) -s"

uninstall:
        rm -f $(plugindir)/misc/libfoo_plugin.so

clean:
        rm -f -- libfoo_plugin.so src/*.o

mostlyclean: clean

SOURCES = foo.c bar.c

$(SOURCES:%.c=src/%.o): %: src/foo.h

libfoo_plugin.so: $(SOURCES:%.c=src/%.o)
        $(CC) $(LDFLAGS) -shared -o $@ $^

.PHONY: all install install-strip uninstall clean mostlyclean

with GNU/autotools

If using automake and libtool, you can follow this instead:

configure.ac

# ...

AC_PROG_CC_C99
AM_PROG_CC_C_O
AM_PROG_LIBTOOL
PKG_PROG_PKG_CONFIG()

# ...

PKG_CHECK_MODULES(VLC_PLUGIN, [vlc-plugin >= 1.1.0])


Makefile.am

vlclibdir = $(libdir)/vlc

vlclib_libfoo_plugin_la_SOURCES = src/foo.c src/foo.h src/bar.c
vlclib_libfoo_plugin_la_CFLAGS = $(VLC_PLUGIN_CFLAGS) \
      -DMODULE_STRING=\"foo\"
vlclib_libfoo_plugin_la_LIBADD = $(VLC_PLUGIN_LIBS)
vlclib_libfoo_plugin_la_LDFLAGS = \
      -avoid-version -module -export-symbol-regex ^vlc_entry