cmake_minimum_required(VERSION 3.10) project(fun VERSION 0.35.0 LANGUAGES C) set(CMAKE_C_STANDARD 99) 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 SQLite support option(FUN_WITH_SQLITE "Enable SQLite (sqlite3) support" OFF) set(SQLITE3_INCLUDE_DIRS "") set(SQLITE3_LINK_LIBS "") if(FUN_WITH_SQLITE) message(STATUS "Building with SQLite support") add_definitions(-DFUN_WITH_SQLITE) find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(SQLITE3 QUIET sqlite3) endif() if(SQLITE3_FOUND) list(APPEND SQLITE3_INCLUDE_DIRS ${SQLITE3_INCLUDE_DIRS} ${SQLITE3_INCLUDE_DIRS}) list(APPEND SQLITE3_LINK_LIBS ${SQLITE3_LINK_LIBS} ${SQLITE3_LIBRARIES}) include_directories(${SQLITE3_INCLUDE_DIRS}) else() find_library(SQLITE3_LIB sqlite3) if(SQLITE3_LIB) list(APPEND SQLITE3_LINK_LIBS ${SQLITE3_LIB}) else() message(FATAL_ERROR "sqlite3 not found. Install sqlite3 (dev headers) or disable FUN_WITH_SQLITE.") endif() endif() 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() # Optional JSON (json-c) support option(FUN_WITH_JSON "Enable JSON (json-c) support" OFF) set(JSONC_INCLUDE_DIRS "") set(JSONC_LINK_LIBS "") if(FUN_WITH_JSON) message(STATUS "Building with JSON (json-c) support") add_definitions(-DFUN_WITH_JSON) find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(JSONC QUIET json-c) endif() if(JSONC_FOUND) list(APPEND JSONC_INCLUDE_DIRS ${JSONC_INCLUDE_DIRS} ${JSONC_INCLUDE_DIRS}) list(APPEND JSONC_LINK_LIBS ${JSONC_LINK_LIBS} ${JSONC_LIBRARIES}) include_directories(${JSONC_INCLUDE_DIRS}) else() # Fallback: try plain -ljson-c list(APPEND JSONC_LINK_LIBS json-c) endif() endif() # Optional INI (iniparser 4.2.6) support option(FUN_WITH_INI "Enable INI (iniparser) support" OFF) set(INIPARSER_INCLUDE_DIRS "") set(INIPARSER_LINK_LIBS "") if(FUN_WITH_INI) message(STATUS "Building with INI (iniparser) support") add_definitions(-DFUN_WITH_INI) find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(INIPARSER QUIET iniparser) endif() if(INIPARSER_FOUND) list(APPEND INIPARSER_INCLUDE_DIRS ${INIPARSER_INCLUDE_DIRS} ${INIPARSER_INCLUDE_DIRS}) list(APPEND INIPARSER_LINK_LIBS ${INIPARSER_LINK_LIBS} ${INIPARSER_LIBRARIES}) else() # Fallback: try to locate headers and library manually find_path(INIPARSER_INCLUDE_DIR iniparser.h) find_library(INIPARSER_LIB NAMES iniparser) if(INIPARSER_INCLUDE_DIR) list(APPEND INIPARSER_INCLUDE_DIRS ${INIPARSER_INCLUDE_DIR}) endif() if(INIPARSER_LIB) list(APPEND INIPARSER_LINK_LIBS ${INIPARSER_LIB}) endif() if(NOT INIPARSER_INCLUDE_DIRS OR NOT INIPARSER_LINK_LIBS) message(FATAL_ERROR "iniparser not found. Install iniparser (>=4.2.6) or disable FUN_WITH_INI.") endif() endif() endif() # Optional XML (libxml2) support option(FUN_WITH_XML2 "Enable XML (libxml2) support" OFF) set(LIBXML2_INCLUDE_DIRS "") set(LIBXML2_LINK_LIBS "") if(FUN_WITH_XML2) message(STATUS "Building with XML (libxml2) support") add_definitions(-DFUN_WITH_XML2) find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(LIBXML2 QUIET libxml-2.0) endif() if(LIBXML2_FOUND) list(APPEND LIBXML2_INCLUDE_DIRS ${LIBXML2_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIRS}) list(APPEND LIBXML2_LINK_LIBS ${LIBXML2_LINK_LIBS} ${LIBXML2_LIBRARIES}) include_directories(${LIBXML2_INCLUDE_DIRS}) else() find_library(LIBXML2_LIB NAMES xml2 libxml2) if(LIBXML2_LIB) list(APPEND LIBXML2_LINK_LIBS ${LIBXML2_LIB}) # Common system include location for libxml2 headers if(EXISTS "/usr/include/libxml2") list(APPEND LIBXML2_INCLUDE_DIRS "/usr/include/libxml2") include_directories(${LIBXML2_INCLUDE_DIRS}) endif() else() message(FATAL_ERROR "libxml2 not found. Install libxml2 (dev headers) or disable FUN_WITH_XML2.") endif() endif() # As a robust fallback, add standard system include path for libxml2 if present if(EXISTS "/usr/include/libxml2") include_directories("/usr/include/libxml2") endif() endif() # Optional libsql support (independent from SQLite) option(FUN_WITH_LIBSQL "Enable libsql (Turso) client support" OFF) set(LIBSQL_INCLUDE_DIRS "") set(LIBSQL_LINK_LIBS "") if(FUN_WITH_LIBSQL) message(STATUS "Building with libsql support") add_definitions(-DFUN_WITH_LIBSQL) # Try pkg-config for libsql first; some systems expose libsql-client find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(LIBSQL QUIET libsql) if(NOT LIBSQL_FOUND) pkg_check_modules(LIBSQL_CLIENT QUIET libsql-client) if(LIBSQL_CLIENT_FOUND) set(LIBSQL_FOUND TRUE) set(LIBSQL_INCLUDE_DIRS ${LIBSQL_CLIENT_INCLUDE_DIRS}) set(LIBSQL_LINK_LIBS ${LIBSQL_CLIENT_LIBRARIES}) endif() endif() endif() if(LIBSQL_FOUND) include_directories(${LIBSQL_INCLUDE_DIRS}) else() # Fallback: many libsql deployments provide a sqlite3-compatible client lib # so try linking against sqlite3 as a compatibility layer. find_library(LIBSQL_LIB sqlite3) if(LIBSQL_LIB) list(APPEND LIBSQL_LINK_LIBS ${LIBSQL_LIB}) else() message(FATAL_ERROR "libsql not found. Install libsql (or compatible sqlite3 client) or disable FUN_WITH_LIBSQL.") endif() endif() endif() # Optional PCRE2 support option(FUN_WITH_PCRE2 "Enable PCRE2 (Perl Compatible Regular Expressions) support" OFF) set(PCRE2_INCLUDE_DIRS "") set(PCRE2_LINK_LIBS "") if(FUN_WITH_PCRE2) message(STATUS "Building with PCRE2 support") add_definitions(-DFUN_WITH_PCRE2) # Try pkg-config first find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(PCRE2 QUIET libpcre2-8) endif() if(PCRE2_FOUND) list(APPEND PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIRS} ${PCRE2_INCLUDE_DIRS}) list(APPEND PCRE2_LINK_LIBS ${PCRE2_LINK_LIBS} ${PCRE2_LIBRARIES}) include_directories(${PCRE2_INCLUDE_DIRS}) else() # Fallback: common defaults list(APPEND PCRE2_LINK_LIBS pcre2-8) endif() endif() # Optional CURL (libcurl) support option(FUN_WITH_CURL "Enable libcurl HTTP client support" OFF) set(CURL_INCLUDE_DIRS "") set(CURL_LINK_LIBS "") if(FUN_WITH_CURL) message(STATUS "Building with libcurl support") add_definitions(-DFUN_WITH_CURL) find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(LIBCURL QUIET libcurl) endif() if(LIBCURL_FOUND) list(APPEND CURL_INCLUDE_DIRS ${LIBCURL_INCLUDE_DIRS}) list(APPEND CURL_LINK_LIBS ${LIBCURL_LIBRARIES}) include_directories(${CURL_INCLUDE_DIRS}) else() list(APPEND CURL_LINK_LIBS curl) 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() # json-c include and link (if enabled) if(JSONC_INCLUDE_DIRS) target_include_directories(fun_core PRIVATE ${JSONC_INCLUDE_DIRS}) endif() if(JSONC_LINK_LIBS) target_link_libraries(fun_core PUBLIC ${JSONC_LINK_LIBS}) endif() # pcre2 include and link (if enabled) if(PCRE2_INCLUDE_DIRS) target_include_directories(fun_core PRIVATE ${PCRE2_INCLUDE_DIRS}) endif() if(PCRE2_LINK_LIBS) target_link_libraries(fun_core PUBLIC ${PCRE2_LINK_LIBS}) endif() # libcurl include and link (if enabled) if(CURL_INCLUDE_DIRS) target_include_directories(fun_core PRIVATE ${CURL_INCLUDE_DIRS}) endif() if(CURL_LINK_LIBS) target_link_libraries(fun_core PUBLIC ${CURL_LINK_LIBS}) endif() # sqlite3 include and link (if enabled) if(SQLITE3_INCLUDE_DIRS) target_include_directories(fun_core PRIVATE ${SQLITE3_INCLUDE_DIRS}) endif() if(SQLITE3_LINK_LIBS) target_link_libraries(fun_core PUBLIC ${SQLITE3_LINK_LIBS}) endif() # iniparser include and link (if enabled) if(INIPARSER_INCLUDE_DIRS) target_include_directories(fun_core PRIVATE ${INIPARSER_INCLUDE_DIRS}) endif() if(INIPARSER_LINK_LIBS) target_link_libraries(fun_core PUBLIC ${INIPARSER_LINK_LIBS}) endif() # libsql include and link (if enabled) if(LIBSQL_INCLUDE_DIRS) target_include_directories(fun_core PRIVATE ${LIBSQL_INCLUDE_DIRS}) endif() if(LIBSQL_LINK_LIBS) target_link_libraries(fun_core PUBLIC ${LIBSQL_LINK_LIBS}) endif() # libxml2 include and link (if enabled) if(LIBXML2_INCLUDE_DIRS) target_include_directories(fun_core PRIVATE ${LIBXML2_INCLUDE_DIRS}) endif() if(LIBXML2_LINK_LIBS) target_link_libraries(fun_core PUBLIC ${LIBXML2_LINK_LIBS}) endif() if(FUN_WITH_XML2) if(EXISTS "/usr/include/libxml2") target_include_directories(fun_core PRIVATE "/usr/include/libxml2") endif() endif() # Link threads if available on UNIX if(Threads_FOUND) target_link_libraries(fun_core PUBLIC Threads::Threads) endif() # Interpreter /usr/bin/fun option(FUN_WITH_REPL "Enable interactive REPL in the fun CLI" OFF) add_executable(fun src/fun.c ) # Provide version string to the CLI target_compile_definitions(fun PRIVATE FUN_VERSION=\"${PROJECT_VERSION}\") if(FUN_WITH_REPL) # Enable REPL compilation path and add the REPL source target_compile_definitions(fun PRIVATE FUN_WITH_REPL=1) target_sources(fun PRIVATE src/repl.c) endif() 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") if(FUN_WITH_REPL) add_custom_target(repl COMMAND $ DEPENDS fun USES_TERMINAL COMMENT "Run Fun REPL" ) endif() 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)" ) # Robust uninstall support as a function (uses install_manifest*.txt) function(fun_add_uninstall_target) set(_FUN_UNINSTALL_SCRIPT "${CMAKE_BINARY_DIR}/cmake_uninstall.cmake") # Generate the cmake_uninstall.cmake script at configure time file(WRITE "${_FUN_UNINSTALL_SCRIPT}" "set(_candidates \"\") # Prefer explicit MANIFEST if provided if(DEFINED MANIFEST AND NOT MANIFEST STREQUAL \"\") list(APPEND _candidates \"\${MANIFEST}\") endif() # Common locations (out-of-source and legacy in-source builds) list(APPEND _candidates \"\${CMAKE_BINARY_DIR}/install_manifest.txt\" \"\${CMAKE_SOURCE_DIR}/install_manifest.txt\" \"\${CMAKE_BINARY_DIR}/install_manifest_Debug.txt\" \"\${CMAKE_BINARY_DIR}/install_manifest_Release.txt\" \"\${CMAKE_BINARY_DIR}/install_manifest_RelWithDebInfo.txt\" \"\${CMAKE_BINARY_DIR}/install_manifest_MinSizeRel.txt\" \"\${CMAKE_SOURCE_DIR}/install_manifest_Debug.txt\" \"\${CMAKE_SOURCE_DIR}/install_manifest_Release.txt\" \"\${CMAKE_SOURCE_DIR}/install_manifest_RelWithDebInfo.txt\" \"\${CMAKE_SOURCE_DIR}/install_manifest_MinSizeRel.txt\" ) set(_manifest_file \"\") foreach(_cand IN LISTS _candidates) if(EXISTS \"\${_cand}\") set(_manifest_file \"\${_cand}\") break() endif() endforeach() if(NOT _manifest_file) message(FATAL_ERROR \"Cannot find install manifest. Tried: \${_candidates}. If you installed from a different build directory, run uninstall from that build directory (where install_manifest*.txt resides).\") endif() file(READ \"\${_manifest_file}\" _manifest) string(REPLACE \"\\n\" \";\" _files \"\${_manifest}\") set(_removed 0) set(_dirs \"\") foreach(_file IN LISTS _files) if(_file STREQUAL \"\") continue() endif() if(EXISTS \"\${_file}\" OR IS_SYMLINK \"\${_file}\") message(STATUS \"Uninstalling: \${_file}\") file(REMOVE \"\${_file}\") # If the file still exists after attempting to remove it, fail with an explicit error if(EXISTS \"\${_file}\" OR IS_SYMLINK \"\${_file}\") message(FATAL_ERROR \"Failed to remove: \${_file}. Try running the uninstall target with sudo if it is a system install.\") endif() # Track the containing directory for potential cleanup get_filename_component(_dir \"\${_file}\" DIRECTORY) list(APPEND _dirs \"\${_dir}\") math(EXPR _removed \"\${_removed}+1\") else() message(STATUS \"Skipping (not found): \${_file}\") endif() endforeach() # Remove empty directories that contained installed files (and their parents under safe roots) # Safe roots we are allowed to prune if they become empty: set(_safe_roots \"/usr/share/fun\" \"/usr/share/doc/fun\") # Expand to include parent directories up to the safe roots set(_all_dirs \"\") foreach(_d IN LISTS _dirs) set(_p \"\${_d}\") while(NOT \"\${_p}\" STREQUAL \"\" AND NOT \"\${_p}\" STREQUAL \"/\") list(APPEND _all_dirs \"\${_p}\") get_filename_component(_p \"\${_p}\" DIRECTORY) # Stop collecting parents once we reach a safe root or the filesystem root list(FIND _safe_roots \"\${_p}\" _root_idx) if(_root_idx GREATER -1) list(APPEND _all_dirs \"\${_p}\") break() endif() endwhile() endforeach() # Deduplicate list(REMOVE_DUPLICATES _all_dirs) # Try multiple passes to remove parents that become empty after children are removed set(_removed_dirs 0) set(_pass 0) while(TRUE) set(_pass_removed 0) foreach(_dir IN LISTS _all_dirs) if(EXISTS \"\${_dir}\" AND IS_DIRECTORY \"\${_dir}\") # Only act on directories within safe roots set(_allowed FALSE) foreach(_root IN LISTS _safe_roots) if(\"\${_dir}\" MATCHES \"^\${_root}(/|\$)\") set(_allowed TRUE) break() endif() endforeach() if(NOT _allowed) # e.g. /usr/bin — do not remove continue() endif() # Remove only if empty (do not recurse unrelated content) file(GLOB _dir_contents LIST_DIRECTORIES true \"\${_dir}/*\") list(LENGTH _dir_contents _dir_len) if(_dir_len EQUAL 0) message(STATUS \"Removing empty directory: \${_dir}\") file(REMOVE_RECURSE \"\${_dir}\") if(IS_DIRECTORY \"\${_dir}\") message(FATAL_ERROR \"Failed to remove directory: \${_dir}. Try running the uninstall target with sudo if it is a system install.\") endif() math(EXPR _removed_dirs \"\${_removed_dirs}+1\") math(EXPR _pass_removed \"\${_pass_removed}+1\") endif() endif() endforeach() math(EXPR _pass \"\${_pass}+1\") if(_pass_removed EQUAL 0 OR _pass GREATER 5) break() endif() endwhile() message(STATUS \"Uninstall finished. Removed \${_removed} files and \${_removed_dirs} directories (if empty) listed in \${_manifest_file}\") ") # Expose an 'uninstall' build target (run with sudo if system locations were used) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -D MANIFEST="${CMAKE_BINARY_DIR}/install_manifest.txt" -D CMAKE_BINARY_DIR="${CMAKE_BINARY_DIR}" -D CMAKE_SOURCE_DIR="${CMAKE_SOURCE_DIR}" -P "${_FUN_UNINSTALL_SCRIPT}" USES_TERMINAL COMMENT "Uninstall files installed by this project (use sudo if needed)" ) endfunction() # Define the uninstall target fun_add_uninstall_target() # 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)