cmake_minimum_required(VERSION 3.16) project(fun VERSION 0.17.2 LANGUAGES C) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) include(GNUInstallDirs) # Defaults and options migrated from Makefile # Convenience: default path to bundled stdlib set(FUN_LIB "${CMAKE_SOURCE_DIR}/lib" CACHE PATH "Path to bundled Fun stdlib") # Optional: override default library directory for #include <...> lookups # -DDEFAULT_LIB_DIR=/custom/fun/lib (trailing slash added automatically) if(NOT DEFINED DEFAULT_LIB_DIR OR DEFAULT_LIB_DIR STREQUAL "") if(WIN32) set(_FUN_DEFAULT_LIB_DIR "C:/Users/Public/fun/lib") elseif(APPLE) set(_FUN_DEFAULT_LIB_DIR "/Library/Application Support/fun/lib") else() set(_FUN_DEFAULT_LIB_DIR "/usr/share/fun/lib") endif() set(DEFAULT_LIB_DIR "${_FUN_DEFAULT_LIB_DIR}" CACHE PATH "Default library directory for Fun stdlib (override with -DDEFAULT_LIB_DIR=...)" FORCE) else() set(DEFAULT_LIB_DIR "${DEFAULT_LIB_DIR}" CACHE PATH "Default library directory for Fun stdlib (override with -DDEFAULT_LIB_DIR=...)" FORCE) endif() # Ensure trailing slash if(NOT DEFAULT_LIB_DIR MATCHES "/$") set(DEFAULT_LIB_DIR "${DEFAULT_LIB_DIR}/") endif() # Optional PCSC support (enabled via -DFUN_WITH_PCSC=ON) option(FUN_WITH_PCSC "Enable PCSC (pcsclite) support" OFF) set(PCSC_LINK_LIBS "") set(PCSC_INCLUDE_DIRS "") if(FUN_WITH_PCSC) message(STATUS "Building with PCSC support") add_definitions(-DFUN_WITH_PCSC) if(APPLE) list(APPEND PCSC_LINK_LIBS "-framework PCSC") else() list(APPEND PCSC_INCLUDE_DIRS "/usr/include/PCSC") list(APPEND PCSC_LINK_LIBS pcsclite) endif() endif() # Debug option to enable verbose parser/VM logging option(FUN_DEBUG "Enable extra debug logging in Fun" OFF) # Threads (used by demos and optionally by the runtime) if(UNIX) find_package(Threads QUIET) endif() # Core VM/library sources add_library(fun_core src/bytecode.c src/parser.c src/value.c src/vm.c ) target_include_directories(fun_core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Apply options to core if(FUN_DEBUG) message(STATUS "FUN_DEBUG enabled: building with verbose debug logging") target_compile_definitions(fun_core PUBLIC FUN_DEBUG=1) endif() # Provide default stdlib directory to the runtime target_compile_definitions(fun_core PUBLIC DEFAULT_LIB_DIR="${DEFAULT_LIB_DIR}") # PCSC include and link (if enabled) if(PCSC_INCLUDE_DIRS) target_include_directories(fun_core PRIVATE ${PCSC_INCLUDE_DIRS}) endif() if(PCSC_LINK_LIBS) target_link_libraries(fun_core PUBLIC ${PCSC_LINK_LIBS}) endif() # Link threads if available on UNIX if(Threads_FOUND) target_link_libraries(fun_core PUBLIC Threads::Threads) endif() # Playground / interpreter (future /usr/bin/fun) add_executable(fun src/fun.c ) # Provide version string to the CLI target_compile_definitions(fun PRIVATE FUN_VERSION=\"${PROJECT_VERSION}\") target_link_libraries(fun PRIVATE fun_core) # Internal test programs add_executable(fun_test src/fun_test.c ) target_link_libraries(fun_test PRIVATE fun_core) add_executable(test_opcodes src/test_opcodes.c ) target_link_libraries(test_opcodes PRIVATE fun_core) # Convenience aggregate target (like 'build' in Makefile) add_custom_target(build DEPENDS fun fun_test test_opcodes ) # Convenience targets: repl, run, threads-demo, ops, examples set(FUN_RUN_SCRIPT "" CACHE STRING "Script to run with the 'run' target, e.g. -DFUN_RUN_SCRIPT=examples/strings_test.fun") add_custom_target(repl COMMAND $ DEPENDS fun USES_TERMINAL COMMENT "Run Fun REPL" ) add_custom_target(run COMMAND $ ${FUN_RUN_SCRIPT} DEPENDS fun USES_TERMINAL COMMENT "Run Fun with script: ${FUN_RUN_SCRIPT}" ) add_custom_target(threads-demo COMMAND ${CMAKE_COMMAND} -E echo "Running Thread class demo with FUN_LIB_DIR=${FUN_LIB}" COMMAND ${CMAKE_COMMAND} -E env FUN_LIB_DIR="${FUN_LIB}" $ ${CMAKE_SOURCE_DIR}/examples/threads_demo.fun DEPENDS fun USES_TERMINAL ) # Python for helper scripts find_package(Python3 QUIET COMPONENTS Interpreter) if(Python3_Interpreter_FOUND) set(_FUN_PY "${Python3_EXECUTABLE}") else() set(_FUN_PY "python3") endif() add_custom_target(ops COMMAND ${_FUN_PY} ${CMAKE_SOURCE_DIR}/scripts/check_op_includes.py --verbose WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} USES_TERMINAL COMMENT "Verbose opcode include check" ) add_custom_target(ops-quiet COMMAND ${_FUN_PY} ${CMAKE_SOURCE_DIR}/scripts/check_op_includes.py WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} USES_TERMINAL COMMENT "Opcode include check" ) add_custom_target(examples COMMAND ${CMAKE_COMMAND} -E env FUN_LIB_DIR="${FUN_LIB}" ${CMAKE_SOURCE_DIR}/scripts/run_examples.sh DEPENDS fun USES_TERMINAL COMMENT "Build and run all examples" ) add_custom_target(run-examples COMMAND ${CMAKE_COMMAND} -E env FUN_LIB_DIR="${FUN_LIB}" ${CMAKE_SOURCE_DIR}/scripts/run_examples.sh DEPENDS fun USES_TERMINAL COMMENT "Build and run all examples" ) # Clean and distclean add_custom_target(fun_clean COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target clean COMMENT "Clean build outputs (objects, binaries) in the build directory" ) add_custom_target(distclean COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target clean COMMAND ${CMAKE_COMMAND} -E rm -rf ${CMAKE_BINARY_DIR}/CMakeCache.txt ${CMAKE_BINARY_DIR}/CMakeFiles ${CMAKE_BINARY_DIR}/cmake_install.cmake ${CMAKE_BINARY_DIR}/install_manifest.txt ${CMAKE_BINARY_DIR}/Makefile ${CMAKE_BINARY_DIR}/*.ninja ${CMAKE_BINARY_DIR}/.ninja_* COMMENT "Remove build outputs and CMake-generated files (reconfigure needed)" ) # Install rules # Binary install(TARGETS fun RUNTIME DESTINATION /usr/bin) # Libs install(DIRECTORY lib/ DESTINATION /usr/share/fun/lib FILES_MATCHING PATTERN "*.fun") # Optionally install example scripts option(FUN_INSTALL_EXAMPLES "Install example .fun scripts" ON) if(FUN_INSTALL_EXAMPLES) install(DIRECTORY examples/ DESTINATION /usr/share/fun/examples FILES_MATCHING PATTERN "*.fun") endif() # - Docs install(FILES README.md LICENSE DESTINATION /usr/share/doc/fun)