AviSynth / AviSynthPlus

AviSynth with improvements
http://avs-plus.net
977 stars 75 forks source link

Cross compilation in mingw #363

Open artenax opened 1 year ago

artenax commented 1 year ago

Hello. I am trying to cross compile avisynth with mingw in linux (mageia 8) for windows, but I get an error:

cmake .. -DBUILD_COFFVERTSTACKED:BOOL=OFF -DBUILD_DIRECTSHOWSOURCE:BOOL=OFF -DBUILD_IMAGESEQ:BOOL=OFF -DBUILD_SHARED_LIBS:BOOL=ON -DBUILD_SHIBATCH:BOOL=OFF -DBUILD_TIMESTRETCH:BOOL=OFF -DBUILD_VDUBFILTER:BOOL=OFF -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr/local -DENABLE_CUDA:BOOL=OFF -DENABLE_INTEL_SIMD:BOOL=OFF -DENABLE_PLUGINS:BOOL=OFF -DHEADERS_OFFLY:BOOL=OFF -DCMAKE_TOOLCHAIN_FILE=/home/denis/mingw.cmake make

17% MTGuard error mmintrin.h error: inlining failed in call to 'always_inline' 'void _mm_empty()': target specific option mismatch

Is this way of compiling not supported?

mingw.cmake:

# the name of the target operating system
set(CMAKE_SYSTEM_NAME Windows)

# which compilers to use for C and C++
set(CMAKE_C_COMPILER   i686-w64-mingw32-gcc)
set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)

# where is the target environment located
set(CMAKE_FIND_ROOT_PATH  /usr/i686-w64-mingw32)

# adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# search headers and libraries in the target environment
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

set(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.dll.a")
set(CMAKE_EXE_LINKER_FLAGS "-static")
qyot27 commented 1 year ago

Why are you disabling everything? But even beyond that, have you tried using the master branch?

artenax commented 1 year ago

I decided to disable everything first to minimize the risk of errors. With the default options there is the same error. I'm using the master branch, I forgot to do a git checkout on release.

qyot27 commented 1 year ago

I can't reproduce it here, even when disabling INTEL_SIMD and using CMAKE_BUILD_TYPE=Release. I vaguely remember an error with mmintrin from quite a while back, and I think it was actually a problem in MinGW-w64 that was fixed with one of their updates. The mmintrin intrinsics (which should have been disabled when disabling Intel SIMD) are provided inside of the compiler headers from MinGW-w64 or GCC.

My cross toolchain is MinGW-w64 v10.0.0, multilib GCC 13.1.0. It would appear that Mageia is still on MinGW-w64 version 8.

cmake ../../ -G "Ninja" -DCMAKE_INSTALL_PREFIX=/usr/i686-w64-mingw32 \ -DCMAKE_TOOLCHAIN_FILE="/usr/x86_64-w64-mingw32/toolchain-x86_64-w64-mingw32.cmake" \ -DCMAKE_C_FLAGS="-m32" -DCMAKE_CXX_FLAGS="-m32" -DCMAKE_RC_FLAGS="-F pe-i386" \ -DCMAKE_SYSTEM_PROCESSOR=i686

-- The CXX compiler identification is GNU 13.1.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/x86_64-w64-mingw32-g++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Detected target processor as: i686
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE  
-- The C compiler identification is GNU 13.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/x86_64-w64-mingw32-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Found Git: /usr/bin/git (found version "2.39.2") 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/qyot27/AviSynthPlus/avisynth-build/i686

$ ninja
[148/148] Linking CXX shared library avs_core/AviSynth.dll

CMake toolchain file:

# Sample toolchain file for building for Windows from an Ubuntu Linux system.
#
# Typical usage:
#    1) install cross compiler: `sudo apt-get install mingw-w64 g++-mingw-w64`
#    2) cp cmake/Toolchain-Ubuntu-mingw32.cmake.sample ~/Toolchain-Ubuntu-mingw32.cmake
#    3) tweak toolchain values as needed
#    4) cd build
#    5) cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-Ubuntu-mingw32.cmake ..

# name of the target OS on which the built artifacts will run
# and the toolchain prefix
set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)

# cross compilers to use for C and C++
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)

# target environment on the build host system
#   set 1st to dir with the cross compiler's C/C++ headers/libs
#   set 2nd to dir containing personal cross development headers/libs
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})

# modify default behavior of FIND_XXX() commands to
# search for headers/libs in the target environment and
# search for programs in the build host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

What exactly is the end goal, though? Building AviSynth+ to use it on Windows, or simply to enable support for it in a cross-compiled build of FFmpeg?

artenax commented 1 year ago

I was able to compile in Debian 12 after I removed the packages mingw*win32 (and left mingw*posix) and removed the cmake option -DCMAKE_BUILD_TYPE:STRING=Release

Do I understand correctly that all plugins must also be compiled with mingw? I tried to use the ffms2 input plugin (which is built in msvc) and output in VirtualDub (wine), but got an error: AVI Import Filter error (Unknown) (8004015) With the original avisynth it works.

No, I don't need the headers and ffmpeg.exe. I am interested in an exotic compilation of avisynth in mingw as an experiment. Few people do that. And because I don't have the space to install Visual Studio. I'm even ready to compile some plugins with mingw (which QTGMC deinterlacing needs). I don't think it will be successful, though. To use avisynth in wine. Of course, I know about the native linux version and I already have it.

artenax commented 1 year ago

Well, trying to open the avs script in ffmpeg.exe in wine I saw an error that libgcc_s_dw2-1.dll, libstdc++-6.dll and libwinpthread-1.dll are missing. I copied them from the debian mingw installation (without strip), the right posix version and i686 architecture, and put them in C:\windows (wine installation). This crashed ffmpeg.exe in wine. See log. Something about "can't find symbol in module". avisynth-ffmpeg-error.txt VirtualDub has the same error it had before.

qyot27 commented 1 year ago

Not all plugins have to be recompiled in that case. Only C++ plugins...which is the vast majority of them. C plugins will work fine.

But standard i686 FFmpeg builds cannot use i686 MinGW builds of AviSynth+ because of win32 calling convention issues. It requires a separate build of FFmpeg that was built with -DAVSC_WIN32_GCC32 passed to --extra-cflags.

artenax commented 1 year ago

Does this mean that AVISource (in VirtualDub) and MPC-HC (AVISource/directshowsource) will not work either?

Despite the big difficulties I could not compile the ffms2 plugin. undefined reference. I must be confuse win32 and posix again in some dependency (ffms2 also needs win zlib). This made me tired. Such a limited build of avisynth mingw makes no sense.

qyot27 commented 1 year ago

AVISource works fine (although getting VfW codecs configured under Wine is sometimes a challenge), DirectShowSource doesn't build with GCC so that's moot. VirtualDub and MPC-HC are not going to work with a 32-bit MinGW build of AviSynth+, because of the calling convention issue I mentioned earlier. Anything that assumes a normal MSVC build of 32-bit AviSynth won't work with 32-bit MinGW builds, and vice-versa.

There's some issues when using ffms2's autotools system for cross-compiling. I normally use the C plugin's custom build system (https://github.com/qyot27/ffms2/ = 'cplugin_master' or 'patches' branch) for that; I hooked it up to allow building the C++ plugin several years ago.

(assuming the FFmpeg that you're linking to FFMS2 is installed in $HOME/mpv-build-deps/ffmpeg_build_for_ffms2/i686)

git clone -b patches https://github.com/qyot27/ffms2 && \
cd ffms2 && \
    PKG_CONFIG_PATH=/usr/i686-w64-mingw32/lib/pkgconfig:$HOME/mpv-build-deps/ffmpeg_build_for_ffms2/i686/lib/pkgconfig \
    RCFLAGS="-F pe-i386" ./configure --prefix=$HOME/mpv-build-deps/ffms2-avs/i686 \
    --cross-prefix=x86_64-w64-mingw32- --host=i686-pc-mingw32 \
    --sysroot=/usr/i686-w64-mingw32 --enable-shared --enable-avisynth-cpp \
    --extra-cppflags="-m32 -mfpmath=sse -march=pentium3 -msse -mtune=pentium3" \
    --extra-ldflags="-m32 -I/usr/i686-w64-mingw32/lib" && \
make -j$(nproc) && \
make install-avs

Largely, MinGW-w64/GCC builds of AviSynth+ are best considered experimental, whether you're talking about 32-bit or 64-bit (but the 64-bit ones are more useful since you can use normal FFmpeg, VirtualDub, etc.). It was an important step to being able to build natively for *nix, but because on Windows there's so much historical inertia toward MSVC it's way more niche to use MinGW builds.

artenax commented 1 year ago

Thank you for this helpful information. I understand that mingw compilation became possible after porting to Unix. I have not yet been able to build ffms2. Does ffms2 from your repository require zlib? If you have a built ffms2.dll (mingw i686), please share it.

qyot27 commented 1 year ago

I understand that mingw compilation became possible after porting to Unix.

The other way around: MinGW/GCC was added in 2016, native Linux/macOS/BSD support in 2020 (Haiku in 2021).

If you have a built ffms2.dll (mingw i686), please share it.

ffms2_r1405+139

The -c++ ones are using the C++ interface and when using a MinGW build of AviSynth, be placed in the plugins_gcc or plugins64_gcc directories in order to autoload (said directories probably also need to be hooked into the relevant registry entries). Or just use LoadPlugin with the correct path if you want to skip autoloading.

artenax commented 1 year ago

I compiled ffms2 and also checked yours, everything works. I had to install the libz-mingw-w64-dev package and then copy zlib1.dll. Only ffmpeg.exe compiled with --extra-cflags="-DAVSC_WIN32_GCC32" works and nothing else. For ffms3.dll only manual run. This will not work on XP because of the posix model and the new gcc, and most likely even on Vista. But it is interesting. I'm posting my files, although it's unlikely that anyone will be interested. I will try to compile more plugins and a more complete ffmpeg.exe. Thanks for your tips. avisynth-mingw.zip

You can apply i686-w64-mingw32-strip --strip-unneeded to reduce the size, I haven't done that yet. And the original installer must be installed first, of course. Maybe someone would like to develop the mingw branch (plugins).

artenax commented 1 year ago

I was able to compile yadifmod2, but not TIVTC. libyadifmod2.0.2.7.zip

pinterf commented 1 year ago

I checked TIVTC readme.MD and it seems that I succeeded in compiling it (I don't remember exactly, but I usually try it before putting it into documentation)

artenax commented 1 year ago

@pinterf You checked in Mingw running in Windows (-G "MinGW Makefiles" indicates this, as well as Msys). I'm trying a rather exotic way of cross-compiling on Linux (on Linux MinGW) for Windows by specifying -DCMAKE_TOOLCHAIN_FILE And also Msys2 hasn't officially supported i686 for a long time (although repositories are available), and I compile for i686. MinGW in Debian 12. There are two win32 and posix models. I have tried both and all have different compilation errors. However there is an error there when compiling even the native Linux version. In Mageia 8 the native Linux version compiles, but mingw for Windows does not.

artenax commented 1 year ago

I managed to cross compile TIVTC 1.0.27 5fcdade5107e51e255fe3919a6a0361c29176d26 (posix threads) after the following edits:

/TIVTC/src/common/info.cpp
/TIVTC/src/common/info.h
add #include <memory>
/TIVTC/src/TDeint/TSwitch.cpp
Windows.h > windows.h

TIVTC-1.0.27.zip libAddGrainC.zip ffmpeg-6.0-i686-full.zip

pinterf commented 1 year ago

Thanks, I'm going to integrate your findings

pinterf commented 1 year ago

Windows.h appears with capital W in my Window system in the original filename. Is yours really with small w letter?

artenax commented 1 year ago

@pinterf Yes, MinGW on Linux uses windows.h and the file system is case sensitive. This would not be a problem with MinGW on Windows or Msys2.

artenax commented 1 year ago

@qyot27 Do you use Arch Linux? Arch Linux provides only the posix threads model, as does Mageia. Debian and Ubuntu ship both win32 (by default) and posix. win32 is compatible with XP, although the newer versions of gcc/mingw have some incompatibilities. Maybe I am wrong.

qyot27 commented 1 year ago

Ubuntu, but I haven't used their cross toolchain in well over 10 years, if I ever did. I just build it myself so I can ensure the cross environment and FFmpeg/mpv dependency chain is as fully static as possible/feasible.

And yes, I think it was MinGW-w64 7 or 8 that introduced the Secure API or made it default, and if the Secure API is enabled, the builds will not work on XP. Further, if you plan on building FFmpeg, which for a couple years now has required one or more of the functions from the Secure API and/or Vista+ cryptographic libraries, you have to really dig deep to revert changes to keep XP support in FFmpeg around and justify keeping MinGW's Secure API functionality disabled.

At some point - if not already - it'll be easier to just tell people to go use ReactOS if they want an XP-ish desktop experience but not be bound by the incompatibility issues.