{"id":13430268,"url":"https://github.com/FluidSynth/fluidsynth","last_synced_at":"2025-03-16T05:30:40.099Z","repository":{"id":37470689,"uuid":"95304991","full_name":"FluidSynth/fluidsynth","owner":"FluidSynth","description":"Software synthesizer based on the SoundFont 2 specifications","archived":false,"fork":false,"pushed_at":"2025-03-09T16:23:20.000Z","size":11200,"stargazers_count":1997,"open_issues_count":36,"forks_count":269,"subscribers_count":54,"default_branch":"master","last_synced_at":"2025-03-13T03:01:39.052Z","etag":null,"topics":["cross-platform","fluidsynth","linux","midi","midi-files","midi-player","realtime","soundfont-synthesizers","soundfont2-synthesizer-library","soundfonts","synthesizer","wavetables"],"latest_commit_sha":null,"homepage":"https://www.fluidsynth.org","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FluidSynth.png","metadata":{"files":{"readme":"README.cmake.md","changelog":"ChangeLog.old","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-06-24T15:09:55.000Z","updated_at":"2025-03-12T09:41:43.000Z","dependencies_parsed_at":"2022-07-09T14:00:27.520Z","dependency_job_id":"4c64631c-8a97-49a7-98b9-50e78d763355","html_url":"https://github.com/FluidSynth/fluidsynth","commit_stats":null,"previous_names":[],"tags_count":59,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FluidSynth%2Ffluidsynth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FluidSynth%2Ffluidsynth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FluidSynth%2Ffluidsynth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FluidSynth%2Ffluidsynth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FluidSynth","download_url":"https://codeload.github.com/FluidSynth/fluidsynth/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243830912,"owners_count":20354848,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cross-platform","fluidsynth","linux","midi","midi-files","midi-player","realtime","soundfont-synthesizers","soundfont2-synthesizer-library","soundfonts","synthesizer","wavetables"],"created_at":"2024-07-31T02:00:51.638Z","updated_at":"2025-03-16T05:30:39.341Z","avatar_url":"https://github.com/FluidSynth.png","language":"C","readme":"## For users - how to compile FluidSynth\n\nThe latest information on how to compile FluidSynth using the cmake build system can be found in our wiki:\n\nhttps://github.com/FluidSynth/fluidsynth/wiki/BuildingWithCMake\n\n## For developers - how to add a new feature to the CMake build system\n\nLet's explain this issue with an example. We are adding InstPatch support to\nFluidSynth as an optional feature, conditionally adding source files that\nrequire this feature. The first step is to add a macro `option()` to the main\nCMakeLists.txt file, the one that is located at the fluidsynth root directory.\n\nfile [CMakeLists.txt](./CMakeLists.txt#L79), line 79:\n\n```cmake\noption ( enable-libinstpatch \"use libinstpatch (if available) to load DLS and GIG files\" on )\n```\n\nIf you require a minimum version of the library, set it as such:\n\nfile [CMakeLists.txt](./CMakeLists.txt#L505), line 505:\n\n```cmake\nset ( LIBINSTPATCH_MINIMUM_VERSION 1.1.0 )\n```\n\nNow, let's check if the InstPatch library and headers are installed, using\nfind_package:\n\nfile [CMakeLists.txt](./CMakeLists.txt#L634), lines 634-641:\n\n```cmake\nunset ( LIBINSTPATCH_SUPPORT CACHE )\nif ( enable-libinstpatch )\n    find_package ( InstPatch ${LIBINSTPATCH_MINIMUM_VERSION} )\n    set ( LIBINSTPATCH_SUPPORT ${InstPatch_FOUND} )\n    if ( LIBINSTPATCH_SUPPORT )\n        list( APPEND PC_REQUIRES_PRIV \"libinstpatch-1.0\")\n    endif (LIBINSTPATCH_SUPPORT )\nendif ( enable-libinstpatch )\n```\n\nThe first line clears the value of the CMake variable LIBINSTPATCH_SUPPORT. If\nthe value of the option `enable-libinstpatch` is true, then the function\n`find_package()` is used to test a package named \"InstPatch\" with version 1.1.0\nor later. Unfortunately, libinstpatch does not provide an official CMake\nconfiguration, so we will need to write it a Find module. Let's start by\ncreating a new file in the cmake_admin directory called\n[FindInstPatch.cmake](./cmake_admin/FindInstPatch.cmake).\n\nThe first thing we should do is to document what this module provides:\n\nfile [cmake_admin/FindInstPatch.cmake](./cmake_admin/FindInstPatch.cmake), lines 1-25:\n\n```cmake\n#[=======================================================================[.rst:\nFindInstPatch\n-------\n\nFinds the InstPatch library.\n\nImported Targets\n^^^^^^^^^^^^^^^^\n\nThis module provides the following imported targets, if found:\n\n``InstPatch::libinstpatch``\n  The InstPatch library\n\nResult Variables\n^^^^^^^^^^^^^^^^\n\nThis will define the following variables:\n\n``InstPatch_FOUND``\n  True if the system has the InstPatch library.\n``InstPatch_VERSION``\n  The version of the InstPatch library which was found.\n\n#]=======================================================================]\n```\n\nIn this case, we provide a CMake target `InstPatch::libinstpatch`, and the two\nvariables `InstPatch_FOUND` and `InstPatch_VERSION`. If upstream provides an\nofficial CMake config, the find module should provide the exact same variables\nand targets, even if they are not used. Moreover, the namespace of the target\n(`InstPatch::`) should match the file name (`FindInstPatch.cmake`).\n\nIf the library provides a pkg-config file, we should use it to get information\nabout location, version, and usage requirements. We can achieve this with the\n`pkg_check_modules` macro:\n\nfile [cmake_admin/FindInstPatch.cmake](./cmake_admin/FindInstPatch.cmake#L27), lines 27-29:\n\n```cmake\n# Use pkg-config if available\nfind_package(PkgConfig QUIET)\npkg_check_modules(PC_INSTPATCH QUIET libinstpatch-1.0)\n```\n\nWe specifically want both calls to have the `QUIET` specifier as the system may\nnot have pkg-config or the pc file for the library, but this should not stop\nsearching for the library.\n\nNext, we need to search for the headers and the library. For the headers,\nlibinstpatch installs them in `libinstpatch-X/libinstpatch/*.h`, with `X` being\n`1` for versions 1.1.0 and below, and `2` for 1.1.1 and above. In our code, we\nuse the headers as such: `#include \u003clibinstpatch/libinstpatch.h\u003e`. With this\nin mind, we use `find_path` to find the include directory:\n\nfile [cmake_admin/FindInstPatch.cmake](./cmake_admin/FindInstPatch.cmake#L32), lines 32-36:\n\n```cmake\nfind_path(\n  InstPatch_INCLUDE_DIR\n  NAMES \"libinstpatch/libinstpatch.h\"\n  PATHS \"${PC_INSTPATCH_INCLUDEDIR}\"\n  PATH_SUFFIXES \"libinstpatch-1\" \"libinstpatch-2\")\n```\n\nHere is a breakdown of the arguments:\n\n- `InstPatch_INCLUDE_DIR` is the variable where the result will be stored;\n- `NAMES` should match what is used in code to include the header;\n- `PATHS` should be set to what pkg-config provided us, if pkg-config is\n  unavailable it will be ignored;\n- `PATH_SUFFIXES` should have the potential intermediate directories between\n  CMake's search paths and what was specified in `NAMES`, it may omitted when\n  not applicable.\n\nTo search for the library, we call `find_library`:\n\nfile [cmake_admin/FindInstPatch.cmake](./cmake_admin/FindInstPatch.cmake#L38), lines 38-41:\n\n```cmake\nfind_library(\n  InstPatch_LIBRARY\n  NAMES \"instpatch-1.0\"\n  PATHS \"${PC_INSTPATCH_LIBDIR}\")\n```\n\nHere is a breakdown of the arguments:\n\n- `InstPatch_LIBRARY` is the variable where the result will be stored;\n- `NAMES` should list every name the library may have, some libraries may have\n  a different prefix or suffix on different configurations (`-static` suffix,\n  `d` suffix for debug builds);\n- `PATHS` should be set to what pkg-config provided us, if pkg-config is\n  unavailable it will be ignored.\n\nGetting the version of the library is trivial with pkg-config, but may not be\npossible to get without. Fortunately, the file `libinstpatch/version.h`\nprovides the version:\n\n```c\n#define IPATCH_VERSION       \"1.2.0\"\n```\n\nWe can extract the version using regex:\n\nfile [cmake_admin/FindInstPatch.cmake](./cmake_admin/FindInstPatch.cmake#L44), lines 44-52:\n\n```cmake\nif(PC_INSTPATCH_VERSION)\n  set(InstPatch_VERSION \"${PC_INSTPATCH_VERSION}\")\nelseif(InstPatch_INCLUDE_DIR)\n  file(READ \"${InstPatch_INCLUDE_DIR}/libinstpatch/version.h\" _version_h)\n  string(REGEX MATCH\n               \"#define[ \\t]+IPATCH_VERSION[ \\t]+\\\"([0-9]+.[0-9]+.[0-9]+)\\\"\"\n               _instpatch_version_re \"${_version_h}\")\n  set(InstPatch_VERSION \"${CMAKE_MATCH_1}\")\nendif()\n```\n\nThe last thing we need to search for is the usage requirements, providing them\nmakes static linking much easier. If pkg-config is available, we use a helper\nfunction to get the correct set of properties, otherwise you need to refer to \nthe upstream documentation. In the case of libinstpatch, we need `glib-2` and\n`libsndfile`, fortunately, we already have Find modules for both libraries:\n\nfile [cmake_admin/FindInstPatch.cmake](./cmake_admin/FindInstPatch.cmake#L55), lines 55-69:\n\n```cmake\nif(PC_INSTPATCH_FOUND)\n  get_target_properties_from_pkg_config(\"${InstPatch_LIBRARY}\" \"PC_INSTPATCH\"\n                                        \"_instpatch\")\nelse()\n  if(NOT TARGET GLib2::gobject-2\n     OR NOT TARGET GLib2::gthread-2\n     OR NOT TARGET GLib2::glib-2)\n    find_package(GLib2 QUIET)\n  endif()\n  if(NOT TARGET SndFile::sndfile)\n    find_package(SndFile QUIET)\n  endif()\n  set(_instpatch_link_libraries \"GLib2::gobject-2\" \"GLib2::gthread-2\"\n                                \"GLib2::glib-2\" \"SndFile::sndfile\")\nendif()\n```\n\nWe then use `find_package_handle_standard_args` to check that all the\nvariables are set and the version matches what was requested:\n\nfile [cmake_admin/FindInstPatch.cmake](./cmake_admin/FindInstPatch.cmake#L72), lines 72-76:\n\n```cmake\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(\n  InstPatch\n  REQUIRED_VARS \"InstPatch_LIBRARY\" \"InstPatch_INCLUDE_DIR\"\n  VERSION_VAR \"InstPatch_VERSION\")\n```\n\nThis will set `InstPatch_FOUND` to true if the checks succeed and false\notherwise.\n\nIf the library is found, we then create the target and set its properties:\n\nfile [cmake_admin/FindInstPatch.cmake](./cmake_admin/FindInstPatch.cmake#L78), lines 78-87:\n\n```cmake\nif(InstPatch_FOUND AND NOT TARGET InstPatch::libinstpatch)\n  add_library(InstPatch::libinstpatch UNKNOWN IMPORTED)\n  set_target_properties(\n    InstPatch::libinstpatch\n    PROPERTIES IMPORTED_LOCATION \"${InstPatch_LIBRARY}\"\n               INTERFACE_COMPILE_OPTIONS \"${_instpatch_compile_options}\"\n               INTERFACE_INCLUDE_DIRECTORIES \"${InstPatch_INCLUDE_DIR}\"\n               INTERFACE_LINK_LIBRARIES \"${_instpatch_link_libraries}\"\n               INTERFACE_LINK_DIRECTORIES \"${_instpatch_link_directories}\")\nendif()\n```\n\nHere is a breakdown of the properties:\n\n- `IMPORTED_LOCATION` should be the result of `find_library`;\n- `INTERFACE_INCLUDE_DIRECTORES` should be the result of `find_path`;\n- `INTERFACE_LINK_LIBRARIES` should be the transitive usage requirements, it\n  may be omitted if there are none;\n- `INTERFACE_COMPILE_OPTIONS` and `INTERFACE_LINK_DIRECTORIES` should be set to\n  what our `get_flags_from_pkg_config` helper provided us, if pkg-config is\n  unavailable they will be ignored.\n\nLastly, we call mark a few cache variables as advanced:\n\nfile [cmake_admin/FindInstPatch.cmake](./cmake_admin/FindInstPatch.cmake#L88), line 88:\n\n```cmake\nmark_as_advanced(InstPatch_INCLUDE_DIR InstPatch_LIBRARY)\n```\n\nNext, we need to inform downstream projects of this so if fluidsynth was built\nas a static library, all the transitive dependencies are properly forwarded. To\nachieve this, we need to edit FluidSynthConfig.cmake.in:\n\nfile [FluidSynthConfig.cmake](./FluidSynthConfig.cmake.in#L22), line 22:\n\n```cmake\nset(FLUIDSYNTH_SUPPORT_LIBINSTPATCH @LIBINSTPATCH_SUPPORT@)\n```\n\nfile [FluidSynthConfig.cmake](./FluidSynthConfig.cmake.in#L91), lines 91-93:\n\n```cmake\n  if(FLUIDSYNTH_SUPPORT_LIBINSTPATCH AND NOT TARGET InstPatch::libinstpatch)\n    find_dependency(InstPatch @LIBINSTPATCH_MINIMUM_VERSION@)\n  endif()\n```\n\nThere is a report to summarize the performed checks and the enabled features\nafter the configuration steps, so let's add a line in this report regarding\nthe InstPatch support.\n\nfile [cmake_admin/report.cmake](./cmake_admin/report.cmake#L119), lines 119-124:\n\n```cmake\nset ( INPUTS_REPORT \"${INPUTS_REPORT}Support for DLS files:   \" )\nif ( LIBINSTPATCH_SUPPORT )\n    set ( INPUTS_REPORT \"${INPUTS_REPORT}yes\\n\" )\nelse ( LIBINSTPATCH_SUPPORT )\n    set ( INPUTS_REPORT \"${INPUTS_REPORT}no (libinstpatch not found)\\n\" )\nendif ( LIBINSTPATCH_SUPPORT )\n```\n\nThe variable `LIBINSTPATCH_SUPPORT` is available for the CMake files, but we\nwant to make it available to the compilers as well, to conditionally build code\nusing `#ifdef LIBINSTPATCH_SUPPORT`. This can be done adding a line to the\nconfig.cmake file:\n\nfile [src/config.cmake](./src/config.cmake#L148), lines 148-149:\n\n```c\n/* libinstpatch for DLS and GIG */\n#cmakedefine LIBINSTPATCH_SUPPORT @LIBINSTPATCH_SUPPORT@\n```\n\nThe file config.cmake will be processed at configure time, producing a header\nfile \"config.h\" in the build directory with this content, if the InstPatch\nsupport has been enabled and found:\n\n```c\n/* libinstpatch for DLS and GIG */\n#define LIBINSTPATCH_SUPPORT 1\n```\n\nFinally, we add the new sources files to the library during the `add_library`\ncall, and link the library using the `target_link_libraries` function. Note\nthat linking to a target will automatically set the necessary include\ndirectories.\n\nfile [src/CMakeLists.txt](./src/CMakeLists.txt#L96), lines 96-98:\n\n```cmake\nif ( LIBINSTPATCH_SUPPORT )\n  set ( fluid_libinstpatch_SOURCES sfloader/fluid_instpatch.c sfloader/fluid_instpatch.h )\nendif ( LIBINSTPATCH_SUPPORT )\n```\n\nfile [src/CMakeLists.txt](./src/CMakeLists.txt#L230), lines 230-257:\n\n```cmake\nadd_library ( libfluidsynth-OBJ OBJECT\n    ...\n    ${fluid_libinstpatch_SOURCES}\n    ...\n)\n```\n\nfile [src/CMakeLists.txt](./src/CMakeLists.txt#L386), lines 386-388:\n\n```cmake\nif ( TARGET InstPatch::libinstpatch AND LIBINSTPATCH_SUPPORT )\n    target_link_libraries ( libfluidsynth-OBJ PUBLIC InstPatch::libinstpatch )\nendif()\n```\n\nIf the library is used in the fluidsynth executable, you also need to link it to its target:\n\nfile [src/CMakeLists.txt](./src/CMakeLists.txt#L484), lines 484-486:\n\n```cmake\nif ( TARGET InstPatch::libinstpatch AND LIBINSTPATCH_SUPPORT )\n    target_link_libraries ( fluidsynth PRIVATE InstPatch::libinstpatch )\nendif()\n```\n\n### Find modules guideline\n\nIt is not always necessary to provide find modules if:\n\n- The upstream library provides its own config\n- Most distribution ship this config\n\nFor example:\n\n- libsndfile provides a CMake config file only when built with CMake but not\n  with autotools. In that case, it may be preferable to provide a Find module\n  that matches what the config would provide. See [cmake_admin/FindSndFile](./cmake_admin/FindSndFile.cmake).\n- SDL2 provides a config file that defines targets starting 2.0.12. Since even\n  Debian stable provides this config, it is safe to assume that a find module\n  will not be needed.\n\nIf upstream has only begun shipping CMake config recently, it is preferable to\nadd a Find module.\n\nIf upstream does not provide a CMake config altogether, you will need to make\nyour own from scratch. There is no defined rule for naming, but the common\npractice is to have the namespace use PascalCase.\n\nYou can have CMake prefer the upstream config file over the find modules by\nsetting `CMAKE_FIND_PACKAGE_PREFER_CONFIG` to `ON`.\n","funding_links":[],"categories":["C"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFluidSynth%2Ffluidsynth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FFluidSynth%2Ffluidsynth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFluidSynth%2Ffluidsynth/lists"}