Opened 4 years ago

Closed 3 years ago

Last modified 3 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 4 years ago by cehoyos

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

comment:2 in reply to: ↑ 1 ; follow-up: Changed 4 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 4 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 4 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 4 years ago by Piroxiljin

Well.
The source of the trouble is msvc preprocessor.
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.

Version 2, edited 4 years ago by Piroxiljin (previous) (next) (diff)

comment:6 Changed 4 years ago by cehoyos

  • Status changed from new to open

comment:7 Changed 4 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 4 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 4 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 4 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 3 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 3 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 3 years ago by cehoyos

Could you test the following?
$ make ffmpeg.exe

comment:14 Changed 3 years ago by Piroxiljin

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

comment:15 Changed 3 years ago by cehoyos

Could you test again with git head?

comment:16 Changed 3 years ago by Piroxiljin

Great!
$ make
is done without errors!

comment:17 Changed 3 years ago by cehoyos

Thank you for testing again!

comment:18 Changed 3 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.