Closed kayahr closed 1 year ago
How do you go about doing this exactly? We require both node-canvas and Sharp, but we are not familiar with c++?
@vito-vanhecke I wrote "Switching is pretty much straight forward" but this was meant for the node-canvas authors. For a node-canvas user (especially when you are not familiar with C++ build stuff on Windows) it is not that simple I'm afraid.
@kayahr a pull request would be much welcome, I think to the prebuilds
branch (@zbjornson has been doing them lately)
Are there plans for these prebuilds? We do require both sharp and node-canvas...
@zbjornson Are you planning these prebuilds? Or is there a workaround? Not using sharp, not using canvas?
I don't think that compiling with UCRT64 will help here. I compiled canvas with @kayahr 's instruction. Requiring both of them does not produce any error, however using them will give the following error:
(process:3040): GLib-GObject-WARNING **: 17:35:30.162: cannot register existing type 'PangoFontMap'
(process:3040): GLib-GObject-WARNING **: 17:35:30.162: cannot add private field to invalid (non-instantiatable) type '<invalid>'
(process:3040): GLib-GObject-WARNING **: 17:35:30.162: cannot register existing type 'GListModel'
(process:3040): GLib-GObject-CRITICAL **: 17:35:30.162: g_type_interface_add_prerequisite: assertion 'G_TYPE_IS_INTERFACE (interface_type)' failed
(process:3040): GLib-CRITICAL **: 17:35:30.162: g_once_init_leave: assertion 'result != 0' failed
(process:3040): GLib-GObject-CRITICAL **: 17:35:30.162: g_type_add_interface_static: assertion 'G_TYPE_IS_INSTANTIATABLE (instance_type)' failed
(process:3040): GLib-CRITICAL **: 17:35:30.162: g_once_init_leave: assertion 'result != 0' failed
(process:3040): GLib-GObject-CRITICAL **: 17:35:30.162: g_type_register_static: assertion 'parent_type > 0' failed
(process:3040): GLib-CRITICAL **: 17:35:30.162: g_once_init_leave: assertion 'result != 0' failed
(process:3040): GLib-GObject-CRITICAL **: 17:35:30.162: g_type_register_static: assertion 'parent_type > 0' failed
(process:3040): GLib-GObject-WARNING **: 17:35:30.162: cannot register existing type 'PangoCairoFontMap'
Neither sharp nor node-canvas seem to catch this error, i.e the promise is never reject nor resolved. The process is then just "stuck".
Not sure what the next steps should be debug this.
I've seen this issue here as well: https://github.com/lovell/sharp/issues/2531. Changing the require order does not seem to help at all.
@suniltandan It's possible this may relate to https://github.com/libvips/libvips/issues/3275 - the forthcoming sharp v0.32.0 will include the fix if so.
I am having this issue with https://github.com/maptiler/tileserver-gl . We just got maplibre-native binaries that work with windows, but there is a conflict between sharp and canvas that prevents it from working on windows. sharp 0.32.0 was just released, but does not appear to fix this issue like suggested in the post above.
We have found we can downgrade sharp to 0.30.7 and it works, but I am told the newer versions fail because of the issue mentioned here.
@acalcutt Are you compiling your own canvas
binaries from source using the instructions provided? If so, do you see the exact sameg_type_interface_add_prerequisite: assertion 'G_TYPE_IS_INTERFACE (interface_type)' failed
error?
We are just using the binary provided by the canvas 2.11.0 npm package, so we are not building our own copy. We are also using the sharp 0.32.0 npm package.
If sharp is imported before canvas, the error looks like this
If canvas is imported before sharp, the error looks like this
If canvas is imported before sharp and we supply custom made UCRT64 node-canvas binary, made like https://github.com/Automattic/node-canvas/pull/2219, it runs
One thing it's worthy to mention is: sharp
uses the official libvips
Windows binaries located here. These are cross-compiled using MXE, and they seem to be the source of most trouble we are having with canvas
. I tried to build both canvas
and sharp
with MSYS2 libraries (and using the MSYS2 libvips
libraries), and they worked very well. Maybe in the future we can find a build configuration (maybe cross compile canvas
too?) that is more compatible with these binaries than the MSYS2 build (but building it with MSYS2 UCRT64 increases the compatibility a lot).
@tdcosta100 This is the whole point of this issue. Both sharp and canvas are compiled with MSYS2 but they use a different C Runtime. Sharp uses the newer and more universal UCRT (Used by MSYS2 UCRT64) while the pre-built canvas binary uses the very old MSVCRT (Used by MSYS2 Mingw64). These runtimes are not compatible and therefor the two libraries cannot be used together. This can be fixed by canvas by switching to UCRT as well as I described in this issue. I think it is not a good solution to convince the sharp developers to downgrade their build to the old MSVCRT because UCRT is the modern way to go on Windows.
My point is switching to MSYS UCRT64 make it compatible, but doesn't fix all errors, like @acalcutt demonstrated. But doing this allows at least the coexistence of the two libraries, which was impossible with MSVCRT. I think it's possible to find a build scheme that makes it fully compatible, just don't know how yet (possibly using MXE too, but maybe there's a solution using MSYS2).
I actually don't see a demonstrated problem. I understood that Acalcutt tried running canvas and sharp with the pre-built binaries and it didn't work but with a custom canvas build using UCRT64 it worked. That is also my experience.
Okay then, you can try loading canvas after sharp and tell me if even with MSYS2 UCRT64 build it works. To me it only worked when I built sharp also with MSYS2 UCRT64. But if I load canvas before sharp, then it works.
Like @tdcosta100 mentioned, there is still an error when sharp is imported before canvas even with the change to UCRT64 , it looks like the first error
This is somewhat a problem for us, since we need to use the oposite order in linux due to https://github.com/lovell/sharp/issues/371 and imports are hard to change the order of since they need to be top level.
Hey all, closing this because I just released 2.11.2 which uses UCRT64. I'm not sure I understand the remaining problems with sharp, but open to anything that works. The only upcoming changes to prebuilds is that we're going to use NAPI and possibly make some of the libraries static.
Thanks for adding this :-)
For anyone in the future (or the past), I solved the conflict by using sharp@0.31.3 with canvas@2.11.2.
There are two issues at play here.
1) including/using both (solved)
2) including/using both AND render an svg with text
Please run the following example in a cmd terminal (debugging in vscode won't show errors)
install latest deps:
"canvas": "2.11.2",
"sharp": "0.32.3"
const canvas = require('canvas')
const sharp = require('sharp')
async function test() {
const c = canvas.createCanvas(200, 200)
// 1. comment next line to make it work
const ctx = c.getContext('2d')
const collectionNameText = Buffer.from(`
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
<!-- 2. empty next tag to make it work -->
<text>hello</text>
</svg>
`.trim())
const buf = await sharp(collectionNameText)
.toBuffer() // Process will hang here
console.log(buf)
}
test()
observe errors:
(process:22100): GLib-GObject-CRITICAL **: 21:44:50.733: cannot register existing type 'GInitable'
(process:22100): GLib-GObject-CRITICAL **: 21:44:50.739: g_type_interface_add_prerequisite: assertion 'G_TYPE_IS_INTERFACE (interface_type)' failed
(process:22100): GLib-CRITICAL **: 21:44:50.739: g_once_init_leave: assertion 'result != 0' failed
(process:22100): GLib-GObject-CRITICAL **: 21:44:50.742: cannot register existing type 'PangoFontMap'
(process:22100): GLib-GObject-CRITICAL **: 21:44:50.742: cannot add private field to invalid (non-instantiatable) type '<invalid>'
(process:22100): GLib-GObject-CRITICAL **: 21:44:50.743: cannot register existing type 'GListModel'
(process:22100): GLib-GObject-CRITICAL **: 21:44:50.743: g_type_interface_add_prerequisite: assertion 'G_TYPE_IS_INTERFACE (interface_type)' failed
(process:22100): GLib-CRITICAL **: 21:44:50.743: g_once_init_leave: assertion 'result != 0' failed
(process:22100): GLib-GObject-CRITICAL **: 21:44:50.744: g_type_add_interface_static: assertion 'G_TYPE_IS_INSTANTIATABLE (instance_type)' failed
(process:22100): GLib-CRITICAL **: 21:44:50.744: g_once_init_leave: assertion 'result != 0' failed
(process:22100): GLib-GObject-CRITICAL **: 21:44:50.745: g_type_register_static: assertion 'parent_type > 0' failed
(process:22100): GLib-GObject-CRITICAL **: 21:44:50.745: cannot add private field to invalid (non-instantiatable) type '<invalid>'
Now note the two comments in the above code: following the instructions of either of the two will make it run with no errors. This was already mentioned here https://github.com/lovell/sharp/issues/2531 and it's likely the issue mentioned above https://github.com/Automattic/node-canvas/issues/2155#issuecomment-1422424184
Issue or Feature
The pre-built Windows binary of node-canvas currently uses DLLs from MSYS2 MinGW64 which uses the old MSVCRT runtime. node-canvas would be more portable and more compatible to other native libraries like Sharp when it would use the universal runtime instead.
See https://learn.microsoft.com/en-us/cpp/porting/upgrade-your-code-to-the-universal-crt?view=msvc-170 and https://www.msys2.org/docs/environments/#msvcrt-vs-ucrt
Switching is pretty much straight forward:
I guess a pull request makes no sense here because your build environment for the pre-built windows binaries seems to be manually installed.