cmake_minimum_required(VERSION 3.16) project(salmanoff VERSION 0.01.000 LANGUAGES CXX) include(CMakeDependentOption) include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/DAPSS.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/DebugOpts.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/VerifyBoostDynamic.cmake) # Set C++ standard set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Build type if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug FORCE) endif() # Compiler flags set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic") # Mind oscillator configuration set(MIND_VOSCILLATOR_PERIOD_MS 33 CACHE STRING "Mind's virtual osc clock rate (ms)") if(NOT MIND_VOSCILLATOR_PERIOD_MS GREATER 0) message(FATAL_ERROR "MIND_VOSCILLATOR_PERIOD_MS must be a positive integer > 0") endif() math(EXPR MIND_VOSCILLATOR_FREQ_MS "1000 / ${MIND_VOSCILLATOR_PERIOD_MS}") # Device manager reattacher configuration set(MRNTT_DEVMGR_REATTACHER_PERIOD_MS 2000 CACHE STRING "Device manager reattacher period (ms)") if(NOT MRNTT_DEVMGR_REATTACHER_PERIOD_MS GREATER 0) message(FATAL_ERROR "MRNTT_DEVMGR_REATTACHER_PERIOD_MS must be a positive integer > 0") endif() # Stimulus buffer frame period configuration set(STIMBUFF_FRAME_PERIOD_MS 33 CACHE STRING "Stimulus buffer frame period (ms)") if(NOT STIMBUFF_FRAME_PERIOD_MS GREATER 0) message(FATAL_ERROR "STIMBUFF_FRAME_PERIOD_MS must be a positive integer > 0") endif() # Stimulus buffer frame retry delay configuration set(STIMBUFF_FRAME_RETRY_DELAY_MS 1 CACHE STRING "Stimulus buffer frame retry delay (ms)") if(NOT STIMBUFF_FRAME_RETRY_DELAY_MS GREATER 0) message(FATAL_ERROR "STIMBUFF_FRAME_RETRY_DELAY_MS must be a positive integer > 0") endif() # World thread configuration option(WORLD_USE_BODY_THREAD "Use body thread for world component instead of separate world thread" OFF) # Test configuration option(ENABLE_TESTS "Enable building tests" OFF) # Set the debug locks variable for config.h if(ENABLE_DEBUG_LOCKS) set(CONFIG_ENABLE_DEBUG_LOCKS TRUE) endif() # Set the debug trace callables variable for config.h if(ENABLE_DEBUG_TRACE_CALLABLES) set(CONFIG_DEBUG_TRACE_CALLABLES TRUE) # Suppress frame-address warnings when using __builtin_return_address() # with values above 0 (See callableTracer.h). set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-frame-address") endif() # Set the world thread variable for config.h if(WORLD_USE_BODY_THREAD) set(CONFIG_WORLD_USE_BODY_THREAD TRUE) endif() # Set the timeout variable for config.h set(CONFIG_DEBUG_QUTEX_DEADLOCK_TIMEOUT_MS ${DEBUG_QUTEX_DEADLOCK_TIMEOUT_MS}) # Set the stimulus buffer frame period variable for config.h set(CONFIG_STIMBUFF_FRAME_PERIOD_MS ${STIMBUFF_FRAME_PERIOD_MS}) # Set the stimulus buffer frame retry delay variable for config.h set(CONFIG_STIMBUFF_FRAME_RETRY_DELAY_MS ${STIMBUFF_FRAME_RETRY_DELAY_MS}) # Configure config.h configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/include/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/config.h @ONLY ) # Include directories include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/smocore/include ${CMAKE_CURRENT_BINARY_DIR}/include ) # Find core dependencies # We cannot use header-only Boost.Asio because we need both our dlopen()'d # libraries and the main binary to refer to the same instances of boost::asio's # metadata. If we use header-only Boost.Asio, each dlopen()'d library will have # its own copy of boost::asio's metadata, which will cause a segfault if # boost::asio objects are used inside of a dlopen()'d library. # # Honestly, I never liked this whole "header-only" idea so I'm happy to be rid # of it. # # Tell CMake we're linking against the shared library (not header-only) set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_HEADER_ONLY OFF) find_package(Boost REQUIRED COMPONENTS system log) # Define BOOST_ALL_DYN_LINK project-wide to ensure all Boost libraries use dynamic linking add_compile_definitions(BOOST_ALL_DYN_LINK) find_package(PkgConfig REQUIRED) find_package(FLEX REQUIRED) find_package(BISON REQUIRED) # Find OpenCL 1.2 or higher: try find_package first, fall back to pkg-config find_package(OpenCL 1.2 QUIET) if(OpenCL_FOUND) # Normalize find_package variables to match pkg_check_modules naming set(OPENCL_FOUND TRUE) set(OPENCL_INCLUDE_DIRS ${OpenCL_INCLUDE_DIRS}) # Handle both OpenCL_LIBRARY (singular) and OpenCL_LIBRARIES (plural) if(OpenCL_LIBRARIES) set(OPENCL_LIBRARIES ${OpenCL_LIBRARIES}) else() set(OPENCL_LIBRARIES ${OpenCL_LIBRARY}) endif() set(OPENCL_LIBRARY_DIRS "") message(STATUS "Found OpenCL using find_package") # Check if version is available and validate if(OpenCL_VERSION) if(OpenCL_VERSION VERSION_LESS "1.2") message(FATAL_ERROR "OpenCL version ${OpenCL_VERSION} found, but 1.2 or higher is required") endif() message(STATUS "OpenCL version: ${OpenCL_VERSION}") else() message(WARNING "OpenCL version could not be determined. " "Version 1.2+ is required at runtime.") endif() else() # Fall back to pkg-config pkg_check_modules(OPENCL OpenCL) if(NOT OPENCL_FOUND) message(FATAL_ERROR "Failed to find OpenCL: both find_package and " "pkg_check_modules failed. Try installing the " "'ocl-icd-opencl-dev' package (or the appropriate " "OpenCL development package for your system)." ) endif() message(STATUS "Found OpenCL using pkg-config") message(WARNING "OpenCL version could not be determined via pkg-config. " "Version 1.2+ is required at runtime.") endif() # Need dlopen() and dlsym() find_library(DL_LIBRARY NAMES dl ldl) if(NOT DL_LIBRARY) message(FATAL_ERROR "Dynamic linking library (libdl/libldl) not found") endif() # Add third-party dependencies if(ENABLE_TESTS) add_subdirectory(third_party) endif() add_subdirectory(compile) # Add core components add_subdirectory(smocore) add_subdirectory(commonLibs) add_subdirectory(stimBuffApis) add_subdirectory(wilzorApis) add_subdirectory(devices) # Main executable add_executable(salmanoff main.cpp) target_link_libraries(salmanoff Boost::system Boost::log smocore ${DL_LIBRARY} attachmentSupport ) # Verify Boost dynamic dependencies after build add_custom_command(TARGET salmanoff POST_BUILD COMMAND ${CMAKE_COMMAND} -DVERIFY_FILE="$" -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/VerifyBoostDynamic.cmake COMMENT "Verifying Boost dynamic dependencies for salmanoff" ) # Add all registered DAPSS targets as dependencies add_all_daps_dependencies() # Add tests if enabled if(ENABLE_TESTS) enable_testing() add_subdirectory(tests) endif() install(TARGETS salmanoff DESTINATION bin) # Install device configuration files (preprocessed .daps files) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/devices/ DESTINATION share/salmanoff/devices FILES_MATCHING PATTERN "*.daps" ) # Install documentation install(FILES README.md DESTINATION share/doc/salmanoff) install(FILES LICENSE DESTINATION share/doc/salmanoff) # Install example configurations if they exist if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/examples") install(DIRECTORY examples/ DESTINATION share/salmanoff/examples) endif() # Include CPack configuration include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/CPackConfig.cmake) include(CPack)