# Hacking Survex

(That's hacking in the "tinkering with code" sense, not in the "breaking into other people's computer systems" sense).

This is currently a random collection of notes that need to be written down while I remember. With time it should evolve into a more coherent document. If you have any questions which this should answer but doesn't then ask me and I'll add them.

## Network code debugging

You can pick which network simplifications are attempted using "-z" with an argument listing code letters. So:

- -z= no special simplifications (articulation still performed)
- -z=l remove "lollipops"
- -z=p remove parallel legs
- -z=d convert deltas to stars

And you can combine these in any combination:

- -z=lp remove "lollipops" and parallel legs
- -z=lpd remove "lollipops" and parallel legs; convert deltas to stars

"-z=lpd" is the default (in 0.99 at least - more transformations may conceivably be added in future, although the simple common cases are already covered).

## Developing on Unix Platforms

You'll need automake 1.14 or later and autoconf 2.59 or later (autoconf 2.64, 2.71 and 2.72 have all been used successfully).

The wxWidgets library is used for aven's UI. Currently >= 3.2.0 is supported.

The PROJ library is used for coordinate conversions. Currently >= 7.2.0 is supported.

The Perl Locale::PO module is used for process message translation files.

For building the documentation you'll need sphinx-doc (Debian/Ubuntu package `python3-sphinx`) and w3m.

And for building unifont.pixelfont, you'll need unifont installed.

On Debian, you can install the required packages using:

    sudo apt-get install autoconf automake liblocale-po-perl libproj-dev libwxgtk3.2-dev inkscape netpbm python3-sphinx w3m unifont

## Building on Non-Unix Platforms

### Mingw (Microsoft Windows)

Survex can be built in an MSYS2+mingw64 environment - since 1.4.9 the pre-built installer for Microsoft Windows is built in such an environment by a CI job running on Github Actions.

It should also be possible to use a Linux-hosted cross-compiler, which is how we used to built releases, but this requires cross-building a lot of required libraries so we gave up on doing this. Some notes on this are left below in case anyone wants to try.

I use the packaged cross-compiler in the debian testing/unstable distribution:

    sudo apt-get install mingw-w64-i686-dev

Then install the various libraries by compiling from source. For wxWidgets I apply a patch to disable a pointless and annoying compiler ABI check (with this check aven stops working each time my cross compiler package is upgraded to a new GCC version; without it everything works fine).

Then I configure, build and install with:

    ./configure --prefix=/usr/i686-w64-mingw32 --host i686-w64-mingw32 --with-msw --with-opengl --enable-display --disable-shared host_alias=i686-w64-mingw32
    make
    sudo make install

For sqlite (needed by PROJ):

    wget https://www.sqlite.org/2021/sqlite-autoconf-3360000.tar.gz
    tar xvf sqlite-autoconf-3360000.tar.gz
    mkdir BUILD
    cd BUILD
    ../configure --prefix=/usr/i686-w64-mingw32 --host i686-w64-mingw32 --disable-shared --disable-fts4 --disable-fts5 --disable-json1 --disable-rtree host_alias=i686-w64-mingw32
    make
    sudo make install

Sadly newer versions of PROJ have to be built with cmake. For PROJ 9.3.0 I used the following (TIFF is apparently useful for some grids, but would also need libtiff):

    mkdir BUILD
    cd BUILD
    cmake .. -DCMAKE_TOOLCHAIN_FILE=~/git/survex/cross-mingw.cmake -DCMAKE_INSTALL_PREFIX=/usr/i686-w64-mingw32 -DENABLE_CURL=OFF -DENABLE_TIFF=OFF -DBUILD_PROJSYNC=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=ON -DCMAKE_FIND_USE_PACKAGE_REGISTRY=OFF -DCMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=ON -DFETCHCONTENT_FULLY_DISCONNECTED=ON -DBUILD_TESTING=OFF
    make
    sudo make install

where `cross-mingw.cmake` contains:

    # the name of the target operating system
    set(CMAKE_SYSTEM_NAME Windows)

    # which compilers to use for C and C++
    set(CMAKE_C_COMPILER   i686-w64-mingw32-gcc)
    set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)

    # where is the target environment located
    set(CMAKE_FIND_ROOT_PATH  /usr/i686-w64-mingw32)

    # adjust the default behaviour of the FIND_XXX() commands:
    # search programs in the host environment
    set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

    # search headers and libraries in the target environment
    set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
    set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

For ffmpeg 4.4.1:

    sudo apt-get install yasm
    mkdir BUILD
    cd BUILD
    ../configure --prefix=/usr/i686-w64-mingw32 --cross-prefix=i686-w64-mingw32- --enable-cross-compile --target-os=mingw32 --arch=i686 --disable-shared --disable-decoders --disable-demuxers --disable-programs --disable-network --disable-bsfs --disable-protocols --disable-devices
    make
    sudo make install

You'll also need to install GDAL, which requires a lot of other libraries installed to build. I gave up at this point.

## Microsoft Windows Installer Builder

We use InnoSetup to build the MS Windows Installer. Since 1.4.9 we use the InnoSetup version which is pre-installed in the Github CI images.

Survex 1.4.8 was built using InnoSetup 6.2.2.

Here are some random notes on the old cross-building approach:

### Packages Needed

On Debian unstable/testing:

    sudo apt-get install wine wx3.2-i18n

And then run:

    wine ~/Downloads/innosetup-6.2.2.exe

### Translations

In addition to the translations included with InnoSetup as standard, we also add these, which you can find in the `lib` subdirectory of Survex's source tree:

- ChineseSimplified.isl (6.1.0+)
- ChineseTraditional.isl (6.1.0+)
- EnglishBritish.isl (6.1.0+)
- Greek.isl (6.1.0+)
- Indonesian.isl (6.1.0+)
- Romanian.isl (6.1.0+)

These are taken from the Inno Setup Translations page.

### survex.iss

This file is generated by configure (from the template survex.iss.in). We could instead have a static survex.iss which uses #include to pull in a file with the Survex version info in, but the current method works well enough so we'll stick with it for now (I suspect #include was introduced since we started using InnoSetup).