= Building GPSD from source
:date: 08 May 2025
:description: Steps for Building GPSD from source
:docinfodir: www
:keywords: GPSD, GPS, installation
:robots: index,follow
:sectlinks:
:toc: macro

include::www/inc-menu.adoc[]

This is a guide to building GPSD from a bare source tree.  It includes
guidance on how to cross-build the package.

Some hints for people building binary packages are in
packaging/README.PACKAGERS.

(This file is marked up in asciidoc.)

== Quick start

You can download the most recent development snapshot from:
https://gitlab.com/gpsd/gpsd/tree/master

You can download the latest gpsd tarball from:
http://download.savannah.gnu.org/releases/gpsd/

Under Linux, assuming you have all your build prerequisites in place,
these lines will do, and need to be run as root:

   # become root, don't forget the dash ('-')
   su -
   tar -xzf gpsd-X.YY.tar.gz
   cd gpsd-X.YY
   scons && scons check
   # if that passes, and you want udev support, not recommended:
   scons udev-install

If you get any errors, you need to read the detailed instructions that follow.

If 'scons' fails, it is possible that your target system has moved to
Python 3 and removed the program 'python'.  Python.org says that if
you have an installed Python, there should be a program in your path
called 'python'.  This is specified in PEP 394.  This rule is not always
followed.  You can work around this by linking python3 to python like
this

    ln -s /usr/bin/python3 /usr/bin/python

Both 'scons' and 'gpsd' work fine on either Python 2 or Python 3.  Which
python you have installed should be transparent to the user, if python
is installed correctly.

Occasionally, builds may fail in completely bizarre ways due to a
corrupted scons database.  This seems to relate to ^Cing the build at
an inopportune moment.  If you suspect that, see "Reverting to a clean
state" below and then try again.

== Supported platforms

Native-build success should be expected on the following platforms,
provided you have the prerequisites listed in the next section
installed:

* Any desktop or server Linux distribution.
* OpenWRT and derivatives such as CeroWRT.
* FreeBSD, NetBSD, OpenBSD
* Android, using the official Google toolchain from the NDK

We consider failure to build and function on any of these platforms a
serious bug; if you encounter it, please complain on the development
list <gpsd-dev@nongnu.org>.

Port difficulty to any system conforming to POSIX-2001.1 should be minimal.

A Cygwin port is in progress but not complete.

Cross-compilation to embedded Linuxes (in addition to the OpenWRT family)
is usually fairly straightforward. An illustrative build transcript
is included at the end of this file.

== Check your build prerequisites

Necessary components for any build:

|============================================================================
|C compiler                    | gpsd and client library are written in C
|scons                         | for executing the build recipe
|Python2.x(x>=6) or 3.y(y>=2)  | for scons and some helper scripts
|============================================================================

On Gentoo, a basic build only requires this package:

|============================================================================
|dev-build/scons               | for executing the build recipe
|============================================================================

=== C compiler

C99 conformance is required in the compiler. The C code depends on one
C11 feature (supported by gcc, clang, and pretty much any C compiler
that also speaks C++): anonymous unions.  We could eliminate these,
but the cost would be source-level interface breakage if we have to
move certain structure members in and out of unions.

Some portions of the code using shared-memory segments are improved by
the C11 stdatomic.h features for lockless concurrency.  These are: the
SHM export mode in shmexport.c, the code for writing clock corrections
to NTP in ntpshmwrite.c, and the code for reading NTP corrections in
ntpshmread.c. These features have been supported in gcc since 4.7 and
clang since 3.1.

GPSD is normally built and tested with gcc. Do not compile with a version
older than 4.1.1; there are several known issues with older versions,
including (a) non-standards-conformant floating-point generation that
messes up regression testing, (b) a compiler bug affecting RTCM2 code
generation, (c)  the option -Wno-missing-field-initializers is
unavailable, leading to a flood of warnings (this is due to generated
code and cannot be fixed).

clang produces a gpsd that passes all regression tests.

If you get a build failure including the text "error adding symbols:
DSO missing from command line" or the complaint "ERROR: CC doesn't
work", you nay have tripped over stale data in the builder's
configuration cache.  Clean the directory with "scons -c" then manually
remove .sconsign.*dblite and retry your build.

=== Python

You will need Python 2.x at minor version 6 or later or Python 3 at
at minor version 3 or later.

While Python is required to build GPSD from source (the build uses
some code generators in Python), it is not required to run the service
daemon.  In particular, you can cross-compile onto an embedded system
without having to take Python with you.

scons finds the python used for scons separately from the python that
should be used for the target.  It seems to look for the target python
as "python", which as above is supposed to exist per python norms.
However, some packaging systems avoid a bare python, preferring to
bind a program to a particular release as it is built.  On systems
without a "python" command, invoking scons as:
  scons target_python=python3.7
seems to help.

You will need both basic Python and (if your package system makes the
distinction) the Python development package used for building C
extensions.  Usually these are called "python" and "python-dev". You
will know you are missing the latter if your compilation fails
because of a missing Python.h.

The xgps and xgpsspeed clients will only be installed if these Python
extensions are installed:

|===========================================================================
|python-gi          | Python bindings for gobject-introspection libraries
|python-gi-cairo    | Python bindings for Cairo toolkit under GI
|===========================================================================

On Gentoo systems those packages are named:
|============================================================================
|dev-python/pygobject
|dev-python/pycairo
|============================================================================

The ubxtool and zerk clients will only be usable in direct-serial mode
if this Python extension is installed:

|===========================================================================
|pyserial           | Python Serial Port extension
|===========================================================================

On Gentoo systems that package is named:
|============================================================================
|dev-python/pyserial
|============================================================================

The *gpsplot( client requires Matplotlib to do its job of creating dynamic
plots.

On Gentoo systems that package is named:
|============================================================================
|dev-python/matplotlib
|============================================================================

=== Scons

You will need scons version 2.3.0 (from 2013-03-02) or later to build the code.
(Note that there is no evidence of recent testing of scons older than about 3.1.)

=== Optional build components

Having the following optional components on your system will enable
various additional capabilities and extensions:

|============================================================================
|C++ compiler     | allows building libgpsmm C++ wrapper for client library
|Qt 4.53+         | allows building libQgpsmm C++ wrapper for client library
|(n)curses        | curses screen-painting library, used by cgps and gpsmon
|pps-tools        | adds support for the KPPS API, for improved timing
|libusb           | Userspace access to USB devices
|dbus             | D-Bus support
|============================================================================

If you have libusb-1.0.0 or later, the GPSD build will autodetect
this and use it to discover Garmin USB GPSes, rather than groveling
through /proc/bus/usb/devices (which has been deprecated by the
Linux kernel team).

On Gentoo systems those packages are named:

|=============================================================================
|dev-qt/qtcore       | Basic Qt
|dev-qt/qtnetwork    | Qt network components
|sys-libs/ncurses    | curses screen-painting library, used by cgps and gpsmon
|net-misc/pps-tools  | adds support for the KPPS API, for improved timing
|virtual/libusb      | Userspace access to USB devices
|sys-apps/dbus       | D-Bus
|=============================================================================

Debian/Ubuntu, and Fedora/RHEL, derived systems often split packages
into binary, and development packages. Raspbian is Debian derived. This
does not apply to Gentoo derived systems.

These development packages usually have a "-dev" suffix. Installing the
development package usually installs the binary package for you.

The development Debian/Ubuntu/Raspbian packages are:

|==============================================================================
|libncurses5-dev      | curses screen-painting library, used by cgps and gpsmon
|libusb-1.0-0-dev     | userspace USB programming library development files
|libdbus-1-dev        | D-Bus Development package
|==============================================================================

Newer Ubuntu (24 and up?) changed the ncurses version:
|==============================================================================
|libncurses6-dev      | curses screen-painting library, used by cgps and gpsmon
|==============================================================================

Debian 12 uses:
|==============================================================================
|libncurses-dev       | curses screen-painting library, used by cgps and gpsmon
|==============================================================================

The development Fedora/RHEL packages are:

|==============================================================================
|ncurses-devel        | curses screen-painting library, used by cgps and gpsmon
|==============================================================================

You can build libQgpsmm if you have Qt (specifically QtCore and
QtNetwork modules) version 4.5.3 or higher.  You will also need a C++
compiler supported by Qt (tested on gcc 4.4.0/mingw on Windows and gcc
4.1.2 on Linux). Please refer to Qt's documentation at
http://qt.nokia.com/doc/4.6/platform-specific.html for platform
specific building documentation

Depending on how your distribution packages ncurses you may also require
libtinfo5, a separate terminfo library.

On some older versions of Ubuntu (notably 11.10) there is a packaging
defect that may cause your build to blow up in SCons. It's a missing
package info file for the tinfo library. To fix this, install the file
packaging/tinfo.pc in /usr/lib/pkgconfig/tinfo.pc. 13.10 fixed this.

If your kernel provides the RFC 2783 KPPS (kernel PPS) API, gpsd will
use that for extra accuracy. Many Linux distributions have a package
called "pps-tools" that will install KPPS support and the timepps.h
header file.  We recommend you do that.  If your kernel is built in
the normal modular way, this package installation will suffice.

For building from the source tree, or if you change the man page source,
Asciidoctor is to generate nroff -man source from asciidoc markup.  The
following packages are used in this process:

|============================================================================
|asciidoctor          | Documentation front end with light markup
|============================================================================

If both are present, then AsciiDoctor is preferred.

On Gentoo systems this packages is named:

|==============================================================================
|dev-ruby/asciidoctor | Documentation front end with light markup
|==============================================================================

The build degrades gracefully in the absence of any of these. You should
be able to tell from scons messages which extensions you will get.

Under Ubuntu and most other Debian-derived distributions, an easy way
to pick up the prerequisites is: "apt-get build-dep gpsd".  Note
that your sources.list will need "deb-src" lines for this, not
just "deb" lines.

If you are custom-building a Linux kernel for embedded deployment, you
will need some subset of the following modules:

|============================================================================
|pl2303       | Prolific Technology, Inc. PL2303 Serial Port
|ftdi_sio     | FTDI 8U232AM / FT232
|cypress_m8   | M8/CY7C64013
|cp210x       | Cygnal Integrated Products devices
|garmin_gps   | Garmin USB mice including GPS-18
|cdc_am       | USB Communication Device Class Abstract Control Model interface
|pps-gpio     | For KPPS support on ARM systems
|pps-ldisc    | For KPPS support with RS-232 ports
|pps_parport  | For KPPS support with a parallel port
|============================================================================

These are listed in rough order of devices covered as of 2013; the
PL23203 by itself accounts for over 70% of deployed USB mice.  We
recommend building with pl2303, ftdi_sio, cypress_m8, and cp210x.

We've received a bug report that suggests the Python test framework
requires legacy PTY support (CONFIG_LEGACY_PTYS) from the Linux
kernel.  You should make sure you're in the 'dialout' group in order
to have permission to use these devices.

== How to build the software from source

To build gpsd for your host platform from source, simply call 'scons'
in a working-directory copy. (Cross-build is described in a later
section.)

To clean the built files, run 'scons -c' or 'scons --clean'.
Run 'rm -f .sconsign.*dblite' to clear the scons
database.  Doing both should return your working directory to a
near pristine state as far as building is concerned.  Some user created
files may remain, and source code changes will not have been reverted..

When in doubt, restart with a clean copy of the source.

You can specify the installation prefix, as for an autotools build, by
running "scons prefix=<installation_root>". The default value is
"/usr/local".  The environment variable DESTDIR also works in the
usual way.

If your linker run fails with missing math symbols, see the FIXME
comment relating to implicit_links in the scons recipe; you probably
need to build with implicit_link=no.  If this happens, please report
your platform, ideally along with a way of identifying it from Python,
to the GPSD maintainers.

After building, please run 'scons check' to test the correctness of
the build.  It is not necessary to install first.  It should be run as
root to avoid some error messages.  If you must run as non-root you can
safely ignore the error messages about seteuid() and shm().  Python is
required for regression tests. If any of the tests fail, you probably
have a toolchain issue.  The most common such problem is failures of
strict C99 conformance in floating-point libraries.

Once you have verified that the code is working, "scons install" will
install it in the system directories.  In almost all cases this must be
run as root. "scons uninstall" will undo this. Note: because scons is a
single-phase build system, this may recompile everything. If you want
feature-configuration options, you need to specify them here.

To enable hotplugging of USB GPSes under Linux, you may do 'scons
udev-install' to put the appropriate udev rules and wrapper files in
place.

You will need php and php-gd installed to support the PHP web page
generator included with the distribution. To install it, copy the file
'gpsd.php' to your HTML document directory. Then see the
post-installation instructions in INSTALL.adoc for how to configure it.

=== Setting prefix and customizing install locations

Adding prefix=/usr/foo will cause scons to install to /usr/foo instead
of the default /usr/local, much as --prefix=/usr/foo works with
autoconf.

In addition, there are a number of other scons command-line variables
that can be used to control the location of various install
directories.  Many of these, such as bindir -- which unsurprisingly
defaults to "bin" -- are unlikely to be ever used.  Generally, these
can be set to absolute paths or relative paths.  Relative paths are
under prefix.  See SConscript and search for "bindir" to see the list.

Some of these variables are typically used to adapt to differing
layout conventions.  For example, pkgsrc would use
docdir=share/doc/gpsd as per-package documentation is placed in
prefix/share/doc/PKGNAME, and mandir=man as man pages are in
prefix/man rather than prefix/share/man.

The includedir= argument sets the location to which gpsd's include
files (gps.h, libgpsmm.h) are installed.  So using prefix=/usr/foo and
includedir=/usr/bar/include will install everything but includes in
/usr/foo and put the includes in /usr/bar.  This is highly unlikely to
be desired, but given to illustrate the behavior.

The includedir=/usr/foo/include argument has no other effects; in
particular it does add -I/usr/foo/include to compilation lines.

=== Specifying locations for prerequisites

This section explains how to configure the build to find
prerequisites.  It can be skipped by those who find that the build
succeeds.

Software that is needed to build gpsd may in general be in various
locations.  (While many GNU/Linux users doing a straightforward build
will have all prerequisites in /usr, most other operating systems have
additional software in other than /usr, and even on Linux one may wish
to build a separate copy of gpsd with alternate versions of
prerequisites.)  

The build will invoke the compiler and linker, so that headers and
libraries in the default compiler and linker search paths will be
found without any additional configuration.

In addition, scons will use pkgconfig to find some prerequisites.
These will be found if the pc files are in the default pkgconfig
search path, and the resulting -I and -L flags added to the compile
and link lines.

The gpsd scons build scripts also support passing in CPPFLAGS and
LDFLAGS via environment variables, similar to how these are used with
autoconf and almost all other build systems.  As an example,
CPPFLAGS=-I/usr/foo/include will cause -I/usr/foo/include to be added
to compilation lines.

=== Gentoo Build and Installation

A cheat sheet for building gpsd from git source on a freshly installed
Gentoo.  Perform these steps, in order, as root.

The '--noreplace' option to 'emerge' prevents reinstalling packages that
are already installed.

----
# install the required build tools
emerge --noreplace dev-build/scons dev-vcs/git

# optional, to support the KPPS API, for improved timing
emerge --noreplace net-misc/pps-tools

# optional, for cgps and gpsmon
emerge --noreplace sys-libs/ncurses

# optional, for ubxtool and zerl serial port support
emerge --noreplace dev-python/pyserial

# optional, to support Garmin USB devices
emerge --noreplace virtual/libusb

# optional, to support Bluetooth GPS devices
emerge --noreplace net-wireless/bluez

# Skip the following optionals on a minimal system:

# optional, to build man page and html pages
emerge --noreplace dev-ruby/asciidoctor

# Optionals for desktop (X) systems:

# optional, for xgps and xgpsspeed
emerge --noreplace dev-python/pygobject dev-python/pycairo

# optional, for gpsplot
emerge --noreplace dev-python/matplotlib

# D-Bus support
emerge --noreplace sys-apps/dbus

# To build Qt compatible library.
emerge --noreplace dev-qt/qtcore dev-qt/qtnetwork

# "scons check" requires bc
emerge --noreplace sys-devel/bc

# prerequisites now installed

# make a place to keep the source
mkdir -p /usr/local/src/GPSD
cd /usr/local/src/GPSD

# grab a shallow clone of gpsd from git.
git clone --depth 1 https://gitlab.com/gpsd/gpsd.git
cd gpsd

# clean the tree, just in case
scons -c

# build the project
scons

# check the results
scons check

# and install if it looks good
scons install
----

== Apple Desktop

=== Special Notes for macOS X Build and Installation

gpsd will build, install and run on macOs. Install the Xcode application
from the Apple store. Then install Homebrew (https://brew.sh/) to get
all the stuff you need, like git, scons, python, etc.

As a normal user, install homebrew, then install scons and asciidoctor.
Installing scons pulls in python3. Brew will become root as needed, so
starting as a normal user is just security theater.

----
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
$ brew install scons asciidoctor
----

Now you need to become root. Make a place for the gpsd source to live,
use git to install it there, then go there.  Build gpsd with "scons",
then install it with "scons install"

----
# mkdir -p /usr/local/src/GPS
# cd /usr/local/src/GPS
# git clone https://gitlab.com/gpsd/gpsd.git
# cd gpsd
# scons && scons install
----

=== Special Notes for OS X Build and Installation

gpsd will build, install and run on OS X (osX).  The easiest way to
do so is to first install the MacPorts package.  Follow their install
procedure at: http://www.macports.org/install.php

Then use their port command to install scons.  Optionally git if you
want to access the development source.  Optionally install asciidoctor
to build the documentation.

----
# port install scons
# port install git
# port install asciidoctor
----

Currently the osX port does not work with Qt5.  To see the build
failure:

----
# port install qt5
# scons --config=force qt_versioned=5
----

If you have Qt5 installed, and want to avoid the build failure, build
this way:

----
# scons --config=force qt=no
----

While running gpsd, or scons check, you may run out of shared memory
segments.  If so, you will see this error message:

----
gpsd:ERROR: shmat failed: Too many open files
----

By default OS X allows a very small number of shared segments.  You
can check your allowed maximum number of shared segments, then increase
the maximum number, with these commands:

----
# sysctl kern.sysv.shmseg=8
kern.sysv.shmseg: 32 -> 8
#   sysctl -a  | fgrep shmseg
kern.sysv.shmseg: 8
# sysctl kern.sysv.shmseg=16
kern.sysv.shmseg: 8 -> 16
#   sysctl -a  | fgrep shmseg
kern.sysv.shmseg: 16
----

If you are using a USB based GPS you will likely need the Prolific
PL2303 driver.  You can find it here:
http://www.prolific.com.tw/US/ShowProduct.aspx?p_id=229&pcid=41

=== Special Notes for Raspberry Pi Build and Installation

*gpsd* will build, install and run on any model of Raspberry Pi. If you
have a Paspberry Pi 3, or newer, then it is recommended that you use the
standard Raspberry Pi Foundation OS - Raspberry Pi OS (64-bit).

Models older than a Pi 3 should use a 32-bit OS.

==== Raspberry Pi OS

Raspberry Pi OS currently is a port of Debian 12 (Bookworm) for the
Raspberry Pi family of SBCs, supported and maintained by the Raspberry
Pi Foundation. For a headless or lite installation of Raspberry Pi
OS w/o a GUI, the Raspberry Pi OS Lite (64-bit) version is a perfect
choice!  There is also Raspberry Pi OS Lite (32-bit) for older devices
or those that want to run a 32-bit OS on newer devices.  Other Debian
based distributions for the Raspberry Pi should also work.  Raspberry
Pi OS & many other Debian based distributions are available and easy
to install with the Raspberry Pi Imager downloaded from this URL,
https://www.raspberrypi.com/software/ . Newer Raspberry Pi (4 & 5), with
current firmware can also network boot & download/install an OS with
only a network connection on the Raspberry Pi.

The *gpsd* package in most versions of Debian are generally not up to
date with current gpsd, missing the latest fixes, features & device
support. Be sure to install a new gpsd version from source.

Before compiling gpsd from source, you should update your system as
root. Open a terminal windows & change to root to update the system &
then reboot:

----
$ sudo su -
# apt update
# apt dist-upgrade
# shutdown -r now
----

Multiple versions of gpsd cannot co-exist on the same system. You need
to ensure all previous versions of gpsd are removed from your system.
Open a terminal window, change to root & use the following commands.
Note that some of the commands may fail or complain if gpsd is not
already installed - that is normal. The commands are required to be sure
any previous gpsd installation is removed:

----
$ sudo su -
# systemctl stop gpsd.socket
# systemctl disable gpsd.socket
# apt purge gpsd gpsd-clients gpsd-tools
----

Next install the required packages:

----
# apt install git scons libncurses-dev asciidoctor pps-tools 
----

Scons is the build system used by the gpsd project.
Git is required to build from a git repository.
libncurses-dev is required by some of the gpsd command line utilities.
asciidocotor is for building the documentation, and pps-tools is for
PPS timing.

*The rest of the gpsd installation is the same as for any other source based
install as already described above.*


==== Raspbian

Before Raspberry Pi OS, there was Raspbian. Now considered obsolete.
To compile gpsd from source, you will need to update your system as
root. Switching to the latest Raspbian distribution (Buster) is strongly
recommended.

----
$ sudo su -
# apt-get update
# apt-get dist-upgrade
# rpi-update
# reboot
----

Multiple versions of gpsd can not co-exist on the same system.  You need
to ensure gpsd from a package is not on the system:

----
# apt purge gpsd
----

Then install the required packages:

----
# apt-get install scons libncurses5-dev python-dev pps-tools
# apt-get install git-core
----

Git-core is required to build from a git repository.  pps-tools is for
PPS timing.

The rest of the installation is just as for any other source based
install, as already described above.

=== Other Debian derivatives (including stock)

==== Bookworm (12) and Trixie (13)

These notes work on both Debian 12 (Bookworm) and 13 (Trixie). Bookworm
is the current stable, and Trixie is testing, that is, Trixie has not
yet been released as stable.

The attached script has been tested on fresh netinst installations to an
AMD64 virtual machine of Bookworm from debian-12.6.0-amd64-netinst.iso,
and the weekly testing CD from Monday, 12 May, 2025.

The script assumes nothing beyond a netinst installation and a few
customizations I run so I can log in to the VM via SSH.

The script takes a kitchen sink approach. It installs almost all
dependencies for gpsd. There are notes in the script of what to take
out if you don't want everything. It clones the gpsd repository, then
compiles and checks it. It does not do either `scons install` or `scons
udev-install`.

If you only run `scons install` you should be able to run gpsd with
something like

----
gpsd -n /dev/ttyACM0
----

Use your GPS receiver's device file, probably
`/dev/ttySomethingOrOther`. After that, you are on your own.

If you want udev and systemd glue, run `scons install && scons
udev-install`. That will install gpsd, and the glue. You will have
to reboot to make the systemd glue effective. The gpsd installation
does not provide `/etc/default/gpsd`. Instead the script installs
one for you. There is a prototype for one in the repository at
`packaging/deb/etc_default_gpsd.in`.

Feel free to hack.

----
#! /bin/bash

# A script to pull in the prerequisites for gpsd, pull it in, compile
# and exercise it. This script works on Debian Trixie as of May 12,
# 2025. As Trixie has not been released, it is a moving target.

# One thing this script does not do is check for and/or purge any
# Debian packages. We assume this is a freshly built system. Run
# "dpkg-query -l libgps* gpsd*" to see if there are any installed, and
# "apt purge" them.

# The location of the build directory. We will cd to this directory,
# pull in the gpsd git repo, and then cd to the repo.
devel=~/versioned

apt update
apt upgrade                     # expect to be asked for approval.

# We take a kitchen sink approach to installing tools. If you want to
# pare down the installation, you can remove packages from this
# list.

# Gtk3 is only required to run xgps and xgpsspeed. You do not need a
# local X11 server installed, but it still pulls in a lot of packages.

# Ubxtool and zerk may optionally use the pyserial module for direct
# connection to the GNSS receiver.

# gpsplot uses matplotlib, which is in the package python3-matplotlib.

# pps-tools is for PPS timing.

# The documentation, including the web site, requires ascidoctor.

# manpages-dev is required for the man pages.

# Not included here: libusb-1.0-0-dev, for some very old Garmin USB devices.

# Everything else is required for a minimal build.

apt install -y asciidoctor build-essential gcc git libgtk-3-dev libncurses-dev \
   manpages-dev pkg-config pps-tools python-dev-is-python3 python-gi-dev \
   python3-cairo-dev python3-gi-cairo python3-matplotlib python3-serial scons

mkdir -p $devel

# shellcheck disable=SC3044
cd $devel || { printf "Cd to %s failed.\n" $devel; exit 1;}

if [ ! -d gpsd ] ; then
    git clone https://gitlab.com/gpsd/gpsd.git
    cd gpsd || { printf "cd to %s failed.\n" $devel/gpsd; exit 1;}
else
    cd gpsd || { printf "cd to %s failed.\n" $devel/gpsd; exit 1;}
    git pull
fi

PYTHONPATH="$PYTHONPATH:/usr/local/lib/python3.13/dist-packages/"

scons -c && scons && scons check

# && scons install && scons udev-install

echo "\$PYTHONPATH" is "$PYTHONPATH"

if [ -d /etc/default ] && [ ! -e /etc/default/gpsd ] ; then

    cat > /etc/default/gpsd << DEFAULT
# Devices gpsd should collect to at boot time.
# They need to be read/writeable, either by user gpsd or the group dialout.
DEVICES=""

# Other options you want to pass to gpsd
# GPSD_OPTIONS=""
GPSD_OPTIONS="--listenany"

# Automatically hot add/remove USB GPS devices via gpsdctl
USBAUTO="true"
DEFAULT
fi

printf "Enable listening on all interfaces in gpsd.socket if you want.\n";
----

==== Bullseye (11)

The main difference between Bullseye and Buster (below) is that Python
2 is not in Bullseye by default. It is available. gpsd is Python 3
compatible, so that's what we will use on Bullseye.

Multiple versions of gpsd can not co-exist on the same system.  You
need to ensure gpsd from a package is not on the system. Also check
for and remove any libgps?? packages.

----
# dpkg-query -l libgps* gpsd*
.....
# apt purge gpsd libgps28
----

Then update your system, and install the packages required by gpsd:

----
# apt-get update
# apt-get dist-upgrade
# reboot
# apt-get install scons libncurses-dev python-dev pps-tools
# apt-get install git-core
# apt-get install build-essential manpages-dev pkg-config
----

If "apt-get install scons ..." fails, check the file "/etc/apt/sources.list".

Git-core is required to build from a git repository.
pps-tools is for PPS timing.
Build-essential installs the compiler and associated tools.
Manpages-dev is for the associated man pages.
Pkg-config is a helper for scons.

Gtk3 is only required to run xgps and xgpsspeed. You do not need a local
X11 server installed, but it still pulls in a lot of packages.

----
# apt-get install python-gi-dev
# apt-get install libgtk-3-dev
----

Ubxtool and zerk may optionally use the pyserial module for
direct connection to the GNSS receiver:

----
# apt-get install python3-serial
----

gpsd may optional connect to dbus with the libdbus package:

----
# apt-get install libdbus-1-dev
----

gpsplot uses matplotlib, which is in the package
python3-matplotlib.

----
# apt install python3-matplotlib
----

Several programs written in Python (xgps, xgpsspeed, etc.) are
installed locally. So if you intend to use them, set your
PYTHONPATH. You may wish to add it to your shell's log-in scripts to
make it permanent. For more information on PYTHONPATH, see:
https://docs.python.org/3/using/cmdline.html#envvar-PYTHONPATH

Something like this, but see the output from the "scons install"
command and other scons commands.

----
# export PYTHONPATH=${PYTHONPATH}:/usr/local/lib/python3/dist-packages
----

Some very old Garmin USB devices need libusb:

----
# apt-get install libusb-1.0-0-dev
----

If you wish to build the documentation, be warned it pulls in a
lot of packages. Build the documentation is a prerequisite to
building the HTML files for the website (www/), and also to make
a source tarball (scons dist). To install the tools to build the
documentation:

----
apt-get install asciidoctor
----

The rest of the installation is just as for any other source based
install:

----
# git clone https://gitlab.com/gpsd/gpsd.git
# cd gpsd
# scons -c && scons && scons check && scons install
----

==== Buster (10) with python2

These Buster instructions seem to also work for Devuan and Maemo Leste.

Multiple versions of gpsd can not co-exist on the same system.  You need
to ensure gpsd from a package is not on the system:

----
# apt purge gpsd libgps23
----

Then update your system, and install the packages required by gpsd:

----
# apt-get update
# apt-get dist-upgrade
# reboot
# apt-get install scons libncurses-dev python-dev pps-tools
# apt-get install git-core
# apt-get install build-essential manpages-dev pkg-config
----

If "apt-get install scons" fails, check the file "/etc/apt/sources.list".

Git-core is required to build from a git repository.
pps-tools is for PPS timing.
Build-essential installs the compiler and associated tools.
Manpages-dev is for the associated man pages.
Pkg-config is a helper for scons.

Gtk3 is only required to run xgps and xgpsspeed.  You do not need a local
X11 server installed, but it still pulls in a lot of packages.

----
# apt-get install python-gi-dev python-cairo-dev
# apt-get install python-gobject-2-dev libgtk-3-dev
----

Ubxtool and zerk may optionally use the pyserial module for
direct connection to the GNSS receiver:

----
# apt-get install python-serial
----

gpsd may optional connect to dbus with the libdbus package:

----
# apt-get install libdbus-1-dev
----

Some very old Garmin USB devices need libusb:

----
# apt-get install libusb-1.0-0-dev
----

If you wish to build the documentation, be warned it pulls in a
lot of packages.  Build the documentation is a prerequisite to
building the HTML files for the website (www/), and also to make
a source tarball (scons dist).  To install the tools to build the
documentation:

----
apt-get install asciidoctor
----

The rest of the installation is just as for any other source based
install:

----
# git clone https://gitlab.com/gpsd/gpsd.git
# cd gpsd
# scons --config=force && scons install
----

==== Jessie (8)

Multiple versions of gpsd can not co-exist on the same system.  You need
to ensure gpsd from a package is not on the system:

----
# apt purge gpsd
----

Then install the required packages:

----
# apt-get install scons libncurses5-dev python-dev pps-tools
# apt-get install git-core
----

Git-core is required to build from a git repository.  pps-tools is for
PPS timing.

The rest of the installation is just as for any other source based
install, as already described above.

==== Wheezy

Multiple versions of gpsd can not co-exist on the same system.  You need
to ensure gpsd from a package is not on the system:

----
# apt purge gpsd
----

Wheezy, being older, requires updating the tools for compiling
and testing gpsd:

You need scons at 2.3.0 or higher to build.
If your scons is less than 2.3.0 you will need to get a newer scons
from wheezy-backport.  Partial instructions are detailed here:
https://backports.debian.org/Instructions/

Basically you need to add this line to /etc/apt/sources.list:

----
deb http://http.debian.net/debian wheezy-backports main
----

Then do another update:

----
apt-get update
----

Which may lead you to this error if you lack a full set of debian keys:

----
W: GPG error: http://http.debian.net wheezy-backports Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 8B48AD6246925553
----

Partial but detailed instructions to fix that are here:

----
https://wiki.debian.org/SecureApt
----

Use either of the following code blocks.  The first is more robust:

----
apt-get install debian-archive-keyring
----

----
gpg --keyserver pgpkeys.mit.edu --recv 8B48AD6246925553
gpg -a --export 46925553 |  apt-key add -
apt-get update
----

You can now install scons from the wheezy-backports repository:

----
apt-get -t wheezy-backports install scons
----

and other tools:

----
# apt-get install scons libncurses5-dev python-dev pps-tools
# apt-get install git-core
----

Git-core is required to build from a git repository.  pps-tools is for
PPS timing.

The rest of the installation is just as for any other source based
install, as described above.

==== Ubuntu Buster 20

If you have Raspbian Buster, that is not this.

Preliminary install notes.

Multiple versions of gpsd can not co-exist on the same system.  You need
to ensure gpsd from a package is not on the system:

----
# apt purge gpsd
----

Then install the required packages:

----
apt install gcc scons python-gi python-gi-cairo g++
apt install python-gobject libgtk-3-dev
apt install libncurses5-dev libtinfo-dev  pps-tools
apt install gir1.2-gtk-3.0
----

At some point Ubuntu renamed "python-gi" to "python3-gi".

If you wish to build the documentation, be warned it pulls in a
lot of packages.  Build the documentation is a prerequisite to
building the HTML files for the website (www/), and also to make
a source tarball (scons dist).  To install the tools to build the
documentation:

----
apt install asciidoctor
----

The rest of the installation is just as for any other source based
install, as described above.

==== Ubuntu 18.04 LTS

Preliminary install notes.

If you have Raspbian Buster, that is not this.

Multiple versions of gpsd can not co-exist on the same system.  You need
to ensure gpsd from a package is not on the system:

----
# apt purge gpsd
----

Then install the required packages:

----
apt install gcc scons python-gi python-gi-cairo g++
apt install libncurses5-dev libtinfo-dev  pps-tools
apt install gir1.2-gtk-3.0
----

If you wish to build the documentation, be warned it pulls in a
lot of packages.  Build the documentation is a prerequisite to
building the HTML files for the website (www/), and also to make
a source tarball (scons dist).  To install the tools to build the
documentation:

----
apt install asciidoctor
----

The rest of the installation is just as for any other source based
install, as described above.

== BSD derivatives ==
=== Special Notes for FreeBSD Build and Installation ===

gpsd will build, install and run on FreeBSD.
Due to the missing CAN bus support (linux/can.h), NMEA2000/CAN
is not supported on FreeBSD.

Use their pkg command to install scons, and optionally git if you
want to access the development source.

If you want to build the QT bindings, you'll also need the
qt5-network and pkgconf packages.

----
# pkg install scons
# pkg install git
# ln -s /usr/local/bin/python2.7 /usr/local/bin/python
# ln -s /usr/local/bin/python2.7 /usr/local/bin/python2
# ln -s /usr/local/bin/python3.6 /usr/local/bin/python3
# git clone https://gitlab.com/gpsd/gpsd.git
# cd gpsd
# scons --config=force && scons install
----

OpenBSD names scons differently, and uses a different Python. 
On OpenBSD 13.0, you need to do this to install scons and Python:

----
# pkg install scons-py38
# ln -s /usr/local/bin/python3.8 /usr/local/bin/python3
----

FreeBSD fails to create the python links as required by PEP394.
So you need to add them yourself, as above.

=== Special Notes for NetBSD 8.1 Build and Installation

gpsd will build, install and run on NetBSD.

Use their 'pkg_add' command to install pkgin.  Then use pkgin to
install the required tools.

----
# export PKG_PATH=\
"http://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/amd64/8.1/All"
# pkg_add -v pkgin
# echo http://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/amd64/8.1/All > \
   /usr/pkg/etc/pkgin/repositories.conf
# pkgin update
# pkgin install python37 py37-curses
# ln -s /usr/pkg/bin/python3.7 /usr/pkg/bin/python
# ln -s /usr/pkg/bin/python3.7 /usr/pkg/bin/python3
# pkgin install py37-scons
# pkgin install ncurses
# pkgin install openssl mozilla-rootcerts
# mozilla-rootcerts install
# pkgin install git
# git clone https://gitlab.com/gpsd/gpsd.git
# cd gpsd
# scons --config=force && scons install
----

=== Special Notes for OpenBSD 6.6 and 7.x Build and Installation

gpsd will build, install and run on OpenBSD.

First, update your system. Then all you need for a basic gpsd install is
scons and git. Then create the missing python link.

----
# syspatch -c
# syspatch
# pkg_add -u
# pkg_add scons
# pkg_add git
# ln -s /usr/local/bin/python2 /usr/local/bin/python
----

Yes, OpenBSD 7.0 still uses Python 2.7.

Then install the normal way.

----
# git clone https://gitlab.com/gpsd/gpsd.git
# cd gpsd
# scons --config=force && scons install
----

=== OpenBSD 7.2

OpenBSD 7.2 may require the linker flag _-fPIC_ in order to completely
build.  Set _LDFLAGS="-fPIC"_.

== Special Notes for Fedora derivatives
=== Special Notes for Fedora 32 to 33, Build and Installation

gpsd currently will build, install and run on Fedora 32, to 37.  Any
supported architecture should work.

Upgrade your packages, install the gcc compiler and tools. Clone the gpsd
source, and then build it.  Fedora recommends a reboot after using dnf.

----
# dnf upgrade --refresh
# dnf install -y gcc-c++ python3-devel scons asciidoctor bzip2
# dnf install -y xz git dnf-plugins-core
# git clone https://gitlab.com/gpsd/gpsd.git
# cd gpsd
# scons
# dnf builddep -y buildtmp/packaging/rpm/gpsd.spec
# scons -c
# scons && scons check && scons install
----

If you wish to make an rpm of your build:

----
# scons dist
# dnf install -y chrpath fedora-packager rpmdevtools
# rpmdev-setuptree
# cp gpsd-3*.tar.* ~/rpmbuild/SOURCES/
# rpmbuild -ba gpsd-3*/packaging/rpm/gpsd.spec
----

=== Special Notes for CentOS 7 Build and Installation

gpsd currently will build, install and run on CentOS 7.

Install the gcc compiler and tools.  Install EPEL.

Note: there is no EPEL for i386.

Use the yum command to install git if you
want to access the development source.

----
# yum group install "Development Tools"
# yum install git
# yum install \
   https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
# yum install scons
# yum install python-devel
# yum install ncurses-devel
# yum install pps-tools-devel
# git clone https://gitlab.com/gpsd/gpsd.git
# cd gpsd
# scons
----

== Leap Seconds

The header gpsd.h contains the value BUILD_LEAPSECONDS.  This is set,
at release time, to the leap second value current at that time.

Ideally gpsd would be reading the standard leapseconds.cache file
provided by most distributions for the current leap second.

Most of the drivers supply the current leap second, after the GNSS
receiver sends it in a message to gpsd.  But none of the standard NMEA
0183 messages supply the current leap second.  Thus the need for a fall
back leap second value.

The leap second value is mainly used to check for invalid UTC time from
the GNSS receiver.  If the receiver is affected by the GPS Week Number
Roll Over (WKNO) bug, then the UTC time it reports will be off by 1024
weeks.

All GNSS receivers may be using the wrong leap second internally on
startup. This may happen if it has been less than about 12 minutes since
power-up; the receiver has not yet received the current leapsecond
offset as part of the periodic almanac download.  Page 18, subframe 4,
of the almanac contains the leap second data.

The gpsd daemon may be using the wrong leap second internally if
the compiled in leap second is no longer valid, and the GNSS receiver
has not reported the current leap second to gpsd.

== Optional features

By giving command-line options to scons you can configure certain rarely-used
optional features in, or compile standard features out to reduce gpsd's
footprint. "scons --help" will tell the story; look under "Local Options"
and consult the source code if in doubt.

Here are a few of the more important feature switches.  Each description
begins with the default for the switch.

dbus_export=no: for systems using D-Bus: gpsd includes support for
shipping fixes as D-Bus notifications, compiled in by default.  This
may lead to complaint messages during testing  on systems that don't
support D-Bus. Build with the option "dbus_export=no" to disable it

qt=yes: libQgpsmm is a Qt version of the libgps/libgpsmm
pair. Thanks to the multi-platform approach of Qt, it allows the gpsd
client library to be available on all the Qt supported platforms.
Please see http://qt.nokia.com/doc/4.6/supported-platforms.html for a
status of Qt supported platforms as of version 4.6.

minimal=no: people building for extremely constrained environments
may want to set this.  It changes the default for all boolean (feature)
options to false; thus, you get *only* the options you specify on the
command line.  Thus, for example, if you want to turn off all features
except socket export.  Note the nmea0183 driver is always built.

----
scons minimal=yes socket_export=yes
----

will do that.

----
scons minimal=yes gpsd=False gpsdclients=False
----

generates only libgps.a

----
scons minimal=yes shared=True gpsd=False gpsdclients=False
----

generates only libgps.so


== Port and toolchain testing

'scons check' will run a comprehensive regression-test suite.  You
should do this, at minimum, every time you build from source on a new
machine type.  GPSD does enough bit-twiddling and floating point that
it is very sensitive to toolchain problems; you'll want to be sure
those aren't going to bite you in production.

So that the tests will run fast and be easy to do often, we make the test
framework shove data through the pty and socket layers *way* faster
than would ever occur in production.  If you get regression-test
failures that aren't repeatable and look like the test framework is
sporadically failing to feed the last line or two of test loads, try
using the slow=yes option with scons check.  If that fails, try
increasing the delay value via the WRITE_PAD environment variable
(above the value reported in the test output).  If you have to do this,
please report your experience to the GPSD maintainers.

Both the builds and the tests are highly parallelizable via the scons
-j option, which can gain a substantial speedup on a multicore machine.
Because the output from the various jobs is interleaved, it may be more
difficult to understand error results with multiple jobs.  In that event,
simply rerun without the -j option for more straightforward output.

If coveraging is enabled (coveraging=yes), then Python programs run
during testing are run via Python coveraging.  This prefixes the relevant
commands with the content of the python_coverage option, whose default
value of "coverage run" is appropriate if the standard Python coverage
package is installed and accessible in the command path.  It can be
set to a different value if necessary, or set to the empty string to
disable Python coveraging.  The latter happens automatically (with a
message) if the tool cannot be found.  When running multiple jobs with
"-j", if python_coverage has its default value, "--parallel" is automatically
appended to the command.  With a non-default setting, accommodating
parallelism is the user's responsibility.

For instructions on how to live-test the software, see the file INSTALL.adoc.

=== Regenerating regression tests

Sometimes, changes are made to code that cause the output to be
different.  Examples are bug fixes and changes to precision.  In these
cases, the regression tests must be updated.  This is dangerous, and
one must guard against the possibility of introducing a bug and
recording that bug's output as the desired state.

A suggested procedure is

  * Create a minimal commit with the breaking change.  Do not include
    any other changes.

  * On master, without the new commit, run the regression tests and
    verify that they pass.  Do this on a machine with a history of
    zero flaky behavior with the regression tests.

  * Apply the minimal commit.

  * Run "scons gps-makeregress".

  * Merge the regression changes into the commit.  Mention in the
    commit message that regression tests were regenerated.

  * Review the diff for sanity, and if OK, push it.

== Reverting to a clean state

The scons equivalent of 'make clean' is 'scons -c' or 'scons
--clean'. This will revert your source tree to a clean state nearly as
though you had just cloned or downloaded it; some scons housekeeping
stuff is left in place.

If you interrupted a regression test, 'scons testclean' will remove
generated test programs.

If you're building in a clone of the git repository, you can use
"git clean -dxf" to remove all untracked files.  Note, however, that
this will remove any files you have created on your own, in addition
to build products and scons temporaries.  You can alternatively use
"git clean -dxn" to see what would be removed without actually removing
anything, or "git clean -dxi" to remove things selectively.  Using
"git clean" after "scons -c" usually results in a fairly short list.

== Notes on Android:

Samuel Cuella reports:

I use the official google toolchain from the Android NDK (Native
Development Kit). You can also use the toolchain from code sourcery I
guess. I cross-compile from a "regular" (with GNU userland) Linux box.

People who port software from Linux to android tend to use either the
NDK or code sourcery's.

If you are going to include "official" guidelines, I would go for
recommending the official toolchain from the NDK.

Here are the scons switches I use:

----
scons wordsize=32 snapshot=off arch=arm sample=shell

scons -j3 prefix=/usr libdir=$prefix/lib udevdir=/lib/udev \
  gpsd_user=gpsd gpsd_group=uucp socket_export=1 sirf=1
----

With the following environment variables:

----
TOOL_HOME=/home/samuel/android-official-last/
export TOOL_PREFIX=${TOOL_HOME}/bin/arm-linux-androideabi
export CXX=$TOOL_PREFIX-g++
export AR=$TOOL_PREFIX-ar
export RANLIB=$TOOL_PREFIX-ranlib
export CC=$TOOL_PREFIX-gcc
export LD=$TOOL_PREFIX-ld

export CCFLAGS="-march=armv7-a -mtune=cortex-a8 -mfpu=vfp"
export ARM_TARGET_LIB=${TOOL_HOME}/sysroot

scons wordsize=32 snapshot=off arch=arm sample=shell
----

== Cross-building

The scons recipe is intended to support cross-building, in particular
for embedded deployment of the software.  A session transcript
illustrating how to do that, with some routine messages suppressed and
replaced with [...], follows.  The script assumes you're cloning from the
GPSD project site or a mirror. Notes and explanation follow the transcript.

----
$ git clone [...]
Cloning into gpsd...
[...]
$ cd gpsd
----

Edit .scons-options-cache (may not exist) and add lines, describing
what your target architecture and build preferences are.

----
$ cat .scons-option-cache
libgpsmm = False
libQgpsmm = False
python = False
prefix = '/work/buildroot/output/staging/usr/'
sysroot = '/work/buildroot/output/staging/'
target = 'arm-indigo-linux-gnueabi'
$ scons
scons: Reading SConscript files ...
[...]
Altered configuration variables:
libgpsmm = False (default True): build C++ bindings
libQgpsmm = False (default True): build QT bindings
python = False (default True): build Python support and modules.
prefix = /work/buildroot/output/staging/usr/ (default /usr/local): installation directory prefix
sysroot = /work/buildroot/output/staging (default ): cross-development system root
target = arm-indigo-linux-gnueabi (default ): cross-development target
scons: done reading SConscript files.
scons: Building targets ...
[...]
scons: done building targets.
$ file gpsd
gpsd: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.36, not stripped
----

The author of this transcript notes:

The sysroot option tells the compiler and linker to use libraries and
headers from the given path as if they were placed at / prefix. During
this build the option allows linking with target ncurses (with the option
of having more packages at the --sysroot path) and including correct
headers without specifying -I and -L options.

In the options cache file gpsd is configured to install to
/work/buildroot/output/staging/usr path, so gpsd clients could be
compiled against libgps.so using /work/buildroot/output/staging as
sysroot option.

"arm-indigo-linux-gnueabi" as target means that
arm-indigo-linux-gnueabi-gcc and related tools are available in PATH;
your cross-compiler is likely to have a different target prefix.

You may also find it useful to set manbuild=no.

== Common build problems

When you start *gpsd* with the -D3 option, you may be presented with
some common errors that result from a marginal build.

=== gpsd:WARN: FLT_EVAL_METHOD is 2, s/b 0

This means your gpsd binary was constructed in a way that does not
support strict IEEE 754 Floating Point operation.  In this case, the
regression tests ("scons check") will likely fail.

A possible workaround for the i686 (32-bit) mode build with gcc is to
set the CCFLAGS to force a compliant mode.  Like this:

    $ export CCFLAGS="-msse2 -mfpmath=sse"
    $ scone -c
    $ scons
    [...]

== Autostarting the daemon

One way to start gpsd is on-demand by a hotplug script
detecting USB device activations.  Look at the gpsd.rules and
gpsd.hotplug files to see how this is accomplished.  Relevant
productions in the build recipe are "udev-install" and
"udev-uninstall"; relevant build options include "udevdir".

You may need to start gpsd unconditionally at boot time.  Do this if you
need to support serial port devices, or want to use gpsd to set the time
on your host. there's a model init.d script under packaging/deb and a
systemd setup under systemd/.

// end
