[FFmpeg-devel] [PATCH] Shared library support for MSVC build.

Ronald S. Bultje rsbultje at gmail.com
Wed Oct 3 02:48:26 CEST 2012


From: "Ronald S. Bultje" <rsbultje at gmail.com>

This patch adds support for .dll shared library generation using MSVC's
native build tools. To properly load non-function symbols from DLL files,
we prefix them with __declspec(dllimport) on MSVC for shared library
builds when accessed from outside the .dll. For optimal performance, we
should do this for functions also, but I'm too lazy to do that right now
and it works without.

Caveats: 1) you need a new version of c99-to-c89, which will generate
the .def files which contains the symbols to be exported. The interface
for this isn't stable yet, I'd like to be able to specify symbols on the
commandline with wildcard support, e.g. c99wrap.exe -symbols 'avpriv_*'
link.exe -dll ..., but for now the hardcoded list does its job. Martin
suggested I use the existing .v files for this.
2) a lot of ff_ symbols, and dsputil_init, are accessed from outside
the library in which they exist. These are bugs and should be fixed (i.e.
renamed).
---
 configure                  |   10 ++++++----
 libavcodec/ac3tab.h        |    3 ++-
 libavcodec/dca.h           |    3 ++-
 libavcodec/dnxhddata.h     |    3 ++-
 libavcodec/golomb.h        |    9 +++++----
 libavcodec/mjpeg.h         |   16 ++++++++--------
 libavcodec/mpeg4audio.h    |    3 ++-
 libavcodec/mpegaudiodata.h |    6 ++++--
 libavcodec/raw.h           |    3 ++-
 libavcodec/symbols.h       |   32 ++++++++++++++++++++++++++++++++
 libavformat/gxf.c          |    3 ++-
 libavutil/aes.h            |    4 +++-
 libavutil/common.h         |    5 +++--
 libavutil/intmath.h        |    3 ++-
 libavutil/md5.h            |    4 +++-
 libavutil/pixdesc.h        |    3 ++-
 libavutil/sha.h            |    4 +++-
 libavutil/symbols.h        |   32 ++++++++++++++++++++++++++++++++
 libavutil/tree.h           |    4 +++-
 library.mak                |    3 ++-
 20 files changed, 120 insertions(+), 33 deletions(-)
 create mode 100644 libavcodec/symbols.h
 create mode 100644 libavutil/symbols.h

diff --git a/configure b/configure
index b7a8b77..2828956 100755
--- a/configure
+++ b/configure
@@ -2616,7 +2616,7 @@ probe_cc(){
         _cc_o='-Fo $@'
         _cc_e='-P -Fi $@'
         _flags_filter=msvc_flags
-        _ld_lib='lib%.a'
+        _ld_lib='%.lib'
         _ld_path='-libpath:'
         _flags='-nologo'
         _cflags='-D_USE_MATH_DEFINES -Dinline=__inline -FIstdlib.h -Dstrtoll=_strtoi64'
@@ -3078,11 +3078,13 @@ case $target_os in
         shlibdir_default="$bindir_default"
         SLIBPREF=""
         SLIBSUF=".dll"
+		LIBPREF=""
+		LIBSUF=".lib"
         SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)'
         SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
         dlltool="${cross_prefix}dlltool"
         if check_cmd lib.exe -list; then
-            SLIB_EXTRA_CMD='-lib.exe /machine:$(LIBTARGET) /def:$$(@:$(SLIBSUF)=.def) /out:$(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib)'
+            SLIB_EXTRA_CMD='-lib.exe -machine:$(LIBTARGET) -def:$$(@:$(SLIBSUF)=.def) -out:$(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib)'
             if enabled x86_64; then
                 LIBTARGET=x64
             fi
@@ -3092,8 +3094,8 @@ case $target_os in
         SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
         SLIB_INSTALL_LINKS=
         SLIB_INSTALL_EXTRA_SHLIB='$(SLIBNAME:$(SLIBSUF)=.lib)'
-        SLIB_INSTALL_EXTRA_LIB='lib$(SLIBNAME:$(SLIBSUF)=.dll.a) $(SLIBNAME_WITH_MAJOR:$(SLIBSUF)=.def)'
-        SHFLAGS='-shared -Wl,--output-def,$$(@:$(SLIBSUF)=.def) -Wl,--out-implib,$(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-auto-image-base'
+        SLIB_INSTALL_EXTRA_LIB='lib$(SLIBNAME:$(SLIBSUF)=.dll) $(SLIBNAME_WITH_MAJOR:$(SLIBSUF)=.def)'
+        SHFLAGS='-dll -def:$$(@:$(SLIBSUF)=.def) -implib:$(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a)'
         objformat="win32"
         ranlib=:
         enable dos_paths
diff --git a/libavcodec/ac3tab.h b/libavcodec/ac3tab.h
index d6e0eed..0063c8d 100644
--- a/libavcodec/ac3tab.h
+++ b/libavcodec/ac3tab.h
@@ -24,6 +24,7 @@
 
 #include "libavutil/common.h"
 #include "ac3.h"
+#include "symbols.h"
 
 #if CONFIG_HARDCODED_TABLES
 #   define HCONST const
@@ -33,7 +34,7 @@
 
 extern const uint16_t ff_ac3_frame_size_tab[38][3];
 extern const uint8_t  ff_ac3_channels_tab[8];
-extern const uint16_t avpriv_ac3_channel_layout_tab[8];
+extern AVCODEC_SYMBOL const uint16_t avpriv_ac3_channel_layout_tab[8];
 extern const uint8_t  ff_ac3_enc_channel_map[8][2][6];
 extern const uint8_t  ff_ac3_dec_channel_map[8][2][6];
 extern const uint16_t ff_ac3_sample_rate_tab[3];
diff --git a/libavcodec/dca.h b/libavcodec/dca.h
index 4d2a829..e754056 100644
--- a/libavcodec/dca.h
+++ b/libavcodec/dca.h
@@ -26,6 +26,7 @@
 #define AVCODEC_DCA_H
 
 #include <stdint.h>
+#include "symbols.h"
 
 /** DCA syncwords, also used for bitstream type detection */
 #define DCA_MARKER_RAW_BE 0x7FFE8001
@@ -36,6 +37,6 @@
 /** DCA-HD specific block starts with this marker. */
 #define DCA_HD_MARKER     0x64582025
 
-extern const uint32_t avpriv_dca_sample_rates[16];
+extern AVCODEC_SYMBOL const uint32_t avpriv_dca_sample_rates[16];
 
 #endif /* AVCODEC_DCA_H */
diff --git a/libavcodec/dnxhddata.h b/libavcodec/dnxhddata.h
index 6e774b5..8572d91 100644
--- a/libavcodec/dnxhddata.h
+++ b/libavcodec/dnxhddata.h
@@ -24,6 +24,7 @@
 
 #include <stdint.h>
 #include "avcodec.h"
+#include "symbols.h"
 
 typedef struct {
     int cid;
@@ -44,7 +45,7 @@ typedef struct {
     int bit_rates[5]; ///< Helpher to choose variants, rounded to nearest 5Mb/s
 } CIDEntry;
 
-extern const CIDEntry ff_dnxhd_cid_table[];
+extern AVCODEC_SYMBOL const CIDEntry ff_dnxhd_cid_table[];
 
 int ff_dnxhd_get_cid_table(int cid);
 int ff_dnxhd_find_cid(AVCodecContext *avctx, int bit_depth);
diff --git a/libavcodec/golomb.h b/libavcodec/golomb.h
index 0ce1b34..35d81b4 100644
--- a/libavcodec/golomb.h
+++ b/libavcodec/golomb.h
@@ -33,13 +33,14 @@
 #include <stdint.h>
 #include "get_bits.h"
 #include "put_bits.h"
+#include "symbols.h"
 
 #define INVALID_VLC           0x80000000
 
-extern const uint8_t ff_golomb_vlc_len[512];
-extern const uint8_t ff_ue_golomb_vlc_code[512];
-extern const  int8_t ff_se_golomb_vlc_code[512];
-extern const uint8_t ff_ue_golomb_len[256];
+extern AVCODEC_SYMBOL const uint8_t ff_golomb_vlc_len[512];
+extern AVCODEC_SYMBOL const uint8_t ff_ue_golomb_vlc_code[512];
+extern AVCODEC_SYMBOL const  int8_t ff_se_golomb_vlc_code[512];
+extern AVCODEC_SYMBOL const uint8_t ff_ue_golomb_len[256];
 
 extern const uint8_t ff_interleaved_golomb_vlc_len[256];
 extern const uint8_t ff_interleaved_ue_golomb_vlc_code[256];
diff --git a/libavcodec/mjpeg.h b/libavcodec/mjpeg.h
index d826278..d9cff5b 100644
--- a/libavcodec/mjpeg.h
+++ b/libavcodec/mjpeg.h
@@ -35,7 +35,7 @@
 
 #include "avcodec.h"
 #include "put_bits.h"
-
+#include "symbols.h"
 
 /* JPEG marker codes */
 typedef enum {
@@ -138,16 +138,16 @@ static inline void put_marker(PutBitContext *p, int code)
         case 7: ret= (left + top)>>1; break;\
     }
 
-extern const uint8_t avpriv_mjpeg_bits_dc_luminance[];
-extern const uint8_t avpriv_mjpeg_val_dc[];
+extern AVCODEC_SYMBOL const uint8_t avpriv_mjpeg_bits_dc_luminance[];
+extern AVCODEC_SYMBOL const uint8_t avpriv_mjpeg_val_dc[];
 
-extern const uint8_t avpriv_mjpeg_bits_dc_chrominance[];
+extern AVCODEC_SYMBOL const uint8_t avpriv_mjpeg_bits_dc_chrominance[];
 
-extern const uint8_t avpriv_mjpeg_bits_ac_luminance[];
-extern const uint8_t avpriv_mjpeg_val_ac_luminance[];
+extern AVCODEC_SYMBOL const uint8_t avpriv_mjpeg_bits_ac_luminance[];
+extern AVCODEC_SYMBOL const uint8_t avpriv_mjpeg_val_ac_luminance[];
 
-extern const uint8_t avpriv_mjpeg_bits_ac_chrominance[];
-extern const uint8_t avpriv_mjpeg_val_ac_chrominance[];
+extern AVCODEC_SYMBOL const uint8_t avpriv_mjpeg_bits_ac_chrominance[];
+extern AVCODEC_SYMBOL const uint8_t avpriv_mjpeg_val_ac_chrominance[];
 
 void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code,
                                   const uint8_t *bits_table,
diff --git a/libavcodec/mpeg4audio.h b/libavcodec/mpeg4audio.h
index 21000a9..69ddc2e 100644
--- a/libavcodec/mpeg4audio.h
+++ b/libavcodec/mpeg4audio.h
@@ -25,6 +25,7 @@
 #include <stdint.h>
 #include "get_bits.h"
 #include "put_bits.h"
+#include "symbols.h"
 
 typedef struct {
     int object_type;
@@ -40,7 +41,7 @@ typedef struct {
     int ps;  ///< -1 implicit, 1 presence
 } MPEG4AudioConfig;
 
-extern const int avpriv_mpeg4audio_sample_rates[16];
+extern AVCODEC_SYMBOL const int avpriv_mpeg4audio_sample_rates[16];
 extern const uint8_t ff_mpeg4audio_channels[8];
 
 /**
diff --git a/libavcodec/mpegaudiodata.h b/libavcodec/mpegaudiodata.h
index c0d595e..f4d86d8 100644
--- a/libavcodec/mpegaudiodata.h
+++ b/libavcodec/mpegaudiodata.h
@@ -29,11 +29,13 @@
 
 #include <stdint.h>
 
+#include "symbols.h"
+
 #define MODE_EXT_MS_STEREO 2
 #define MODE_EXT_I_STEREO  1
 
-extern const uint16_t avpriv_mpa_bitrate_tab[2][3][15];
-extern const uint16_t avpriv_mpa_freq_tab[3];
+extern AVCODEC_SYMBOL const uint16_t avpriv_mpa_bitrate_tab[2][3][15];
+extern AVCODEC_SYMBOL const uint16_t avpriv_mpa_freq_tab[3];
 extern const int ff_mpa_sblimit_table[5];
 extern const int ff_mpa_quant_steps[17];
 extern const int ff_mpa_quant_bits[17];
diff --git a/libavcodec/raw.h b/libavcodec/raw.h
index 4724cd3..f5dd067 100644
--- a/libavcodec/raw.h
+++ b/libavcodec/raw.h
@@ -28,13 +28,14 @@
 #define AVCODEC_RAW_H
 
 #include "avcodec.h"
+#include "symbols.h"
 
 typedef struct PixelFormatTag {
     enum PixelFormat pix_fmt;
     unsigned int fourcc;
 } PixelFormatTag;
 
-extern const PixelFormatTag ff_raw_pix_fmt_tags[];
+extern AVCODEC_SYMBOL const PixelFormatTag ff_raw_pix_fmt_tags[];
 enum PixelFormat ff_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc);
 
 #endif /* AVCODEC_RAW_H */
diff --git a/libavcodec/symbols.h b/libavcodec/symbols.h
new file mode 100644
index 0000000..ca4a89d
--- /dev/null
+++ b/libavcodec/symbols.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012 Ronald S. Bultje <rsbultje at gmail.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_SYMBOLS_H
+#define AVCODEC_SYMBOLS_H
+
+#include "libavutil/avconfig.h"
+
+#if AV_HAVE_SHARED_LIBS && defined(_MSC_VER) && !defined(COMPILING_avcodec)
+#define AVCODEC_SYMBOL __declspec(dllimport)
+#else
+#define AVCODEC_SYMBOL
+#endif
+
+#endif /* AVCODEC_SYMBOLS_H */
diff --git a/libavformat/gxf.c b/libavformat/gxf.c
index 9f000d0..8df8933 100644
--- a/libavformat/gxf.c
+++ b/libavformat/gxf.c
@@ -20,6 +20,7 @@
  */
 
 #include "libavutil/common.h"
+#include "libavcodec/symbols.h"
 #include "avformat.h"
 #include "internal.h"
 #include "gxf.h"
@@ -207,7 +208,7 @@ static void gxf_material_tags(AVIOContext *pb, int *len, struct gxf_stream_info
  * @return fps as AVRational, or 0 / 0 if unknown
  */
 static AVRational fps_tag2avr(int32_t fps) {
-    extern const AVRational avpriv_frame_rate_tab[];
+    extern AVCODEC_SYMBOL const AVRational avpriv_frame_rate_tab[];
     if (fps < 1 || fps > 9) fps = 9;
     return avpriv_frame_rate_tab[9 - fps]; // values have opposite order
 }
diff --git a/libavutil/aes.h b/libavutil/aes.h
index bafa4cc..c73a7a1 100644
--- a/libavutil/aes.h
+++ b/libavutil/aes.h
@@ -23,13 +23,15 @@
 
 #include <stdint.h>
 
+#include "symbols.h"
+
 /**
  * @defgroup lavu_aes AES
  * @ingroup lavu_crypto
  * @{
  */
 
-extern const int av_aes_size;
+extern AVUTIL_SYMBOL const int av_aes_size;
 
 struct AVAES;
 
diff --git a/libavutil/common.h b/libavutil/common.h
index 3e3baab..868ebab 100644
--- a/libavutil/common.h
+++ b/libavutil/common.h
@@ -36,6 +36,7 @@
 #include <string.h>
 #include "attributes.h"
 #include "libavutil/avconfig.h"
+#include "symbols.h"
 
 #if AV_HAVE_BIGENDIAN
 #   define AV_NE(be, le) (be)
@@ -62,12 +63,12 @@
 #define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1))
 
 /* misc math functions */
-extern const uint8_t ff_log2_tab[256];
+extern AVUTIL_SYMBOL const uint8_t ff_log2_tab[256];
 
 /**
  * Reverse the order of the bits of an 8-bits unsigned integer.
  */
-extern const uint8_t av_reverse[256];
+extern AVUTIL_SYMBOL const uint8_t av_reverse[256];
 
 static av_always_inline av_const int av_log2_c(unsigned int v)
 {
diff --git a/libavutil/intmath.h b/libavutil/intmath.h
index 9cba406..461319d 100644
--- a/libavutil/intmath.h
+++ b/libavutil/intmath.h
@@ -24,6 +24,7 @@
 #include <stdint.h>
 #include "config.h"
 #include "attributes.h"
+#include "symbols.h"
 
 /**
  * @addtogroup lavu_internal
@@ -55,7 +56,7 @@ extern const uint32_t ff_inverse[257];
 
 #include "common.h"
 
-extern const uint8_t ff_sqrt_tab[256];
+extern AVUTIL_SYMBOL const uint8_t ff_sqrt_tab[256];
 
 static inline av_const unsigned int ff_sqrt(unsigned int a)
 {
diff --git a/libavutil/md5.h b/libavutil/md5.h
index a3534ed..0c42d5c 100644
--- a/libavutil/md5.h
+++ b/libavutil/md5.h
@@ -23,13 +23,15 @@
 
 #include <stdint.h>
 
+#include "symbols.h"
+
 /**
  * @defgroup lavu_md5 MD5
  * @ingroup lavu_crypto
  * @{
  */
 
-extern const int av_md5_size;
+extern AVUTIL_SYMBOL const int av_md5_size;
 
 struct AVMD5;
 
diff --git a/libavutil/pixdesc.h b/libavutil/pixdesc.h
index 1fa916a..f0ae24d 100644
--- a/libavutil/pixdesc.h
+++ b/libavutil/pixdesc.h
@@ -24,6 +24,7 @@
 
 #include <inttypes.h>
 #include "pixfmt.h"
+#include "symbols.h"
 
 typedef struct AVComponentDescriptor{
     uint16_t plane        :2;            ///< which of the 4 planes contains the component
@@ -102,7 +103,7 @@ typedef struct AVPixFmtDescriptor{
 /**
  * The array of all the pixel format descriptors.
  */
-extern const AVPixFmtDescriptor av_pix_fmt_descriptors[];
+extern AVUTIL_SYMBOL const AVPixFmtDescriptor av_pix_fmt_descriptors[];
 
 /**
  * Read a line from an image, and write the values of the
diff --git a/libavutil/sha.h b/libavutil/sha.h
index d891cae..62e4edf 100644
--- a/libavutil/sha.h
+++ b/libavutil/sha.h
@@ -23,13 +23,15 @@
 
 #include <stdint.h>
 
+#include "symbols.h"
+
 /**
  * @defgroup lavu_sha SHA
  * @ingroup lavu_crypto
  * @{
  */
 
-extern const int av_sha_size;
+extern AVUTIL_SYMBOL const int av_sha_size;
 
 struct AVSHA;
 
diff --git a/libavutil/symbols.h b/libavutil/symbols.h
new file mode 100644
index 0000000..6011da2
--- /dev/null
+++ b/libavutil/symbols.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012 Ronald S. Bultje <rsbultje at gmail.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_SYMBOLS_H
+#define AVUTIL_SYMBOLS_H
+
+#include "libavutil/avconfig.h"
+
+#if AV_HAVE_SHARED_LIBS && defined(_MSC_VER) && !defined(COMPILING_avutil)
+#define AVUTIL_SYMBOL __declspec(dllimport)
+#else
+#define AVUTIL_SYMBOL
+#endif
+
+#endif /* AVUTIL_SYMBOLS_H */
diff --git a/libavutil/tree.h b/libavutil/tree.h
index 12f76f0..f2485a7 100644
--- a/libavutil/tree.h
+++ b/libavutil/tree.h
@@ -27,6 +27,8 @@
 #ifndef AVUTIL_TREE_H
 #define AVUTIL_TREE_H
 
+#include "symbols.h"
+
 /**
  * @addtogroup lavu_tree AVTree
  * @ingroup lavu_data
@@ -40,7 +42,7 @@
 
 
 struct AVTreeNode;
-extern const int av_tree_node_size;
+extern AVUTIL_SYMBOL const int av_tree_node_size;
 
 /**
  * Find an element.
diff --git a/library.mak b/library.mak
index 821fe7e..a61680a 100644
--- a/library.mak
+++ b/library.mak
@@ -20,6 +20,7 @@ $(SUBDIR)x86/%.o: $(SUBDIR)x86/%.asm
 	$(DEPYASM) $(YASMFLAGS) -I $(<D)/ -M -o $@ $< > $(@:.o=.d)
 	$(YASM) $(YASMFLAGS) -I $(<D)/ -o $@ $<
 
+$(OBJS): CPPFLAGS := -DCOMPILING_$(NAME)=1 $(CPPFLAGS)
 $(OBJS) $(OBJS:.o=.s) $(SUBDIR)%.h.o $(TESTOBJS): CPPFLAGS += -DHAVE_AV_CONFIG_H
 $(TESTOBJS): CPPFLAGS += -DTEST
 
@@ -94,7 +95,7 @@ endef
 
 $(eval $(RULES))
 
-$(EXAMPLES) $(TESTPROGS) $(TOOLS): $(THIS_LIB) $(DEP_LIBS)
+#$(EXAMPLES) $(TESTPROGS) $(TOOLS): $(THIS_LIB) $(DEP_LIBS)
 $(TESTPROGS): $(SUBDIR)$(LIBNAME)
 
 examples: $(EXAMPLES)
-- 
1.7.9.6 (Apple Git-31.1)



More information about the ffmpeg-devel mailing list