microsoft / vcpkg

C++ Library Manager for Windows, Linux, and MacOS
MIT License
23.27k stars 6.42k forks source link

[ffmpeg] Build error if there is no compiler called "gcc". How to use a different compiler? #20434

Closed Toxe closed 2 years ago

Toxe commented 3 years ago

Host Environment

To Reproduce

  1. Do not have a compiler installed that is called gcc.
  2. CC=/usr/bin/gcc-11 CXX=/usr/bin/g++-11 ./vcpkg install ffmpeg

Failure logs

The following packages will be built and installed:
    ffmpeg[avcodec,avdevice,avfilter,avformat,core,swresample,swscale]:x64-linux -> 4.4#14
Detecting compiler hash for triplet x64-linux...
Restored 0 packages from /home/toxe/.cache/vcpkg/archives in 6.9 us. Use --debug to see more details.
Starting package 1/1: ffmpeg:x64-linux
Building package ffmpeg[avcodec,avdevice,avfilter,avformat,core,swresample,swscale]:x64-linux...
-- Downloading https://github.com/ffmpeg/ffmpeg/archive/n4.4.tar.gz -> ffmpeg-ffmpeg-n4.4.tar.gz...
-- Extracting source /home/toxe/vcpkg/downloads/ffmpeg-ffmpeg-n4.4.tar.gz
-- Applying patch 0001-create-lib-libraries.patch
-- Applying patch 0003-fix-windowsinclude.patch
-- Applying patch 0004-fix-debug-build.patch
-- Applying patch 0006-fix-StaticFeatures.patch
-- Applying patch 0007-fix-lib-naming.patch
-- Applying patch 0009-Fix-fdk-detection.patch
-- Applying patch 0010-Fix-x264-detection.patch
-- Applying patch 0011-Fix-x265-detection.patch
-- Applying patch 0012-Fix-ssl-110-detection.patch
-- Applying patch 0013-define-WINVER.patch
-- Applying patch 0014-avfilter-dependency-fix.patch
-- Applying patch 0015-Fix-xml2-detection.patch
-- Applying patch 0016-configure-dnn-needs-avformat.patch
-- Using source at /home/toxe/vcpkg/buildtrees/ffmpeg/src/n4.4-b04690e0e5.clean
-- Getting CMake variables for x64-linux-dbg
-- Getting CMake variables for x64-linux-rel
-- Building Options: --enable-pic --disable-doc --enable-debug --enable-runtime-cpudetect --enable-asm --enable-x86asm --disable-ffmpeg --disable-ffplay --disable-ffprobe --enable-avcodec --enable-avdevice --enable-avformat --enable-avfilter --disable-postproc --enable-swresample --enable-swscale --disable-libass --disable-avisynth --disable-bzlib --disable-libdav1d --disable-libfdk-aac --disable-libfontconfig --disable-libfreetype --disable-libfribidi --disable-iconv --disable-libilbc --disable-lzma --disable-libmp3lame --disable-libmodplug --disable-cuda --disable-nvenc --disable-nvdec  --disable-cuvid --disable-ffnvcodec --disable-opencl --disable-opengl --disable-libopenh264 --disable-libopenjpeg --disable-openssl --disable-libopus --disable-sdl2 --disable-libsnappy --disable-libsoxr --disable-libspeex --disable-libssh --disable-libtensorflow --disable-libtesseract --disable-libtheora --disable-libvorbis --disable-libvpx --disable-libwebp --disable-libx264 --disable-libx265 --disable-libxml2 --disable-zlib  --pkg-config-flags=--static
-- Building Release Options:
-- Building ffmpeg for Release
CMake Error at scripts/cmake/vcpkg_execute_required_process.cmake:127 (message):
    Command failed: /bin/sh ./build.sh
    Working Directory: /home/toxe/vcpkg/buildtrees/ffmpeg/x64-linux-rel
    Error code: 1
    See logs for more information:
      /home/toxe/vcpkg/buildtrees/ffmpeg/build-x64-linux-rel-out.log

Call Stack (most recent call first):
  ports/ffmpeg/portfile.cmake:651 (vcpkg_execute_required_process)
  scripts/ports.cmake:141 (include)

Error: Building package ffmpeg:x64-linux failed with: BUILD_FAILED
Please ensure you're using the latest portfiles with `./vcpkg update`, then
submit an issue at https://github.com/Microsoft/vcpkg/issues including:
  Package: ffmpeg:x64-linux
  Vcpkg version: 2021-09-10-unknownhash

Additionally, attach any relevant sections from the log files above.

Additional context How can I build FFmpeg with a compiler other than gcc?

I do not have gcc and g++ symlinks on my system (which has never been an issue) but instead I want to manually specify the compiler when installing a new package. For years I have done something like this (or used equivalent settings from VSCode, which is important for switching compiler kits):

CC=/usr/bin/gcc-11 CXX=/usr/bin/g++-11 ./vcpkg install [...]

This has always been fine. But now I have an issue with FFmpeg. Looks like it always wants to use gcc, no matter if I supply a compiler on my call to vcpkg install or not.

Which raises the question: Is it even possible to compile FFmpeg (via Vcpkg) with anything other than GCC? What would be the proper way to specify the compiler when installing a new package? I feel like I am missing something here.

vcpkg\buildtrees\ffmpeg\build-x64-linux-rel-out.log:

gcc is unable to create an executable file.
If gcc is a cross-compiler, use the --enable-cross-compile option.
Only do this if you know what cross compiling means.
C compiler test failed.

If you think configure made a mistake, make sure you are using the latest
version from Git.  If the latest version fails, report the problem to the
ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "ffbuild/config.log" produced by configure as this will help
solve the problem.

Bottom of vcpkg\buildtrees\ffmpeg\x64-linux-rel\ffbuild\config.log:

test_ld cc
test_cc
BEGIN /tmp/ffconf.6XlHizIY/test.c
    1   int main(void){ return 0; }
END /tmp/ffconf.6XlHizIY/test.c
gcc -c -o /tmp/ffconf.6XlHizIY/test.o /tmp/ffconf.6XlHizIY/test.c
/home/toxe/vcpkg/buildtrees/ffmpeg/src/n4.4-b04690e0e5.clean/configure: 984: gcc: not found
C compiler test failed.

How to fix this First of all, if I define gcc and g++ symlinks to GCC 11 everything works fine. But that's not really the point, because how would anyone use a different compiler to build FFmpeg?

I can pass through the options --cc=/usr/bin/gcc-11 and --cxx=/usr/bin/g++-11 to the FFmpeg configure script from the file ports/ffmpeg/build.sh.in (line 94) and that would allow me to build FFmpeg with a different compiler other than gcc:

    sh "$PATH_TO_SRC_DIR/configure" "--prefix=$PATH_TO_PACKAGE_DIR" --cc=/usr/bin/gcc-11 --cxx=/usr/bin/g++-11 @CONFIGURE_OPTIONS@ $@

Now I only need a way to pass these options to ports/ffmpeg/build.sh.in. Basically the portfile should check if $CC or $CXX are defined and then add these options to the call of the FFmpeg configure script, I suppose? Would that be the way to go? Should I make a PR and add these? I'm just a bit puzzled that something like this isn't already possible and I feel like I am missing something on a very fundamental level.

autoantwort commented 3 years ago

The corrent solution is to create an own triplet and set VCPKG_CHAINLOAD_TOOLCHAIN_FILE (The compiler selected by cmake will be passed to every other build system)

dg0yt commented 3 years ago

The corrent solution is to create an own triplet and set VCPKG_CHAINLOAD_TOOLCHAIN_FILE (The compiler selected by cmake will be passed to every other build system)

AFAIU this the correct solution for generally forcing a particular compiler.

However, if all dependencies of ffmpeg build well, and in particular if cmake finds a compiler, then port ffmpeg should perhaps pass the cmake detected compiler to the build script?

Toxe commented 3 years ago

However, if all dependencies of ffmpeg build well, and in particular if cmake finds a compiler, then port ffmpeg should perhaps pass the cmake detected compiler to the build script?

As far as I can tell everything else that Vcpkg does behind the scenes works flawlessly (including the compiler detection bit) which is why I was so confused that it does not pass my compiler to the FFmpeg configure script.

Toxe commented 3 years ago

The corrent solution is to create an own triplet and set VCPKG_CHAINLOAD_TOOLCHAIN_FILE (The compiler selected by cmake will be passed to every other build system)

I never worked with toolchains or custom triplets before and so far this does not work at all for me. I cannot even get beyond the detect compiler step and always get a "No CMAKE_CCOMPILER could be found" error. But honestly even if it would work I am not sure that it would change anything because it still looks to me that my `CMAKE*_COMPILER` settings are just not passed down to the actual FFmpeg configure script.

NancyLi1013 commented 3 years ago

@mcmtroffaes Do you have any suggestion for this problem?

Thanks.

mcmtroffaes commented 3 years ago

At the moment, to the best of my understanding, the ffmpeg configure script simply autodetects the compiler from the environment, and it's quite possible that this doesn't work the same way as with other vcpkg packages. So, explicitly passing CMAKE_*_COMPILER via --cc and --ccx flags to the ffmpeg configure script to ensure the same compiler is used as with other packages feels like the right approach.

Toxe commented 3 years ago

At the moment, to the best of my understanding, the ffmpeg configure script simply autodetects the compiler from the environment, and it's quite possible that this doesn't work the same way as with other vcpkg packages. So, explicitly passing CMAKE_*_COMPILER via --cc and --ccx flags to the ffmpeg configure script to ensure the same compiler is used as with other packages feels like the right approach.

This is how that configure call (line 94 in ports/ffmpeg/build.sh.in) should look like in my case:

sh "$PATH_TO_SRC_DIR/configure" "--prefix=$PATH_TO_PACKAGE_DIR" --cc=/usr/bin/gcc-11 --cxx=/usr/bin/g++-11 @CONFIGURE_OPTIONS@ $@

Is there any "official" way (like some Vcpkg flags) to get the --cc and --cxx options into @CONFIGURE_OPTIONS@? Or would I need to modify this file anytime I want to use a different compiler?

mcmtroffaes commented 3 years ago

The build.sh script is created from build.sh.in by the portfile; see https://github.com/microsoft/vcpkg/blob/master/ports/ffmpeg/portfile.cmake. Instead of using those options, however, it might also be possible to experiment with setting CC and CCX. I just noticed that this is how the CFLAGS etc. are set:

https://github.com/microsoft/vcpkg/blob/master/ports/ffmpeg/portfile.cmake#L639

So for consistency, I guess the compiler could also be set this way, at least if the configure script will then look for these settings (I suspect it will). If that fails, --cc and --cxx should work i.e. through

set(OPTIONS "${OPTIONS} --cc=...")
set(OPTIONS "${OPTIONS} --cxx=...")

at any point prior to https://github.com/microsoft/vcpkg/blob/master/ports/ffmpeg/portfile.cmake#L633

Toxe commented 3 years ago

Setting CC and CXX does not work at the moment, which is my issue. Normally I would call something like:

$ CC=/usr/bin/gcc-11 CXX=/usr/bin/g++-11 ./vcpkg install ffmpeg

But neither the portfile nor the build.sh script respect these settings, and the actual FFmpeg configure script ignores these as well. The output from the FFmpeg configure script does confirm that it actually sees the CC and CXX flags, it just does nothing with those values and ignores them and always just tries plain old gcc. Well, unless we pass in the compiler via the configure --cc=[..] --cxx=[..] options.

I feel like the proper solution would be to update the portfile so that it checks if CC or CXX are set (like it already does for CFLAGS/CXXFLAGS) and then update OPTIONS, as you have shown.

mcmtroffaes commented 3 years ago

Well, I think that the portfile ought to pass CMAKE_C_COMPILER and CMAKE_CXX_COMPILER to the configure script, since that's what the toolchain files use. This will fix situations where potentially compilers get mixed if more than one compiler is installed. But I'm not sure if CC/CXX should be detected at toolchain level or not. Do you know if CMAKE_C_COMPILER gets set to your desired compiler if you call vcpkg with CC=... ./vcpkg ...? If it does, then this will fix also your issue. If it does not, maybe a wider discussion is needed as to what is the correct approach, i.e. whether this needs fixing in the portfile or somewhere else in the vcpkg internal code.

Toxe commented 3 years ago

Sorry, you are right, I actually meant checking if CMAKE_C_COMPILER and CMAKE_CXX_COMPILER are set in the portfile instead of looking for CC/CXX. My bad.

Do you know if CMAKE_C_COMPILER gets set to your desired compiler if you call vcpkg with CC=... ./vcpkg ...?

CMAKE_C_COMPILER is empty in the portfile. Only value I could find that is set was $ENV{CC}. But I'm no expert here and have no idea what values should be available at this stage. Honestly I expected that CMAKE_C_COMPILER would be filled by now but that does not seem to be the case.

If I add the following to the portfile I can build FFmpeg just fine when calling: $ CC=/usr/bin/gcc-11 CXX=/usr/bin/g++-11 ./vcpkg install ffmpeg:

if(DEFINED ENV{CC})
    set(OPTIONS "${OPTIONS} --cc=$ENV{CC}")
endif()

if(DEFINED ENV{CXX})
    set(OPTIONS "${OPTIONS} --cxx=$ENV{CXX}")
endif()

Unless there is a better solution I would suggest adding something like that to the portfile for the time being.

mcmtroffaes commented 3 years ago

Many thanks for running some tests. To me, your suggested patch looks like a very reasonable way solve your problem.

I fear that I don't understand why CMAKE_C_COMPILER and CMAKE_CXX_COMPILER are not set in the portfile... It would be great to get some input from someone who better understands the vcpkg compiler detection mechanics, and to see if there's a better solution than just passing on $ENV{CC} to the configure script.

dg0yt commented 3 years ago

I fear that I don't understand why CMAKE_C_COMPILER and CMAKE_CXX_COMPILER are not set in the portfile..

See the end of the maintainer's guide: Portfiles run in script mode. There is no configuration for any language or similar. Vcpkg has internal maintainer functions to get cmake configuration into portfiles when needed: https://github.com/microsoft/vcpkg/blob/master/docs/maintainers/internal/z_vcpkg_get_cmake_vars.md Normally this is used by other maintainer functions, but ffmpeg doesn't use a standard configuration function.

mcmtroffaes commented 3 years ago

Thanks @dg0yt. That function is actually called here: https://github.com/microsoft/vcpkg/blob/master/ports/ffmpeg/portfile.cmake#L547 Would VCPKG_DETECTED_CMAKE_C_COMPILER work? If so, should we use it?

dg0yt commented 3 years ago

I think you can take inspiration from vcpkg_configure_make. Usually it takes a few more variables, e.g. for flags, linker etc. Only with a complete and consistent set it will work for native builds, cross builds, different osx CPUs...

Neumann-A commented 2 years ago

@JackBoosY can be closed. Should be fixed since the port now sets CC