This commit is contained in:
Anthony Samms
2025-09-15 19:09:48 -04:00
parent b82940ea54
commit dea8c64acd
2 changed files with 180 additions and 123 deletions

View File

@@ -19,19 +19,6 @@ jobs:
- name: Check-out repository - name: Check-out repository
uses: actions/checkout@v4 uses: actions/checkout@v4
# Install audio library dependencies
- name: Install Audio Dependencies (Ubuntu)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
pkg-config \
portaudio19-dev \
libsndfile1-dev \
libsamplerate0-dev \
ccache
- name: Install Audio Dependencies (macOS) - name: Install Audio Dependencies (macOS)
if: runner.os == 'macOS' if: runner.os == 'macOS'
run: | run: |

View File

@@ -1,121 +1,167 @@
# Makefile for audio library with full static linking # Makefile for audio library with intelligent dependency detection
CC = gcc CC = gcc
CFLAGS = -Wall -Wextra -O3 -fPIC -std=c99 CFLAGS = -Wall -Wextra -O3 -fPIC -std=c99
LDFLAGS = -shared -Wl,--export-dynamic LDFLAGS = -shared -Wl,--export-dynamic
LIBS = -lportaudio -lsndfile -lsamplerate -lpthread -lm
UNAME_S := $(shell uname -s 2>/dev/null || echo Windows) UNAME_S := $(shell uname -s 2>/dev/null || echo Windows)
# MSYS2/MinGW-w64 with full static linking # Function to check if a library exists
define check_lib
$(shell pkg-config --exists $(1) 2>/dev/null && echo "yes" || echo "no")
endef
# Function to check if a static library file exists
define check_static_lib
$(shell find /usr/lib /usr/local/lib /lib -name "lib$(1).a" 2>/dev/null | head -1)
endef
# MSYS2/MinGW-w64 with intelligent static linking
ifneq (,$(findstring MINGW,$(UNAME_S))) ifneq (,$(findstring MINGW,$(UNAME_S)))
CC = x86_64-w64-mingw32-gcc CC = x86_64-w64-mingw32-gcc
LIBNAME = libaudio.dll LIBNAME = libaudio.dll
CFLAGS = -Wall -Wextra -O3 -fPIC -std=c99 -I/mingw64/include -m64 CFLAGS = -Wall -Wextra -O3 -fPIC -std=c99 -I/mingw64/include -m64
LDFLAGS = -shared -Wl,--export-all-symbols -static-libgcc -static-libstdc++ -L/mingw64/lib -m64
# Full static linking flags # Core libraries (try static first, fall back to dynamic)
LDFLAGS = -shared \ CORE_LIBS =
-Wl,--export-all-symbols \ ifneq (,$(wildcard /mingw64/lib/libportaudio.a))
-Wl,--whole-archive \ CORE_LIBS += /mingw64/lib/libportaudio.a
-static-libgcc \ else
-static-libstdc++ \ CORE_LIBS += -lportaudio
-static \ endif
-L/mingw64/lib \
-m64
# Static libraries in correct order (dependencies matter!) ifneq (,$(wildcard /mingw64/lib/libsndfile.a))
LIBS = -Wl,--start-group \ CORE_LIBS += /mingw64/lib/libsndfile.a
-lportaudio \ else
-lsndfile \ CORE_LIBS += -lsndfile
-lsamplerate \ endif
-lFLAC \
-lvorbisenc \
-lvorbisfile \
-lvorbis \
-logg \
-lopus \
-lwinmm \
-lole32 \
-luuid \
-lksuser \
-lsetupapi \
-lws2_32 \
-ladvapi32 \
-luser32 \
-lgdi32 \
-lkernel32 \
-Wl,--end-group \
-Wl,--no-whole-archive
ifneq (,$(wildcard /mingw64/lib/libsamplerate.a))
CORE_LIBS += /mingw64/lib/libsamplerate.a
else
CORE_LIBS += -lsamplerate
endif
# Optional codec libraries
CODEC_LIBS =
ifneq (,$(wildcard /mingw64/lib/libFLAC.a))
CODEC_LIBS += /mingw64/lib/libFLAC.a
endif
ifneq (,$(wildcard /mingw64/lib/libvorbisenc.a))
CODEC_LIBS += /mingw64/lib/libvorbisenc.a /mingw64/lib/libvorbisfile.a /mingw64/lib/libvorbis.a
endif
ifneq (,$(wildcard /mingw64/lib/libogg.a))
CODEC_LIBS += /mingw64/lib/libogg.a
endif
# System libraries
SYSTEM_LIBS = -lwinmm -lole32 -luuid -lksuser -lsetupapi -lws2_32
LIBS = $(CORE_LIBS) $(CODEC_LIBS) $(SYSTEM_LIBS)
OBJ_EXT = .o OBJ_EXT = .o
else ifneq (,$(findstring Windows,$(UNAME_S)))
# Windows with MSVC (alternative approach)
CC = cl
LIBNAME = libaudio.dll
CFLAGS = /O2 /W3 /MD /TC /DSTATIC_LINK
LDFLAGS = /DLL /NODEFAULTLIB:MSVCRT
LIBS = portaudio_static.lib libsndfile_static.lib libsamplerate_static.lib \
winmm.lib ole32.lib uuid.lib setupapi.lib ws2_32.lib
OBJ_EXT = .obj
else ifeq ($(UNAME_S),Darwin) else ifeq ($(UNAME_S),Darwin)
# macOS with static linking # macOS
LIBNAME = libaudio.dylib LIBNAME = libaudio.dylib
CFLAGS += -I/usr/local/include -I/opt/homebrew/include CFLAGS += -I/usr/local/include -I/opt/homebrew/include
LDFLAGS = -shared -undefined dynamic_lookup LDFLAGS = -shared -undefined dynamic_lookup -L/usr/local/lib -L/opt/homebrew/lib
LDFLAGS += -L/usr/local/lib -L/opt/homebrew/lib
# Try static first, fall back to dynamic # Core libraries
LIBS = -Wl,-search_paths_first \ LIBS = -lportaudio -lsndfile -lsamplerate
/usr/local/lib/libportaudio.a \
/usr/local/lib/libsndfile.a \ # macOS frameworks
/usr/local/lib/libsamplerate.a \ LIBS += -framework CoreAudio -framework AudioToolbox -framework AudioUnit
-framework CoreAudio -framework AudioToolbox -framework AudioUnit \ LIBS += -framework CoreFoundation -framework CoreServices
-framework CoreFoundation -framework CoreServices
OBJ_EXT = .o OBJ_EXT = .o
else ifeq ($(UNAME_S),Linux) else ifeq ($(UNAME_S),Linux)
# Linux with static linking # Linux with intelligent library detection
LIBNAME = libaudio.so LIBNAME = libaudio.so
LDFLAGS = -shared -static-libgcc
# Static link audio libraries, dynamic link system libraries # Check for pkg-config availability
LIBS = -Wl,-Bstatic \ PKG_CONFIG := $(shell command -v pkg-config 2> /dev/null)
-lportaudio \
-lsndfile \ # Core audio libraries (required)
-lsamplerate \ CORE_LIBS = -lportaudio -lsndfile
-lFLAC \
-lvorbisenc \ # Check for libsamplerate
-lvorbisfile \ ifeq ($(call check_lib,samplerate),yes)
-lvorbis \ CORE_LIBS += -lsamplerate
-logg \ CFLAGS += -DHAVE_SAMPLERATE
-Wl,-Bdynamic \ else
-lasound \ $(warning libsamplerate not found - building without sample rate conversion)
-ljack \ endif
-lpulse \
-lpulse-simple \ # Audio backend libraries (optional)
-pthread \ BACKEND_LIBS =
-lm \
-ldl # Check for ALSA
ifeq ($(call check_lib,alsa),yes)
BACKEND_LIBS += -lasound
CFLAGS += -DHAVE_ALSA
endif
# Check for PulseAudio
ifeq ($(call check_lib,libpulse),yes)
BACKEND_LIBS += -lpulse
CFLAGS += -DHAVE_PULSE
endif
ifeq ($(call check_lib,libpulse-simple),yes)
BACKEND_LIBS += -lpulse-simple
CFLAGS += -DHAVE_PULSE_SIMPLE
endif
# Check for JACK (optional)
ifeq ($(call check_lib,jack),yes)
BACKEND_LIBS += -ljack
CFLAGS += -DHAVE_JACK
endif
# Codec libraries (optional)
CODEC_LIBS =
ifeq ($(call check_lib,flac),yes)
CODEC_LIBS += -lFLAC
CFLAGS += -DHAVE_FLAC
endif
ifeq ($(call check_lib,vorbisenc),yes)
CODEC_LIBS += -lvorbisenc -lvorbisfile -lvorbis
CFLAGS += -DHAVE_VORBIS
endif
ifeq ($(call check_lib,ogg),yes)
CODEC_LIBS += -logg
CFLAGS += -DHAVE_OGG
endif
# System libraries
SYSTEM_LIBS = -lpthread -lm -ldl
# Combine all libraries
LIBS = $(CORE_LIBS) $(BACKEND_LIBS) $(CODEC_LIBS) $(SYSTEM_LIBS)
OBJ_EXT = .o OBJ_EXT = .o
else else
# Generic Unix fallback # Generic Unix fallback - minimal dependencies
LIBNAME = libaudio.so LIBNAME = libaudio.so
LIBS = -lportaudio -lsndfile -lpthread -lm
OBJ_EXT = .o OBJ_EXT = .o
endif endif
SOURCES = $(wildcard *.c) SOURCES = $(wildcard *.c)
# Object files with correct extension # Object files
ifneq (,$(findstring Windows,$(UNAME_S))) ifneq (,$(findstring Windows,$(UNAME_S)))
OBJECTS = $(SOURCES:.c=.obj) OBJECTS = $(SOURCES:.c=.obj)
else else
OBJECTS = $(SOURCES:.c=.o) OBJECTS = $(SOURCES:.c=.o)
endif endif
.PHONY: all clean install debug check-deps static .PHONY: all clean install debug check-deps list-libs minimal
all: $(LIBNAME) all: check-deps $(LIBNAME)
# Main build targets # Build targets
ifneq (,$(findstring Windows,$(UNAME_S))) ifneq (,$(findstring Windows,$(UNAME_S)))
$(LIBNAME): $(OBJECTS) $(LIBNAME): $(OBJECTS)
link $(LDFLAGS) /OUT:$@ $^ $(LIBS) link $(LDFLAGS) /OUT:$@ $^ $(LIBS)
@@ -126,10 +172,6 @@ $(LIBNAME): $(OBJECTS)
clean: clean:
-del /Q *.obj $(LIBNAME) 2>nul || rm -f $(OBJECTS) $(LIBNAME) -del /Q *.obj $(LIBNAME) 2>nul || rm -f $(OBJECTS) $(LIBNAME)
check-deps:
@echo "Checking for static libraries on Windows..."
@if exist "$(VCPKG_INSTALLATION_ROOT)\installed\x64-windows-static\lib\portaudio.lib" (echo Static PortAudio found!) else (echo Static PortAudio not found!)
else else
# Unix/Linux/macOS build rules # Unix/Linux/macOS build rules
$(LIBNAME): $(OBJECTS) $(LIBNAME): $(OBJECTS)
@@ -144,46 +186,74 @@ clean:
install: $(LIBNAME) install: $(LIBNAME)
sudo cp $(LIBNAME) /usr/local/lib/ sudo cp $(LIBNAME) /usr/local/lib/
sudo ldconfig 2>/dev/null || true sudo ldconfig 2>/dev/null || true
check-deps:
@echo "Checking for static libraries..."
@pkg-config --exists --static portaudio-2.0 || echo "Static PortAudio not found"
@pkg-config --exists --static sndfile || echo "Static libsndfile not found"
@find /usr/local/lib /usr/lib -name "libportaudio.a" 2>/dev/null || echo "No static portaudio found"
@find /usr/local/lib /usr/lib -name "libsndfile.a" 2>/dev/null || echo "No static sndfile found"
endif endif
# Development target with debug symbols # Check dependencies and show what will be used
debug: CFLAGS += $(if $(findstring Windows,$(UNAME_S)),/Zi,-g -DDEBUG) check-deps:
debug: $(LIBNAME) @echo "=== Dependency Check ==="
@echo "Target system: $(UNAME_S)"
@echo "Library name: $(LIBNAME)"
@echo "Compiler: $(CC)"
ifneq (,$(findstring MINGW,$(UNAME_S)))
@echo "=== MinGW Libraries ==="
@echo "Available static libraries:"
@ls /mingw64/lib/lib{portaudio,sndfile,samplerate,FLAC,vorbis*,ogg}.a 2>/dev/null || echo "None found"
@echo "Libraries to link: $(LIBS)"
else ifeq ($(UNAME_S),Linux)
@echo "=== Linux Package Check ==="
ifdef PKG_CONFIG
@echo "pkg-config available: yes"
@echo -n "PortAudio: "; pkg-config --exists portaudio-2.0 && echo "✓" || echo "✗"
@echo -n "libsndfile: "; pkg-config --exists sndfile && echo "✓" || echo "✗"
@echo -n "libsamplerate: "; pkg-config --exists samplerate && echo "✓" || echo "✗"
@echo -n "ALSA: "; pkg-config --exists alsa && echo "✓" || echo "✗"
@echo -n "PulseAudio: "; pkg-config --exists libpulse && echo "✓" || echo "✗"
@echo -n "JACK: "; pkg-config --exists jack && echo "✓" || echo "✗"
else
@echo "pkg-config not available"
endif
@echo "Libraries to link: $(LIBS)"
else
@echo "Libraries to link: $(LIBS)"
endif
# Target to build with maximum static linking # Show detected libraries
static: LDFLAGS += $(if $(findstring MINGW,$(UNAME_S)),-static,) list-libs:
static: $(LIBNAME) @echo "Core libraries: $(CORE_LIBS)"
@echo "Backend libraries: $(BACKEND_LIBS)"
@echo "Codec libraries: $(CODEC_LIBS)"
@echo "System libraries: $(SYSTEM_LIBS)"
@echo "All libraries: $(LIBS)"
# Build with only essential libraries (fallback)
minimal: override LIBS = -lportaudio -lsndfile -lpthread -lm
minimal: $(LIBNAME)
@echo "Built minimal version with basic dependencies only"
# Development target
debug: CFLAGS += -g -DDEBUG
debug: $(LIBNAME)
# Verification target # Verification target
verify: $(LIBNAME) verify: $(LIBNAME)
@echo "=== Library Information ===" @echo "=== Library Information ==="
@if [ "$(findstring MINGW,$(UNAME_S))" ]; then \ @file $(LIBNAME)
file $(LIBNAME); \ ifneq (,$(findstring MINGW,$(UNAME_S)))
echo "=== Dependencies ==="; \ @echo "=== Dependencies ==="
objdump -p $(LIBNAME) | grep "DLL Name:" || echo "No DLL dependencies (fully static)"; \ @objdump -p $(LIBNAME) | grep "DLL Name:" | head -10 || echo "No dependencies found"
elif [ "$(UNAME_S)" = "Linux" ]; then \ else ifeq ($(UNAME_S),Linux)
file $(LIBNAME); \ @echo "=== Dependencies ==="
echo "=== Dependencies ==="; \ @ldd $(LIBNAME) 2>/dev/null | head -10 || echo "Static build or no dependencies"
ldd $(LIBNAME) 2>/dev/null || echo "No shared library dependencies"; \ endif
else \
file $(LIBNAME); \
fi
help: help:
@echo "Available targets:" @echo "Available targets:"
@echo " all - Build the audio library (default)" @echo " all - Build the audio library (default)"
@echo " static - Build with maximum static linking" @echo " minimal - Build with minimal dependencies"
@echo " clean - Remove build artifacts" @echo " clean - Remove build artifacts"
@echo " install - Install library (Unix/Linux/macOS only)" @echo " install - Install library (Unix/Linux/macOS only)"
@echo " debug - Build with debug symbols" @echo " debug - Build with debug symbols"
@echo " check-deps- Check for required dependencies" @echo " check-deps- Check for required dependencies"
@echo " list-libs - Show detected library configuration"
@echo " verify - Verify built library and show dependencies" @echo " verify - Verify built library and show dependencies"
@echo " help - Show this help message" @echo " help - Show this help message"