简体   繁体   中英

cmake installation of x265 for ffmpeg on Cygwin - executable location different from other codecs

TL;DR (with expected vs. real)

For a Cygwin build of ffmpeg , I'm installing x265 , and it seems to me that the executable ends up in the wrong place. I'll show some basic directory structure, then I'll show the tree outputs for expected and real, both before and after the cmake installation. For directories where I think this is important, I'll show the outputs before and after the cmake installation.

My question has two parts. I used the following cmake and make commands,

# pwd => $HOME/programs/ffmpeg/ffmpeg_sources/x265/build/linux
PATH="$HOME/programs/ffmpeg/bin:$PATH" \
  cmake -G "Unix Makefiles" \
        -DCMAKE_INSTALL_PREFIX="$HOME/programs/ffmpeg/ffmpeg_build" \
        -DENABLE_SHARED=OFF \
        -DCMAKE_EXE_LINKER_FLAGS="-static" 
            ../../source
PATH="$HOME/programs/ffmpeg/bin:$PATH" make -j $(nproc)
make install

The result is below, with my real vs. expected, and there is a more detailed, more explicit, and hopefully more clear file with the info at pastebin.com/86wHrtxR . Now, for my two-part question:

  1. How can I change my cmake command so that my x265.exe file ends up in $HOME/programs/ffmpeg/bin with the proper linking , rather than $HOME/programs/ffmpeg/ffmpeg_build/bin ?

  2. Would the build/linker/whatever figure things out for the ffmpeg build?

I want to know the answer to question number 1 regardless of the answer to question number 2. I haven't used cmake with the -DVAR=var flags before, and I'd like to take this opportunity to learn.

For the result:

Things surrounded by double curly brackets are {{ expected }} .

Things surrounded by double angle brackets are << real >> , ie they exist after the installation is done.

If real matches expected, and the file/directory is new, I've surrounded it by double parentheses, ie double round brackets. (( match ))

If something is not new (and thus has the same before and after) I haven't marked it.

   me@MACHINE ~/programs/ffmpeg
   $ tree --charset=ascii bin
   bin
   |-- lame.exe
   |-- mp3rtp.exe
   |-- mp3x.exe
   `-- x264.exe
{{ `-- x265.exe                     }} ## Expected, not Exists

   me@MACHINE ~/programs/ffmpeg
   $ tree --charset=ascii \
                   ffmpeg_build
   ffmpeg_build
<< |-- bin                          >> ## Not expected, Exists
<< |   `-- x265.exe                 >> ## Not expected, Exists
   |-- include
   |   |-- fdk-aac
   |   |   |-- aacdecoder_lib.h
   |   |   |-- aacenc_lib.h
   |   |   `-- ... <more .h files>
   |   |-- lame
   |   |   `-- lame.h
   |   |-- x264.h
   |   `-- x264_config.h
(( |   |-- x265.h                   )) ## Expected and Exists
(( |   `-- x265_config.h            )) ## Expected and Exists
   |-- lib
   |   |-- libfdk-aac.a
   |   |-- libfdk-aac.la
   |   |-- libmp3lame.a
   |   |-- libmp3lame.la
(( |   |-- libx265.a                )) ## Expected and Exists
   |   `-- pkgconfig
   |       |-- fdk-aac.pc
   |       `-- x264.pc
(( |       `-- x265.pc              )) ## Expected and Exists
   `-- share
       |-- doc
       |   ... <only lame>
       `-- man
           ... <only lame>

Other, possibly useful information about the build directory structure.

me@MACHINE ~/programs/ffmpeg
$ tree --charset=ascii -L 1 .
.
|-- bin
|-- ffmpeg_build
`-- ffmpeg_sources

3 directories, 0 files

For this next, ffmpeg_sources dir, I'm showing the after (which is both expected and real/exists) surrounded by double parentheses, ie double round brackets, (( <after> )) .

   me@MACHINE ~/programs/ffmpeg
   $ tree --charset=ascii -L 1 ffmpeg_sources
   ffmpeg_sources
   |-- fdk-aac.zip
   |-- lame-svn
   |-- mstorsjo-fdk-aac-e7d8591
   |-- x264-snapshot-20191217-2245
   |-- x264-snapshot-20191217-2245.tar.bz2
   `-- x264-snapshot-20191218-README.txt
(( `-- x265                         ))

   3 directories, 3 files
(( 4 directories, 3 files ))

NOW, FOR SOME MORE DETAIL


What I'm Doing

I am working on a Cygwin build (vs. a Windows/mingw build) of ffmpeg . I am following an older guide by koohiimaster ( archived ). That guide says,

[W]e are not cross-compiling for windows; we are compiling for Cygwin.

This 2014 guide doesn't have all of the codecs I want - I want as complete a build as possible - so I've also been referring to this ffmpeg-for-Ubuntu guide ( archived ), which I hope is kept up-to-date. It's referred to by koohiimaster.

Also, as a way of checking that I'm getting all the codecs I want, I've been looking at this FFmpeg for Windows guide from SuperUser

I'll give the basics of my steps below. More details, as well as all the output is at pastebin.com/suL1nU6Z .

A look at directory structure for the build

me@MACHINE ~/programs/ffmpeg
$ cd $HOME/programs/ffmpeg

me@MACHINE ~/programs/ffmpeg
$ tree --charset=ascii -d -L 1
.
|-- bin
|-- ffmpeg_build
`-- ffmpeg_sources

3 directories

Getting the source. Note that I had to apt-cyg install mercurial , though (with my Cygwin setup GUI/EXE in my Cygwin root directory, ie C:\cygwin64\setup-x86_64.exe ), I could also have done /setup-x86_64.exe install -q -P mercurial .

cd ffmpeg_sources
hg clone https://bitbucket.org/multicoreware/x265

Running the cmake and make commands

cd x265/build/linux
PATH="$HOME/programs/ffmpeg/bin:$PATH" \
  cmake -G "Unix Makefiles" \
        -DCMAKE_INSTALL_PREFIX="$HOME/programs/ffmpeg/ffmpeg_build" \
        -DENABLE_SHARED=OFF \
        -DCMAKE_EXE_LINKER_FLAGS="-static" \
            ../../source
PATH="$HOME/programs/ffmpeg/bin:$PATH" make -j $(nproc)
make install

It was the last part (actually the very last line) of the make install output that worried me. Here is the whole output - it's not very long.

make[1]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
make[2]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
make[2]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
[ 20%] Built target encoder
make[2]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
make[2]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
[ 83%] Built target common
make[2]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
make[2]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
[ 84%] Built target x265-static
make[2]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
make[2]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
[100%] Built target cli
make[1]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
Install the project...
-- Install configuration: "Release"
-- Installing: /home/me/programs/ffmpeg/ffmpeg_build/lib/libx265.a
-- Installing: /home/me/programs/ffmpeg/ffmpeg_build/include/x265.h
-- Installing: /home/me/programs/ffmpeg/ffmpeg_build/include/x265_config.h
-- Installing: /home/me/programs/ffmpeg/ffmpeg_build/lib/pkgconfig/x265.pc
-- Installing: /home/me/programs/ffmpeg/ffmpeg_build/bin/x265.exe

As discussed in the TL;DR section, I expected to see x265.exe at

home/me/programs/ffmpeg/bin/x265.exe

rather than the path given on the last line of output,

/home/me/programs/ffmpeg/ffmpeg_build/bin/x265.exe

This worries me especially because the first part of the ffmpeg install command that my instructions inform me to run is

PATH="$HOME/programs/ffmpeg/bin:$PATH" \
PKG_CONFIG_PATH="$HOME/programs/ffmpeg/ffmpeg_build/lib/pkgconfig" \
  ./configure \
    --prefix="$HOME/programs/ffmpeg/ffmpeg_build" \
    --extra-cflags="-I$HOME/programs/ffmpeg/ffmpeg_build/include" \
    --extra-ldflags="-L$HOME/programs/ffmpeg/ffmpeg_build/lib" \
    --bindir="$HOME/programs/ffmpeg/bin" \

... and on it goes...

It would seem to me that the .configure script for ffmpeg won't find the x265 executable, since it's not in the bindir .

I'll repeat my two-part question from before:

  1. How can I change my cmake command so that my x265.exe file ends up in $HOME/programs/ffmpeg/bin with the proper linking , rather than $HOME/programs/ffmpeg/ffmpeg_build/bin ?

What I'm looking for here is something akin to the --bindir flag from make 's ./confiure .

  1. Would the build/linker/whatever figure things out for the ffmpeg build?

I want to know the answer to question number 1 regardless of the answer to question number 2. I haven't used cmake with the -DVAR=var flags before, and I'd like to take this opportunity to learn.


Where I've Looked & What I've Tried

I first started with the man page and the --help for cmake . That was scary. I was hoping that I'd find something useful around the CMAKE_INSTALL_PREFIX stuff, but I wasn't sure what to make of it.

I tried grep ing through cmake --help-full (with 50 lines before and after whatever I was searching for), but got tripped up by the complexity. I've only used basic cmake stuff, before, and I got more than a little lost.

Even with the --help , I don't know if I need to look at the help-manual , the help-command , the help-module , the help-policy , the help-variable , or something else.

It seemed to me, in reading, that a "binary directory" is the top of the "build", whereas I thought it would be the dir named bin ... I couldn't tell what things were meant to be used by the person creating the package rather than by me, who am trying to make/build the package from the command line.

I looked through what seemed to be a cmake wiki's Useful Variables page ( archived ), as well as at this thread at cmake.org ( archived ), which, along with this SO source and this and this and this and this SO sources, seemed to suggest using the CMAKE_RUNTIME_OUTPUT_DIRECTORY variable (since the EXECUTABLE_OUTPUT-DIRECTORY variable has been superseded by it). By the way, I couldn't tell which things should be used by the creator of the package vs. the consumer of the package - the consumer being me. I tried with

PATH="$HOME/programs/ffmpeg/bin:$PATH" \
  cmake -G "Unix Makefiles" \
        -DCMAKE_INSTALL_PREFIX="$HOME/programs/ffmpeg/ffmpeg_build" \
        -DCMAKE_RUNTIME_OUTPUT_DIRECTORY="$HOME/programs/ffmpeg/bin" \
        -DENABLE_SHARED=OFF \
        -DCMAKE_EXE_LINKER_FLAGS="-static" 
            ../../source
PATH="$HOME/

and have thought about fifty-or-so other -DVAR variables, but with any I have tried, I still get the same result. I still get the executable in what seems to be the wrong place.


System Details

$ date && date +'%s'
Tue, May  5, 2020 11:14:40 AM
1588698880
$ uname -a
CYGWIN_NT-10.0 MACHINE 3.1.4(0.340/5/3) 2020-02-19 08:49 x86_64 Cygwin
$ cmake --version
cmake version 3.14.5

CMake suite maintained and supported by Kitware (kitware.com/cmake).
$ bash --version | head -n 1
GNU bash, version 4.4.12(3)-release (x86_64-unknown-cygwin)
$ gcc --version | head -n 1
gcc (GCC) 9.3.0
$ g++ --version | head -n 1
g++ (GCC) 9.3.0
$ make --version | head -n 2
GNU Make 4.3
Built for x86_64-pc-cygwin

To have x286.exe file in $HOME/programs/ffmpeg/bin

    --prefix="$HOME/programs/ffmpeg" \
    --extra-cflags="-I$HOME/programs/ffmpeg/include" \
    --extra-ldflags="-L$HOME/programs/ffmpeg/lib" \

For cmake:

-DCMAKE_INSTALL_PREFIX="$HOME/programs/ffmpeg"

VERY close with @Philippe

The answer by @Philippe got me pointed in the right direction. My comment on that answer, with some changes shows how close it got me.

That's helpful - with

-DCMAKE_INSTALL_PREFIX="$HOME/programs/ffmpeg"

I went all the way through the make install . Doing so, I ended up quite close. The last part of the make install output was

-- Installing: /home/me/programs/ffmpeg/lib/libx265.a
-- Installing: /home/me/programs/ffmpeg/include/x265.h
-- Installing: /home/me/programs/ffmpeg/include/x265_config.h
-- Installing: /home/me/programs/ffmpeg/lib/pkgconfig/x265.pc
-- Installing: /home/me/programs/ffmpeg/bin/x265.exe

The x265.exe is where I want it, but now the other five files ( libx265.a , x265.h , x265_config.h , and x265.pc ) are not where it seems that the pattern of other installs would like them, eg, I would like /home/me/programs/ffmpeg/ffmpeg_build/lib/libx265.a - it seems the eventual ffmpeg build wants them there.

The last paragraph describes the desired output from the original question. To put it another way, just for clarity's sake, I want those last lines of output to be

-- Installing: /home/me/programs/ffmpeg/ffmpeg_build/lib/libx265.a
-- Installing: /home/me/programs/ffmpeg/ffmpeg_build/include/x265.h
-- Installing: /home/me/programs/ffmpeg/ffmpeg_build/include/x265_config.h
-- Installing: /home/me/programs/ffmpeg/ffmpeg_build/lib/pkgconfig/x265.pc
-- Installing: /home/me/programs/ffmpeg/bin/x265.exe

Answer to Match the 'Desired Output'

The combination of ideas in the answer from @Philippe got me to where I needed to be. First, a few little changes needed to be made to CMakeLists.txt . The file as cloned is already set up to allow the location of the "*.exe" files (inside whichever bin directory be desired) to be changed from the command-line. The same is true for the library ( lib ) files. Rather than hard-code the location for the header ( include ) files, I make this change.

me@MACHINE ~/programs/ffmpeg/ffmpeg_sources/x265/source
$ cp CMakeLists.txt CMakeLists.txt.$(date +'%s').bak

me@MACHINE ~/programs/ffmpeg/ffmpeg_sources/x265/source
$ cat -n CMakeLists.txt.1588732600.bak | head -n 386 | tail -16   ### BEFORE
   371
   372  # Build options
   373  set(LIB_INSTALL_DIR lib CACHE STRING "Install location of libraries")
   374  set(BIN_INSTALL_DIR bin CACHE STRING "Install location of executables")
   375  set(EXTRA_LIB "" CACHE STRING "Extra libraries to link against")
   376  set(EXTRA_LINK_FLAGS "" CACHE STRING "Extra link flags")
   377  if(EXTRA_LINK_FLAGS)
   378      list(APPEND LINKER_OPTIONS ${EXTRA_LINK_FLAGS})
   379  endif()
   380  if(EXTRA_LIB)
   381      option(LINKED_8BIT  "8bit libx265 is being linked with this library" OFF)
   382      option(LINKED_10BIT "10bit libx265 is being linked with this library" OFF)
   383      option(LINKED_12BIT "12bit libx265 is being linked with this library" OFF)
   384  endif(EXTRA_LIB)
   385  mark_as_advanced(EXTRA_LIB EXTRA_LINK_FLAGS)
   386

me@MACHINE ~/programs/ffmpeg/ffmpeg_sources/x265/source
$ vim CMakeLists.txt   ### Making the change

me@MACHINE ~/programs/ffmpeg/ffmpeg_sources/x265/source
$ cat -n CMakeLists.txt | head -n 389 | tail -19   ### AFTER
   371
   372  # Build options
   373  set(LIB_INSTALL_DIR lib CACHE STRING "Install location of libraries")
   374  set(BIN_INSTALL_DIR bin CACHE STRING "Install location of executables")
   375  # Start DWB insert 2020-05-05
   376  set(INCLUDE_INSTALL_DIR include CACHE STRING "Install location of headers")
   377  #   End DWB insert 2020-05-05
   378  set(EXTRA_LIB "" CACHE STRING "Extra libraries to link against")
   379  set(EXTRA_LINK_FLAGS "" CACHE STRING "Extra link flags")
   380  if(EXTRA_LINK_FLAGS)
   381      list(APPEND LINKER_OPTIONS ${EXTRA_LINK_FLAGS})
   382  endif()
   383  if(EXTRA_LIB)
   384      option(LINKED_8BIT  "8bit libx265 is being linked with this library" OFF)
   385      option(LINKED_10BIT "10bit libx265 is being linked with this library" OFF)
   386      option(LINKED_12BIT "12bit libx265 is being linked with this library" OFF)
   387  endif(EXTRA_LIB)
   388  mark_as_advanced(EXTRA_LIB EXTRA_LINK_FLAGS)
   389

Seen via diff

me@MACHINE ~/programs/ffmpeg/ffmpeg_sources/x265/source
$ diff CMakeLists.txt CMakeLists.txt.1588732600.bak
375,377d374
< # Start DWB insert 2020-05-05
< set(INCLUDE_INSTALL_DIR include CACHE STRING "Install location of headers")
< #   End DWB insert 2020-05-05
599,604c596,597

Next change:

me@MACHINE ~/programs/ffmpeg/ffmpeg_sources/x265/source
$ cat -n CMakeLists.txt.1588732600.bak | head -n 602 | tail -9   ### BEFORE
   594
   595  if(SVTHEVC_FOUND)
   596      install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbApi.h" DESTINATION include)
   597      install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbErrorCodes.h" DESTINATION include)
   598      install(FILES "${SVT_HEVC_LIBRARY}" DESTINATION ${LIB_INSTALL_DIR})
   599  endif()
   600
   601  install(FILES x265.h "${PROJECT_BINARY_DIR}/x265_config.h" DESTINATION include)
   602  if((WIN32 AND ENABLE_CLI) OR (WIN32 AND ENABLE_SHARED))

me@MACHINE ~/programs/ffmpeg/ffmpeg_sources/x265/source
$ vim CMakeLists.txt   ### Making the change

me@MACHINE ~/programs/ffmpeg/ffmpeg_sources/x265/source
$ cat -n CMakeLists.txt | head -n 611 | tail -15   ### AFTER
   597
   598  if(SVTHEVC_FOUND)
   599      # DWB change 2020-05-05, original is next (cmt) line, new is the line after
   600      #install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbApi.h" DESTINATION include)
   601      install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbApi.h" DESTINATION ${INCLUDE_INSTALL_DIR})
   602      # DWB change 2020-05-05, original is next (cmt) line, new is the line after
   603      #install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbErrorCodes.h" DESTINATION include)
   604      install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbErrorCodes.h" DESTINATION ${INCLUDE_INSTALL_DIR})
   605      install(FILES "${SVT_HEVC_LIBRARY}" DESTINATION ${LIB_INSTALL_DIR})
   606  endif()
   607
   608  # DWB change 2020-05-05, original is next (comment) line, new is the line after
   609  #install(FILES x265.h "${PROJECT_BINARY_DIR}/x265_config.h" DESTINATION include)
   610  install(FILES x265.h "${PROJECT_BINARY_DIR}/x265_config.h" DESTINATION ${INCLUDE_INSTALL_DIR})
   611  if((WIN32 AND ENABLE_CLI) OR (WIN32 AND ENABLE_SHARED))

Or, again as seen via diff (with both changes having been made),

me@MACHINE ~/programs/ffmpeg/ffmpeg_sources/x265/source
$ diff CMakeLists.txt CMakeLists.txt.1588732600.bak
375,377d374
< # Start DWB insert 2020-05-05
< set(INCLUDE_INSTALL_DIR include CACHE STRING "Install location of headers")
< #   End DWB insert 2020-05-05
599,604c596,597
<     # DWB change 2020-05-05, original is next (cmt) line, new is the line after
<     #install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbApi.h" DESTINATION include)
<     install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbApi.h" DESTINATION ${INCLUDE_INSTALL_DIR})
<     # DWB change 2020-05-05, original is next (cmt) line, new is the line after
<     #install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbErrorCodes.h" DESTINATION include)
<     install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbErrorCodes.h" DESTINATION ${INCLUDE_INSTALL_DIR})
---
>     install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbApi.h" DESTINATION include)
>     install(FILES "${SVT_HEVC_INCLUDE_DIR}/EbErrorCodes.h" DESTINATION include)
608,610c601
< # DWB change 2020-05-05, original is next (comment) line, new is the line after
< #install(FILES x265.h "${PROJECT_BINARY_DIR}/x265_config.h" DESTINATION include)
< install(FILES x265.h "${PROJECT_BINARY_DIR}/x265_config.h" DESTINATION ${INCLUDE_INSTALL_DIR})
---
> install(FILES x265.h "${PROJECT_BINARY_DIR}/x265_config.h" DESTINATION include)

The `cmake` Command and the `make` Commands

Let's get into the correct build directory and run cmake

cd $HOME/programs/ffmpeg/ffmpeg_sources/x265/build/linux

PATH="$HOME/programs/ffmpeg/bin:$PATH" \
  cmake -G "Unix Makefiles" \
        -DCMAKE_INSTALL_PREFIX="$HOME/programs/ffmpeg" \
        -DBIN_INSTALL_DIR="bin" \
        -DLIB_INSTALL_DIR="ffmpeg_build/lib" \
        -DINCLUDE_INSTALL_DIR="ffmpeg_build/include" \
        -DENABLE_SHARED=OFF \
        -DCMAKE_EXE_LINKER_FLAGS="-static" \
            ../../source

This gives some deprecation warnings that we don't need to worry about. Now, for the make parts.

PATH="$HOME/programs/ffmpeg/bin:$PATH" make -j $(nproc)

make install

which led to the desired result. The last few lines of the make install output were

-- Installing: /home/13852/programs/ffmpeg/ffmpeg_build/lib/libx265.a
-- Installing: /home/13852/programs/ffmpeg/ffmpeg_build/include/x265.h
-- Installing: /home/13852/programs/ffmpeg/ffmpeg_build/include/x265_config.h
-- Installing: /home/13852/programs/ffmpeg/ffmpeg_build/lib/pkgconfig/x265.pc
-- Installing: /home/13852/programs/ffmpeg/bin/x265.exe

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM