文章特色图像是Nalphanne作品

canvas已经是咱们的老朋友了。这个包成功让咱们水了两篇文章,干脆专门开个tag算了。

不过也是有趣,加上这篇文章,canvasWindows、Mac OS、Linux(CentOS)的编译坑都要给我碰全了。不过,和之前的不同,这次的问题似乎是特别新鲜的大瓜。

按照惯例先从报错开始:

第一个错误就是Mac上安装canvas喜闻乐见的

fatal error: 'jpeglib.h' file not found
#include <jpeglib.h>
         ^~~~~~~~~~~
1 error generated.

这篇2016年的issue可以解决大部分这个报错:没有安装libjpeg,或是xcode cl tool没有安装好。然而,随着brew加入对xcode clt的检测,后一种情况基本不会发生。

那么还有什么东西会导致这个错误呢?根本上分析,这就是构建系统没能在之前约好的地方找到对应的头文件。

这个约好的位置一般是/usr/local/includes(头文件的位置),当电脑中安装了homebrew后,homebrew的文件夹下的/includes也会被加入约定中。

所以,碰到这种情况时第一时间应该检查homebrew/includes下是否有对应文件。如果你是使用官方提供的安装脚本安装的话,这个位置应该是/opt/homebrew/includes。一般,brew会把指向你安装的包的头文件的链接放在这里。如果没有的话,使用brew link ${package_name}手动链接即可。

然而回到这次的情况,homebrew/includes下有对应的链接,homebrew也重装了一次,可是构建系统还是找不到文件。

因为我猜构建系统一定要检查/usr/local/includes,我就尝试把文件手动拷贝到这里。首先是把文件链接拷贝过来,构建系统不认。可是神奇的是,把源文件直接拷贝过来后,构建系统认了,然后抛出了下一个错误你这是解谜吗?)

fatal error: 'cairo/cairo-pdf.h' file not found
#include <cairo/cairo-pdf.h>
         ^~~~~~~~~~~~~~~~~~~
1 error generated.

啊?这可怎么办?

后面想到,*.gyp会告诉node-gyp该在哪找文件。查了下npm文档,用npm install ----ignore-scripts阻止自动跑postinstall,从而把canvas整个包留在本地后,手动进去看了看binding.gyp

{//...
'include_dirs': [
            '<!@(pkg-config cairo --cflags-only-I | sed s/-I//g)',
            '<!@(pkg-config libpng --cflags-only-I | sed s/-I//g)',
            '<!@(pkg-config pangocairo --cflags-only-I | sed s/-I//g)',
            '<!@(pkg-config freetype2 --cflags-only-I | sed s/-I//g)',
]//...
}

值得一提的是里面并没有libjpeg。我试了下把/usr/local/includes下刚拷过去的源文件删掉然后加了个'<!@(pkg-config libjpeg --cflags-only-I | sed s/-I//g)',它还真就和刚刚一样又抛了找不到cairo-pdf.h的错误。

可是,点开pkg-config输出的cairo头文件位置一看,cairo-pdf.h明明就在这文件夹里面啊,这是干啥?

到这里就卡了。不得已去node-canvas的Github仓库提交issue,却发现近一个月前有人也在Mac上碰到了无法安装的问题,并且也是M1 Mac(这里没有任何说arm架构不好的意思)

虽然TA的报错和我的完全不一样(TA这大概率是编译的结果出问题了,而我们这是直接倒在了编译上),但是我在下边找到一位老哥的评论

Could be a little bit off topic, for me it seems that the /opt/homebrew/include folder is not in clang include path.

If you see this error:
fatal error: 'jpeglib.h' file not found
you can try
CPLUS_INCLUDE_PATH=/opt/homebrew/include npm i canvas (alternative you can use yarn),
or you can just export CPLUS_INCLUDE_PATH in, say, .zshrc.

To summarize, the following works for me,
xcode-select --install
brew install pkg-config cairo pango libpng jpeg giflib librsvg
CPLUS_INCLUDE_PATH=/opt/homebrew/include npm i canvas

草,我赶紧试了试,居然真的编译成了。(然而我还没试,毕竟我要用的是jest而jest默认捆绑了canvas,并且我也没用canvas任何功能)但是我在前几个月编译canvas的时候是不需要这个参数的。就homebrew安装依赖后直接一build就好了。这就让我想到是不是这期间发生了啥?还真有,那就是苹果推送的Developer Tools更新。

于是我根据堆栈交换的这篇回答输出了一下自己的Developer Tools版本,然后期待一下老哥们的回复。万一真的是苹果这次更新导致的,那苹果得好好解释解释了。