438 lines
8.5 KiB
Markdown
438 lines
8.5 KiB
Markdown
# racket-audio-native-libs
|
|
|
|
Native library distribution repository for `racket-audio`.
|
|
|
|
This repository contains the platform-specific native libraries used by
|
|
`racket-audio`. It uses one Git branch per published Racket package.
|
|
|
|
The `main` branch contains the build and maintenance files. The other branches
|
|
contain the actual Racket packages that are registered in the Racket Package
|
|
Index.
|
|
|
|
## Branch structure
|
|
|
|
The repository uses the following branches:
|
|
|
|
```text
|
|
main
|
|
native-libs
|
|
x86_64-win32
|
|
x86_64-linux
|
|
aarch64-linux
|
|
aarch64-macosx
|
|
```
|
|
|
|
Their purpose is:
|
|
|
|
```text
|
|
main
|
|
Build scripts, documentation and maintenance files.
|
|
|
|
native-libs
|
|
Meta-package: racket-audio-native-libs.
|
|
Selects the correct platform package.
|
|
|
|
x86_64-win32
|
|
Native libraries for 64-bit Windows.
|
|
|
|
x86_64-linux
|
|
Native libraries for 64-bit Intel/AMD Linux.
|
|
|
|
aarch64-linux
|
|
Native libraries for 64-bit ARM Linux, for example a 64-bit Raspberry Pi.
|
|
|
|
aarch64-macosx
|
|
Native libraries for Apple Silicon macOS, for example an M1 Mac.
|
|
```
|
|
|
|
Each platform branch is a separate Racket package.
|
|
|
|
## Package names
|
|
|
|
The intended Racket package names are:
|
|
|
|
```text
|
|
racket-audio-native-libs
|
|
racket-audio-x86_64-win32
|
|
racket-audio-x86_64-linux
|
|
racket-audio-aarch64-linux
|
|
racket-audio-aarch64-macosx
|
|
```
|
|
|
|
`racket-audio` itself should depend on:
|
|
|
|
```text
|
|
racket-audio-native-libs
|
|
```
|
|
|
|
The `racket-audio-native-libs` package then selects the correct platform
|
|
package.
|
|
|
|
This keeps the Racket code in `racket-audio` independent of the operating
|
|
system and architecture.
|
|
|
|
## Native package layout
|
|
|
|
A platform branch contains the native libraries directly in the root of the
|
|
branch, together with `info.rkt`.
|
|
|
|
For example, the `x86_64-win32` branch may look like:
|
|
|
|
```text
|
|
info.rkt
|
|
portaudio.dll
|
|
libsndfile-1.dll
|
|
libmpg123-0.dll
|
|
...
|
|
```
|
|
|
|
The exact DLL names depend on the libraries used by `racket-audio`.
|
|
|
|
The corresponding `info.rkt` uses `copy-foreign-libs`:
|
|
|
|
```racket
|
|
#lang info
|
|
|
|
(define collection 'multi)
|
|
|
|
(define version "0.1.0")
|
|
|
|
(define pkg-desc
|
|
"native libraries for \"racket-audio\" on \"x86_64-win32\"")
|
|
|
|
(define pkg-authors
|
|
'(hans))
|
|
|
|
(define install-platform
|
|
"win32\\x86_64")
|
|
|
|
(define copy-foreign-libs
|
|
'("portaudio.dll"
|
|
"libsndfile-1.dll"))
|
|
|
|
(define deps
|
|
'("base"))
|
|
```
|
|
|
|
Every native library that must be installed with the package must be listed in
|
|
`copy-foreign-libs`.
|
|
|
|
This also includes DLLs, shared objects or dylibs that are runtime dependencies
|
|
of the primary audio libraries.
|
|
|
|
During package setup, Racket copies these files to a location that can be found
|
|
by `ffi-lib`.
|
|
|
|
## Meta-package
|
|
|
|
The `native-libs` branch contains the package:
|
|
|
|
```text
|
|
racket-audio-native-libs
|
|
```
|
|
|
|
It contains no native libraries itself.
|
|
|
|
Its `info.rkt` selects the correct package based on the current Racket
|
|
platform.
|
|
|
|
Conceptually:
|
|
|
|
```text
|
|
racket-audio
|
|
|
|
|
+-- racket-audio-native-libs
|
|
|
|
|
+-- racket-audio-x86_64-win32
|
|
+-- racket-audio-x86_64-linux
|
|
+-- racket-audio-aarch64-linux
|
|
+-- racket-audio-aarch64-macosx
|
|
```
|
|
|
|
Only the package matching the current platform is installed.
|
|
|
|
## Use from racket-audio
|
|
|
|
The `racket-audio` package should declare `racket-audio-native-libs` as a
|
|
dependency in its `info.rkt`.
|
|
|
|
For example:
|
|
|
|
```racket
|
|
(define deps
|
|
'("base"
|
|
"racket-audio-native-libs"))
|
|
```
|
|
|
|
The FFI code should preferably load libraries by their logical name instead of
|
|
using machine-specific absolute paths.
|
|
|
|
For example:
|
|
|
|
```racket
|
|
(ffi-lib "portaudio")
|
|
```
|
|
|
|
rather than:
|
|
|
|
```racket
|
|
(ffi-lib "C:\\some\\local\\directory\\portaudio.dll")
|
|
```
|
|
|
|
The native package is responsible for installing the actual library for the
|
|
current platform.
|
|
|
|
## Development workflow
|
|
|
|
Development and package preparation take place on `main`.
|
|
|
|
The platform branches should contain only the files required for the published
|
|
Racket package.
|
|
|
|
A typical Windows workflow is:
|
|
|
|
```text
|
|
main
|
|
|
|
|
| prepare/test Windows DLL package
|
|
v
|
|
x86_64-win32
|
|
|
|
|
| commit + push
|
|
v
|
|
Racket Package Index
|
|
```
|
|
|
|
The same approach can later be used for Linux, Raspberry Pi and macOS.
|
|
|
|
## Adding or updating a Windows package
|
|
|
|
Start on `main`:
|
|
|
|
```bash
|
|
git switch main
|
|
git pull
|
|
```
|
|
|
|
Prepare or collect the required 64-bit Windows DLL files.
|
|
|
|
Before publishing, verify that all runtime dependencies are included.
|
|
|
|
Then switch to the platform branch:
|
|
|
|
```bash
|
|
git switch x86_64-win32
|
|
```
|
|
|
|
Update:
|
|
|
|
```text
|
|
info.rkt
|
|
*.dll
|
|
```
|
|
|
|
Make sure `copy-foreign-libs` contains every DLL that belongs to the package.
|
|
|
|
Commit and push:
|
|
|
|
```bash
|
|
git add info.rkt *.dll
|
|
git commit -m "Update Windows native libraries"
|
|
git push
|
|
```
|
|
|
|
## Adding or updating Linux x86_64
|
|
|
|
Use:
|
|
|
|
```bash
|
|
git switch x86_64-linux
|
|
```
|
|
|
|
The branch will normally contain:
|
|
|
|
```text
|
|
info.rkt
|
|
*.so
|
|
*.so.*
|
|
```
|
|
|
|
Include all shared libraries required at runtime.
|
|
|
|
After testing:
|
|
|
|
```bash
|
|
git add .
|
|
git commit -m "Update Linux x86_64 native libraries"
|
|
git push
|
|
```
|
|
|
|
## Adding or updating Raspberry Pi / Linux ARM64
|
|
|
|
For a Raspberry Pi running a 64-bit operating system and 64-bit Racket, use:
|
|
|
|
```bash
|
|
git switch aarch64-linux
|
|
```
|
|
|
|
This package is intended for:
|
|
|
|
```text
|
|
aarch64-linux
|
|
```
|
|
|
|
Build the libraries natively on the Raspberry Pi where practical.
|
|
|
|
After testing:
|
|
|
|
```bash
|
|
git add .
|
|
git commit -m "Update Linux ARM64 native libraries"
|
|
git push
|
|
```
|
|
|
|
## Adding or updating Apple Silicon macOS
|
|
|
|
For an Apple Silicon Mac, such as an M1 Mac, use:
|
|
|
|
```bash
|
|
git switch aarch64-macosx
|
|
```
|
|
|
|
The branch normally contains:
|
|
|
|
```text
|
|
info.rkt
|
|
*.dylib
|
|
```
|
|
|
|
Build and test the libraries on the Apple Silicon target machine.
|
|
|
|
After testing:
|
|
|
|
```bash
|
|
git add .
|
|
git commit -m "Update Apple Silicon native libraries"
|
|
git push
|
|
```
|
|
|
|
## Testing a platform package locally
|
|
|
|
Before registering or updating a package in the Racket Package Index, install
|
|
the platform branch locally and verify that `racket-audio` can load and use the
|
|
libraries.
|
|
|
|
For example, from a checkout of the platform branch:
|
|
|
|
```bash
|
|
raco pkg install --auto .
|
|
```
|
|
|
|
After changing an already installed package, use the normal Racket package
|
|
update/reinstall workflow as appropriate.
|
|
|
|
The important test is that the existing FFI code can load the libraries without
|
|
using local absolute paths.
|
|
|
|
## Racket Package Index
|
|
|
|
Each published branch is registered as a separate Racket package.
|
|
|
|
The source URL can point directly to the corresponding Git branch.
|
|
|
|
Conceptually:
|
|
|
|
```text
|
|
racket-audio-native-libs
|
|
<repository-url>#native-libs
|
|
|
|
racket-audio-x86_64-win32
|
|
<repository-url>#x86_64-win32
|
|
|
|
racket-audio-x86_64-linux
|
|
<repository-url>#x86_64-linux
|
|
|
|
racket-audio-aarch64-linux
|
|
<repository-url>#aarch64-linux
|
|
|
|
racket-audio-aarch64-macosx
|
|
<repository-url>#aarch64-macosx
|
|
```
|
|
|
|
The Racket Package Index therefore does not need a separate manually uploaded
|
|
ZIP file. The Git branch itself is the package source.
|
|
|
|
## Initial branch publication
|
|
|
|
If the branches exist locally but not yet on `origin`, publish them with:
|
|
|
|
```bash
|
|
git push -u origin native-libs
|
|
git push -u origin x86_64-win32
|
|
git push -u origin x86_64-linux
|
|
git push -u origin aarch64-linux
|
|
git push -u origin aarch64-macosx
|
|
```
|
|
|
|
After that, a normal:
|
|
|
|
```bash
|
|
git push
|
|
```
|
|
|
|
is sufficient when working on a branch that has its upstream configured.
|
|
|
|
## Build automation
|
|
|
|
The first goal is to make the packaging work reliably using already available
|
|
native libraries.
|
|
|
|
After that, `main` can grow into a build orchestrator using Racket itself.
|
|
|
|
The intended direction is:
|
|
|
|
```text
|
|
Windows machine
|
|
-> build x86_64-win32
|
|
|
|
Linux x86_64 machine
|
|
-> build x86_64-linux
|
|
|
|
Raspberry Pi 64-bit
|
|
-> build aarch64-linux
|
|
|
|
Apple Silicon Mac
|
|
-> build aarch64-macosx
|
|
```
|
|
|
|
The build orchestration can use `racket-makefile`, the Racket `git` module and,
|
|
for remote targets, SSH or another small remote-execution layer.
|
|
|
|
The native libraries should preferably be built on the target architecture
|
|
instead of cross-compiled, unless there is a good reason to do otherwise.
|
|
|
|
## Versioning
|
|
|
|
The version in each platform package should correspond to the native library
|
|
set delivered by that branch.
|
|
|
|
When changing the packaged native libraries, update the package version where
|
|
appropriate and keep the meta-package dependency versions compatible.
|
|
|
|
## Licenses
|
|
|
|
Native libraries may have licenses that differ from the license of the Racket
|
|
wrapper.
|
|
|
|
Before publishing a new library or version, verify:
|
|
|
|
```text
|
|
- the upstream license;
|
|
- whether binary redistribution is permitted;
|
|
- whether license or copyright files must be included;
|
|
- whether additional runtime libraries have separate license requirements.
|
|
```
|
|
|
|
Do not assume that the license of `racket-audio` automatically covers the
|
|
native binaries.
|