1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
|
include choose_mrbuild.mk
include $(MRBUILD_MK)/Makefile.common.header
# "0" or undefined means "false"
# everything else means "true"
# libelas stereo matcher. Available in Debian/non-free. I don't want to depend
# on anything in non-free, so I default to not using libelas
USE_LIBELAS ?= 0
# If true, we compile libstb into image.o and libmrcal.so. If false, we link to
# an external libstb.so. We default to building it ourselves on macos and using
# the library otherwise
USE_LOCAL_STB_IMPLEMENTATION ?= $(COND_DARWIN)
# convert all USE_XXX:=0 to an empty string
$(foreach v,$(filter USE_%,$(.VARIABLES)),$(if $(filter 0,${$v}),$(eval $v :=)))
# to print them all: $(foreach v,$(filter USE_%,$(.VARIABLES)),$(warning $v = '${$v}'))
PROJECT_NAME := mrcal
ABI_VERSION := 5
TAIL_VERSION := 0
VERSION = $(VERSION_FROM_PROJECT)
LIB_SOURCES += \
mrcal.c \
opencv.c \
uncertainty.c \
image.c \
stereo.c \
poseutils.c \
poseutils-opencv.c \
poseutils-uses-autodiff.cc \
triangulation.cc \
cahvore.cc \
traverse-sensor-links.c \
heap.cc \
python-cameramodel-converter.c
ifneq (${USE_LIBELAS},) # using libelas
LIB_SOURCES := $(LIB_SOURCES) stereo-matching-libelas.cc
endif
ifneq ($(USE_LOCAL_STB_IMPLEMENTATION),)
image.o: CFLAGS += -DSTB_IMAGE_IMPLEMENTATION=1
endif
BIN_SOURCES += \
test/test-gradients.c \
test/test-cahvor.c \
test/test-lensmodel-string-manipulation.c \
test/test-parser-cameramodel.c \
test/test-heap.c
LDLIBS += -ldogleg $(if $(USE_LOCAL_STB_IMPLEMENTATION),,-lstb) -lpng -ljpeg -llapack
ifneq (${USE_LIBELAS},) # using libelas
LDLIBS += -lelas
endif
CFLAGS += --std=gnu99
CCXXFLAGS += -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-parameter -Wno-missing-braces
$(patsubst %.c,%.o,$(shell grep -l '#include .*minimath\.h' *.c */*.c)): minimath/minimath_generated.h
minimath/minimath_generated.h: minimath/minimath_generate.pl
./$< > $@.tmp && mv $@.tmp $@
EXTRA_CLEAN += minimath/minimath_generated.h
DIST_INCLUDE += \
mrcal.h \
image.h \
internal.h \
basic-geometry.h \
poseutils.h \
triangulation.h \
types.h \
stereo.h \
heap.h \
python-cameramodel-converter.h
DIST_BIN := \
mrcal-calibrate-cameras \
mrcal-convert-lensmodel \
mrcal-show-distortion-off-pinhole \
mrcal-show-splined-model-correction \
mrcal-show-projection-uncertainty \
mrcal-show-projection-diff \
mrcal-show-model-resolution \
mrcal-show-stereo-pair-diff \
mrcal-reproject-points \
mrcal-reproject-image \
mrcal-graft-models \
mrcal-to-cahvor \
mrcal-from-cahvor \
mrcal-to-kalibr \
mrcal-from-kalibr \
mrcal-from-ros \
mrcal-show-geometry \
mrcal-show-valid-intrinsics-region \
mrcal-is-within-valid-intrinsics-region \
mrcal-triangulate \
mrcal-cull-corners \
mrcal-show-residuals-board-observation \
mrcal-show-residuals \
mrcal-stereo
# generate manpages from distributed binaries, and ship them. This is a hoaky
# hack because apparenly manpages from python tools is a crazy thing to want to
# do
DIST_MAN := $(addsuffix .1,$(DIST_BIN))
# if using an older mrbuild SO won't be defined, and we need it
SO ?= so
# parser
cameramodel-parser_GENERATED.c: cameramodel-parser.re mrcal.h
re2c $< > $@.tmp && mv $@.tmp $@
LIB_SOURCES += cameramodel-parser_GENERATED.c
EXTRA_CLEAN += cameramodel-parser_GENERATED.c
cameramodel-parser_GENERATED.o: CCXXFLAGS += -fno-fast-math
ALL_NPSP_EXTENSION_MODULES := $(patsubst %-genpywrap.py,%,$(wildcard *-genpywrap.py))
ifeq (${USE_LIBELAS},) # not using libelas
ALL_NPSP_EXTENSION_MODULES := $(filter-out elas,$(ALL_NPSP_EXTENSION_MODULES))
endif
ALL_PY_EXTENSION_MODULES := _mrcal $(patsubst %,_%_npsp,$(ALL_NPSP_EXTENSION_MODULES))
%/:
mkdir -p $@
######### python stuff
# python-cameramodel-converter contains a utility function for external Python
# wrapping. I link this into libmrcal.so, but libmrcal.so does NOT link with
# libpython. 99% of the usage of libmrcal.so will not use this, so it should
# work without libpython. People using this function will be doing so as part of
# PyArg_ParseTupleAndKeywords(), so they will be linking to libpython anyway.
# Thus I weaken all the references to libpython here. c_build_rule is the
# default logic in mrbuild
#
# This is a DEEP rabbithole. With Debian/trixie (released summer 2025) objcopy
# --weaken works to weaken the symbols after compiling. With older objcopy (not
# sure which), the objcopy command completes successfully, but it doesn't
# actually weaken the symbols. I thus run nm to find the non-weakened symbols;
# if any remain, I recompile, explicitly telling the linker about the weak
# linkage on these symbols. I can't do this on the first pass because before
# compiling even once I don't know which Py symbols I'm going to get (some are
# generated by the Python internals).
#
# On macos there're more details: there is no objcopy and nm works slightly
# differently and the linker has to be explicitly be told to not worry about the
# undefined symbols. Here I allow objcopy to fail (the symbols will be weakened
# on the second pass, as with a tool-old objcopy), and I make sure to invoke nm
# in a way that will work on both macos and Linux (the options and output
# formatting varies a bit).
ifneq ($(COND_DARWIN),)
libmrcal.$(SO): LDFLAGS += -Wl,-undefined,dynamic_lookup
endif
python-cameramodel-converter.o: CFLAGS += -fno-lto # LTO breaks the WEAKEN_PY_REFS thing, so I make sure to turn it off
python-cameramodel-converter.o: %.o:%.c
$(c_build_rule) && mv $@ _$@
$(OBJCOPY) --wildcard --weaken-symbol='Py*' --weaken-symbol='_Py*' _$@ 2>&1 || true
$(NM) -u _$@ | awk '$$1 != "w" && $$NF ~ "Py" { print $$NF }' > python-cameramodel-converter-py-symbol-refs
if [ -s python-cameramodel-converter-py-symbol-refs ]; then \
< python-cameramodel-converter-py-symbol-refs \
awk 'BEGIN {ORS=""; print "#define PY_REFS(_) " } {print "_("$$1") "} ' \
> python-cameramodel-converter-py-symbol-refs.h \
&& \
$(c_build_rule) -DWEAKEN_PY_REFS; \
else \
mv _$@ $@; \
fi
EXTRA_CLEAN += \
python-cameramodel-converter-py-symbol-refs \
python-cameramodel-converter-py-symbol-refs.h \
_*python-cameramodel-converter.o
%-npsp-pywrap-GENERATED.c: %-genpywrap.py
python3 $< > $@.tmp && mv $@.tmp $@
mrcal/_%_npsp$(PY_EXT_SUFFIX): %-npsp-pywrap-GENERATED.o libmrcal.$(SO) libmrcal.$(SO).${ABI_VERSION}
$(PY_MRBUILD_LINKER) $(PY_MRBUILD_LDFLAGS) $(LDFLAGS) $< -lmrcal -o $@
ALL_NPSP_C := $(patsubst %,%-npsp-pywrap-GENERATED.c,$(ALL_NPSP_EXTENSION_MODULES))
ALL_NPSP_O := $(patsubst %,%-npsp-pywrap-GENERATED.o,$(ALL_NPSP_EXTENSION_MODULES))
ALL_NPSP_SO := $(patsubst %,mrcal/_%_npsp$(PY_EXT_SUFFIX),$(ALL_NPSP_EXTENSION_MODULES))
EXTRA_CLEAN += $(ALL_NPSP_C)
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95635
$(ALL_NPSP_O): CFLAGS += -Wno-array-bounds
mrcal-pywrap.o: $(addsuffix .h,$(wildcard *.docstring))
mrcal/_mrcal$(PY_EXT_SUFFIX): mrcal-pywrap.o libmrcal.$(SO) libmrcal.$(SO).${ABI_VERSION}
$(PY_MRBUILD_LINKER) $(PY_MRBUILD_LDFLAGS) $(LDFLAGS) $< -lmrcal -lsuitesparseconfig -o $@
PYTHON_OBJECTS := mrcal-pywrap.o python-cameramodel-converter.o $(ALL_NPSP_O)
$(PYTHON_OBJECTS): CFLAGS += $(PY_MRBUILD_CFLAGS)
# The python libraries (compiled ones and ones written in python) all live in
# mrcal/
DIST_PY3_MODULES := mrcal
all: mrcal/_mrcal$(PY_EXT_SUFFIX) $(ALL_NPSP_SO)
EXTRA_CLEAN += mrcal/*$(PY_EXT_SUFFIX)
TESTS_ALL_TARGETS := test-all test-nosampling test-triangulation-uncertainty test-external-data
$(TESTS_ALL_TARGETS): all
./test.sh $@
.PHONY: $(TESTS_ALL_TARGETS)
test:
@echo "Which test set should we run? I know about '$(TESTS_ALL_TARGETS)'" > /dev/stderr; false
.PHONY: test
include Makefile.doc
include $(MRBUILD_MK)/Makefile.common.footer
# to work with mrbuild < 1.14
OBJCOPY ?= objcopy
|