321 lines
11 KiB
CMake
321 lines
11 KiB
CMake
# CMakeLists.txt
|
|
|
|
cmake_minimum_required(VERSION 3.18)
|
|
|
|
project(YrCrystals VERSION 1.0 LANGUAGES CXX C)
|
|
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_AUTOMOC ON)
|
|
set(CMAKE_AUTORCC ON)
|
|
set(CMAKE_AUTOUIC ON)
|
|
|
|
# --- FOR WINDOWS MSVC ERRORS ---
|
|
if(MSVC)
|
|
add_compile_options($<$<COMPILE_LANGUAGE:C>:/std:clatest>)
|
|
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
|
endif()
|
|
|
|
include(FetchContent)
|
|
|
|
option(BUILD_ANDROID "Build for Android" OFF)
|
|
option(BUILD_IOS "Build for iOS" OFF)
|
|
|
|
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Multimedia)
|
|
find_package(Qt6 QUIET COMPONENTS ShaderTools)
|
|
|
|
# --- FFTW3 Configuration (Double Precision) ---
|
|
|
|
if(WIN32)
|
|
# Windows: Expects FFTW3 to be installed/found via Config
|
|
find_package(FFTW3 CONFIG REQUIRED)
|
|
if(TARGET FFTW3::fftw3)
|
|
add_library(fftw3 ALIAS FFTW3::fftw3)
|
|
endif()
|
|
elseif(APPLE AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" AND NOT BUILD_IOS)
|
|
message(STATUS "Detected Apple Silicon Desktop. Using Homebrew FFTW3 (Double).")
|
|
find_library(FFTW3_LIB NAMES fftw3 libfftw3 PATHS /opt/homebrew/lib NO_DEFAULT_PATH)
|
|
find_path(FFTW3_INCLUDE_DIR fftw3.h PATHS /opt/homebrew/include NO_DEFAULT_PATH)
|
|
|
|
if(NOT FFTW3_LIB OR NOT FFTW3_INCLUDE_DIR)
|
|
message(FATAL_ERROR "FFTW3 not found in /opt/homebrew. Please run: brew install fftw")
|
|
endif()
|
|
|
|
add_library(fftw3 STATIC IMPORTED)
|
|
set_target_properties(fftw3 PROPERTIES
|
|
IMPORTED_LOCATION "${FFTW3_LIB}"
|
|
INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR}"
|
|
)
|
|
|
|
else()
|
|
message(STATUS "Building FFTW3 from source (Double Precision)...")
|
|
|
|
set(ENABLE_FLOAT OFF CACHE BOOL "Build double precision" FORCE)
|
|
set(ENABLE_SSE OFF CACHE BOOL "Disable SSE" FORCE)
|
|
set(ENABLE_SSE2 OFF CACHE BOOL "Disable SSE2" FORCE)
|
|
set(ENABLE_AVX OFF CACHE BOOL "Disable AVX" FORCE)
|
|
set(ENABLE_AVX2 OFF CACHE BOOL "Disable AVX2" FORCE)
|
|
set(ENABLE_THREADS OFF CACHE BOOL "Disable Threads" FORCE)
|
|
set(ENABLE_OPENMP OFF CACHE BOOL "Disable OpenMP" FORCE)
|
|
set(ENABLE_MPI OFF CACHE BOOL "Disable MPI" FORCE)
|
|
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build Static Libs" FORCE)
|
|
set(BUILD_TESTS OFF CACHE BOOL "Disable Tests" FORCE)
|
|
|
|
# Enhanced NEON detection for Windows on Arm as well
|
|
if(ANDROID_ABI STREQUAL "arm64-v8a")
|
|
message(STATUS "Enabling NEON for Android ARM64")
|
|
set(ENABLE_NEON ON CACHE BOOL "Enable NEON" FORCE)
|
|
elseif(BUILD_IOS)
|
|
set(ENABLE_NEON ON CACHE BOOL "Enable NEON" FORCE)
|
|
elseif(MSVC AND CMAKE_SYSTEM_PROCESSOR MATCHES "(ARM64|arm64|aarch64)")
|
|
set(ENABLE_NEON ON CACHE BOOL "Enable NEON" FORCE)
|
|
endif()
|
|
|
|
# Only apply sed patch on UNIX-like systems
|
|
if(UNIX)
|
|
set(PATCH_CMD sed -i.bak "s/cmake_minimum_required.*/cmake_minimum_required(VERSION 3.16)/" <SOURCE_DIR>/CMakeLists.txt)
|
|
else()
|
|
set(PATCH_CMD "")
|
|
endif()
|
|
|
|
FetchContent_Declare(
|
|
fftw3_source
|
|
URL https://www.fftw.org/fftw-3.3.10.tar.gz
|
|
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
|
PATCH_COMMAND ${PATCH_CMD}
|
|
)
|
|
|
|
FetchContent_MakeAvailable(fftw3_source)
|
|
endif()
|
|
|
|
# ==========================================
|
|
# --- ICON GENERATION ---
|
|
# ==========================================
|
|
|
|
set(ICON_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/assets/icon_source.png")
|
|
|
|
find_program(MAGICK_EXECUTABLE NAMES magick)
|
|
if(NOT MAGICK_EXECUTABLE)
|
|
message(WARNING "ImageMagick 'magick' not found. Icons will not be generated.")
|
|
endif()
|
|
|
|
if(EXISTS "${ICON_SOURCE}" AND MAGICK_EXECUTABLE)
|
|
|
|
if(WIN32)
|
|
# --- WINDOWS SPECIFIC ---
|
|
# Generates into BINARY dir to keep source clean
|
|
set(WINDOWS_ICON "${CMAKE_CURRENT_BINARY_DIR}/app_icon.ico")
|
|
set(WINDOWS_RC "${CMAKE_CURRENT_BINARY_DIR}/app_icon.rc")
|
|
set(ICON_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_icons.bat")
|
|
|
|
# 1. Create the .rc file so the linker knows to include the icon
|
|
file(WRITE "${WINDOWS_RC}" "IDI_ICON1 ICON \"app_icon.ico\"\n")
|
|
|
|
# 2. Command to generate the actual .ico
|
|
add_custom_command(
|
|
OUTPUT "${WINDOWS_ICON}"
|
|
COMMAND "${ICON_SCRIPT}" "${MAGICK_EXECUTABLE}" "${ICON_SOURCE}" "${WINDOWS_ICON}"
|
|
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
|
DEPENDS "${ICON_SOURCE}" "${ICON_SCRIPT}"
|
|
COMMENT "Generating Windows Icon (app_icon.ico)..."
|
|
VERBATIM
|
|
)
|
|
|
|
add_custom_target(GenerateIcons DEPENDS "${WINDOWS_ICON}")
|
|
|
|
else()
|
|
# --- MAC/LINUX/ANDROID/IOS SPECIFIC ---
|
|
# Must generate into SOURCE dir so Android/iOS packaging tools find them
|
|
set(MACOS_ICON "${CMAKE_CURRENT_SOURCE_DIR}/assets/icons/app_icon.icns")
|
|
set(IOS_ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/ios/Assets.xcassets")
|
|
set(IOS_CONTENTS_JSON "${IOS_ASSETS_PATH}/Contents.json")
|
|
set(ANDROID_RES_PATH "${CMAKE_CURRENT_SOURCE_DIR}/android/res/mipmap-mdpi/ic_launcher.png")
|
|
|
|
set(ICON_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_icons.sh")
|
|
execute_process(COMMAND chmod +x "${ICON_SCRIPT}")
|
|
|
|
add_custom_command(
|
|
OUTPUT "${MACOS_ICON}" "${IOS_CONTENTS_JSON}" "${ANDROID_RES_PATH}"
|
|
COMMAND "${ICON_SCRIPT}" "${MAGICK_EXECUTABLE}"
|
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
DEPENDS "${ICON_SOURCE}" "${ICON_SCRIPT}"
|
|
COMMENT "Generating Cross-Platform Icons..."
|
|
VERBATIM
|
|
)
|
|
|
|
add_custom_target(GenerateIcons DEPENDS "${MACOS_ICON}" "${IOS_CONTENTS_JSON}" "${ANDROID_RES_PATH}")
|
|
endif()
|
|
endif()
|
|
|
|
# --- Sources ---
|
|
|
|
set(PROJECT_SOURCES
|
|
src/main.cpp
|
|
src/Utils.cpp
|
|
src/Processor.cpp
|
|
src/AudioEngine.cpp
|
|
src/VisualizerWidget.cpp
|
|
src/CommonWidgets.cpp
|
|
src/PlayerControls.cpp
|
|
src/MainWindow.cpp
|
|
src/complex_block.cpp
|
|
src/complex_frames.cpp
|
|
src/trig_interpolation.cpp
|
|
)
|
|
|
|
# Add the generated icons AND the RC file to the source list
|
|
if(EXISTS "${ICON_SOURCE}")
|
|
if(WIN32)
|
|
list(APPEND PROJECT_SOURCES ${WINDOWS_RC} ${WINDOWS_ICON})
|
|
elseif(APPLE AND NOT BUILD_IOS)
|
|
list(APPEND PROJECT_SOURCES ${MACOS_ICON})
|
|
endif()
|
|
endif()
|
|
|
|
set(PROJECT_HEADERS
|
|
src/Utils.h
|
|
src/Processor.h
|
|
src/AudioEngine.h
|
|
src/VisualizerWidget.h
|
|
src/CommonWidgets.h
|
|
src/PlayerControls.h
|
|
src/MainWindow.h
|
|
src/complex_block.h
|
|
src/complex_frames.h
|
|
src/trig_interpolation.h
|
|
)
|
|
|
|
qt_add_executable(YrCrystals MANUAL_FINALIZATION ${PROJECT_SOURCES} ${PROJECT_HEADERS})
|
|
|
|
if(TARGET Qt6::ShaderTools)
|
|
qt_add_shaders(YrCrystals "visualizer_shaders"
|
|
BATCHABLE
|
|
PREFIX "/"
|
|
FILES
|
|
shaders/visualizer.vert
|
|
shaders/visualizer.frag
|
|
)
|
|
else()
|
|
set(QSB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build_macos/.qsb/shaders")
|
|
if(NOT EXISTS "${QSB_DIR}/visualizer.vert.qsb" OR NOT EXISTS "${QSB_DIR}/visualizer.frag.qsb")
|
|
message(FATAL_ERROR "Pre-compiled shaders not found. Run 'make macos' first.")
|
|
endif()
|
|
qt_add_resources(YrCrystals "visualizer_shaders"
|
|
PREFIX "/shaders"
|
|
BASE "${QSB_DIR}"
|
|
FILES
|
|
${QSB_DIR}/visualizer.vert.qsb
|
|
${QSB_DIR}/visualizer.frag.qsb
|
|
)
|
|
endif()
|
|
|
|
if(EXISTS "${ICON_SOURCE}" AND MAGICK_EXECUTABLE)
|
|
add_dependencies(YrCrystals GenerateIcons)
|
|
endif()
|
|
|
|
# --- Mobile Definitions ---
|
|
if(BUILD_ANDROID OR BUILD_IOS)
|
|
target_compile_definitions(YrCrystals PRIVATE IS_MOBILE)
|
|
endif()
|
|
|
|
# --- Linking ---
|
|
|
|
if(TARGET fftw3)
|
|
set(FFTW_TARGET fftw3)
|
|
# Only include source dirs if actually built from source (FetchContent)
|
|
if(DEFINED fftw3_source_SOURCE_DIR)
|
|
target_include_directories(YrCrystals PRIVATE
|
|
"${fftw3_source_SOURCE_DIR}/api"
|
|
"${fftw3_source_BINARY_DIR}"
|
|
)
|
|
endif()
|
|
else()
|
|
set(FFTW_TARGET fftw3)
|
|
endif()
|
|
|
|
target_link_libraries(YrCrystals PRIVATE
|
|
Qt6::Core Qt6::Gui Qt6::GuiPrivate Qt6::Widgets Qt6::Multimedia
|
|
${FFTW_TARGET}
|
|
)
|
|
|
|
if(BUILD_ANDROID)
|
|
target_link_libraries(YrCrystals PRIVATE log m)
|
|
set_property(TARGET YrCrystals PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
|
|
endif()
|
|
|
|
if(BUILD_IOS)
|
|
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ios/Info.plist")
|
|
message(FATAL_ERROR "Missing ios/Info.plist. Please create it before building.")
|
|
endif()
|
|
|
|
set_source_files_properties(src/Utils.cpp PROPERTIES LANGUAGE OBJCXX)
|
|
|
|
set_target_properties(YrCrystals PROPERTIES
|
|
MACOSX_BUNDLE TRUE
|
|
MACOSX_BUNDLE_BUNDLE_NAME "Yr Crystals"
|
|
MACOSX_BUNDLE_GUI_IDENTIFIER "com.yrcrystals.app"
|
|
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/ios/Info.plist"
|
|
XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon"
|
|
RESOURCE "${IOS_ASSETS_PATH}"
|
|
)
|
|
|
|
if(EXISTS "${ICON_SOURCE}")
|
|
message(STATUS "Adding iOS Assets from: ${IOS_ASSETS_PATH}")
|
|
file(MAKE_DIRECTORY "${IOS_ASSETS_PATH}")
|
|
target_sources(YrCrystals PRIVATE "${IOS_ASSETS_PATH}")
|
|
endif()
|
|
|
|
qt_import_plugins(YrCrystals
|
|
EXCLUDE
|
|
Qt6::FFmpegMediaPlugin
|
|
Qt6::QFFmpegMediaPlugin
|
|
)
|
|
|
|
target_link_libraries(YrCrystals PRIVATE
|
|
"-framework AudioToolbox"
|
|
"-framework AVFoundation"
|
|
"-framework CoreMedia"
|
|
"-framework VideoToolbox"
|
|
"-framework CoreVideo"
|
|
"-framework CoreFoundation"
|
|
"-framework UIKit"
|
|
"-framework UniformTypeIdentifiers"
|
|
"-lz"
|
|
"-lbz2"
|
|
"-liconv"
|
|
)
|
|
endif()
|
|
|
|
if(APPLE AND NOT BUILD_IOS)
|
|
set_target_properties(YrCrystals PROPERTIES
|
|
MACOSX_BUNDLE TRUE
|
|
MACOSX_BUNDLE_BUNDLE_NAME "Yr Crystals"
|
|
MACOSX_BUNDLE_GUI_IDENTIFIER "com.yrcrystals.app"
|
|
MACOSX_BUNDLE_ICON_FILE "app_icon.icns"
|
|
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/platform/macos/Info.plist.in"
|
|
RESOURCE "${MACOS_ICON}"
|
|
)
|
|
|
|
# --- macOS Code Signing ---
|
|
# Qt 6.9+ on macOS Sequoia requires audio entitlements for CoreAudio access.
|
|
# Set MACOS_SIGNING_IDENTITY to your identity (e.g. "Apple Development: Name (ID)")
|
|
# or leave empty to use ad-hoc signing. Run `security find-identity -v -p codesigning`
|
|
# to list available identities.
|
|
set(MACOS_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/platform/macos/YrCrystals.entitlements")
|
|
if(NOT DEFINED MACOS_SIGNING_IDENTITY)
|
|
set(MACOS_SIGNING_IDENTITY "-")
|
|
endif()
|
|
add_custom_command(TARGET YrCrystals POST_BUILD
|
|
COMMAND codesign --force --sign "${MACOS_SIGNING_IDENTITY}"
|
|
--entitlements "${MACOS_ENTITLEMENTS}"
|
|
--deep "$<TARGET_BUNDLE_DIR:YrCrystals>"
|
|
COMMENT "Signing YrCrystals.app with audio entitlements..."
|
|
VERBATIM
|
|
)
|
|
elseif(WIN32)
|
|
set_target_properties(YrCrystals PROPERTIES
|
|
WIN32_EXECUTABLE TRUE
|
|
)
|
|
endif()
|
|
|
|
qt_finalize_executable(YrCrystals) |