Some checks failed
akbasic CI Build / cmake_build (push) Successful in 2m52s
akbasic CI Build / sanitizers (push) Successful in 3m9s
akbasic CI Build / coverage (push) Failing after 3m12s
akbasic CI Build / akgl_build (push) Failing after 20s
akbasic CI Build / mutation_test (push) Successful in 7m27s
That file wrapped strtoll and strtod because libakstdlib's aksl_ato* family
could not report a conversion failure at all -- atoi("not a number") returned
success with 0, turning four diagnosable errors into wrong answers. Its own note
said what to do when that changed: "When it grows it, delete src/convert.c and
switch the call sites over." 0.2.0 grew it, so it is gone.
Six call sites go straight to the library now: both literal constructors in
src/grammar.c, the line number in src/scanner.c, FunctionVAL in
src/runtime_functions.c, INPUT in src/runtime_commands.c, and GSHAPE's handle in
src/runtime_graphics.c. aksl_strtoll(str, NULL, base, &dest) rather than
aksl_atoll wherever a base is involved, because the ato* forms are base 10 and
grammar.c picks base 8 or 16 off the lexeme's prefix; the NULL endptr is what
makes trailing junk an error rather than a stopping point.
The raised status changed from AKBASIC_ERR_VALUE to AKERR_VALUE, and the message
with it -- VAL("garbage") now says `no digits in "garbage"`. Section 1.8 makes
message text part of the acceptance contract, so that was checked against the
corpus before touching anything: no golden file contained a conversion message,
which is also why section 1.9 had been asking for one. Two exist now, so the next
change to that text has to move a golden file, and one of them pins the
reference's octal-literal defect (section 6 item 10) while it is still
deliberately reproduced.
tests/convert.c became tests/numeric_contract.c rather than being deleted with
the code. The assertions did not stop being worth making when the wrapper went
away -- they became assertions about a contract this port depends on and no
longer owns, and a regression in it would make four things quietly return zero.
Repoints the CI mutation job, which was bounded to src/convert.c and
src/symtab.c. src/symtab.c alone measures 74.1% against the gate of 65.
src/audio_tables.c was measured as a replacement second file and scored 64.7%:
that is a real gap rather than a reason to skip it, since almost every survivor
is in akbasic_audio_state_init, where nothing asserts a freshly initialised audio
state is actually zeroed -- the same gap this job's history records closing for
symtab. Recorded in TODO.md so the file can earn its place back.
One thing worth knowing before reading any score here, and now written down: the
harness's ICR operator only rewrites the constants 0 and 1, so a lookup table of
other values produces no mutants and a high score over one says nothing about
whether its entries are right. tests/audio_verbs.c now asserts all 32 ADSR
entries against the datasheet anyway, because a hand-edit typo is the real
failure mode there -- but that could not and did not move the mutation number,
and claiming otherwise would be the kind of thing this file exists to stop.
72/72 core, 73/73 with libakgl, 72/72 under ASan+UBSan, coverage 93.6% line and
97.8% function, clean under -Wall -Wextra, doxygen clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
402 lines
16 KiB
CMake
402 lines
16 KiB
CMake
cmake_minimum_required(VERSION 3.10)
|
|
# The single source of truth for the version, in the shape libakstdlib and
|
|
# libakgl both use. It flows into the library SOVERSION and nothing else spells
|
|
# a version number.
|
|
#
|
|
# 0.x on purpose: TODO.md section 12 records eleven defects carried over from the
|
|
# Go reference that are deliberately reproduced and not yet fixed, so the
|
|
# language surface is not being promised yet.
|
|
project(akbasic VERSION 0.1.0 LANGUAGES C)
|
|
|
|
# Pre-1.0 the ABI may break on a minor bump, so the soname carries MAJOR.MINOR.
|
|
# At 1.0 this becomes ${PROJECT_VERSION_MAJOR} alone.
|
|
if(PROJECT_VERSION_MAJOR EQUAL 0)
|
|
set(AKBASIC_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
|
else()
|
|
set(AKBASIC_SOVERSION "${PROJECT_VERSION_MAJOR}")
|
|
endif()
|
|
|
|
include(CTest)
|
|
include(GNUInstallDirs)
|
|
|
|
option(AKBASIC_WITH_AKGL "Build the libakgl-backed text sink and link SDL3" OFF)
|
|
option(AKBASIC_BUILD_EXAMPLES "Build the embedding example in examples/" ON)
|
|
option(AKBASIC_COVERAGE "Instrument the build with gcov coverage counters" OFF)
|
|
option(AKBASIC_SANITIZE "Build with ASan + UBSan" OFF)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Dependencies
|
|
#
|
|
# libakgl vendors its own copies of libakerror and libakstdlib and guards every
|
|
# dependency with if(NOT TARGET ...), so akerror::akerror and akstdlib::akstdlib
|
|
# must exist *before* add_subdirectory(deps/libakgl) or the targets are declared
|
|
# twice.
|
|
#
|
|
# All three dependencies register their CTest tests unconditionally. Pulled in
|
|
# EXCLUDE_FROM_ALL their test binaries are never built, so each one would land in
|
|
# our suite as "Not Run" and fail. CMake has no way to un-register a test and
|
|
# set_tests_properties cannot reach across directory scopes, so add_test() and
|
|
# set_tests_properties() are shadowed for the duration of the add_subdirectory()
|
|
# calls. Note libakstdlib carries the same shadow but only arms it when *it* is
|
|
# top-level, so it does nothing for us -- this one has to wrap all three.
|
|
#
|
|
# libakerror additionally namespaces its `mutation` target when embedded but not
|
|
# its `coverage` target (deps/libakerror/CMakeLists.txt:194 vs :172), so a
|
|
# coverage build collides on the `coverage` target and fails to configure at all.
|
|
# Rename the dependency's on the way past. Remove this once libakerror applies
|
|
# the same CMAKE_SOURCE_DIR test to `coverage` that it already applies to
|
|
# `mutation` -- filed in deps/libakstdlib/TODO.md section 2.3.
|
|
# ---------------------------------------------------------------------------
|
|
set(AKBASIC_SUPPRESS_ADD_TEST TRUE)
|
|
|
|
function(add_test)
|
|
if(NOT AKBASIC_SUPPRESS_ADD_TEST)
|
|
_add_test(${ARGV})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(set_tests_properties)
|
|
if(NOT AKBASIC_SUPPRESS_ADD_TEST)
|
|
_set_tests_properties(${ARGV})
|
|
endif()
|
|
endfunction()
|
|
|
|
function(add_custom_target _name)
|
|
if(AKBASIC_SUPPRESS_ADD_TEST AND _name STREQUAL "coverage")
|
|
_add_custom_target(akerror_coverage ${ARGN})
|
|
else()
|
|
_add_custom_target(${ARGV})
|
|
endif()
|
|
endfunction()
|
|
|
|
add_subdirectory(deps/libakerror EXCLUDE_FROM_ALL)
|
|
add_subdirectory(deps/libakstdlib EXCLUDE_FROM_ALL)
|
|
if(AKBASIC_WITH_AKGL)
|
|
# libakgl builds its own vendored SDL, SDL_image, SDL_mixer, SDL_ttf and
|
|
# jansson only when it is *top-level*. Embedded, it goes down a find_package
|
|
# path instead and requires all five installed on the system -- which is a
|
|
# surprise, because they are sitting right there in deps/libakgl/deps as
|
|
# submodules. Every one of those lookups is guarded with
|
|
# if(NOT TARGET ...), so declaring the targets here first satisfies them
|
|
# and the vendored copies get used after all. Same trick, and the same
|
|
# ordering requirement, that akerror::akerror and akstdlib::akstdlib already
|
|
# need above.
|
|
#
|
|
# Filed upstream: an embedded libakgl should add its own vendored
|
|
# dependencies rather than requiring them installed.
|
|
set(JANSSON_WITHOUT_TESTS ON CACHE BOOL "Do not build vendored Jansson tests" FORCE)
|
|
set(JANSSON_EXAMPLES OFF CACHE BOOL "Do not build vendored Jansson examples" FORCE)
|
|
set(JANSSON_BUILD_DOCS OFF CACHE BOOL "Do not build vendored Jansson docs" FORCE)
|
|
add_subdirectory(deps/libakgl/deps/jansson EXCLUDE_FROM_ALL)
|
|
add_subdirectory(deps/libakgl/deps/SDL EXCLUDE_FROM_ALL)
|
|
add_subdirectory(deps/libakgl/deps/SDL_image EXCLUDE_FROM_ALL)
|
|
add_subdirectory(deps/libakgl/deps/SDL_mixer EXCLUDE_FROM_ALL)
|
|
add_subdirectory(deps/libakgl/deps/SDL_ttf EXCLUDE_FROM_ALL)
|
|
add_subdirectory(deps/libakgl EXCLUDE_FROM_ALL)
|
|
endif()
|
|
|
|
set(AKBASIC_SUPPRESS_ADD_TEST FALSE)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Instrumentation, applied per target so it never leaks into an exported
|
|
# interface.
|
|
# ---------------------------------------------------------------------------
|
|
function(akbasic_instrument _target)
|
|
if(AKBASIC_COVERAGE)
|
|
target_compile_options(${_target} PRIVATE --coverage -O0 -g)
|
|
target_link_options(${_target} PRIVATE --coverage)
|
|
endif()
|
|
if(AKBASIC_SANITIZE)
|
|
target_compile_options(${_target} PRIVATE -fsanitize=address,undefined -fno-omit-frame-pointer -g)
|
|
target_link_options(${_target} PRIVATE -fsanitize=address,undefined)
|
|
endif()
|
|
endfunction()
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# The interpreter library. Everything here must be free of SDL, free of any
|
|
# process-terminating call, and buildable with no libakgl present.
|
|
# ---------------------------------------------------------------------------
|
|
set(AKBASIC_SOURCES
|
|
src/audio_tables.c
|
|
src/environment.c
|
|
src/error.c
|
|
src/grammar.c
|
|
src/graphics_tables.c
|
|
src/parser.c
|
|
src/parser_commands.c
|
|
src/play.c
|
|
src/runtime.c
|
|
src/runtime_audio.c
|
|
src/runtime_commands.c
|
|
src/runtime_functions.c
|
|
src/runtime_graphics.c
|
|
src/runtime_input.c
|
|
src/scanner.c
|
|
src/sink_stdio.c
|
|
src/symtab.c
|
|
src/value.c
|
|
src/variable.c
|
|
src/verbs.c
|
|
)
|
|
|
|
add_library(akbasic ${AKBASIC_SOURCES})
|
|
add_library(akbasic::akbasic ALIAS akbasic)
|
|
|
|
target_include_directories(akbasic PUBLIC
|
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/>
|
|
)
|
|
|
|
target_compile_options(akbasic PRIVATE -Wall -Wextra)
|
|
target_link_libraries(akbasic PUBLIC akstdlib::akstdlib akerror::akerror)
|
|
target_link_libraries(akbasic PRIVATE m)
|
|
|
|
set_target_properties(akbasic PROPERTIES
|
|
VERSION ${PROJECT_VERSION}
|
|
SOVERSION ${AKBASIC_SOVERSION}
|
|
)
|
|
|
|
akbasic_instrument(akbasic)
|
|
|
|
# The libakgl-backed text sink, kept in its own target so the core library and
|
|
# the whole golden suite build with no SDL present.
|
|
if(AKBASIC_WITH_AKGL)
|
|
add_library(akbasic_akgl
|
|
src/audio_akgl.c
|
|
src/graphics_akgl.c
|
|
src/input_akgl.c
|
|
src/sink_akgl.c
|
|
)
|
|
target_compile_options(akbasic_akgl PRIVATE -Wall -Wextra)
|
|
target_link_libraries(akbasic_akgl PUBLIC akbasic akgl)
|
|
akbasic_instrument(akbasic_akgl)
|
|
endif()
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# The standalone driver. This is the only place FINISH_NORETURN may appear.
|
|
# ---------------------------------------------------------------------------
|
|
add_executable(basic src/main.c)
|
|
target_compile_options(basic PRIVATE -Wall -Wextra)
|
|
target_link_libraries(basic PRIVATE akbasic)
|
|
if(AKBASIC_WITH_AKGL)
|
|
target_link_libraries(basic PRIVATE akbasic_akgl)
|
|
target_compile_definitions(basic PRIVATE AKBASIC_HAVE_AKGL=1)
|
|
endif()
|
|
akbasic_instrument(basic)
|
|
|
|
# The embedding example. It is built by default and registered as a test so the
|
|
# code README.md quotes cannot rot: a signature change breaks the build.
|
|
if(AKBASIC_BUILD_EXAMPLES)
|
|
foreach(_example IN ITEMS embed hostvars)
|
|
add_executable(akbasic_example_${_example} examples/${_example}.c)
|
|
target_compile_options(akbasic_example_${_example} PRIVATE -Wall -Wextra)
|
|
target_link_libraries(akbasic_example_${_example} PRIVATE akbasic)
|
|
akbasic_instrument(akbasic_example_${_example})
|
|
_add_test(NAME example_${_example} COMMAND akbasic_example_${_example})
|
|
endforeach()
|
|
endif()
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Tests.
|
|
#
|
|
# Three lists, and two of them invert the meaning of "Passed", exactly as
|
|
# libakstdlib does:
|
|
# AKBASIC_TESTS must exit 0
|
|
# AKBASIC_WILL_FAIL_TESTS abort by design
|
|
# AKBASIC_KNOWN_FAILING_TESTS assert the *correct* contract for a defect
|
|
# recorded in TODO.md and are expected to fail.
|
|
# When one starts passing CTest reports
|
|
# "unexpectedly passed" -- that is the cue to move
|
|
# it into AKBASIC_TESTS along with the fix.
|
|
#
|
|
# Test executables are named akbasic_test_<name>, never test_<name>: a
|
|
# dependency's targets are created even under EXCLUDE_FROM_ALL, and libakstdlib
|
|
# already ships test_version. The CTest name stays bare, so `ctest -R value`
|
|
# still selects it.
|
|
# ---------------------------------------------------------------------------
|
|
set(AKBASIC_TESTS
|
|
audio_verbs
|
|
devices
|
|
environment_scope
|
|
error_codes
|
|
grammar_leaves
|
|
graphics_verbs
|
|
input_verbs
|
|
numeric_contract
|
|
parser_commands
|
|
parser_expressions
|
|
runtime_evaluate
|
|
runtime_verbs
|
|
scanner_tokens
|
|
sink_stdio
|
|
symtab
|
|
value_arithmetic
|
|
value_bitwise
|
|
value_compare
|
|
variable_subscript
|
|
verbs_table
|
|
version_check
|
|
)
|
|
|
|
set(AKBASIC_WILL_FAIL_TESTS
|
|
)
|
|
|
|
set(AKBASIC_KNOWN_FAILING_TESTS
|
|
known_reference_defects
|
|
)
|
|
|
|
foreach(_test IN LISTS AKBASIC_TESTS AKBASIC_WILL_FAIL_TESTS AKBASIC_KNOWN_FAILING_TESTS)
|
|
add_executable(akbasic_test_${_test} tests/${_test}.c)
|
|
target_compile_options(akbasic_test_${_test} PRIVATE -Wall -Wextra)
|
|
target_link_libraries(akbasic_test_${_test} PRIVATE akbasic)
|
|
target_include_directories(akbasic_test_${_test} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/tests")
|
|
akbasic_instrument(akbasic_test_${_test})
|
|
_add_test(NAME ${_test} COMMAND akbasic_test_${_test})
|
|
endforeach()
|
|
|
|
# The akgl-backed suite. Its own list because it is the only test here that links
|
|
# SDL, and because it can only exist when AKBASIC_WITH_AKGL is on -- the whole
|
|
# point of the backend records is that everything else builds without it.
|
|
#
|
|
# It runs under the dummy video and audio drivers with a software renderer,
|
|
# following deps/libakgl/tests/draw.c: a 128x128 target read back with
|
|
# SDL_RenderReadPixels, so it needs no display and no offscreen harness.
|
|
if(AKBASIC_WITH_AKGL)
|
|
add_executable(akbasic_test_akgl_backends tests/akgl_backends.c)
|
|
target_compile_options(akbasic_test_akgl_backends PRIVATE -Wall -Wextra)
|
|
target_link_libraries(akbasic_test_akgl_backends PRIVATE akbasic_akgl)
|
|
target_include_directories(akbasic_test_akgl_backends PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/tests")
|
|
# libakgl's monospaced fixture font, borrowed rather than copied: a second copy
|
|
# of a 10 KB binary is a second thing to keep in step for no benefit.
|
|
target_compile_definitions(akbasic_test_akgl_backends PRIVATE
|
|
AKBASIC_TEST_FONT="${CMAKE_CURRENT_SOURCE_DIR}/deps/libakgl/tests/assets/akgl_test_mono.ttf")
|
|
akbasic_instrument(akbasic_test_akgl_backends)
|
|
_add_test(NAME akgl_backends COMMAND akbasic_test_akgl_backends)
|
|
_set_tests_properties(akgl_backends PROPERTIES
|
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests"
|
|
TIMEOUT 60
|
|
ENVIRONMENT "SDL_VIDEODRIVER=dummy;SDL_AUDIODRIVER=dummy")
|
|
endif()
|
|
|
|
if(AKBASIC_TESTS OR AKBASIC_WILL_FAIL_TESTS OR AKBASIC_KNOWN_FAILING_TESTS)
|
|
_set_tests_properties(
|
|
${AKBASIC_TESTS} ${AKBASIC_WILL_FAIL_TESTS} ${AKBASIC_KNOWN_FAILING_TESTS}
|
|
PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests" TIMEOUT 30
|
|
)
|
|
endif()
|
|
|
|
if(AKBASIC_WILL_FAIL_TESTS OR AKBASIC_KNOWN_FAILING_TESTS)
|
|
_set_tests_properties(
|
|
${AKBASIC_WILL_FAIL_TESTS} ${AKBASIC_KNOWN_FAILING_TESTS}
|
|
PROPERTIES WILL_FAIL TRUE
|
|
)
|
|
endif()
|
|
|
|
# The golden-file suite. It drives deps/basicinterpret/tests/**/*.bas in place --
|
|
# the corpus is a submodule and copying it guarantees drift -- and byte-compares
|
|
# stdout against the sibling .txt. One CTest case per .bas so a failure names the
|
|
# file.
|
|
file(GLOB_RECURSE AKBASIC_GOLDEN_CASES
|
|
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/deps/basicinterpret"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/deps/basicinterpret/tests/*.bas"
|
|
)
|
|
|
|
foreach(_case IN LISTS AKBASIC_GOLDEN_CASES)
|
|
string(REGEX REPLACE "^tests/" "" _name "${_case}")
|
|
string(REGEX REPLACE "\\.bas$" "" _name "${_name}")
|
|
string(REPLACE "/" "_" _name "${_name}")
|
|
_add_test(
|
|
NAME golden_${_name}
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DBASIC=$<TARGET_FILE:basic>
|
|
-DCASE=${CMAKE_CURRENT_SOURCE_DIR}/deps/basicinterpret/${_case}
|
|
-P ${CMAKE_CURRENT_SOURCE_DIR}/tests/golden.cmake
|
|
)
|
|
endforeach()
|
|
|
|
if(AKBASIC_GOLDEN_CASES)
|
|
set(AKBASIC_GOLDEN_NAMES)
|
|
foreach(_case IN LISTS AKBASIC_GOLDEN_CASES)
|
|
string(REGEX REPLACE "^tests/" "" _name "${_case}")
|
|
string(REGEX REPLACE "\\.bas$" "" _name "${_name}")
|
|
string(REPLACE "/" "_" _name "${_name}")
|
|
list(APPEND AKBASIC_GOLDEN_NAMES golden_${_name})
|
|
endforeach()
|
|
_set_tests_properties(${AKBASIC_GOLDEN_NAMES} PROPERTIES TIMEOUT 30)
|
|
endif()
|
|
|
|
# The local golden corpus, for verbs the reference never implemented.
|
|
#
|
|
# It has to be separate: the corpus above is a submodule and nothing in this
|
|
# repository may add files to it, but goal 2's new verbs still need the .bas/.txt
|
|
# half of their coverage. Registered under local_ so a failure says at a glance
|
|
# which corpus it came from.
|
|
#
|
|
# Note what this can and cannot cover. The graphics and sound verbs draw and play
|
|
# rather than print, so what a golden file sees of them is their *refusals* and
|
|
# whatever a program can PRINT about the state they changed. The behaviour that
|
|
# reaches a device is asserted against tests/mockdevice.h instead.
|
|
file(GLOB_RECURSE AKBASIC_LOCAL_CASES
|
|
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/tests"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/language/*.bas"
|
|
)
|
|
|
|
set(AKBASIC_LOCAL_NAMES)
|
|
foreach(_case IN LISTS AKBASIC_LOCAL_CASES)
|
|
string(REGEX REPLACE "^language/" "" _name "${_case}")
|
|
string(REGEX REPLACE "\\.bas$" "" _name "${_name}")
|
|
string(REPLACE "/" "_" _name "${_name}")
|
|
_add_test(
|
|
NAME local_${_name}
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DBASIC=$<TARGET_FILE:basic>
|
|
-DCASE=${CMAKE_CURRENT_SOURCE_DIR}/tests/${_case}
|
|
-P ${CMAKE_CURRENT_SOURCE_DIR}/tests/golden.cmake
|
|
)
|
|
list(APPEND AKBASIC_LOCAL_NAMES local_${_name})
|
|
endforeach()
|
|
|
|
if(AKBASIC_LOCAL_NAMES)
|
|
_set_tests_properties(${AKBASIC_LOCAL_NAMES} PROPERTIES TIMEOUT 30)
|
|
endif()
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Mutation testing.
|
|
#
|
|
# Coverage says which lines ran; mutation testing says whether anything would
|
|
# have noticed if they were wrong. That distinction matters more here than in an
|
|
# ordinary C library: the akerror control-flow macros expand at their call sites,
|
|
# so gcov attributes ATTEMPT/CATCH/PASS to the caller and cannot really see them.
|
|
# Mutation testing is the only thing that checks them at all.
|
|
#
|
|
# This target runs the whole akbasic-owned src/ tree and is slow -- upwards of an
|
|
# hour. CI runs a narrower, faster set with a --threshold gate; see
|
|
# .gitea/workflows/ci.yaml.
|
|
#
|
|
# Namespaced when embedded in another project, for the same reason the coverage
|
|
# targets in the dependencies are: a sibling may well ship a `mutation` target.
|
|
find_package(Python3 COMPONENTS Interpreter)
|
|
if(Python3_FOUND)
|
|
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
|
set(AKBASIC_MUTATION_TARGET mutation)
|
|
else()
|
|
set(AKBASIC_MUTATION_TARGET akbasic_mutation)
|
|
endif()
|
|
add_custom_target(${AKBASIC_MUTATION_TARGET}
|
|
COMMAND ${Python3_EXECUTABLE}
|
|
${CMAKE_CURRENT_SOURCE_DIR}/scripts/mutation_test.py
|
|
--source-root ${CMAKE_CURRENT_SOURCE_DIR}
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
USES_TERMINAL
|
|
COMMENT "Running mutation tests (breaks the library, expects tests to fail)"
|
|
)
|
|
endif()
|
|
|
|
install(TARGETS akbasic basic
|
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
|
)
|
|
install(DIRECTORY include/akbasic DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|