Opened 5 years ago

Closed 4 years ago

Last modified 4 years ago

#2049 closed defect (fixed)

msvc: --extra-cflags="-MD" leads to unresolved externals

Reported by: Piroxiljin Owned by:
Priority: normal Component: build system
Version: git-master Keywords: msvc
Cc: Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

Summary of the bug:
Compilation ffmpeg with toolchain=msvc leads to unresolved external simbols.

How to reproduce:
I use guide from this page: http://blogs.gnome.org/rbultje/2012/09/27/microsoft-visual-studio-support-in-ffmpeg-and-libav/

I.e.

  • Open MSVC2010 command prompt
  • Run mingw-msys shell

c:\mingw\msys\1.0\msys.bat

  • configure ffmpeg

./configure --toolchain=msvc --extra-cflags="-MD"
Waiting, while configuration has done.

  • make

At the end of building I have error messages:

LD      ffmpeg_g.exe
LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; us
e /NODEFAULTLIB:library
libavutil.a(opt.o) : error LNK2001: unresolved external symbol __imp__avpriv_snp
rintf
libavutil.a(pixdesc.o) : error LNK2001: unresolved external symbol __imp__avpriv
_snprintf
libavutil.a(samplefmt.o) : error LNK2001: unresolved external symbol __imp__avpr
iv_snprintf

...

ffmpeg.o : error LNK2019: unresolved external symbol __imp__avpriv_vsnprintf ref
erenced in function _update_benchmark
libavformat.a(aviobuf.o) : error LNK2001: unresolved external symbol __imp__avpr
iv_vsnprintf
libavformat.a(utils.o) : error LNK2001: unresolved external symbol __imp__avpriv
_vsnprintf
libavformat.a(rtpproto.o) : error LNK2001: unresolved external symbol __imp__avp
riv_vsnprintf
libavformat.a(rtmpproto.o) : error LNK2019: unresolved external symbol __imp__av
priv_strtod referenced in function _rtmp_write_amf_data
libavformat.a(sbgdec.o) : error LNK2001: unresolved external symbol __imp__avpri
v_strtod
libavutil.a(parseutils.o) : error LNK2001: unresolved external symbol __imp__avp
riv_strtod
libavutil.a(eval.o) : error LNK2001: unresolved external symbol __imp__avpriv_st
rtod
ffmpeg_g.exe : fatal error LNK1120: 3 unresolved externals
make: *** [ffmpeg_g.exe] Error 1

Change History (18)

comment:1 follow-up: Changed 5 years ago by cehoyos

Why do you want to add -MD to the compiler flags?

comment:2 in reply to: ↑ 1 ; follow-up: Changed 5 years ago by Piroxiljin

Replying to cehoyos:

Why do you want to add -MD to the compiler flags?

I use ffmpeg libraries, and my application and all other libraries are linked with DLL run-time library.

MSDN: /MD, /MT, /LD (Use Run-Time Library) (http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=vs.100).aspx)

-MD Causes your application to use the multithread- and DLL-specific version of the run-time library.
-MT Causes your application to use the multithread, static version of the run-time library.

Also, I found out that prefix __imp__ appears when object-file compiles with -MD. In another way (without -MD, or with -MT) all unresolved symbols has another prefix.(I'm not sure, but I belive it just underscore. I'll check it tomorrow. ) And those object-files (and static libavutils.a) successfully linked with ffmpeg.exe

comment:3 in reply to: ↑ 2 ; follow-up: Changed 5 years ago by cehoyos

Replying to Piroxiljin:

Replying to cehoyos:

Why do you want to add -MD to the compiler flags?

MSDN: /MD, /MT, /LD (Use Run-Time Library) (http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=vs.100).aspx)

-MD Causes your application to use the multithread- and DLL-specific version of the run-time library.

I had also read that page today and please excuse my ignorance but are you sure that "/MD" is the same as "-MD"?

comment:4 in reply to: ↑ 3 Changed 5 years ago by Piroxiljin

Replying to cehoyos:

Replying to Piroxiljin:

Replying to cehoyos:

Why do you want to add -MD to the compiler flags?

MSDN: /MD, /MT, /LD (Use Run-Time Library) (http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=vs.100).aspx)

-MD Causes your application to use the multithread- and DLL-specific version of the run-time library.

I had also read that page today and please excuse my ignorance but are you sure that "/MD" is the same as "-MD"?

Compiler Command-Line Syntax (http://msdn.microsoft.com/en-us/library/610ecb4h(v=vs.100).aspx)

CL [option...] file... [option | file]... [lib...] [@command-file] [/link link-opt...]
option - One or more CL options. Note that all options apply to all specified source files. Options are specified by either a forward slash (/) or a dash (–). If an option takes an argument, the option's description documents whether a space is allowed between the option and the arguments. Option names (except for the /HELP option) are case sensitive. See Order of CL Options for more information.

Yes, I am.

comment:5 Changed 5 years ago by Piroxiljin

Well.
The source of the trouble is msvc preprocessor and declaration of funtions in standart library, when compiles with DLL runtime.
Compilation is evoked with command like this

c99wrap cl -I. -I./ -D_ISOC99_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
-Dstrtod=avpriv_strtod -Dsnprintf=avpriv_snprintf -D_snprintf=avpriv_snprintf \
-Dvsnprintf=avpriv_vsnprintf -DHAVE_AV_CONFIG_H -nologo -D_USE_MATH_DEFINES \
-Dinline=__inline -FIstdlib.h -Dstrtoll=_strtoi64   -Oy -Z7 -W4 -wd4244 \
-wd4127 -wd4018 -wd4389 -wd4146 -wd4057 -wd4204 -wd4706 -wd4305 -wd4152 \
-wd4324 -we4013 -wd4100 -wd4214 -wd4554 -wd4996 -wd4273 -O2 -MD     -c \
-Fo libavutil/../compat/msvcrt/snprintf.o libavutil/../compat/msvcrt/snprintf.c

Here we have preprocessor defines which replace "snprintf" to "avpriv_snprintf"
Also, preprocessed source file includes declarations of _snprintf ( and another functions from standart library). When we compile with -MD option, this functions are declared as

#pragma warning(push)
#pragma warning(disable:4793)
__declspec(deprecated("This function or variable may be unsafe. Consider using " \
"_snprintf_s" " instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.")) \

__declspec(dllimport) int __cdecl _snprintf(   char *_Dest,   size_t _Count,     const char * _Format, ...);\

 __declspec(deprecated("This function or variable may be unsafe. Consider using " "_vsnprintf_s" " instead. \
To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.")) \

__declspec(dllimport) int __cdecl _vsnprintf(   char *_Dest,   size_t _Count,     const char * _Format, va_list _Args);
#pragma warning(pop)

I.e. this functions declared as imported from DLL.

But preprocessor replace such declarations and so we have our avpriv_snprintf function is declared as imported.

Last edited 5 years ago by Piroxiljin (previous) (diff)

comment:6 Changed 5 years ago by cehoyos

  • Status changed from new to open

comment:7 Changed 5 years ago by cehoyos

Is it sufficient to just compile snprintf.c manually without the defines that cause the trouble or are the defines bad for all source files?

comment:8 Changed 5 years ago by Piroxiljin

In this way, you need to compile manualy every file which uses redefined functions.

Also, this page (http://ffmpeg.org/platform.html#Linking-to-FFmpeg-with-Microsoft-Visual-C_002b_002b) notifies that one must link project with static runtime (/MT option).

Right now, I just compile shared library with static runtime.

comment:9 Changed 5 years ago by reimar

Since we do not use _snprintf I don't understand why that define is there.
Could you try with this configure patch, if that makes all cases work:

--- a/configure
+++ b/configure
@@ -3372,7 +3372,6 @@ elif check_func_headers stdlib.h _get_doserrno; then
     libc_type=msvcrt
     add_compat strtod.o strtod=avpriv_strtod
     add_compat msvcrt/snprintf.o snprintf=avpriv_snprintf   \
-                                 _snprintf=avpriv_snprintf  \
                                  vsnprintf=avpriv_vsnprintf
 elif check_cpp_condition stddef.h "defined __KLIBC__"; then
     libc_type=klibc

comment:10 Changed 5 years ago by Piroxiljin

$ make
echo @printf "CC\t%s\n" libavfilter/af_amix.o; c99wrap cl -I. -I./ -D_ISOC99_SOU
RCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Dstrtod=avpriv_strtod -Dsnprintf
=avpriv_snprintf -Dvsnprintf=avpriv_vsnprintf -DHAVE_AV_CONFIG_H -nologo -D_USE_
MATH_DEFINES -Dinline=__inline -FIstdlib.h -Dstrtoll=_strtoi64 -Z7 -MD  -Oy -Z7
-W4 -wd4244 -wd4127 -wd4018 -wd4389 -wd4146 -wd4057 -wd4204 -wd4706 -wd4305 -wd4
152 -wd4324 -we4013 -wd4100 -wd4214 -wd4554 -wd4996 -wd4273 -O2     -c -Fo libav
filter/af_amix.o libavfilter/af_amix.c
@printf CC\t%s\n libavfilter/af_amix.o
af_amix.c
d:\user\Alex\projects\ffmpeg\msvc-10-debug\3\ffmpeg-HEAD-1166fc0\config.h(9) : w
arning C4005: 'av_restrict' : macro redefinition
        d:\user\alex\projects\ffmpeg\msvc-10-debug\3\ffmpeg-head-1166fc0\libavut
il\attributes.h(66) : see previous definition of 'av_restrict'
af_amix.o_converted.c
libavfilter/af_amix.c(502) : error C4013: 'avpriv_snprintf' undefined; assuming
extern returning int
libavfilter/af_amix.c(531) : warning C4090: 'function' : different 'const' quali
fiers
make: *** [libavfilter/af_amix.o] Error 1

comment:11 Changed 4 years ago by cehoyos

  • Resolution set to fixed
  • Status changed from open to closed

Should be fixed by Martin Storsjö since 760f7d3, please test!

comment:12 Changed 4 years ago by Piroxiljin

Well.

./configure --toolchain=msvc --extra-cflags="-MD"
make ffmpeg.exe

now produces executable, but

./configure --toolchain=msvc --extra-cflags="-MD"
make

produces link error

HOSTLD  doc/print_options.exe
cl : Command line warning D9002 : ignoring unknown option '-lm'
cl : Command line warning D9024 : unrecognized source file type 'doc/print_optio
ns.o', object file assumed
print_options.o : error LNK2001: unresolved external symbol _avpriv_strtod
print_options.o : error LNK2001: unresolved external symbol _avpriv_snprintf
doc/print_options.exe : fatal error LNK1120: 2 unresolved externals
make: *** [doc/print_options.exe] Error 1

comment:13 Changed 4 years ago by cehoyos

Could you test the following?
$ make ffmpeg.exe

comment:14 Changed 4 years ago by Piroxiljin

make ffmpeg.exe
produces a lot of warnings, but linking is successful.

comment:15 Changed 4 years ago by cehoyos

Could you test again with git head?

comment:16 Changed 4 years ago by Piroxiljin

Great!
$ make
is done without errors!

comment:17 Changed 4 years ago by cehoyos

Thank you for testing again!

comment:18 Changed 4 years ago by nikolaynnov

As I remember on old ffmpeg I have used workaround like:

libavtuil/common.h:

#if _MSC_VER
#define snprintf _snprintf
#endif

Note: See TracTickets for help on using tickets.