[技术探索者手记] C++自学之路 × linux下搭建属于自己风格的FFmpeg开发项目框架

我是一名.NET开发者,最近开始学习C++。目前,我已经掌握了C++的基础语法和入门知识,并对FFmpeg产生了浓厚的兴趣。接下来,我计划自学与FFmpeg相关的技术内容,并记录自己的学习过程。欢迎大家提出宝贵意见,我会虚心接受并采纳大家的建议。谢谢!我是一名.NET开发者,最近开始学习C++。目前,我已经掌握了C++的基础语法和入门知识,并对FFmpeg产生了浓厚的兴趣。接下来,我计划自学与FFmpeg相关的技术内容,并记录自己的学习过程。欢迎大家提出宝贵意见,我会虚心接受并采纳大家的建议。谢谢!

  • linux下构建自己的个性化的FFmpeg库
  • linux下搭建属于自己风格的FFmpeg开发项目框架

目录结构设计

project_name/
    ├── .vscode
    │   └── settings.json
    │   └── tasks.json
    ├── bin/        # 可执行文件
    ├── build/      # 编译中间文件(*.o, *.d)
    ├── lib/        # 库文件
    ├── include/    # 公共头文件(按模块/项目名组织)
    │   └── project_name/
    ├── src/        # 源文件(按模块组织)
    │   └── app/
    │       └── main.cpp
    │   └── project_name/
    │         └── xxx.cpp
    ├── test/       # 单元测试代码
    ├── thirdparty/ # 第三方库(或external/3rdparty)
    │   └── thirdpartylibname(例如:ffmpeg)
    │          └── include
    │          └── lib
    ├── CMakeLists.txt # 构建配置
    ├── build.sh #cmake 构建执行脚本
    └── README.md   # 项目说明

学习了2中构建方式:
– Make构建
– task.json构建

CMake构建记录

# 设置 CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)

# 设置项目名称
project(cpp-journey                   # 项目名称
  VERSION 1.0                         # 项目版本(可选)
  LANGUAGES CXX                       # 指定语言(CXX为C++)
)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)           # 设置 C++ 标准为 C++17
set(CMAKE_CXX_STANDARD_REQUIRED ON)  # 要求使用 C++17 标准
set(CMAKE_BUILD_TYPE Release)        # 默认构建类型(Debug/Release)

# 设置可执行文件输出目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# 设置库文件输出目录
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

# 添加头文件搜索路径
include_directories(${PROJECT_SOURCE_DIR}/include)

# 自动查找 src 目录下的所有源文件
file(GLOB_RECURSE SOURCES "${PROJECT_SOURCE_DIR}/src/*.cpp")

# 生成静态库
add_library(${PROJECT_NAME}_static STATIC ${SOURCES})
set_target_properties(${PROJECT_NAME}_static PROPERTIES OUTPUT_NAME ${PROJECT_NAME})

# 生成动态库
add_library(${PROJECT_NAME}_shared SHARED ${SOURCES})
set_target_properties(${PROJECT_NAME}_shared PROPERTIES OUTPUT_NAME ${PROJECT_NAME})

# 添加可执行文件
add_executable(${PROJECT_NAME}_${PROJECT_VERSION} ${SOURCES})

# 链接库到可执行文件
target_link_libraries(${PROJECT_NAME}_${PROJECT_VERSION} PRIVATE ${PROJECT_NAME}_shared)

# find_package(FFmpeg REQUIRED)
# target_link_libraries(cpp-journey_1.0 PRIVATE ${FFmpeg_LIBRARIES})

# include_directories("/path/to/your/ffmpeg/include")
# link_directories("/path/to/your/ffmpeg/lib/*")

# 处理第三方库
if(EXISTS "${PROJECT_SOURCE_DIR}/thirdparty")
    # 获取 thirdparty 目录下的所有子目录
    file(GLOB THIRDPARTY_DIRS "${PROJECT_SOURCE_DIR}/thirdparty/*")
    foreach(THIRDPARTY_DIR ${THIRDPARTY_DIRS})
        if(IS_DIRECTORY ${THIRDPARTY_DIR})
            # 获取第三方库名称
            get_filename_component(THIRDPARTY_NAME ${THIRDPARTY_DIR} NAME)

            # 添加第三方库的头文件搜索路径
            set(THIRDPARTY_INCLUDE_DIR "${THIRDPARTY_DIR}/include")
            if(EXISTS ${THIRDPARTY_INCLUDE_DIR})
                include_directories(${THIRDPARTY_INCLUDE_DIR})
                # target_include_directories(${PROJECT_NAME}_${PROJECT_VERSION} PRIVATE ${THIRDPARTY_INCLUDE_DIR})
            endif()

            # 查找 lib 目录下所有库文件
            file(GLOB THIRDPARTY_LIBS "${THIRDPARTY_DIR}/lib/*${CMAKE_SHARED_LIBRARY_SUFFIX}" "${THIRDPARTY_DIR}/lib/*${CMAKE_SHARED_LIBRARY_SUFFIX}*")            
            if(THIRDPARTY_LIBS)
                # message(WARNING "---> 在 ${THIRDPARTY_DIR}/lib 中找到以下第三方库:")
                foreach(LIB ${THIRDPARTY_LIBS})
                    # message(WARNING "---> ${PROJECT_NAME}_${PROJECT_VERSION} --->${LIB}")
                    # 将找到的第三方库链接到可执行文件
                    target_link_libraries(${PROJECT_NAME}_${PROJECT_VERSION} PRIVATE ${LIB})
                endforeach()
            else()
                message(WARNING "在 ${THIRDPARTY_DIR}/lib 中未找到任何第三方库")
            endif()
        endif()
    endforeach()
endif()

# 处理单元测试
if(BUILD_TESTS)
    enable_testing()
    add_subdirectory(test)
endif()
#!/bin/bash

# This script will build the project and run the tests.
# 定义项目根目录
PROJECT_ROOT=$(realpath "$(dirname "$0")")

# 定义构建目录
BUILD_DIR="$PROJECT_ROOT/build"

# 定义是否启用测试,默认未启动 OFF
ENABLE_TEST=${ENABLE_TEST:-OFF}

# 创建并进入构建目录
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR" || { echo "无法进入构建目录 $BUILD_DIR,退出..."; exit 1; }

# 运行 cmake 配置
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=$ENABLE_TEST
# 检查 CMake 是否成功执行
if [ $? -ne 0 ]; then
    echo "CMake configuration failed. Exiting..."
    exit 1
fi

# 编译项目
make -j$(nproc) VERBOSE=1
# 检查编译是否成功
if [ $? -ne 0 ]; then
    echo "Build failed. Exiting..."
    exit 1
fi
echo "项目构建成功,可执行文件位于 $PROJECT_ROOT/bin 目录下。"

# 检查是否启用测试
if [ "$ENABLE_TEST" = "ON" ]; then
    # 运行测试
    ctest --output-on-failure
fi

task.json构建记录

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        // 清理旧文件
        {
            "label": "Clean",
            "type": "shell",
            "command": "rm -rf ${workspaceFolder}/build/",
            "group": "build"
        },
        // 编译所有 .cpp 为 .o 文件(增量编译)
        {
            "label": "Compile Objects",
            "type": "shell",
            "command": "bash",
            "args": [
                "-c",                 
                 "mkdir -p build/obj build/bin && find src -name \"*.cpp\" | while read cpp_file; do obj_name=\"$(basename \"$cpp_file\" .cpp).o\" ; g++ -c -std=c++17 -Iinclude -Ithirdparty/ffmpeg/include -o  \"build/obj/$obj_name\" \"$cpp_file\"; done"
                ],
            "group": "build"
        },     
        // 链接生成可执行文件
        {
            "label": "Link Executable",
            "type": "shell",
            "command": "g++",
            "args": [
                "${workspaceFolder}/build/obj/*.o",
                 //"$(find ${workspaceFolder}/build/obj -name '*.o')",
                //链接选项 -l 应直接指定库名称(如 -lavcodec),而库的实际路径需通过 -L 参数指定
                "-L${workspaceFolder}/thirdparty/ffmpeg/lib",
                //GCC 的 -l 默认会自动添加前缀 lib 和后缀(如 .so)
                //FFmpeg 库有严格的依赖顺序,错误的顺序会导致链接失败。
                //-l: 语法强制指定文件名,绕过默认的 lib<name>.so 规则
                "-l:libavformat.so.62", "-l:libavcodec.so.62", "-l:libswresample.so.6", "-l:libswscale.so.9", "-l:libavfilter.so.11", "-l:libavutil.so.60", "-l:libavdevice.so.62",
                "-o",
                "${workspaceFolder}/build/bin/app"
            ],
            "dependsOn": ["Compile Objects"],
            "group": "build"
        },
    ]
}

请教过C++大神,推荐我开始学习的时候采用task.json方式进行构建,如果以后有幸最大项目开发,可以采用cmake方案。但是,经过2个方案的简单学习,我个人比较喜欢cmake方式,目前学习项目采用的构建方式都是通过cmake方式实现进行的,日后遇到坑在自己慢慢填吧!

来源链接:https://www.cnblogs.com/netx/p/18871785

© 版权声明
THE END
支持一下吧
点赞10 分享
评论 抢沙发
头像
请文明发言!
提交
头像

昵称

取消
昵称表情代码快捷回复

    暂无评论内容