mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Add a MLT=0 build for a tippecanoe without MapLibre Tile support
MapLibre Tile support pulls in the maplibre-tile-spec submodule and needs cmake to build it, which is a lot to ask of anyone who only wants to work with Mapbox Vector Tiles. `make MLT=0` compiles with -DNO_MLT, skips the submodule and its cmake build entirely, and drops the MLT tests from `make test`. The result needs no dependencies beyond the ones MVT already needed, and can be built from a checkout with no submodules at all. Everything that touches the MLT library is behind the #ifdef, which is just the two files that were written for it. The option parsing and the tile format helpers stay compiled either way, so nothing else needs to know: --output-format=mlt reports that the build has no MLT support rather than being an unrecognized value, and a tile that is recognized as MLT reports the same instead of being misparsed as a protobuf, since the format sniffing itself doesn't need the library. CI builds and tests this configuration from a checkout without submodules, so it can't quietly stop working. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LxhELiLtpUFwrPSWwTYdHG
This commit is contained in:
@@ -21,3 +21,12 @@ jobs:
|
||||
run: brew install sqlite3
|
||||
- run: uname -a; BUILDTYPE=${{ matrix.version }} make
|
||||
- run: make test
|
||||
|
||||
test-without-mlt:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# No submodules: the MLT=0 build must not need them
|
||||
- uses: actions/checkout@v3
|
||||
- run: sudo apt-get install libsqlite3-dev
|
||||
- run: uname -a; make MLT=0
|
||||
- run: make MLT=0 test
|
||||
|
||||
@@ -4,12 +4,36 @@ BUILDTYPE ?= Release
|
||||
BUILD_INFO ?=
|
||||
SHELL = /bin/sh
|
||||
|
||||
# MapLibre Tile support requires the maplibre-tile-spec submodule and cmake
|
||||
# to build it. Use `make MLT=0` for a build with no dependencies beyond the
|
||||
# ones that Mapbox Vector Tiles need; it can neither read nor write MLT.
|
||||
MLT ?= 1
|
||||
|
||||
MLT_BUILD_STAMP = mlt-build/.built
|
||||
|
||||
ifeq ($(MLT),0)
|
||||
MLT_FLAGS = -DNO_MLT
|
||||
MLT_INCLUDES =
|
||||
MLT_STD =
|
||||
MLT_DEPS =
|
||||
MLT_DECODE_LIBS =
|
||||
MLT_LIBS =
|
||||
MLT_TESTS =
|
||||
else
|
||||
MLT_FLAGS =
|
||||
MLT_INCLUDES = -isystem maplibre-tile-spec/cpp/include -isystem maplibre-tile-spec/cpp/vendor/fsst
|
||||
MLT_STD = -std=c++20
|
||||
MLT_DEPS = $(MLT_BUILD_STAMP)
|
||||
MLT_DECODE_LIBS = mlt-build/libmlt-cpp.a mlt-build/libfsst-lib.a mlt-build/fastpfor/libFastPFOR.a
|
||||
MLT_LIBS = mlt-build/libmlt-cpp-encoder.a $(MLT_DECODE_LIBS)
|
||||
MLT_TESTS = mlt-test mlt-decode-test mlt-output-test
|
||||
endif
|
||||
|
||||
# inherit from env if set
|
||||
CC := $(CC)
|
||||
CXX := $(CXX)
|
||||
CFLAGS := $(CFLAGS) -fPIE -DBUILD_INFO=$(BUILD_INFO)
|
||||
CXXFLAGS := $(CXXFLAGS) -std=c++17 -fPIE -DBUILD_INFO=$(BUILD_INFO)
|
||||
CXXFLAGS := $(CXXFLAGS) -std=c++17 -fPIE -DBUILD_INFO=$(BUILD_INFO) $(MLT_FLAGS)
|
||||
LDFLAGS := $(LDFLAGS)
|
||||
WARNING_FLAGS := -Wall -Wshadow -Wsign-compare -Wextra -Wunreachable-code -Wuninitialized -Wshadow
|
||||
RELEASE_FLAGS := -O3 -DNDEBUG
|
||||
@@ -57,10 +81,6 @@ H = $(wildcard *.h) $(wildcard *.hpp)
|
||||
C = $(wildcard *.c) $(wildcard *.cpp)
|
||||
|
||||
INCLUDES = -I/usr/local/include -I. -Iclipper2/include
|
||||
MLT_INCLUDES = -isystem maplibre-tile-spec/cpp/include -isystem maplibre-tile-spec/cpp/vendor/fsst
|
||||
MLT_DECODE_LIBS = mlt-build/libmlt-cpp.a mlt-build/libfsst-lib.a mlt-build/fastpfor/libFastPFOR.a
|
||||
MLT_LIBS = mlt-build/libmlt-cpp-encoder.a $(MLT_DECODE_LIBS)
|
||||
MLT_BUILD_STAMP = mlt-build/.built
|
||||
LIBS = -L/usr/local/lib
|
||||
|
||||
$(MLT_BUILD_STAMP): maplibre-tile-spec/cpp/CMakeLists.txt
|
||||
@@ -76,7 +96,9 @@ $(MLT_BUILD_STAMP): maplibre-tile-spec/cpp/CMakeLists.txt
|
||||
cmake --build mlt-build --target mlt-cpp mlt-cpp-encoder $(if $(VERBOSE),,-- -s) > /dev/null
|
||||
touch $@
|
||||
|
||||
ifneq ($(MLT),0)
|
||||
$(MLT_LIBS): $(MLT_BUILD_STAMP)
|
||||
endif
|
||||
|
||||
tippecanoe: geojson.o jsonpull/jsonpull.o tile.o pool.o mbtiles.o geometry.o projection.o memfile.o mvt.o mlt.o mlt_decode.o serial.o main.o platform.o text.o dirtiles.o pmtiles_file.o plugin.o read_json.o write_json.o geobuf.o flatgeobuf.o evaluator.o geocsv.o csv.o geojson-loop.o json_logger.o visvalingam.o compression.o clip.o sort.o attribute.o thread.o shared_borders.o clipper2/src/clipper.engine.o $(MLT_LIBS)
|
||||
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
|
||||
@@ -104,8 +126,8 @@ tippecanoe-overzoom: overzoom.o mvt.o mlt.o mlt_decode.o clip.o evaluator.o json
|
||||
%.o: %.c
|
||||
$(CC) -MMD $(PG) $(INCLUDES) $(FINAL_FLAGS) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
mlt.o mlt_decode.o: %.o: %.cpp $(MLT_BUILD_STAMP)
|
||||
$(CXX) -MMD $(PG) $(INCLUDES) $(MLT_INCLUDES) $(FINAL_FLAGS) $(CXXFLAGS) -std=c++20 -c -o $@ $<
|
||||
mlt.o mlt_decode.o: %.o: %.cpp $(MLT_DEPS)
|
||||
$(CXX) -MMD $(PG) $(INCLUDES) $(MLT_INCLUDES) $(FINAL_FLAGS) $(CXXFLAGS) $(MLT_STD) -c -o $@ $<
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) -MMD $(PG) $(INCLUDES) $(FINAL_FLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
@@ -119,7 +141,7 @@ indent:
|
||||
TESTS = $(wildcard tests/*/out/*.json)
|
||||
SPACE = $(NULL) $(NULL)
|
||||
|
||||
test: tippecanoe tippecanoe-decode $(addsuffix .check,$(TESTS)) raw-tiles-test parallel-test pbf-test join-test enumerate-test decode-test join-filter-test unit json-tool-test allow-existing-test csv-test layer-json-test pmtiles-test decode-pmtiles-test overzoom-test flatgeobuf-test mlt-test mlt-decode-test mlt-output-test
|
||||
test: tippecanoe tippecanoe-decode $(addsuffix .check,$(TESTS)) raw-tiles-test parallel-test pbf-test join-test enumerate-test decode-test join-filter-test unit json-tool-test allow-existing-test csv-test layer-json-test pmtiles-test decode-pmtiles-test overzoom-test flatgeobuf-test $(MLT_TESTS)
|
||||
./unit
|
||||
|
||||
suffixes = json json.gz
|
||||
|
||||
@@ -50,6 +50,12 @@ $ make -j
|
||||
$ make install
|
||||
```
|
||||
|
||||
The submodule is the [MapLibre Tile](https://github.com/maplibre/maplibre-tile-spec)
|
||||
implementation, which is built with `cmake`. If you don't need MapLibre Tile support,
|
||||
build with `make MLT=0` instead, which needs neither the submodule nor `cmake`. Such a
|
||||
build can't read or write MLT, and rejects `--output-format=mlt`, but is otherwise the same.
|
||||
Run `make clean` first if you are switching an existing build directory between the two.
|
||||
|
||||
See [Development](#development) below for how to upgrade your
|
||||
C++ compiler or install prerequisite packages if you get
|
||||
compiler errors.
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "mlt.hpp"
|
||||
#include "errors.hpp"
|
||||
|
||||
#include <mlt/encoder.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
@@ -12,7 +10,11 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifndef NO_MLT
|
||||
#include <mlt/encoder.hpp>
|
||||
|
||||
using Vertex = mlt::Encoder::Vertex;
|
||||
#endif
|
||||
|
||||
int output_format = OUTPUT_MVT;
|
||||
bool mlt_sort_features = true;
|
||||
@@ -22,7 +24,12 @@ void set_output_format(char **argv, const char *format) {
|
||||
if (strcmp(format, "mvt") == 0 || strcmp(format, "pbf") == 0) {
|
||||
output_format = OUTPUT_MVT;
|
||||
} else if (strcmp(format, "mlt") == 0) {
|
||||
#ifdef NO_MLT
|
||||
fprintf(stderr, "%s: this build was compiled without MapLibre Tile support\n", argv[0]);
|
||||
exit(EXIT_ARGS);
|
||||
#else
|
||||
output_format = OUTPUT_MLT;
|
||||
#endif
|
||||
} else {
|
||||
fprintf(stderr, "%s: --output-format must be 'mvt' or 'mlt'\n", argv[0]);
|
||||
exit(EXIT_ARGS);
|
||||
@@ -38,13 +45,19 @@ const char *tile_format_extension(int format) {
|
||||
}
|
||||
|
||||
std::string encode_tile(mvt_tile &tile, int format) {
|
||||
#ifndef NO_MLT
|
||||
if (format == OUTPUT_MLT) {
|
||||
return encode_as_mlt(tile, mlt_sort_features, mlt_pretessellate);
|
||||
} else {
|
||||
return tile.encode();
|
||||
}
|
||||
#else
|
||||
(void) format;
|
||||
#endif
|
||||
|
||||
return tile.encode();
|
||||
}
|
||||
|
||||
#ifndef NO_MLT
|
||||
|
||||
// An MLT property column has a single type for the whole layer, while MVT
|
||||
// values each carry their own type, so a type that can hold every value of
|
||||
// an attribute has to be chosen before the layer can be converted.
|
||||
@@ -327,3 +340,5 @@ std::string encode_as_mlt(const mvt_tile &tile, bool sort_features, bool pretess
|
||||
auto bytes = encoder.encode(layers, config);
|
||||
return std::string(reinterpret_cast<const char *>(bytes.data()), bytes.size());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,14 +24,17 @@ const char *tile_format_extension(int format);
|
||||
// options were selected on the command line
|
||||
std::string encode_tile(mvt_tile &tile, int format);
|
||||
|
||||
#ifndef NO_MLT
|
||||
std::string encode_as_mlt(const mvt_tile &tile, bool sort_features, bool pretessellate);
|
||||
#endif
|
||||
|
||||
// Does this (already decompressed) tile look like MapLibre Tile rather than
|
||||
// Mapbox Vector Tile data?
|
||||
bool is_mlt(const std::string &message);
|
||||
|
||||
// Decode a MapLibre Tile into the equivalent vector tile, returning false
|
||||
// (and complaining to stderr) if it can't be parsed.
|
||||
// (and complaining to stderr) if it can't be parsed, or if this build
|
||||
// doesn't have MLT support compiled in.
|
||||
bool decode_mlt(const std::string &message, mvt_tile &out);
|
||||
|
||||
#endif
|
||||
|
||||
+26
-6
@@ -1,11 +1,5 @@
|
||||
#include "mlt.hpp"
|
||||
|
||||
#include <mlt/decoder.hpp>
|
||||
#include <mlt/geometry.hpp>
|
||||
#include <mlt/layer.hpp>
|
||||
#include <mlt/properties.hpp>
|
||||
#include <mlt/tile.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
@@ -18,6 +12,14 @@
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#ifndef NO_MLT
|
||||
#include <mlt/decoder.hpp>
|
||||
#include <mlt/geometry.hpp>
|
||||
#include <mlt/layer.hpp>
|
||||
#include <mlt/properties.hpp>
|
||||
#include <mlt/tile.hpp>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
bool read_varint(const char *&p, const char *end, unsigned long long &out) {
|
||||
@@ -39,6 +41,8 @@ bool read_varint(const char *&p, const char *end, unsigned long long &out) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef NO_MLT
|
||||
|
||||
long long round_coord(float v) {
|
||||
return (long long) std::llround(v);
|
||||
}
|
||||
@@ -237,6 +241,8 @@ void convert_layer(const mlt::Layer &in, mvt_layer &out, const std::shared_ptr<s
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
bool is_mlt(const std::string &message) {
|
||||
@@ -267,6 +273,18 @@ bool is_mlt(const std::string &message) {
|
||||
return layer_tag == 1;
|
||||
}
|
||||
|
||||
#ifdef NO_MLT
|
||||
|
||||
bool decode_mlt(const std::string &message, mvt_tile &out) {
|
||||
(void) message;
|
||||
(void) out;
|
||||
|
||||
fprintf(stderr, "This build was compiled without MapLibre Tile support\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool decode_mlt(const std::string &message, mvt_tile &out) {
|
||||
try {
|
||||
mlt::Decoder decoder(true);
|
||||
@@ -289,3 +307,5 @@ bool decode_mlt(const std::string &message, mvt_tile &out) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user