ios web 前端支持 webP 的 WebAssembly 方案 --环境搭建与编译(一)
ios safari webp 图片优化之 WebAssembly 移植谷歌开源库 libwebp 到 web 应用
前言
libwebp
编译成JavaScript
解码器的过程 使用Emscripten
和CMake
。下文主要记录mac
上Emscripten
和CMake
的安装,编译libwebp --> webp_wasm.js + webp_wasm.wasm
完整过程。
一、下载安装 Emscripten SDK
简称 emsdk
由于
Emscripten SDK (emsdk)
是用Python
写的, 相关依赖也是从python.org
下载,需要有python
环境 。首先需要查看本地Python
版本,安装 pip ( 官方) 。
第一步:查看 python 的版本
Mac
电脑自带python
环境,打开终端,输入python
,按下enter
键,查看自己电脑中的python
版本(默认安装的是python2.7
版本)【提示:查看完python
的版本后,输入exit()
,或者quit()
即可退出终端中的python
环境】。 但是在开发时,我们多数使用的是python3
,在终端中输入python3
,按下enter
键,查看电脑中是否装有python3
。如果电脑中没有安装python3
,可以去python
官网下载。https://www.python.org/downloads/release/python-363/
。 下载后安装python3
,一直点击下一步即可。安装完成后,在终端中输入python3
,查看是否安装成功。python3
安装完成后,我们下载python
的一些扩展包的时候需要使用pip3 install
命令,如需下载ipython
扩展包,在终端命令行中输入pip3 install ipython
,按下enter
即可自动安装。【输入pip3 list
可以查看当前python
环境中安装了哪些扩展包】
# 退出 python 环境
quit()
# 查看 python2 版本
python
# 下载 get-pip.py
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
# 运行安装脚本 (注意:用哪个版本的 Python 运行安装脚本,pip 就被关联到哪个版本,如果是 Python3 则执行以下命令)
sudo python get-pip.py
# 安装证书(避免终端下载 `python` 包失败)
pip install certifi
# 如何是 python3 请看👇
# 查看 python3 的版本
python3
sudo python3 get-pip.py
第二步:安装 emsdk
# Get the emsdk repo
git clone https://github.com/emscripten-core/emsdk.git
# Enter that directory
cd emsdk
git pull
# Download and install the latest SDK tools. 这个过程有点久~需要耐心等待
./emsdk install latest
# Make the "latest" SDK "active" for the current user. (writes ~/.emscripten file)
./emsdk activate latest
# Activate PATH and other environment variables in the current terminal (这步很重要!!!每次修改环境变量都要执行使之生效)
source ./emsdk_env.sh
# $EMSCRIPTEN should point to the top-level directory containing Emscripten tools (添加环境变量,让 emcc 的命令可以在任意目录使用)
vim ~/.bash_profile
## 在 bash_profile 最后
export EMSCRIPTEN=$EMSDK/upstream/emscripten
export EMSDK="/Users/zhangxj/Desktop/workspace/demo/libwebp-demo/emsdk"
export EM_CONFIG="/Users/zhangxj/.emscripten"
export EMSCRIPTEN="$EMSDK/upstream/emscripten"
export EMSDK_NODE="/Users/zhangxj/Desktop/workspace/demo/libwebp-demo/emsdk/node/12.9.1_64bit/bin/node"
PATH="$EMSDK:${PATH}"
PATH="$EMSCRIPTEN:${PATH}"
PATH="$EMSDK_NODE:${PATH}"
export PATH
source ~/.bash_profile
附:emsdk
安装过程常见错误 Q&A
Q1: pip
证书没安装
Q2: 安装 pip
需要加 sudo
,正确姿势:sudo python get-pip.py
第三步:安装 cmake download
$ cd ~
$ vim .bash_profile
## 添加 cmake 环境变量到 bash_profile
export CMAKE_ROOT=/Applications/CMake.app/Contents/bin/
export PATH=$CMAKE_ROOT:$PATH
$ source ./.bash_profile
$ cmake --version
## 到 libwep 的源目录,让CMake使用emcc命令作为Compiler和LinkTool
$ cd webp_js && \
cmake -DWEBP_BUILD_WEBP_JS=ON \
-DEMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES=1 \
-DCMAKE_TOOLCHAIN_FILE=$EMSCRIPTEN/cmake/Modules/Platform/Emscripten.cmake \
../
执行完
$libwebp git:(master) cd webp_js && \
cmake -DWEBP_BUILD_WEBP_JS=ON \
-DEMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES=1 \
-DCMAKE_TOOLCHAIN_FILE=$EMSCRIPTEN/cmake/Modules/Platform/Emscripten.cmake \
../
CMake Warning (dev) at CMakeLists.txt:45 (set):
implicitly converting 'Build type: Release, Debug, MinSizeRel or
RelWithDebInfo' to 'STRING' type.
This warning is for project developers. Use -Wno-dev to suppress it.
-- Performing Test HAVE_BUILTIN_BSWAP16
-- Performing Test HAVE_BUILTIN_BSWAP16 - Success
-- Performing Test HAVE_BUILTIN_BSWAP32
-- Performing Test HAVE_BUILTIN_BSWAP32 - Success
-- Performing Test HAVE_BUILTIN_BSWAP64
-- Performing Test HAVE_BUILTIN_BSWAP64 - Success
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Performing Test HAVE_PTHREAD_PRIO_INHERIT
-- Performing Test HAVE_PTHREAD_PRIO_INHERIT - Success
-- Performing Test PTHREAD_CREATE_UNDETACHED
-- Performing Test PTHREAD_CREATE_UNDETACHED - Success
-- Performing Test HAVE_MATH_LIBRARY
-- Performing Test HAVE_MATH_LIBRARY - Success
-- Could NOT find ZLIB (missing: ZLIB_LIBRARY ZLIB_INCLUDE_DIR)
-- Could NOT find PNG (missing: PNG_LIBRARY PNG_PNG_INCLUDE_DIR)
-- Could NOT find JPEG (missing: JPEG_LIBRARY JPEG_INCLUDE_DIR)
-- Could NOT find TIFF (missing: TIFF_LIBRARY TIFF_INCLUDE_DIR)
-- Could NOT find GIF (missing: GIF_LIBRARY GIF_INCLUDE_DIR)
-- Looking for 4 include files stdlib.h, ..., float.h
-- Looking for 4 include files stdlib.h, ..., float.h - found
-- Looking for include file dlfcn.h
-- Looking for include file dlfcn.h - found
-- Looking for include file GLUT/glut.h
-- Looking for include file GLUT/glut.h - not found
-- Looking for include file GL/glut.h
-- Looking for include file GL/glut.h - found
-- Looking for include file inttypes.h
-- Looking for include file inttypes.h - found
-- Looking for include file memory.h
-- Looking for include file memory.h - found
-- Looking for include file OpenGL/glut.h
-- Looking for include file OpenGL/glut.h - not found
-- Looking for include file shlwapi.h
-- Looking for include file shlwapi.h - not found
-- Looking for include file stdint.h
-- Looking for include file stdint.h - found
-- Looking for include file stdlib.h
-- Looking for include file stdlib.h - found
-- Looking for include file strings.h
-- Looking for include file strings.h - found
-- Looking for include file string.h
-- Looking for include file string.h - found
-- Looking for include file sys/stat.h
-- Looking for include file sys/stat.h - found
-- Looking for include file sys/types.h
-- Looking for include file sys/types.h - found
-- Looking for include file unistd.h
-- Looking for include file unistd.h - found
-- Looking for include file wincodec.h
-- Looking for include file wincodec.h - not found
-- Looking for include file windows.h
-- Looking for include file windows.h - not found
-- Disabling SSE41 optimization.
-- Disabling SSE41 optimization.
-- Performing Test HAS_COMPILE_FLAG
-- Performing Test HAS_COMPILE_FLAG - Success
-- Performing Test FLAG_-mno-sse4.1
-- Performing Test FLAG_-mno-sse4.1 - Failed
-- Disabling SSE2 optimization.
-- Disabling SSE2 optimization.
-- Performing Test HAS_COMPILE_FLAG
-- Performing Test HAS_COMPILE_FLAG - Success
-- Performing Test FLAG_-mno-sse2
-- Performing Test FLAG_-mno-sse2 - Failed
-- Disabling MIPS32 optimization.
-- Disabling MIPS32 optimization.
-- Disabling MIPS_DSP_R2 optimization.
-- Disabling MIPS_DSP_R2 optimization.
-- Performing Test HAS_COMPILE_FLAG
-- Performing Test HAS_COMPILE_FLAG - Success
-- Performing Test FLAG_-mno-dspr2
-- Performing Test FLAG_-mno-dspr2 - Failed
-- Disabling NEON optimization.
-- Disabling NEON optimization.
-- Disabling MSA optimization.
-- Disabling MSA optimization.
-- Performing Test HAS_COMPILE_FLAG
-- Performing Test HAS_COMPILE_FLAG - Success
-- Performing Test FLAG_-mno-msa
-- Performing Test FLAG_-mno-msa - Failed
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/zhangxj/Desktop/workspace/demo/libwebp/webp_js
# 最后一步,到 webp_js 目录下 执行
$ make
Q & A
-
Q1:为什么改了 配置编译编译没生效?
-
A1:cmake 的工程,每次执行 cmake 需要清除,
cd webp_js && git clean -dxf .
-
Q2:make 编译过程出现报错
--share--memory mused to be use
-
A2:尝试去掉
-DEMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES=1
,换成这个cd webp_js && git clean -dxf . && cmake -DWEBP_BUILD_WEBP_JS=ON -DCMAKE_TOOLCHAIN_FILE=$EMSCRIPTEN/cmake/Modules/Platform/Emscripten.cmake ../
--share--memory mused to be use
报错的截图
编译前后对比 webp_js
文件目录对比
# 编译前
$ webp_js git:(master) ✗ tree .
.
├── index.html
├── index_wasm.html
├── test_webp_js.webp
└── test_webp_wasm.webp
0 directories, 4 files
# 编译后
$ webp_js git:(master) ✗ tree .
.
├── CMakeCache.txt
├── CMakeFiles
│ ├── 3.16.1
│ │ ├── CMakeCCompiler.cmake
│ │ └── CMakeSystem.cmake
│ ├── CMakeDirectoryInformation.cmake
│ ├── CMakeError.log
│ ├── CMakeOutput.log
│ ├── CMakeTmp
│ ├── CheckIncludeFiles
│ │ ├── HAVE_DLFCN_H.c
│ │ ├── HAVE_GLUT_GLUT_H.c
│ │ ├── HAVE_GL_GLUT_H.c
│ │ ├── HAVE_INTTYPES_H.c
│ │ ├── HAVE_MEMORY_H.c
│ │ ├── HAVE_OPENGL_GLUT_H.c
│ │ ├── HAVE_SHLWAPI_H.c
│ │ ├── HAVE_STDINT_H.c
│ │ ├── HAVE_STDLIB_H.c
│ │ ├── HAVE_STRINGS_H.c
│ │ ├── HAVE_STRING_H.c
│ │ ├── HAVE_SYS_STAT_H.c
│ │ ├── HAVE_SYS_TYPES_H.c
│ │ ├── HAVE_UNISTD_H.c
│ │ ├── HAVE_WINCODEC_H.c
│ │ ├── HAVE_WINDOWS_H.c
│ │ └── STDC_HEADERS.c
│ ├── Export
│ │ └── share
│ │ └── WebP
│ │ └── cmake
│ │ ├── WebPTargets-release.cmake
│ │ └── WebPTargets.cmake
│ ├── Makefile.cmake
│ ├── Makefile2
│ ├── TargetDirectories.txt
│ ├── cmake.check_cache
│ ├── progress.marks
│ ├── webp.dir
│ │ ├── DependInfo.cmake
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── cmake_clean_target.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── includes_C.rsp
│ │ ├── link.txt
│ │ ├── objects1.rsp
│ │ └── progress.make
│ ├── webp_js.dir
│ │ ├── C.includecache
│ │ ├── DependInfo.cmake
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── extras
│ │ │ └── webp_to_sdl.c.o
│ │ ├── flags.make
│ │ ├── includes_C.rsp
│ │ ├── link.txt
│ │ ├── linklibs.rsp
│ │ ├── objects1.rsp
│ │ └── progress.make
│ ├── webp_wasm.dir
│ │ ├── C.includecache
│ │ ├── DependInfo.cmake
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── extras
│ │ │ └── webp_to_sdl.c.o
│ │ ├── flags.make
│ │ ├── includes_C.rsp
│ │ ├── link.txt
│ │ ├── linklibs.rsp
│ │ ├── objects1.rsp
│ │ └── progress.make
│ ├── webpdecode.dir
│ │ ├── C.includecache
│ │ ├── DependInfo.cmake
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── includes_C.rsp
│ │ ├── progress.make
│ │ └── src
│ │ └── dec
│ │ ├── alpha_dec.c.o
│ │ ├── buffer_dec.c.o
│ │ ├── frame_dec.c.o
│ │ ├── idec_dec.c.o
│ │ ├── io_dec.c.o
│ │ ├── quant_dec.c.o
│ │ ├── tree_dec.c.o
│ │ ├── vp8_dec.c.o
│ │ ├── vp8l_dec.c.o
│ │ └── webp_dec.c.o
│ ├── webpdecoder.dir
│ │ ├── DependInfo.cmake
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── cmake_clean_target.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── includes_C.rsp
│ │ ├── link.txt
│ │ ├── objects1.rsp
│ │ └── progress.make
│ ├── webpdemux.dir
│ │ ├── C.includecache
│ │ ├── DependInfo.cmake
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── cmake_clean_target.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── includes_C.rsp
│ │ ├── link.txt
│ │ ├── objects1.rsp
│ │ ├── progress.make
│ │ └── src
│ │ └── demux
│ │ ├── anim_decode.c.o
│ │ └── demux.c.o
│ ├── webpdsp.dir
│ │ ├── C.includecache
│ │ ├── DependInfo.cmake
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── includes_C.rsp
│ │ ├── progress.make
│ │ └── src
│ │ └── dsp
│ │ ├── alpha_processing.c.o
│ │ ├── cost.c.o
│ │ ├── cpu.c.o
│ │ ├── dec.c.o
│ │ ├── dec_clip_tables.c.o
│ │ ├── enc.c.o
│ │ ├── filters.c.o
│ │ ├── lossless.c.o
│ │ ├── lossless_enc.c.o
│ │ ├── rescaler.c.o
│ │ ├── ssim.c.o
│ │ ├── upsampling.c.o
│ │ └── yuv.c.o
│ ├── webpdspdecode.dir
│ │ ├── C.includecache
│ │ ├── DependInfo.cmake
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── includes_C.rsp
│ │ ├── progress.make
│ │ └── src
│ │ └── dsp
│ │ ├── alpha_processing.c.o
│ │ ├── cpu.c.o
│ │ ├── dec.c.o
│ │ ├── dec_clip_tables.c.o
│ │ ├── filters.c.o
│ │ ├── lossless.c.o
│ │ ├── rescaler.c.o
│ │ ├── upsampling.c.o
│ │ └── yuv.c.o
│ ├── webpencode.dir
│ │ ├── C.includecache
│ │ ├── DependInfo.cmake
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── includes_C.rsp
│ │ ├── progress.make
│ │ └── src
│ │ └── enc
│ │ ├── alpha_enc.c.o
│ │ ├── analysis_enc.c.o
│ │ ├── backward_references_cost_enc.c.o
│ │ ├── backward_references_enc.c.o
│ │ ├── config_enc.c.o
│ │ ├── cost_enc.c.o
│ │ ├── filter_enc.c.o
│ │ ├── frame_enc.c.o
│ │ ├── histogram_enc.c.o
│ │ ├── iterator_enc.c.o
│ │ ├── near_lossless_enc.c.o
│ │ ├── picture_csp_enc.c.o
│ │ ├── picture_enc.c.o
│ │ ├── picture_psnr_enc.c.o
│ │ ├── picture_rescale_enc.c.o
│ │ ├── picture_tools_enc.c.o
│ │ ├── predictor_enc.c.o
│ │ ├── quant_enc.c.o
│ │ ├── syntax_enc.c.o
│ │ ├── token_enc.c.o
│ │ ├── tree_enc.c.o
│ │ ├── vp8l_enc.c.o
│ │ └── webp_enc.c.o
│ ├── webputils.dir
│ │ ├── C.includecache
│ │ ├── DependInfo.cmake
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── includes_C.rsp
│ │ ├── progress.make
│ │ └── src
│ │ └── utils
│ │ ├── bit_reader_utils.c.o
│ │ ├── bit_writer_utils.c.o
│ │ ├── color_cache_utils.c.o
│ │ ├── filters_utils.c.o
│ │ ├── huffman_encode_utils.c.o
│ │ ├── huffman_utils.c.o
│ │ ├── quant_levels_dec_utils.c.o
│ │ ├── quant_levels_utils.c.o
│ │ ├── random_utils.c.o
│ │ ├── rescaler_utils.c.o
│ │ ├── thread_utils.c.o
│ │ └── utils.c.o
│ └── webputilsdecode.dir
│ ├── C.includecache
│ ├── DependInfo.cmake
│ ├── build.make
│ ├── cmake_clean.cmake
│ ├── depend.internal
│ ├── depend.make
│ ├── flags.make
│ ├── includes_C.rsp
│ ├── progress.make
│ └── src
│ └── utils
│ ├── bit_reader_utils.c.o
│ ├── color_cache_utils.c.o
│ ├── filters_utils.c.o
│ ├── huffman_utils.c.o
│ ├── quant_levels_dec_utils.c.o
│ ├── random_utils.c.o
│ ├── rescaler_utils.c.o
│ ├── thread_utils.c.o
│ └── utils.c.o
├── Makefile
├── WebPConfig.cmake
├── WebPConfigVersion.cmake
├── cmake_install.cmake
├── index.html
├── index_wasm.html
├── libwebp.a
├── libwebpdecoder.a
├── libwebpdemux.a
├── src
│ ├── demux
│ │ └── libwebpdemux.pc
│ ├── libwebp.pc
│ ├── libwebpdecoder.pc
│ └── webp
│ └── config.h
├── test_webp_js.webp
├── test_webp_wasm.webp
├── webp.js
├── webp.wasm
├── webp.worker.js
├── webp_wasm.js
├── webp_wasm.wasm
└── webp_wasm.worker.js
38 directories, 243 files
测试一下
# webp_js 目录下 ,启动服务
$ http-server
后言
想要了解一下,
webpack
工程如何使用web_wasm.js
和web_wasm.wasm
,请移步下一篇文章ios web 前端支持 webP 的 WebAssembly 方案 -- 结合 webpack ios web 生产环境应用 webp(二)
(待写),先放一个已完成并应用到生产环境webp-decode
的js库。
这是一整个系列文章,定期更新
- WebAssembly 系列(一):简单介绍
- WebAssembly 系列(二):编程语言、虚拟机和 webAssembly 三者有什么关系?
- WebAssembly 系列(三):图片解码 webp实践 1
- WebAssembly 系列(三):图片解码 webp实践 2
- WebAssembly 系列(三):图片解码 webp实践 3