Conflict between Zlib and FFmpeg when building for MSVC
Hi,
I'm trying to build FFmpeg with the PNG encoder/decoder/mutex, which requires Zlib, under MSVC 2022. This requires Zlib. However, when running the configure checks, one of them validates the existence of unistd.h and stores the result in the macro HAVE_UNISTD_H unconditionally.
When building with compilers such as GCC, this is a no-op because all of them carry unistd.h. But, under MSVC, this causes a Catch-22: the macro is defined to 0, which causes FFmpeg to ignore correctly the parts involving it, but the macro is defined, which causes Zlib to try and include the header:
FAILED: libavcodec-static.a.p/libavcodec_pngenc.c.obj
"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.35.32215/bin/Hostx64/x64/cl.exe" "-Ilibavcodec-static.a.p" "-I." "-I..\ext_ffmpeg" "-I..\ext_ffmpeg\compat\atomics\
win32" "-IE:/krita-win/msvc/i/include" "-IE:/krita-win/msvc/i//include" "/MD" "/nologo" "/showIncludes" "/utf-8" "/W2" "/O2" "/Zi" "/wo4005" "/wd4018" "/wd4146" "/wd4244" "/wd4305" "/wd4554" "/wd4
114" "/wd4028" "/wd4090" "/wd4133" "/utf-8" "-D_ISOC99_SOURCE" "-D_GNU_SOURCE" "-D_LARGEFILE_SOURCE" "-DPIC" "-D_USE_MATH_DEFINES" "-D_CRT_SECURE_NO_WARNINGS" "-D_CRT_NONSTDC_NO_WARNINGS" "-D_WIN3
2_WINNT=0x0600" "-guard:cf" "-DHAVE_AV_CONFIG_H" "-DBUILDING_avcodec" "/Fdlibavcodec-static.a.p\libavcodec_pngenc.c.pdb" /Folibavcodec-static.a.p/libavcodec_pngenc.c.obj "/c" ../ext_ffmpeg/libavco
dec/pngenc.c
E:\krita-win\msvc\i\include\zconf.h(477): fatal error C1083: No se puede abrir el archivo incluir: 'unistd.h': No such file or directory [E:\krita-win\msvc\b_deps\ext_ffmpeg\ext_ffmpeg.vcxproj]
[372/2143] Compiling C object libavcodec-static.a.p/libavcodec_pngdec.c.obj
FAILED: libavcodec-static.a.p/libavcodec_pngdec.c.obj
"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.35.32215/bin/Hostx64/x64/cl.exe" "-Ilibavcodec-static.a.p" "-I." "-I..\ext_ffmpeg" "-I..\ext_ffmpeg\compat\atomics\
win32" "-IE:/krita-win/msvc/i/include" "-IE:/krita-win/msvc/i//include" "/MD" "/nologo" "/showIncludes" "/utf-8" "/W2" "/O2" "/Zi" "/wo4005" "/wd4018" "/wd4146" "/wd4244" "/wd4305" "/wd4554" "/wd4
114" "/wd4028" "/wd4090" "/wd4133" "/utf-8" "-D_ISOC99_SOURCE" "-D_GNU_SOURCE" "-D_LARGEFILE_SOURCE" "-DPIC" "-D_USE_MATH_DEFINES" "-D_CRT_SECURE_NO_WARNINGS" "-D_CRT_NONSTDC_NO_WARNINGS" "-D_WIN3
2_WINNT=0x0600" "-guard:cf" "-DHAVE_AV_CONFIG_H" "-DBUILDING_avcodec" "/Fdlibavcodec-static.a.p\libavcodec_pngdec.c.pdb" /Folibavcodec-static.a.p/libavcodec_pngdec.c.obj "/c" ../ext_ffmpeg/libavco
dec/pngdec.c
E:\krita-win\msvc\i\include\zconf.h(477): fatal error C1083: No se puede abrir el archivo incluir: 'unistd.h': No such file or directory [E:\krita-win\msvc\b_deps\ext_ffmpeg\ext_ffmpeg.vcxproj]
My workaround is to patch Zlib and modify this check as follows:
https://github.com/madler/zlib/blob/04f42ceca40f73e2978b50e93806c2a18c1281fc/zconf.h.cmakein#L442-L444
#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
# ifndef _MSC_VER
# define Z_HAVE_UNISTD_H
# endif
#endif
Another, possibly better way is to remove them altogether from the CMake version (since the cmakedefine will take care of the macro).
Using Zlib 1.2.12 built with CMake 3.25.2 under MSVC 2022 17.6.0 Preview 1.
You're not the only ones to encounter this problem. There's a full patch here in the Microsoft vcpkg repo: https://github.com/microsoft/vcpkg/blob/master/ports/zlib/0001-Prevent-invalid-inclusions-when-HAVE_-is-set-to-0.patch
There are some other handy patches too in the same folder.
To follow