# Build libfec on Linux, macOS and on/for 64-bit Windows with MinGW-w64. # # make build for the host platform # make linux build Linux libraries # make macos build macOS libraries # make windows build Windows libraries (cross-build on Linux/macOS) # make static build only the static library # make shared build only the shared library # make clean remove obj/ and lib/ ifeq ($(OS),Windows_NT) HOST_OS := windows else ifeq ($(shell uname -s),Darwin) HOST_OS := macos else HOST_OS := linux endif BUILD ?= $(HOST_OS) OBJROOT := obj OUTROOT := lib OBJDIR := $(OBJROOT)/$(BUILD) OUTDIR := $(OUTROOT)/$(BUILD) GENDIR := $(OBJDIR)/generated TOOLDIR := $(OBJROOT)/tools/$(HOST_OS) # Command-line assignments (for example CC=clang) still take precedence. ifeq ($(BUILD),windows) ifeq ($(HOST_OS),windows) CROSS_PREFIX ?= else CROSS_PREFIX ?= x86_64-w64-mingw32- endif ifeq ($(origin CC),default) CC := $(CROSS_PREFIX)gcc endif ifeq ($(origin AR),default) AR := $(CROSS_PREFIX)ar endif ifeq ($(origin RANLIB),undefined) RANLIB := $(CROSS_PREFIX)ranlib endif SHARED_LIB := $(OUTDIR)/libfec.dll IMPORT_LIB := $(OUTDIR)/libfec.dll.a SHARED_FLAGS := -shared -Wl,--out-implib,$(IMPORT_LIB) PIC_CFLAGS := else ifeq ($(BUILD),linux) ifeq ($(origin CC),default) CC := gcc endif ifeq ($(origin AR),default) AR := ar endif ifeq ($(origin RANLIB),undefined) RANLIB := ranlib endif SHARED_LIB := $(OUTDIR)/libfec.so IMPORT_LIB := SHARED_FLAGS := -shared -Wl,-soname,libfec.so PIC_CFLAGS := -fPIC else ifeq ($(BUILD),macos) ifeq ($(origin CC),default) CC := cc endif ifeq ($(origin AR),default) AR := ar endif ifeq ($(origin RANLIB),undefined) RANLIB := ranlib endif SHARED_LIB := $(OUTDIR)/libfec.dylib IMPORT_LIB := SHARED_FLAGS := -dynamiclib -install_name libfec.dylib PIC_CFLAGS := -fPIC else $(error Unsupported BUILD='$(BUILD)'; use BUILD=linux, BUILD=macos or BUILD=windows) endif ifeq ($(origin HOSTCC),undefined) HOSTCC := gcc endif CPPFLAGS ?= CFLAGS ?= -O2 -Wall -Wno-implicit-int -Wno-implicit-function-declaration -Wno-int-conversion LDFLAGS ?= LDLIBS ?= -lm HOSTCFLAGS ?= -O2 STATIC_LIB := $(OUTDIR)/libfec.a TEST_EXEEXT := $(if $(filter windows,$(BUILD)),.exe) SOURCES := \ cpu_mode_generic.c fec.c sim.c \ viterbi27.c viterbi27_port.c \ viterbi29.c viterbi29_port.c \ viterbi615.c viterbi615_port.c \ encode_rs_char.c encode_rs_int.c encode_rs_8.c \ decode_rs_char.c decode_rs_int.c decode_rs_8.c \ init_rs_char.c init_rs_int.c \ encode_rs_ccsds.c decode_rs_ccsds.c \ dotprod.c dotprod_port.c \ peakval.c peakval_port.c \ sumsq.c sumsq_port.c GENERATED_SOURCES := $(GENDIR)/ccsds_tab.c $(GENDIR)/ccsds_tal.c OBJECTS := $(addprefix $(OBJDIR)/,$(SOURCES:.c=.o)) \ $(OBJDIR)/ccsds_tab.o $(OBJDIR)/ccsds_tal.o TESTS := vtest27 vtest29 vtest615 rstest dtest sumsq_test peaktest TEST_PROGRAMS := $(addprefix $(OUTDIR)/,$(addsuffix $(TEST_EXEEXT),$(TESTS))) TEST_OBJECTS := $(addprefix $(OBJDIR)/,$(addsuffix .o,$(TESTS))) DEPS := $(OBJECTS:.o=.d) $(TEST_OBJECTS:.o=.d) GEN_CCSDS := $(TOOLDIR)/gen_ccsds$(if $(filter windows,$(HOST_OS)),.exe) GEN_TAL := $(TOOLDIR)/gen_ccsds_tal$(if $(filter windows,$(HOST_OS)),.exe) HOST_GEN_OBJECTS := $(TOOLDIR)/gen_ccsds.o $(TOOLDIR)/init_rs_char.o .DEFAULT_GOAL := all .SECONDARY: $(TEST_OBJECTS) .PHONY: all build linux macos windows static shared test check-tools clean all: build build: check-tools static shared static: $(STATIC_LIB) shared: $(SHARED_LIB) ifeq ($(BUILD),$(HOST_OS)) test: $(TEST_PROGRAMS) $(OUTDIR)/vtest27$(TEST_EXEEXT) -e 3.0 -n 1000 -v $(OUTDIR)/vtest27$(TEST_EXEEXT) $(OUTDIR)/vtest29$(TEST_EXEEXT) -e 2.5 -n 1000 -v $(OUTDIR)/vtest29$(TEST_EXEEXT) $(OUTDIR)/vtest615$(TEST_EXEEXT) -e 1.0 -n 100 -v $(OUTDIR)/vtest615$(TEST_EXEEXT) $(OUTDIR)/rstest$(TEST_EXEEXT) $(OUTDIR)/dtest$(TEST_EXEEXT) $(OUTDIR)/sumsq_test$(TEST_EXEEXT) $(OUTDIR)/peaktest$(TEST_EXEEXT) else test: @echo "Error: tests can only run for the host platform ($(HOST_OS)); requested BUILD=$(BUILD)." @exit 1 endif # Explicit platform aliases are recursive so their toolchains and paths are # resolved with the requested BUILD value from the start. linux: $(MAKE) BUILD=linux build macos: $(MAKE) BUILD=macos build windows: $(MAKE) BUILD=windows build check-tools: @command -v $(CC) >/dev/null 2>&1 || { \ echo "Error: compiler '$(CC)' was not found."; \ echo "For Windows builds install MinGW-w64 or use an MSYS2 MinGW 64-bit shell."; \ exit 1; \ } @command -v $(HOSTCC) >/dev/null 2>&1 || { \ echo "Error: host compiler '$(HOSTCC)' was not found."; \ exit 1; \ } $(STATIC_LIB): $(OBJECTS) | $(OUTDIR) $(AR) rcs $@ $^ $(RANLIB) $@ $(SHARED_LIB): $(OBJECTS) | $(OUTDIR) $(CC) $(SHARED_FLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(OUTDIR)/%$(TEST_EXEEXT): $(OBJDIR)/%.o $(STATIC_LIB) | $(OUTDIR) $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(OBJDIR)/%.o: %.c | $(OBJDIR) $(CC) $(CPPFLAGS) $(CFLAGS) $(PIC_CFLAGS) -MMD -MP -I. -c -o $@ $< $(OBJDIR)/ccsds_tab.o: $(GENDIR)/ccsds_tab.c | $(OBJDIR) $(CC) $(CPPFLAGS) $(CFLAGS) $(PIC_CFLAGS) -MMD -MP -I. -c -o $@ $< $(OBJDIR)/ccsds_tal.o: $(GENDIR)/ccsds_tal.c | $(OBJDIR) $(CC) $(CPPFLAGS) $(CFLAGS) $(PIC_CFLAGS) -MMD -MP -I. -c -o $@ $< $(GENDIR)/ccsds_tab.c: $(GEN_CCSDS) | $(GENDIR) $(GEN_CCSDS) > $@ $(GENDIR)/ccsds_tal.c: $(GEN_TAL) | $(GENDIR) $(GEN_TAL) > $@ $(GEN_CCSDS): $(HOST_GEN_OBJECTS) | $(TOOLDIR) $(HOSTCC) -o $@ $^ $(GEN_TAL): gen_ccsds_tal.c | $(TOOLDIR) $(HOSTCC) $(HOSTCFLAGS) -I. -o $@ $< $(TOOLDIR)/gen_ccsds.o: gen_ccsds.c char.h rs-common.h fec.h | $(TOOLDIR) $(HOSTCC) $(HOSTCFLAGS) -I. -c -o $@ $< $(TOOLDIR)/init_rs_char.o: init_rs_char.c char.h rs-common.h init_rs.h fec.h | $(TOOLDIR) $(HOSTCC) $(HOSTCFLAGS) -I. -c -o $@ $< $(OBJDIR) $(OUTDIR) $(GENDIR) $(TOOLDIR): mkdir -p $@ clean: -rm -rf $(OBJROOT) $(OUTROOT) -include $(DEPS)