mirror of
https://github.com/sshlien/abcmidi.git
synced 2026-05-30 20:09:29 +00:00
* Add configuration for CMake build system alongside autoconf - Add a modern CMake build system (`CMakeLists.txt`, `CMakePresets.json`) that coexists with the legacy autoconf/Makefile build - Shared source files (`midifile.c`, `parseabc.c`, `music_utils.c`, `parser2.c`) are compiled once via OBJECT libraries and linked into the 8 binaries - Three presets: `default` (Release), `debug`, `sanitize` (ASan + UBSan) - Generates `compile_commands.json` for clangd/LSP editor support - Install rules match the legacy Makefile (binaries, doc files, man pages) - Pinned to `-std=gnu89` because the codebase mixes K&R `()` and ANSI typed prototypes — in C23/gnu23 (GCC 15+ default), `()` means `(void)`, making these a hard error. Note: **the existing autoconf build is also broken with GCC 15** for the same reason ```sh cmake --preset debug cmake --build --preset debug cmake --install build/debug --prefix /usr/local Documentation - README.md: added Building section with both autoconf and CMake instructions - doc/readme.txt: added build instructions in the existing preamble - doc/CHANGES: added changelog entry Test plan - All 3 presets configure and build with GCC 15 - Smoke test: abc2midi samples/coleraine.abc produces valid MIDI through mftext - Sanitizer build (--preset sanitize) runs clean on sample files - Install layout verified: 8 binaries, 10 doc files, 8 man pages in correct paths - Build on macOS (untested, should work with AppleClang) * Implement basic testing infrastructure The CMake build includes a test suite covering all 8 programs: - **Smoke tests** verify each binary runs cleanly with `-ver`. - **Golden-file tests** run each program on a sample input and compare the (normalized) output to a checked-in reference. Binary MIDI outputs are piped through `mftext` to produce diffable text. Volatile lines (version banners, dates, temporary paths) are stripped before comparison. ```sh ctest --preset debug ctest --preset debug -L golden ctest --preset debug -L smoke ``` To regenerate the golden files after an intentional behavioural change, review the diff, then commit: ```sh cmake --build build/debug --target update-golden git diff tests/golden/ ``` * Factorize more the test CMake code
150 lines
4.2 KiB
CMake
150 lines
4.2 KiB
CMake
cmake_minimum_required(VERSION 3.14)
|
|
|
|
# Read version from the VERSION file, matching the existing convention
|
|
file(STRINGS VERSION ABCMIDI_VERSION_STRING LIMIT_COUNT 1)
|
|
|
|
project(abcmidi
|
|
VERSION 2026.02.24
|
|
DESCRIPTION "ABC music notation tools: converters between ABC, MIDI, and PostScript"
|
|
LANGUAGES C
|
|
)
|
|
|
|
# Modern CMake: export compile_commands.json for clangd/LSP
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
|
# Default to Release if not specified
|
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
|
|
set_property(CACHE CMAKE_BUILD_TYPE
|
|
PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel)
|
|
endif()
|
|
|
|
# --- Options ---
|
|
|
|
option(ABCMIDI_SANITIZERS "Enable AddressSanitizer and UndefinedBehaviorSanitizer" OFF)
|
|
|
|
# --- Compiler configuration ---
|
|
|
|
# Common compile options applied to every target via an INTERFACE library
|
|
add_library(abcmidi_common INTERFACE)
|
|
|
|
target_compile_definitions(abcmidi_common INTERFACE
|
|
ANSILIBS
|
|
)
|
|
|
|
# The codebase mixes K&R empty-parens "()" (meaning unspecified args) with
|
|
# ANSI typed prototypes. In C23/gnu23 (GCC 15+ default), "()" means "(void)",
|
|
# making these a hard error. Pin to gnu89 until the ANSI migration is complete,
|
|
# then switch to c_std_11 or later.
|
|
target_compile_options(abcmidi_common INTERFACE
|
|
$<$<C_COMPILER_ID:GNU,Clang,AppleClang>:
|
|
-std=gnu89
|
|
-Wall
|
|
>
|
|
)
|
|
|
|
if(ABCMIDI_SANITIZERS)
|
|
target_compile_options(abcmidi_common INTERFACE
|
|
-fsanitize=address,undefined -fno-omit-frame-pointer)
|
|
target_link_options(abcmidi_common INTERFACE
|
|
-fsanitize=address,undefined)
|
|
endif()
|
|
|
|
# --- Shared object libraries (compiled once, linked into multiple binaries) ---
|
|
|
|
add_library(obj_midifile OBJECT midifile.c)
|
|
target_link_libraries(obj_midifile PUBLIC abcmidi_common)
|
|
|
|
add_library(obj_parseabc OBJECT parseabc.c music_utils.c)
|
|
target_link_libraries(obj_parseabc PUBLIC abcmidi_common)
|
|
|
|
add_library(obj_parser2 OBJECT parser2.c)
|
|
target_link_libraries(obj_parser2 PUBLIC abcmidi_common)
|
|
|
|
# --- Executables ---
|
|
|
|
# abc2midi: ABC notation → MIDI
|
|
add_executable(abc2midi
|
|
store.c genmidi.c queues.c stresspat.c
|
|
)
|
|
target_link_libraries(abc2midi PRIVATE
|
|
obj_parseabc obj_parser2 obj_midifile abcmidi_common m)
|
|
|
|
# abc2abc: ABC notation → ABC notation (transposition, reformatting)
|
|
add_executable(abc2abc toabc.c)
|
|
target_link_libraries(abc2abc PRIVATE obj_parseabc abcmidi_common m)
|
|
|
|
# midi2abc: MIDI → ABC notation
|
|
add_executable(midi2abc midi2abc.c)
|
|
target_link_libraries(midi2abc PRIVATE obj_midifile abcmidi_common m)
|
|
|
|
# midistats: MIDI file statistics
|
|
add_executable(midistats midistats.c)
|
|
target_link_libraries(midistats PRIVATE obj_midifile abcmidi_common m)
|
|
|
|
# mftext: MIDI → human-readable text
|
|
add_executable(mftext mftext.c crack.c)
|
|
target_link_libraries(mftext PRIVATE obj_midifile abcmidi_common m)
|
|
|
|
# yaps: ABC notation → PostScript
|
|
add_executable(yaps
|
|
yapstree.c drawtune.c debug.c pslib.c position.c
|
|
)
|
|
target_link_libraries(yaps PRIVATE
|
|
obj_parseabc obj_parser2 abcmidi_common m)
|
|
|
|
# midicopy: MIDI file filtering/extraction
|
|
add_executable(midicopy midicopy.c)
|
|
target_link_libraries(midicopy PRIVATE abcmidi_common m)
|
|
|
|
# abcmatch: ABC tune matching/comparison
|
|
add_executable(abcmatch abcmatch.c matchsup.c)
|
|
target_link_libraries(abcmatch PRIVATE obj_parseabc abcmidi_common m)
|
|
|
|
# --- Install ---
|
|
|
|
include(GNUInstallDirs)
|
|
|
|
set(ABCMIDI_BINARIES abc2midi abc2abc midi2abc midistats mftext yaps midicopy abcmatch)
|
|
|
|
install(TARGETS ${ABCMIDI_BINARIES}
|
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
)
|
|
|
|
# Match the legacy Makefile: install only top-level doc files, not subdirectories
|
|
install(FILES
|
|
doc/abcguide.txt
|
|
doc/abcmatch.txt
|
|
doc/gpl.txt
|
|
doc/history.txt
|
|
doc/hudsonshift.txt
|
|
doc/readme.txt
|
|
doc/yapshelp.txt
|
|
doc/AUTHORS
|
|
doc/CHANGES
|
|
VERSION
|
|
DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
|
)
|
|
|
|
install(FILES
|
|
doc/abc2abc.1
|
|
doc/abc2midi.1
|
|
doc/abcmatch.1
|
|
doc/mftext.1
|
|
doc/midi2abc.1
|
|
doc/midicopy.1
|
|
doc/midistats.1
|
|
doc/yaps.1
|
|
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
|
|
)
|
|
|
|
# --- Tests ---
|
|
|
|
include(CTest)
|
|
if(BUILD_TESTING)
|
|
add_subdirectory(tests)
|
|
endif()
|
|
|
|
# TODO: install-validation test that verifies all binaries, doc files, and man
|
|
# pages are installed to the expected paths.
|