#+title: Building or installing

I provide packages for a number of Linux distros. These packages are the
recommended method of installing mrcal. If you're interested in support for some
other Linux distro or some other distribution method or even a non-Linux OS,
send me a message. We can work something out.

* Installing from packages
:PROPERTIES:
:CUSTOM_ID: installing-from-packages
:END:

mrcal is included in recent versions of Debian and Ubuntu. So if you're running
at least Debian 12 (bookworm) or Ubuntu 22.04 (jammy), you can install with a
single command. For instance the commandline tools and the C development library
and the Python library can be installed with

#+begin_src sh
apt install mrcal libmrcal-dev python3-mrcal
#+end_src

The older distros will have older builds of mrcal. To get the most recent mrcal
packages, you can use the mrcal APT repository. I currently distribute packages
for

- Debian/trixie (13)
- Debian/bookworm (12)
- Debian/bullseye (11)
- Ubuntu/noble (24.04 LTS)
- Ubuntu/jammy (22.04 LTS)
- Ubuntu/focal (20.04 LTS)

=amd64= and =arm64= architectures only. To use these, add to your
=/etc/apt/sources.list=:

#+begin_example
deb [trusted=yes] http://mrcal.secretsauce.net/packages/DISTRO/public/ DISTRO main
#+end_example

where =DISTRO= is one of

- =trixie=
- =bookworm=
- =bulleye=
- =noble=
- =jammy=
- =focal=

Then, =apt update && apt install mrcal=. The chessboard corner finder, while not
strictly required, is needed if you're doing chessboard-based calibrations. =apt
install mrgingham=

* Building from source
If you cannot use the packages for whatever reason, you must build from source.
This isn't /difficult/, but requires you to obtain all the dependencies. They're
listed in the =Build-Depends= section of the [[https://salsa.debian.org/science-team/mrcal/-/blob/master/debian/control][debian package definition]]. Most of
these are available in most distros. Things that may not be:

- [[https://www.github.com/dkogan/mrbuild][=mrbuild=]]: the build system. If you can't get it from the package manager,
  just run =make=, and follow the printed message to get a local copy of
  =mrbuild=. Version 1.14 or above is required.

- [[https://github.com/dkogan/libdogleg/][=libdogleg-dev=]]: the optimization library. You need at least version 0.15.3.

- [[https://github.com/dkogan/vnlog/][=vnlog=]]: the toolkit to manipulate textual tables. You only /need/ this for
  the test suite. There's nothing to build. Simply downloading the sources and
  pointing the =PATH= there is sufficient.

- [[https://github.com/dkogan/numpysane/][=python3-numpysane=]]: The make-numpy-reasonable library. You absolutely need at
  least version 0.35. Available in the usual places Python libraries live. This
  is a python-only library. Simply downloading the sources and pointing the
  =PYTHONPATH= there is sufficient.

- [[https://github.com/dkogan/gnuplotlib/][=python3-gnuplotlib=]]: The plotting library used in all the visualizations. You
  need at least version 0.38. Available in the usual places Python libraries
  live. This is a python-only library. Simply downloading the sources and
  pointing the =PYTHONPATH= there is sufficient.

- [[https://github.com/dkogan/mrgingham/][=mrgingham=]]: the chessboard corner finder. This isn't strictly a requirement -
  any corner finder can be used. If you want to use this one (and you can't use
  the packages), you need to build it.

- [[https://re2c.org/][=re2c=]]: parser-generator for the C code to parse =.cameramodel= files. At
  least version 2 is required.

- [[https://github.com/yaml/pyyaml][=python3-yaml=]]: yaml parser used for the OpenCV, Kalibr model reading

- [[https://pyfltk.sourceforge.io/][=python3-fltk=]]: Python bindings for the [[https://www.fltk.org/][FLTK]] GUI toolkit. Optional. Most
  notably used in the [[file:mrcal-stereo.html][=mrcal-stereo --viz stereo=]] visualizer, but will be used
  more widely over time.

- [[https://github.com/dkogan/GL_image_display][=python3-gl-image-display=]]: an image widget for FLTK. Optional. Used together
  with =python3-fltk=

- [[https://www.cvlibs.net/software/libelas/][=libelas-dev=]]: the ELAS stereo matcher. Used as an option in the
  [[file:mrcal-stereo.html][=mrcal-stereo=]] tool. Optional.

Once these are all downloaded and built (where needed), we can talk about
building mrcal. The build-time executables (=re2c=) must be found in the =PATH=,
the Python libraries in =PYTHONPATH=, and the C headers and libraries must be
findable via the flags in =CFLAGS= and =LDFLAGS= respectively. Anything that
hasn't been installed to a standard location must be pointed to via the
environment. So to build:

#+begin_src sh
export PATH=$PATH:extra_path_to_executables
export PYTHONPATH=extra_path_to_python_libraries

CFLAGS=-Iextra_path_to_c_headers LDFLAGS="-Lextra_path_to_libraries -Wl,-rpath=extra_path_to_libraries" make
#+end_src

If everything has been installed to a standard location, you just run =make=
without any of the extra stuff. The build should then complete successfully, and
the test suite should pass:

#+begin_src sh
make test-nosampling
#+end_src

If stuff doesn't work, feel free to bug me.

* code                                                             :noexport:
** To add a new distro
*** On the server
#+begin_src sh
distro=noble
V=24.04

mkdir -p /var/www/mrcal/packages/$distro/public/conf

< /var/www/mrcal/packages/jammy/public/conf/distributions \
perl -pe "s/jammy/$distro/g; s/22.04/$V/g;" \
> /var/www/mrcal/packages/$distro/public/conf/distributions
#+end_src

** Building

To native-build (amd64) any dependency or mrcal itself:

#+begin_src sh
for distro (bullseye bookworm trixie) {
    perl -a -p -i -e 'if($. == 1) { $F[1] =~ s/-([0-9]+).*\)/-$1'$distro'1)/; $F[2] = "'$distro';"; $_ = join(" ",@F) . "\n"; }' debian/changelog;

    DEB_BUILD_OPTIONS=nocheck \
    sbuild \
      --host=amd64 \
      --arch-any \
      --arch-all \
      --source \
      -d ${distro} \
      --anything-failed-commands '%s' \
      --extra-repository="deb [trusted=yes] http://mrcal.secretsauce.net/packages/$distro/public/ $distro main" && \
    dput -u digitalocean_mrcal ../*${distro}*.changes(om[1])
}
#+end_src

I think I need to do ubuntu separately because they have other suites I need
/and/ for some reason they put different arches on different domains. See
https://lists.debian.org/debian-cross/2025/10/msg00010.html

#+begin_src sh
for distro (focal jammy noble) {
    perl -a -p -i -e 'if($. == 1) { $F[1] =~ s/-([0-9]+).*\)/-$1'$distro'1)/; $F[2] = "'$distro';"; $_ = join(" ",@F) . "\n"; }' debian/changelog;

    DEB_BUILD_OPTIONS=nocheck \
    sbuild \
      --host=amd64 \
      --arch-any \
      --arch-all \
      --source \
      -d ${distro} \
      --anything-failed-commands '%s' \
      --chroot-setup-commands "echo \"
deb [trusted=yes arch=amd64] http://archive.ubuntu.com/ubuntu/     ${distro}          main restricted universe multiverse
deb [trusted=yes arch=amd64] http://archive.ubuntu.com/ubuntu/     ${distro}-security main restricted universe multiverse
deb [trusted=yes arch=amd64] http://archive.ubuntu.com/ubuntu/     ${distro}-updates  main restricted universe multiverse
deb [trusted=yes arch=amd64] http://archive.ubuntu.com/ubuntu/     ${distro}-proposed main restricted universe multiverse
\" > \$1/etc/apt/sources.list" \
      --extra-repository="deb [trusted=yes] http://mrcal.secretsauce.net/packages/$distro/public/ $distro main" && \
    dput -u digitalocean_mrcal ../*${distro}*.changes(om[1])
}
#+end_src

To cross-build for arm64:

Distros prior to numpy 2 (everything that isn't trixie) needs this patch:

#+begin_src diff
diff --git a/debian/control b/debian/control
index 374f20f..53e5d37 100644
--- a/debian/control
+++ b/debian/control
@@ -20,13 +20,12 @@ Build-Depends:
  liblist-moreutils-perl:native,
  vnlog,
  chrpath,
  re2c (>= 2),
  python3-all-dev:any,
  libpython3-all-dev,
- python3-numpy-dev,
 # Needed for *-genpywrap.py. Need arch:build for tests, but testing while
 # cross-building doesn't work anyway
  python3-numpy:native,
 # Need this even when not running tests: *-genpywrap.py uses npsp
 # Need at least 0.37 for the interactive pixel picking in mrcal-stereo to
 # work
diff --git a/debian/rules b/debian/rules
index bf3f3d3..ac91b61 100755
--- a/debian/rules
+++ b/debian/rules
@@ -7,12 +7,13 @@ export VERSION_USE_LATEST_TAG  = 1
 %:
 	dh $@ --with python3
 
 # I build the python libraries for all the available python versions. The
 # non-Python stuff shouldn't be rebuilt because Make should see that it's
 # up-to-date
+override_dh_auto_build: CFLAGS+=-I/usr/lib/python3/dist-packages/numpy/core/include
 override_dh_auto_build:
 	for v in `py3versions -s | sed s/python//g`; do		\
 	  rm -f *pywrap*.o;					\
 	  PYTHON_VERSION_FOR_EXTENSIONS=$$v dh_auto_build;	\
 	done
 
#+end_src

#+begin_src sh
for distro (bullseye bookworm trixie) {
    perl -a -p -i -e 'if($. == 1) { $F[1] =~ s/-([0-9]+).*\)/-$1'$distro'1)/; $F[2] = "'$distro';"; $_ = join(" ",@F) . "\n"; }' debian/changelog;

    DEB_BUILD_OPTIONS=nocheck \
    sbuild \
      --host=arm64 \
      --arch-any \
      --no-arch-all \
      --no-source \
      --profiles=nocheck,cross \
      -d ${distro} \
      --anything-failed-commands '%s' \
      --extra-repository="deb [trusted=yes] http://mrcal.secretsauce.net/packages/$distro/public/ $distro main" && \
    dput -u digitalocean_mrcal ../*${distro}*.changes(om[1])
}

for distro (focal jammy noble) {
    perl -a -p -i -e 'if($. == 1) { $F[1] =~ s/-([0-9]+).*\)/-$1'$distro'1)/; $F[2] = "'$distro';"; $_ = join(" ",@F) . "\n"; }' debian/changelog;

    DEB_BUILD_OPTIONS=nocheck \
    sbuild \
      --host=arm64 \
      --arch-any \
      --no-arch-all \
      --no-source \
      --profiles=nocheck,cross \
      -d ${distro} \
      --anything-failed-commands '%s' \
      --chroot-setup-commands "echo \"
deb [trusted=yes arch=amd64] http://archive.ubuntu.com/ubuntu/     ${distro}          main restricted universe multiverse
deb [trusted=yes arch=amd64] http://archive.ubuntu.com/ubuntu/     ${distro}-security main restricted universe multiverse
deb [trusted=yes arch=amd64] http://archive.ubuntu.com/ubuntu/     ${distro}-updates  main restricted universe multiverse
deb [trusted=yes arch=amd64] http://archive.ubuntu.com/ubuntu/     ${distro}-proposed main restricted universe multiverse
deb [trusted=yes arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ ${distro}          main restricted universe multiverse
deb [trusted=yes arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ ${distro}-security main restricted universe multiverse
deb [trusted=yes arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ ${distro}-updates  main restricted universe multiverse
deb [trusted=yes arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ ${distro}-proposed main restricted universe multiverse
\" > \$1/etc/apt/sources.list" \
      --extra-repository="deb [trusted=yes] http://mrcal.secretsauce.net/packages/$distro/public/ $distro main" && \
    dput -u digitalocean_mrcal ../*${distro}*.changes(om[1])
}
#+end_src
