diff --git a/.github/actions/autotools/build/action.yml b/.github/actions/autotools/build/action.yml new file mode 100644 index 00000000..5ea44c7a --- /dev/null +++ b/.github/actions/autotools/build/action.yml @@ -0,0 +1,15 @@ +--- +runs: + using: composite + steps: + - name: Run `./autogen.sh` + run: ./autogen.sh + shell: bash --noprofile --norc -euxo pipefail {0} + + - name: Run `./configure` + run: ./configure + shell: bash --noprofile --norc -euxo pipefail {0} + + - name: Run `make` + run: make + shell: bash --noprofile --norc -euxo pipefail {0} diff --git a/.github/actions/autotools/install/action.yml b/.github/actions/autotools/install/action.yml new file mode 100644 index 00000000..67e3b2f1 --- /dev/null +++ b/.github/actions/autotools/install/action.yml @@ -0,0 +1,11 @@ +--- +runs: + using: composite + steps: + - name: Run `make install` + run: make install + shell: bash --noprofile --norc -euxo pipefail {0} + + - name: Run `make install-mod_tile` + run: make install-mod_tile + shell: bash --noprofile --norc -euxo pipefail {0} diff --git a/.github/actions/autotools/test/action.yml b/.github/actions/autotools/test/action.yml new file mode 100644 index 00000000..6f3c52e0 --- /dev/null +++ b/.github/actions/autotools/test/action.yml @@ -0,0 +1,7 @@ +--- +runs: + using: composite + steps: + - name: Run `make test` + run: make test + shell: bash --noprofile --norc -euxo pipefail {0} diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml new file mode 100644 index 00000000..baa36b40 --- /dev/null +++ b/.github/actions/build/action.yml @@ -0,0 +1,11 @@ +--- +runs: + using: composite + steps: + - name: Build `mod_tile` (Autotools) + uses: ./.github/actions/autotools/build + if: matrix.build_system == 'Autotools' + + - name: Build `mod_tile` (CMake) + uses: ./.github/actions/cmake/build + if: matrix.build_system == 'CMake' diff --git a/.github/actions/cmake/build/action.yml b/.github/actions/cmake/build/action.yml new file mode 100644 index 00000000..2afd3afb --- /dev/null +++ b/.github/actions/cmake/build/action.yml @@ -0,0 +1,25 @@ +--- +runs: + using: composite + steps: + - name: Create `cmake` symbolic link + run: | + if ! command -v cmake &> /dev/null && command -v cmake3 &> /dev/null; then + ln --symbolic cmake3 /usr/bin/cmake + fi + shell: bash --noprofile --norc -euxo pipefail {0} + + - name: Prepare `build` directory + run: | + cmake -B build -S . \ + -LA \ + -DCMAKE_BUILD_TYPE:STRING=${BUILD_TYPE:-Release} \ + -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_PREFIX:-/usr/local} \ + -DENABLE_TESTS:BOOL=ON + shell: bash --noprofile --norc -euxo pipefail {0} + + - name: Build `mod_tile` + run: | + export CMAKE_BUILD_PARALLEL_LEVEL=${BUILD_PARALLEL_LEVEL:-$(nproc)} + cmake --build build + shell: bash --noprofile --norc -euxo pipefail {0} diff --git a/.github/actions/cmake/install/action.yml b/.github/actions/cmake/install/action.yml new file mode 100644 index 00000000..aef22734 --- /dev/null +++ b/.github/actions/cmake/install/action.yml @@ -0,0 +1,7 @@ +--- +runs: + using: composite + steps: + - name: Install `mod_tile` + run: ${{ !matrix.image && 'sudo' || '' }} cmake --install build + shell: bash --noprofile --norc -euxo pipefail {0} diff --git a/.github/actions/cmake/test/action.yml b/.github/actions/cmake/test/action.yml new file mode 100644 index 00000000..fb04fcd5 --- /dev/null +++ b/.github/actions/cmake/test/action.yml @@ -0,0 +1,31 @@ +--- +runs: + using: composite + steps: + - name: Create `ctest` symbolic link + run: | + if ! command -v ctest &> /dev/null && command -v ctest3 &> /dev/null; then + ln --symbolic ctest3 /usr/bin/ctest + fi + shell: bash --noprofile --norc -euxo pipefail {0} + + - name: Test `mod_tile` + run: ctest --exclude-regex 'clear_dirs|remove_tiles' --output-on-failure + shell: bash --noprofile --norc -euxo pipefail {0} + working-directory: build + + - name: Archive test artifacts on failure + if: failure() + run: | + TAR_FILENAME=${{ matrix.image || matrix.os || github.job }}-${{ matrix.compiler }}.tar.gz + TAR_FILENAME=$(echo "${TAR_FILENAME}" | sed 's/:/-/g') + tar -zcf ${TAR_FILENAME} tests + shell: bash --noprofile --norc -euxo pipefail {0} + working-directory: build + + - name: Upload test artifacts on failure + if: failure() + uses: actions/upload-artifact@v3 + with: + name: Test Artifacts + path: build/*.tar.gz diff --git a/.github/actions/dependencies/build-and-install/mapnik/action.yml b/.github/actions/dependencies/build-and-install/mapnik/action.yml new file mode 100644 index 00000000..0cefae6d --- /dev/null +++ b/.github/actions/dependencies/build-and-install/mapnik/action.yml @@ -0,0 +1,61 @@ +--- +inputs: + version: + description: Version of Mapnik to build & install + required: true + +runs: + using: composite + steps: + - name: Create `Mapnik` source directory + run: | + mkdir mapnik-src + shell: bash --noprofile --norc -euxo pipefail {0} + + - name: Cache "Download `Mapnik`" & "Build `Mapnik`" + id: cache-mapnik-src + uses: actions/cache@v3 + with: + path: mapnik-src + key: ${{ matrix.image }}-${{ matrix.compiler }}-mapnik-${{ inputs.version }} + + - name: Download `Mapnik` + run: | + curl --silent --location \ + https://github.com/mapnik/mapnik/releases/download/v${{ inputs.version }}/mapnik-v${{ inputs.version }}.tar.bz2 \ + | tar --extract --bzip2 --strip-components=1 --file=- + shell: bash --noprofile --norc -euxo pipefail {0} + working-directory: mapnik-src + if: steps.cache-mapnik-src.outputs.cache-hit != 'true' + + - name: Build `Mapnik` + run: | + # Export variables + export GDAL_DATA=/usr/share/gdal + export JOBS=${JOBS:-$(nproc)} + export PROJ_LIB=/usr/share/proj + export PYTHON=${PYTHON:-python3} + + # Create GDAL_DATA/PROJ_LIB directories + mkdir --parents ${GDAL_DATA} ${PROJ_LIB} + + # Configure & build + ./configure \ + CC=${CC:-gcc} \ + CXX=${CXX:-g++} \ + FAST=True \ + OPTIMIZATION=0 \ + PREFIX="/usr" + make PYTHON=${PYTHON} || make PYTHON=${PYTHON} + shell: bash --noprofile --norc -euxo pipefail {0} + working-directory: mapnik-src + if: steps.cache-mapnik-src.outputs.cache-hit != 'true' + + - name: Install `Mapnik` + run: | + # Export `PYTHON` + export PYTHON=${PYTHON:-python3} + + make install PYTHON=${PYTHON} + shell: bash --noprofile --norc -euxo pipefail {0} + working-directory: mapnik-src diff --git a/.github/actions/dependencies/build-and-install/mapnik/latest/action.yml b/.github/actions/dependencies/build-and-install/mapnik/latest/action.yml new file mode 100644 index 00000000..2ee30317 --- /dev/null +++ b/.github/actions/dependencies/build-and-install/mapnik/latest/action.yml @@ -0,0 +1,36 @@ +--- +runs: + using: composite + steps: + - name: Cache "Checkout `Mapnik`" & "Build `Mapnik`" + id: cache-mapnik + uses: actions/cache@v3 + with: + path: | + mapnik-build + mapnik-src + key: ${{ matrix.image }}-${{ matrix.compiler }}-mapnik-latest + + - name: Checkout `Mapnik` + uses: actions/checkout@v4 + with: + path: mapnik-src + repository: mapnik/mapnik + submodules: recursive + if: steps.cache-mapnik.outputs.cache-hit != 'true' + + - name: Build `Mapnik` + run: | + export CMAKE_BUILD_PARALLEL_LEVEL=${BUILD_PARALLEL_LEVEL:-$(nproc)} + cmake -B mapnik-build -S mapnik-src \ + -DBUILD_DEMO_VIEWER:BOOL=OFF \ + -DBUILD_TESTING:BOOL=OFF \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + -DCMAKE_INSTALL_PREFIX:PATH=/usr + cmake --build mapnik-build + shell: bash --noprofile --norc -euxo pipefail {0} + if: steps.cache-mapnik.outputs.cache-hit != 'true' + + - name: Install `Mapnik` + run: cmake --install mapnik-build + shell: bash --noprofile --norc -euxo pipefail {0} diff --git a/.github/actions/dependencies/install/action.yml b/.github/actions/dependencies/install/action.yml new file mode 100644 index 00000000..94a8a0ab --- /dev/null +++ b/.github/actions/dependencies/install/action.yml @@ -0,0 +1,314 @@ +--- +inputs: + debian-build-dependencies: + default: >- + apache2-dev + libcairo2-dev + libcurl4-gnutls-dev + libglib2.0-dev + libiniparser-dev + libmemcached-dev + librados-dev + debian-mapnik-latest-build-dependencies: + default: >- + cmake + git + libboost-filesystem-dev + libboost-program-options-dev + libboost-regex-dev + libfreetype6-dev + libgdal-dev + libharfbuzz-dev + libicu-dev + libjpeg-dev + libpq-dev + libproj-dev + libsqlite3-dev + libtiff-dev + libwebp-dev + libxml2-dev + postgresql-server-dev-all + debian-test-dependencies: + default: >- + apache2 + jq + fedora-build-dependencies: + default: >- + cairo-devel + glib2-devel + httpd-devel + iniparser-devel + libcurl-devel + libmemcached-devel + librados-devel + mapnik-devel + sqlite-devel + fedora-test-dependencies: + default: >- + httpd + jq + freebsd-build-dependencies: + default: >- + apache24 + cairo + coreutils + curl + glib + iniparser + libmemcached + mapnik + pkgconf + freebsd-test-dependencies: + default: >- + jq + macos-build-dependencies: + default: >- + apr + cairo + curl + glib + httpd + iniparser + libmemcached + mapnik + pkg-config + macos-test-dependencies: + default: >- + coreutils + jq + opensuse-build-dependencies: + default: >- + apache2-devel + cairo-devel + curl + glib2-devel + libcurl-devel + libiniparser-devel + libmemcached-devel + librados-devel + opensuse-test-dependencies: + default: >- + apache2 + apache2-event + apache2-prefork + jq + opensuse-mapnik-build-dependencies: + default: >- + bzip2 + freetype-devel + gdal-devel + harfbuzz-devel + libboost_filesystem1_75_0-devel + libboost_headers1_75_0-devel + libboost_program_options1_75_0-devel + libboost_regex1_75_0-devel + libboost_system1_75_0-devel + libicu-devel + libjpeg8-devel + libpng16-devel + libtiff-devel + libwebp-devel + libxml2-devel + make + postgresql-devel + proj-devel + python3 + sqlite3-devel + tar + zlib-devel + rhel-build-dependencies: + default: >- + cairo-devel + glib2-devel + httpd-devel + iniparser-devel + libcurl-devel + libmemcached-devel + librados2-devel + rhel-test-dependencies: + default: >- + httpd + jq + rhel-mapnik-build-dependencies: + default: >- + boost-devel + bzip2 + freetype-devel + gdal-devel + harfbuzz-devel + libicu-devel + libjpeg-devel + libpng-devel + libtiff-devel + libwebp-devel + libxml2-devel + make + postgresql-devel + proj-devel + python3 + sqlite-devel + tar + zlib-devel + ubuntu-build-dependencies: + default: >- + apache2-dev + libcairo2-dev + libcurl4-gnutls-dev + libglib2.0-dev + libiniparser-dev + libmemcached-dev + librados-dev + ubuntu-mapnik-latest-build-dependencies: + default: >- + cmake + git + libboost-filesystem-dev + libboost-program-options-dev + libboost-regex-dev + libfreetype6-dev + libgdal-dev + libharfbuzz-dev + libicu-dev + libjpeg-dev + libpq-dev + libproj-dev + libsqlite3-dev + libtiff-dev + libwebp-dev + libxml2-dev + postgresql-server-dev-all + ubuntu-test-dependencies: + default: >- + apache2 + jq + mapnik-build-version-centos-stream: + default: 3.1.0 + mapnik-build-version-amazonlinux2-centos7: + default: 3.0.17 + mapnik-build-version-opensuse: + default: 3.1.0 + +runs: + using: composite + steps: + - name: Install Dependencies (Amazon Linux/CentOS/CentOS Stream) + uses: ./.github/actions/dependencies/install/yum + with: + dependencies: epel-release + packages: >- + ${{ inputs.rhel-build-dependencies }} + ${{ inputs.rhel-mapnik-build-dependencies }} + ${{ inputs.rhel-test-dependencies }} + ${{ matrix.build_system == 'CMake' && 'cmake3' || 'autoconf automake redhat-rpm-config' }} + ${{ matrix.compiler == 'LLVM' && 'clang' || 'gcc gcc-c++' }} + ${{ matrix.image == 'centos:7' && matrix.compiler == 'LLVM' && 'gcc-c++' || '' }} + if: | + startsWith(matrix.image, 'amazonlinux:') || + startsWith(matrix.image, 'centos:') || + startsWith(matrix.image, 'quay.io/centos/centos:stream') + + - name: Install Dependencies (Debian) + uses: ./.github/actions/dependencies/install/apt-get + with: + packages: >- + ${{ inputs.debian-build-dependencies }} + ${{ matrix.mapnik_latest && inputs.debian-mapnik-latest-build-dependencies || 'libmapnik-dev' }} + ${{ inputs.debian-test-dependencies }} + ${{ matrix.build_system == 'CMake' && 'cmake' || '' }} + ${{ matrix.compiler == 'LLVM' && 'clang' || 'g++ gcc' }} + if: startsWith(matrix.image, 'debian:') + + - name: Install Dependencies (Fedora) + uses: ./.github/actions/dependencies/install/yum + with: + packages: >- + ${{ inputs.fedora-build-dependencies }} + ${{ inputs.fedora-test-dependencies }} + ${{ matrix.build_system == 'CMake' && 'cmake' || 'autoconf automake redhat-rpm-config' }} + ${{ matrix.compiler == 'LLVM' && 'clang' || 'gcc gcc-c++' }} + if: startsWith(matrix.image, 'fedora:') + + - name: Install Dependencies (FreeBSD) + uses: ./.github/actions/dependencies/install/pkg + with: + packages: >- + ${{ inputs.freebsd-build-dependencies }} + ${{ inputs.freebsd-test-dependencies }} + ${{ matrix.build_system == 'CMake' && 'cmake' || 'autoconf automake' }} + ${{ matrix.compiler == 'GNU' && 'gcc' || 'llvm' }} + if: github.job == 'FreeBSD' + + - name: Install Dependencies (macOS) + uses: ./.github/actions/dependencies/install/brew + with: + packages: >- + ${{ inputs.macos-build-dependencies }} + ${{ inputs.macos-test-dependencies }} + ${{ matrix.build_system == 'CMake' && 'cmake' || 'autoconf automake' }} + ${{ matrix.compiler == 'GNU' && 'gcc' || '' }} + if: github.job == 'macOS' + + - name: Install Dependencies (openSUSE) + uses: ./.github/actions/dependencies/install/zypper + with: + packages: >- + ${{ inputs.opensuse-build-dependencies }} + ${{ inputs.opensuse-mapnik-build-dependencies }} + ${{ inputs.opensuse-test-dependencies }} + ${{ matrix.build_system == 'CMake' && 'cmake' || 'automake' }} + ${{ matrix.compiler == 'LLVM' && 'clang' || 'gcc12 gcc12-c++' }} + if: startsWith(matrix.image, 'opensuse/') + + - name: Install Dependencies (Ubuntu) + uses: ./.github/actions/dependencies/install/apt-get + with: + packages: >- + ${{ inputs.ubuntu-build-dependencies }} + ${{ matrix.mapnik_latest && inputs.ubuntu-mapnik-latest-build-dependencies || 'libmapnik-dev' }} + ${{ inputs.ubuntu-test-dependencies }} + ${{ matrix.build_system == 'CMake' && 'cmake' || '' }} + ${{ matrix.compiler == 'LLVM' && 'clang' || 'g++ gcc' }} + if: | + startsWith(matrix.image, 'ubuntu:') || + (!matrix.image && github.job != 'FreeBSD' && runner.os == 'Linux') + + - name: Link `gcc`/`g++` (openSUSE) + run: | + update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 40 + update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 40 + shell: bash --noprofile --norc -euxo pipefail {0} + if: startsWith(matrix.image, 'opensuse/') && matrix.compiler == 'GNU' + + - name: Add `nobody` user/group (openSUSE) + run: | + useradd --home-dir / --no-create-home --shell /usr/sbin/nologin --system --user-group nobody + shell: bash --noprofile --norc -euxo pipefail {0} + if: startsWith(matrix.image, 'opensuse/') + + - name: Build & Install `mapnik` (Amazon Linux 2/CentOS 7) + uses: ./.github/actions/dependencies/build-and-install/mapnik + with: + version: ${{ inputs.mapnik-build-version-amazonlinux2-centos7 }} + if: matrix.image == 'amazonlinux:2' || matrix.image == 'centos:7' + + - name: Build & Install `mapnik` (CentOS Stream) + uses: ./.github/actions/dependencies/build-and-install/mapnik + with: + version: ${{ inputs.mapnik-build-version-centos-stream }} + if: startsWith(matrix.image, 'quay.io/centos/centos:stream') + + - name: Build & Install `mapnik` (openSUSE) + uses: ./.github/actions/dependencies/build-and-install/mapnik + with: + version: ${{ inputs.mapnik-build-version-opensuse }} + if: (!matrix.mapnik_latest && startsWith(matrix.image, 'opensuse/')) + + - name: Build & Install latest `mapnik` (Debian/Ubuntu) + uses: ./.github/actions/dependencies/build-and-install/mapnik/latest + if: | + matrix.mapnik_latest && + (startsWith(matrix.image, 'debian:') || startsWith(matrix.image, 'ubuntu:')) + + - name: Build & Install latest `mapnik` (openSUSE) + uses: ./.github/actions/dependencies/build-and-install/mapnik/latest + if: (matrix.mapnik_latest && startsWith(matrix.image, 'opensuse/')) diff --git a/.github/actions/dependencies/install/apt-get/action.yml b/.github/actions/dependencies/install/apt-get/action.yml new file mode 100644 index 00000000..a5b3917b --- /dev/null +++ b/.github/actions/dependencies/install/apt-get/action.yml @@ -0,0 +1,18 @@ +--- +inputs: + packages: + description: List of package(s) to install + required: true + +runs: + using: composite + steps: + - name: Update package information + run: ${{ !matrix.image && 'sudo' || '' }} apt-get --yes update + shell: bash --noprofile --norc -euxo pipefail {0} + + - name: Install package(s) + env: + DEBIAN_FRONTEND: noninteractive + run: ${{ !matrix.image && 'sudo' || '' }} apt-get --yes install ${{ inputs.packages }} + shell: bash --noprofile --norc -euxo pipefail {0} diff --git a/.github/actions/dependencies/install/brew/action.yml b/.github/actions/dependencies/install/brew/action.yml new file mode 100644 index 00000000..1ce176e9 --- /dev/null +++ b/.github/actions/dependencies/install/brew/action.yml @@ -0,0 +1,12 @@ +--- +inputs: + packages: + description: List of package(s) to install + required: true + +runs: + using: composite + steps: + - name: Install package(s) + run: brew install ${{ inputs.packages }} || true + shell: bash --noprofile --norc -euxo pipefail {0} diff --git a/.github/actions/dependencies/install/pkg/action.yml b/.github/actions/dependencies/install/pkg/action.yml new file mode 100644 index 00000000..b57d6abb --- /dev/null +++ b/.github/actions/dependencies/install/pkg/action.yml @@ -0,0 +1,15 @@ +--- +inputs: + packages: + description: List of package(s) to install + required: true + options: + default: --yes + description: Option(s) to pass + +runs: + using: composite + steps: + - name: Install package(s) + run: ${{ !matrix.image && 'sudo' || '' }} pkg install ${{ inputs.options }} ${{ inputs.packages }} + shell: bash --noprofile --norc -euxo pipefail {0} diff --git a/.github/actions/dependencies/install/yum/action.yml b/.github/actions/dependencies/install/yum/action.yml new file mode 100644 index 00000000..353c4344 --- /dev/null +++ b/.github/actions/dependencies/install/yum/action.yml @@ -0,0 +1,57 @@ +--- +inputs: + dependencies: + description: List of package(s) to pre-install + required: false + groups: + description: List of group(s) to install + required: false + packages: + description: List of package(s) to install + required: true + +runs: + using: composite + steps: + - name: Install "dnf-command(config-manager)" (CentOS Stream) + run: dnf --assumeyes --skip-broken install "dnf-command(config-manager)" + shell: bash --noprofile --norc -euxo pipefail {0} + if: startsWith(matrix.image, 'quay.io/centos/centos:stream') + + - name: Enable PowerTools repository (CentOS Stream 8) + run: dnf config-manager --set-enabled powertools + shell: bash --noprofile --norc -euxo pipefail {0} + if: matrix.image == 'quay.io/centos/centos:stream8' + + - name: Enable CRB repository (CentOS Stream 9) + run: dnf config-manager --set-enabled crb + shell: bash --noprofile --norc -euxo pipefail {0} + if: matrix.image == 'quay.io/centos/centos:stream9' + + - name: Enable EPEL repository (Amazon Linux 2) + run: amazon-linux-extras install epel -y + shell: bash --noprofile --norc -euxo pipefail {0} + if: matrix.image == 'amazonlinux:2' && contains(inputs.dependencies, 'epel-release') + + - name: Install dependency package(s) + run: | + if [ -n "${{ inputs.dependencies }}" ]; then + yum --assumeyes install ${{ inputs.dependencies }} + fi + shell: bash --noprofile --norc -euxo pipefail {0} + + - name: Install group(s) + run: | + if [ -n '${{ inputs.groups }}' ]; then + yum --assumeyes groups install ${{ inputs.groups }} + fi + shell: bash --noprofile --norc -euxo pipefail {0} + + - name: Install package(s) + run: | + if command -v dnf5 &> /dev/null; then + yum --assumeyes install ${{ inputs.packages }} + else + yum --assumeyes --skip-broken install ${{ inputs.packages }} + fi + shell: bash --noprofile --norc -euxo pipefail {0} diff --git a/.github/actions/dependencies/install/zypper/action.yml b/.github/actions/dependencies/install/zypper/action.yml new file mode 100644 index 00000000..9875749e --- /dev/null +++ b/.github/actions/dependencies/install/zypper/action.yml @@ -0,0 +1,12 @@ +--- +inputs: + packages: + description: List of package(s) to install + required: true + +runs: + using: composite + steps: + - name: Install package(s) + run: ${{ !matrix.image && 'sudo' || '' }} zypper --non-interactive install ${{ inputs.packages }} + shell: bash --noprofile --norc -euxo pipefail {0} diff --git a/.github/actions/install/action.yml b/.github/actions/install/action.yml new file mode 100644 index 00000000..5a48d208 --- /dev/null +++ b/.github/actions/install/action.yml @@ -0,0 +1,11 @@ +--- +runs: + using: composite + steps: + - name: Install `mod_tile` (Autotools) + uses: ./.github/actions/autotools/install + if: matrix.build_system == 'Autotools' + + - name: Install `mod_tile` (CMake) + uses: ./.github/actions/cmake/install + if: matrix.build_system == 'CMake' diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml new file mode 100644 index 00000000..827a03a5 --- /dev/null +++ b/.github/actions/test/action.yml @@ -0,0 +1,11 @@ +--- +runs: + using: composite + steps: + - name: Test `mod_tile` (Autotools) + uses: ./.github/actions/autotools/test + if: matrix.build_system == 'Autotools' + + - name: Test `mod_tile` (CMake) + uses: ./.github/actions/cmake/test + if: matrix.build_system == 'CMake' diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 00000000..63cf5b77 --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,232 @@ +--- +name: Build & Test + +on: + pull_request: + push: + +jobs: + Linux: + name: >- + ${{ matrix.image }} + (${{ matrix.build_system }}) + (${{ matrix.compiler }}) + runs-on: ubuntu-latest + strategy: + matrix: + image: + - "centos:7" + - "debian:11" + - "debian:12" + - "debian:testing" + - "fedora:38" + - "fedora:39" + - "fedora:rawhide" + - "opensuse/leap:15" + - "ubuntu:20.04" + - "ubuntu:rolling" + build_system: + - CMake + compiler: + - GNU + on_default_branch: + - ${{ contains(github.ref, 'master') || contains(github.ref, 'develop') || contains(github.ref, 'CI') }} + include: + - image: "ubuntu:22.04" + build_system: Autotools + compiler: GNU + - image: "ubuntu:22.04" + build_system: Autotools + compiler: LLVM + - image: "ubuntu:22.04" + build_system: CMake + compiler: GNU + - image: "ubuntu:22.04" + build_system: CMake + compiler: LLVM + exclude: + - on_default_branch: false + fail-fast: false + container: + env: + CC: ${{ matrix.compiler == 'LLVM' && 'clang' || 'gcc' }} + CXX: ${{ matrix.compiler == 'LLVM' && 'clang++' || 'g++' }} + image: ${{ matrix.image }} + steps: + - name: Install `git` (Amazon Linux 2) + run: yum --assumeyes install git + if: matrix.image == 'amazonlinux:2' + + - name: Install `git` (openSUSE) + run: zypper --non-interactive install git + if: startsWith(matrix.image, 'opensuse/') + + - name: Checkout code (CentOS 7) + uses: actions/checkout@v3 + if: matrix.image == 'centos:7' + + - name: Checkout code + uses: actions/checkout@v4 + if: matrix.image != 'centos:7' + + - name: Install dependencies + uses: ./.github/actions/dependencies/install + + - name: Build `mod_tile` + uses: ./.github/actions/build + + - name: Test `mod_tile` + uses: ./.github/actions/test + + - name: Install `mod_tile` + uses: ./.github/actions/install + + Linux-Latest-Mapnik: + continue-on-error: true + name: >- + ${{ matrix.image }} + (Latest Mapnik) + (${{ matrix.build_system }}) + (${{ matrix.compiler }}) + runs-on: ubuntu-latest + strategy: + matrix: + image: + - "debian:12" + - "ubuntu:22.04" + build_system: + - CMake + compiler: + - GNU + mapnik_latest: + - true + fail-fast: false + container: + env: + CC: ${{ matrix.compiler == 'LLVM' && 'clang' || 'gcc' }} + CXX: ${{ matrix.compiler == 'LLVM' && 'clang++' || 'g++' }} + image: ${{ matrix.image }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + uses: ./.github/actions/dependencies/install + + - name: Build `mod_tile` + uses: ./.github/actions/build + + - name: Test `mod_tile` + uses: ./.github/actions/test + + - name: Install `mod_tile` + uses: ./.github/actions/install + + macOS: + env: + CFLAGS: -Wno-implicit-function-declaration + LDFLAGS: -undefined dynamic_lookup + LIBRARY_PATH: /usr/local/lib + name: >- + ${{ matrix.os }} + (${{ matrix.build_system }}) + (${{ matrix.compiler }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - macos-12 + build_system: + - CMake + compiler: + - LLVM + on_default_branch: + - ${{ contains(github.ref, 'master') || contains(github.ref, 'develop') || contains(github.ref, 'CI') }} + include: + - os: macos-13 + build_system: Autotools + compiler: LLVM + - os: macos-13 + build_system: CMake + compiler: LLVM + exclude: + - on_default_branch: false + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + uses: ./.github/actions/dependencies/install + + - name: Set ICU_ROOT + run: | + echo "ICU_ROOT=$(brew --prefix icu4c)" >> ${GITHUB_ENV} + + - name: Build `mod_tile` + uses: ./.github/actions/build + + - name: Test `mod_tile` + uses: ./.github/actions/test + + - name: Install `mod_tile` + uses: ./.github/actions/install + + FreeBSD: + continue-on-error: true + env: + BUILD_PARALLEL_LEVEL: 2 + LIBRARY_PATH: /usr/local/lib + TMPDIR: /tmp + name: >- + ${{ matrix.box_generic }} + (${{ matrix.build_system }}) + (${{ matrix.compiler }}) + runs-on: ubuntu-latest + strategy: + matrix: + box_generic: + - freebsd12 + - freebsd13 + build_system: + - CMake + compiler: + - LLVM + on_default_branch: + - ${{ contains(github.ref, 'master') || contains(github.ref, 'develop') || contains(github.ref, 'CI') }} + include: + - box_generic: freebsd14 + build_system: CMake + compiler: LLVM + exclude: + - on_default_branch: false + fail-fast: false + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Provision VM + uses: hummeltech/freebsd-vagrant-action@v1.4 + with: + box: generic/${{ matrix.box_generic }} + cpus: ${{ env.BUILD_PARALLEL_LEVEL }} + memory: 4096 + + # Mapnik is not in the `quarterly` repository (2023.10.12) + - name: Use "latest" repository + run: | + sudo mkdir -p /usr/local/etc/pkg/repos + sed 's#/quarterly#/latest#g' /etc/pkg/FreeBSD.conf | sudo tee /usr/local/etc/pkg/repos/FreeBSD.conf + sudo pkg upgrade + + - name: Install dependencies + uses: ./.github/actions/dependencies/install + + - name: Build `mod_tile` + uses: ./.github/actions/build + + - name: Test `mod_tile` + uses: ./.github/actions/test + + - name: Install `mod_tile` + uses: ./.github/actions/install diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 00000000..ea4cf6e1 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,68 @@ +--- +name: Coverage + +on: + pull_request: + push: + branches: + - develop + - master + - "*CI" + +jobs: + Coverage: + name: Build, Test & Report Coverage + runs-on: ubuntu-latest + env: + BUILD_TYPE: Debug + CFLAGS: --coverage + CXXFLAGS: --coverage + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + uses: ./.github/actions/dependencies/install + with: + ubuntu-test-dependencies: >- + apache2 + lcov + + - name: Build `mod_tile` + uses: ./.github/actions/cmake/build + + - name: Test `mod_tile` + uses: ./.github/actions/cmake/test + + - name: Test `mod_tile` again (to gather more coverage data) + uses: ./.github/actions/cmake/test + + - name: Process `mod_tile` coverage results + run: | + ctest -T coverage + lcov \ + --capture \ + --directory . \ + --output-file coverage.info + lcov \ + --output-file coverage.info \ + --remove coverage.info \ + "${GITHUB_WORKSPACE}/includes/catch/catch.hpp" \ + "${GITHUB_WORKSPACE}/src/gen_tile_test.cpp" \ + "/usr/*" + genhtml coverage.info --output-directory coverage + working-directory: build + + - name: Write coverage summary to `$GITHUB_STEP_SUMMARY` + run: lcov --summary build/coverage.info | sed 's/^ /* /g' >> ${GITHUB_STEP_SUMMARY} + + - name: Upload `mod_tile` coverage results artifact + uses: actions/upload-artifact@v3 + with: + name: Coverage Results + path: build/coverage + + - name: Report `mod_tile` coverage results to `codecov.io` + uses: codecov/codecov-action@v3 + with: + files: build/coverage.info diff --git a/.github/workflows/flawfinder-analysis.yml b/.github/workflows/flawfinder-analysis.yml new file mode 100644 index 00000000..68c96eb7 --- /dev/null +++ b/.github/workflows/flawfinder-analysis.yml @@ -0,0 +1,34 @@ +--- +name: flawfinder + +on: + pull_request: + push: + branches: + - develop + - master + schedule: + - cron: "44 0 * * 4" + +jobs: + flawfinder: + name: Flawfinder + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: flawfinder_scan + uses: david-a-wheeler/flawfinder@2.0.19 + with: + arguments: "--sarif includes src" + output: "flawfinder_results.sarif" + + - name: Upload analysis results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: ${{github.workspace}}/flawfinder_results.sarif diff --git a/.github/workflows/install-package-and-test.yml b/.github/workflows/install-package-and-test.yml new file mode 100644 index 00000000..4a6f7103 --- /dev/null +++ b/.github/workflows/install-package-and-test.yml @@ -0,0 +1,78 @@ +--- +name: Install Package & Test + +on: + - push + +jobs: + install-package-and-test: + name: ${{ matrix.image }} + runs-on: ubuntu-latest + strategy: + matrix: + image: + - "debian:11" + - "debian:12" + - "ubuntu:22.04" + fail-fast: false + container: + image: ${{ matrix.image }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install mod_tile & renderd + uses: ./.github/actions/dependencies/install/apt-get + with: + packages: >- + apache2 + curl + libapache2-mod-tile + renderd + + - name: Prepare + run: | + mkdir -p /usr/share/renderd + cp -av utils/example-map /usr/share/renderd/ + cp -av etc/apache2/renderd-example-map.conf /etc/apache2/sites-available/renderd-example-map.conf + printf ' + [example-map] + URI=/tiles/renderd-example + XML=/usr/share/renderd/example-map/mapnik.xml + + [example-map-jpg] + TYPE=jpg image/jpeg jpeg + URI=/tiles/renderd-example-jpg + XML=/usr/share/renderd/example-map/mapnik.xml + + [example-map-png256] + TYPE=png image/png png256 + URI=/tiles/renderd-example-png256 + XML=/usr/share/renderd/example-map/mapnik.xml + + [example-map-png32] + TYPE=png image/png png32 + URI=/tiles/renderd-example-png32 + XML=/usr/share/renderd/example-map/mapnik.xml + + [example-map-webp] + TYPE=webp image/webp webp + URI=/tiles/renderd-example-webp + XML=/usr/share/renderd/example-map/mapnik.xml + ' | tee -a /etc/renderd.conf + mkdir -p /var/run/renderd + renderd + a2enmod tile + a2ensite renderd-example-map + apache2ctl restart + shell: bash --noprofile --norc -euxo pipefail {0} + + - name: Test + run: | + until $(curl --fail --output tile.png --silent http://localhost:8081/tiles/renderd-example/9/297/191.png); do + echo 'Sleeping 5s'; + sleep 5; + done + echo 'dbf26531286e844a3a9735cdd193598dca78d22f77cafe5824bcaf17f88cbb08 tile.png' | sha256sum --check + shell: bash --noprofile --norc -euxo pipefail {0} + timeout-minutes: 1 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..26060aed --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,89 @@ +--- +name: Lint + +on: + pull_request: + push: + +jobs: + astyle: + env: + ASTYLE_CMD: >- + astyle + --break-blocks + --indent-switches + --indent=force-tab=8 + --lineend=linux + --options=none + --pad-header + --pad-oper + --style=1tbs + --suffix=none + --unpad-paren + includes/*.h includes/*.hpp src/*.c src/*.cpp + name: Lint with `Artistic Style` + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Provision environment + uses: ./.github/actions/dependencies/install/apt-get + with: + packages: astyle + - name: Check if any modifications were made by `astyle` + run: | + ASTYLE_OUTPUT=$(${ASTYLE_CMD} --dry-run) + if [ -n "$(echo "${ASTYLE_OUTPUT}" | grep -v "Unchanged")" ]; then + echo "The following files are in need of formatting:" + echo "${ASTYLE_OUTPUT}" | grep -v "Unchanged" | awk '{print "`"$2"`"}' + echo "" + echo "Run the following command before submitting a pull request:" + echo '`'"${ASTYLE_CMD}"'`' + exit 1 + fi + - name: Write `$ASTYLE_OUTPUT` to `$GITHUB_STEP_SUMMARY` + if: failure() + run: | + ASTYLE_OUTPUT=$(${ASTYLE_CMD} --dry-run) + echo "### The following files are in need of formatting:" >> ${GITHUB_STEP_SUMMARY} + echo "${ASTYLE_OUTPUT}" | grep -v "Unchanged" | awk '{print "- `"$2"`"}' >> ${GITHUB_STEP_SUMMARY} + echo "### Run the following command before submitting a pull request:" >> ${GITHUB_STEP_SUMMARY} + echo -e '```shell\n'"${ASTYLE_CMD}"'\n```' >> ${GITHUB_STEP_SUMMARY} + - name: Generate `ArtisticStyleFormattingFixes.patch` file + if: failure() + run: | + ${ASTYLE_CMD} + git diff --patch > ArtisticStyleFormattingFixes.patch + - name: Upload `ArtisticStyleFormattingFixes.patch` file + if: failure() + uses: actions/upload-artifact@v3 + with: + name: ArtisticStyleFormattingFixes.patch + path: ArtisticStyleFormattingFixes.patch + + cmakelint: + name: Lint with `CMakeLint` + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Provision environment + run: pip install --user cmakelint + - name: Run linter + run: | + cmakelint --linelength=125 \ + CMakeLists.txt \ + */CMakeLists.txt \ + */*.cmake + + prettier: + name: Lint with `Prettier` + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Provision environment + run: npm install prettier + - name: Run linter + run: | + npx prettier --check . diff --git a/.gitignore b/.gitignore index ce454cc0..860ca30e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,36 +1,49 @@ -Makefile* -*.o +.deps/ +.dirstamp +.libs/ *.la *.lo +*.o *.slo -.deps/ -.libs/ +aclocal.m4 autom4te.cache/ +build +!docs/build +compile config.guess +config.guess~ config.h config.h.in config.h.in~ config.log config.status config.sub +config.sub~ configure +configure~ depcomp gen_tile_test -iniparser3.0b/.deps/ -iniparser3.0b/.libs/ install-sh libtool ltmain.sh +m4/libtool.m4 +m4/lt~obsolete.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +Makefile* missing render_expired render_list render_old render_speedtest renderd +renderd.sock +renderd.stats stamp-h1 -aclocal.m4 -m4/libtool.m4 -m4/ltoptions.m4 -m4/ltsugar.m4 -m4/ltversion.m4 -m4/lt~obsolete.m4 +stderr.out + +# Do not ignore +!Makefile.am +!etc/renderd +!.github/**/* diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fc5697e2..00000000 --- a/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -language: cpp - -compiler: - - clang - - gcc - -before_install: - #- sudo apt-add-repository --yes ppa:mapnik/nightly-trunk - #- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - - sudo apt-get update -y - -install: - - sudo apt-get -y install build-essential apache2-threaded-dev autotools-dev automake libtool - #- sudo apt-get install -y gcc-4.8 g++-4.8 - -before_script: - - sudo apt-get -y install libmapnik2-2.0 libmapnik-dev mapnik-utils - - #- sudo apt-get -qq install libmapnik=3.0.0* mapnik-utils=3.0.0* libmapnik-dev=3.0.0* mapnik-input-plugin*=3.0.0* - -script: - #- if [ "${CXX}" = 'g++' ]; then export CXX="g++-4.8" && export CC="gcc-4.8"; fi; - # workaround https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=63403 and https://bugs.launchpad.net/ubuntu/+source/cairomm/+bug/452733 - - export CXXFLAGS="-I/usr/lib/x86_64-linux-gnu/sigc++-2.0/include/" - - ./autogen.sh - - ./configure - - make - - make test diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..de5cddf0 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,42 @@ +Ævar Arnfjörð Bjarmason +Amanda +Andreas Hubel +Anton Belichkov +Bas Couwenberg +Ben Hosmer +Ben Kochie +Brian Quinion +Christoph Brill +Dane Springmeyer +David Hummel <6109326+hummeltech@users.noreply.github.com> +Dirk Stöcker +Eric Stadtherr +Felix Delattre +Frederik Ramm +Ircama +JaimeLynSchatz +Jocelyn Jaubert +Jochen Topf +Jon Burgess +Kai Krueger +Lennard voor den Dag +Manfred Stock +Matt Amos +Michael Fazio +Michael Schmiedgen +Moritz Seemann +Paul Norman +Peter Körner +Rainer Jung +Ramunas +Robert Buchholz +rusvdw +Sean Reifschneider +SomeoneElseOSM +Stephan Austermühle +Stephan Knauss +Stephan Plepelits +Tom Hughes +vholten +Xin Yu +Zverik diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..8fdd0dca --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,298 @@ +#----------------------------------------------------------------------------- +# +# CMake Config +# +#----------------------------------------------------------------------------- + +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") + +#----------------------------------------------------------------------------- +# +# Project version +# +#----------------------------------------------------------------------------- + +project(mod_tile VERSION 0.7.0) + +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(THREADS_PREFER_PTHREAD_FLAG ON) + +set(ENABLE_MAN ON CACHE BOOL "Build man pages") +set(ENABLE_TESTS OFF CACHE BOOL "Build test suite") +set(CMAKE_INSTALL_MODULESDIR CACHE PATH "Apache HTTP Server module installation directory") + +#----------------------------------------------------------------------------- +# +# Find external dependencies +# +#----------------------------------------------------------------------------- + +include(GNUInstallDirs) + +# Packages +find_package(CURL) +find_package(ICU REQUIRED uc) +find_package(Threads REQUIRED) + +find_package(APR REQUIRED) +find_package(CAIRO REQUIRED) +find_package(GLIB REQUIRED) +find_package(HTTPD REQUIRED) +find_package(INIPARSER REQUIRED) +find_package(LIBMAPNIK REQUIRED) +find_package(LIBMEMCACHED) +find_package(LIBRADOS) + +if(LIBMAPNIK_VERSION STRGREATER_EQUAL "4") + set(CMAKE_CXX_STANDARD 14) +endif() + +# Programs +find_program(APXS_EXECUTABLE apxs REQUIRED) + +# Functions +include(CheckFunctionExists) +# check_function_exists(bzero HAVE_BZERO) +check_function_exists(daemon HAVE_DAEMON) +# check_function_exists(gethostbyname HAVE_GETHOSTBYNAME) +check_function_exists(getloadavg HAVE_GETLOADAVG) +# check_function_exists(gettimeofday HAVE_GETTIMEOFDAY) +# check_function_exists(inet_ntoa HAVE_INET_NTOA) +# check_function_exists(memset HAVE_MEMSET) +# check_function_exists(mkdir HAVE_MKDIR) +# check_function_exists(pow HAVE_POW) +# check_function_exists(select HAVE_SELECT) +# check_function_exists(socket HAVE_SOCKET) +# check_function_exists(strchr HAVE_STRCHR) +# check_function_exists(strdup HAVE_STRDUP) +# check_function_exists(strerror HAVE_STRERROR) +# check_function_exists(strrchr HAVE_STRRCHR) +# check_function_exists(strstr HAVE_STRSTR) +# check_function_exists(strtol HAVE_STRTOL) +# check_function_exists(strtoul HAVE_STRTOUL) +# check_function_exists(utime HAVE_UTIME) + +# Include files +include(CheckIncludeFile) +# check_include_file(arpa/inet.h HAVE_ARPA_INET_H) +# check_include_file(fcntl.h HAVE_FCNTL_H) +# check_include_file(limits.h HAVE_LIMITS_H) +# check_include_file(netdb.h HAVE_NETDB_H) +# check_include_file(netinet/in.h HAVE_NETINET_IN_H) +check_include_file(paths.h HAVE_PATHS_H) +# check_include_file(stdint.h HAVE_STDINT_H) +# check_include_file(stdlib.h HAVE_STDLIB_H) +# check_include_file(string.h HAVE_STRING_H) +check_include_file(sys/cdefs.h HAVE_SYS_CDEFS_H) +check_include_file(sys/loadavg.h HAVE_SYS_LOADAVG_H) +# check_include_file(sys/socket.h HAVE_SYS_SOCKET_H) +# check_include_file(sys/time.h HAVE_SYS_TIME_H) +# check_include_file(syslog.h HAVE_SYSLOG_H) +# check_include_file(unistd.h HAVE_UNISTD_H) +# check_include_file(utime.h HAVE_UTIME_H) + +#----------------------------------------------------------------------------- +# +# Set variables +# +#----------------------------------------------------------------------------- + +execute_process(COMMAND ${APXS_EXECUTABLE} -q libexecdir + OUTPUT_VARIABLE HTTPD_LIBEXECDIR + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +execute_process(COMMAND ${APXS_EXECUTABLE} -q sysconfdir + OUTPUT_VARIABLE HTTPD_SYSCONFDIR + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +if(LIBMAPNIK_VERSION STRLESS "4") + find_program(MAPNIK_CONFIG_EXECUTABLE NAMES mapnik-config REQUIRED) + execute_process(COMMAND ${MAPNIK_CONFIG_EXECUTABLE} --fonts + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE MAPNIK_FONTS_DIR + ) + execute_process(COMMAND ${MAPNIK_CONFIG_EXECUTABLE} --input-plugins + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE MAPNIK_PLUGINS_DIR + ) +elseif(LIBMAPNIK_VERSION STRGREATER_EQUAL "4") + pkg_get_variable(MAPNIK_FONTS_DIR libmapnik fonts_dir) + pkg_get_variable(MAPNIK_PLUGINS_DIR libmapnik plugins_dir) +endif() + +if(NOT CMAKE_INSTALL_MODULESDIR) + set(CMAKE_INSTALL_MODULESDIR ${HTTPD_LIBEXECDIR}) +endif() + +if(CAIRO_FOUND) + set(HAVE_CAIRO 1) +endif() + +if(CURL_FOUND) + set(HAVE_LIBCURL 1) +endif() + +if(LIBMEMCACHED_FOUND) + set(HAVE_LIBMEMCACHED 1) +endif() + +if(LIBRADOS_FOUND) + set(HAVE_LIBRADOS 1) +endif() + +if(CMAKE_HAVE_PTHREAD_H) + set(HAVE_PTHREAD 1) +endif() + +set(MAPNIK_FONTS_DIR "${MAPNIK_FONTS_DIR}") +set(MAPNIK_FONTS_DIR_RECURSE 0) +set(MAPNIK_PLUGINS_DIR "${MAPNIK_PLUGINS_DIR}") +set(RENDERD_CONFIG "/${CMAKE_INSTALL_SYSCONFDIR}/renderd.conf") +set(RENDERD_RUN_DIR "/${CMAKE_INSTALL_RUNSTATEDIR}/renderd") +set(RENDERD_TILE_DIR "/${CMAKE_INSTALL_LOCALSTATEDIR}/cache/renderd/tiles") + +set(RENDERD_PIDFILE "${RENDERD_RUN_DIR}/renderd.pid") +set(RENDERD_SOCKET "${RENDERD_RUN_DIR}/renderd.sock") + +set(TILE_LOAD_DIRECTORY "${HTTPD_SYSCONFDIR}") +set(TILE_LOAD_FILENAME "tile.load") +set(VERSION "${PROJECT_VERSION}") + +#----------------------------------------------------------------------------- +# +# Configure +# +#----------------------------------------------------------------------------- + +# include/config.h.in +configure_file( + ${PROJECT_SOURCE_DIR}/includes/config.h.in + ${PROJECT_SOURCE_DIR}/includes/config.h +) + +# etc/apache2/tile.load.in +configure_file( + ${PROJECT_SOURCE_DIR}/etc/apache2/tile.load.in + ${PROJECT_BINARY_DIR}/tile.load +) + +# etc/renderd/renderd.conf.in +configure_file( + ${PROJECT_SOURCE_DIR}/etc/renderd/renderd.conf.in + ${PROJECT_BINARY_DIR}/renderd.conf +) + +#----------------------------------------------------------------------------- +# +# Build +# +#----------------------------------------------------------------------------- + +add_subdirectory(src) + +#----------------------------------------------------------------------------- +# +# Install +# +#----------------------------------------------------------------------------- + +# Determine install destination for 'etc/apache2/tile.load.in' +if(EXISTS "/etc/os-release") + execute_process(COMMAND sh -c ". /etc/os-release && echo $ID" + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE DISTRO_ID + ) + message(STATUS "Found ID='${DISTRO_ID}' in '/etc/os-release'") + if(DISTRO_ID MATCHES "arch") + set(TILE_LOAD_DIRECTORY "${HTTPD_SYSCONFDIR}/extra") + set(TILE_LOAD_FILENAME "httpd-tile.conf") + elseif(DISTRO_ID MATCHES "centos|fedora|rhel") + set(TILE_LOAD_DIRECTORY "${HTTPD_SYSCONFDIR}.modules.d") + set(TILE_LOAD_FILENAME "11-tile.conf") + elseif(DISTRO_ID MATCHES "debian|ubuntu") + set(TILE_LOAD_DIRECTORY "${HTTPD_SYSCONFDIR}/mods-available") + elseif(DISTRO_ID MATCHES "freebsd") + set(TILE_LOAD_DIRECTORY "${HTTPD_SYSCONFDIR}/modules.d") + set(TILE_LOAD_FILENAME "080_tile.conf") + elseif(DISTRO_ID MATCHES "opensuse-leap") + set(TILE_LOAD_DIRECTORY "${HTTPD_SYSCONFDIR}/conf.d") + set(TILE_LOAD_FILENAME "mod_tile.conf") + endif() +elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") + set(TILE_LOAD_DIRECTORY "${HTTPD_SYSCONFDIR}/extra") + set(TILE_LOAD_FILENAME "httpd-tile.conf") +endif() +message(STATUS "File 'etc/apache2/tile.load.in' will be installed to '${TILE_LOAD_DIRECTORY}/${TILE_LOAD_FILENAME}'") + +# Directories +install( + DIRECTORY + DESTINATION ${RENDERD_TILE_DIR} +) + +install( + DIRECTORY + DESTINATION ${RENDERD_RUN_DIR} +) + +# Configuration files +install( + FILES + ${PROJECT_BINARY_DIR}/tile.load + DESTINATION ${TILE_LOAD_DIRECTORY} + RENAME ${TILE_LOAD_FILENAME} +) + +install( + FILES + ${PROJECT_BINARY_DIR}/renderd.conf + DESTINATION /${CMAKE_INSTALL_SYSCONFDIR} +) + +# Targets +install( + TARGETS + mod_tile + render_expired + render_list + render_old + render_speedtest + renderd + LIBRARY DESTINATION ${CMAKE_INSTALL_MODULESDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +# Man files +if(ENABLE_MAN) + install( + FILES + docs/man/render_expired.1 + docs/man/render_list.1 + docs/man/render_old.1 + docs/man/render_speedtest.1 + docs/man/renderd.1 + DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 + ) + install( + FILES + docs/man/renderd.conf.5 + DESTINATION ${CMAKE_INSTALL_MANDIR}/man5 + ) +endif() + +#----------------------------------------------------------------------------- +# +# Test +# +#----------------------------------------------------------------------------- + +if(ENABLE_TESTS) + enable_testing() + add_subdirectory(tests) +endif() diff --git a/Makefile.am b/Makefile.am index 7fe98fac..f822e008 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,57 +1,144 @@ AUTOMAKE_OPTIONS = foreign -if !SYSTEM_LIBINIPARSER - SUBDIRS = iniparser3.0b -endif ACLOCAL_AMFLAGS = -I m4 -AM_CPPFLAGS = $(PTHREAD_CFLAGS) -DSYSTEM_LIBINIPARSER=@SYSTEM_LIBINIPARSER@ +AM_CPPFLAGS = $(PTHREAD_CFLAGS) $(GLIB_CFLAGS) + +STORE_SOURCES = \ + src/store.c \ + src/store_file.c \ + src/store_file_utils.c \ + src/store_memcached.c \ + src/store_rados.c \ + src/store_ro_http_proxy.c \ + src/store_ro_composite.c \ + src/store_null.c \ + src/g_logger.c +STORE_LDFLAGS = $(LIBMEMCACHED_LDFLAGS) $(LIBRADOS_LDFLAGS) $(LIBCURL) $(GLIB_LIBS) -STORE_SOURCES = src/store.c src/store_file.c src/store_file_utils.c src/store_memcached.c src/store_rados.c src/store_ro_http_proxy.c src/store_ro_composite.c src/store_null.c -STORE_LDFLAGS = $(LIBMEMCACHED_LDFLAGS) $(LIBRADOS_LDFLAGS) $(LIBCURL) STORE_CPPFLAGS = -bin_PROGRAMS = renderd render_expired render_list render_speedtest render_old +bin_PROGRAMS = \ + renderd \ + render_expired \ + render_list \ + render_speedtest \ + render_old noinst_PROGRAMS = gen_tile_test -man_MANS = docs/renderd.8 docs/render_expired.1 docs/render_list.1 docs/render_old.1 docs/render_speedtest.1 + +man_MANS = \ + docs/man/renderd.1 \ + docs/man/renderd.conf.5 \ + docs/man/render_expired.1 \ + docs/man/render_list.1 \ + docs/man/render_old.1 \ + docs/man/render_speedtest.1 renderddir = $(sysconfdir) -renderd_SOURCES = src/daemon.c src/daemon_compat.c src/gen_tile.cpp src/sys_utils.c src/request_queue.c src/cache_expire.c src/metatile.cpp src/parameterize_style.cpp src/protocol_helper.c $(STORE_SOURCES) + +renderd_SOURCES = \ + src/daemon.c \ + src/daemon_compat.c \ + src/gen_tile.cpp \ + src/sys_utils.c \ + src/request_queue.c \ + src/cache_expire.c \ + src/metatile.cpp \ + src/parameterize_style.cpp \ + src/protocol_helper.c \ + $(STORE_SOURCES) renderd_CXXFLAGS = $(MAPNIK_CFLAGS) -renderd_LDADD = $(PTHREAD_CFLAGS) $(MAPNIK_LDFLAGS) $(STORE_LDFLAGS) -liniparser -if !SYSTEM_LIBINIPARSER - renderd_SOURCES += iniparser3.0b/libiniparser.la - renderd_LDADD += -Liniparser3.0b/.libs -endif -renderd_DATA = renderd.conf -render_speedtest_SOURCES = src/speedtest.cpp src/protocol_helper.c src/render_submit_queue.c src/sys_utils.c -render_speedtest_LDADD = $(PTHREAD_CFLAGS) -render_list_SOURCES = src/render_list.c src/sys_utils.c src/protocol_helper.c src/render_submit_queue.c $(STORE_SOURCES) +renderd_LDADD = $(PTHREAD_CFLAGS) $(MAPNIK_LDFLAGS) $(STORE_LDFLAGS) $(INIPARSER_LDFLAGS) +renderd_DATA = etc/renderd/renderd.conf + +render_speedtest_SOURCES = \ + src/speedtest.cpp \ + src/protocol_helper.c \ + src/render_submit_queue.c \ + src/sys_utils.c \ + src/g_logger.c +render_speedtest_LDADD = $(PTHREAD_CFLAGS) $(GLIB_LIBS) + +render_list_SOURCES = \ + src/render_list.c \ + src/sys_utils.c \ + src/protocol_helper.c \ + src/render_submit_queue.c \ + $(STORE_SOURCES) render_list_LDADD = $(PTHREAD_CFLAGS) $(STORE_LDFLAGS) -render_expired_SOURCES = src/render_expired.c src/protocol_helper.c src/render_submit_queue.c src/sys_utils.c $(STORE_SOURCES) + +render_expired_SOURCES = \ + src/render_expired.c \ + src/protocol_helper.c \ + src/render_submit_queue.c \ + src/sys_utils.c \ + $(STORE_SOURCES) render_expired_LDADD = $(PTHREAD_CFLAGS) $(STORE_LDFLAGS) -render_old_SOURCES = src/store_file_utils.c src/render_old.c src/sys_utils.c src/protocol_helper.c src/render_submit_queue.c -render_old_LDADD = $(PTHREAD_CFLAGS) + +render_old_SOURCES = \ + src/store_file_utils.c \ + src/render_old.c \ + src/sys_utils.c \ + src/protocol_helper.c \ + src/render_submit_queue.c \ + src/g_logger.c +render_old_LDADD = $(PTHREAD_CFLAGS) $(GLIB_LIBS) + #convert_meta_SOURCES = src/dir_utils.c src/store.c src/convert_meta.c -gen_tile_test_SOURCES = src/gen_tile_test.cpp src/metatile.cpp src/request_queue.c src/protocol_helper.c src/daemon.c src/daemon_compat.c src/gen_tile.cpp src/sys_utils.c src/cache_expire.c src/parameterize_style.cpp $(STORE_SOURCES) -gen_tile_test_CFLAGS = -DMAIN_ALREADY_DEFINED $(PTHREAD_CFLAGS) + +gen_tile_test_SOURCES = \ + src/gen_tile_test.cpp \ + src/metatile.cpp \ + src/request_queue.c \ + src/protocol_helper.c \ + src/daemon.c \ + src/daemon_compat.c \ + src/gen_tile.cpp \ + src/sys_utils.c \ + src/cache_expire.c \ + src/parameterize_style.cpp \ + $(STORE_SOURCES) +gen_tile_test_CFLAGS = -DMAIN_ALREADY_DEFINED $(PTHREAD_CFLAGS) $(GLIB_CFLAGS) gen_tile_test_CXXFLAGS = $(MAPNIK_CFLAGS) -gen_tile_test_LDADD = $(PTHREAD_CFLAGS) $(MAPNIK_LDFLAGS) $(STORE_LDFLAGS) -liniparser -if !SYSTEM_LIBINIPARSER - gen_tile_test_SOURCES += iniparser3.0b/libiniparser.la - gen_tile_test_LDADD += -Liniparser3.0b/.libs -endif +gen_tile_test_LDADD = $(PTHREAD_CFLAGS) $(MAPNIK_LDFLAGS) $(STORE_LDFLAGS) $(INIPARSER_LDFLAGS) + CLEANFILES=*.slo mod_tile.la stderr.out src/*.slo src/*.lo src/.libs/* src/*.la +COMMA=, test: gen_tile_test ./gen_tile_test all-local: - $(APXS) -c $(DEF_LDLIBS) $(AM_CFLAGS) -I@srcdir@/includes $(AM_LDFLAGS) $(STORE_LDFLAGS) @srcdir@/src/mod_tile.c @srcdir@/src/sys_utils.c @srcdir@/src/store.c @srcdir@/src/store_file.c @srcdir@/src/store_file_utils.c @srcdir@/src/store_memcached.c @srcdir@/src/store_rados.c @srcdir@/src/store_ro_http_proxy.c @srcdir@/src/store_ro_composite.c @srcdir@/src/store_null.c + $(APXS) -c $(DEF_LDLIBS) $(AM_CFLAGS) \ + $(subst -pthread,-Wc$(COMMA)-pthread,$(GLIB_CFLAGS)) \ + -I@srcdir@/includes $(AM_LDFLAGS) $(STORE_LDFLAGS) \ + @srcdir@/src/mod_tile.c \ + @srcdir@/src/sys_utils.c \ + @srcdir@/src/store.c \ + @srcdir@/src/store_file.c \ + @srcdir@/src/store_file_utils.c \ + @srcdir@/src/store_memcached.c \ + @srcdir@/src/store_rados.c \ + @srcdir@/src/store_ro_http_proxy.c \ + @srcdir@/src/store_ro_composite.c \ + @srcdir@/src/store_null.c \ + @srcdir@/src/g_logger.c -install-mod_tile: +install-mod_tile: mkdir -p $(DESTDIR)`$(APXS) -q LIBEXECDIR` - $(APXS) -S LIBEXECDIR=$(DESTDIR)`$(APXS) -q LIBEXECDIR` -c -i $(DEF_LDLIBS) $(AM_CFLAGS) -I@srcdir@/includes $(AM_LDFLAGS) $(STORE_LDFLAGS) @srcdir@/src/mod_tile.c @srcdir@/src/sys_utils.c @srcdir@/src/store.c @srcdir@/src/store_file.c @srcdir@/src/store_file_utils.c @srcdir@/src/store_memcached.c @srcdir@/src/store_rados.c @srcdir@/src/store_ro_http_proxy.c @srcdir@/src/store_ro_composite.c @srcdir@/src/store_null.c - - + $(APXS) -S LIBEXECDIR=$(DESTDIR)`$(APXS) \ + -q LIBEXECDIR` -c -i $(DEF_LDLIBS) $(AM_CFLAGS) \ + $(subst -pthread,-Wc$(COMMA)-pthread,$(GLIB_CFLAGS)) \ + -I@srcdir@/includes $(AM_LDFLAGS) $(STORE_LDFLAGS) \ + @srcdir@/src/mod_tile.c \ + @srcdir@/src/sys_utils.c \ + @srcdir@/src/store.c \ + @srcdir@/src/store_file.c \ + @srcdir@/src/store_file_utils.c \ + @srcdir@/src/store_memcached.c \ + @srcdir@/src/store_rados.c \ + @srcdir@/src/store_ro_http_proxy.c \ + @srcdir@/src/store_ro_composite.c \ + @srcdir@/src/store_null.c \ + @srcdir@/src/g_logger.c diff --git a/README.rst b/README.rst new file mode 100644 index 00000000..157a3849 --- /dev/null +++ b/README.rst @@ -0,0 +1,264 @@ +==================== +mod_tile and renderd +==================== + +This software contains two main pieces: + +1) ``mod_tile``: An Apache 2 module to deliver map tiles. +2) ``renderd``: A daemon that renders map tiles using mapnik. + +.. figure:: ./screenshot.jpg + :alt: Image showing example slippy map and OSM layer + +Together they efficiently render and serve raster map tiles for example +to use within a slippy map. The two consist of the classic raster tile +stack from `OpenStreetMap.org `__. + +As an alternative to ``renderd`` its drop-in replacement +`Tirex `__ can be used in +combination with ``mod_tile``. + +Dependencies +------------ + +* `Supported Operating Systems` + * `GNU/Linux` (works best on Debian or Ubuntu) + * `FreeBSD` + * `macOS` +* `Supported Build Systems` + * `GNU Autotools `__ + * `CMake `__ +* `Runtime/Build Dependencies` + * `Apache 2 HTTP webserver `__ + * `Mapnik `__ + * `Cairo 2D graphics library `__ + * `Curl library (SSL variant) `__ + * `Iniparser library `__ + * `GLib library `__ + * `Memcached library (optional) `__ + * `RADOS library (optional) `__ + +Installation +------------ + +Starting from the following operation systems and their versions: + +* Debian 11 (Bullseye) +* Ubuntu 21.04 (Hirsute Hippo) + +the software and all dependencies can be installed simply with: + +:: + + $ apt install libapache2-mod-tile renderd + +These packages for **Debian** and **Ubuntu** are being maintained by +the `Debian GIS Team `__ in the respective +`repository `__. + +Compilation +----------- + +You may want to compile this software yourself. Either for developing on it or +when using it on an operating system this is not being packaged for. + +We prepared instructions for you on how to build the software on the following +distributions: + +* `CentOS `__ +* `CentOS Stream `__ +* `Debian `__ +* `Fedora `__ +* `FreeBSD `__ +* `macOS `__ +* `openSUSE `__ +* `Ubuntu `__ + +Configuration +------------- + +After you either installed the software packages or compiled the software +yourself, you can continue with the configuration. For your convenience +example configuration files are distributed with the software packages and +located in the ``etc`` directory of this repository. + +A very basic example-map and data can be found in the ``utils/example-map`` +directory. + +For a simple test copy it over to ``/usr/share/renderd/example-map``: + +:: + + $ sudo mkdir -p /usr/share/renderd + $ sudo cp -av utils/example-map /usr/share/renderd/ + +Copy the apache configuration file to its place, too: + +:: + + $ sudo cp -av etc/apache2/renderd-example-map.conf /etc/apache2/sites-available/renderd-example-map.conf + +Add map configurations for example-map to ``/etc/renderd.conf``: + +:: + + $ printf ' + [example-map] + URI=/tiles/renderd-example + XML=/usr/share/renderd/example-map/mapnik.xml + + [example-map-jpg] + TYPE=jpg image/jpeg jpeg + URI=/tiles/renderd-example-jpg + XML=/usr/share/renderd/example-map/mapnik.xml + + [example-map-png256] + TYPE=png image/png png256 + URI=/tiles/renderd-example-png256 + XML=/usr/share/renderd/example-map/mapnik.xml + + [example-map-png32] + TYPE=png image/png png32 + URI=/tiles/renderd-example-png32 + XML=/usr/share/renderd/example-map/mapnik.xml + + [example-map-webp] + TYPE=webp image/webp webp + URI=/tiles/renderd-example-webp + XML=/usr/share/renderd/example-map/mapnik.xml + ' | sudo tee -a /etc/renderd.conf + +Ensure the ``/var/run/renderd`` directory exists: + +:: + + $ sudo mkdir -p /var/run/renderd + +Start the rendering daemon: + +:: + + $ sudo renderd + +Enable the apache module and site: + +:: + + $ sudo a2enmod tile + $ sudo a2ensite renderd-example-map + +Restart apache: + +:: + + $ sudo apache2ctl restart + +Now visit the renderd example map in your browser, e.g.: + +:: + + http://localhost/renderd-example-map + +Or try loading a single tile, e.g: + +:: + + http://localhost:8081/tiles/renderd-example/0/0/0.png + +*Note: the above commands and paths may differ based on your OS/distribution.* + +You may edit ``/etc/renderd.conf`` to indicate the location of different +mapnik style sheets (up to ten) and the endpoints you wish to use to access +it. + +It is recommended to checkout `switch2osm +`__ for nice tutorials +on how to set up a full tile server like on `OpenStreetMap.org +`__, using this software together with a +`PostgreSQL `__ database and data from +OpenStreetMap. + + +Details about ``renderd``: Tile rendering +----------------------------------------- + +The rendering is implemented in a multithreaded process +called ``renderd`` which opens either a unix or tcp socket +and listens for requests to render tiles. It uses Mapnik +to render tiles using the rendering rules defined in +the configuration file ``/etc/renderd.conf``. Its configuration +also allows to specify the number of rendering +threads. + +The render daemon implements a queuing mechanism with multiple +priority levels to provide an as up-to-date viewing experience +given the available rendering resources. The highest priority +is for on the fly rendering of tiles not yet in the tile cache, +two priority levels for re-rendering out of date tiles on the fly +and two background batch rendering queues. The on the fly rendering +queues are limited to a short 32 metatile size to minimize latency. +The size of the main background queue is determined +at compile time, see: ``render_config.h`` + + +Details about ``mod_tile``: Tile serving +---------------------------------------- + +An Apache module called ``mod_tile`` enhances the regular +Apache file serving mechanisms to provide: + +1) When tiles have expired it requests the rendering daemon to render (or re-render) the tile. +2) Remapping of the file path to the hashed layout. +3) Prioritizes rendering requests depending on the available resources on the server and how out of date they are. +4) Use tile storage other than a plain posix file system. e.g it can store tiles in a ceph object store, or proxy them from another tile server. +5) Tile expiry. It estimates when the tile is next likely to be rendered and adds the appropriate HTTP cache expiry headers. This is a configurable heuristic. + +To avoid problems with directories becoming too large and to avoid +too many tiny files. They store the rendered tiles in "meta tiles" in a +special hashed directory structure. These combine 8x8 actual tiles into a +single metatile file. This is a more efficient use of disk space and inodes. + +The metatiles are then stored in the following directory structure: +``/[base_dir]/[TileSetName]/[Z]/[xxxxyyyy]/[xxxxyyyy]/[xxxxyyyy]/[xxxxyyyy]/[xxxxyyyy].meta`` + +Where ``base_dir`` is a configurable base path for all tiles. ``TileSetName`` +is the name of the style sheet rendered. ``Z`` is the zoom level. +``[xxxxyyyy]`` is an 8 bit number, with the first 4 bits taken from the x +coordinate and the second 4 bits taken from the y coordinate. This +attempts to cluster 16x16 square of tiles together into a single sub +directory for more efficient access patterns. + +Apache serves the files as if they were present under +``/[TileSetName]/Z/X/Y.png`` with the path being converted automatically. + +Notes about performance +----------------------- + +``mod_tile`` is designed for high performance tile serving. If the +underlying disk system allows it, it can easily provide > 10k tiles/s +on a single serve. + +Rendering performance is mostly dependent on mapnik and postgis performance, +however ``renderd`` tries to make sure it uses underlying hardware as +efficiently as possible and scales well on multi core systems. ``renderd`` +also provides built-in features to scale to multi server rendering set-ups. + +Copyright and copyleft +---------------------- + +Copyright (c) 2007 - 2023 by mod_tile contributors (see `AUTHORS <./AUTHORS>`__) + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation, either version 2 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see http://www.gnu.org/licenses/. + +See the `COPYING <./COPYING>`__ for the full license text. diff --git a/cmake/FindAPR.cmake b/cmake/FindAPR.cmake new file mode 100644 index 00000000..3ea371cd --- /dev/null +++ b/cmake/FindAPR.cmake @@ -0,0 +1,49 @@ +# - Find APR +# Find the APR includes and libraries. +# This module defines: +# APR_FOUND +# APR_INCLUDE_DIRS +# APR_LIBRARIES + +find_package(PkgConfig QUIET) +pkg_check_modules(APR QUIET apr-1) + +find_path(APR_INCLUDE_DIR + NAMES apr.h + PATHS ${APR_INCLUDE_DIRS} + PATH_SUFFIXES apr-1 +) + +if((NOT APR_INCLUDE_DIRS) AND (APR_INCLUDE_DIR)) + set(APR_INCLUDE_DIRS ${APR_INCLUDE_DIR}) +elseif(APR_INCLUDE_DIRS AND APR_INCLUDE_DIR) + list(APPEND APR_INCLUDE_DIRS ${APR_INCLUDE_DIR}) +endif() + +find_library(APR_LIBRARY + NAMES ${APR_LIBRARIES} apr-1 +) + +if((NOT APR_LIBRARIES) AND (APR_LIBRARY)) + set(APR_LIBRARIES ${APR_LIBRARY}) +elseif(APR_LIBRARIES AND APR_LIBRARY) + list(APPEND APR_LIBRARIES ${APR_LIBRARY}) +endif() + +message(VERBOSE "APR_INCLUDE_DIRS=${APR_INCLUDE_DIRS}") +message(VERBOSE "APR_INCLUDE_DIR=${APR_INCLUDE_DIR}") +message(VERBOSE "APR_LIBRARIES=${APR_LIBRARIES}") +message(VERBOSE "APR_LIBRARY=${APR_LIBRARY}") + +if((NOT APR_FOUND) AND (APR_INCLUDE_DIRS) AND (APR_LIBRARIES)) + set(APR_FOUND True) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(APR + FOUND_VAR APR_FOUND + REQUIRED_VARS APR_FOUND APR_INCLUDE_DIRS APR_LIBRARIES + VERSION_VAR APR_VERSION +) + +mark_as_advanced(APR_INCLUDE_DIR APR_LIBRARY) diff --git a/cmake/FindCAIRO.cmake b/cmake/FindCAIRO.cmake new file mode 100644 index 00000000..b95d5b1e --- /dev/null +++ b/cmake/FindCAIRO.cmake @@ -0,0 +1,49 @@ +# - Find CAIRO +# Find the CAIRO includes and libraries. +# This module defines: +# CAIRO_FOUND +# CAIRO_INCLUDE_DIRS +# CAIRO_LIBRARIES + +find_package(PkgConfig QUIET) +pkg_check_modules(CAIRO QUIET cairo) + +find_path(CAIRO_INCLUDE_DIR + NAMES cairo.h + PATHS ${CAIRO_INCLUDE_DIRS} + PATH_SUFFIXES cairo +) + +if((NOT CAIRO_INCLUDE_DIRS) AND (CAIRO_INCLUDE_DIR)) + set(CAIRO_INCLUDE_DIRS ${CAIRO_INCLUDE_DIR}) +elseif(CAIRO_INCLUDE_DIRS AND CAIRO_INCLUDE_DIR) + list(APPEND CAIRO_INCLUDE_DIRS ${CAIRO_INCLUDE_DIR}) +endif() + +find_library(CAIRO_LIBRARY + NAMES ${CAIRO_LIBRARIES} cairo +) + +if((NOT CAIRO_LIBRARIES) AND (CAIRO_LIBRARY)) + set(CAIRO_LIBRARIES ${CAIRO_LIBRARY}) +elseif(CAIRO_LIBRARIES AND CAIRO_LIBRARY) + list(APPEND CAIRO_LIBRARIES ${CAIRO_LIBRARY}) +endif() + +message(VERBOSE "CAIRO_INCLUDE_DIRS=${CAIRO_INCLUDE_DIRS}") +message(VERBOSE "CAIRO_INCLUDE_DIR=${CAIRO_INCLUDE_DIR}") +message(VERBOSE "CAIRO_LIBRARIES=${CAIRO_LIBRARIES}") +message(VERBOSE "CAIRO_LIBRARY=${CAIRO_LIBRARY}") + +if((NOT CAIRO_FOUND) AND (CAIRO_INCLUDE_DIRS) AND (CAIRO_LIBRARIES)) + set(CAIRO_FOUND True) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(CAIRO + FOUND_VAR CAIRO_FOUND + REQUIRED_VARS CAIRO_FOUND CAIRO_INCLUDE_DIRS CAIRO_LIBRARIES + VERSION_VAR CAIRO_VERSION +) + +mark_as_advanced(CAIRO_INCLUDE_DIR CAIRO_LIBRARY) diff --git a/cmake/FindGLIB.cmake b/cmake/FindGLIB.cmake new file mode 100644 index 00000000..87b2012f --- /dev/null +++ b/cmake/FindGLIB.cmake @@ -0,0 +1,49 @@ +# - Find GLIB +# Find the GLIB includes and libraries. +# This module defines: +# GLIB_FOUND +# GLIB_INCLUDE_DIRS +# GLIB_LIBRARIES + +find_package(PkgConfig QUIET) +pkg_check_modules(GLIB QUIET glib-2.0) + +find_path(GLIB_INCLUDE_DIR + NAMES glib.h + PATHS ${GLIB_INCLUDE_DIRS} + PATH_SUFFIXES glib-2.0 +) + +if((NOT GLIB_INCLUDE_DIRS) AND (GLIB_INCLUDE_DIR)) + set(GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIR}) +elseif(GLIB_INCLUDE_DIRS AND GLIB_INCLUDE_DIR) + list(APPEND GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIR}) +endif() + +find_library(GLIB_LIBRARY + NAMES ${GLIB_LIBRARIES} glib-2.0 +) + +if((NOT GLIB_LIBRARIES) AND (GLIB_LIBRARY)) + set(GLIB_LIBRARIES ${GLIB_LIBRARY}) +elseif(GLIB_LIBRARIES AND GLIB_LIBRARY) + list(APPEND GLIB_LIBRARIES ${GLIB_LIBRARY}) +endif() + +message(VERBOSE "GLIB_INCLUDE_DIRS=${GLIB_INCLUDE_DIRS}") +message(VERBOSE "GLIB_INCLUDE_DIR=${GLIB_INCLUDE_DIR}") +message(VERBOSE "GLIB_LIBRARIES=${GLIB_LIBRARIES}") +message(VERBOSE "GLIB_LIBRARY=${GLIB_LIBRARY}") + +if((NOT GLIB_FOUND) AND (GLIB_INCLUDE_DIRS) AND (GLIB_LIBRARIES)) + set(GLIB_FOUND True) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GLIB + FOUND_VAR GLIB_FOUND + REQUIRED_VARS GLIB_FOUND GLIB_INCLUDE_DIRS GLIB_LIBRARIES + VERSION_VAR GLIB_VERSION +) + +mark_as_advanced(GLIB_INCLUDE_DIR GLIB_LIBRARY) diff --git a/cmake/FindHTTPD.cmake b/cmake/FindHTTPD.cmake new file mode 100644 index 00000000..523f3ff4 --- /dev/null +++ b/cmake/FindHTTPD.cmake @@ -0,0 +1,47 @@ +# - Find HTTPD +# Find the HTTPD includes and libraries. +# This module defines: +# HTTPD_FOUND +# HTTPD_INCLUDE_DIRS + +find_package(PkgConfig QUIET) +pkg_check_modules(HTTPD QUIET httpd) + +find_path(HTTPD_INCLUDE_DIR + NAMES httpd.h + PATHS ${HTTPD_INCLUDE_DIRS} + PATH_SUFFIXES apache2 apache24 httpd +) + +if((NOT HTTPD_INCLUDE_DIRS) AND (HTTPD_INCLUDE_DIR)) + set(HTTPD_INCLUDE_DIRS ${HTTPD_INCLUDE_DIR}) +elseif(HTTPD_INCLUDE_DIRS AND HTTPD_INCLUDE_DIR) + list(APPEND HTTPD_INCLUDE_DIRS ${HTTPD_INCLUDE_DIR}) +endif() + +message(VERBOSE "HTTPD_INCLUDE_DIRS=${HTTPD_INCLUDE_DIRS}") +message(VERBOSE "HTTPD_INCLUDE_DIR=${HTTPD_INCLUDE_DIR}") + +if((NOT HTTPD_FOUND) AND (HTTPD_INCLUDE_DIRS)) + set(HTTPD_FOUND True) +endif() + +if((NOT HTTPD_VERSION) AND (HTTPD_FOUND)) + file(STRINGS "${HTTPD_INCLUDE_DIR}/ap_release.h" _contents REGEX "#define AP_SERVER_[A-Z]+_NUMBER[ \t]+") + if(_contents) + string(REGEX REPLACE ".*#define AP_SERVER_MAJORVERSION_NUMBER[ \t]+([0-9]+).*" "\\1" HTTPD_MAJOR_VERSION "${_contents}") + string(REGEX REPLACE ".*#define AP_SERVER_MINORVERSION_NUMBER[ \t]+([0-9]+).*" "\\1" HTTPD_MINOR_VERSION "${_contents}") + string(REGEX REPLACE ".*#define AP_SERVER_PATCHLEVEL_NUMBER[ \t]+([0-9]+).*" "\\1" HTTPD_PATCH_VERSION "${_contents}") + + set(HTTPD_VERSION ${HTTPD_MAJOR_VERSION}.${HTTPD_MINOR_VERSION}.${HTTPD_PATCH_VERSION}) + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(HTTPD + FOUND_VAR HTTPD_FOUND + REQUIRED_VARS HTTPD_FOUND HTTPD_INCLUDE_DIRS + VERSION_VAR HTTPD_VERSION +) + +mark_as_advanced(HTTPD_INCLUDE_DIR) diff --git a/cmake/FindINIPARSER.cmake b/cmake/FindINIPARSER.cmake new file mode 100644 index 00000000..79dafba3 --- /dev/null +++ b/cmake/FindINIPARSER.cmake @@ -0,0 +1,48 @@ +# - Find INIPARSER +# Find the INIPARSER includes and libraries. +# This module defines: +# INIPARSER_FOUND +# INIPARSER_INCLUDE_DIRS +# INIPARSER_LIBRARIES + +find_package(PkgConfig QUIET) +pkg_check_modules(INIPARSER QUIET iniparser) + +find_path(INIPARSER_INCLUDE_DIR + NAMES iniparser.h + PATHS ${INIPARSER_INCLUDE_DIRS} + PATH_SUFFIXES iniparser +) + +if((NOT INIPARSER_INCLUDE_DIRS) AND (INIPARSER_INCLUDE_DIR)) + set(INIPARSER_INCLUDE_DIRS ${INIPARSER_INCLUDE_DIR}) +elseif(INIPARSER_INCLUDE_DIRS AND INIPARSER_INCLUDE_DIR) + list(APPEND INIPARSER_INCLUDE_DIRS ${INIPARSER_INCLUDE_DIR}) +endif() + +find_library(INIPARSER_LIBRARY + NAMES ${INIPARSER_LIBRARIES} iniparser +) + +if((NOT INIPARSER_LIBRARIES) AND (INIPARSER_LIBRARY)) + set(INIPARSER_LIBRARIES ${INIPARSER_LIBRARY}) +elseif(INIPARSER_LIBRARIES AND INIPARSER_LIBRARY) + list(APPEND INIPARSER_LIBRARIES ${INIPARSER_LIBRARY}) +endif() + +message(VERBOSE "INIPARSER_INCLUDE_DIRS=${INIPARSER_INCLUDE_DIRS}") +message(VERBOSE "INIPARSER_INCLUDE_DIR=${INIPARSER_INCLUDE_DIR}") +message(VERBOSE "INIPARSER_LIBRARIES=${INIPARSER_LIBRARIES}") +message(VERBOSE "INIPARSER_LIBRARY=${INIPARSER_LIBRARY}") + +if((NOT INIPARSER_FOUND) AND (INIPARSER_INCLUDE_DIRS) AND (INIPARSER_LIBRARIES)) + set(INIPARSER_FOUND True) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(INIPARSER + FOUND_VAR INIPARSER_FOUND + REQUIRED_VARS INIPARSER_FOUND INIPARSER_INCLUDE_DIRS INIPARSER_LIBRARIES +) + +mark_as_advanced(INIPARSER_INCLUDE_DIR INIPARSER_LIBRARY) diff --git a/cmake/FindLIBMAPNIK.cmake b/cmake/FindLIBMAPNIK.cmake new file mode 100644 index 00000000..6959de0d --- /dev/null +++ b/cmake/FindLIBMAPNIK.cmake @@ -0,0 +1,60 @@ +# - Find LIBMAPNIK +# Find the LIBMAPNIK includes and libraries. +# This module defines: +# LIBMAPNIK_FOUND +# LIBMAPNIK_INCLUDE_DIRS +# LIBMAPNIK_LIBRARIES + +find_package(PkgConfig QUIET) +pkg_check_modules(LIBMAPNIK QUIET libmapnik) + +find_path(LIBMAPNIK_INCLUDE_DIR + NAMES version.hpp + PATHS ${LIBMAPNIK_INCLUDE_DIRS} + PATH_SUFFIXES mapnik +) + +if((NOT LIBMAPNIK_INCLUDE_DIRS) AND (LIBMAPNIK_INCLUDE_DIR)) + set(LIBMAPNIK_INCLUDE_DIRS ${LIBMAPNIK_INCLUDE_DIR}) +elseif(LIBMAPNIK_INCLUDE_DIRS AND LIBMAPNIK_INCLUDE_DIR) + list(APPEND LIBMAPNIK_INCLUDE_DIRS ${LIBMAPNIK_INCLUDE_DIR}) +endif() + +find_library(LIBMAPNIK_LIBRARY + NAMES ${LIBMAPNIK_LIBRARIES} mapnik +) + +if((NOT LIBMAPNIK_LIBRARIES) AND (LIBMAPNIK_LIBRARY)) + set(LIBMAPNIK_LIBRARIES ${LIBMAPNIK_LIBRARY}) +elseif(LIBMAPNIK_LIBRARIES AND LIBMAPNIK_LIBRARY) + list(APPEND LIBMAPNIK_LIBRARIES ${LIBMAPNIK_LIBRARY}) +endif() + +message(VERBOSE "LIBMAPNIK_INCLUDE_DIRS=${LIBMAPNIK_INCLUDE_DIRS}") +message(VERBOSE "LIBMAPNIK_INCLUDE_DIR=${LIBMAPNIK_INCLUDE_DIR}") +message(VERBOSE "LIBMAPNIK_LIBRARIES=${LIBMAPNIK_LIBRARIES}") +message(VERBOSE "LIBMAPNIK_LIBRARY=${LIBMAPNIK_LIBRARY}") + +if((NOT LIBMAPNIK_FOUND) AND (LIBMAPNIK_INCLUDE_DIRS) AND (LIBMAPNIK_LIBRARIES)) + set(LIBMAPNIK_FOUND True) +endif() + +if((NOT LIBMAPNIK_VERSION) AND (LIBMAPNIK_FOUND)) + file(STRINGS "${LIBMAPNIK_INCLUDE_DIR}/version.hpp" _contents REGEX "#define MAPNIK_[A-Z]+_VERSION[ \t]+") + if(_contents) + string(REGEX REPLACE ".*#define MAPNIK_MAJOR_VERSION[ \t]+([0-9]+).*" "\\1" LIBMAPNIK_MAJOR_VERSION "${_contents}") + string(REGEX REPLACE ".*#define MAPNIK_MINOR_VERSION[ \t]+([0-9]+).*" "\\1" LIBMAPNIK_MINOR_VERSION "${_contents}") + string(REGEX REPLACE ".*#define MAPNIK_PATCH_VERSION[ \t]+([0-9]+).*" "\\1" LIBMAPNIK_PATCH_VERSION "${_contents}") + + set(LIBMAPNIK_VERSION ${LIBMAPNIK_MAJOR_VERSION}.${LIBMAPNIK_MINOR_VERSION}.${LIBMAPNIK_PATCH_VERSION}) + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LIBMAPNIK + FOUND_VAR LIBMAPNIK_FOUND + REQUIRED_VARS LIBMAPNIK_FOUND LIBMAPNIK_INCLUDE_DIRS LIBMAPNIK_LIBRARIES + VERSION_VAR LIBMAPNIK_VERSION +) + +mark_as_advanced(LIBMAPNIK_INCLUDE_DIR LIBMAPNIK_LIBRARY) diff --git a/cmake/FindLIBMEMCACHED.cmake b/cmake/FindLIBMEMCACHED.cmake new file mode 100644 index 00000000..9faa04c1 --- /dev/null +++ b/cmake/FindLIBMEMCACHED.cmake @@ -0,0 +1,49 @@ +# - Find LIBMEMCACHED +# Find the LIBMEMCACHED includes and libraries. +# This module defines: +# LIBMEMCACHED_FOUND +# LIBMEMCACHED_INCLUDE_DIRS +# LIBMEMCACHED_LIBRARIES + +find_package(PkgConfig QUIET) +pkg_check_modules(LIBMEMCACHED QUIET libmemcached) + +find_path(LIBMEMCACHED_INCLUDE_DIR + NAMES memcached.h + PATHS ${LIBMEMCACHED_INCLUDE_DIRS} + PATH_SUFFIXES libmemcached +) + +if((NOT LIBMEMCACHED_INCLUDE_DIRS) AND (LIBMEMCACHED_INCLUDE_DIR)) + set(LIBMEMCACHED_INCLUDE_DIRS ${LIBMEMCACHED_INCLUDE_DIR}) +elseif(LIBMEMCACHED_INCLUDE_DIRS AND LIBMEMCACHED_INCLUDE_DIR) + list(APPEND LIBMEMCACHED_INCLUDE_DIRS ${LIBMEMCACHED_INCLUDE_DIR}) +endif() + +find_library(LIBMEMCACHED_LIBRARY + NAMES ${LIBMEMCACHED_LIBRARIES} memcached +) + +if((NOT LIBMEMCACHED_LIBRARIES) AND (LIBMEMCACHED_LIBRARY)) + set(LIBMEMCACHED_LIBRARIES ${LIBMEMCACHED_LIBRARY}) +elseif(LIBMEMCACHED_LIBRARIES AND LIBMEMCACHED_LIBRARY) + list(APPEND LIBMEMCACHED_LIBRARIES ${LIBMEMCACHED_LIBRARY}) +endif() + +message(VERBOSE "LIBMEMCACHED_INCLUDE_DIRS=${LIBMEMCACHED_INCLUDE_DIRS}") +message(VERBOSE "LIBMEMCACHED_INCLUDE_DIR=${LIBMEMCACHED_INCLUDE_DIR}") +message(VERBOSE "LIBMEMCACHED_LIBRARIES=${LIBMEMCACHED_LIBRARIES}") +message(VERBOSE "LIBMEMCACHED_LIBRARY=${LIBMEMCACHED_LIBRARY}") + +if((NOT LIBMEMCACHED_FOUND) AND (LIBMEMCACHED_INCLUDE_DIRS) AND (LIBMEMCACHED_LIBRARIES)) + set(LIBMEMCACHED_FOUND True) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LIBMEMCACHED + FOUND_VAR LIBMEMCACHED_FOUND + REQUIRED_VARS LIBMEMCACHED_FOUND LIBMEMCACHED_INCLUDE_DIRS LIBMEMCACHED_LIBRARIES + VERSION_VAR LIBMEMCACHED_VERSION +) + +mark_as_advanced(LIBMEMCACHED_INCLUDE_DIR LIBMEMCACHED_LIBRARY) diff --git a/cmake/FindLIBRADOS.cmake b/cmake/FindLIBRADOS.cmake new file mode 100644 index 00000000..575b5c8d --- /dev/null +++ b/cmake/FindLIBRADOS.cmake @@ -0,0 +1,60 @@ +# - Find LIBRADOS +# Find the LIBRADOS includes and libraries. +# This module defines: +# LIBRADOS_FOUND +# LIBRADOS_INCLUDE_DIRS +# LIBRADOS_LIBRARIES + +find_package(PkgConfig QUIET) +pkg_check_modules(LIBRADOS QUIET rados) + +find_path(LIBRADOS_INCLUDE_DIR + NAMES librados.h + PATHS ${LIBRADOS_INCLUDE_DIRS} + PATH_SUFFIXES rados +) + +if((NOT LIBRADOS_INCLUDE_DIRS) AND (LIBRADOS_INCLUDE_DIR)) + set(LIBRADOS_INCLUDE_DIRS ${LIBRADOS_INCLUDE_DIR}) +elseif(LIBRADOS_INCLUDE_DIRS AND LIBRADOS_INCLUDE_DIR) + list(APPEND LIBRADOS_INCLUDE_DIRS ${LIBRADOS_INCLUDE_DIR}) +endif() + +find_library(LIBRADOS_LIBRARY + NAMES ${LIBRADOS_LIBRARIES} rados +) + +if((NOT LIBRADOS_LIBRARIES) AND (LIBRADOS_LIBRARY)) + set(LIBRADOS_LIBRARIES ${LIBRADOS_LIBRARY}) +elseif(LIBRADOS_LIBRARIES AND LIBRADOS_LIBRARY) + list(APPEND LIBRADOS_LIBRARIES ${LIBRADOS_LIBRARY}) +endif() + +message(VERBOSE "LIBRADOS_INCLUDE_DIRS=${LIBRADOS_INCLUDE_DIRS}") +message(VERBOSE "LIBRADOS_INCLUDE_DIR=${LIBRADOS_INCLUDE_DIR}") +message(VERBOSE "LIBRADOS_LIBRARIES=${LIBRADOS_LIBRARIES}") +message(VERBOSE "LIBRADOS_LIBRARY=${LIBRADOS_LIBRARY}") + +if((NOT LIBRADOS_FOUND) AND (LIBRADOS_INCLUDE_DIRS) AND (LIBRADOS_LIBRARIES)) + set(LIBRADOS_FOUND True) +endif() + +if((NOT LIBRADOS_VERSION) AND (LIBRADOS_FOUND)) + file(STRINGS "${LIBRADOS_INCLUDE_DIR}/librados.h" _contents REGEX "#define LIBRADOS_VER_[A-Z]+[ \t]+") + if(_contents) + string(REGEX REPLACE ".*#define LIBRADOS_VER_MAJOR[ \t]+([0-9]+).*" "\\1" LIBRADOS_MAJOR_VERSION "${_contents}") + string(REGEX REPLACE ".*#define LIBRADOS_VER_MINOR[ \t]+([0-9]+).*" "\\1" LIBRADOS_MINOR_VERSION "${_contents}") + string(REGEX REPLACE ".*#define LIBRADOS_VER_EXTRA[ \t]+([0-9]+).*" "\\1" LIBRADOS_EXTRA_VERSION "${_contents}") + + set(LIBRADOS_VERSION ${LIBRADOS_MAJOR_VERSION}.${LIBRADOS_MINOR_VERSION}.${LIBRADOS_EXTRA_VERSION}) + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LIBRADOS + FOUND_VAR LIBRADOS_FOUND + REQUIRED_VARS LIBRADOS_FOUND LIBRADOS_INCLUDE_DIRS LIBRADOS_LIBRARIES + VERSION_VAR LIBRADOS_VERSION +) + +mark_as_advanced(LIBRADOS_INCLUDE_DIR LIBRADOS_LIBRARY) diff --git a/configure.ac b/configure.ac index c6ff10ad..66f559c6 100644 --- a/configure.ac +++ b/configure.ac @@ -1,9 +1,14 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. +# Define mod_tile version number +m4_define([mod_tile_version], [0.7.0]) + AC_PREREQ([2.61]) AX_CONFIG_NICE -AC_INIT(mod_tile, 0.1, http://trac.openstreetmap.org) +AC_INIT([mod_tile], + [mod_tile_version], + [http://trac.openstreetmap.org]) AM_INIT_AUTOMAKE([subdir-objects]) LT_INIT AC_CONFIG_SRCDIR([src/convert_meta.c]) @@ -15,17 +20,18 @@ AC_PROG_CXX AC_PROG_CC AC_PROG_CC_C99 -dnl Find C++ compiler -AC_CHECK_PROG(HAVE_CXX, $CXX, yes, no) -if test "$HAVE_CXX" = "no" -then - AC_MSG_ERROR([Could not find a c++ compiler]); +dnl Find C++ compiler +AC_CHECK_PROG(HAVE_CXX, $CXX, yes, no) +if test "$HAVE_CXX" = "no" +then + AC_MSG_ERROR([Could not find a c++ compiler]); fi # Checks for libraries. +PKG_CHECK_MODULES([GLIB], [glib-2.0]) # Checks for header files. -AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h stdint.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h utime.h paths.h sys/cdefs.h sys/loadavg.h]) +AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h stdint.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h utime.h paths.h sys/cdefs.h sys/loadavg.h iniparser.h iniparser/iniparser.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE @@ -45,7 +51,11 @@ AC_SEARCH_LIBS(inet_ntoa, nsl) AC_SEARCH_LIBS(gethostbyname, resolv nsl) AC_SEARCH_LIBS(pow,m) AC_SEARCH_LIBS(clock_gettime,[rt posix4]) -AX_LIB_MAPNIK +PKG_CHECK_MODULES([MAPNIK], [libmapnik >= 4], [ + AC_DEFINE([HAVE_MAPNIK], [1]) + AC_SUBST([MAPNIK_LDFLAGS], [${MAPNIK_LIBS}]) + ], [AX_LIB_MAPNIK] +) AX_ENABLE_LIBMEMCACHED LIBCURL_CHECK_CONFIG AC_CHECK_LIB(rados, rados_version, [ @@ -53,6 +63,10 @@ AC_CHECK_LIB(rados, rados_version, [ LIBRADOS_LDFLAGS='-lrados' AC_SUBST(LIBRADOS_LDFLAGS) ][]) +AC_CHECK_LIB(iniparser, iniparser_load, [ + INIPARSER_LDFLAGS='-liniparser' + AC_SUBST(INIPARSER_LDFLAGS) +], [AC_MSG_ERROR([Unable to find libiniparser])]) AC_CHECK_FUNCS([bzero gethostbyname gettimeofday inet_ntoa memset mkdir pow select socket strchr strdup strerror strrchr strstr strtol strtoul utime],[],[AC_MSG_ERROR([One of the required functions was not found])]) AC_CHECK_FUNCS([daemon getloadavg],[],[]) @@ -74,17 +88,5 @@ if test "$APXS" = "reject"; then AC_MSG_ERROR([Could not find apxs on the path.]) fi -AC_SEARCH_LIBS([iniparser_load], [iniparser], [ - AC_CHECK_HEADERS([iniparser.h], [have_system_iniparser=yes]) -]) -AM_CONDITIONAL([SYSTEM_LIBINIPARSER], [test "x$have_system_iniparser" = "xyes"]) -if test "x$have_system_iniparser" = "xyes"; then - AC_SUBST(SYSTEM_LIBINIPARSER, 1) - AC_MSG_NOTICE([Using installed iniparser]) -else - AC_SUBST(SYSTEM_LIBINIPARSER, 0) - AC_CONFIG_FILES(iniparser3.0b/Makefile) - AC_MSG_NOTICE([Building iniparser]) -fi AC_CONFIG_FILES(Makefile) AC_OUTPUT diff --git a/debian/README b/debian/README deleted file mode 100644 index 3902bb2e..00000000 --- a/debian/README +++ /dev/null @@ -1,4 +0,0 @@ -Debian packages for mod_tile and renderd ----------------------------------------- - - -- Frederik Ramm Fri, 04 Jun 2009 diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index e2793ecd..00000000 --- a/debian/changelog +++ /dev/null @@ -1,64 +0,0 @@ -libapache2-mod-tile (0.4-12~saucy1) saucy; urgency=low - * update to new release - - -- Sarah Hoffmann Wed, 09 Apr 2014 00:00:00 +0000 - -libapache2-mod-tile (0.4-12~precise2) precise; urgency=low - * fixed renderd.conf to use mapnik 2.0 plugins dir - - -- Kai Krueger Mon, 27 Aug 2012 00:00:00 +0000 - -libapache2-mod-tile (0.4-12~precise1) precise; urgency=low - * new upstream version - revision 28638 - - add a json-tile handler - - a number of bug fixes - - -- Kai Krueger Sun, 26 Aug 2012 00:00:00 +0000 - -libapache2-mod-tile (0.4-11~precise2) precise; urgency=low - - * correct renderd.conf - * update upstream - - -- Kai Krueger Thu, 03 May 2012 00:00:00 +0000 - -libapache2-mod-tile (0.4-10~oneiric1) oneiric; urgency=low - - * support extensions other than png - * autoconf'ify build system - - -- Kai Krueger Sun, 15 Jan 2012 00:00:00 +0000 - -libapache2-mod-tile (0.4-9~oneiric2) oneiric; urgency=low - - * added a slippymap - * added scripts to update a tileserver - - -- Kai Krueger Sun, 09 Oct 2011 00:00:00 +0000 - -libapache2-mod-tile (0.4-8~natty1) natty; urgency=low - - * new upstream version - * fixed debian package scripts - - -- Kai Krueger Thu, 06 Oct 2011 00:00:00 +0000 - -libapache2-mod-tile (0.3) jaunty; urgency=low - - * new version of render_list with proper multithreading - * bugfixes - * new render_expired - - -- Frederik Ramm Tue, 24 Nov 2009 00:09:17 +0100 - -libapache2-mod-tile (0.2) jaunty; urgency=low - - * now also installs munin stuff - - -- Frederik Ramm Tue, 20 Oct 2009 19:52:04 +0200 - -libapache2-mod-tile (0.1) unstable; urgency=low - - * Initial Debian packaging for mod_tile and renderd - - -- Frederik Ramm Thu, 04 Jun 2009 13:33:42 +0200 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index 7f8f011e..00000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -7 diff --git a/debian/control b/debian/control deleted file mode 100644 index ce79e067..00000000 --- a/debian/control +++ /dev/null @@ -1,24 +0,0 @@ -Source: libapache2-mod-tile -Section: utils -Priority: optional -Maintainer: Frederik Ramm -Build-Depends: debhelper (>= 7), apache2-dev (>= 2.4.0), libmapnik-dev | libmapnik2-dev, autoconf, automake, m4, libtool -Standards-Version: 3.9.3 - -Package: libapache2-mod-tile -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, renderd | tirex-master, apache2 -Suggests: renderd -Description: Apache module to deliver tiles created by renderd - This Apache module receives map tiles requests and satisfies them from - tiles stored on disk, or queries a renderd instance to create them. - -Package: renderd -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Suggests: libapache2-mod-tile -Recommends: osm2pgsql, openstreetmap-mapnik-stylesheet-data -Description: Daemon that renders map tiles using mapnik - This daemon creates "metatiles" for map tile requests issued by mod_tile - using the mapnik library. - diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index 05368cf7..00000000 --- a/debian/copyright +++ /dev/null @@ -1,34 +0,0 @@ -Format: http://dep.debian.net/deps/dep5 -Source: http://svn.openstreetmap.org/applications/utils/mod_tile/ - -Files: * -Copyright: © 2007 - 2011, Jon Burgess -Copyright: © 2009 - 2012, Kai Krueger -Copyright: © 2009 - 2011, Frederik Ramm -Copyright: © 2008 - 2010, Tom Hughes -Copyright: © 2011, Stephan Knauss -Copyright: © 2010, Lennard voor den Dag -Copyright: © 2010, Dane Springmeyer -Copyright: © 2010, Andreas Hubel -Copyright: © 2010, Brian Quinion -Copyright: © 2009, Ævar Arnfjörð Bjarmason -Copyright: © 2009, Jochen Topf -License: GPL-2+ - This package is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - . - This package is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with this package; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -Comments: - On Debian systems, the complete text of the GNU General Public License - version 2 or later can be found in `/usr/share/common-licenses/GPL-2'. - - diff --git a/debian/libapache2-mod-tile.conffiles b/debian/libapache2-mod-tile.conffiles deleted file mode 100644 index e69de29b..00000000 diff --git a/debian/libapache2-mod-tile.config b/debian/libapache2-mod-tile.config deleted file mode 100644 index 36cff0ad..00000000 --- a/debian/libapache2-mod-tile.config +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -set -e - -. /usr/share/debconf/confmodule - -db_input high libapache2-mod-tile/enablesite || true -db_go || true - -cat < /etc/default/libapache2-mod-tile -# Default settings for openstreetmap-mapnik-data -INIT_DB="$INIT_DB" -GRANT_USER="$GRANT_USER" -EOF - diff --git a/debian/libapache2-mod-tile.install b/debian/libapache2-mod-tile.install deleted file mode 100644 index 5f096c12..00000000 --- a/debian/libapache2-mod-tile.install +++ /dev/null @@ -1,6 +0,0 @@ -debian/tile.load /etc/apache2/mods-available -debian/tileserver_site.conf /etc/apache2/sites-available/ -readme.txt /usr/share/doc/libapache2-mod-tile -munin/mod_tile* /usr/share/munin/plugins -openstreetmap-tiles-update-expire /usr/bin/ -osmosis-db_replag /usr/bin diff --git a/debian/libapache2-mod-tile.postinst b/debian/libapache2-mod-tile.postinst deleted file mode 100644 index 599a1ce8..00000000 --- a/debian/libapache2-mod-tile.postinst +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -set -e - -if [ "$1" = configure ] ; then - - mkdir -p /var/lib/mod_tile - chown www-data:www-data /var/lib/mod_tile - - # only enable on new installs, not on upgrades - if [ -z "$2" ] ; then - a2enmod tile - fi - - # only restart if mod_something is enabled - if [ -e /etc/apache2/mods-enabled/tile.load ] ; then - invoke-rc.d apache2 restart - fi - - # automatically install munin plugins if munin is present. - if [ -d /etc/munin/plugins ] ; then - cd /etc/munin/plugins - for i in /usr/share/munin/plugins/mod_tile* - do - if [ ! -h `basename $i` ] - then - ln -s $i . - fi - done - fi - true -fi - - -exit 0 diff --git a/debian/libapache2-mod-tile.prerm b/debian/libapache2-mod-tile.prerm deleted file mode 100644 index 01c94a13..00000000 --- a/debian/libapache2-mod-tile.prerm +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -set -e - -if [ "$1" = remove ] ; then - a2dissite tileserver_site || true - a2ensite 000-default || true - a2dismod -q -f tile || true - invoke-rc.d apache2 restart || true -fi - -# automatically remove munin plugins -if [ -d /etc/munin/plugins ] -then - rm -f /etc/munin/plugins/mod_tile* -fi - -#DEBHELPER# diff --git a/debian/libapache2-mod-tile.templates b/debian/libapache2-mod-tile.templates deleted file mode 100644 index 9e37b1d9..00000000 --- a/debian/libapache2-mod-tile.templates +++ /dev/null @@ -1,6 +0,0 @@ -Template: libapache2-mod-tile/enablesite -Type: boolean -Default: true -Description: Do you want to enable mod_tile in the apache config? - This will enable the apache config for mod_tile - WARNING: This will disable the currently active default site config diff --git a/debian/renderd.conf b/debian/renderd.conf deleted file mode 100644 index abf7590f..00000000 --- a/debian/renderd.conf +++ /dev/null @@ -1,22 +0,0 @@ -[renderd] -stats_file=/var/run/renderd/renderd.stats -socketname=/var/run/renderd/renderd.sock -num_threads=4 -tile_dir=/var/lib/mod_tile - -[mapnik] -plugins_dir=/usr/lib/mapnik/2.0/input -font_dir=/usr/share/fonts/truetype/ttf-dejavu -font_dir_recurse=false - -[default] -URI=/osm/ -XML=/etc/mapnik-osm-data/osm.xml -DESCRIPTION=This is the standard osm mapnik style -;ATTRIBUTION=©OpenStreetMap and contributors, CC-BY-SA -;HOST=tile.openstreetmap.org -;SERVER_ALIAS=http://a.tile.openstreetmap.org -;SERVER_ALIAS=http://b.tile.openstreetmap.org -;HTCPHOST=proxy.openstreetmap.org - diff --git a/debian/renderd.conffiles b/debian/renderd.conffiles deleted file mode 100644 index e69de29b..00000000 diff --git a/debian/renderd.init b/debian/renderd.init deleted file mode 100644 index 639a0b0d..00000000 --- a/debian/renderd.init +++ /dev/null @@ -1,153 +0,0 @@ -#! /bin/sh -### BEGIN INIT INFO -# Provides: renderd -# Required-Start: $remote_fs -# Required-Stop: $remote_fs -# Should-Start: postgresql -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Mapnik rendering daemon -# Description: Mapnik rendering daemon. -### END INIT INFO - -# Do NOT "set -e" - -# PATH should only include /usr/* if it runs after the mountnfs.sh script -PATH=/sbin:/usr/sbin:/bin:/usr/bin -DESC="Mapnik rendering daemon" -NAME=renderd -DAEMON=/usr/bin/$NAME -DAEMON_ARGS="" -PIDSOCKDIR=/var/run/$NAME -PIDFILE=$PIDSOCKDIR/$NAME.pid -SCRIPTNAME=/etc/init.d/$NAME -RUNASUSER=www-data - -# Exit if the package is not installed -[ -x "$DAEMON" ] || exit 0 - -# Read configuration variable file if it is present -[ -r /etc/default/$NAME ] && . /etc/default/$NAME - -# Load the VERBOSE setting and other rcS variables -. /lib/init/vars.sh - -# Define LSB log_* functions. -# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. -. /lib/lsb/init-functions - -# -# Function that starts the daemon/service -# -do_start() -{ - [ -d "$PIDSOCKDIR" ] || mkdir -p $PIDSOCKDIR && chown $RUNASUSER $PIDSOCKDIR - # Return - # 0 if daemon has been started - # 1 if daemon was already running - # 2 if daemon could not be started - start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $RUNASUSER --exec $DAEMON --test > /dev/null \ - || return 1 - start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $RUNASUSER --exec $DAEMON -- \ - $DAEMON_ARGS \ - || return 2 - # Add code here, if necessary, that waits for the process to be ready - # to handle requests from services started subsequently which depend - # on this one. As a last resort, sleep for some time. -} - -# -# Function that stops the daemon/service -# -do_stop() -{ - # Return - # 0 if daemon has been stopped - # 1 if daemon was already stopped - # 2 if daemon could not be stopped - # other if a failure occurred - start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME - RETVAL="$?" - [ "$RETVAL" = 2 ] && return 2 - # Wait for children to finish too if this is a daemon that forks - # and if the daemon is only ever run from this initscript. - # If the above conditions are not satisfied then add some other code - # that waits for the process to drop all resources that could be - # needed by services started subsequently. A last resort is to - # sleep for some time. - start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON - [ "$?" = 2 ] && return 2 - # Many daemons don't delete their pidfiles when they exit. - rm -f $PIDFILE - return "$RETVAL" -} - -# -# Function that sends a SIGHUP to the daemon/service -# -do_reload() { - # - # If the daemon can reload its configuration without - # restarting (for example, when it is sent a SIGHUP), - # then implement that here. - # - start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME - return 0 -} - -case "$1" in - start) - log_daemon_msg "Starting $DESC" "$NAME" - do_start - case "$?" in - 0|1) log_end_msg 0 ;; - 2) log_end_msg 1 ;; - esac - ;; - stop) - log_daemon_msg "Stopping $DESC" "$NAME" - do_stop - case "$?" in - 0|1) log_end_msg 0 ;; - 2) log_end_msg 1 ;; - esac - ;; - #reload|force-reload) - # - # If do_reload() is not implemented then leave this commented out - # and leave 'force-reload' as an alias for 'restart'. - # - #log_daemon_msg "Reloading $DESC" "$NAME" - #do_reload - #log_end_msg $? - #;; - restart|force-reload) - # - # If the "reload" option is implemented then remove the - # 'force-reload' alias - # - log_daemon_msg "Restarting $DESC" "$NAME" - do_stop - case "$?" in - 0|1) - do_start - case "$?" in - 0) log_end_msg 0 ;; - 1) log_end_msg 1 ;; # Old process is still running - *) log_end_msg 1 ;; # Failed to start - esac - ;; - *) - # Failed to stop - log_end_msg 1 - ;; - esac - ;; - *) - #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 - echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 - exit 3 - ;; -esac - -: diff --git a/debian/renderd.install b/debian/renderd.install deleted file mode 100644 index fb7d20e8..00000000 --- a/debian/renderd.install +++ /dev/null @@ -1,5 +0,0 @@ -readme.txt /usr/share/doc/renderd -debian/renderd.conf /etc -munin/renderd* /usr/share/munin/plugins - - diff --git a/debian/renderd.postinst b/debian/renderd.postinst deleted file mode 100644 index 3b91fce7..00000000 --- a/debian/renderd.postinst +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -set -e - -mkdir -p /var/lib/mod_tile -chown www-data:www-data /var/lib/mod_tile - -# automatically install munin plugins if munin is present. -if [ -d /etc/munin/plugins ] -then - cd /etc/munin/plugins - for i in /usr/share/munin/plugins/renderd_* - do - if [ ! -h `basename $i` ] - then - ln -s $i . - fi - done -fi - -#DEBHELPER# diff --git a/debian/renderd.prerm b/debian/renderd.prerm deleted file mode 100644 index f15209e9..00000000 --- a/debian/renderd.prerm +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -set -e - -# automatically remove munin plugins -if [ -d /etc/munin/plugins ] -then - rm -f /etc/munin/plugins/renderd_* -fi - -#DEBHELPER# diff --git a/debian/rules b/debian/rules deleted file mode 100755 index 00f31f6c..00000000 --- a/debian/rules +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/make -f -# -*- makefile -*- -# Sample debian/rules that uses debhelper. -# This file was originally written by Joey Hess and Craig Small. -# As a special exception, when this file is copied by dh-make into a -# dh-make output file, you may use that output file without restriction. -# This special exception was added by Craig Small in version 0.37 of dh-make. - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -configure: configure-stamp -configure-stamp: - dh_testdir - - # Add here commands to configure the package. - - touch configure-stamp - -build: build-arch build-indep -build-arch: build-stamp -build-indep: build-stamp -build-stamp: configure-stamp - dh_testdir - - # Add here commands to compile the package. - ./autogen.sh - ./configure --prefix=/usr --sysconfdir=/etc - $(MAKE) - - touch $@ - -clean: - dh_testdir - dh_testroot - rm -f build-stamp configure-stamp - rm -f config.status - rm -f config.log - # Add here commands to clean up after the build process. - $(MAKE) clean || /bin/true - - dh_clean - -patch: - -install: build - dh_testdir - dh_testroot - dh_prep - dh_installdirs - - # Add here commands to install the package into debian/libapache2-mod-tile. - $(MAKE) DESTDIR=$(CURDIR)/debian/libapache2-mod-tile install-mod_tile - $(MAKE) DESTDIR=$(CURDIR)/debian/renderd install - - -# Build architecture-independent files here. -binary-indep: build install -# We have nothing to do by default. - -# Build architecture-dependent files here. -binary-arch: build install - dh_testdir - dh_testroot - dh_installchangelogs - dh_installdocs - dh_installexamples - dh_install -# dh_installmenu - dh_installdebconf -# dh_installlogrotate -# dh_installemacsen -# dh_installpam -# dh_installmime -# dh_python - dh_installinit -# dh_installcron -# dh_installinfo - dh_installman - dh_link - dh_strip - dh_compress - dh_fixperms -# dh_perl - dh_makeshlibs - dh_installdeb - dh_shlibdeps - dh_gencontrol - dh_md5sums - dh_builddeb - -binary: binary-indep binary-arch -.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/debian/source/format b/debian/source/format deleted file mode 100644 index 89ae9db8..00000000 --- a/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (native) diff --git a/debian/tile.load b/debian/tile.load deleted file mode 100644 index eb6b3301..00000000 --- a/debian/tile.load +++ /dev/null @@ -1 +0,0 @@ -LoadModule tile_module /usr/lib/apache2/modules/mod_tile.so diff --git a/debian/tileserver_site.conf b/debian/tileserver_site.conf deleted file mode 100644 index 42802b9f..00000000 --- a/debian/tileserver_site.conf +++ /dev/null @@ -1,164 +0,0 @@ -# This is the Apache server configuration file for providing OSM tile support -# through mod_tile - - - ServerAdmin webmaster@localhost - - ServerName tile.mytileserver.org - ServerAlias a.tile.mytileserver.org b.tile.mytileserver.org c.tile.mytileserver.org - DocumentRoot /var/www - - ### - ### - # increase the log level for more detailed information - LogLevel info - -# You can manually configure each tile set with AddTileConfig or AddTileMimeConfig. -# The first argument is the URL path relative to this virtual host -# under which a tile set is served. The second argument specifies the -# name of the tile set. This is used in the communication with renderd -# and is the directory under which (meta)tiles are stored on disk. -# -# By default (AddTileConfig) mod_tile assumes you are serving png files, however, -# mod_tile can also serve arbitrary other tile types such as javascript vector tiles, -# assuming the backend render daemon can handle the file type. -# To this purpose AddTileMimeConfig takes a 3rd agument, the file extension and it -# will guess the correct mimetype from it. If the mime type is not set correctly automatically, -# you need to use the configuration file route, where you can specify the mimetype and file extension -# independently. -# -# AddTileConfig /folder/ TileSetName -# AddTileMimeConfig /folder2/ TileSetName2 js - -# Alternatively (or in addition) you can load all the tile sets defined in the configuration file into this virtual host - LoadTileConfigFile /etc/renderd.conf - -# Timeout before giving up for a tile to be rendered - ModTileRequestTimeout 3 - -# Timeout before giving up for a tile to be rendered that is otherwise missing - ModTileMissingRequestTimeout 10 - -# If tile is out of date, don't re-render it if past this load threshold (users gets old tile) - ModTileMaxLoadOld 2 - -# If tile is missing, don't render it if past this load threshold (user gets 404 error) - ModTileMaxLoadMissing 5 - -# Socket where we connect to the rendering daemon - ModTileRenderdSocketName /var/run/renderd/renderd.sock - -## -## Options controlling the cache proxy expiry headers. All values are in seconds. -## -## Caching is both important to reduce the load and bandwidth of the server, as -## well as reduce the load time for the user. The site loads fastest if tiles can be -## taken from the users browser cache and no round trip through the internet is needed. -## With minutely or hourly updates, however there is a trade-off between cacheability -## and freshness. As one can't predict the future, these are only heuristics, that -## need tuning. -## If there is a known update schedule such as only using weekly planet dumps to update the db, -## this can also be taken into account through the constant PLANET_INTERVAL in render_config.h -## but requires a recompile of mod_tile - -## The values in this sample configuration are not the same as the defaults -## that apply if the config settings are left out. The defaults are more conservative -## and disable most of the heuristics. - - -## -## Caching is always a trade-off between being up to date and reducing server load or -## client side latency and bandwidth requirements. Under some conditions, like poor -## network conditions it might be more important to have good caching rather than the latest tiles. -## Therefor the following config options allow to set a special hostheader for which the caching -## behaviour is different to the normal heuristics -## -## The CacheExtended parameters overwrite all other caching parameters (including CacheDurationMax) -## for tiles being requested via the hostname CacheExtendedHostname -#ModTileCacheExtendedHostname cache.tile.openstreetmap.org -#ModTileCacheExtendedDuration 2592000 - -# Upper bound on the length a tile will be set cacheable, which takes -# precedence over other settings of cacheing -ModTileCacheDurationMax 604800 - -# Sets the time tiles can be cached for that are known to by outdated and have been -# sent to renderd to be rerendered. This should be set to a value corresponding -# roughly to how long it will take renderd to get through its queue. There is an additional -# fuzz factor on top of this to not have all tiles expire at the same time -ModTileCacheDurationDirty 900 - -# Specify the minimum time mod_tile will set the cache expiry to for fresh tiles. There -# is an additional fuzz factor of between 0 and 3 hours on top of this. -ModTileCacheDurationMinimum 10800 - -# Lower zoom levels are less likely to change noticeable, so these could be cached for longer -# without users noticing much. -# The heuristic offers three levels of zoom, Low, Medium and High, for which different minimum -# cacheing times can be specified. - -#Specify the zoom level below which Medium starts and the time in seconds for which they can be cached -ModTileCacheDurationMediumZoom 13 86400 - -#Specify the zoom level below which Low starts and the time in seconds for which they can be cached -ModTileCacheDurationLowZoom 9 518400 - -# A further heuristic to determine cacheing times is when was the last time a tile has changed. -# If it hasn't changed for a while, it is less likely to change in the immediate future, so the -# tiles can be cached for longer. -# For example, if the factor is 0.20 and the tile hasn't changed in the last 5 days, it can be cached -# for up to one day without having to re-validate. -ModTileCacheLastModifiedFactor 0.20 - -## Tile Throttling -## Tile scrappers can often download large numbers of tiles and overly staining tileserver resources -## mod_tile therefore offers the ability to automatically throttle requests from ip addresses that have -## requested a lot of tiles. -## The mechanism uses a token bucket approach to shape traffic. I.e. there is an initial pool of n tiles -## per ip that can be requested arbitrarily fast. After that this pool gets filled up at a constant rate -## The algorithm has to metrics. One based on overall tiles served to an ip address and a second one based on -## the number of requests to renderd / tirex to render a new tile. - -## Overall enable or disable tile throttling -ModTileEnableTileThrottling Off -## When the tileserver is behind a proxy one can use the X-Forwarded-For http header to determin the remote IP for throttling -## 0: don't use X-Forwarded-For -## 1: Use the first address in the X-Forwarded chain, which should be the client address. However, this may not be trusted. -## 2: Use the last address in the X-Forwarded chain. If one uses a reverse proxy, this will be the IP address seen by the reverse proxy and can be trusted. -ModTileEnableTileThrottlingXForward 0 - -## Parameters (poolsize in tiles and topup rate in tiles per second) for throttling tile serving. -ModTileThrottlingTiles 10000 1 -## Parameters (poolsize in tiles and topup rate in tiles per second) for throttling render requests. -ModTileThrottlingRenders 128 0.2 - - - Options FollowSymLinks - AllowOverride None - - - Options Indexes FollowSymLinks MultiViews - AllowOverride None - Order allow,deny - allow from all - - - ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ - - AllowOverride None - Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch - Order allow,deny - Allow from all - - - Alias /doc/ "/usr/share/doc/" - - Options Indexes MultiViews FollowSymLinks - AllowOverride None - Order deny,allow - Deny from all - Allow from 127.0.0.0/255.0.0.0 ::1/128 - - - - diff --git a/docs/build/building_on_centos.md b/docs/build/building_on_centos.md new file mode 100644 index 00000000..e5224a51 --- /dev/null +++ b/docs/build/building_on_centos.md @@ -0,0 +1,73 @@ +# Building on CentOS + +This document provides users with step-by-step instructions on how to compile and use`mod_tile` and `renderd`. + +Please see our [Continuous Integration script](/.github/workflows/build-and-test.yml) for more details. + +_CentOS does not provide a `mapnik`/`mapnik-devel` package, so it will first need to be built & installed, which is beyond the scope of this document, please visit the project's [installation document on GitHub](https://github.com/mapnik/mapnik/blob/master/INSTALL.md) or our [Continuous Integration script](/.github/actions/dependencies/build-and-install/mapnik/action.yml) for more information._ + +## CentOS 7 + +```shell +#!/usr/bin/env bash + +# Update installed packages +sudo yum --assumeyes update + +# Install build dependencies +# (libmemcached-devel & librados2-devel are optional) +sudo yum --assumeyes install epel-release +sudo yum --assumeyes --setopt=install_weak_deps=False install \ + boost169-devel \ + cairo-devel \ + cmake3 \ + gcc \ + gcc-c++ \ + gdal \ + git \ + glib2-devel \ + harfbuzz-devel \ + httpd-devel \ + iniparser-devel \ + libcurl-devel \ + libicu-devel \ + libjpeg \ + libmemcached-devel \ + librados2-devel \ + libtiff \ + libwebp \ + make \ + proj + +# Download, Build, Test & Install `mod_tile` +export CFLAGS="-I/usr/include/boost169" +export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) +export CXXFLAGS="-I/usr/include/boost169" +rm -rf /tmp/mod_tile_src /tmp/mod_tile_build +mkdir /tmp/mod_tile_src /tmp/mod_tile_build +cd /tmp/mod_tile_src +git clone --depth 1 https://github.com/openstreetmap/mod_tile.git . +cd /tmp/mod_tile_build +cmake3 -B . -S /tmp/mod_tile_src \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + -DENABLE_TESTS:BOOL=ON +cmake3 --build . +ctest3 +sudo cmake --install . --prefix /usr --strip + +# Create /usr/share/renderd directory +sudo mkdir --parents /usr/share/renderd + +# Copy files of example map +sudo cp -av /tmp/mod_tile_src/utils/example-map /usr/share/renderd/example-map + +# Add configuration +sudo cp -av /tmp/mod_tile_src/etc/apache2/renderd-example-map.conf /etc/httpd/conf.d/renderd-example-map.conf +printf '\n[example-map]\nURI=/tiles/renderd-example\nXML=/usr/share/renderd/example-map/mapnik.xml\n' | sudo tee -a /etc/renderd.conf + +# Start services +sudo httpd +sudo renderd -f +``` + +Then you can visit: `http://localhost:8081/renderd-example-map` diff --git a/docs/build/building_on_centos_stream.md b/docs/build/building_on_centos_stream.md new file mode 100644 index 00000000..2d740ca2 --- /dev/null +++ b/docs/build/building_on_centos_stream.md @@ -0,0 +1,95 @@ +# Building on CentOS Stream + +This document provides users with step-by-step instructions on how to compile and use`mod_tile` and `renderd`. + +Please see our [Continuous Integration script](/.github/workflows/build-and-test.yml) for more details. + +_CentOS Stream does not provide a `mapnik`/`mapnik-devel` package, so it will first need to be built & installed, which is beyond the scope of this document, please visit the project's [installation document on GitHub](https://github.com/mapnik/mapnik/blob/master/INSTALL.md) or our [Continuous Integration script](/.github/actions/dependencies/build-and-install/mapnik/action.yml) for more information._ + +## CentOS Stream 8 + +```shell +#!/usr/bin/env bash + +# Update config-manager DNF plugin +sudo dnf --assumeyes install "dnf-command(config-manager)" + +# Enable PowerTools Repository +sudo dnf config-manager --save --setopt=powertools.enabled=1 +``` + +## CentOS Stream 9 + +```shell +#!/usr/bin/env bash + +# Update config-manager DNF plugin +sudo dnf --assumeyes install "dnf-command(config-manager)" + +# Enable CRB Repository +sudo dnf config-manager --save --setopt=crb.enabled=1 +``` + +## CentOS Stream 8/9 + +```shell +#!/usr/bin/env bash + +# Update installed packages +sudo dnf --assumeyes update + +# Install build dependencies +# (libmemcached-devel & librados2-devel are optional) +sudo dnf --assumeyes install epel-release +sudo dnf --assumeyes --setopt=install_weak_deps=False install \ + boost-devel \ + cairo-devel \ + cmake3 \ + gcc \ + gcc-c++ \ + gdal \ + git \ + glib2-devel \ + harfbuzz-devel \ + httpd-devel \ + iniparser-devel \ + libcurl-devel \ + libicu-devel \ + libjpeg \ + libmemcached-devel \ + librados2-devel \ + libtiff \ + libwebp \ + make \ + proj + +# Download, Build, Test & Install `mod_tile` +export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) +rm -rf /tmp/mod_tile_src /tmp/mod_tile_build +mkdir /tmp/mod_tile_src /tmp/mod_tile_build +cd /tmp/mod_tile_src +git clone --depth 1 https://github.com/openstreetmap/mod_tile.git . +cd /tmp/mod_tile_build +cmake -B . -S /tmp/mod_tile_src \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + -DENABLE_TESTS:BOOL=ON +cmake --build . +ctest +sudo cmake --install . --prefix /usr --strip + +# Create /usr/share/renderd directory +sudo mkdir --parents /usr/share/renderd + +# Copy files of example map +sudo cp -av /tmp/mod_tile_src/utils/example-map /usr/share/renderd/example-map + +# Add configuration +sudo cp -av /tmp/mod_tile_src/etc/apache2/renderd-example-map.conf /etc/httpd/conf.d/renderd-example-map.conf +printf '\n[example-map]\nURI=/tiles/renderd-example\nXML=/usr/share/renderd/example-map/mapnik.xml\n' | sudo tee -a /etc/renderd.conf + +# Start services +sudo httpd +sudo renderd -f +``` + +Then you can visit: `http://localhost:8081/renderd-example-map` diff --git a/docs/build/building_on_debian.md b/docs/build/building_on_debian.md new file mode 100644 index 00000000..b25a7341 --- /dev/null +++ b/docs/build/building_on_debian.md @@ -0,0 +1,67 @@ +# Building on Debian + +This document provides users with step-by-step instructions on how to compile and use`mod_tile` and `renderd`. + +Please see our [Continuous Integration script](/.github/workflows/build-and-test.yml) for more details. + +## Debian 10/11/12 + +```shell +#!/usr/bin/env bash + +# Update installed packages +sudo apt update && sudo apt --yes upgrade +sudo apt --yes install --reinstall ca-certificates + +# Install build dependencies +# (libmemcached-dev & librados-dev are optional) +sudo apt --no-install-recommends --yes install \ + apache2 \ + apache2-dev \ + cmake \ + curl \ + g++ \ + gcc \ + git \ + libcairo2-dev \ + libcurl4-openssl-dev \ + libglib2.0-dev \ + libiniparser-dev \ + libmapnik-dev \ + libmemcached-dev \ + librados-dev + +# Download, Build, Test & Install `mod_tile` +export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) +rm -rf /tmp/mod_tile_src /tmp/mod_tile_build +mkdir /tmp/mod_tile_src /tmp/mod_tile_build +cd /tmp/mod_tile_src +git clone --depth 1 https://github.com/openstreetmap/mod_tile.git . +cd /tmp/mod_tile_build +cmake -B . -S /tmp/mod_tile_src \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + -DENABLE_TESTS:BOOL=ON +cmake --build . +ctest +sudo cmake --install . --prefix /usr --strip + +# Create /usr/share/renderd directory +sudo mkdir --parents /usr/share/renderd + +# Copy files of example map +sudo cp -av /tmp/mod_tile_src/utils/example-map /usr/share/renderd/example-map + +# Add configuration +sudo cp -av /tmp/mod_tile_src/etc/apache2/renderd-example-map.conf /etc/apache2/sites-available/renderd-example-map.conf +printf '\n[example-map]\nURI=/tiles/renderd-example\nXML=/usr/share/renderd/example-map/mapnik.xml\n' | sudo tee -a /etc/renderd.conf + +# Enable configuration +a2enmod tile +a2ensite renderd-example-map + +# Start services +sudo apache2ctl start +sudo renderd -f +``` + +Then you can visit: `http://localhost:8081/renderd-example-map` diff --git a/docs/build/building_on_fedora.md b/docs/build/building_on_fedora.md new file mode 100644 index 00000000..44b36069 --- /dev/null +++ b/docs/build/building_on_fedora.md @@ -0,0 +1,60 @@ +# Building on Fedora + +This document provides users with step-by-step instructions on how to compile and use`mod_tile` and `renderd`. + +Please see our [Continuous Integration script](/.github/workflows/build-and-test.yml) for more details. + +## Fedora 34/35/36/37/38/39 + +```shell +#!/usr/bin/env bash + +# Update installed packages +sudo dnf --assumeyes update + +# Install build dependencies +# (libmemcached-devel & librados-devel are optional) +sudo dnf --assumeyes --setopt=install_weak_deps=False install \ + cairo-devel \ + cmake \ + gcc \ + gcc-c++ \ + git \ + glib2-devel \ + httpd-devel \ + iniparser-devel \ + libcurl-devel \ + libmemcached-devel \ + librados-devel \ + mapnik-devel + +# Download, Build, Test & Install `mod_tile` +export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) +rm -rf /tmp/mod_tile_src /tmp/mod_tile_build +mkdir /tmp/mod_tile_src /tmp/mod_tile_build +cd /tmp/mod_tile_src +git clone --depth 1 https://github.com/openstreetmap/mod_tile.git . +cd /tmp/mod_tile_build +cmake -B . -S /tmp/mod_tile_src \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + -DENABLE_TESTS:BOOL=ON +cmake --build . +ctest +sudo cmake --install . --prefix /usr --strip + +# Create /usr/share/renderd directory +sudo mkdir --parents /usr/share/renderd + +# Copy files of example map +sudo cp -av /tmp/mod_tile_src/utils/example-map /usr/share/renderd/example-map + +# Add configuration +sudo cp -av /tmp/mod_tile_src/etc/apache2/renderd-example-map.conf /etc/httpd/conf.d/renderd-example-map.conf +printf '\n[example-map]\nURI=/tiles/renderd-example\nXML=/usr/share/renderd/example-map/mapnik.xml\n' | sudo tee -a /etc/renderd.conf + +# Start services +sudo httpd +sudo renderd -f +``` + +Then you can visit: `http://localhost:8081/renderd-example-map` diff --git a/docs/build/building_on_freebsd.md b/docs/build/building_on_freebsd.md new file mode 100644 index 00000000..8631ef95 --- /dev/null +++ b/docs/build/building_on_freebsd.md @@ -0,0 +1,65 @@ +# Building on FreeBSD + +This document provides users with step-by-step instructions on how to compile and use`mod_tile` and `renderd`. + +Please see our [Continuous Integration script](/.github/workflows/build-and-test.yml) for more details. + +## FreeBSD 12/13/14 + +```shell +#!/usr/bin/env sh + +# Mapnik is not in the `quarterly` repository (2023.10.12) +sudo mkdir -p /usr/local/etc/pkg/repos +sudo sed 's#/quarterly#/latest#g' /etc/pkg/FreeBSD.conf > /usr/local/etc/pkg/repos/FreeBSD.conf + +# Update installed packages +sudo pkg upgrade --yes + +# Install build dependencies +# (libmemcached & ceph14 are optional) +sudo pkg install --yes \ + apache24 \ + cairo \ + ceph14 \ + cmake \ + coreutils \ + curl \ + git \ + glib \ + iniparser \ + libmemcached \ + mapnik \ + pkgconf + +# Download, Build, Test & Install `mod_tile` +export CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.ncpu) +export LIBRARY_PATH="/usr/local/lib" +rm -rf /tmp/mod_tile_src /tmp/mod_tile_build +mkdir /tmp/mod_tile_src /tmp/mod_tile_build +cd /tmp/mod_tile_src +git clone --depth 1 https://github.com/openstreetmap/mod_tile.git . +cd /tmp/mod_tile_build +cmake -B . -S /tmp/mod_tile_src \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + -DENABLE_TESTS:BOOL=ON +cmake --build . +ctest +sudo cmake --install . --prefix /usr --strip + +# Create /usr/share/renderd directory +sudo mkdir -p /usr/share/renderd + +# Copy files of example map +sudo cp -av /tmp/mod_tile_src/utils/example-map /usr/share/renderd/example-map + +# Add configuration +sudo cp -av /tmp/mod_tile_src/etc/apache2/renderd-example-map.conf /usr/local/etc/apache24/Includes/renderd-example-map.conf +printf '\n[example-map]\nURI=/tiles/renderd-example\nXML=/usr/share/renderd/example-map/mapnik.xml\n' | sudo tee -a /etc/renderd.conf + +# Start services +sudo httpd +sudo renderd -f +``` + +Then you can visit: `http://localhost:8081/renderd-example-map` diff --git a/docs/build/building_on_macos.md b/docs/build/building_on_macos.md new file mode 100644 index 00000000..872c355d --- /dev/null +++ b/docs/build/building_on_macos.md @@ -0,0 +1,64 @@ +# Building on macOS + +This document provides users with step-by-step instructions on how to compile and use`mod_tile` and `renderd`. + +Please see our [Continuous Integration script](/.github/workflows/build-and-test.yml) for more details. + +## macOS 11/12/13 + +```shell +#!/usr/bin/env bash + +# Update installed packages +brew upgrade + +# Install build dependencies +# (libmemcached is optional) +brew install \ + apr \ + cairo \ + cmake \ + coreutils \ + curl \ + glib \ + httpd \ + iniparser \ + libmemcached \ + mapnik \ + pkg-config + +# Download, Build, Test & Install `mod_tile` +export CFLAGS="-Wno-implicit-function-declaration" +export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) +export ICU_ROOT=$(brew --prefix icu4c) +export LDFLAGS="-undefined dynamic_lookup" +export LIBRARY_PATH="/usr/local/lib" +rm -rf /tmp/mod_tile_src /tmp/mod_tile_build +mkdir /tmp/mod_tile_src /tmp/mod_tile_build +cd /tmp/mod_tile_src +git clone --depth 1 https://github.com/openstreetmap/mod_tile.git . +cd /tmp/mod_tile_build +cmake -B . -S /tmp/mod_tile_src \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + -DENABLE_TESTS:BOOL=ON +cmake --build . +ctest +sudo cmake --install . --prefix /usr/local --strip + +# Create /usr/local/share/renderd directory +sudo mkdir -p /usr/local/share/renderd + +# Copy files of example map +sudo cp -av /tmp/mod_tile_src/utils/example-map /usr/local/share/renderd/example-map + +# Add configuration +sed 's#/usr/share/#/usr/local/share/#g' /tmp/mod_tile_src/etc/apache2/renderd-example-map.conf | sudo tee /usr/local/etc/httpd/extra/renderd-example-map.conf +printf '\nInclude /usr/local/etc/httpd/extra/httpd-tile.conf\nInclude /usr/local/etc/httpd/extra/renderd-example-map.conf\n' | sudo tee -a /usr/local/etc/httpd/httpd.conf +printf '\n[example-map]\nURI=/tiles/renderd-example\nXML=/usr/local/share/renderd/example-map/mapnik.xml\n' | sudo tee -a /etc/renderd.conf + +# Start services +httpd +sudo renderd -f +``` + +Then you can visit: `http://localhost:8081/renderd-example-map` diff --git a/docs/build/building_on_opensuse.md b/docs/build/building_on_opensuse.md new file mode 100644 index 00000000..ba4d3fdb --- /dev/null +++ b/docs/build/building_on_opensuse.md @@ -0,0 +1,66 @@ +# Building on openSUSE + +This document provides users with step-by-step instructions on how to compile and use`mod_tile` and `renderd`. + +Please see our [Continuous Integration script](/.github/workflows/build-and-test.yml) for more details. + +_openSUSE does not provide a `mapnik`/`mapnik-devel` package, so it will first need to be built & installed, which is beyond the scope of this document, please visit the project's [installation document on GitHub](https://github.com/mapnik/mapnik/blob/master/INSTALL.md) or our [Continuous Integration script](/.github/actions/dependencies/build-and-install/mapnik/action.yml) for more information._ + +## openSUSE 15 + +```shell +#!/usr/bin/env bash + +# Update installed packages +sudo zypper --non-interactive update + +# Install build dependencies +# (libmemcached-devel & librados-devel are optional) +sudo zypper --non-interactive install \ + apache2 \ + apache2-devel \ + apache2-prefork \ + cairo-devel \ + curl \ + glib2-devel \ + libcurl-devel \ + libiniparser-devel \ + libmemcached-devel \ + librados-devel + +# Create `nobody` user and group +sudo useradd --home-dir / --no-create-home --shell /usr/sbin/nologin --system --user-group nobody + +# Download, Build, Test & Install `mod_tile` +export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) +rm -rf /tmp/mod_tile_src /tmp/mod_tile_build +mkdir /tmp/mod_tile_src /tmp/mod_tile_build +cd /tmp/mod_tile_src +git clone --depth 1 https://github.com/openstreetmap/mod_tile.git . +cd /tmp/mod_tile_build +cmake -B . -S /tmp/mod_tile_src \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + -DENABLE_TESTS:BOOL=ON +cmake --build . +ctest +sudo cmake --install . --prefix /usr --strip + +# Create /usr/share/renderd directory +sudo mkdir --parents /usr/share/renderd + +# Copy files of example map +sudo cp -av /tmp/mod_tile_src/utils/example-map /usr/share/renderd/example-map + +# Add configuration +sudo cp -av /tmp/mod_tile_src/etc/apache2/renderd-example-map.conf /etc/apache2/conf.d/renderd-example-map.conf +printf '\n[example-map]\nURI=/tiles/renderd-example\nXML=/usr/share/renderd/example-map/mapnik.xml\n' | sudo tee -a /etc/renderd.conf + +# Enable `mod_access_compat` +sudo sed -i 's/^APACHE_MODULES="actions/APACHE_MODULES="access_compat actions/g' /etc/sysconfig/apache2 + +# Start services +sudo apache2ctl start +sudo renderd -f +``` + +Then you can visit: `http://localhost:8081/renderd-example-map` diff --git a/docs/build/building_on_ubuntu.md b/docs/build/building_on_ubuntu.md new file mode 100644 index 00000000..1607aeab --- /dev/null +++ b/docs/build/building_on_ubuntu.md @@ -0,0 +1,67 @@ +# Building on Ubuntu + +This document provides users with step-by-step instructions on how to compile and use`mod_tile` and `renderd`. + +Please see our [Continuous Integration script](/.github/workflows/build-and-test.yml) for more details. + +# Ubuntu 20.04/22.04 + +```shell +#!/usr/bin/env bash + +# Update installed packages +sudo apt update && sudo apt --yes upgrade +sudo apt --yes install --reinstall ca-certificates + +# Install build dependencies +# (libmemcached-dev & librados-dev are optional) +sudo apt --no-install-recommends --yes install \ + apache2 \ + apache2-dev \ + cmake \ + curl \ + g++ \ + gcc \ + git \ + libcairo2-dev \ + libcurl4-openssl-dev \ + libglib2.0-dev \ + libiniparser-dev \ + libmapnik-dev \ + libmemcached-dev \ + librados-dev + +# Download, Build, Test & Install `mod_tile` +export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) +rm -rf /tmp/mod_tile_src /tmp/mod_tile_build +mkdir /tmp/mod_tile_src /tmp/mod_tile_build +cd /tmp/mod_tile_src +git clone --depth 1 https://github.com/openstreetmap/mod_tile.git . +cd /tmp/mod_tile_build +cmake -B . -S /tmp/mod_tile_src \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + -DENABLE_TESTS:BOOL=ON +cmake --build . +ctest +sudo cmake --install . --prefix /usr --strip + +# Create /usr/share/renderd directory +sudo mkdir --parents /usr/share/renderd + +# Copy files of example map +sudo cp -av /tmp/mod_tile_src/utils/example-map /usr/share/renderd/example-map + +# Add configuration +sudo cp -av /tmp/mod_tile_src/etc/apache2/renderd-example-map.conf /etc/apache2/sites-available/renderd-example-map.conf +printf '\n[example-map]\nURI=/tiles/renderd-example\nXML=/usr/share/renderd/example-map/mapnik.xml\n' | sudo tee -a /etc/renderd.conf + +# Enable configuration +a2enmod tile +a2ensite renderd-example-map + +# Start services +sudo apache2ctl start +sudo renderd -f +``` + +Then you can visit: `http://localhost:8081/renderd-example-map` diff --git a/docs/convert_meta.1 b/docs/man/convert_meta.1 similarity index 85% rename from docs/convert_meta.1 rename to docs/man/convert_meta.1 index 6e6e9c4c..4696c0a2 100644 --- a/docs/convert_meta.1 +++ b/docs/man/convert_meta.1 @@ -1,11 +1,14 @@ -.TH CONVERT_META 1 "Jan 25, 2012" +.TH CONVERT_META "1" "2023-12-19" "mod_tile v0.7.0" .\" Please adjust this date whenever revising the manpage. + .SH NAME convert_meta \- A conversion program from .png map tiles to a more efficient conglomerate format (.meta). + .SH SYNOPSIS .B convert_meta .RI [ options ] -.br +.BR + .SH DESCRIPTION This manual page documents briefly the .B convert_meta @@ -16,17 +19,18 @@ converts individual .png map tiles into the more efficient .meta file format. Th format stores a grid of 8x8 tiles in a single meta tile, reducing the number of files by a factor of 64. .PP + .SH OPTIONS This program follows the usual GNU command line syntax, with long options starting with two dashes (`-'). A summary of options is included below. .TP \fB\-t\fR|\-\-tile-dir -Specify the base directory where the tiles are stored. The default is /var/lib/mod_tile +Specify the base directory where the tiles are stored. The default is /var/cache/renderd/tiles .TP \fB\-m\fR|\-\-map Specify the map style to convert. This specifies the full path to the files and is relative to the tile directory. -The default is "default" and results in a full path of /var/lib/mod_tile/default to search for the tiles to convert +The default is "default" and results in a full path of /var/cache/renderd/tiles/default to search for the tiles to convert .TP \fB\-u\fR|\-\-unpack Unpack the .meta files back to PNGs @@ -37,6 +41,7 @@ Specify the smallest zoom level to process. The default is 0. \fB\-Z\fR|\-\-max-zoom Specify the largest zoom level up to which to process tiles. The default is 18. .PP + .SH AUTHOR convert_meta was written by Jon Burgess and other OpenStreetMap project members. diff --git a/docs/openstreetmap-tiles-update-expire.1 b/docs/man/openstreetmap-tiles-update-expire.1 similarity index 94% rename from docs/openstreetmap-tiles-update-expire.1 rename to docs/man/openstreetmap-tiles-update-expire.1 index b1348fb5..bba4e72b 100644 --- a/docs/openstreetmap-tiles-update-expire.1 +++ b/docs/man/openstreetmap-tiles-update-expire.1 @@ -1,11 +1,14 @@ -.TH TILES-UPDATE-EXPIRE 1 "Apr 20, 2013" +.TH TILES-UPDATE-EXPIRE "1" "2023-12-19" "mod_tile v0.7.0" .\" Please adjust this date whenever revising the manpage. + .SH NAME openstreetmap-tiles-update-expire \- updates a map database from the OSM diff stream. + .SH SYNOPSIS .B openstreetmap-tiles-update-expire .RI [ YYYY-MM-DD ] -.br +.BR + .SH DESCRIPTION This manual page documents briefly the .B openstreetmap-tiles-update-expire @@ -15,18 +18,19 @@ command. is a helper script to keep a mod_tile based openstreetmap tile server up to date. It downloads a diff stream from OpenStreetMap using osmosis, then applies it to your database using osm2pgsql and finally marks changed tiles on disk as "dirty". -.br +.BR Each time you call this script, it does one update cycle. If your db is further behind than the maximum duration for which osmosis is configured to fetch diffs, the db will not be fully up-to-date at the end of this script and it will be necessary to call it multiple times for a fully up-to-date database. -.br +.BR This script can be used in conjunction with cron to automatically keep your database in sync with the OSM diff stream. .PP The first time this script needs to be called with a date to initialise the process. Thereafter, the script gets called without arguments. .PP + .SH OPTIONS .TP \fBYYYY-MM-DD @@ -36,10 +40,11 @@ ensures that there is no missing data due to a gap between the generation of the the start of the diff processing. .PP + .SH SEE ALSO -.BR renderd (8), -.BR mod_tile (1). -.br +.BR renderd(1) +.BR + .SH AUTHOR openstreetmap-tiles-update-expire was written by OpenStreetMap project members. .PP diff --git a/docs/render_expired.1 b/docs/man/render_expired.1 similarity index 84% rename from docs/render_expired.1 rename to docs/man/render_expired.1 index 89a79892..008599a4 100644 --- a/docs/render_expired.1 +++ b/docs/man/render_expired.1 @@ -1,11 +1,14 @@ -.TH RENDER_EXPIRED 1 "Jan 27, 2012" +.TH RENDER_EXPIRED "1" "2023-12-19" "mod_tile v0.7.0" .\" Please adjust this date whenever revising the manpage. + .SH NAME render_expired \- expires a list of map tiles so that they get re-rendered. + .SH SYNOPSIS .B render_expired .RI [ options ] < "expire.list" -.br +.BR + .SH DESCRIPTION This manual page documents briefly the .B render_expired @@ -14,27 +17,28 @@ command. .B render_expired is a helper utility that takes a list of map tiles from stdin and expires them such that they will get re-rendered. Render_expired has three potential strategies of how to expire map tiles: -.br +.BR 1) Render tiles directly: Render_expired can connect to the renderd socket and submit rendering requests for expired tiles directly -.br +.BR 2) Delete tiles: Render_expired can delete expired tiles from disk. The next time the tile then gets viewed it will get re-rendered, assuming a dynamic rendering setup like mod_tile is installed -.br +.BR 3) Mark tiles as dirty: A dynamic tile rendering system like mod_tile decides if a tile needs re-rendering by comparing the timestamp of the tile with the time of the planet-import-complet timestamp. Render_expired can set the timestamp of a tile back many years, ensuring it is older than the db import time, thus causeing the tile to be considered dirty and in need for re-render. .PP These three strategies can be combined and applied at different zoom levels. E.g. Zoom level 17-18 get deleted, z11 - z16 get marked dirty and z6 - z10 get rendered directly. .PP Render_expired takes a list of tiles from stdin which should be expired. The format of the list is one tile per line specified as z/x/y. -.br +.BR 1/0/1 -.br +.BR 1/1/1 -.br +.BR 1/0/0 -.br +.BR 1/1/0 .PP render_expired will automatically expand the list to cover the effected tiles at other zoom levels. .PP + .SH OPTIONS This program follows the usual GNU command line syntax, with long options starting with two dashes (`-'). @@ -43,15 +47,15 @@ A summary of options is included below. \fB\-m\fR|\-\-map=MAP Specify the style-sheet for which to expire tiles. The default is "default". .TP -\fB\-s\fR|\-\-socket=SOCKET -Specify the location of the renderd socket. +\fB\-s\fR|\-\-socket=SOCKET|HOSTNAME:PORT +Specify the location of the renderd socket or hostname and port to connect to. .TP \fB\-n\fR|\-\-num-threads=N Specify the number of parallel requests to renderd. Should renderd have less threads active, requests will be queued. The default is 1. default if \fB\-\-append\fR is not specified. .TP -\fB\-t\fR|\-\-tiledir=DIR -Specify the base directory where the rendered tiles are. The default is '/var/lib/mod_tile' +\fB\-t\fR|\-\-tile-dir=DIR +Specify the base directory where the rendered tiles are. The default is '/var/cache/renderd/tiles' .TP \fB\-z\fR|\-\-min-zoom=ZOOM Filter input to only render tiles greater or equal to this zoom level (default is 0) @@ -64,11 +68,21 @@ When expiring tiles of ZOOM or higher, delete them instead of re-rendering (defa .TP \fB\-T\fR|\-\-touch-from=ZOOM when expiring tiles of ZOOM or higher, touch them instead of re-rendering (default is off) +.TP +\-\-no-progress +Disable display of progress messages (default is off) +.TP +\fB\-h\fR|\-\-help +Print out a help text for render_expired +.TP +\fB\-V\fR|\-\-version +Print out the version number for render_expired .PP + .SH SEE ALSO -.BR renderd (1), -.BR mod_tile (1). -.br +.BR renderd(1) +.BR + .SH AUTHOR render_expire was written by OpenStreetMap project members. .PP diff --git a/docs/man/render_list.1 b/docs/man/render_list.1 new file mode 100644 index 00000000..a6fd40ae --- /dev/null +++ b/docs/man/render_list.1 @@ -0,0 +1,93 @@ +.TH RENDER_LIST "1" "2023-12-19" "mod_tile v0.7.0" +.\" Please adjust this date whenever revising the manpage. + +.SH NAME +render_list \- renders a list of map tiles by sending requests to a rendering daemon. + +.SH SYNOPSIS +.B render_list +.RI [ options ] < "render.list" +.BR + +.SH DESCRIPTION +This manual page briefly documents the +.B render_list +command. +.PP +.B render_list +is a helper utility that takes a list of map tiles from stdin and sends the requests to a rendering daemon +.PP + +.SH OPTIONS +This program follows the usual GNU command line syntax, with long +options starting with two dashes (`-'). +A summary of options is included below. +.TP +\fB\-a\fR|\-\-all +Render all tiles in given zoom level range instead of reading from STDIN. +.TP +\fB\-f\fR|\-\-force +Render tiles even if they seem current. +.TP +\fB\-m\fR|\-\-map=MAP +Render tiles in this map (defaults to 'default'). +.TP +\fB\-l\fR|\-\-max-load=LOAD +Sleep if load is this high (defaults to 16). +.TP +\fB\-s\fR|\-\-socket=SOCKET|HOSTNAME:PORT +Unix domain socket name or hostname and port for contacting renderd. +.TP +\fB\-n\fR|\-\-num-threads=N +The number of parallel request threads (default 1). +.TP +\fB\-t\fR|\-\-tile-dir +Tile cache directory (defaults to '/var/cache/renderd/tiles'). +.TP +\fB\-z\fR|\-\-min-zoom=ZOOM +Filter input to only render tiles greater or equal to this zoom level (default is 0). +.TP +\fB\-Z\fR|\-\-max-zoom=ZOOM +Filter input to only render tiles less than or equal to this zoom level (default is 20). +.PP +If you are using --all, you can restrict the tile range by adding these options: +.BR + -x, --min-x=X minimum X tile coordinate +.BR + -X, --max-x=X maximum X tile coordinate +.BR + -y, --min-y=Y minimum Y tile coordinate +.BR + -Y, --max-y=Y maximum Y tile coordinate +.PP +Without --all, send a list of tiles to be rendered from STDIN in the format: +.BR + X Y Z +.BR +e.g. +.BR + 0 0 1 +.BR + 0 1 1 +.BR + 1 0 1 +.BR + 1 1 1 +.BR +The above would cause all 4 tiles at zoom 1 to be rendered +.TP +\fB\-h\fR|\-\-help +Print out a help text for render_list +.TP +\fB\-V\fR|\-\-version +Print out the version number for render_list +.PP + +.SH SEE ALSO +.BR renderd(1) +.BR + +.SH AUTHOR +render_list was written by OpenStreetMap project members. +.PP +This manual page was written by OpenStreetMap authors. diff --git a/docs/render_old.1 b/docs/man/render_old.1 similarity index 87% rename from docs/render_old.1 rename to docs/man/render_old.1 index e597ca30..6d346799 100644 --- a/docs/render_old.1 +++ b/docs/man/render_old.1 @@ -1,11 +1,14 @@ -.TH RENDER_OLD 1 "Mar 28, 2013" +.TH RENDER_OLD "1" "2023-12-19" "mod_tile v0.7.0" .\" Please adjust this date whenever revising the manpage. + .SH NAME render_old \- renders a list of map tiles by sending requests to a rendering daemon. + .SH SYNOPSIS .B render_list .RI [ options ] < "render.list" -.br +.BR + .SH DESCRIPTION This manual page documents briefly the .B render_old @@ -14,10 +17,11 @@ command. .B render_old is a helper utility that pre renders expired map tiles by sending appropriate requests to a rendering daemon .PP + .SH SEE ALSO -.BR renderd (8), -.BR mod_tile (1). -.br +.BR renderd(1) +.BR + .SH AUTHOR render_expire was written by OpenStreetMap project members. .PP diff --git a/docs/man/render_speedtest.1 b/docs/man/render_speedtest.1 new file mode 100644 index 00000000..cafd6f50 --- /dev/null +++ b/docs/man/render_speedtest.1 @@ -0,0 +1,55 @@ +.TH RENDER_SPEEDTEST "1" "2023-12-19" "mod_tile v0.7.0" +.\" Please adjust this date whenever revising the manpage. + +.SH NAME +render_speedtest \- Benchmark tile rendering with renderd. + +.SH SYNOPSIS +.B render_speedtest +.RI [ options ] + +.SH DESCRIPTION +This manual page documents briefly the +.B render_speedtest +command. +.PP +.B render_speedtest +renders a bunch of tiles at various zoom levels to benchmark the speed of the rendering. +.PP + +.SH OPTIONS +These programs follow the usual GNU command line syntax, with long +options starting with two dashes (`-'). +A summary of options is included below. +.TP +\fB\-s\fR|\-\-socket=SOCKET|HOSTNAME:PORT +Specify the location of the renderd socket or hostname and port to connect to. +.TP +\fB\-m\fR|\-\-map=MAP +Specify the rendering style to test. The default is "default" +.TP +\fB\-n\fR|\-\-num-threads=N +The number of parallel request threads (default 1). +.TP +\fB\-z\fR|\-\-min-zoom=ZOOM +Only render tiles greater or equal to this zoom level (default is 0). +.TP +\fB\-Z\fR|\-\-max-zoom=ZOOM +Only render tiles less than or equal to this zoom level (default is 20). +.TP +\fB\-h\fR|\-\-help +Print out a help text for render_speedtest +.TP +\fB\-V\fR|\-\-version +Print out the version number for render_speedtest +.PP + +.SH SEE ALSO +.BR renderd(1) +.BR + +.SH AUTHOR +render_speedtest was written by Jon Burgess and other +OpenStreetMap project members. +.PP +This manual page was written by OpenStreetMap authors. diff --git a/docs/renderd.8 b/docs/man/renderd.1 similarity index 84% rename from docs/renderd.8 rename to docs/man/renderd.1 index 6b9a7564..c57e6b3b 100644 --- a/docs/renderd.8 +++ b/docs/man/renderd.1 @@ -1,11 +1,14 @@ -.TH RENDERD 1 "Jan 25, 2012" +.TH RENDERD "1" "2023-12-19" "mod_tile v0.7.0" .\" Please adjust this date whenever revising the manpage. + .SH NAME renderd \- Rendering daemon for rendering OpenStreetMap tiles. + .SH SYNOPSIS .B renderd .RI [ options ] -.br +.BR + .SH DESCRIPTION This manual page documents briefly the .B renderd @@ -17,6 +20,7 @@ on a socket. Renderd queues requests in a number of different queues to manage l rendering the requests with the mapnik library. By default renderd will start as a daemon. It will log information in the syslog. .PP + .SH OPTIONS This programs follow the usual GNU command line syntax, with long options starting with two dashes (`-'). @@ -30,16 +34,21 @@ Set the location of the config file used to configure the various parameters of like the mapnik style sheet. The default is /etc/renderd.conf .TP \fB\-s\fR|\-\-slave -Renderd can be used in a distributed fashion accross multiple rendering servers. The master renderd handles queuing and +Renderd can be used in a distributed fashion across multiple rendering servers. The master renderd handles queuing and passes requests to the slaves. This parameter specifies which of the slave sections of renderd.conf applies to this instance of renderd. The default is to use the master section .TP \fB\-h\fR|\-\-help Print out a help text for renderd +.TP +\fB\-V\fR|\-\-version +Print out the version number for renderd .PP + .SH SEE ALSO -.BR renderd.conf (1), -.br +.BR renderd.conf(5) +.BR + .SH AUTHOR renderd was written by Jon Burgess, and other OpenStreetMap project members. .PP diff --git a/docs/man/renderd.conf.5 b/docs/man/renderd.conf.5 new file mode 100644 index 00000000..d5cde5d8 --- /dev/null +++ b/docs/man/renderd.conf.5 @@ -0,0 +1,208 @@ +.TH RENDERD.CONF 5 "2023-12-19" "mod_tile v0.7.0" +.\" Please adjust this date whenever revising the manpage. + +.SH NAME +renderd.conf \- Configuration file of rendering daemon for rendering OpenStreetMap tiles. + +.SH SYNOPSIS +renderd.conf + +.SH DESCRIPTION +This manual page documents briefly the \fBrenderd.conf\fR configuration file. +.PP +\fBrenderd.conf\fR is an INI configuration file for use with \fBrenderd(1)\fR. +.PP +The default location is \fB'/etc/renderd.conf'\fR (macro definition \fB'RENDERD_CONFIG'\fR). +.PP +All option names are \fBcase-insensitive\fR unless otherwise specified. + + +.SH RENDERD +Options belonging to a \fB[renderd]\fR section. +.PP +There must be at least one \fB[renderd]\fR section (e.g. \fB[renderd]\fR or \fB[renderd0]\fR). +.PP +By default, there can be up to \fB5\fR (macro definition \fB'MAX_SLAVES'\fR) \fB[renderd]\fR sections (e.g. \fB[renderd0]\fR - \fB[renderd4]\fR). +.PP +\fB[renderd]\fR section names must begin with \fB[renderd]\fR. + +.TP +.B iphostname +Specify the IP address/hostname to be used for communication with \fBrenderd\fR. +This must be specified in combination with \fBipport\fR. +This option and \fBsocketname\fR are mutually exclusive. + +.TP +.B ipport +Specify the port number to be used for communication with \fBrenderd\fR. +This must be specified in combination with \fBiphostname\fR. +This option and \fBsocketname\fR are mutually exclusive. + +.TP +.B num_threads +Specify the number of threads to be used for \fBrenderd\fR. +The default value is \fB'4'\fR (macro definition \fB'NUM_THREADS'\fR). + +.TP +.B pid_file +Specify the file path into which the PID will be written by \fBrenderd\fR. +It is only written to when \fBrenderd\fR is not running in \fBforeground\fR mode (e.g. without \fB'--foreground'\fR / \fB'-f')\fR. +The default value is \fB'/var/run/renderd/renderd.pid'\fR (macro definition \fB'RENDERD_PIDFILE'\fR). + +.TP +.B socketname +Specify the file path to be used as a unix domain socket for communication with \fBrenderd\fR. +This option and \fBiphostname\fR / \fBipport\fR are mutually exclusive. +The default value is \fB'/var/run/renderd/renderd.sock'\fR (macro definition \fB'RENDERD_SOCKET'\fR). + +.TP +.B stats_file +Specify the file path into which statistics will be written by \fBrenderd\fR. +By default, a stats file will not be created. + +.TP +.B tile_dir +Specify the directory path into which tiles will be written by \fBrenderd\fR. +The default value is \fB'/var/cache/renderd/tiles'\fR (macro definition \fB'RENDERD_TILE_DIR'\fR). + + +.SH MAPNIK +Options belonging to the \fB[mapnik]\fR section. +.PP +There can be only one \fB[mapnik]\fR section. +.PP +\fB[mapnik]\fR section name must be equal to \fB[mapnik]\fR. + +.TP +.B font_dir +Specify the directory path where fonts are searched for by \fBlibmapnik\fR. +The default value is the output of \fB'mapnik-config --fonts'\fR / \fB'pkgconf --variable=fonts_dir libmapnik'\fR (macro definition \fB'MAPNIK_FONTS_DIR'\fR). + +.TP +.B font_dir_recurse +Specify whether or not to recurse the \fBfont_dir\fR when searching for fonts by \fBlibmapnik\fR. +The default value is \fB'false'\fR / \fB'0'\fR (macro definition \fB'MAPNIK_FONTS_DIR_RECURSE'\fR). + +.TP +.B plugins_dir +Specify the directory path where input plugins are searched for by \fBlibmapnik\fR. +The default value is the output of \fB'mapnik-config --input-plugins'\fR / \fB'pkgconf --variable=plugins_dir libmapnik'\fR (macro definition \fB'MAPNIK_PLUGINS_DIR'\fR). + + +.SH MAP SECTION +Options belonging a \fB[map]\fR section. +.PP +There must be at least one \fB[map]\fR section. +.PP +\fB[map]\fR section names can neither begin with \fB[renderd]\fR nor be equal to \fB[mapnik]\fR. +.PP +\fB[map]\fR section names can be anything else, but they must all be unique. + +.TP +.B ASPECTX +Specify the X aspect to be used by \fBmod_tile\fR. +Only used by \fBmod_tile\fR. +The default value is \fB'1'\fR. +This option name is \fBcase-sensitive\fR. + +.TP +.B ASPECTY +Specify the Y aspect to be used by \fBmod_tile\fR. +Only used by \fBmod_tile\fR. +The default value is \fB'1'\fR. +This option name is \fBcase-sensitive\fR. + +.TP +.B ATTRIBUTION +Specify the data attribution to be provided by \fBmod_tile\fR as \fBTileJSON\fR (via \fB{URI}/tile-layer.json\fR). +Only used by \fBmod_tile\fR. +The default value is \fB'©OpenStreetMap and contributors, (ODbL)'\fR (macro definition \fB'DEFAULT_ATTRIBUTION'\fR). +This option name is \fBcase-sensitive\fR. + +.TP +.B CORS +Specify the CORS configuration for \fBmod_tile\fR. +Only used by \fBmod_tile\fR. +This option name is \fBcase-sensitive\fR. + +.TP +.B DESCRIPTION +Specify the description to be provided by \fBmod_tile\fR as \fBTileJSON\fR (via \fB{URI}/tile-layer.json\fR). +Only used by \fBmod_tile\fR. +This option name is \fBcase-sensitive\fR. + +.TP +.B htcphost +Specify the IP address/hostname of the HTCP Host to be used by \fBrenderd\fR for HTCP cache expiry. +Only used by \fBrenderd\fR. + +.TP +.B host +Specify the IP address/hostname of the Host to be used by \fBrenderd\fR for HTCP cache expiry. +Only used by \fBrenderd\fR. + +.TP +.B MAXZOOM +Specify the maximum zoom level for this section. +The default value is \fB'20'\fR (macro definition \fB'MAX_ZOOM'\fR). +This option name is \fBcase-sensitive\fR. + +.TP +.B MINZOOM +Specify the minimum zoom level for this section. +The default value is \fB'0'\fR. +This option name is \fBcase-sensitive\fR. + +.TP +.B PARAMETERIZE_STYLE +Specify the parameterization style/function to be used for this section. +The value of \fB'language'\fR seems to be the only one supported. +This option name is \fBcase-sensitive\fR. + +.TP +.B SERVER_ALIAS +Specify a URL alias of this server to be provided by \fBmod_tile\fR as \fBTileJSON\fR (via \fB{URI}/tile-layer.json\fR). +Only used by \fBmod_tile\fR. +This option name is \fBcase-sensitive\fR. + +.TP +.B scale +Specify the scale for this section. +Only used by \fBrenderd\fR. +The default value is \fB'1.0'\fR. + +.TP +.B TILEDIR +Specify the directory path into which tiles will be written by \fBrenderd\fR. +The default value is \fB'/var/cache/renderd/tiles'\fR (macro definition \fB'RENDERD_TILE_DIR'\fR). +This option name is \fBcase-sensitive\fR. + +.TP +.B tilesize +Specify the tile size for this section. +Only used by \fBrenderd\fR. +The default value is \fB'256'\fR. + +.TP +.B TYPE +Specify the tile configuration (in the format \fB' '\fR) for this section (e.g. \fB'png image/png png256'\fR). +This option name is \fBcase-sensitive\fR. + +.TP +.B URI +Specify the URI prefix with which tiles can be accessed for this section. +This option name is \fBcase-sensitive\fR. + +.TP +.B xml +Specify the file path of the Mapnik configuration XML file for this section. +Only used by \fBrenderd\fR. + +.SH SEE ALSO +.BR renderd(1) +.BR + +.SH AUTHOR +renderd was written by Jon Burgess, and other OpenStreetMap project members. +.PP +This manual page was written by OpenStreetMap authors. \ No newline at end of file diff --git a/docs/render_list.1 b/docs/render_list.1 deleted file mode 100644 index e66d071d..00000000 --- a/docs/render_list.1 +++ /dev/null @@ -1,24 +0,0 @@ -.TH RENDER_LIST 1 "Apr 25, 2013" -.\" Please adjust this date whenever revising the manpage. -.SH NAME -render_list \- renders a list of map tiles by sending requests to a rendering daemon. -.SH SYNOPSIS -.B render_list -.RI [ options ] < "render.list" -.br -.SH DESCRIPTION -This manual page documents briefly the -.B render_list -command. -.PP -.B render_list -is a helper utility that takes a list of map tiles from stdin and sends the requests to a rendering daemon -.PP -.SH SEE ALSO -.BR renderd (8), -.BR mod_tile (1). -.br -.SH AUTHOR -render_list was written by OpenStreetMap project members. -.PP -This manual page was written by OpenStreetMap authors. diff --git a/docs/render_speedtest.1 b/docs/render_speedtest.1 deleted file mode 100644 index 32d99b98..00000000 --- a/docs/render_speedtest.1 +++ /dev/null @@ -1,34 +0,0 @@ -.TH SPEEDTEST 1 "Jan 25, 2012" -.\" Please adjust this date whenever revising the manpage. -.SH NAME -speedtest \- Benchmapr tile rendering with renderd. -.SH SYNOPSIS -.B speedtest -.RI [ options ] -.SH DESCRIPTION -This manual page documents briefly the -.B speedtest -command. -.PP -.B speedtest -renders a bunch of tiles at various zoom levels to benchmark the speed of the rendering. -.PP -.SH OPTIONS -These programs follow the usual GNU command line syntax, with long -options starting with two dashes (`-'). -A summary of options is included below. -.TP -\fB\-s\fR|\-\-socket=SOCKET -Specify the location of the renderd socket to connect to. -.TP -\fB\-m\fR|\-\-map=MAP -Specify the rendering style to test. The default is "default" -.PP -.SH SEE ALSO -.BR renderd (1), -.br -.SH AUTHOR -speedtest was written by Jon Burgess and other -OpenStreetMap project members. -.PP -This manual page was written by OpenStreetMap authors. diff --git a/etc/apache2/renderd-example-map.conf b/etc/apache2/renderd-example-map.conf new file mode 100644 index 00000000..6d038391 --- /dev/null +++ b/etc/apache2/renderd-example-map.conf @@ -0,0 +1,158 @@ +Alias /renderd-example-map /usr/share/renderd/example-map +Redirect /renderd-example-map/leaflet/leaflet.css https://unpkg.com/leaflet/dist/leaflet.css +Redirect /renderd-example-map/leaflet/leaflet.min.js https://unpkg.com/leaflet/dist/leaflet.js + + + Options +FollowSymLinks + AllowOverride All + Order Allow,Deny + Allow from all + + Require all granted + + + +Listen 8081 + + + ModTileTileDir /var/cache/renderd/tiles + + # You can manually configure each tile set with AddTileConfig or AddTileMimeConfig. + # The first argument is the URL path relative to this virtual host + # under which a tile set is served. The second argument specifies the + # name of the tile set. This is used in the communication with renderd + # and is the directory under which (meta)tiles are stored on disk. + # + # By default (AddTileConfig) mod_tile assumes you are serving png files, however, + # mod_tile can also serve arbitrary other tile types such as javascript vector tiles, + # assuming the backend render daemon can handle the file type. + # To this purpose AddTileMimeConfig takes a 3rd agument, the file extension and it + # will guess the correct mimetype from it. If the mime type is not set correctly automatically, + # you need to use the configuration file route, where you can specify the mimetype and file extension + # independently. + # + #AddTileConfig /folder/ TileSetName + #AddTileMimeConfig /folder2/ TileSetName2 js + + # Alternatively (or in addition) you can load all the tile sets defined in the configuration file into this virtual host + LoadTileConfigFile /etc/renderd.conf + + # Specify if mod_tile should keep tile delivery stats, which can be accessed from the URL /mod_tile + # The default is On. As keeping stats needs to take a lock, this might have some performance impact, + # but for nearly all intents and purposes this should be negligable and so it is safe to keep this turned on. + ModTileEnableStats On + + # Turns on bulk mode. In bulk mode, mod_tile does not request any dirty tiles to be rerendered. Missing tiles + # are always requested in the lowest priority. The default is Off. + ModTileBulkMode Off + + # Timeout before giving up for a tile to be rendered + ModTileRequestTimeout 3 + + # Timeout before giving up for a tile to be rendered that is otherwise missing + ModTileMissingRequestTimeout 10 + + # If tile is out of date, don't re-render it if past this load threshold (users gets old tile) + ModTileMaxLoadOld 2 + + # If tile is missing, don't render it if past this load threshold (user gets 404 error) + ModTileMaxLoadMissing 5 + + # Socket where we connect to the rendering daemon + ModTileRenderdSocketName /var/run/renderd/renderd.sock + + # Options controlling the cache proxy expiry headers. All values are in seconds. + # + # Caching is both important to reduce the load and bandwidth of the server, as + # well as reduce the load time for the user. The site loads fastest if tiles can be + # taken from the users browser cache and no round trip through the internet is needed. + # With minutely or hourly updates, however there is a trade-off between cacheability + # and freshness. As one can't predict the future, these are only heuristics, that + # need tuning. + # If there is a known update schedule such as only using weekly planet dumps to update the db, + # this can also be taken into account through the constant PLANET_INTERVAL in render_config.h + # but requires a recompile of mod_tile + + # The values in this sample configuration are not the same as the defaults + # that apply if the config settings are left out. The defaults are more conservative + # and disable most of the heuristics. + + # Caching is always a trade-off between being up to date and reducing server load or + # client side latency and bandwidth requirements. Under some conditions, like poor + # network conditions it might be more important to have good caching rather than the latest tiles. + # Therefor the following config options allow to set a special hostheader for which the caching + # behaviour is different to the normal heuristics + # + # The CacheExtended parameters overwrite all other caching parameters (including CacheDurationMax) + # for tiles being requested via the hostname CacheExtendedHostname + # + #ModTileCacheExtendedHostname cache.tile.openstreetmap.org + #ModTileCacheExtendedDuration 2592000 + + # Upper bound on the length a tile will be set cacheable, which takes + # precedence over other settings of cacheing + ModTileCacheDurationMax 604800 + + # Sets the time tiles can be cached for that are known to by outdated and have been + # sent to renderd to be rerendered. This should be set to a value corresponding + # roughly to how long it will take renderd to get through its queue. There is an additional + # fuzz factor on top of this to not have all tiles expire at the same time + ModTileCacheDurationDirty 900 + + # Specify the minimum time mod_tile will set the cache expiry to for fresh tiles. There + # is an additional fuzz factor of between 0 and 3 hours on top of this. + ModTileCacheDurationMinimum 10800 + + # Lower zoom levels are less likely to change noticeable, so these could be cached for longer + # without users noticing much. + # The heuristic offers three levels of zoom, Low, Medium and High, for which different minimum + # cacheing times can be specified. + + #Specify the zoom level below which Medium starts and the time in seconds for which they can be cached + ModTileCacheDurationMediumZoom 13 86400 + + #Specify the zoom level below which Low starts and the time in seconds for which they can be cached + ModTileCacheDurationLowZoom 9 518400 + + # A further heuristic to determine cacheing times is when was the last time a tile has changed. + # If it hasn't changed for a while, it is less likely to change in the immediate future, so the + # tiles can be cached for longer. + # For example, if the factor is 0.20 and the tile hasn't changed in the last 5 days, it can be cached + # for up to one day without having to re-validate. + ModTileCacheLastModifiedFactor 0.20 + + # Tile Throttling + # Tile scrapers can often download large numbers of tiles and overly strain tileserver resources + # mod_tile therefore offers the ability to automatically throttle requests from ip addresses that have + # requested a lot of tiles. + # The mechanism uses a token bucket approach to shape traffic. I.e. there is an initial pool of n tiles + # per ip that can be requested arbitrarily fast. After that this pool gets filled up at a constant rate + # The algorithm has two metrics. One based on overall tiles served to an ip address and a second one based on + # the number of requests to renderd / tirex to render a new tile. + + # Overall enable or disable tile throttling + ModTileEnableTileThrottling Off + + # Specify if you want to use the connecting IP for throtteling, or use the X-Forwarded-For header to determin the + # 1 - use the client IP address, i.e. the first entry in the X-Forwarded-For list. This works through a cascade of proxies. + # However, as the X-Forwarded-For is written by the client this is open to manipulation and can be used to circumvent the throttling + # 2 - use the last specified IP in the X-Forwarded-For list. If you know all requests come through a reverse proxy + # that adds an X-Forwarded-For header, you can trust this IP to be the IP the reverse proxy saw for the request + ModTileEnableTileThrottlingXForward 0 + + # Parameters (poolsize in tiles and topup rate in tiles per second) for throttling tile serving. + ModTileThrottlingTiles 10000 1 + # Parameters (poolsize in tiles and topup rate in tiles per second) for throttling render requests. + ModTileThrottlingRenders 128 0.2 + + # Enable the .../Z/X/Y.ext/status URL, which shows details of that tile. + # Off = a 404 is returned for that url instead. + # Default: On + #ModTileEnableStatusURL Off + + # Enable the .../Z/X/Y.ext/dirty URL, which marks that tile as dirty. + # Off = a 404 is returned for that url instead. + # Default: On + #ModTileEnableDirtyURL Off + + diff --git a/etc/apache2/tile.load.in b/etc/apache2/tile.load.in new file mode 100644 index 00000000..4e7a3ee8 --- /dev/null +++ b/etc/apache2/tile.load.in @@ -0,0 +1 @@ +LoadModule tile_module @CMAKE_INSTALL_MODULESDIR@/mod_tile.so diff --git a/etc/renderd/renderd.conf b/etc/renderd/renderd.conf new file mode 100644 index 00000000..412f0f40 --- /dev/null +++ b/etc/renderd/renderd.conf @@ -0,0 +1,15 @@ +; BASIC AND SIMPLE CONFIGURATION: + +[renderd] +pid_file=/run/renderd/renderd.pid +stats_file=/run/renderd/renderd.stats +socketname=/run/renderd/renderd.sock +num_threads=4 +tile_dir=/var/cache/renderd/tiles + +[mapnik] +plugins_dir=/usr/lib/mapnik/3.1/input +font_dir=/usr/share/fonts/truetype +font_dir_recurse=true + +; ADD YOUR LAYERS: diff --git a/renderd.conf b/etc/renderd/renderd.conf.examples similarity index 53% rename from renderd.conf rename to etc/renderd/renderd.conf.examples index b8c5fa87..9d74b8eb 100644 --- a/renderd.conf +++ b/etc/renderd/renderd.conf.examples @@ -1,39 +1,52 @@ +; EXAMPLES FOR BASIC CONFIGURATION OPTIONS + [renderd] -;socketname=/var/run/renderd/renderd.sock +pid_file=/run/renderd/renderd.pid +stats_file=/run/renderd/renderd.stats +socketname=/run/renderd/renderd.sock num_threads=4 -tile_dir=/var/lib/mod_tile -stats_file=/var/run/renderd/renderd.stats +tile_dir=/var/cache/renderd/tiles -;[renderd01] +;[renderd] ;iphostname=::1 ;ipport=7654 ;num_threads=4 ;tile_dir=rados://tiles/etc/ceph/ceph.conf -;stats_file=/var/run/renderd/renderd.stats +;pid_file=/run/renderd/renderd_rados.pid +;stats_file=/run/renderd/renderd.stats -;[renderd02] +;[renderd] ;iphostname=::1 ;ipport=7654 ;num_threads=8 ;tile_dir=memcached:// -;stats_file=/var/run/renderd/renderd.stats +;pid_file=/run/renderd/renderd_memcached.pid +;stats_file=/run/renderd/renderd.stats + +; EXAMPLE FOR MAPNIK CONFIGURATION OPTION [mapnik] -plugins_dir=/usr/lib/mapnik/input +plugins_dir=/usr/lib/mapnik/3.0/input font_dir=/usr/share/fonts/truetype -font_dir_recurse=1 - -[default] -URI=/osm_tiles/ -TILEDIR=/var/lib/mod_tile -XML=/home/jburgess/osm/svn.openstreetmap.org/applications/rendering/mapnik/osm-local.xml -HOST=tile.openstreetmap.org -TILESIZE=256 +font_dir_recurse=true + +; EXAMPLES FOR LAYER CONFIGURATION OPTIONS + +[example-map] +URI=/tiles/renderd-example +XML=/var/www/example-map/mapnik.xml + +;[style1] +;URI=/osm_tiles/ +;TILEDIR=/var/cache/renderd/tiles +;XML=/usr/share/renderd/openstreetmap/osm-local.xml +;HOST=tile.openstreetmap.org +;TILESIZE=256 ;HTCPHOST=proxy.openstreetmap.org ;** config options used by mod_tile, but not renderd ** ;MINZOOM=0 ;MAXZOOM=18 -;TYPE=png image/png +;TYPE=png image/png png256 ; Values are: (for more information about output format see https://github.com/mapnik/mapnik/wiki/Image-IO) ;DESCRIPTION=This is a description of the tile layer used in the tile json request ;ATTRIBUTION=©OpenStreetMap and contributors, ODbL ;SERVER_ALIAS=http://localhost/ @@ -46,15 +59,14 @@ TILESIZE=256 ;URI=/osm_tiles2/ ;TILEDIR=rados://tiles/etc/ceph/ceph.conf ;TILESIZE=512 -;XML=/home/jburgess/osm/svn.openstreetmap.org/applications/rendering/mapnik/osm-local2.xml +;XML=/usr/share/renderd/openstreetmap/osm-local2.xml ;HOST=tile.openstreetmap.org ;HTCPHOST=proxy.openstreetmap.org ;** config options used by mod_tile, but not renderd ** ;MINZOOM=0 ;MAXZOOM=22 -;TYPE=png image/png +;TYPE=png image/png png256 ; Values are: (for more information about output format see https://github.com/mapnik/mapnik/wiki/Image-IO) ;DESCRIPTION=This is a description of the tile layer used in the tile json request ;ATTRIBUTION=©OpenStreetMap and contributors, ODbL ;SERVER_ALIAS=http://localhost/ ;CORS=* - diff --git a/etc/renderd/renderd.conf.in b/etc/renderd/renderd.conf.in new file mode 100644 index 00000000..36c82b5a --- /dev/null +++ b/etc/renderd/renderd.conf.in @@ -0,0 +1,10 @@ +[renderd] +pid_file=@RENDERD_PIDFILE@ +socketname=@RENDERD_SOCKET@ +stats_file=@RENDERD_RUN_DIR@/renderd.stats +tile_dir=@RENDERD_TILE_DIR@ + +[mapnik] +font_dir=@MAPNIK_FONTS_DIR@ +font_dir_recurse=@MAPNIK_FONTS_DIR_RECURSE@ +plugins_dir=@MAPNIK_PLUGINS_DIR@ diff --git a/extra/Makefile b/extra/Makefile deleted file mode 100644 index a20aea88..00000000 --- a/extra/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -meta2tile: meta2tile.c - gcc -O3 -std=gnu99 -I../includes -I/usr/include meta2tile.c -o meta2tile -lm diff --git a/extra/README b/extra/README deleted file mode 100644 index 78aac211..00000000 --- a/extra/README +++ /dev/null @@ -1,5 +0,0 @@ -meta2tile.c is a small utility to convert meta tiles into normal tiles. -It is similar to convert_meta.c, but convert_meta.c creates individual -tiles in a "hashed" directory structure whereas meta2tile.c creates them -in a simple z/x/y directory structure. - diff --git a/extra/meta2tile.c b/extra/meta2tile.c deleted file mode 100644 index 8562f029..00000000 --- a/extra/meta2tile.c +++ /dev/null @@ -1,428 +0,0 @@ -// meta2tile.c -// written by Frederik Ramm -// License: GPL because this is based on other work in mod_tile - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "store_file.h" -#include "metatile.h" - -#define MIN(x,y) ((x)<(y)?(x):(y)) -#define META_MAGIC "META" - -static int verbose = 0; -static int num_render = 0; -static struct timeval start, end; - -const char *source; -const char *target; - -#define MODE_STAT 1 -#define MODE_GLOB 2 -#define MAXZOOM 20 - -int mode = MODE_GLOB; - -int zoom[MAXZOOM+1]; -float bbox[4] = {-180.0, -90.0, 180.0, 90.0}; - -int path_to_xyz(const char *path, int *px, int *py, int *pz) -{ - int i, n, hash[5], x, y, z; - char copy[PATH_MAX]; - strcpy(copy, path); - char *slash = rindex(copy, '/'); - int c=5; - while (slash && c) - { - *slash = 0; - c--; - hash[c]= atoi(slash+1); - slash = rindex(copy, '/'); - } - if (c != 0) - { - fprintf(stderr, "Failed to parse tile path: %s\n", path); - return 1; - } - *slash = 0; - *pz = atoi(slash+1); - - x = y = 0; - for (i=0; i<5; i++) - { - if (hash[i] < 0 || hash[i] > 255) - { - fprintf(stderr, "Failed to parse tile path (invalid %d): %s\n", hash[i], path); - return 2; - } - x <<= 4; - y <<= 4; - x |= (hash[i] & 0xf0) >> 4; - y |= (hash[i] & 0x0f); - } - z = *pz; - *px = x; - *py = y; - return 0; -} - -int long2tilex(double lon, int z) -{ - return (int)(floor((lon + 180.0) / 360.0 * pow(2.0, z))); -} - -int lat2tiley(double lat, int z) -{ - return (int)(floor((1.0 - log( tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * pow(2.0, z))); -} - -double tilex2long(int x, int z) -{ - return x / pow(2.0, z) * 360.0 - 180; -} - -double tiley2lat(int y, int z) -{ - double n = M_PI - 2.0 * M_PI * y / pow(2.0, z); - return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))); -} - -int expand_meta(const char *name) -{ - int fd; - char header[4096]; - int x, y, z; - size_t pos; - void *buf; - - if (path_to_xyz(name, &x, &y, &z)) return -1; - - int limit = (1 << z); - limit = MIN(limit, METATILE); - - float fromlat = tiley2lat(y+8, z); - float tolat = tiley2lat(y, z); - float fromlon = tilex2long(x, z); - float tolon = tilex2long(x+8, z); - - if (tolon < bbox[0] || fromlon > bbox[2] || tolat < bbox[1] || fromlat > bbox[3]) - { - if (verbose) printf("z=%d x=%d y=%d is out of bbox\n", z, x, y); - return -8; - } - - fd = open(name, O_RDONLY); - if (fd < 0) - { - fprintf(stderr, "Could not open metatile %s. Reason: %s\n", name, strerror(errno)); - return -1; - } - - struct stat st; - fstat(fd, &st); - - buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (buf == MAP_FAILED) - { - fprintf(stderr, "Cannot mmap file %s for %ld bytes: %s\n", name, st.st_size, strerror(errno)); - close(fd); - return -3; - } - struct meta_layout *m = (struct meta_layout *)buf; - - if (memcmp(m->magic, META_MAGIC, strlen(META_MAGIC))) - { - fprintf(stderr, "Meta file %s header magic mismatch\n", name); - close(fd); - return -4; - } - - if (m->count != (METATILE * METATILE)) - { - fprintf(stderr, "Meta file %s header bad count %d != %d\n", name, m->count, METATILE * METATILE); - close(fd); - return -5; - } - - char path[PATH_MAX]; - sprintf(path, "%s/%d", target, z); - if (mkdir(path, 0755) && (errno != EEXIST)) - { - fprintf(stderr, "cannot create directory %s: %s\n", path, strerror(errno)); - close(fd); - return -1; - } - - for (int meta = 0; meta < METATILE*METATILE; meta++) - { - int tx = x + (meta / METATILE); - int ty = y + (meta % METATILE); - int output; - - if (ty==y) - { - sprintf(path, "%s/%d/%d", target, z, tx); - if (mkdir(path, 0755) && (errno != EEXIST)) - { - fprintf(stderr, "cannot create directory %s: %s\n", path, strerror(errno)); - close(fd); - return -1; - } - } - - sprintf(path, "%s/%d/%d/%d.png", target, z, tx, ty); - output = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0666); - if (output == -1) - { - fprintf(stderr, "cannot open %s for writing: %s\n", path, strerror(errno)); - close(fd); - return -1; - } - - pos = 0; - while (pos < m->index[meta].size) - { - size_t len = m->index[meta].size - pos; - int written = write(output, buf + pos + m->index[meta].offset, len); - if (written < 0) - { - fprintf(stderr, "Failed to write data to file %s. Reason: %s\n", path, strerror(errno)); - close(fd); - return -7; - } - else if (written > 0) - { - pos += written; - } - else - { - break; - } - } - close(output); - if (verbose) printf("Produced tile: %s\n", path); - } - - munmap(buf, st.st_size); - close(fd); - num_render++; - return pos; -} - -void display_rate(struct timeval start, struct timeval end, int num) -{ - int d_s, d_us; - float sec; - - d_s = end.tv_sec - start.tv_sec; - d_us = end.tv_usec - start.tv_usec; - - sec = d_s + d_us / 1000000.0; - - printf("Converted %d tiles in %.2f seconds (%.2f tiles/s)\n", num, sec, num / sec); - fflush(NULL); -} - -static void descend(const char *search, int zoomdone) -{ - DIR *tiles = opendir(search); - struct dirent *entry; - char path[PATH_MAX]; - int this_is_zoom = -1; - - if (!tiles) - { - //fprintf(stderr, "Unable to open directory: %s\n", search); - return; - } - - while ((entry = readdir(tiles))) - { - struct stat b; - char *p; - - //check_load(); - - if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) - continue; - - if (this_is_zoom == -1) - { - if (!zoomdone && isdigit(*(entry->d_name)) && atoi(entry->d_name) >= 0 && atoi(entry->d_name) <= MAXZOOM) - { - this_is_zoom = 1; - } - else - { - this_is_zoom = 0; - } - } - - if (this_is_zoom) - { - int z = atoi(entry->d_name); - if (z<0 || z>MAXZOOM || !zoom[z]) continue; - } - - snprintf(path, sizeof(path), "%s/%s", search, entry->d_name); - if (stat(path, &b)) - continue; - if (S_ISDIR(b.st_mode)) { - descend(path, zoomdone || this_is_zoom); - continue; - } - p = strrchr(path, '.'); - if (p && !strcmp(p, ".meta")) expand_meta(path); - } - closedir(tiles); -} - - -void usage() -{ - fprintf(stderr, "Usage: m2t [-m mode] [-b bbox] [-z zoom] sourcedir targetdir\n"); - fprintf(stderr, "Convert .meta files found in source dir to .png in target dir,\n"); - fprintf(stderr, "using the standard \"hash\" type directory (5-level) for meta\n"); - fprintf(stderr, "tiles and the z/x/y.png structure (3-level) for output.\n"); -} - -int handle_bbox(char *arg) -{ - char *token = strtok(arg, ","); - int bbi = 0; - while(token && bbi<4) - { - bbox[bbi++] = atof(token); - token = strtok(NULL, ","); - } - return (bbi==4 && token==NULL); -} - -int handle_zoom(char *arg) -{ - char *token = strtok(arg, ","); - while(token) - { - int fromz = atoi(token); - int toz = atoi(token); - char *minus = strchr(token, '-'); - if (minus) - { - toz = atoi(minus+1); - } - if (fromz<0 || toz<0 || fromz>MAXZOOM || toz>MAXZOOM || toz= argc-1) - { - usage(); - return -1; - } - - source=argv[optind++]; - target=argv[optind++]; - - fprintf(stderr, "Converting tiles from directory %s to directory %s\n", source, target); - - gettimeofday(&start, NULL); - - descend(source, 0); - - gettimeofday(&end, NULL); - printf("\nTotal for all tiles converted\n"); - printf("Meta tiles converted: "); - display_rate(start, end, num_render); - printf("Total tiles converted: "); - display_rate(start, end, num_render * METATILE * METATILE); - - return 0; -} diff --git a/includes/cache_expire.h b/includes/cache_expire.h index 8f3457b5..6efe1751 100644 --- a/includes/cache_expire.h +++ b/includes/cache_expire.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2007 - 2023 by mod_tile contributors (see AUTHORS file) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see http://www.gnu.org/licenses/. + */ + #ifndef CACHEEXPIRE_H #define CACHEEXPIRE_H diff --git a/includes/catch.hpp b/includes/catch.hpp deleted file mode 100644 index 306b9208..00000000 --- a/includes/catch.hpp +++ /dev/null @@ -1,6446 +0,0 @@ -/* - * Generated: 2013-02-19 08:44:57.311773 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - -#define TWOBLUECUBES_CATCH_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wglobal-constructors" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// #included from: internal/catch_notimplemented_exception.h -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED - -// #included from: catch_common.h -#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED - -#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line -#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) -#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) - -#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr -#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) - -#ifdef __GNUC__ -#define CATCH_ATTRIBUTE_NORETURN __attribute__ ((noreturn)) -#else -#define CATCH_ATTRIBUTE_NORETURN -#endif - -#include -#include -#include - -namespace Catch { - - class NonCopyable { - NonCopyable( const NonCopyable& ); - void operator = ( const NonCopyable& ); - protected: - NonCopyable() {} - virtual ~NonCopyable(); - }; - - class SafeBool { - public: - typedef void (SafeBool::*type)() const; - - static type makeSafe( bool value ) { - return value ? &SafeBool::trueValue : 0; - } - private: - void trueValue() const {} - }; - - template - inline void deleteAll( ContainerT& container ) { - typename ContainerT::const_iterator it = container.begin(); - typename ContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - { - delete *it; - } - } - template - inline void deleteAllValues( AssociativeContainerT& container ) { - typename AssociativeContainerT::const_iterator it = container.begin(); - typename AssociativeContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - { - delete it->second; - } - } - - template - inline void forEach( ContainerT& container, Function function ) { - std::for_each( container.begin(), container.end(), function ); - } - - template - inline void forEach( const ContainerT& container, Function function ) { - std::for_each( container.begin(), container.end(), function ); - } - - inline bool startsWith( const std::string& s, const std::string& prefix ) { - return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; - } - inline bool endsWith( const std::string& s, const std::string& suffix ) { - return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; - } - inline bool contains( const std::string& s, const std::string& infix ) { - return s.find( infix ) != std::string::npos; - } - - struct pluralise { - pluralise( std::size_t count, const std::string& label ) - : m_count( count ), - m_label( label ) - {} - - friend std::ostream& operator << ( std::ostream& os, const pluralise& pluraliser ) { - os << pluraliser.m_count << " " << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << "s"; - return os; - } - - std::size_t m_count; - std::string m_label; - }; - - struct SourceLineInfo { - - SourceLineInfo() : line( 0 ){} - SourceLineInfo( const std::string& _file, std::size_t _line ) - : file( _file ), - line( _line ) - {} - SourceLineInfo( const SourceLineInfo& other ) - : file( other.file ), - line( other.line ) - {} - bool empty() const { - return file.empty(); - } - - std::string file; - std::size_t line; - }; - - inline std::ostream& operator << ( std::ostream& os, const SourceLineInfo& info ) { -#ifndef __GNUG__ - os << info.file << "(" << info.line << "): "; -#else - os << info.file << ":" << info.line << ": "; -#endif - return os; - } - - CATCH_ATTRIBUTE_NORETURN - inline void throwLogicError( const std::string& message, const SourceLineInfo& locationInfo ) { - std::ostringstream oss; - oss << "Internal Catch error: '" << message << "' at: " << locationInfo; - throw std::logic_error( oss.str() ); - } -} - -#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) -#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); - -#include - -namespace Catch { - - class NotImplementedException : public std::exception - { - public: - NotImplementedException( const SourceLineInfo& lineInfo ); - - virtual ~NotImplementedException() throw() {} - - virtual const char* what() const throw(); - - private: - std::string m_what; - SourceLineInfo m_lineInfo; - }; - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) - -// #included from: internal/catch_context.h -#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED - -// #included from: catch_interfaces_generators.h -#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED - -#include - -namespace Catch { - - struct IGeneratorInfo { - virtual ~IGeneratorInfo(); - virtual bool moveNext() = 0; - virtual std::size_t getCurrentIndex() const = 0; - }; - - struct IGeneratorsForTest { - virtual ~IGeneratorsForTest(); - - virtual IGeneratorInfo& getGeneratorInfo( const std::string& fileInfo, std::size_t size ) = 0; - virtual bool moveNext() = 0; - }; - - IGeneratorsForTest* createGeneratorsForTest(); - -} // end namespace Catch - -#include -#include -#include - -namespace Catch { - - class TestCaseInfo; - class Stream; - struct IResultCapture; - struct IRunner; - struct IGeneratorsForTest; - struct IConfig; - - struct IContext - { - virtual ~IContext(); - - virtual IResultCapture& getResultCapture() = 0; - virtual IRunner& getRunner() = 0; - virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) = 0; - virtual bool advanceGeneratorsForCurrentTest() = 0; - virtual const IConfig* getConfig() const = 0; - }; - - struct IMutableContext : IContext - { - virtual ~IMutableContext(); - virtual void setResultCapture( IResultCapture* resultCapture ) = 0; - virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( const IConfig* config ) = 0; - }; - - IContext& getCurrentContext(); - IMutableContext& getCurrentMutableContext(); - void cleanUpContext(); - Stream createStream( const std::string& streamName ); - -} - -// #included from: internal/catch_test_registry.hpp -#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED - -// #included from: catch_interfaces_testcase.h -#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED - -// #included from: catch_ptr.hpp -#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED - -namespace Catch { - - // An intrusive reference counting smart pointer. - // T must implement addRef() and release() methods - // typically implementing the IShared interface - template - class Ptr { - public: - Ptr() : m_p( NULL ){} - Ptr( T* p ) : m_p( p ){ - if( m_p ) - m_p->addRef(); - } - Ptr( const Ptr& other ) : m_p( other.m_p ){ - if( m_p ) - m_p->addRef(); - } - ~Ptr(){ - if( m_p ) - m_p->release(); - } - Ptr& operator = ( T* p ){ - Ptr temp( p ); - swap( temp ); - return *this; - } - Ptr& operator = ( const Ptr& other ){ - Ptr temp( other ); - swap( temp ); - return *this; - } - void swap( Ptr& other ){ - std::swap( m_p, other.m_p ); - } - - T* get(){ - return m_p; - } - const T* get() const{ - return m_p; - } - - T& operator*() const { - return *m_p; - } - - T* operator->() const { - return m_p; - } - - bool operator !() const { - return m_p == NULL; - } - - private: - T* m_p; - }; - - struct IShared : NonCopyable { - virtual ~IShared(); - virtual void addRef() = 0; - virtual void release() = 0; - }; - - template - struct SharedImpl : T { - - SharedImpl() : m_rc( 0 ){} - - virtual void addRef(){ - ++m_rc; - } - virtual void release(){ - if( --m_rc == 0 ) - delete this; - } - - int m_rc; - }; - -} // end namespace Catch - -#include - -namespace Catch { - - class TestCaseFilters; - - struct ITestCase : IShared { - virtual void invoke () const = 0; - protected: - virtual ~ITestCase(); - }; - - class TestCaseInfo; - - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual const std::vector& getAllTests() const = 0; - virtual std::vector getMatchingTestCases( const std::string& rawTestSpec ) const = 0; - }; -} - -namespace Catch { - -template -class MethodTestCase : public SharedImpl { - -public: - MethodTestCase( void (C::*method)() ) : m_method( method ) {} - - virtual void invoke() const { - C obj; - (obj.*m_method)(); - } - -private: - virtual ~MethodTestCase() {} - - void (C::*m_method)(); -}; - -typedef void(*TestFunction)(); - -struct AutoReg { - - AutoReg( TestFunction function, - const char* name, - const char* description, - const SourceLineInfo& lineInfo ); - - template - AutoReg( void (C::*method)(), - const char* className, - const char* name, - const char* description, - const SourceLineInfo& lineInfo ) { - registerTestCase( new MethodTestCase( method ), className, name, description, lineInfo ); - } - - void registerTestCase( ITestCase* testCase, - const char* className, - const char* name, - const char* description, - const SourceLineInfo& lineInfo ); - - ~AutoReg(); - -private: - AutoReg( const AutoReg& ); - void operator= ( const AutoReg& ); -}; - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ - static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\ - static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TESTCASE_NORETURN( Name, Desc ) \ - static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() CATCH_ATTRIBUTE_NORETURN; \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\ - static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Name, Desc, CATCH_INTERNAL_LINEINFO ); } - -/////////////////////////////////////////////////////////////////////////////// -#define TEST_CASE_METHOD( ClassName, TestName, Desc )\ - namespace{ \ - struct INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ ) : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test, #ClassName, TestName, Desc, CATCH_INTERNAL_LINEINFO ); \ - } \ - void INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test() - -// #included from: internal/catch_capture.hpp -#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED - -// #included from: catch_expression_decomposer.hpp -#define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED - -// #included from: catch_expression_lhs.hpp -#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED - -// #included from: catch_expressionresult_builder.h -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED - -// #included from: catch_tostring.hpp -#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED - -#include - -#ifdef __OBJC__ -// #included from: catch_objc_arc.hpp -#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED - -#import - -#ifdef __has_feature -#define CATCH_ARC_ENABLED __has_feature(objc_arc) -#else -#define CATCH_ARC_ENABLED 0 -#endif - -void arcSafeRelease( NSObject* obj ); -id performOptionalSelector( id obj, SEL sel ); - -#if !CATCH_ARC_ENABLED -inline void arcSafeRelease( NSObject* obj ) { - [obj release]; -} -inline id performOptionalSelector( id obj, SEL sel ) { - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; - return nil; -} -#define CATCH_UNSAFE_UNRETAINED -#define CATCH_ARC_STRONG -#else -inline void arcSafeRelease( NSObject* ){} -inline id performOptionalSelector( id obj, SEL sel ) { -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" -#endif - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - return nil; -} -#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained -#define CATCH_ARC_STRONG __strong -#endif - -#endif - -namespace Catch { -namespace Detail { - - struct NonStreamable { - template NonStreamable( const T& ){} - }; - - // If the type does not have its own << overload for ostream then - // this one will be used instead - inline std::ostream& operator << ( std::ostream& ss, NonStreamable ){ - return ss << "{?}"; - } - - template - inline std::string makeString( const T& value ) { - std::ostringstream oss; - oss << value; - return oss.str(); - } - - template - inline std::string makeString( T* p ) { - if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); - std::ostringstream oss; - oss << p; - return oss.str(); - } - - template - inline std::string makeString( const T* p ) { - if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); - std::ostringstream oss; - oss << p; - return oss.str(); - } - -} // end namespace Detail - -/// \brief converts any type to a string -/// -/// The default template forwards on to ostringstream - except when an -/// ostringstream overload does not exist - in which case it attempts to detect -/// that and writes {?}. -/// Overload (not specialise) this template for custom typs that you don't want -/// to provide an ostream overload for. -template -std::string toString( const T& value ) { - return Detail::makeString( value ); -} - -// Built in overloads - -inline std::string toString( const std::string& value ) { - return "\"" + value + "\""; -} - -inline std::string toString( const std::wstring& value ) { - std::ostringstream oss; - oss << "\""; - for(size_t i = 0; i < value.size(); ++i ) - oss << static_cast( value[i] <= 0xff ? value[i] : '?'); - oss << "\""; - return oss.str(); -} - -inline std::string toString( const char* const value ) { - return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); -} - -inline std::string toString( char* const value ) { - return Catch::toString( static_cast( value ) ); -} - -inline std::string toString( int value ) { - std::ostringstream oss; - oss << value; - return oss.str(); -} - -inline std::string toString( unsigned long value ) { - std::ostringstream oss; - if( value > 8192 ) - oss << "0x" << std::hex << value; - else - oss << value; - return oss.str(); -} - -inline std::string toString( unsigned int value ) { - return toString( static_cast( value ) ); -} - -inline std::string toString( const double value ) { - std::ostringstream oss; - oss << value; - return oss.str(); -} - -inline std::string toString( bool value ) { - return value ? "true" : "false"; -} - -inline std::string toString( char value ) { - return value < ' ' - ? toString( (unsigned int)value ) - : Detail::makeString( value ); -} - -inline std::string toString( signed char value ) { - return toString( static_cast( value ) ); -} - -#ifdef CATCH_CONFIG_CPP11_NULLPTR -inline std::string toString( std::nullptr_t ) { - return "nullptr"; -} -#endif - -#ifdef __OBJC__ - inline std::string toString( NSString const * const& nsstring ) { - return std::string( "@\"" ) + [nsstring UTF8String] + "\""; - } - inline std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { - return std::string( "@\"" ) + [nsstring UTF8String] + "\""; - } - inline std::string toString( NSObject* const& nsObject ) { - return toString( [nsObject description] ); - } -#endif - -} // end namespace Catch - -// #included from: catch_assertionresult.h -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED - -#include -// #included from: catch_result_type.h -#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED - -namespace Catch { - - // ResultWas::OfType enum - struct ResultWas { enum OfType { - Unknown = -1, - Ok = 0, - Info = 1, - Warning = 2, - - FailureBit = 0x10, - - ExpressionFailed = FailureBit | 1, - ExplicitFailure = FailureBit | 2, - - Exception = 0x100 | FailureBit, - - ThrewException = Exception | 1, - DidntThrowException = Exception | 2 - - }; }; - - inline bool isOk( ResultWas::OfType resultType ) { - return ( resultType & ResultWas::FailureBit ) == 0; - } - - // ResultAction::Value enum - struct ResultAction { enum Value { - None, - Failed = 1, // Failure - but no debug break if Debug bit not set - Debug = 2, // If this bit is set, invoke the debugger - Abort = 4 // Test run should abort - }; }; - - // ResultDisposition::Flags enum - struct ResultDisposition { enum Flags { - Normal = 0x00, - - ContinueOnFailure = 0x01, // Failures fail test, but execution continues - NegateResult = 0x02, // Prefix expressiom with ! - SuppressFail = 0x04 // Failures are reported but do not fail the test - }; }; - - inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { - return static_cast( static_cast( lhs ) | static_cast( rhs ) ); - } - - inline bool shouldContinueOnFailure( int flags ) { return flags & ResultDisposition::ContinueOnFailure; } - inline bool shouldNegate( int flags ) { return flags & ResultDisposition::NegateResult; } - inline bool shouldSuppressFailure( int flags ) { return flags & ResultDisposition::SuppressFail; } - -} // end namespace Catch - - -namespace Catch { - - struct AssertionInfo - { - AssertionInfo() {} - AssertionInfo( const std::string& _macroName, - const SourceLineInfo& _lineInfo, - const std::string& _capturedExpression, - ResultDisposition::Flags _resultDisposition ); - - std::string macroName; - SourceLineInfo lineInfo; - std::string capturedExpression; - ResultDisposition::Flags resultDisposition; - }; - - struct AssertionResultData - { - AssertionResultData() : resultType( ResultWas::Unknown ) {} - - std::string reconstructedExpression; - std::string message; - ResultWas::OfType resultType; - }; - - class AssertionResult { - public: - AssertionResult(); - AssertionResult( const AssertionInfo& info, const AssertionResultData& data ); - ~AssertionResult(); - - bool isOk() const; - bool succeeded() const; - ResultWas::OfType getResultType() const; - bool hasExpression() const; - bool hasMessage() const; - std::string getExpression() const; - bool hasExpandedExpression() const; - std::string getExpandedExpression() const; - std::string getMessage() const; - SourceLineInfo getSourceInfo() const; - std::string getTestMacroName() const; - - protected: - AssertionInfo m_info; - AssertionResultData m_resultData; - }; - -} // end namespace Catch - -// #included from: catch_evaluate.hpp -#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED - -namespace Catch { -namespace Internal { - - enum Operator { - IsEqualTo, - IsNotEqualTo, - IsLessThan, - IsGreaterThan, - IsLessThanOrEqualTo, - IsGreaterThanOrEqualTo - }; - - template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; - template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; - template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; - template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; - template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; - template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; - template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; - - // So the compare overloads can be operator agnostic we convey the operator as a template - // enum, which is used to specialise an Evaluator for doing the comparison. - template - class Evaluator{}; - - template - struct Evaluator { - static bool evaluate( const T1& lhs, const T2& rhs) { - return const_cast( lhs ) == const_cast( rhs ); - } - }; - template - struct Evaluator { - static bool evaluate( const T1& lhs, const T2& rhs ) { - return const_cast( lhs ) != const_cast( rhs ); - } - }; - template - struct Evaluator { - static bool evaluate( const T1& lhs, const T2& rhs ) { - return const_cast( lhs ) < const_cast( rhs ); - } - }; - template - struct Evaluator { - static bool evaluate( const T1& lhs, const T2& rhs ) { - return const_cast( lhs ) > const_cast( rhs ); - } - }; - template - struct Evaluator { - static bool evaluate( const T1& lhs, const T2& rhs ) { - return const_cast( lhs ) >= const_cast( rhs ); - } - }; - template - struct Evaluator { - static bool evaluate( const T1& lhs, const T2& rhs ) { - return const_cast( lhs ) <= const_cast( rhs ); - } - }; - - template - bool applyEvaluator( const T1& lhs, const T2& rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - - // This level of indirection allows us to specialise for integer types - // to avoid signed/ unsigned warnings - - // "base" overload - template - bool compare( const T1& lhs, const T2& rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - - // unsigned X to int - template bool compare( unsigned int lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned long lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned char lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - - // unsigned X to long - template bool compare( unsigned int lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned long lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned char lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - - // int to unsigned X - template bool compare( int lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( int lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( int lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // long to unsigned X - template bool compare( long lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // pointer to long (when comparing against NULL) - template bool compare( long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } - - // pointer to int (when comparing against NULL) - template bool compare( int lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, int rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } - -} // end of namespace Internal -} // end of namespace Catch - -namespace Catch { - -// Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as -// the result of evaluating it. This is used to build an AssertionResult object -class ExpressionResultBuilder { -public: - - ExpressionResultBuilder( ResultWas::OfType resultType = ResultWas::Unknown ); - ExpressionResultBuilder( const ExpressionResultBuilder& other ); - ExpressionResultBuilder& operator=(const ExpressionResultBuilder& other ); - - ExpressionResultBuilder& setResultType( ResultWas::OfType result ); - ExpressionResultBuilder& setResultType( bool result ); - ExpressionResultBuilder& setLhs( const std::string& lhs ); - ExpressionResultBuilder& setRhs( const std::string& rhs ); - ExpressionResultBuilder& setOp( const std::string& op ); - - ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ); - - template - ExpressionResultBuilder& operator << ( const T& value ) { - m_stream << value; - return *this; - } - - std::string reconstructExpression( const AssertionInfo& info ) const; - - AssertionResult buildResult( const AssertionInfo& info ) const; - -private: - AssertionResultData m_data; - struct ExprComponents { - ExprComponents() : shouldNegate( false ) {} - bool shouldNegate; - std::string lhs, rhs, op; - } m_exprComponents; - std::ostringstream m_stream; -}; - -} // end namespace Catch - -namespace Catch { - -struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; - -// Wraps the LHS of an expression and captures the operator and RHS (if any) - wrapping them all -// in an ExpressionResultBuilder object -template -class ExpressionLhs { - void operator = ( const ExpressionLhs& ); - -public: - ExpressionLhs( T lhs ) : m_lhs( lhs ) {} - - template - ExpressionResultBuilder& operator == ( const RhsT& rhs ) { - return captureExpression( rhs ); - } - - template - ExpressionResultBuilder& operator != ( const RhsT& rhs ) { - return captureExpression( rhs ); - } - - template - ExpressionResultBuilder& operator < ( const RhsT& rhs ) { - return captureExpression( rhs ); - } - - template - ExpressionResultBuilder& operator > ( const RhsT& rhs ) { - return captureExpression( rhs ); - } - - template - ExpressionResultBuilder& operator <= ( const RhsT& rhs ) { - return captureExpression( rhs ); - } - - template - ExpressionResultBuilder& operator >= ( const RhsT& rhs ) { - return captureExpression( rhs ); - } - - ExpressionResultBuilder& operator == ( bool rhs ) { - return captureExpression( rhs ); - } - - ExpressionResultBuilder& operator != ( bool rhs ) { - return captureExpression( rhs ); - } - - ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ) { - bool value = m_lhs ? true : false; - return m_result - .setLhs( Catch::toString( value ) ) - .setResultType( value ) - .endExpression( resultDisposition ); - } - - // Only simple binary expressions are allowed on the LHS. - // If more complex compositions are required then place the sub expression in parentheses - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( const RhsT& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( const RhsT& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( const RhsT& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( const RhsT& ); - -private: - template - ExpressionResultBuilder& captureExpression( const RhsT& rhs ) { - return m_result - .setResultType( Internal::compare( m_lhs, rhs ) ) - .setLhs( Catch::toString( m_lhs ) ) - .setRhs( Catch::toString( rhs ) ) - .setOp( Internal::OperatorTraits::getName() ); - } - -private: - ExpressionResultBuilder m_result; - T m_lhs; -}; - -} // end namespace Catch - -namespace Catch { - -// Captures the LHS of the expression and wraps it in an Expression Lhs object -class ExpressionDecomposer { -public: - - template - ExpressionLhs operator->* ( const T & operand ) { - return ExpressionLhs( operand ); - } - - ExpressionLhs operator->* ( bool value ) { - return ExpressionLhs( value ); - } -}; - -} // end namespace Catch - -// #included from: catch_interfaces_capture.h -#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED - -#include -// #included from: catch_totals.hpp -#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED - -#include - -namespace Catch { - - struct Counts { - Counts() : passed( 0 ), failed( 0 ) {} - - Counts operator - ( const Counts& other ) const { - Counts diff; - diff.passed = passed - other.passed; - diff.failed = failed - other.failed; - return diff; - } - Counts& operator += ( const Counts& other ) { - passed += other.passed; - failed += other.failed; - return *this; - } - - std::size_t total() const { - return passed + failed; - } - - std::size_t passed; - std::size_t failed; - }; - - struct Totals { - - Totals operator - ( const Totals& other ) const { - Totals diff; - diff.assertions = assertions - other.assertions; - diff.testCases = testCases - other.testCases; - return diff; - } - - Totals delta( const Totals& prevTotals ) const { - Totals diff = *this - prevTotals; - if( diff.assertions.failed > 0 ) - ++diff.testCases.failed; - else - ++diff.testCases.passed; - return diff; - } - - Totals& operator += ( const Totals& other ) { - assertions += other.assertions; - testCases += other.testCases; - return *this; - } - - Counts assertions; - Counts testCases; - }; -} - - -namespace Catch { - - class TestCaseInfo; - class ScopedInfo; - class ExpressionResultBuilder; - class AssertionResult; - struct AssertionInfo; - - struct IResultCapture { - - virtual ~IResultCapture(); - - virtual void testEnded( const AssertionResult& result ) = 0; - virtual bool sectionStarted( const std::string& name, - const std::string& description, - const SourceLineInfo& lineInfo, - Counts& assertions ) = 0; - virtual void sectionEnded( const std::string& name, const Counts& assertions ) = 0; - virtual void pushScopedInfo( ScopedInfo* scopedInfo ) = 0; - virtual void popScopedInfo( ScopedInfo* scopedInfo ) = 0; - virtual bool shouldDebugBreak() const = 0; - - virtual ResultAction::Value acceptExpression( const ExpressionResultBuilder& assertionResult, const AssertionInfo& assertionInfo ) = 0; - - virtual std::string getCurrentTestName() const = 0; - virtual const AssertionResult* getLastResult() const = 0; - }; -} - -// #included from: catch_debugger.hpp -#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED - -#include - -#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) -#define CATCH_PLATFORM_MAC -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) -#define CATCH_PLATFORM_IPHONE -#elif defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -#define CATCH_PLATFORM_WINDOWS -#endif - -#ifdef CATCH_PLATFORM_MAC - - #include - #include - #include - #include - #include - - namespace Catch{ - - // The following function is taken directly from the following technical note: - // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html - - // Returns true if the current process is being debugged (either - // running under the debugger or has a debugger attached post facto). - inline bool isDebuggerActive(){ - - int junk; - int mib[4]; - struct kinfo_proc info; - size_t size; - - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - - info.kp_proc.p_flag = 0; - - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - // Call sysctl. - - size = sizeof(info); - junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); - assert(junk == 0); - - // We're being debugged if the P_TRACED flag is set. - - return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); - } - } - - // The following code snippet taken from: - // http://cocoawithlove.com/2008/03/break-into-debugger.html - #ifdef DEBUG - #if defined(__ppc64__) || defined(__ppc__) - #define BreakIntoDebugger() \ - if( Catch::isDebuggerActive() ) { \ - __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ - : : : "memory","r0","r3","r4" ); \ - } - #else - #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} - #endif - #else - inline void BreakIntoDebugger(){} - #endif - -#elif defined(_MSC_VER) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); } - inline bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - extern "C" __declspec(dllimport) void __stdcall DebugBreak(); - #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); } - inline bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } -#else - inline void BreakIntoDebugger(){} - inline bool isDebuggerActive() { return false; } -#endif - -#ifdef CATCH_PLATFORM_WINDOWS -extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); -inline void writeToDebugConsole( const std::string& text ) { - ::OutputDebugStringA( text.c_str() ); -} -#else -inline void writeToDebugConsole( const std::string& text ) { - // !TBD: Need a version for Mac/ XCode and other IDEs - std::cout << text; -} -#endif // CATCH_PLATFORM_WINDOWS - -// #included from: catch_interfaces_registry_hub.h -#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED - -// #included from: catch_interfaces_reporter.h -#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED - -// #included from: catch_config.hpp -#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED - -// #included from: catch_test_spec.h -#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED - -// #included from: catch_test_case_info.h -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED - -#include -#include - -namespace Catch { - - struct ITestCase; - - class TestCaseInfo { - public: - TestCaseInfo(); - - TestCaseInfo( ITestCase* testCase, - const std::string& className, - const std::string& name, - const std::string& description, - const SourceLineInfo& lineInfo ); - - TestCaseInfo( const TestCaseInfo& other, const std::string& name ); - TestCaseInfo( const TestCaseInfo& other ); - - void invoke() const; - - const std::string& getClassName() const; - const std::string& getName() const; - const std::string& getDescription() const; - const SourceLineInfo& getLineInfo() const; - bool isHidden() const; - bool hasTag( const std::string& tag ) const; - bool matchesTags( const std::string& tagPattern ) const; - const std::set& getTags() const; - - void swap( TestCaseInfo& other ); - bool operator == ( const TestCaseInfo& other ) const; - bool operator < ( const TestCaseInfo& other ) const; - TestCaseInfo& operator = ( const TestCaseInfo& other ); - - private: - Ptr m_test; - std::string m_className; - std::string m_name; - std::string m_description; - std::set m_tags; - SourceLineInfo m_lineInfo; - bool m_isHidden; - }; -} - -// #included from: catch_tags.hpp -#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED - -#include -#include -#include -#include - -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - class TagParser { - public: - virtual ~TagParser(); - - void parse( const std::string& str ) { - std::size_t pos = 0; - while( pos < str.size() ) { - char c = str[pos]; - if( c == '[' ) { - std::size_t end = str.find_first_of( ']', pos ); - if( end != std::string::npos ) { - acceptTag( str.substr( pos+1, end-pos-1 ) ); - pos = end+1; - } - else { - acceptChar( c ); - pos++; - } - } - else { - acceptChar( c ); - pos++; - } - } - endParse(); - } - - protected: - virtual void acceptTag( const std::string& tag ) = 0; - virtual void acceptChar( char c ) = 0; - virtual void endParse() {} - - private: - }; - - class TagExtracter : public TagParser { - public: - - TagExtracter( std::set& tags ) - : m_tags( tags ) - {} - virtual ~TagExtracter(); - - void parse( std::string& description ) { - TagParser::parse( description ); - description = m_remainder; - } - - private: - virtual void acceptTag( const std::string& tag ) { - m_tags.insert( tag ); - } - virtual void acceptChar( char c ) { - m_remainder += c; - } - - TagExtracter& operator=(const TagExtracter&); - - std::set& m_tags; - std::string m_remainder; - }; - - class Tag { - public: - Tag() - : m_isNegated( false ) - {} - - Tag( const std::string& name, bool isNegated ) - : m_name( name ), - m_isNegated( isNegated ) - {} - - std::string getName() const { - return m_name; - } - bool isNegated() const { - return m_isNegated; - } - - bool operator ! () const { - return m_name.empty(); - } - - private: - std::string m_name; - bool m_isNegated; - }; - - class TagSet { - typedef std::map TagMap; - public: - void add( const Tag& tag ) { - m_tags.insert( std::make_pair( tag.getName(), tag ) ); - } - - bool empty() const { - return m_tags.empty(); - } - - bool matches( const std::set& tags ) const { - TagMap::const_iterator it = m_tags.begin(); - TagMap::const_iterator itEnd = m_tags.end(); - for(; it != itEnd; ++it ) { - bool found = tags.find( it->first ) != tags.end(); - if( found == it->second.isNegated() ) - return false; - } - return true; - } - - private: - TagMap m_tags; - }; - - class TagExpression { - public: - bool matches( const std::set& tags ) const { - std::vector::const_iterator it = m_tagSets.begin(); - std::vector::const_iterator itEnd = m_tagSets.end(); - for(; it != itEnd; ++it ) - if( it->matches( tags ) ) - return true; - return false; - } - - private: - friend class TagExpressionParser; - - std::vector m_tagSets; - }; - - class TagExpressionParser : public TagParser { - public: - TagExpressionParser( TagExpression& exp ) - : m_isNegated( false ), - m_exp( exp ) - {} - - ~TagExpressionParser(); - - private: - virtual void acceptTag( const std::string& tag ) { - m_currentTagSet.add( Tag( tag, m_isNegated ) ); - m_isNegated = false; - } - virtual void acceptChar( char c ) { - switch( c ) { - case '~': - m_isNegated = true; - break; - case ',': - m_exp.m_tagSets.push_back( m_currentTagSet ); - break; - } - } - virtual void endParse() { - if( !m_currentTagSet.empty() ) - m_exp.m_tagSets.push_back( m_currentTagSet ); - } - - TagExpressionParser& operator=(const TagExpressionParser&); - - bool m_isNegated; - TagSet m_currentTagSet; - TagExpression& m_exp; - }; - -} // end namespace Catch - -#include -#include - -namespace Catch { - - struct IfFilterMatches{ enum DoWhat { - AutoDetectBehaviour, - IncludeTests, - ExcludeTests - }; }; - - class TestCaseFilter { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - - public: - TestCaseFilter( const std::string& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour ) - : m_stringToMatch( testSpec ), - m_filterType( matchBehaviour ), - m_wildcardPosition( NoWildcard ) - { - if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) { - if( startsWith( m_stringToMatch, "exclude:" ) ) { - m_stringToMatch = m_stringToMatch.substr( 8 ); - m_filterType = IfFilterMatches::ExcludeTests; - } - else if( startsWith( m_stringToMatch, "~" ) ) { - m_stringToMatch = m_stringToMatch.substr( 1 ); - m_filterType = IfFilterMatches::ExcludeTests; - } - else { - m_filterType = IfFilterMatches::IncludeTests; - } - } - - if( m_stringToMatch[0] == '*' ) { - m_stringToMatch = m_stringToMatch.substr( 1 ); - m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart ); - } - if( m_stringToMatch[m_stringToMatch.size()-1] == '*' ) { - m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 ); - m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd ); - } - } - - IfFilterMatches::DoWhat getFilterType() const { - return m_filterType; - } - - bool shouldInclude( const TestCaseInfo& testCase ) const { - return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests); - } - private: - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - - bool isMatch( const TestCaseInfo& testCase ) const { - const std::string& name = testCase.getName(); - - switch( m_wildcardPosition ) { - case NoWildcard: - return m_stringToMatch == name; - case WildcardAtStart: - return endsWith( name, m_stringToMatch ); - case WildcardAtEnd: - return startsWith( name, m_stringToMatch ); - case WildcardAtBothEnds: - return contains( name, m_stringToMatch ); - } - throw std::logic_error( "Unhandled wildcard type" ); - } - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - - std::string m_stringToMatch; - IfFilterMatches::DoWhat m_filterType; - WildcardPosition m_wildcardPosition; - }; - - class TestCaseFilters { - public: - TestCaseFilters( const std::string& name ) : m_name( name ) {} - - std::string getName() const { - return m_name; - } - - void addFilter( const TestCaseFilter& filter ) { - if( filter.getFilterType() == IfFilterMatches::ExcludeTests ) - m_exclusionFilters.push_back( filter ); - else - m_inclusionFilters.push_back( filter ); - } - - void addTags( const std::string& tagPattern ) { - TagExpression exp; - TagExpressionParser( exp ).parse( tagPattern ); - - m_tagExpressions.push_back( exp ); - } - - bool shouldInclude( const TestCaseInfo& testCase ) const { - if( !m_tagExpressions.empty() ) { - std::vector::const_iterator it = m_tagExpressions.begin(); - std::vector::const_iterator itEnd = m_tagExpressions.end(); - for(; it != itEnd; ++it ) - if( it->matches( testCase.getTags() ) ) - break; - if( it == itEnd ) - return false; - } - - if( !m_inclusionFilters.empty() ) { - std::vector::const_iterator it = m_inclusionFilters.begin(); - std::vector::const_iterator itEnd = m_inclusionFilters.end(); - for(; it != itEnd; ++it ) - if( it->shouldInclude( testCase ) ) - break; - if( it == itEnd ) - return false; - } - else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) { - return !testCase.isHidden(); - } - - std::vector::const_iterator it = m_exclusionFilters.begin(); - std::vector::const_iterator itEnd = m_exclusionFilters.end(); - for(; it != itEnd; ++it ) - if( !it->shouldInclude( testCase ) ) - return false; - return true; - } - private: - std::vector m_tagExpressions; - std::vector m_inclusionFilters; - std::vector m_exclusionFilters; - std::string m_name; - }; - -} - -// #included from: catch_interfaces_config.h -#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED - -namespace Catch { - - struct IConfig { - - virtual ~IConfig(); - - virtual bool allowThrows() const = 0; - }; -} - -// #included from: catch_stream.hpp -#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED - -// #included from: catch_streambuf.h -#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED - -#include - -namespace Catch { - - class StreamBufBase : public std::streambuf { - public: - virtual ~StreamBufBase(); - }; -} - -#include -#include - -namespace Catch { - - template - class StreamBufImpl : public StreamBufBase { - char data[bufferSize]; - WriterF m_writer; - - public: - StreamBufImpl() { - setp( data, data + sizeof(data) ); - } - - ~StreamBufImpl() { - sync(); - } - - private: - int overflow( int c ) { - sync(); - - if( c != EOF ) { - if( pbase() == epptr() ) - m_writer( std::string( 1, static_cast( c ) ) ); - else - sputc( static_cast( c ) ); - } - return 0; - } - - int sync() { - if( pbase() != pptr() ) { - m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); - setp( pbase(), epptr() ); - } - return 0; - } - }; - - /////////////////////////////////////////////////////////////////////////// - - struct OutputDebugWriter { - - void operator()( const std::string &str ) { - writeToDebugConsole( str ); - } - }; - - class Stream { - public: - Stream() - : streamBuf( NULL ), isOwned( false ) - {} - - Stream( std::streambuf* _streamBuf, bool _isOwned ) - : streamBuf( _streamBuf ), isOwned( _isOwned ) - {} - - void release() { - if( isOwned ) { - delete streamBuf; - streamBuf = NULL; - isOwned = false; - } - } - - std::streambuf* streamBuf; - - private: - bool isOwned; - }; -} - -#include -#include -#include -#include - -namespace Catch { - - struct Include { enum WhichResults { - FailedOnly, - SuccessfulResults - }; }; - - struct List{ enum What { - None = 0, - - Reports = 1, - Tests = 2, - All = 3, - - TestNames = 6, - - WhatMask = 0xf, - - AsText = 0x10, - AsXml = 0x20, - - AsMask = 0xf0 - }; }; - - struct ConfigData { - - struct WarnAbout { enum What { - Nothing = 0x00, - NoAssertions = 0x01 - }; }; - - ConfigData() - : listSpec( List::None ), - shouldDebugBreak( false ), - includeWhichResults( Include::FailedOnly ), - cutoff( -1 ), - allowThrows( true ), - warnings( WarnAbout::Nothing ) - {} - - std::string reporter; - std::string outputFilename; - List::What listSpec; - std::vector filters; - bool shouldDebugBreak; - std::string stream; - Include::WhichResults includeWhichResults; - std::string name; - int cutoff; - bool allowThrows; - WarnAbout::What warnings; - }; - - class Config : public IConfig { - private: - Config( const Config& other ); - Config& operator = ( const Config& other ); - virtual void dummy(); - public: - - Config() - : m_os( std::cout.rdbuf() ) - {} - - Config( const ConfigData& data ) - : m_data( data ), - m_os( std::cout.rdbuf() ) - {} - - virtual ~Config() { - m_os.rdbuf( std::cout.rdbuf() ); - m_stream.release(); - } - - void setFilename( const std::string& filename ) { - m_data.outputFilename = filename; - } - - List::What getListSpec( void ) const { - return m_data.listSpec; - } - - const std::string& getFilename() const { - return m_data.outputFilename ; - } - - List::What listWhat() const { - return static_cast( m_data.listSpec & List::WhatMask ); - } - - List::What listAs() const { - return static_cast( m_data.listSpec & List::AsMask ); - } - - std::string getName() const { - return m_data.name; - } - - bool shouldDebugBreak() const { - return m_data.shouldDebugBreak; - } - - virtual std::ostream& stream() const { - return m_os; - } - - void setStreamBuf( std::streambuf* buf ) { - m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); - } - - void useStream( const std::string& streamName ) { - Stream stream = createStream( streamName ); - setStreamBuf( stream.streamBuf ); - m_stream.release(); - m_stream = stream; - } - - void addTestSpec( const std::string& testSpec ) { - TestCaseFilters filters( testSpec ); - filters.addFilter( TestCaseFilter( testSpec ) ); - m_data.filters.push_back( filters ); - } - - virtual bool includeSuccessfulResults() const { - return m_data.includeWhichResults == Include::SuccessfulResults; - } - - int getCutoff() const { - return m_data.cutoff; - } - - virtual bool allowThrows() const { - return m_data.allowThrows; - } - - const ConfigData& data() const { - return m_data; - } - ConfigData& data() { - return m_data; - } - - private: - ConfigData m_data; - - // !TBD Move these out of here - Stream m_stream; - mutable std::ostream m_os; - }; - -} // end namespace Catch - -#include -#include -#include - -namespace Catch -{ - struct ReporterConfig - { - ReporterConfig( const std::string& _name, - std::ostream& _stream, - bool _includeSuccessfulResults, - const ConfigData& _fullConfig ) - : name( _name ), - stream( _stream ), - includeSuccessfulResults( _includeSuccessfulResults ), - fullConfig( _fullConfig ) - {} - - ReporterConfig( const ReporterConfig& other ) - : name( other.name ), - stream( other.stream ), - includeSuccessfulResults( other.includeSuccessfulResults ), - fullConfig( other.fullConfig ) - {} - - std::string name; - std::ostream& stream; - bool includeSuccessfulResults; - ConfigData fullConfig; - - private: - void operator=(const ReporterConfig&); - }; - - class TestCaseInfo; - class AssertionResult; - - struct IReporter : IShared { - virtual ~IReporter(); - - virtual bool shouldRedirectStdout() const = 0; - - virtual void StartTesting() = 0; - virtual void EndTesting( const Totals& totals ) = 0; - - virtual void StartGroup( const std::string& groupName ) = 0; - virtual void EndGroup( const std::string& groupName, const Totals& totals ) = 0; - - virtual void StartTestCase( const TestCaseInfo& testInfo ) = 0; - // TestCaseResult - virtual void EndTestCase( const TestCaseInfo& testInfo, const Totals& totals, const std::string& stdOut, const std::string& stdErr ) = 0; - - // SectionInfo - virtual void StartSection( const std::string& sectionName, const std::string& description ) = 0; - // Section Result - virtual void EndSection( const std::string& sectionName, const Counts& assertions ) = 0; - - // - merge into SectionResult ? - virtual void NoAssertionsInSection( const std::string& sectionName ) = 0; - virtual void NoAssertionsInTestCase( const std::string& testName ) = 0; - - // - merge into SectionResult, TestCaseResult, GroupResult & TestRunResult - virtual void Aborted() = 0; - - // AssertionReslt - virtual void Result( const AssertionResult& result ) = 0; - }; - - struct IReporterFactory { - virtual ~IReporterFactory(); - virtual IReporter* create( const ReporterConfig& config ) const = 0; - virtual std::string getDescription() const = 0; - }; - - struct IReporterRegistry { - typedef std::map FactoryMap; - - virtual ~IReporterRegistry(); - virtual IReporter* create( const std::string& name, const ReporterConfig& config ) const = 0; - virtual const FactoryMap& getFactories() const = 0; - }; - - inline std::string trim( const std::string& str ) { - std::string::size_type start = str.find_first_not_of( "\n\r\t " ); - std::string::size_type end = str.find_last_not_of( "\n\r\t " ); - - return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; - } -} - -#include - -namespace Catch { - - class TestCaseInfo; - struct ITestCaseRegistry; - struct IExceptionTranslatorRegistry; - struct IExceptionTranslator; - - struct IRegistryHub { - virtual ~IRegistryHub(); - - virtual const IReporterRegistry& getReporterRegistry() const = 0; - virtual const ITestCaseRegistry& getTestCaseRegistry() const = 0; - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; - }; - - struct IMutableRegistryHub { - virtual ~IMutableRegistryHub(); - virtual void registerReporter( const std::string& name, IReporterFactory* factory ) = 0; - virtual void registerTest( const TestCaseInfo& testInfo ) = 0; - virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; - }; - - IRegistryHub& getRegistryHub(); - IMutableRegistryHub& getMutableRegistryHub(); - void cleanUp(); - std::string translateActiveException(); - -} - -#include - -namespace Catch { - - inline IResultCapture& getResultCapture() { - return getCurrentContext().getResultCapture(); - } - - template - ExpressionResultBuilder expressionResultBuilderFromMatcher( const MatcherT& matcher, - const std::string& matcherCallAsString ) { - std::string matcherAsString = matcher.toString(); - if( matcherAsString == "{?}" ) - matcherAsString = matcherCallAsString; - return ExpressionResultBuilder() - .setRhs( matcherAsString ) - .setOp( "matches" ); - } - - template - ExpressionResultBuilder expressionResultBuilderFromMatcher( const MatcherT& matcher, - const ArgT& arg, - const std::string& matcherCallAsString ) { - return expressionResultBuilderFromMatcher( matcher, matcherCallAsString ) - .setLhs( Catch::toString( arg ) ) - .setResultType( matcher.match( arg ) ); - } - - template - ExpressionResultBuilder expressionResultBuilderFromMatcher( const MatcherT& matcher, - ArgT* arg, - const std::string& matcherCallAsString ) { - return expressionResultBuilderFromMatcher( matcher, matcherCallAsString ) - .setLhs( Catch::toString( arg ) ) - .setResultType( matcher.match( arg ) ); - } - -struct TestFailureException{}; - -class ScopedInfo { -public: - ScopedInfo() : m_resultBuilder( ResultWas::Info ) { - getResultCapture().pushScopedInfo( this ); - } - ~ScopedInfo() { - getResultCapture().popScopedInfo( this ); - } - template - ScopedInfo& operator << ( const T& value ) { - m_resultBuilder << value; - return *this; - } - AssertionResult buildResult( const AssertionInfo& assertionInfo ) const { - return m_resultBuilder.buildResult( assertionInfo ); - } - -private: - ExpressionResultBuilder m_resultBuilder; -}; - -// This is just here to avoid compiler warnings with macro constants and boolean literals -inline bool isTrue( bool value ){ return value; } - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ASSERTIONINFO_NAME INTERNAL_CATCH_UNIQUE_NAME( __assertionInfo ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \ - if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \ - if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \ - if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \ - if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \ - if( Catch::isTrue( false ) ){ bool this_is_here_to_invoke_warnings = ( originalExpr ); Catch::isTrue( this_is_here_to_invoke_warnings ); } \ - } - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ACCEPT_INFO( expr, macroName, resultDisposition ) \ - Catch::AssertionInfo INTERNAL_CATCH_ASSERTIONINFO_NAME( macroName, CATCH_INTERNAL_LINEINFO, expr, resultDisposition ); - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ - try { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \ - } catch( Catch::TestFailureException& ) { \ - throw; \ - } catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \ - resultDisposition | Catch::ResultDisposition::ContinueOnFailure, expr ); \ - throw; \ - } \ - } while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ - INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ - if( Catch::getResultCapture().getLastResult()->succeeded() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ - INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ - if( !Catch::getResultCapture().getLastResult()->succeeded() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ - try { \ - expr; \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ - } \ - catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \ - } \ -} while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ - try { \ - if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \ - expr; \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \ - } \ - } \ - catch( Catch::TestFailureException& ) { \ - throw; \ - } \ - catch( exceptionType ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ - } - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ - INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ - } while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ - INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ - catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ - resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \ - } \ - } while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_MSG( reason, resultType, resultDisposition, macroName ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( resultType ) << reason, resultDisposition, true ) \ - } while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_SCOPED_INFO( log, macroName ) \ - INTERNAL_CATCH_ACCEPT_INFO( "", macroName, Catch::ResultDisposition::Normal ); \ - Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \ - INTERNAL_CATCH_UNIQUE_NAME( info ) << log - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \ - try { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \ - } catch( Catch::TestFailureException& ) { \ - throw; \ - } catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ - resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \ - throw; \ - } \ - } while( Catch::isTrue( false ) ) - -// #included from: internal/catch_section.hpp -#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED - -#include - -namespace Catch { - - class Section { - public: - Section( const std::string& name, - const std::string& description, - const SourceLineInfo& lineInfo ) - : m_name( name ), - m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( name, description, lineInfo, m_assertions ) ) - {} - - ~Section() { - if( m_sectionIncluded ) - getCurrentContext().getResultCapture().sectionEnded( m_name, m_assertions ); - } - - // This indicates whether the section should be executed or not - operator bool() { - return m_sectionIncluded; - } - - private: - - std::string m_name; - Counts m_assertions; - bool m_sectionIncluded; - }; - -} // end namespace Catch - -#define INTERNAL_CATCH_SECTION( name, desc ) \ - if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, CATCH_INTERNAL_LINEINFO ) ) - -// #included from: internal/catch_generators.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED - -#include -#include -#include -#include - -namespace Catch { - -template -struct IGenerator { - virtual ~IGenerator() {} - virtual T getValue( std::size_t index ) const = 0; - virtual std::size_t size () const = 0; -}; - -template -class BetweenGenerator : public IGenerator { -public: - BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} - - virtual T getValue( std::size_t index ) const { - return m_from+static_cast( index ); - } - - virtual std::size_t size() const { - return static_cast( 1+m_to-m_from ); - } - -private: - - T m_from; - T m_to; -}; - -template -class ValuesGenerator : public IGenerator { -public: - ValuesGenerator(){} - - void add( T value ) { - m_values.push_back( value ); - } - - virtual T getValue( std::size_t index ) const { - return m_values[index]; - } - - virtual std::size_t size() const { - return m_values.size(); - } - -private: - std::vector m_values; -}; - -template -class CompositeGenerator { -public: - CompositeGenerator() : m_totalSize( 0 ) {} - - // *** Move semantics, similar to auto_ptr *** - CompositeGenerator( CompositeGenerator& other ) - : m_fileInfo( other.m_fileInfo ), - m_totalSize( 0 ) - { - move( other ); - } - - CompositeGenerator& setFileInfo( const char* fileInfo ) { - m_fileInfo = fileInfo; - return *this; - } - - ~CompositeGenerator() { - deleteAll( m_composed ); - } - - operator T () const { - size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); - - typename std::vector*>::const_iterator it = m_composed.begin(); - typename std::vector*>::const_iterator itEnd = m_composed.end(); - for( size_t index = 0; it != itEnd; ++it ) - { - const IGenerator* generator = *it; - if( overallIndex >= index && overallIndex < index + generator->size() ) - { - return generator->getValue( overallIndex-index ); - } - index += generator->size(); - } - CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); - return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so - } - - void add( const IGenerator* generator ) { - m_totalSize += generator->size(); - m_composed.push_back( generator ); - } - - CompositeGenerator& then( CompositeGenerator& other ) { - move( other ); - return *this; - } - - CompositeGenerator& then( T value ) { - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( value ); - add( valuesGen ); - return *this; - } - -private: - - void move( CompositeGenerator& other ) { - std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); - m_totalSize += other.m_totalSize; - other.m_composed.clear(); - } - - std::vector*> m_composed; - std::string m_fileInfo; - size_t m_totalSize; -}; - -namespace Generators -{ - template - CompositeGenerator between( T from, T to ) { - CompositeGenerator generators; - generators.add( new BetweenGenerator( from, to ) ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2 ) { - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - generators.add( valuesGen ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2, T val3 ){ - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - generators.add( valuesGen ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2, T val3, T val4 ) { - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - valuesGen->add( val4 ); - generators.add( valuesGen ); - return generators; - } - -} // end namespace Generators - -using namespace Generators; - -} // end namespace Catch - -#define INTERNAL_CATCH_LINESTR2( line ) #line -#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) - -#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) - -// #included from: internal/catch_interfaces_exception.h -#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED - -#include - -namespace Catch { - - typedef std::string(*exceptionTranslateFunction)(); - - struct IExceptionTranslator { - virtual ~IExceptionTranslator(); - virtual std::string translate() const = 0; - }; - - struct IExceptionTranslatorRegistry { - virtual ~IExceptionTranslatorRegistry(); - - virtual std::string translateActiveException() const = 0; - }; - - class ExceptionTranslatorRegistrar { - template - class ExceptionTranslator : public IExceptionTranslator { - public: - - ExceptionTranslator( std::string(*translateFunction)( T& ) ) - : m_translateFunction( translateFunction ) - {} - - virtual std::string translate() const { - try { - throw; - } - catch( T& ex ) { - return m_translateFunction( ex ); - } - } - - protected: - std::string(*m_translateFunction)( T& ); - }; - - public: - template - ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { - getMutableRegistryHub().registerTranslator - ( new ExceptionTranslator( translateFunction ) ); - } - }; -} - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ - static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ - namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ - static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) - -// #included from: internal/catch_approx.hpp -#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED - -#include -#include - -namespace Catch { -namespace Detail { - - class Approx { - public: - explicit Approx ( double value ) - : m_epsilon( std::numeric_limits::epsilon()*100 ), - m_scale( 1.0 ), - m_value( value ) - {} - - Approx( const Approx& other ) - : m_epsilon( other.m_epsilon ), - m_scale( other.m_scale ), - m_value( other.m_value ) - {} - - static Approx custom() { - return Approx( 0 ); - } - - Approx operator()( double value ) { - Approx approx( value ); - approx.epsilon( m_epsilon ); - approx.scale( m_scale ); - return approx; - } - - friend bool operator == ( double lhs, const Approx& rhs ) { - // Thanks to Richard Harris for his help refining this formula - return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); - } - - friend bool operator == ( const Approx& lhs, double rhs ) { - return operator==( rhs, lhs ); - } - - friend bool operator != ( double lhs, const Approx& rhs ) { - return !operator==( lhs, rhs ); - } - - friend bool operator != ( const Approx& lhs, double rhs ) { - return !operator==( rhs, lhs ); - } - - Approx& epsilon( double newEpsilon ) { - m_epsilon = newEpsilon; - return *this; - } - - Approx& scale( double newScale ) { - m_scale = newScale; - return *this; - } - - std::string toString() const { - std::ostringstream oss; - oss << "Approx( " << m_value << " )"; - return oss.str(); - } - - private: - double m_epsilon; - double m_scale; - double m_value; - }; -} - -template<> -inline std::string toString( const Detail::Approx& value ) { - return value.toString(); -} - -} // end namespace Catch - -// #included from: internal/catch_matchers.hpp -#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED - -namespace Catch { -namespace Matchers { - namespace Impl { - - template - struct Matcher : SharedImpl - { - typedef ExpressionT ExpressionType; - - virtual ~Matcher() {} - virtual Ptr clone() const = 0; - virtual bool match( const ExpressionT& expr ) const = 0; - virtual std::string toString() const = 0; - }; - - template - struct MatcherImpl : Matcher { - - virtual Ptr > clone() const { - return Ptr >( new DerivedT( static_cast( *this ) ) ); - } - }; - - namespace Generic { - - template - class AllOf : public MatcherImpl, ExpressionT> { - public: - - AllOf() {} - AllOf( const AllOf& other ) : m_matchers( other.m_matchers ) {} - - AllOf& add( const Matcher& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( const ExpressionT& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( !m_matchers[i]->match( expr ) ) - return false; - return true; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " and "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - private: - std::vector > > m_matchers; - }; - - template - class AnyOf : public MatcherImpl, ExpressionT> { - public: - - AnyOf() {} - AnyOf( const AnyOf& other ) : m_matchers( other.m_matchers ) {} - - AnyOf& add( const Matcher& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( const ExpressionT& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( m_matchers[i]->match( expr ) ) - return true; - return false; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " or "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - private: - std::vector > > m_matchers; - }; - - } - - namespace StdString { - - struct Equals : MatcherImpl { - Equals( const std::string& str ) : m_str( str ){} - Equals( const Equals& other ) : m_str( other.m_str ){} - - virtual ~Equals(); - - virtual bool match( const std::string& expr ) const { - return m_str == expr; - } - virtual std::string toString() const { - return "equals: \"" + m_str + "\""; - } - - std::string m_str; - }; - - struct Contains : MatcherImpl { - Contains( const std::string& substr ) : m_substr( substr ){} - Contains( const Contains& other ) : m_substr( other.m_substr ){} - - virtual ~Contains(); - - virtual bool match( const std::string& expr ) const { - return expr.find( m_substr ) != std::string::npos; - } - virtual std::string toString() const { - return "contains: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - - struct StartsWith : MatcherImpl { - StartsWith( const std::string& substr ) : m_substr( substr ){} - StartsWith( const StartsWith& other ) : m_substr( other.m_substr ){} - - virtual ~StartsWith(); - - virtual bool match( const std::string& expr ) const { - return expr.find( m_substr ) == 0; - } - virtual std::string toString() const { - return "starts with: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - - struct EndsWith : MatcherImpl { - EndsWith( const std::string& substr ) : m_substr( substr ){} - EndsWith( const EndsWith& other ) : m_substr( other.m_substr ){} - - virtual ~EndsWith(); - - virtual bool match( const std::string& expr ) const { - return expr.find( m_substr ) == expr.size() - m_substr.size(); - } - virtual std::string toString() const { - return "ends with: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - } // namespace StdString - } // namespace Impl - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - template - inline Impl::Generic::AllOf AllOf( const Impl::Matcher& m1, - const Impl::Matcher& m2 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AllOf AllOf( const Impl::Matcher& m1, - const Impl::Matcher& m2, - const Impl::Matcher& m3 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); - } - template - inline Impl::Generic::AnyOf AnyOf( const Impl::Matcher& m1, - const Impl::Matcher& m2 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AnyOf AnyOf( const Impl::Matcher& m1, - const Impl::Matcher& m2, - const Impl::Matcher& m3 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); - } - - inline Impl::StdString::Equals Equals( const std::string& str ){ return Impl::StdString::Equals( str ); } - inline Impl::StdString::Contains Contains( const std::string& substr ){ return Impl::StdString::Contains( substr ); } - inline Impl::StdString::StartsWith StartsWith( const std::string& substr ){ return Impl::StdString::StartsWith( substr ); } - inline Impl::StdString::EndsWith EndsWith( const std::string& substr ){ return Impl::StdString::EndsWith( substr ); } - -} // namespace Matchers - -using namespace Matchers; - -} // namespace Catch - -// These files are included here so the single_include script doesn't put them -// in the conditionally compiled sections -// #included from: internal/catch_interfaces_runner.h -#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED - -#include - -namespace Catch { - class TestCaseInfo; - - struct IRunner { - virtual ~IRunner(); - }; -} - - -#ifdef __OBJC__ -// #included from: internal/catch_objc.hpp -#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED - -#import - -#include - -// NB. Any general catch headers included here must be included -// in catch.hpp first to make sure they are included by the single -// header for non obj-usage - -/////////////////////////////////////////////////////////////////////////////// -// This protocol is really only here for (self) documenting purposes, since -// all its methods are optional. -@protocol OcFixture - -@optional - --(void) setUp; --(void) tearDown; - -@end - -namespace Catch { - - class OcMethod : public SharedImpl { - - public: - OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} - - virtual void invoke() const { - id obj = [[m_cls alloc] init]; - - performOptionalSelector( obj, @selector(setUp) ); - performOptionalSelector( obj, m_sel ); - performOptionalSelector( obj, @selector(tearDown) ); - - arcSafeRelease( obj ); - } - private: - virtual ~OcMethod() {} - - Class m_cls; - SEL m_sel; - }; - - namespace Detail{ - - inline bool startsWith( const std::string& str, const std::string& sub ) { - return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub; - } - - inline std::string getAnnotation( Class cls, - const std::string& annotationName, - const std::string& testCaseName ) { - NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; - SEL sel = NSSelectorFromString( selStr ); - arcSafeRelease( selStr ); - id value = performOptionalSelector( cls, sel ); - if( value ) - return [(NSString*)value UTF8String]; - return ""; - } - } - - inline size_t registerTestMethods() { - size_t noTestMethods = 0; - int noClasses = objc_getClassList( NULL, 0 ); - - Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); - objc_getClassList( classes, noClasses ); - - for( int c = 0; c < noClasses; c++ ) { - Class cls = classes[c]; - { - u_int count; - Method* methods = class_copyMethodList( cls, &count ); - for( u_int m = 0; m < count ; m++ ) { - SEL selector = method_getName(methods[m]); - std::string methodName = sel_getName(selector); - if( Detail::startsWith( methodName, "Catch_TestCase_" ) ) { - std::string testCaseName = methodName.substr( 15 ); - std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); - std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); - const char* className = class_getName( cls ); - - getMutableRegistryHub().registerTest( TestCaseInfo( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); - noTestMethods++; - } - } - free(methods); - } - } - return noTestMethods; - } - - namespace Matchers { - namespace Impl { - namespace NSStringMatchers { - - template - struct StringHolder : MatcherImpl{ - StringHolder( NSString* substr ) : m_substr( [substr copy] ){} - StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} - StringHolder() { - arcSafeRelease( m_substr ); - } - - NSString* m_substr; - }; - - struct Equals : StringHolder { - Equals( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return [str isEqualToString:m_substr]; - } - - virtual std::string toString() const { - return "equals string: \"" + Catch::toString( m_substr ) + "\""; - } - }; - - struct Contains : StringHolder { - Contains( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return [str rangeOfString:m_substr].location != NSNotFound; - } - - virtual std::string toString() const { - return "contains string: \"" + Catch::toString( m_substr ) + "\""; - } - }; - - struct StartsWith : StringHolder { - StartsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return [str rangeOfString:m_substr].location == 0; - } - - virtual std::string toString() const { - return "starts with: \"" + Catch::toString( m_substr ) + "\""; - } - }; - struct EndsWith : StringHolder { - EndsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return [str rangeOfString:m_substr].location == [str length] - [m_substr length]; - } - - virtual std::string toString() const { - return "ends with: \"" + Catch::toString( m_substr ) + "\""; - } - }; - - } // namespace NSStringMatchers - } // namespace Impl - - inline Impl::NSStringMatchers::Equals - Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } - - inline Impl::NSStringMatchers::Contains - Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } - - inline Impl::NSStringMatchers::StartsWith - StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } - - inline Impl::NSStringMatchers::EndsWith - EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } - - } // namespace Matchers - - using namespace Matchers; - -} // namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define OC_TEST_CASE( name, desc )\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ -{\ -return @ name; \ -}\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ -{ \ -return @ desc; \ -} \ --(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) - -#endif - -#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER ) -// #included from: internal/catch_impl.hpp -#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED - -// Collect all the implementation files together here -// These are the equivalent of what would usually be cpp files - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#endif - -// #included from: catch_runner.hpp -#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED - -// #included from: internal/catch_commandline.hpp -#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED - -namespace Catch { - - class Command { - public: - Command(){} - - explicit Command( const std::string& name ) : m_name( name ) { - } - - Command& operator += ( const std::string& arg ) { - m_args.push_back( arg ); - return *this; - } - Command& operator += ( const Command& other ) { - std::copy( other.m_args.begin(), other.m_args.end(), std::back_inserter( m_args ) ); - if( m_name.empty() ) - m_name = other.m_name; - return *this; - } - Command operator + ( const Command& other ) { - Command newCommand( *this ); - newCommand += other; - return newCommand; - } - - operator SafeBool::type() const { - return SafeBool::makeSafe( !m_name.empty() || !m_args.empty() ); - } - - std::string name() const { return m_name; } - std::string operator[]( std::size_t i ) const { return m_args[i]; } - std::size_t argsCount() const { return m_args.size(); } - - CATCH_ATTRIBUTE_NORETURN - void raiseError( const std::string& message ) const { - std::ostringstream oss; - if( m_name.empty() ) - oss << "Error while parsing " << m_name << ". " << message << "."; - else - oss << "Error while parsing arguments. " << message << "."; - - if( m_args.size() > 0 ) - oss << " Arguments were:"; - for( std::size_t i = 0; i < m_args.size(); ++i ) - oss << " " << m_args[i]; - throw std::domain_error( oss.str() ); - } - - private: - - std::string m_name; - std::vector m_args; - }; - - class CommandParser { - public: - CommandParser( int argc, char const * const * argv ) : m_argc( static_cast( argc ) ), m_argv( argv ) {} - - std::string exeName() const { - return m_argv[0]; - } - Command find( const std::string& arg1, const std::string& arg2, const std::string& arg3 ) const { - return find( arg1 ) + find( arg2 ) + find( arg3 ); - } - - Command find( const std::string& shortArg, const std::string& longArg ) const { - return find( shortArg ) + find( longArg ); - } - Command find( const std::string& arg ) const { - if( arg.empty() ) - return getArgs( "", 1 ); - else - for( std::size_t i = 1; i < m_argc; ++i ) - if( m_argv[i] == arg ) - return getArgs( m_argv[i], i+1 ); - return Command(); - } - Command getDefaultArgs() const { - return getArgs( "", 1 ); - } - - private: - Command getArgs( const std::string& cmdName, std::size_t from ) const { - Command command( cmdName ); - for( std::size_t i = from; i < m_argc && m_argv[i][0] != '-'; ++i ) - command += m_argv[i]; - return command; - } - - std::size_t m_argc; - char const * const * m_argv; - }; - - class OptionParser : public SharedImpl { - public: - OptionParser( int minArgs = 0, int maxArgs = 0 ) - : m_minArgs( minArgs ), m_maxArgs( maxArgs ) - {} - - virtual ~OptionParser() {} - - Command find( const CommandParser& parser ) const { - Command cmd; - for( std::vector::const_iterator it = m_optionNames.begin(); - it != m_optionNames.end(); - ++it ) - cmd += parser.find( *it ); - return cmd; - } - - void validateArgs( const Command& args ) const { - if( tooFewArgs( args ) || tooManyArgs( args ) ) { - std::ostringstream oss; - if( m_maxArgs == -1 ) - oss <<"Expected at least " << pluralise( static_cast( m_minArgs ), "argument" ); - else if( m_minArgs == m_maxArgs ) - oss <<"Expected " << pluralise( static_cast( m_minArgs ), "argument" ); - else - oss <<"Expected between " << m_minArgs << " and " << m_maxArgs << " argument"; - args.raiseError( oss.str() ); - } - } - - void parseIntoConfig( const CommandParser& parser, ConfigData& config ) { - if( Command cmd = find( parser ) ) { - validateArgs( cmd ); - parseIntoConfig( cmd, config ); - } - } - - virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) = 0; - virtual std::string argsSynopsis() const = 0; - virtual std::string optionSummary() const = 0; - virtual std::string optionDescription() const { return ""; } - - std::string optionNames() const { - std::string names; - for( std::vector::const_iterator it = m_optionNames.begin(); - it != m_optionNames.end(); - ++it ) { - if( !it->empty() ) { - if( !names.empty() ) - names += ", "; - names += *it; - } - else { - names = "[" + names; - } - } - if( names[0] == '[' ) - names += "]"; - return names; - } - - protected: - - bool tooFewArgs( const Command& args ) const { - return args.argsCount() < static_cast( m_minArgs ); - } - bool tooManyArgs( const Command& args ) const { - return m_maxArgs >= 0 && args.argsCount() > static_cast( m_maxArgs ); - } - std::vector m_optionNames; - int m_minArgs; - int m_maxArgs; - }; - - namespace Options { - - class HelpOptionParser : public OptionParser { - public: - HelpOptionParser() { - m_optionNames.push_back( "-?" ); - m_optionNames.push_back( "-h" ); - m_optionNames.push_back( "--help" ); - } - virtual std::string argsSynopsis() const { - return "[