CentOS 7 安装canvas编译失败

发布于 2021-01-26  1779 次阅读


很好,今天我们的主题又是canvas。真是自古原生包事儿多。

不过讲句公道话(?),其实很多问题是包作者或者(特指)node-gyp作者们没有考量到或不好考量到的问题。因此需要每位developer自己好好debug。

各位以后成功解决了什么bug的话也可以像这样发出来,并且确保搜索引擎可以正确收录。It saves peoples life.

那么按照惯例,先从日志文件开始:

npm install canvas执行到node-gyp rebuild这一步时,报错输出:(点此跳过日志)

gyp info it worked if it ends with ok
gyp info using node-gyp@7.1.2
gyp info using node@15.6.0 | linux | x64
gyp info ok
gyp info it worked if it ends with ok
gyp info using node-gyp@7.1.2
gyp info using node@15.6.0 | linux | x64
gyp info find Python using Python version 2.7.5 found at "/usr/bin/python"
gyp info spawn /usr/bin/python
gyp info spawn args [
gyp info spawn args   '/usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args   'binding.gyp',
gyp info spawn args   '-f',
gyp info spawn args   'make',
gyp info spawn args   '-I',
gyp info spawn args   '/usr/mikon/node_project/node_modules/canvas/build/config.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/usr/mikon/.cache/node-gyp/15.6.0/include/node/common.gypi',
gyp info spawn args   '-Dlibrary=shared_library',
gyp info spawn args   '-Dvisibility=default',
gyp info spawn args   '-Dnode_root_dir=/usr/mikon/.cache/node-gyp/15.6.0',
gyp info spawn args   '-Dnode_gyp_dir=/usr/local/lib/node_modules/npm/node_modules/node-gyp',
gyp info spawn args   '-Dnode_lib_file=/usr/mikon/.cache/node-gyp/15.6.0/<(target_arch)/node.lib',
gyp info spawn args   '-Dmodule_root_dir=/usr/mikon/node_project/node_modules/canvas',
gyp info spawn args   '-Dnode_engine=v8',
gyp info spawn args   '--depth=.',
gyp info spawn args   '--no-parallel',
gyp info spawn args   '--generator-output',
gyp info spawn args   'build',
gyp info spawn args   '-Goutput_dir=.'
gyp info spawn args ]
gyp info ok
gyp info it worked if it ends with ok
gyp info using node-gyp@7.1.2
gyp info using node@15.6.0 | linux | x64
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
In file included from /usr/mikon/.cache/node-gyp/15.6.0/include/node/node.h:63:0,
                 from ../../nan/nan.h:56,
                 from ../src/backend/Backend.h:6,
                 from ../src/backend/Backend.cc:1:
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h: In member function ‘void v8::TracedReferenceBase::SetSlotThreadSafe(T*)’:
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:912:22: error: expected type-specifier
     reinterpret_cast*>(&val_)->store(new_val,
                      ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:912:22: error: expected ‘>’
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:912:22: error: expected ‘(’
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:912:22: error: ‘atomic’ is not a member of ‘std’
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:912:35: error: expected primary-expression before ‘*’ token
     reinterpret_cast*>(&val_)->store(new_val,
                                   ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:912:36: error: expected primary-expression before ‘>’ token
     reinterpret_cast*>(&val_)->store(new_val,
                                    ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:912:38: error: expected primary-expression before ‘>’ token
     reinterpret_cast*>(&val_)->store(new_val,
                                      ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:913:54: error: ‘memory_order_relaxed’ is not a member of ‘std’
                                                      std::memory_order_relaxed);
                                                      ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:913:80: error: expected ‘)’ before ‘;’ token
                                                      std::memory_order_relaxed);
                                                                                ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h: In member function ‘const T* v8::TracedReferenceBase::GetSlotThreadSafe() const’:
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:920:29: error: expected type-specifier
     return reinterpret_cast const*>(&val_)->load(
                             ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:920:29: error: expected ‘>’
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:920:29: error: expected ‘(’
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:920:29: error: ‘atomic’ is not a member of ‘std’
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:920:41: error: expected primary-expression before ‘const’
     return reinterpret_cast const*>(&val_)->load(
                                         ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:920:41: error: expected ‘)’ before ‘const’
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:920:41: error: expected ‘;’ before ‘const’
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:920:49: error: expected unqualified-id before ‘>’ token
     return reinterpret_cast const*>(&val_)->load(
                                                 ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:920:49: error: expected initializer before ‘>’ token
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h: At global scope:
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:1631:58: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
                                 Local export_value);
                                                          ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:3405:23: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   Local Name() const { return Description(); }
                       ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:5223:76: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
       ArrayBufferCreationMode mode = ArrayBufferCreationMode::kExternalized);
                                                                            ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:5270:21: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   bool IsExternal() const;
                     ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:5297:24: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   Contents Externalize();
                        ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:5307:70: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   void Externalize(const std::shared_ptr& backing_store);
                                                                      ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:5318:24: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   Contents GetContents();
                        ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:5706:76: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
       ArrayBufferCreationMode mode = ArrayBufferCreationMode::kExternalized);
                                                                            ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:5755:76: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
       ArrayBufferCreationMode mode = ArrayBufferCreationMode::kExternalized);
                                                                            ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:5764:21: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   bool IsExternal() const;
                     ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:5780:24: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   Contents Externalize();
                        ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:5790:70: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   void Externalize(const std::shared_ptr& backing_store);
                                                                      ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:5805:24: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   Contents GetContents();
                        ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:7150:28: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   size_t code_range_size() const { return code_range_size_ / kMB; }
                            ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:7152:46: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   void set_code_range_size(size_t limit_in_mb) {
                                              ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:7156:38: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   size_t max_semi_space_size_in_kb() const;
                                      ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:7158:56: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   void set_max_semi_space_size_in_kb(size_t limit_in_kb);
                                                        ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:7160:31: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   size_t max_old_space_size() const { return max_old_generation_size_ / kMB; }
                               ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:7162:49: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   void set_max_old_space_size(size_t limit_in_mb) {
                                                 ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:7166:31: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   size_t max_zone_pool_size() const { return max_zone_pool_size_; }
                               ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:7168:43: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   void set_max_zone_pool_size(size_t bytes) { max_zone_pool_size_ = bytes; }
                                           ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:8758:59: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
                                     MeasureMemoryMode mode);
                                                           ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:8821:36: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   Local GetEnteredContext();
                                    ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:9105:22: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   void RunMicrotasks() { PerformMicrotaskCheckpoint(); }
                      ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:9149:75: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   void AddMicrotasksCompletedCallback(MicrotasksCompletedCallback callback);
                                                                           ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:9157:78: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   void RemoveMicrotasksCompletedCallback(MicrotasksCompletedCallback callback);
                                                                              ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:9341:30: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   UnwindState GetUnwindState();
                              ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:9404:54: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
       AllowCodeGenerationFromStringsCallback callback);
                                                      ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:9764:75: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   static bool TryHandleSignal(int signal_number, void* info, void* context);
                                                                           ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:10723:55: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
                                 const void* stack_base);
                                                       ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/v8.h:10749:65: warning: ‘deprecated’ attribute directive ignored [-Wattributes]
   static bool PCIsInV8(const UnwindState& unwind_state, void* pc);
                                                                 ^
In file included from ../../nan/nan.h:56:0,
                 from ../src/backend/Backend.h:6,
                 from ../src/backend/Backend.cc:1:
/usr/mikon/.cache/node-gyp/15.6.0/include/node/node.h: In lambda function:
/usr/mikon/.cache/node-gyp/15.6.0/include/node/node.h:613:43: error: parameter packs not expanded with ‘...’:
             std::forward(env_args)...);
                                           ^
/usr/mikon/.cache/node-gyp/15.6.0/include/node/node.h:613:43: note:         ‘env_args’
make: *** [Release/obj.target/canvas/src/backend/Backend.o] Error 1
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:194:23)
gyp ERR! stack     at ChildProcess.emit (node:events:379:20)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (node:internal/child_process:285:12)
gyp ERR! System Linux 5.0.11-1.el7.elrepo.x86_64
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "build" "--fallback-to-build" "--module=/usr/mikon/node_project/node_modules/canvas/build/Release/canvas.node" "--module_name=canvas" "--module_path=/usr/mikon/node_project/node_modules/canvas/build/Release" "--napi_version=7" "--node_abi_napi=napi" "--napi_build_version=0" "--node_napi_label=node-v88"
gyp ERR! cwd /usr/mikon/node_project/node_modules/canvas
gyp ERR! node -v v15.6.0
gyp ERR! node-gyp -v v7.1.2
gyp ERR! not ok
node-pre-gyp ERR! build error
node-pre-gyp ERR! stack Error: Failed to execute '/usr/local/bin/node /usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js build --fallback-to-build --module=/usr/mikon/node_project/node_modules/canvas/build/Release/canvas.node --module_name=canvas --module_path=/usr/mikon/node_project/node_modules/canvas/build/Release --napi_version=7 --node_abi_napi=napi --napi_build_version=0 --node_napi_label=node-v88' (1)
node-pre-gyp ERR! stack     at ChildProcess. (/usr/mikon/node_project/node_modules/node-pre-gyp/lib/util/compile.js:83:29)
node-pre-gyp ERR! stack     at ChildProcess.emit (node:events:379:20)
node-pre-gyp ERR! stack     at maybeClose (node:internal/child_process:1065:16)
node-pre-gyp ERR! stack     at Process.ChildProcess._handle.onexit (node:internal/child_process:296:5)
node-pre-gyp ERR! System Linux 5.0.11-1.el7.elrepo.x86_64
node-pre-gyp ERR! command "/usr/local/bin/node" "/usr/mikon/node_project/node_modules/.bin/node-pre-gyp" "install" "--fallback-to-build"
node-pre-gyp ERR! cwd /usr/mikon/node_project/node_modules/canvas
node-pre-gyp ERR! node -v v15.6.0
node-pre-gyp ERR! node-pre-gyp -v v0.11.0
node-pre-gyp ERR! not ok

从输出解读,error基本都是node自带的头文件有格式相关的错误。

那么,node的作者们可能会犯这种错误吗?显然不可能,格式错误他们自己都编译不过去。

所以先去node的官方仓库查看相关文件,对比一下源文件,看看是不是下载过程出现了错误(其实可能性不大)

检查没有问题,两边是一样一样的。

那么就只有可能是编译器的错误了。毕竟Uglify.js在读ES6+的JS时也是一个样子疯狂报格式错误。

于是我检查了node-gyp的版本,重装确认它是最新的。(这也是百度上对于node-gyp出错的最常见解决方案)

这里我犯了一个错误,就是以为编译器是node-gyp自带的。这就是我对Linux了解不深的问题了。然而node-gyp只是个包工头(自动建构系统),具体的活有更下边的人(编译器)干。

然后我检查了下cmake,在我的印象中C语言编译应该也要用到它,其实也是错误的。cmake也只是一个建构系统,并不是编译器。(所以说没有写过C的孩子根本不懂人间疾苦)

那么具体的编译器是谁呢?答案就是GCC。幸好Mac编程和看golang的时候有见过它的大名。于是键入:gcc --version

在我看到输出的文本里有句Copyright@2015的时候我已经感觉有点不对劲了,赶紧查一下gcc最新版的版本号。

我的天啊都到gcc 8了,怎么我的还是4,怪不得编译不了。

于是赶紧百度一下怎么在CentOS上升级gcc,文章开头的第一句话是:(顺带这老哥的页面标题挺可爱的)

Centos 7默认gcc版本为4.8,有时需要更高版本的,

我人傻了,立刻按照步骤更新。然后就成啦!

所以,回到之前说的,“很多bug可能只是包的作者们没想到而已”,这个问题就是典型的node-gyp在编译前没有检查编译器版本与代码的最低应用编译器版本的问题。但是,并不能什么事都靠包作者,特别是这种弱智问题只有在云服务器上的CentOS才会出现。真的想咨询一下各位,你们开发会用CentOS吗?

知道为什么学校要教C了吗?你不学可能连npm一个包都装不上。