macOS 编译
在 macOS M2 上编译使用 FFmpeg 与 JNI 的项目,您可以按照以下步骤进行配置和构建:
1. 准备工作
1. 是否需要使用 vcpkg?
不一定
在 macOS 上,推荐使用 Homebrew 来安装 FFmpeg、lame 等依赖,因为 Homebrew 在 macOS 平台具有更高的普及率和维护性。可选方案
如果您希望在跨平台开发中保持一致的依赖管理工具,或习惯使用 vcpkg,也可以选择使用 vcpkg。不过对于 macOS 平台来说,vcpkg 的使用并非必须。
2. macOS vcpkg 安装的 FFmpeg 是动态库吗?
是的
在 macOS 上,通过 vcpkg 安装的 FFmpeg 默认生成的是动态库(文件扩展名为.dylib
)。这与 Homebrew 安装的方式类似,都提供动态链接的 FFmpeg 库。注意事项
- 如果使用 vcpkg,请确保在 CMakeLists.txt 中正确指定 vcpkg 工具链文件(例如通过
-DCMAKE_TOOLCHAIN_FILE=path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
)。 - 同时也可查看 vcpkg 的配置选项,确认生成的是动态库(默认配置下 macOS 一般为动态库)。
- 如果使用 vcpkg,请确保在 CMakeLists.txt 中正确指定 vcpkg 工具链文件(例如通过
3.环境准备
安装 Xcode 与命令行工具
确保已经安装 Xcode 以及其命令行工具(Command Line Tools),这为编译 C/C++ 代码提供必备环境。安装 Homebrew(可选)
Homebrew 是 macOS 上非常流行的包管理器,可以方便地安装各类依赖:/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
安装 Java 开发环境
下载并安装 JDK(例如 AdoptOpenJDK 或 Oracle JDK),并确保配置好JAVA_HOME
环境变量:export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home
1.2 安装 FFmpeg 与其他依赖
macOS 上可以通过两种方式安装依赖库:
方式 A:使用 Homebrew(推荐)
安装 FFmpeg 以及开发包:
brew install ffmpeg
Homebrew 安装的 FFmpeg 默认会提供动态库(.dylib)。
如果项目需要 libmp3lame 等组件,也可以一起安装:
brew install lame
方式 B:使用 vcpkg(可选)
- vcpkg 也支持 macOS,但在 macOS 上并不是必须的,因为 Homebrew 更加主流且方便。
- 如果您选择使用 vcpkg,请先按照 vcpkg 官方文档 安装和配置 vcpkg。
1.3 配置 CMake 构建脚本
在 CMakeLists.txt 中配置项目时,需要查找 JNI、FFmpeg 等依赖。例如:
在 macOS 平台上,如果使用 Homebrew 安装 FFmpeg,那么一般不需要单独 target_link mp3lame,因为:
- 集成情况:Homebrew 安装的 FFmpeg 通常已经编译时内置或动态链接了 mp3lame 支持,所以不需要额外链接 mp3lame 库。
- 动态链接:FFmpeg 动态库中已经包含了对 MP3 编码器的支持(例如 libmp3lame),调用时系统会自动解析这些依赖。
因此,在 macOS 下只需正确查找并链接 FFmpeg 的相关动态库(如 avcodec、avformat、swresample、avutil)即可,无需额外 target_link mp3lame。
cmake_minimum_required(VERSION 3.15)
project(native_media)
set(CMAKE_CXX_STANDARD 17)
# Find JNI
find_package(JNI REQUIRED)
include_directories(${JNI_INCLUDE_DIRS})
# Find FFmpeg components explicitly
find_path(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h)
find_path(AVFORMAT_INCLUDE_DIR libavformat/avformat.h)
find_path(SWRESAMPLE_INCLUDE_DIR libswresample/swresample.h)
find_path(AVUTIL_INCLUDE_DIR libavutil/avutil.h)
find_library(AVCODEC_LIBRARY avcodec)
find_library(AVFORMAT_LIBRARY avformat)
find_library(SWRESAMPLE_LIBRARY swresample)
find_library(AVUTIL_LIBRARY avutil)
# Print paths for debugging
message(STATUS "AVCODEC_INCLUDE_DIR: ${AVCODEC_INCLUDE_DIR}")
message(STATUS "AVCODEC_LIBRARY: ${AVCODEC_LIBRARY}")
message(STATUS "AVFORMAT_INCLUDE_DIR: ${AVFORMAT_INCLUDE_DIR}")
message(STATUS "AVFORMAT_LIBRARY: ${AVFORMAT_LIBRARY}")
message(STATUS "SWRESAMPLE_INCLUDE_DIR: ${SWRESAMPLE_INCLUDE_DIR}")
message(STATUS "SWRESAMPLE_LIBRARY: ${SWRESAMPLE_LIBRARY}")
message(STATUS "AVUTIL_INCLUDE_DIR: ${AVUTIL_INCLUDE_DIR}")
message(STATUS "AVUTIL_LIBRARY: ${AVUTIL_LIBRARY}")
# 检测操作系统类型
if(WIN32)
message(STATUS "Configuring for Windows")
find_package(mp3lame CONFIG REQUIRED)
elseif(APPLE)
message(STATUS "Configuring for macOS")
elseif(UNIX)
message(STATUS "Configuring for Linux/UNIX")
endif()
# Include directories
include_directories(
${AVCODEC_INCLUDE_DIR}
${AVFORMAT_INCLUDE_DIR}
${SWRESAMPLE_INCLUDE_DIR}
${AVUTIL_INCLUDE_DIR}
jni
)
# Add sources
add_library(native_media SHARED src/native_mp3.c src/native_mp4.c)
# Link libraries
target_link_libraries(native_media
${JNI_LIBRARIES}
${AVCODEC_LIBRARY}
${AVFORMAT_LIBRARY}
${SWRESAMPLE_LIBRARY}
${AVUTIL_LIBRARY})
if(WIN32)
target_link_libraries(native_media mp3lame::mp3lame)
elseif(APPLE)
elseif(UNIX)
target_link_libraries(native_media mp3lame)
endif()
# Add test executable
add_executable(mp4_test src/mp4_test.c src/native_mp4.c)
target_link_libraries(mp4_test
${AVCODEC_LIBRARY}
${AVFORMAT_LIBRARY}
${SWRESAMPLE_LIBRARY}
${AVUTIL_LIBRARY}
)
1.4 编译项目
进入项目根目录后,按照以下步骤进行编译:
生成构建文件
建议使用 Release 模式:cmake -S . -B cmake-build-release -DCMAKE_BUILD_TYPE=Release
-- The C compiler identification is AppleClang 15.0.0.15000309
-- The CXX compiler identification is AppleClang 15.0.0.15000309
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found JNI: /Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/include found components: AWT JVM
-- AVCODEC_INCLUDE_DIR: /opt/homebrew/include
-- AVCODEC_LIBRARY: /opt/homebrew/lib/libavcodec.dylib
-- AVFORMAT_INCLUDE_DIR: /opt/homebrew/include
-- AVFORMAT_LIBRARY: /opt/homebrew/lib/libavformat.dylib
-- SWRESAMPLE_INCLUDE_DIR: /opt/homebrew/include
-- SWRESAMPLE_LIBRARY: /opt/homebrew/lib/libswresample.dylib
-- AVUTIL_INCLUDE_DIR: /opt/homebrew/include
-- AVUTIL_LIBRARY: /opt/homebrew/lib/libavutil.dylib
-- Configuring for Linux/UNIX
-- Configuring done (1.8s)
-- Generating done (0.0s)
-- Build files have been written to: /Users/ping/code/cpp/native-media/cmake-build-release
编译项目
在构建目录下运行:cmake --build cmake-build-release --target all
生成的共享库
编译完成后,将生成类似libnative_media.dylib
的共享库,可在 Java 中通过System.loadLibrary("native_media")
加载。
总结
- 编译步骤:在 macOS M2 上,您可以使用 Xcode/命令行工具和 CMake 构建项目;依赖安装方面,推荐使用 Homebrew,但 vcpkg 也是可选方案。
- 是否使用 vcpkg:在 macOS 上不强制要求使用 vcpkg,因为 Homebrew 提供了更友好的安装体验。
- FFmpeg 库类型:无论是通过 Homebrew 还是 vcpkg 安装,默认情况下 FFmpeg 提供的是动态库(.dylib)。
通过以上步骤,您可以在 macOS M2 上顺利编译和运行基于 JNI 调用 FFmpeg 的项目。如果有其他问题或需要更详细的配置说明,请继续讨论。