diff --git a/docs/changelog.md b/docs/changelog.md index 52150ca39..37a4ffa32 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -10,6 +10,9 @@ Requires libvips v8.16.0 * Expose WebP `smartDeblock` output option. +* Support `info.size` on wide-character systems via upgrade to C++17. + [#3943](https://github.com/lovell/sharp/issues/3943) + * Ensure `background` metadata can be parsed by `color` package. [#4090](https://github.com/lovell/sharp/issues/4090) diff --git a/docs/install.md b/docs/install.md index 8a897589f..8d16fe1d9 100644 --- a/docs/install.md +++ b/docs/install.md @@ -38,7 +38,7 @@ Ready-compiled sharp and libvips binaries are provided for use on the most commo * macOS x64 (>= 10.15) * macOS ARM64 -* Linux ARM (glibc >= 2.28) +* Linux ARM (glibc >= 2.31) * Linux ARM64 (glibc >= 2.26, musl >= 1.2.2) * Linux ppc64 (glibc >= 2.31) * Linux s390x (glibc >= 2.31) @@ -111,7 +111,7 @@ environment variables. Building from source requires: -* C++11 compiler +* C++17 compiler * [node-addon-api](https://www.npmjs.com/package/node-addon-api) version 7+ * [node-gyp](https://github.com/nodejs/node-gyp#installation) version 9+ and its dependencies diff --git a/npm/linux-arm/package.json b/npm/linux-arm/package.json index 31ab2b75b..91b322dd8 100644 --- a/npm/linux-arm/package.json +++ b/npm/linux-arm/package.json @@ -15,7 +15,7 @@ }, "preferUnplugged": true, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.1.0-rc3" + "@img/sharp-libvips-linux-arm": "1.1.0-rc3.1" }, "files": [ "lib" @@ -32,7 +32,7 @@ "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "config": { - "glibc": ">=2.28" + "glibc": ">=2.31" }, "os": [ "linux" diff --git a/package.json b/package.json index a41d2ff67..bcf1f8c0d 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,7 @@ "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.1.0-rc3", "@img/sharp-libvips-darwin-x64": "1.1.0-rc3", - "@img/sharp-libvips-linux-arm": "1.1.0-rc3", + "@img/sharp-libvips-linux-arm": "1.1.0-rc3.1", "@img/sharp-libvips-linux-arm64": "1.1.0-rc3", "@img/sharp-libvips-linux-ppc64": "1.1.0-rc3", "@img/sharp-libvips-linux-s390x": "1.1.0-rc3", @@ -178,7 +178,7 @@ "jsdoc-to-markdown": "^9.0.5", "license-checker": "^25.0.1", "mocha": "^10.8.2", - "node-addon-api": "8.1.0", + "node-addon-api": "^8.2.1", "nyc": "^17.1.0", "prebuild": "^13.0.1", "semistandard": "^17.0.0", diff --git a/src/binding.gyp b/src/binding.gyp index 5049d8cad..8292b64b9 100644 --- a/src/binding.gyp +++ b/src/binding.gyp @@ -45,6 +45,9 @@ 'Release': { 'msvs_settings': { 'VCCLCompilerTool': { + "AdditionalOptions": [ + "/std:c++17" + ], 'ExceptionHandling': 1, 'Optimization': 1, 'WholeProgramOptimization': 'true' @@ -172,6 +175,7 @@ '-l:libvips-cpp.so.<(vips_version)' ], 'ldflags': [ + '-lstdc++fs', '-Wl,-s', '-Wl,--disable-new-dtags', '-Wl,-z,nodelete', @@ -207,13 +211,13 @@ }] ], 'cflags_cc': [ - '-std=c++0x', + '-std=c++17', '-fexceptions', '-Wall', '-Os' ], 'xcode_settings': { - 'CLANG_CXX_LANGUAGE_STANDARD': 'c++11', + 'CLANG_CXX_LANGUAGE_STANDARD': 'c++17', 'MACOSX_DEPLOYMENT_TARGET': '10.15', 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES', 'GCC_ENABLE_CPP_RTTI': 'YES', @@ -234,6 +238,9 @@ ['OS == "win"', { 'msvs_settings': { 'VCCLCompilerTool': { + "AdditionalOptions": [ + "/std:c++17" + ], 'ExceptionHandling': 1, 'Optimization': 1, 'WholeProgramOptimization': 'true' diff --git a/src/common.h b/src/common.h index f079de1e0..67d864115 100644 --- a/src/common.h +++ b/src/common.h @@ -20,13 +20,9 @@ #error "libvips version 8.16.0+ is required - please see https://sharp.pixelplumbing.com/install" #endif -#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6))) -#error "GCC version 4.6+ is required for C++11 features - please see https://sharp.pixelplumbing.com/install" -#endif - -#if (defined(__clang__) && defined(__has_feature)) -#if (!__has_feature(cxx_range_for)) -#error "clang version 3.0+ is required for C++11 features - please see https://sharp.pixelplumbing.com/install" +#if defined(__has_include) +#if !__has_include() +#error "C++17 compiler required - please see https://sharp.pixelplumbing.com/install" #endif #endif diff --git a/src/pipeline.cc b/src/pipeline.cc index 4f8424725..cd9294494 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -20,17 +21,6 @@ #include "operations.h" #include "pipeline.h" -#ifdef _WIN32 -#define STAT64_STRUCT __stat64 -#define STAT64_FUNCTION _stat64 -#elif defined(_LARGEFILE64_SOURCE) -#define STAT64_STRUCT stat64 -#define STAT64_FUNCTION stat64 -#else -#define STAT64_STRUCT stat -#define STAT64_FUNCTION stat -#endif - class PipelineWorker : public Napi::AsyncWorker { public: PipelineWorker(Napi::Function callback, PipelineBaton *baton, @@ -1306,9 +1296,11 @@ class PipelineWorker : public Napi::AsyncWorker { Callback().Call(Receiver().Value(), { env.Null(), data, info }); } else { // Add file size to info - struct STAT64_STRUCT st; - if (STAT64_FUNCTION(baton->fileOut.data(), &st) == 0) { - info.Set("size", static_cast(st.st_size)); + if (baton->formatOut != "dz" || sharp::IsDzZip(baton->fileOut)) { + try { + uint32_t const size = static_cast(std::filesystem::file_size(baton->fileOut)); + info.Set("size", size); + } catch (...) {} } Callback().Call(Receiver().Value(), { env.Null(), info }); } diff --git a/test/unit/tile.js b/test/unit/tile.js index d1b3d831c..53e91bf5d 100644 --- a/test/unit/tile.js +++ b/test/unit/tile.js @@ -483,7 +483,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); fs.stat(path.join(directory, 'ImageProperties.xml'), function (err, stat) { if (err) throw err; assert.strictEqual(true, stat.isFile()); @@ -509,7 +509,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); assertZoomifyTiles(directory, 256, 1, done); }); }); @@ -530,7 +530,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); assertZoomifyTiles(directory, 256, 5, done); }); }); @@ -551,7 +551,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); assertZoomifyTiles(directory, 256, 13, done); }); }); @@ -575,7 +575,7 @@ describe('Tile', function () { assert.strictEqual(2048, info.width); assert.strictEqual(1536, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); assertZoomifyTiles(directory, 256, 4, done); }); }); @@ -594,7 +594,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); fs.stat(path.join(directory, '0', '0', '0.jpg'), function (err, stat) { if (err) throw err; assert.strictEqual(true, stat.isFile()); @@ -621,7 +621,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); const sample = path.join(directory, '0', '0', '0.jpg'); sharp(sample).metadata(function (err, metadata) { if (err) throw err; @@ -658,7 +658,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); const sample = path.join(directory, '0', '0', '0.png'); sharp(sample).metadata(function (err, metadata) { if (err) throw err; @@ -696,7 +696,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); const sample = path.join(directory, '0', '0', '0.webp'); sharp(sample).metadata(function (err, metadata) { if (err) throw err; @@ -732,8 +732,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); - + assert.strictEqual(undefined, info.size); assertGoogleTiles(directory, 256, 1, done); }); }); @@ -754,8 +753,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); - + assert.strictEqual(undefined, info.size); assertGoogleTiles(directory, 256, 5, done); }); }); @@ -779,8 +777,7 @@ describe('Tile', function () { assert.strictEqual(2809, info.width); assert.strictEqual(2074, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); - + assert.strictEqual(undefined, info.size); assertGoogleTiles(directory, 256, 5, done); }); }); @@ -800,7 +797,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); fixtures.assertSimilar(fixtures.expected('tile_centered.jpg'), fs.readFileSync(path.join(directory, '0', '0', '0.jpg')), done); }); }); @@ -820,7 +817,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); fixtures.assertSimilar(fixtures.expected('tile_centered.jpg'), fs.readFileSync(path.join(directory, '0', '0', '0.jpg')), done); }); }); @@ -842,7 +839,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); const infoJson = require(path.join(directory, 'info.json')); assert.strictEqual('http://iiif.io/api/image/2/context.json', infoJson['@context']); assert.strictEqual(`${id}/${name}`, infoJson['@id']); @@ -872,7 +869,7 @@ describe('Tile', function () { assert.strictEqual(2725, info.width); assert.strictEqual(2225, info.height); assert.strictEqual(3, info.channels); - assert.strictEqual('number', typeof info.size); + assert.strictEqual(undefined, info.size); const infoJson = require(path.join(directory, 'info.json')); assert.strictEqual('http://iiif.io/api/image/3/context.json', infoJson['@context']); assert.strictEqual('ImageService3', infoJson.type);