很好,今天我们的主题又是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一个包都装不上。
Comments NOTHING