include(GNUInstallDirs) option(BUILD_TESTING "Build Product Vamp tests" OFF) include(CTest) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) find_package(modulus CONFIG REQUIRED COMPONENTS boost_json openssl raylib) find_package(Threads REQUIRED) include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/build_python.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/theme.cmake) find_package(ligo CONFIG REQUIRED) find_package(noto CONFIG REQUIRED) find_package(luma CONFIG REQUIRED) find_package(sonus CONFIG REQUIRED) include(CheckCXXSourceCompiles) include(CMakePushCheckState) cmake_push_check_state(RESET) set(CMAKE_TRY_COMPILE_CONFIGURATION "${CMAKE_BUILD_TYPE}") set(CMAKE_REQUIRED_LIBRARIES sonus::sonus luma::luma) unset(VAMP_DEPENDENCY_APIS_AVAILABLE CACHE) check_cxx_source_compiles(" #include #include #include static_assert(requires(sonus::engine& engine, sonus::prepared_transport transport) { engine.play_transport(std::move(transport)); }); static_assert(requires(luma::application& application, std::string path) { application.load_texture_uncached(path); }); int main() { return 0; } " VAMP_DEPENDENCY_APIS_AVAILABLE) cmake_pop_check_state() if(NOT VAMP_DEPENDENCY_APIS_AVAILABLE) message(FATAL_ERROR "Product Vamp requires current Sonus recording transport and Luma uncached-texture APIs. Run ./modulus.py configure --update after publishing the updated dependencies, or create their Conan packages locally before configuring --no-remote. See CMake's configure log for the compiler diagnostic.") endif() execute_process( COMMAND git rev-parse --short=12 HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE VAMP_GIT_SHA OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) if(NOT VAMP_GIT_SHA) set(VAMP_GIT_SHA dev) endif() set(VAMP_STYLE_SOURCES src/vamp_style.cpp ) add_library(vamp_style STATIC ${VAMP_STYLE_SOURCES}) vamp_add_theme(vamp_style) target_include_directories(vamp_style PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ) target_compile_features(vamp_style PUBLIC cxx_std_17) target_link_libraries(vamp_style PUBLIC modulus::modulus ) set(VAMP_PROTOCOL_SOURCES src/vamp_protocol/gesture.cpp src/vamp_protocol/page_control.cpp ) add_library(vamp_protocol STATIC ${VAMP_PROTOCOL_SOURCES}) target_include_directories(vamp_protocol PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ) target_compile_features(vamp_protocol PUBLIC cxx_std_17) target_link_libraries(vamp_protocol PUBLIC modulus::modulus ) set(VAMP_CORE_SOURCES src/vamp_zero/app.cpp src/vamp_zero/audio.cpp src/vamp_zero/color.cpp src/vamp_zero/config.cpp src/vamp_zero/database.cpp src/vamp_zero/errors.cpp src/vamp_zero/health.cpp src/vamp_zero/library.cpp src/vamp_zero/menu.cpp src/vamp_zero/menu_view.cpp src/vamp_zero/navigation.cpp src/vamp_zero/notation.cpp src/vamp_zero/page_control.cpp src/vamp_zero/performance.cpp src/vamp_zero/control.cpp src/vamp_zero/score.cpp src/vamp_zero/score_loader.cpp src/vamp_zero/types.cpp src/vamp_zero/touch_input.cpp src/vamp_zero/ui.cpp ) add_library(vamp_zero_core STATIC ${VAMP_CORE_SOURCES}) target_include_directories(vamp_zero_core PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/generated) target_include_directories(vamp_zero_core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ) target_compile_features(vamp_zero_core PUBLIC cxx_std_23) target_compile_definitions(vamp_zero_core PUBLIC VAMP_GIT_SHA="${VAMP_GIT_SHA}" ) target_link_libraries(vamp_zero_core PUBLIC vamp_style vamp_protocol modulus::modulus modulus::boost_json modulus::openssl Threads::Threads ligo::ligo noto::noto luma::luma sonus::sonus PRIVATE modulus::raylib ) add_executable(vamp_zero src/vamp_zero/main.cpp) target_compile_features(vamp_zero PRIVATE cxx_std_23) target_link_libraries(vamp_zero PRIVATE vamp_zero_core) if(BUILD_TESTING) add_subdirectory(tests) endif() set(VAMP_BUNDLE_DIR ${CMAKE_CURRENT_BINARY_DIR}/bundle) set(VAMP_MANIFEST ${VAMP_BUNDLE_DIR}/manifest.json) configure_file(package/manifest.json.in ${VAMP_MANIFEST} @ONLY) file(GLOB_RECURSE VAMP_GENERATOR_INPUTS CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/data/songs/*.xml ${CMAKE_CURRENT_SOURCE_DIR}/data/training/*.xml ${CMAKE_CURRENT_SOURCE_DIR}/data/training/*.json ${CMAKE_CURRENT_SOURCE_DIR}/data/models/*.json ${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/performance_summary.json ${CMAKE_CURRENT_SOURCE_DIR}/data/composition/*.json ${CMAKE_CURRENT_SOURCE_DIR}/generator/*.py ${CMAKE_CURRENT_SOURCE_DIR}/generator/**/*.py ${VAMP_SHARED_PYTHON_INPUTS} ${CMAKE_CURRENT_SOURCE_DIR}/generator/palette.json ${CMAKE_CURRENT_SOURCE_DIR}/generator/theme.py ${CMAKE_CURRENT_SOURCE_DIR}/cmake/build_python.cmake ${CMAKE_CURRENT_SOURCE_DIR}/cmake/theme.cmake ${CMAKE_CURRENT_SOURCE_DIR}/package/assets/sounds/*.wav ${CMAKE_CURRENT_SOURCE_DIR}/package/assets/backing/*.wav ${CMAKE_CURRENT_SOURCE_DIR}/package/assets/fonts/* ${CMAKE_CURRENT_SOURCE_DIR}/package/assets/fonts/**/* ) set(VAMP_GENERATED_ASSETS_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated_assets) set(VAMP_GENERATED_ASSETS_STAMP ${CMAKE_CURRENT_BINARY_DIR}/generated_assets.stamp) set(VAMP_ENGRAVING_JOBS 2 CACHE STRING "Maximum parallel Python engraving workers (1-16)") set(VAMP_COMPOSITION_JOBS 2 CACHE STRING "Maximum independent musical role workers (1-16)") set(VAMP_ENGRAVING_CACHE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build/build_common/engraving_cache" CACHE PATH "Shared build-only page cache; empty disables caching") set(VAMP_ENGRAVING_CACHE_ARGS) if(VAMP_ENGRAVING_CACHE_DIR) list(APPEND VAMP_ENGRAVING_CACHE_ARGS --engraving-cache "${VAMP_ENGRAVING_CACHE_DIR}") endif() string(JOIN "\n" VAMP_GENERATOR_INPUT_MANIFEST ${VAMP_GENERATOR_INPUTS}) file(CONFIGURE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated_assets.inputs CONTENT "@VAMP_GENERATOR_INPUT_MANIFEST@\n" @ONLY) add_custom_command( OUTPUT ${VAMP_GENERATED_ASSETS_STAMP} BYPRODUCTS ${VAMP_GENERATED_ASSETS_DIR}/catalog.db COMMAND ${VAMP_PYTHON_COMMAND} -m generator --data-dir ${CMAKE_CURRENT_SOURCE_DIR}/data --output-dir ${VAMP_GENERATED_ASSETS_DIR} --static-assets-dir ${CMAKE_CURRENT_SOURCE_DIR}/package/assets --check --jobs ${VAMP_ENGRAVING_JOBS} --composition-jobs ${VAMP_COMPOSITION_JOBS} --composition-cache ${CMAKE_CURRENT_SOURCE_DIR}/build/build_common/composition_cache --progress ${VAMP_ENGRAVING_CACHE_ARGS} COMMAND ${CMAKE_COMMAND} -E touch ${VAMP_GENERATED_ASSETS_STAMP} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ${VAMP_GENERATOR_INPUTS} ${CMAKE_CURRENT_BINARY_DIR}/generated_assets.inputs USES_TERMINAL VERBATIM ) add_custom_target(vamp_generated_assets ALL DEPENDS ${VAMP_GENERATED_ASSETS_STAMP}) if(BUILD_TESTING) add_dependencies(product_vamp_test vamp_generated_assets) endif() install(TARGETS vamp_zero RUNTIME DESTINATION zero/bin ) install(FILES package/config/vamp.example.json DESTINATION zero/config) install(DIRECTORY ${VAMP_GENERATED_ASSETS_DIR}/ DESTINATION zero/share/product_vamp PATTERN "*.json" EXCLUDE PATTERN "analysis" EXCLUDE PATTERN "print" EXCLUDE) install(PROGRAMS package/zero/install_zero.sh package/zero/start_ap.sh package/zero/start_zero.sh DESTINATION zero ) install(FILES package/zero/product_vamp_ap.service package/zero/product_vamp_zero.service DESTINATION zero/systemd ) install(FILES package/pico/wiring.md DESTINATION pico) install(FILES ${VAMP_MANIFEST} DESTINATION .) if(VAMP_BUILD_ZERO_IMAGE OR VAMP_BUILD_PICO_FIRMWARE) find_program(BASH_EXECUTABLE bash REQUIRED) endif() if(VAMP_BUILD_ZERO_IMAGE) find_program(DOCKER_EXECUTABLE docker REQUIRED) set(VAMP_ZERO_IMAGE_CONTEXT ${CMAKE_CURRENT_BINARY_DIR}/zero_image_context) set(VAMP_ZERO_IMAGE_TAR ${CMAKE_CURRENT_BINARY_DIR}/product_vamp_zero_linux_arm64.docker.tar) add_custom_command( OUTPUT ${VAMP_ZERO_IMAGE_TAR} COMMAND ${CMAKE_COMMAND} -E rm -rf ${VAMP_ZERO_IMAGE_CONTEXT} COMMAND ${CMAKE_COMMAND} -E make_directory ${VAMP_ZERO_IMAGE_CONTEXT}/usr/bin COMMAND ${CMAKE_COMMAND} -E make_directory ${VAMP_ZERO_IMAGE_CONTEXT}/usr/share/product_vamp COMMAND ${CMAKE_COMMAND} -E copy $ ${VAMP_ZERO_IMAGE_CONTEXT}/usr/bin/vamp_zero COMMAND ${CMAKE_COMMAND} -E copy package/zero/Dockerfile ${VAMP_ZERO_IMAGE_CONTEXT}/Dockerfile COMMAND ${CMAKE_COMMAND} -DSOURCE=${VAMP_GENERATED_ASSETS_DIR} -DDESTINATION=${VAMP_ZERO_IMAGE_CONTEXT}/usr/share/product_vamp -P cmake/runtime_assets.cmake COMMAND ${CMAKE_COMMAND} -E make_directory ${VAMP_ZERO_IMAGE_CONTEXT}/usr/share/product_vamp/config COMMAND ${CMAKE_COMMAND} -E copy package/config/vamp.example.json ${VAMP_ZERO_IMAGE_CONTEXT}/usr/share/product_vamp/config/vamp.example.json COMMAND ${BASH_EXECUTABLE} package/scripts/build_zero_image.sh ${VAMP_ZERO_IMAGE_CONTEXT} ${VAMP_ZERO_IMAGE_TAR} ${VAMP_ZERO_IMAGE_TAG} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS vamp_zero package/scripts/build_zero_image.sh package/zero/Dockerfile package/config/vamp.example.json cmake/runtime_assets.cmake ${VAMP_GENERATED_ASSETS_STAMP} VERBATIM ) add_custom_target(vamp_zero_image ALL DEPENDS ${VAMP_ZERO_IMAGE_TAR}) install(FILES ${VAMP_ZERO_IMAGE_TAR} DESTINATION zero) endif() if(VAMP_BUILD_PICO_FIRMWARE) set(VAMP_PICO_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/pico_build) set(VAMP_PICO_UF2 ${CMAKE_CURRENT_BINARY_DIR}/product_vamp_pico2w.uf2) file(GLOB VAMP_PICO_SOURCES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/cmake/pico.cmake ${CMAKE_CURRENT_SOURCE_DIR}/cmake/pico_artwork.cmake ${CMAKE_CURRENT_SOURCE_DIR}/generator/pico_artwork.py ${VAMP_SHARED_PYTHON_INPUTS} ${CMAKE_CURRENT_SOURCE_DIR}/generator/palette.json ${CMAKE_CURRENT_SOURCE_DIR}/generator/theme.py ${CMAKE_CURRENT_SOURCE_DIR}/cmake/build_python.cmake ${CMAKE_CURRENT_SOURCE_DIR}/cmake/theme.cmake ${CMAKE_CURRENT_SOURCE_DIR}/package/assets/fonts/petaluma/PetalumaScript.otf ${CMAKE_CURRENT_SOURCE_DIR}/cmake/vamp_options.cmake ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/vamp_style/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/vamp_pico/*.h ${CMAKE_CURRENT_SOURCE_DIR}/include/vamp_pico/capi/*.h ${CMAKE_CURRENT_SOURCE_DIR}/include/vamp_pico/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/vamp_protocol/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/src/vamp_style.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/vamp_pico/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/vamp_pico/*.S.in ${CMAKE_CURRENT_SOURCE_DIR}/src/vamp_protocol/*.cpp ) add_custom_command( OUTPUT ${VAMP_PICO_UF2} COMMAND ${BASH_EXECUTABLE} package/scripts/build_pico_firmware.sh ${VAMP_PICO_BUILD_DIR} ${VAMP_PICO_UF2} ${VAMP_PICO_SDK_VERSION} "${VAMP_PICO_WIFI_SSID}" "${VAMP_PICO_WIFI_PASSPHRASE}" "${VAMP_ZERO_HOST}" "${VAMP_ZERO_PORT}" "${modulus_INCLUDE_DIR}" "${Python3_EXECUTABLE}" "${MODULUS_PYTHON_RUNNER}" "${MODULUS_PYTHON_ROOT}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS package/scripts/build_pico_firmware.sh ${VAMP_PICO_SOURCES} VERBATIM ) add_custom_target(vamp_pico_firmware ALL DEPENDS ${VAMP_PICO_UF2}) install(FILES ${VAMP_PICO_UF2} DESTINATION pico) endif()