selsta / hlsdl

C program to download VoD HLS (.m3u8) files
MIT License
636 stars 158 forks source link

cmake: add basic support #79

Open selsta opened 4 years ago

selsta commented 4 years ago

@Reino17 @mengmo Opinion on this? Both of you have compiled hlsdl on Windows before so you might be interested.

This seems cleaner than the current build script but can you still build static binaries using this?

mengmo commented 4 years ago
$ cmake ./
-- Building for: NMake Makefiles
-- The C compiler identification is unknown
CMake Error at CMakeLists.txt:3 (project):
  The CMAKE_C_COMPILER:

    cl

  is not a full path and was not found in the PATH.
$ cmake -G "MinGW Makefiles" ./
-- The C compiler identification is GNU 10.1.0
-- Check for working C compiler: D:/msys64/mingw64/bin/gcc.exe
-- Check for working C compiler: D:/msys64/mingw64/bin/gcc.exe - works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Found OpenSSL: D:/msys64/mingw64/lib/libcrypto.dll.a (found version "1.1.1g")
-- Found CURL: D:/msys64/mingw64/lib/libcurl.dll.a (found version "7.71.0")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: D:/devel/hlsdl-cmake/src
$ mingw32-make
Scanning dependencies of target hlsdl
[ 11%] Building C object CMakeFiles/hlsdl.dir/main.c.obj
[ 22%] Building C object CMakeFiles/hlsdl.dir/aes_openssl.c.obj
[ 33%] Building C object CMakeFiles/hlsdl.dir/curl.c.obj
[ 44%] Building C object CMakeFiles/hlsdl.dir/hls.c.obj
D:\devel\hlsdl-cmake\src\hls.c: In function 'is_playlist_FPS':
D:\devel\hlsdl-cmake\src\hls.c:108:12: warning: returning 'char *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion]
  108 |     return strstr(source, "KEYFORMAT=\"com.apple.streamingkeydelivery\"");
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[ 55%] Building C object CMakeFiles/hlsdl.dir/misc.c.obj
[ 66%] Building C object CMakeFiles/hlsdl.dir/msg.c.obj
[ 77%] Building C object CMakeFiles/hlsdl.dir/mpegts.c.obj
D:\devel\hlsdl-cmake\src\mpegts.c: In function 'get_dts_from_id3':
D:\devel\hlsdl-cmake\src\mpegts.c:563:39: warning: implicit declaration of function 'memmem'; did you mean 'memset'? [-Wimplicit-function-declaration]
  563 |             uint8_t *ptr = (uint8_t *)memmem(buf, size, "com.apple.streaming.transportStreamTimestamp", 44);
      |                                       ^~~~~~
      |                                       memset
D:\devel\hlsdl-cmake\src\mpegts.c:563:28: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
  563 |             uint8_t *ptr = (uint8_t *)memmem(buf, size, "com.apple.streaming.transportStreamTimestamp", 44);
      |                            ^
[ 88%] Building C object CMakeFiles/hlsdl.dir/D_/devel/hlsdl-cmake/msvc/win/memmem.c.obj
[100%] Linking C executable hlsdl.exe
[100%] Built target hlsdl

A dynamic linked hlsdl has been built, these DLLs required if running outside MINGW64:

libbrotlicommon.dll libbrotlidec.dll libcrypto-1_1-x64.dll libcurl-4.dll libiconv-2.dll libidn2-0.dll libintl-8.dll libnghttp2-14.dll libpsl-5.dll libssh2-1.dll libssl-1_1-x64.dll libunistring-2.dll libwinpthread-1.dll zlib1.dll

Actually dynamic linked hlsdl build always works on MINGW32/MINGW64 But for distributing, I think a static linked hlsdl is better at least for Windows users.

mengmo commented 4 years ago

Sorry! my carelessness Finally I successfully build static hlsdl with CMake

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)

project(hlsdl VERSION 0.27 LANGUAGES C)

if (APPLE AND NOT IOS)
  if (NOT OPENSSL_ROOT_DIR)
    EXECUTE_PROCESS(COMMAND brew --prefix openssl
      OUTPUT_VARIABLE OPENSSL_ROOT_DIR
      OUTPUT_STRIP_TRAILING_WHITESPACE)
  endif()
endif()

if (WIN32)
    add_definitions(-DCURL_STATICLIB)
    set(CURL_LIBRARY ${CMAKE_SOURCE_DIR}/../lib/libcurl.a)
    set(OPENSSL_USE_STATIC_LIBS TRUE)
endif()

find_package(OpenSSL REQUIRED)
find_package(CURL REQUIRED)
find_package(Threads REQUIRED)

add_executable(hlsdl main.c aes_openssl.c curl.c hls.c misc.c msg.c mpegts.c)

target_include_directories(hlsdl PRIVATE ${OPENSSL_INCLUDE_DIR} ${CURL_INCLUDE_DIRS})

if (WIN32)
    target_sources(hlsdl PRIVATE "../msvc/win/memmem.c")
endif()

target_link_libraries(hlsdl PRIVATE CURL::libcurl -lnghttp2 -lssh2 -lbrotlidec-static -lbrotlicommon-static -lssl OpenSSL::Crypto -lcrypt32 -lwsock32 -lws2_32 -lwldap32 -lz Threads::Threads)

build

cmake -G "MinGW Makefiles" -DCMAKE_EXE_LINKER_FLAGS="-static -s" src -B build
cd build && mingw32-make
selsta commented 4 years ago

@mengmo Awesome, thank you.

Reino17 commented 4 years ago

I'm not a cmake expert, but all the libraries I've compiled so far that use cmake have 'CMakeLists.txt' in the root-dir.
I've checked out the "cmake"-branch, removed 'makefile' (because as far as I know cmake is now supposed to create that file), made the following changes to 'src/CMakeLists.txt'...

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d070f48..6e6de86 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -14,12 +14,12 @@ find_package(OpenSSL REQUIRED)
 find_package(CURL REQUIRED)
 find_package(Threads REQUIRED)

-add_executable(hlsdl main.c aes_openssl.c curl.c hls.c misc.c msg.c mpegts.c)
+add_executable(hlsdl src/main.c src/aes_openssl.c src/curl.c src/hls.c src/misc.c src/msg.c src/mpegts.c)

 target_include_directories(hlsdl PRIVATE ${OPENSSL_INCLUDE_DIR} ${CURL_INCLUDE_DIRS})

 if (WIN32)
-    target_sources(hlsdl PRIVATE "../msvc/win/memmem.c")
+    target_sources(hlsdl PRIVATE "msvc/win/memmem.c")
 endif()

 target_link_libraries(hlsdl PRIVATE OpenSSL::Crypto CURL::libcurl Threads::Threads)

...and moved it to the root-dir (where it belongs in my opinion).

This is the (shortened) log of running cmake and make with my script:

Configuring hlsdl_git as "cmake -G "Unix Makefiles" /cygdrive/m/[...]/win32/hlsdl_git -DENABLE_STATIC_RUNTIME=1 -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_FIND_ROOT_PATH=/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32 -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY -DCMAKE_RANLIB=/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/bin/i686-w64-mingw32-ranlib.exe -DCMAKE_C_COMPILER=/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/bin/i686-w64-mingw32-gcc.exe -DCMAKE_CXX_COMPILER=/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/bin/i686-w64-mingw32-g++.exe -DCMAKE_RC_COMPILER=/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/bin/i686-w64-mingw32-windres.exe -DCMAKE_INSTALL_PREFIX=/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32".
-- The C compiler identification is GNU 9.3.0
-- Check for working C compiler: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/bin/i686-w64-mingw32-gcc.exe
-- Check for working C compiler: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/bin/i686-w64-mingw32-gcc.exe - works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Found OpenSSL: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a (found version "1.1.1g")
-- Found CURL: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcurl.a (found version "7.69.1")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
CMake Warning:
  Manually-specified variables were not used by the project:

    CMAKE_CXX_COMPILER
    ENABLE_STATIC_RUNTIME

-- Build files have been written to: /cygdrive/m/[...]/win32/hlsdl_git
Compiling hlsdl_git as "make -j 1".
Scanning dependencies of target hlsdl
[ 11%] Building C object CMakeFiles/hlsdl.dir/src/main.c.obj
[ 22%] Building C object CMakeFiles/hlsdl.dir/src/aes_openssl.c.obj
[ 33%] Building C object CMakeFiles/hlsdl.dir/src/curl.c.obj
[ 44%] Building C object CMakeFiles/hlsdl.dir/src/hls.c.obj
/cygdrive/m/[...]/win32/hlsdl_git/src/hls.c: In function 'is_playlist_FPS':
/cygdrive/m/[...]/win32/hlsdl_git/src/hls.c:108:12: warning: returning 'char *' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion]
  108 |     return strstr(source, "KEYFORMAT=\"com.apple.streamingkeydelivery\"");
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[ 55%] Building C object CMakeFiles/hlsdl.dir/src/misc.c.obj
[ 66%] Building C object CMakeFiles/hlsdl.dir/src/msg.c.obj
[ 77%] Building C object CMakeFiles/hlsdl.dir/src/mpegts.c.obj
/cygdrive/m/[...]/win32/hlsdl_git/src/mpegts.c: In function 'get_dts_from_id3':
/cygdrive/m/[...]/win32/hlsdl_git/src/mpegts.c:563:39: warning: implicit declaration of function 'memmem'; did you mean 'memset'? [-Wimplicit-function-declaration]
  563 |             uint8_t *ptr = (uint8_t *)memmem(buf, size, "com.apple.streaming.transportStreamTimestamp", 44);
      |                                       ^~~~~~
      |                                       memset
[ 88%] Building C object CMakeFiles/hlsdl.dir/msvc/win/memmem.c.obj
[100%] Linking C executable hlsdl.exe
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: CMakeFiles/hlsdl.dir/objects.a(main.c.obj):main.c:(.text.startup+0xa6): undefined reference to `_imp__curl_global_init'
[...]
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: CMakeFiles/hlsdl.dir/objects.a(curl.c.obj):curl.c:(.text+0xb7c): undefined reference to `_imp__curl_slist_free_all'
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a(e_capi.o):e_capi.c:(.text+0x187): undefined reference to `_imp__CertFreeCertificateContext@4'
[...]
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a(e_capi.o):e_capi.c:(.text+0x3107): undefined reference to `_imp__CertCloseStore@8'
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a(b_addr.o):b_addr.c:(.text+0xbe): undefined reference to `_imp__getnameinfo@28'
[...]
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a(b_addr.o):b_addr.c:(.text+0xb3a): undefined reference to `gai_strerrorW'
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a(b_sock.o):b_sock.c:(.text+0x5): undefined reference to `_imp__WSAGetLastError@0'
[...]
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a(b_sock.o):b_sock.c:(.text+0x972): undefined reference to `_imp__WSAGetLastError@0'
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a(b_sock2.o):b_sock2.c:(.text+0x25): undefined reference to `_imp__socket@12'
[...]
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a(b_sock2.o):b_sock2.c:(.text+0x8dc): undefined reference to `_imp__closesocket@4'
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a(bss_sock.o):bss_sock.c:(.text+0x215): undefined reference to `_imp__WSAGetLastError@0'
[...]
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a(bss_sock.o):bss_sock.c:(.text+0x339): undefined reference to `_imp__send@16'
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a(c_zlib.o):c_zlib.c:(.text+0x54): undefined reference to `inflate'
[...]
/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld: /cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib/libcrypto.a(c_zlib.o):c_zlib.c:(.text+0xb16): undefined reference to `deflateEnd'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/hlsdl.dir/build.make:213: hlsdl.exe] Error 1
make[1]: *** [CMakeFiles/Makefile2:96: CMakeFiles/hlsdl.dir/all] Error 2
make: *** [Makefile:104: all] Error 2

Lots of "undefined reference"-errors!
Only with these additional changes...

diff --git a/src/CMakeLists.txt b/CMakeLists.txt
index d070f48..12fdd49
--- a/src/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,16 +10,20 @@ if (APPLE AND NOT IOS)
   endif()
 endif()

+if (WIN32)
+    add_definitions(-DCURL_STATICLIB)
+endif()
+
 find_package(OpenSSL REQUIRED)
 find_package(CURL REQUIRED)
 find_package(Threads REQUIRED)

-add_executable(hlsdl main.c aes_openssl.c curl.c hls.c misc.c msg.c mpegts.c)
+add_executable(hlsdl src/main.c src/aes_openssl.c src/curl.c src/hls.c src/misc.c src/msg.c src/mpegts.c)

 target_include_directories(hlsdl PRIVATE ${OPENSSL_INCLUDE_DIR} ${CURL_INCLUDE_DIRS})

 if (WIN32)
-    target_sources(hlsdl PRIVATE "../msvc/win/memmem.c")
+    target_sources(hlsdl PRIVATE "msvc/win/memmem.c")
 endif()

-target_link_libraries(hlsdl PRIVATE OpenSSL::Crypto CURL::libcurl Threads::Threads)
+target_link_libraries(hlsdl PRIVATE CURL::libcurl -lssl OpenSSL::Crypto -lz -lws2_32 -lgdi32 -lcrypt32 -lwldap32 Threads::Threads)

...do I get a working 'hlsdl.exe'.

I don't understand the need for either of these changes. After cmake 'CMakeCache.txt' shows me:

[...]
########################
# INTERNAL cache entries
########################
[...]
PC_CURL_CFLAGS:INTERNAL=-DCURL_STATICLIB;-I/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/include
PC_CURL_CFLAGS_OTHER:INTERNAL=-DCURL_STATICLIB
[...]
PC_CURL_STATIC_CFLAGS:INTERNAL=-DCURL_STATICLIB;-I/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/include
PC_CURL_STATIC_CFLAGS_OTHER:INTERNAL=-DCURL_STATICLIB
[...]
PC_CURL_STATIC_LDFLAGS:INTERNAL=-L/cygdrive/m/[...]/cross_compilers/mingw-w64-i686/i686-w64-mingw32/lib;-lcurl;-lssl;-lcrypto;-lssl;-lcrypto;-lz;-lws2_32;-lgdi32;-lcrypt32;-lgdi32;-lwldap32;-lz;-lws2_32
PC_CURL_STATIC_LIBRARIES:INTERNAL=curl;ssl;crypto;ssl;crypto;z;ws2_32;gdi32;crypt32;gdi32;wldap32;z;ws2_32
[...]

So it looks like cmake correctly detects...

Libs.private: -lssl -lcrypto -lssl -lcrypto -lz -lws2_32 -lgdi32 -lcrypt32 -lgdi32 -lwldap32 -lz -lws2_32
Cflags: -I${includedir} -DCURL_STATICLIB

...from 'libcurl.pc', but somehow the additional changes to 'CMakeLists.txt' are still needed nonetheless.

Again, I'm no expert, but I'd say these additional changes shouldn't be needed. The detection of curl (and all its dependencies) should be fully automatic.