cmake_minimum_required(VERSION 3.22) project(rockstream VERSION 0.1.0 LANGUAGES CXX) if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") message(FATAL_ERROR "rockstream currently supports Linux only") endif() option(ROCKSTREAM_WITH_MPP "Build with the target BSP's Rockchip MPP SDK" OFF) option(ROCKSTREAM_SANITIZERS "Enable AddressSanitizer and UndefinedBehaviorSanitizer" OFF) option(ROCKSTREAM_WARNINGS_AS_ERRORS "Treat project compiler warnings as errors" OFF) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(CMAKE_EXPORT_COMPILE_COMMANDS ON) include(CTest) include(GNUInstallDirs) find_package(Threads REQUIRED) add_library(rockstream_options INTERFACE) target_compile_features(rockstream_options INTERFACE cxx_std_20) if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") target_compile_options(rockstream_options INTERFACE -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wshadow $<$:-Werror>) if(ROCKSTREAM_SANITIZERS) include(CheckCXXSourceCompiles) include(CMakePushCheckState) cmake_push_check_state(RESET) set(CMAKE_REQUIRED_FLAGS "-fsanitize=address,undefined") set(CMAKE_REQUIRED_LINK_OPTIONS "-fsanitize=address,undefined") check_cxx_source_compiles("int main() { return 0; }" ROCKSTREAM_SANITIZERS_LINK) cmake_pop_check_state() if(NOT ROCKSTREAM_SANITIZERS_LINK) message(FATAL_ERROR "Sanitizer runtime compile/link check failed. Install ASan and UBSan runtimes matching your compiler, or disable ROCKSTREAM_SANITIZERS.") endif() target_compile_options(rockstream_options INTERFACE -fsanitize=address,undefined -fno-omit-frame-pointer) target_link_options(rockstream_options INTERFACE -fsanitize=address,undefined) endif() elseif(ROCKSTREAM_SANITIZERS OR ROCKSTREAM_WARNINGS_AS_ERRORS) message(FATAL_ERROR "Requested compiler options require GCC or Clang") endif() if(ROCKSTREAM_WITH_MPP) find_package(RockchipMPP REQUIRED) # Compile and link only: this check never executes hardware code, including # when cross compiling. Catch missing public headers or an unusable library. include(CheckCXXSourceCompiles) include(CMakePushCheckState) cmake_push_check_state(RESET) set(CMAKE_REQUIRED_LIBRARIES RockchipMPP::MPP) unset(ROCKSTREAM_MPP_SDK_LINKS CACHE) check_cxx_source_compiles(" #include #include #include #include #include #include int main() { MppCtx ctx = nullptr; MppApi* api = nullptr; MppEncCfg cfg = nullptr; if (mpp_enc_cfg_init(&cfg) != MPP_OK) return 1; mpp_enc_cfg_deinit(cfg); if (mpp_create(&ctx, &api) != MPP_OK) return 1; return mpp_destroy(ctx); }" ROCKSTREAM_MPP_SDK_LINKS) cmake_pop_check_state() if(NOT ROCKSTREAM_MPP_SDK_LINKS) message(FATAL_ERROR "MPP SDK compile/link check failed. Use matching BSP headers and libraries; see CMakeFiles/CMakeError.log or CMakeConfigureLog.yaml.") endif() endif() configure_file(cmake/build_config.hpp.in generated/rockstream/build_config.hpp @ONLY) add_library(rockstream_core STATIC src/build_info.cpp src/probe.cpp src/latency.cpp) target_include_directories(rockstream_core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/generated") target_link_libraries(rockstream_core PRIVATE rockstream_options PUBLIC Threads::Threads) set_target_properties(rockstream_core PROPERTIES CXX_EXTENSIONS OFF) if(ROCKSTREAM_WITH_MPP) target_sources(rockstream_core PRIVATE src/mpp_probe.cpp) target_link_libraries(rockstream_core PRIVATE RockchipMPP::MPP) else() # Host development gets public API declarations, never a pretend MPP runtime. add_library(rockstream_mpp_headers INTERFACE) target_include_directories(rockstream_mpp_headers SYSTEM INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/third_party/mpp/include") target_link_libraries(rockstream_core PRIVATE rockstream_mpp_headers) endif() add_executable(rockstream src/main.cpp) target_link_libraries(rockstream PRIVATE rockstream_core rockstream_options) set_target_properties(rockstream PROPERTIES CXX_EXTENSIONS OFF) install(TARGETS rockstream RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") if(BUILD_TESTING) # Compile only: exercise SDK declarations without requiring device access or # linking undefined MPP calls. Board builds use their installed SDK instead. add_library(mpp_headers_check OBJECT tests/mpp_headers_check.cpp) if(NOT ROCKSTREAM_WITH_MPP) # Compile the complete native probe against pinned headers on the host. # Its objects are deliberately never linked into a host executable. target_sources(mpp_headers_check PRIVATE src/mpp_probe.cpp) target_include_directories(mpp_headers_check PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") endif() target_link_libraries(mpp_headers_check PRIVATE rockstream_options) set_target_properties(mpp_headers_check PROPERTIES CXX_EXTENSIONS OFF) if(ROCKSTREAM_WITH_MPP) target_link_libraries(mpp_headers_check PRIVATE RockchipMPP::MPP) else() target_link_libraries(mpp_headers_check PRIVATE rockstream_mpp_headers) endif() add_test(NAME cli_help COMMAND rockstream --help) add_test(NAME cli_build_info COMMAND rockstream --build-info) set_tests_properties(cli_build_info PROPERTIES PASS_REGULAR_EXPRESSION "MPP SDK: (enabled|disabled)") add_test(NAME cli_reject_unknown COMMAND rockstream --invalid-option) set_tests_properties(cli_reject_unknown PROPERTIES WILL_FAIL TRUE) add_test(NAME probe_dry_run COMMAND rockstream encode-probe --dry-run --tiles off --split-ctus 60) set_tests_properties(probe_dry_run PROPERTIES PASS_REGULAR_EXPRESSION "Dry run: no encoder initialized") add_executable(probe_tests tests/probe_tests.cpp) target_link_libraries(probe_tests PRIVATE rockstream_core rockstream_options) set_target_properties(probe_tests PROPERTIES CXX_EXTENSIONS OFF) add_test(NAME probe_logic COMMAND probe_tests) endif() message(STATUS "rockstream ${PROJECT_VERSION}: ${CMAKE_SYSTEM_PROCESSOR}, MPP=${ROCKSTREAM_WITH_MPP}, sanitizers=${ROCKSTREAM_SANITIZERS}")