找回密码
 立即注册
首页 资源区 代码 [技术探索者手记] C++自学之路 × linux下搭建属于 ...

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

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


  • linux下构建自己的个性化的FFmpeg库
  • linux下搭建属于自己风格的FFmpeg开发项目框架
目录结构设计
  1. project_name/
  2.     ├── .vscode
  3.     │   └── settings.json
  4.     │   └── tasks.json
  5.     ├── bin/        # 可执行文件
  6.     ├── build/      # 编译中间文件(*.o, *.d)
  7.     ├── lib/        # 库文件
  8.     ├── include/    # 公共头文件(按模块/项目名组织)
  9.     │   └── project_name/
  10.     ├── src/        # 源文件(按模块组织)
  11.     │   └── app/
  12.     │       └── main.cpp
  13.     │   └── project_name/
  14.     │         └── xxx.cpp
  15.     ├── test/       # 单元测试代码
  16.     ├── thirdparty/ # 第三方库(或external/3rdparty)
  17.     │   └── thirdpartylibname(例如:ffmpeg)
  18.     │          └── include
  19.     │          └── lib
  20.     ├── CMakeLists.txt # 构建配置
  21.     ├── build.sh #cmake 构建执行脚本
  22.     └── README.md   # 项目说明
复制代码
学习了2中构建方式:
- Make构建
- task.json构建
CMake构建记录
  1. # 设置 CMake 最低版本要求
  2. cmake_minimum_required(VERSION 3.10)
  3. # 设置项目名称
  4. project(cpp-journey                   # 项目名称
  5.   VERSION 1.0                         # 项目版本(可选)
  6.   LANGUAGES CXX                       # 指定语言(CXX为C++)
  7. )
  8. # 设置 C++ 标准
  9. set(CMAKE_CXX_STANDARD 17)           # 设置 C++ 标准为 C++17
  10. set(CMAKE_CXX_STANDARD_REQUIRED ON)  # 要求使用 C++17 标准
  11. set(CMAKE_BUILD_TYPE Release)        # 默认构建类型(Debug/Release)
  12. # 设置可执行文件输出目录
  13. set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
  14. # 设置库文件输出目录
  15. set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
  16. # 添加头文件搜索路径
  17. include_directories(${PROJECT_SOURCE_DIR}/include)
  18. # 自动查找 src 目录下的所有源文件
  19. file(GLOB_RECURSE SOURCES "${PROJECT_SOURCE_DIR}/src/*.cpp")
  20. # 生成静态库
  21. add_library(${PROJECT_NAME}_static STATIC ${SOURCES})
  22. set_target_properties(${PROJECT_NAME}_static PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
  23. # 生成动态库
  24. add_library(${PROJECT_NAME}_shared SHARED ${SOURCES})
  25. set_target_properties(${PROJECT_NAME}_shared PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
  26. # 添加可执行文件
  27. add_executable(${PROJECT_NAME}_${PROJECT_VERSION} ${SOURCES})
  28. # 链接库到可执行文件
  29. target_link_libraries(${PROJECT_NAME}_${PROJECT_VERSION} PRIVATE ${PROJECT_NAME}_shared)
  30. # find_package(FFmpeg REQUIRED)
  31. # target_link_libraries(cpp-journey_1.0 PRIVATE ${FFmpeg_LIBRARIES})
  32. # include_directories("/path/to/your/ffmpeg/include")
  33. # link_directories("/path/to/your/ffmpeg/lib/*")
  34. # 处理第三方库
  35. if(EXISTS "${PROJECT_SOURCE_DIR}/thirdparty")
  36.     # 获取 thirdparty 目录下的所有子目录
  37.     file(GLOB THIRDPARTY_DIRS "${PROJECT_SOURCE_DIR}/thirdparty/*")
  38.     foreach(THIRDPARTY_DIR ${THIRDPARTY_DIRS})
  39.         if(IS_DIRECTORY ${THIRDPARTY_DIR})
  40.             # 获取第三方库名称
  41.             get_filename_component(THIRDPARTY_NAME ${THIRDPARTY_DIR} NAME)
  42.             # 添加第三方库的头文件搜索路径
  43.             set(THIRDPARTY_INCLUDE_DIR "${THIRDPARTY_DIR}/include")
  44.             if(EXISTS ${THIRDPARTY_INCLUDE_DIR})
  45.                 include_directories(${THIRDPARTY_INCLUDE_DIR})
  46.                 # target_include_directories(${PROJECT_NAME}_${PROJECT_VERSION} PRIVATE ${THIRDPARTY_INCLUDE_DIR})
  47.             endif()
  48.             # 查找 lib 目录下所有库文件
  49.             file(GLOB THIRDPARTY_LIBS "${THIRDPARTY_DIR}/lib/*${CMAKE_SHARED_LIBRARY_SUFFIX}" "${THIRDPARTY_DIR}/lib/*${CMAKE_SHARED_LIBRARY_SUFFIX}*")            
  50.             if(THIRDPARTY_LIBS)
  51.                 # message(WARNING "---> 在 ${THIRDPARTY_DIR}/lib 中找到以下第三方库:")
  52.                 foreach(LIB ${THIRDPARTY_LIBS})
  53.                     # message(WARNING "---> ${PROJECT_NAME}_${PROJECT_VERSION} --->${LIB}")
  54.                     # 将找到的第三方库链接到可执行文件
  55.                     target_link_libraries(${PROJECT_NAME}_${PROJECT_VERSION} PRIVATE ${LIB})
  56.                 endforeach()
  57.             else()
  58.                 message(WARNING "在 ${THIRDPARTY_DIR}/lib 中未找到任何第三方库")
  59.             endif()
  60.         endif()
  61.     endforeach()
  62. endif()
  63. # 处理单元测试
  64. if(BUILD_TESTS)
  65.     enable_testing()
  66.     add_subdirectory(test)
  67. endif()
复制代码
  1. #!/bin/bash
  2. # This script will build the project and run the tests.
  3. # 定义项目根目录
  4. PROJECT_ROOT=$(realpath "$(dirname "$0")")
  5. # 定义构建目录
  6. BUILD_DIR="$PROJECT_ROOT/build"
  7. # 定义是否启用测试,默认未启动 OFF
  8. ENABLE_TEST=${ENABLE_TEST:-OFF}
  9. # 创建并进入构建目录
  10. mkdir -p "$BUILD_DIR"
  11. cd "$BUILD_DIR" || { echo "无法进入构建目录 $BUILD_DIR,退出..."; exit 1; }
  12. # 运行 cmake 配置
  13. cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=$ENABLE_TEST
  14. # 检查 CMake 是否成功执行
  15. if [ $? -ne 0 ]; then
  16.     echo "CMake configuration failed. Exiting..."
  17.     exit 1
  18. fi
  19. # 编译项目
  20. make -j$(nproc) VERBOSE=1
  21. # 检查编译是否成功
  22. if [ $? -ne 0 ]; then
  23.     echo "Build failed. Exiting..."
  24.     exit 1
  25. fi
  26. echo "项目构建成功,可执行文件位于 $PROJECT_ROOT/bin 目录下。"
  27. # 检查是否启用测试
  28. if [ "$ENABLE_TEST" = "ON" ]; then
  29.     # 运行测试
  30.     ctest --output-on-failure
  31. fi
复制代码
task.json构建记录
  1. {
  2.     // See https://go.microsoft.com/fwlink/?LinkId=733558
  3.     // for the documentation about the tasks.json format
  4.     "version": "2.0.0",
  5.     "tasks": [
  6.         // 清理旧文件
  7.         {
  8.             "label": "Clean",
  9.             "type": "shell",
  10.             "command": "rm -rf ${workspaceFolder}/build/",
  11.             "group": "build"
  12.         },
  13.         // 编译所有 .cpp 为 .o 文件(增量编译)
  14.         {
  15.             "label": "Compile Objects",
  16.             "type": "shell",
  17.             "command": "bash",
  18.             "args": [
  19.                 "-c",                 
  20.                  "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"
  21.                 ],
  22.             "group": "build"
  23.         },     
  24.         // 链接生成可执行文件
  25.         {
  26.             "label": "Link Executable",
  27.             "type": "shell",
  28.             "command": "g++",
  29.             "args": [
  30.                 "${workspaceFolder}/build/obj/*.o",
  31.                  //"$(find ${workspaceFolder}/build/obj -name '*.o')",
  32.                 //链接选项 -l 应直接指定库名称(如 -lavcodec),而库的实际路径需通过 -L 参数指定
  33.                 "-L${workspaceFolder}/thirdparty/ffmpeg/lib",
  34.                 //GCC 的 -l 默认会自动添加前缀 lib 和后缀(如 .so)
  35.                 //FFmpeg 库有严格的依赖顺序,错误的顺序会导致链接失败。
  36.                 //-l: 语法强制指定文件名,绕过默认的 lib<name>.so 规则
  37.                 "-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",
  38.                 "-o",
  39.                 "${workspaceFolder}/build/bin/app"
  40.             ],
  41.             "dependsOn": ["Compile Objects"],
  42.             "group": "build"
  43.         },
  44.     ]
  45. }
复制代码
请教过C++大神,推荐我开始学习的时候采用task.json方式进行构建,如果以后有幸最大项目开发,可以采用cmake方案。但是,经过2个方案的简单学习,我个人比较喜欢cmake方式,目前学习项目采用的构建方式都是通过cmake方式实现进行的,日后遇到坑在自己慢慢填吧!

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册