diff --git a/CMakeLists.txt b/CMakeLists.txt index 31510c913..fe1243f03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ mapnik_option(USE_PROJ "adds proj support" ON) mapnik_option(USE_GRID_RENDERER "adds grid renderer" ON) mapnik_option(USE_SVG_RENDERER "adds svg renderer" ON) mapnik_option(USE_BIGINT "uses 64 bit instead of 32" ON) +mapnik_option(USE_BOOST_FILESYSTEM "use boost::filesytem even if `std::filesystem` is avaible (since c++17)" OFF) mapnik_option(USE_MEMORY_MAPPED_FILE "uses file cache" ON) mapnik_option(USE_MULTITHREADED "enables the multithreaded features (threadsafe)" ON) mapnik_option(USE_NO_ATEXIT "disable atexit" OFF) @@ -154,7 +155,14 @@ mapnik_find_package(PkgConfig REQUIRED) mapnik_find_threads() mapnik_find_package(ICU REQUIRED COMPONENTS uc i18n data) -mapnik_find_package(Boost ${BOOST_MIN_VERSION} REQUIRED COMPONENTS filesystem system regex) +mapnik_find_package(Boost ${BOOST_MIN_VERSION} REQUIRED COMPONENTS regex) +if(CMAKE_CXX_STANDARD LESS 17) + set(USE_BOOST_FILESYSTEM ON) +endif() +if(USE_BOOST_FILESYSTEM) +mapnik_find_package(Boost ${BOOST_MIN_VERSION} REQUIRED COMPONENTS filesystem system) +endif() + list(APPEND MAPNIK_COMPILE_DEFS BOOST_REGEX_HAS_ICU) if(USE_BOOST_REGEX_ICU_WORKAROUND) message(STATUS "using boost regex workaround") @@ -257,6 +265,11 @@ if(USE_BIGINT) list(APPEND MAPNIK_COMPILE_DEFS BIGINT) endif() +if(USE_BOOST_FILESYSTEM) + list(APPEND MAPNIK_COMPILE_DEFS USE_BOOST_FILESYSYTEM) + list(APPEND MAPNIK_OPTIONAL_LIBS Boost::filesystem) +endif() + if(USE_MEMORY_MAPPED_FILE) list(APPEND MAPNIK_COMPILE_DEFS MAPNIK_MEMORY_MAPPED_FILE) endif() @@ -394,10 +407,10 @@ target_link_libraries(core INTERFACE ICU::i18n Boost::headers Boost::regex - Boost::filesystem Freetype::Freetype ${MAPNIK_OPTIONAL_LIBS} ) + target_compile_definitions(core INTERFACE ${MAPNIK_COMPILE_DEFS}) mapnik_install(core) diff --git a/SConstruct b/SConstruct index 9df2c5f9f..0c3f67ce6 100644 --- a/SConstruct +++ b/SConstruct @@ -467,6 +467,7 @@ opts.AddVariables( BoolVariable('MAPNIK_RENDER', 'Compile and install a utility to render a map to an image', 'True'), BoolVariable('COLOR_PRINT', 'Print build status information in color', 'True'), BoolVariable('BIGINT', 'Compile support for 64-bit integers in mapnik::value', 'True'), + BoolVariable('USE_BOOST_FILESYSTEM','Use boost::filesytem even if `std::filesystem` is avaible (since c++17)', 'False'), BoolVariable('QUIET', 'Reduce build verbosity', 'False'), ) @@ -535,6 +536,7 @@ pickle_store = [# Scons internal variables 'SQLITE_LINKFLAGS', 'BOOST_LIB_VERSION_FROM_HEADER', 'BIGINT', + 'USE_BOOST_FILESYSTEM', 'HOST', 'QUERIED_GDAL_DATA', 'QUERIED_ICU_DATA', @@ -1631,6 +1633,9 @@ if not preconfigured: if env['BIGINT']: env.Append(CPPDEFINES = '-DBIGINT') + if env['USE_BOOST_FILESYSTEM']: + env.Append(CPPDEFINES = '-DUSE_BOOST_FILESYSTEM') + if env['THREADING'] == 'multi': thread_flag = thread_suffix else: @@ -1650,12 +1655,13 @@ if not preconfigured: # The other required boost headers. BOOST_LIBSHEADERS = [ - ['system', 'boost/system/system_error.hpp', True], - ['filesystem', 'boost/filesystem/operations.hpp', True], ['regex', 'boost/regex.hpp', True], ['program_options', 'boost/program_options.hpp', False] ] + if int(env['CXX_STD']) < 17 or env['USE_BOOST_FILESYSTEM']: + BOOST_LIBSHEADERS.append(['system', 'boost/system/system_error.hpp', True]) + BOOST_LIBSHEADERS.append(['filesystem', 'boost/filesystem/operations.hpp', True]) # if requested, sort LIBPATH and CPPPATH before running CheckLibWithHeader tests if env['PRIORITIZE_LINKING']: conf.prioritize_paths(silent=True) diff --git a/include/mapnik/filesystem.hpp b/include/mapnik/filesystem.hpp new file mode 100644 index 000000000..09a3731e4 --- /dev/null +++ b/include/mapnik/filesystem.hpp @@ -0,0 +1,43 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2023 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_FILESYSTEM_HPP +#define MAPNIK_FILESYSTEM_HPP + +#if defined(__cpp_lib_filesystem) && !defined(USE_BOOST_FILESYSTEM) +#include +#else +#include // for absolute, exists, etc +#include // for path, operator/ +#endif + +namespace mapnik { +#if defined(__cpp_lib_filesystem) && !defined(USE_BOOST_FILESYSTEM) +namespace fs = std::filesystem; +using error_code = std::error_code; +#else +namespace fs = boost::filesystem; +using error_code = boost::system::error_code; +#endif +} // namespace mapnik + +#endif // MAPNIK_FILESYSTEM_HPP diff --git a/plugins/input/csv/build.py b/plugins/input/csv/build.py index f5e030d88..c71fff747 100644 --- a/plugins/input/csv/build.py +++ b/plugins/input/csv/build.py @@ -53,7 +53,6 @@ else: libraries.append('mapnik-wkt') if env['PLUGIN_LINKING'] == 'shared': - libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.insert(0,env['MAPNIK_NAME']) libraries.append(env['ICU_LIB_NAME']) diff --git a/plugins/input/gdal/build.py b/plugins/input/gdal/build.py index 4dc631dde..91f51b0c5 100644 --- a/plugins/input/gdal/build.py +++ b/plugins/input/gdal/build.py @@ -45,7 +45,6 @@ if env['RUNTIME_LINK'] == 'static': libraries = copy(plugin_env['LIBS']) if env['PLUGIN_LINKING'] == 'shared': - libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.insert(0,env['MAPNIK_NAME']) libraries.append(env['ICU_LIB_NAME']) diff --git a/plugins/input/geobuf/build.py b/plugins/input/geobuf/build.py index 45b092423..702512b1e 100644 --- a/plugins/input/geobuf/build.py +++ b/plugins/input/geobuf/build.py @@ -37,7 +37,6 @@ plugin_sources = Split( # Link Library to Dependencies libraries = [] libraries.append(env['ICU_LIB_NAME']) -libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('mapnik-json') if env['PLUGIN_LINKING'] == 'shared': diff --git a/plugins/input/geojson/build.py b/plugins/input/geojson/build.py index d0f8d2966..3453d6449 100644 --- a/plugins/input/geojson/build.py +++ b/plugins/input/geojson/build.py @@ -53,7 +53,6 @@ else: libraries.append('mapnik-json') if env['PLUGIN_LINKING'] == 'shared': - libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.insert(0,env['MAPNIK_NAME']) libraries.append(env['ICU_LIB_NAME']) diff --git a/plugins/input/ogr/build.py b/plugins/input/ogr/build.py index 1681d0b4d..acf487311 100644 --- a/plugins/input/ogr/build.py +++ b/plugins/input/ogr/build.py @@ -51,7 +51,6 @@ libraries = copy(plugin_env['LIBS']) plugin_env.Append(CXXFLAGS=cxxflags) if env['PLUGIN_LINKING'] == 'shared': - libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.insert(0,env['MAPNIK_NAME']) libraries.append(env['ICU_LIB_NAME']) diff --git a/plugins/input/pgraster/build.py b/plugins/input/pgraster/build.py index 9147d14f9..7936767ee 100644 --- a/plugins/input/pgraster/build.py +++ b/plugins/input/pgraster/build.py @@ -52,7 +52,6 @@ else: libraries = copy(plugin_env['LIBS']) if env['PLUGIN_LINKING'] == 'shared': - libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.insert(0,env['MAPNIK_NAME']) libraries.append(env['ICU_LIB_NAME']) diff --git a/plugins/input/postgis/build.py b/plugins/input/postgis/build.py index 8a7e891ca..8448a33e3 100644 --- a/plugins/input/postgis/build.py +++ b/plugins/input/postgis/build.py @@ -51,7 +51,6 @@ else: libraries = copy(plugin_env['LIBS']) if env['PLUGIN_LINKING'] == 'shared': - libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.insert(0,env['MAPNIK_NAME']) libraries.append(env['ICU_LIB_NAME']) diff --git a/plugins/input/raster/build.py b/plugins/input/raster/build.py index 2ca3c2e53..52bf9da3f 100644 --- a/plugins/input/raster/build.py +++ b/plugins/input/raster/build.py @@ -38,7 +38,6 @@ plugin_sources = Split( libraries = [] if env['PLUGIN_LINKING'] == 'shared': - libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.insert(0,env['MAPNIK_NAME']) libraries.append(env['ICU_LIB_NAME']) diff --git a/plugins/input/shape/build.py b/plugins/input/shape/build.py index 3f397d02e..0ddaef03c 100644 --- a/plugins/input/shape/build.py +++ b/plugins/input/shape/build.py @@ -47,7 +47,6 @@ plugin_env.Append(CXXFLAGS=cxxflags) plugin_env.Append(CPPDEFINES=cppdefines) if env['PLUGIN_LINKING'] == 'shared': - libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.insert(0,env['MAPNIK_NAME']) libraries.append(env['ICU_LIB_NAME']) diff --git a/plugins/input/sqlite/build.py b/plugins/input/sqlite/build.py index 53dfd8b37..b9c4a499a 100644 --- a/plugins/input/sqlite/build.py +++ b/plugins/input/sqlite/build.py @@ -42,7 +42,6 @@ if env['SQLITE_LINKFLAGS']: plugin_env.Append(LINKFLAGS=linkflags) if env['PLUGIN_LINKING'] == 'shared': - libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.insert(0,env['MAPNIK_NAME']) libraries.append(env['ICU_LIB_NAME']) diff --git a/plugins/input/topojson/build.py b/plugins/input/topojson/build.py index 6df31a3a6..e9a96b541 100644 --- a/plugins/input/topojson/build.py +++ b/plugins/input/topojson/build.py @@ -49,7 +49,6 @@ else: libraries.append('mapnik-json') if env['PLUGIN_LINKING'] == 'shared': - libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.insert(0,env['MAPNIK_NAME']) libraries.append(env['ICU_LIB_NAME']) diff --git a/src/build.py b/src/build.py index b68d33ef1..aa273ad96 100644 --- a/src/build.py +++ b/src/build.py @@ -52,14 +52,20 @@ libmapnik_defines = copy(lib_env['CPPDEFINES']) ABI_VERSION = env['ABI_VERSION'] enabled_imaging_libraries = [] + + filesystem = 'boost_filesystem%s' % env['BOOST_APPEND'] -regex = 'boost_regex%s' % env['BOOST_APPEND'] system = 'boost_system%s' % env['BOOST_APPEND'] +regex = 'boost_regex%s' % env['BOOST_APPEND'] + # clear out and re-set libs for this env # note: order matters on linux: see lorder | tsort -lib_env['LIBS'] = [filesystem, - regex] +lib_env['LIBS'] = [regex] + +if int(env['CXX_STD']) < 17 or env['USE_BOOST_FILESYSTEM']: + lib_env['LIBS'].append(filesystem) + lib_env['LIBS'].append(system) if env['COVERAGE']: lib_env.Append(LINKFLAGS='--coverage') @@ -95,7 +101,7 @@ if env['XMLPARSER'] == 'libxml2' and env['HAS_LIBXML2']: if '-DBOOST_REGEX_HAS_ICU' in env['CPPDEFINES']: lib_env['LIBS'].append('icui18n') -lib_env['LIBS'].append(system) + lib_env['LIBS'].append('harfbuzz') diff --git a/src/fs.cpp b/src/fs.cpp index a5da18d40..6139218b4 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -23,13 +23,7 @@ // mapnik #include #include - -#include -MAPNIK_DISABLE_WARNING_PUSH -#include -#include // for absolute, exists, etc -#include // for path, operator/ -MAPNIK_DISABLE_WARNING_POP +#include // stl #include @@ -41,45 +35,45 @@ namespace util { bool exists(std::string const& filepath) { #ifdef _WIN32 - return boost::filesystem::exists(mapnik::utf8_to_utf16(filepath)); + return fs::exists(mapnik::utf8_to_utf16(filepath)); #else - return boost::filesystem::exists(filepath); + return fs::exists(filepath); #endif } bool is_directory(std::string const& filepath) { #ifdef _WIN32 - return boost::filesystem::is_directory(mapnik::utf8_to_utf16(filepath)); + return fs::is_directory(mapnik::utf8_to_utf16(filepath)); #else - return boost::filesystem::is_directory(filepath); + return fs::is_directory(filepath); #endif } bool is_regular_file(std::string const& filepath) { #ifdef _WIN32 - return boost::filesystem::is_regular_file(mapnik::utf8_to_utf16(filepath)); + return fs::is_regular_file(mapnik::utf8_to_utf16(filepath)); #else - return boost::filesystem::is_regular_file(filepath); + return fs::is_regular_file(filepath); #endif } bool remove(std::string const& filepath) { #ifdef _WIN32 - return boost::filesystem::remove(mapnik::utf8_to_utf16(filepath)); + return fs::remove(mapnik::utf8_to_utf16(filepath)); #else - return boost::filesystem::remove(filepath); + return fs::remove(filepath); #endif } bool is_relative(std::string const& filepath) { #ifdef _WIN32 - boost::filesystem::path child_path(mapnik::utf8_to_utf16(filepath)); + fs::path child_path(mapnik::utf8_to_utf16(filepath)); #else - boost::filesystem::path child_path(filepath); + fs::path child_path(filepath); #endif return (!child_path.has_root_directory() && !child_path.has_root_name()); } @@ -87,48 +81,48 @@ bool is_relative(std::string const& filepath) std::string make_relative(std::string const& filepath, std::string const& base) { #ifdef _WIN32 - boost::filesystem::path absolute_path(mapnik::utf8_to_utf16(base)); + fs::path absolute_path(mapnik::utf8_to_utf16(base)); #else - boost::filesystem::path absolute_path(base); + fs::path absolute_path(base); #endif // support symlinks - if (boost::filesystem::is_symlink(absolute_path)) + if (fs::is_symlink(absolute_path)) { - absolute_path = boost::filesystem::read_symlink(absolute_path); + absolute_path = fs::read_symlink(absolute_path); } - return boost::filesystem::absolute(absolute_path.parent_path() / filepath).string(); + return fs::absolute(absolute_path.parent_path() / filepath).string(); } std::string make_absolute(std::string const& filepath, std::string const& base) { // TODO - normalize is now deprecated, use make_preferred? - return boost::filesystem::absolute(boost::filesystem::path(base) / filepath).string(); + return fs::absolute(fs::path(base) / filepath).string(); } std::string dirname(std::string const& filepath) { - boost::filesystem::path bp(filepath); + fs::path bp(filepath); return bp.parent_path().string(); } std::string basename(std::string const& value) { - boost::filesystem::path bp(value); + fs::path bp(value); return bp.filename().string(); } std::vector list_directory(std::string const& dir) { std::vector listing; - boost::filesystem::directory_iterator end_itr; + fs::directory_iterator end_itr; #ifdef _WIN32 std::wstring wide_dir(mapnik::utf8_to_utf16(dir)); - for (boost::filesystem::directory_iterator itr(wide_dir); itr != end_itr; ++itr) + for (fs::directory_iterator itr(wide_dir); itr != end_itr; ++itr) { listing.emplace_back(mapnik::utf16_to_utf8(itr->path().wstring())); } #else - for (boost::filesystem::directory_iterator itr(dir); itr != end_itr; ++itr) + for (fs::directory_iterator itr(dir); itr != end_itr; ++itr) { listing.emplace_back(itr->path().string()); } diff --git a/test/standalone/map_xml_test.cpp b/test/standalone/map_xml_test.cpp index 71c37cc76..35026d5f1 100644 --- a/test/standalone/map_xml_test.cpp +++ b/test/standalone/map_xml_test.cpp @@ -8,26 +8,36 @@ #include #include #include - -#include +#include +#include #include #include - -namespace bfs = boost::filesystem; +#include namespace { +static std::random_device entropy; + +std::string unique_mapnik_name() +{ + std::mt19937 gen(entropy()); + std::uniform_int_distribution<> distrib(0, 65535); + auto fmt = boost::format("mapnik-test-%1$04x-%2$04x-%3$04x-%4$04x") % distrib(gen) % distrib(gen) % distrib(gen) % + distrib(gen); + return fmt.str(); +} + class tmp_dir { private: - bfs::path m_path; + mapnik::fs::path m_path; public: tmp_dir() - : m_path(bfs::temp_directory_path() / bfs::unique_path("mapnik-test-%%%%-%%%%-%%%%-%%%%")) + : m_path(mapnik::fs::temp_directory_path() / unique_mapnik_name()) { - bfs::create_directories(m_path); + mapnik::fs::create_directories(m_path); } ~tmp_dir() @@ -36,21 +46,21 @@ class tmp_dir // running, which isn't necessarily an error as far as this // code is concerned - it just wants to delete everything // underneath the temporary directory. - boost::system::error_code err; + mapnik::error_code err; // catch all errors - we don't want to throw in the destructor try { // but loop while the path exists and the errors are // ignorable. - while (bfs::exists(m_path)) + while (mapnik::fs::exists(m_path)) { - bfs::remove_all(m_path, err); + mapnik::fs::remove_all(m_path, err); // for any non-ignorable error, there's not much we can // do from the destructor. it's in /tmp anyway, so it'll // get reclaimed next boot. - if (err && (err != boost::system::errc::no_such_file_or_directory)) + if (err && (err != std::errc::no_such_file_or_directory)) { break; } @@ -68,22 +78,22 @@ class tmp_dir } } - bfs::path path() const { return m_path; } + mapnik::fs::path path() const { return m_path; } }; -void compare_map(bfs::path xml) +void compare_map(mapnik::fs::path xml) { tmp_dir dir; mapnik::Map m(256, 256); REQUIRE(m.register_fonts("fonts", true)); - bfs::path abs_base = xml.parent_path(); + mapnik::fs::path abs_base = xml.parent_path(); // first, load the XML into a map object and save it. this // is a normalisation step to ensure that the file is in // whatever the current version of mapnik uses as the // standard indentation, quote style, etc... REQUIRE_NOTHROW(mapnik::load_map(m, xml.generic_string(), false, abs_base.generic_string())); - bfs::path test_map1 = dir.path() / "mapnik-temp-map1.xml"; + mapnik::fs::path test_map1 = dir.path() / "mapnik-temp-map1.xml"; REQUIRE_NOTHROW(mapnik::save_map(m, test_map1.generic_string())); // create a new map, load the one saved in the previous @@ -91,23 +101,24 @@ void compare_map(bfs::path xml) mapnik::Map new_map(256, 256); REQUIRE(new_map.register_fonts("fonts", true)); REQUIRE_NOTHROW(mapnik::load_map(new_map, test_map1.generic_string(), false, abs_base.generic_string())); - bfs::path test_map2 = dir.path() / "mapnik-temp-map2.xml"; + mapnik::fs::path test_map2 = dir.path() / "mapnik-temp-map2.xml"; REQUIRE_NOTHROW(mapnik::save_map(new_map, test_map2.generic_string())); // if all the information survived the load/save round-trip // then the two files ought to be identical. - REQUIRE(bfs::is_regular_file(test_map1)); - REQUIRE(bfs::is_regular_file(test_map2)); - REQUIRE(bfs::file_size(test_map1) == bfs::file_size(test_map2)); + REQUIRE(mapnik::fs::is_regular_file(test_map1)); + REQUIRE(mapnik::fs::is_regular_file(test_map2)); + REQUIRE(mapnik::fs::file_size(test_map1) == mapnik::fs::file_size(test_map2)); std::ifstream in_map1(test_map1.native()), in_map2(test_map2.native()); REQUIRE(std::equal(std::istream_iterator(in_map1), std::istream_iterator(), std::istream_iterator(in_map2))); } -void add_xml_files(bfs::path dir, std::vector& xml_files) +void add_xml_files(mapnik::fs::path dir, std::vector& xml_files) { - for (auto const& entry : boost::make_iterator_range(bfs::directory_iterator(dir), bfs::directory_iterator())) + for (auto const& entry : + boost::make_iterator_range(mapnik::fs::directory_iterator(dir), mapnik::fs::directory_iterator())) { auto path = entry.path(); if (path.extension().generic_string() == ".xml") @@ -117,7 +128,7 @@ void add_xml_files(bfs::path dir, std::vector& xml_files) } } -void load_map(mapnik::Map& m, bfs::path const& path) +void load_map(mapnik::Map& m, mapnik::fs::path const& path) { try { @@ -140,7 +151,7 @@ void load_map(mapnik::Map& m, bfs::path const& path) } // anonymous namespace #ifndef MAPNIK_STATIC_PLUGINS const bool registered = - mapnik::datasource_cache::instance().register_datasources((bfs::path("plugins") / "input").generic_string()); + mapnik::datasource_cache::instance().register_datasources((mapnik::fs::path("plugins") / "input").generic_string()); #endif TEST_CASE("map xml I/O") { @@ -156,8 +167,8 @@ TEST_CASE("map xml I/O") SECTION("good maps") { - std::vector good_maps; - add_xml_files(bfs::path("test") / "data" / "good_maps", good_maps); + std::vector good_maps; + add_xml_files(mapnik::fs::path("test") / "data" / "good_maps", good_maps); for (auto const& path : good_maps) { @@ -176,7 +187,7 @@ TEST_CASE("map xml I/O") SECTION("duplicate styles only throw in strict mode") { std::string duplicate_stylename( - (bfs::path("test") / "data" / "broken_maps" / "duplicate_stylename.xml").generic_string()); + (mapnik::fs::path("test") / "data" / "broken_maps" / "duplicate_stylename.xml").generic_string()); CAPTURE(duplicate_stylename); mapnik::Map m(256, 256); REQUIRE(m.register_fonts("fonts", true)); @@ -188,9 +199,9 @@ TEST_CASE("map xml I/O") SECTION("broken maps") { - std::vector broken_maps; - add_xml_files(bfs::path("test") / "data" / "broken_maps", broken_maps); - broken_maps.emplace_back(bfs::path("test") / "data" / "broken_maps" / "does_not_exist.xml"); + std::vector broken_maps; + add_xml_files(mapnik::fs::path("test") / "data" / "broken_maps", broken_maps); + broken_maps.emplace_back(mapnik::fs::path("test") / "data" / "broken_maps" / "does_not_exist.xml"); for (auto const& path : broken_maps) { diff --git a/test/unit/data/test.xml b/test/unit/data/test.xml new file mode 100644 index 000000000..1a45e4d34 --- /dev/null +++ b/test/unit/data/test.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + 1 + rgb(0,0,0) + 1 + rgb(0,0,0) + 0.5 + 1 + + + + diff --git a/test/unit/imaging/image_io_test.cpp b/test/unit/imaging/image_io_test.cpp index 3beaf1264..9ce008d80 100644 --- a/test/unit/imaging/image_io_test.cpp +++ b/test/unit/imaging/image_io_test.cpp @@ -13,17 +13,19 @@ #endif #include + MAPNIK_DISABLE_WARNING_PUSH #include #include -#include #include MAPNIK_DISABLE_WARNING_POP + +#include #include inline void make_directory(std::string const& dir) { - boost::filesystem::create_directories(dir); + mapnik::fs::create_directories(dir); } namespace { diff --git a/test/unit/renderer/cairo_io.cpp b/test/unit/renderer/cairo_io.cpp index 4f95f0d49..64b65bbd3 100644 --- a/test/unit/renderer/cairo_io.cpp +++ b/test/unit/renderer/cairo_io.cpp @@ -1,14 +1,8 @@ #include "catch.hpp" #include +#include #include - -#include -MAPNIK_DISABLE_WARNING_PUSH -#include -#include -MAPNIK_DISABLE_WARNING_POP - #include #if defined(HAVE_CAIRO) @@ -22,7 +16,7 @@ TEST_CASE("cairo_io") SECTION("save_to_cairo_file - SVG") { std::string directory_name("/tmp/mapnik-tests/"); - boost::filesystem::create_directories(directory_name); + mapnik::fs::create_directories(directory_name); REQUIRE(mapnik::util::exists(directory_name)); std::string output_file(directory_name + "test_save_to_cairo_file.svg"); diff --git a/test/unit/run.cpp b/test/unit/run.cpp index 94836d7ed..dd9a8b363 100644 --- a/test/unit/run.cpp +++ b/test/unit/run.cpp @@ -3,9 +3,9 @@ #include #include +#include #include #include -#include #include "cleanup.hpp" // run_cleanup() @@ -43,7 +43,7 @@ int main(int argc, char** argv) std::clog << "Could not find " << working_dir << "\n"; return -1; } - boost::filesystem::current_path(working_dir); + mapnik::fs::current_path(working_dir); } if (result == 0) diff --git a/test/visual/CMakeLists.txt b/test/visual/CMakeLists.txt index 0c0c306fc..c459a4ff6 100644 --- a/test/visual/CMakeLists.txt +++ b/test/visual/CMakeLists.txt @@ -7,11 +7,11 @@ add_executable(mapnik-test-visual target_link_libraries(mapnik-test-visual PRIVATE Catch2::Catch2 Boost::program_options - Boost::filesystem mapnik::mapnik mapnik::agg ICU::data ICU::i18n ICU::uc # needed for the static build (TODO: why isn't this correctly propagated from mapnik::mapnik?) ) + # needed for cleanup.hpp target_include_directories(mapnik-test-visual PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..") diff --git a/test/visual/config.hpp b/test/visual/config.hpp index 16d6931cf..a0d04cde5 100644 --- a/test/visual/config.hpp +++ b/test/visual/config.hpp @@ -28,10 +28,7 @@ #include #include #include - -// boost -#include - +#include #include namespace visual_tests { @@ -76,8 +73,8 @@ struct result map_size size; map_size tiles; double scale_factor; - boost::filesystem::path actual_image_path; - boost::filesystem::path reference_image_path; + mapnik::fs::path actual_image_path; + mapnik::fs::path reference_image_path; std::string error_message; unsigned diff; std::chrono::high_resolution_clock::duration duration; diff --git a/test/visual/renderer.hpp b/test/visual/renderer.hpp index f446fe794..bbc97c625 100644 --- a/test/visual/renderer.hpp +++ b/test/visual/renderer.hpp @@ -57,8 +57,7 @@ #include #endif -// boost -#include +#include namespace visual_tests { @@ -70,7 +69,7 @@ struct raster_renderer_base static constexpr const char* ext = ".png"; static constexpr const bool support_tiles = true; - unsigned compare(image_type const& actual, boost::filesystem::path const& reference) const + unsigned compare(image_type const& actual, mapnik::fs::path const& reference) const { std::unique_ptr reader(mapnik::get_image_reader(reference.string(), "png")); if (!reader.get()) @@ -84,7 +83,7 @@ struct raster_renderer_base return mapnik::compare(actual, reference_image, 0, true); } - void save(image_type const& image, boost::filesystem::path const& path) const + void save(image_type const& image, mapnik::fs::path const& path) const { mapnik::save_to_file(image, path.string(), "png32"); } @@ -96,7 +95,7 @@ struct vector_renderer_base static constexpr const bool support_tiles = false; - unsigned compare(image_type const& actual, boost::filesystem::path const& reference) const + unsigned compare(image_type const& actual, mapnik::fs::path const& reference) const { std::ifstream stream(reference.string().c_str(), std::ios_base::in | std::ios_base::binary); if (!stream) @@ -107,7 +106,7 @@ struct vector_renderer_base return std::max(actual.size(), expected.size()) - std::min(actual.size(), expected.size()); } - void save(image_type const& image, boost::filesystem::path const& path) const + void save(image_type const& image, mapnik::fs::path const& path) const { std::ofstream file(path.string().c_str(), std::ios::out | std::ios::trunc | std::ios::binary); if (!file) @@ -302,7 +301,7 @@ class renderer using renderer_type = Renderer; using image_type = typename Renderer::image_type; - renderer(boost::filesystem::path const& _output_dir, boost::filesystem::path const& _reference_dir, bool _overwrite) + renderer(mapnik::fs::path const& _output_dir, mapnik::fs::path const& _reference_dir, bool _overwrite) : ren() , output_dir(_output_dir) , reference_dir(_reference_dir) @@ -340,8 +339,8 @@ class renderer map_size const& tiles, double scale_factor) const { - boost::filesystem::path reference = reference_dir / image_file_name(name, size, tiles, scale_factor, true); - bool reference_exists = boost::filesystem::exists(reference); + mapnik::fs::path reference = reference_dir / image_file_name(name, size, tiles, scale_factor, true); + bool reference_exists = mapnik::fs::exists(reference); result res; res.state = reference_exists ? STATE_OK : STATE_OVERWRITE; @@ -355,8 +354,8 @@ class renderer if (res.diff) { - boost::filesystem::create_directories(output_dir); - boost::filesystem::path path = output_dir / image_file_name(name, size, tiles, scale_factor, false); + mapnik::fs::create_directories(output_dir); + mapnik::fs::path path = output_dir / image_file_name(name, size, tiles, scale_factor, false); res.actual_image_path = path; res.state = STATE_FAIL; ren.save(image, path); @@ -394,8 +393,8 @@ class renderer } const Renderer ren; - const boost::filesystem::path output_dir; - const boost::filesystem::path reference_dir; + const mapnik::fs::path output_dir; + const mapnik::fs::path reference_dir; const bool overwrite; }; diff --git a/test/visual/report.cpp b/test/visual/report.cpp index cb46e2e34..8d0eb41ae 100644 --- a/test/visual/report.cpp +++ b/test/visual/report.cpp @@ -172,7 +172,7 @@ void console_short_report::report(result const& r) } } -void html_report::report(result const& r, boost::filesystem::path const& output_dir) +void html_report::report(result const& r, mapnik::fs::path const& output_dir) { if (r.state == STATE_ERROR) { @@ -180,8 +180,7 @@ void html_report::report(result const& r, boost::filesystem::path const& output_ } else if (r.state == STATE_FAIL) { - using namespace boost::filesystem; - + using namespace mapnik::fs; path reference = output_dir / r.reference_image_path.filename(); path actual = output_dir / r.actual_image_path.filename(); @@ -238,7 +237,7 @@ constexpr const char* html_footer = R"template( )template"; -void html_report::summary(result_list const& results, boost::filesystem::path const& output_dir) +void html_report::summary(result_list const& results, mapnik::fs::path const& output_dir) { s << html_header; @@ -253,11 +252,11 @@ void html_report::summary(result_list const& results, boost::filesystem::path co s << html_footer; } -void html_summary(result_list const& results, boost::filesystem::path output_dir) +void html_summary(result_list const& results, mapnik::fs::path output_dir) { - boost::filesystem::path html_root = output_dir / "visual-test-results"; - boost::filesystem::create_directories(html_root); - boost::filesystem::path html_report_path = html_root / "index.html"; + mapnik::fs::path html_root = output_dir / "visual-test-results"; + mapnik::fs::create_directories(html_root); + mapnik::fs::path html_report_path = html_root / "index.html"; std::clog << "View failure report at " << html_report_path << "\n"; std::ofstream output_file(html_report_path.string()); html_report report(output_file); diff --git a/test/visual/report.hpp b/test/visual/report.hpp index a496a0056..b0c40aee3 100644 --- a/test/visual/report.hpp +++ b/test/visual/report.hpp @@ -76,8 +76,8 @@ class html_report : s(_s) {} - void report(result const& r, boost::filesystem::path const& output_dir); - void summary(result_list const& results, boost::filesystem::path const& output_dir); + void report(result const& r, mapnik::fs::path const& output_dir); + void summary(result_list const& results, mapnik::fs::path const& output_dir); protected: std::ostream& s; @@ -119,7 +119,7 @@ class summary_visitor result_list const& result_; }; -void html_summary(result_list const& results, boost::filesystem::path output_dir); +void html_summary(result_list const& results, mapnik::fs::path output_dir); } // namespace visual_tests diff --git a/test/visual/run.cpp b/test/visual/run.cpp index a352f2c34..cab19c168 100644 --- a/test/visual/run.cpp +++ b/test/visual/run.cpp @@ -36,6 +36,9 @@ #include #endif +#include +#include + #ifdef MAPNIK_LOG using log_levels_map = std::map; @@ -48,10 +51,23 @@ log_levels_map log_levels{{"debug", mapnik::logger::severity_type::debug}, using namespace visual_tests; namespace po = boost::program_options; -runner::renderer_container - create_renderers(po::variables_map const& args, boost::filesystem::path const& output_dir, bool force_append = false) +namespace { + +static std::random_device entropy; + +std::string unique_name() { - boost::filesystem::path reference_dir(args["images-dir"].as()); + std::mt19937 gen(entropy()); + std::uniform_int_distribution<> distrib(0, 65535); + auto fmt = boost::format("%1$04x-%2$04x-%3$04x-%4$04x") % distrib(gen) % distrib(gen) % distrib(gen) % distrib(gen); + return fmt.str(); +} +} // namespace + +runner::renderer_container + create_renderers(po::variables_map const& args, mapnik::fs::path const& output_dir, bool force_append = false) +{ + mapnik::fs::path reference_dir(args["images-dir"].as()); bool overwrite = args.count("overwrite"); runner::renderer_container renderers; @@ -185,11 +201,11 @@ int main(int argc, char** argv) mapnik::freetype_engine::register_fonts(vm["fonts"].as(), true); mapnik::datasource_cache::instance().register_datasources(vm["plugins"].as()); - boost::filesystem::path output_dir(vm["output-dir"].as()); + mapnik::fs::path output_dir(vm["output-dir"].as()); if (vm.count("unique-subdir")) { - output_dir /= boost::filesystem::unique_path(); + output_dir /= unique_name(); } config defaults; diff --git a/test/visual/runner.cpp b/test/visual/runner.cpp index d538e4522..9394d1b47 100644 --- a/test/visual/runner.cpp +++ b/test/visual/runner.cpp @@ -149,8 +149,8 @@ runner::runner(runner::path_type const& styles_dir, result_list runner::test_all(report_type& report) const { - boost::filesystem::directory_iterator begin(styles_dir_); - boost::filesystem::directory_iterator end; + mapnik::fs::directory_iterator begin(styles_dir_); + mapnik::fs::directory_iterator end; std::vector files(begin, end); return test_parallel(files, report, jobs_); } diff --git a/test/visual/runner.hpp b/test/visual/runner.hpp index e33de2c94..1530640e0 100644 --- a/test/visual/runner.hpp +++ b/test/visual/runner.hpp @@ -31,7 +31,7 @@ namespace visual_tests { class runner { - using path_type = boost::filesystem::path; + using path_type = mapnik::fs::path; using files_iterator = std::vector::const_iterator; public: diff --git a/utils/mapnik-index/build.py b/utils/mapnik-index/build.py index 9bddaf196..c08a3cc43 100644 --- a/utils/mapnik-index/build.py +++ b/utils/mapnik-index/build.py @@ -40,8 +40,7 @@ source = Split( headers = env['CPPPATH'] boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND'] -boost_system = 'boost_system%s' % env['BOOST_APPEND'] -libraries = [env['MAPNIK_NAME'], boost_program_options, boost_system] +libraries = [env['MAPNIK_NAME'], boost_program_options] # need on linux: https://github.com/mapnik/mapnik/issues/3145 libraries.append('mapnik-json') libraries.append('mapnik-wkt') diff --git a/utils/ogrindex/build.py b/utils/ogrindex/build.py index 68a4c0452..4142f3152 100644 --- a/utils/ogrindex/build.py +++ b/utils/ogrindex/build.py @@ -39,7 +39,6 @@ program_env['LIBS'] = [env['PLUGINS']['ogr']['lib']] # Link Library to Dependencies program_env['LIBS'].append(env['MAPNIK_NAME']) program_env['LIBS'].append(env['ICU_LIB_NAME']) -program_env['LIBS'].append('boost_system%s' % env['BOOST_APPEND']) program_env['LIBS'].append('boost_program_options%s' % env['BOOST_APPEND']) if env['RUNTIME_LINK'] == 'static': diff --git a/utils/pgsql2sqlite/build.py b/utils/pgsql2sqlite/build.py index cc0674b24..265933899 100644 --- a/utils/pgsql2sqlite/build.py +++ b/utils/pgsql2sqlite/build.py @@ -65,9 +65,6 @@ libraries.extend([boost_program_options,'sqlite3',env['MAPNIK_NAME'],'icuuc']) if env.get('BOOST_LIB_VERSION_FROM_HEADER'): boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1]) - if boost_version_from_header >= 50: - boost_system = 'boost_system%s' % env['BOOST_APPEND'] - libraries.extend([boost_system]) if env['SQLITE_LINKFLAGS']: program_env.Append(LINKFLAGS=env['SQLITE_LINKFLAGS']) diff --git a/utils/shapeindex/build.py b/utils/shapeindex/build.py index 2a4c2ab07..dbd178a03 100644 --- a/utils/shapeindex/build.py +++ b/utils/shapeindex/build.py @@ -38,8 +38,7 @@ source = Split( headers = ['#plugins/input/shape'] + env['CPPPATH'] boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND'] -boost_system = 'boost_system%s' % env['BOOST_APPEND'] -libraries = [env['MAPNIK_NAME'], boost_program_options, boost_system] +libraries = [env['MAPNIK_NAME'], boost_program_options] libraries.append(env['ICU_LIB_NAME']) if env['RUNTIME_LINK'] == 'static': libraries.extend(copy(env['LIBMAPNIK_LIBS']))