windows下编译skia
Posted Redrain
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了windows下编译skia相关的知识,希望对你有一定的参考价值。
转载请说明原出处,谢谢~~:https://redrain.blog.csdn.net/article/details/111685123
目录
skia是谷歌的一个开源2D引擎,用来实现利用CPU实现2D图形绘制。skia应用非常广泛,chrome、android、firefox、flutter等项目的渲染引擎都是skia。
最近打算给ui库替换为skia渲染引擎,所以搞一下windows下的skia编译。以前也搞过老版本的skia编译https://blog.csdn.net/zhuhongshu/article/details/51272050,现在打算编译一个最新的skia。
这次的skia编译时间为2020-12-22,SHA-1:71f75e3111aebcb9895934ecdf2a84a82ac87ba4
虽然官网中有相关的文档,但是实际编译时会遇到一些官网没有说明的情况,所以专门写一篇文章。
准备环境
打开网站需要梯子,skia的官网:https://skia.org/
下载文档:https://skia.org/user/download
编译文档:https://skia.org/user/build
- Win7/Win10(我是win10)
- Visual Studio 2017/2019(我是2017)
- python v2.7.x(必须是v2,需要添加到Path环境变量)
- Git(需要添加到Path环境变量)
1.配置代理
skia本身和相关代码的下载都需要梯子,可以用ShadowSocks或者其他代理
git config --global http.proxy 'socks5://127.0.0.1:1080' git config --global https.proxy 'socks5://127.0.0.1:1080'
使用完毕后取消git代理
git config --global --unset http.proxy git config --global --unset https.proxy
2.下载depot_tools
depot_tools是编译谷歌系列源码需要用到的工具
git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git'
下载后需要添加到Path环境变量
3.下载skia
git clone https://skia.googlesource.com/skia.git
打开cmd,切换到skia目录,执行脚本
python2 tools/git-sync-deps
这一步是自动下载skia依赖的三方库,会自动下载到skia/third_party/externals目录;以及用于生成项目文件的工具gn.exe。
4.假如没有梯子
如果没有梯子,可以在github上找depot_tools和skia的镜像,也可以用。
但是skia依赖的三方库会比较麻烦。python2 tools/git-sync-deps命令会按照skia/DEPS文件里的列表下载依赖的三方库,几乎都是谷歌的地址。这时需要根据自己的需求自己另外下载需要的三方库放到skia/third_party/externals目录。有网友建立了这些三方库的镜像,可以把DEPS文件中的代码改为:
use_relative_paths = True
vars =
"checkout_chromium": False,
deps =
"buildtools" : "https://github.com/GoogleDepends/buildtools.git@505de88083136eefd056e5ee4ca0f01fe9b33de8",
"common" : "https://github.com/GoogleDepends/common.git@9737551d7a52c3db3262db5856e6bcd62c462b92",
"third_party/externals/angle2" : "https://github.com/GoogleDepends/angle2.git@1cc49bb2e230555fb3dc33d3400a5f7a0cefe943",
# Dawn requires jinja2 and markupsafe for the code generator, and glslang and shaderc for SPIRV compilation.
# When the Dawn revision is updated these should be updated from the Dawn DEPS as well.
"third_party/externals/dawn" : "https://github.com/GoogleDepends/dawn.git@11652ff8f8b3c3104eb2627717fa652d432d5b84",
"third_party/externals/glslang" : "https://github.com/GoogleDepends/glslang@1f0fcbe5a30fdc9632a8bff36277103fabf0797c",
"third_party/externals/jinja2" : "https://github.com/GoogleDepends/jinja2@b41863e42637544c2941b574c7877d3e1f663e25",
"third_party/externals/markupsafe" : "https://github.com/GoogleDepends/markupsafe@8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
"third_party/externals/shaderc" : "https://github.com/GoogleDepends/shaderc@362becca1ff2a841c21fd675ac3a9c1ee9bb5612",
"third_party/externals/dng_sdk" : "https://github.com/GoogleDepends/dng_sdk.git@c8d0c9b1d16bfda56f15165d39e0ffa360a11123",
"third_party/externals/egl-registry" : "https://github.com/GoogleDepends/EGL-Registry@a0bca08de07c7d7651047bedc0b653cfaaa4f2ae",
"third_party/externals/expat" : "https://github.com/GoogleDepends/expat.git@e5aa0a2cb0a5f759ef31c0819dc67d9b14246a4a",
"third_party/externals/freetype" : "https://github.com/GoogleDepends/freetype2.git@0a3d2bb99b45b72e1d45185ab054efa993d97210",
"third_party/externals/harfbuzz" : "https://github.com/GoogleDepends/harfbuzz.git@3a74ee528255cc027d84b204a87b5c25e47bff79",
"third_party/externals/icu" : "https://github.com/GoogleDepends/icu.git@dbd3825b31041d782c5b504c59dcfb5ac7dda08c",
"third_party/externals/imgui" : "https://github.com/GoogleDepends/imgui.git@d38d7c6628bebd02692cfdd6fa76b4d992a35b75",
"third_party/externals/libgifcodec" : "https://github.com/GoogleDepends/libgifcodec@d06d2a6d42baf6c0c91cacc28df2542a911d05fe",
"third_party/externals/libjpeg-turbo" : "https://github.com/GoogleDepends/libjpeg-turbo.git@574f3a772c96dc9db2c98ef24706feb3f6dbda9a",
"third_party/externals/libpng" : "https://github.com/GoogleDepends/libpng.git@386707c6d19b974ca2e3db7f5c61873813c6fe44",
"third_party/externals/libwebp" : "https://github.com/GoogleDepends/libwebp.git@0fe1a89dbf1930fc2554dbe76adad5d962054ead",
"third_party/externals/lua" : "https://github.com/GoogleDepends/lua.git@e354c6355e7f48e087678ec49e340ca0696725b1",
"third_party/externals/microhttpd" : "https://github.com/GoogleDepends/libmicrohttpd@748945ec6f1c67b7efc934ab0808e1d32f2fb98d",
"third_party/externals/opencl-lib" : "https://github.com/GoogleDepends/common-lib-amd-APPSDK-3.0@4e6d30e406d2e5a65e1d65e404fe6df5f772a32b",
"third_party/externals/opencl-registry" : "https://github.com/GoogleDepends/OpenCL-Registry@932ed55c85f887041291cef8019e54280c033c35",
"third_party/externals/opengl-registry" : "https://github.com/GoogleDepends/OpenGL-Registry@14b80ebeab022b2c78f84a573f01028c96075553",
"third_party/externals/piex" : "https://github.com/GoogleDepends/piex.git@bb217acdca1cc0c16b704669dd6f91a1b509c406",
"third_party/externals/sdl" : "https://github.com/GoogleDepends/sdl@5d7cfcca344034aff9327f77fc181ae3754e7a90",
"third_party/externals/sfntly" : "https://github.com/GoogleDepends/sfntly.git@b55ff303ea2f9e26702b514cf6a3196a2e3e2974",
"third_party/externals/spirv-cross" : "https://github.com/GoogleDepends/SPIRV-Cross@871c85d7f0edc6b613e3959bc51d13bfbc2fe2df",
"third_party/externals/spirv-headers" : "https://github.com/GoogleDepends/SPIRV-Headers.git@f8bf11a0253a32375c32cad92c841237b96696c0",
"third_party/externals/spirv-tools" : "https://github.com/GoogleDepends/SPIRV-Tools.git@1c8bda3721e6b9302f694b58c26d32eff341b126",
"third_party/externals/swiftshader" : "https://github.com/GoogleDepends/swiftshader@f99302c4efe6f32297a619d407b4410ec3ee6412",
#"third_party/externals/v8" : "https://chromium.googlesource.com/v8/v8.git@5f1ae66d5634e43563b2d25ea652dfb94c31a3b4",
"third_party/externals/wuffs" : "https://github.com/GoogleDepends/wuffs.git@4080840928c0b05a80cda0d14ac2e2615f679f1a",
"third_party/externals/zlib" : "https://github.com/GoogleDepends/zlib@47af7c547f8551bd25424e56354a2ae1e9062859",
"../src":
"url": "https://chromium.googlesource.com/chromium/src.git@d086f1bdb67d4d54ba424d42d01eb256c9a3765f",
"condition": "checkout_chromium",
,
recursedeps = [
"common",
"../src",
]
gclient_gn_args_from = 'src'
剩下的就是工具gn.exe,这个可以在网上搜索编译好的:https://download.csdn.net/download/qq_35824650/12398406,下载后放到skia\\bin目录下。
不过这样做容易出现各个依赖库版本不一致的文件,最好还是弄个梯子。
开始编译
打开cmd并且切换到skia目录,按照官方的方法执行命令:
生成静态库
bin/gn gen out/Static --args='is_official_build=true'
生成动态库
bin/gn gen out/Shared --args='is_official_build=true is_component_build=true'
但是直接这样做行不通,有几个坑,编译肯定失败。需要额外注意几个参数:
1.args的参数说明
- is_component_build:是否生成动态库
- is_debug:是否生成调试版本
- target_cpu="x86":表示win32平台,不指定的话默认是64位
- is_official_build:是否只编译skia自身
- win_sdk:如果windows sdk没有安装到默认路径,需要指定此参数
- win_vc:如果vs没有安装到默认路径,需要指定此参数
其中is_official_build参数表示是否只编译skia自身,官方示例写为true,这样在编译过程中会因为缺少三方库而编译失败,所以我直接设置为false。
2.生成项目文件
另外有一个坑,就是官方文档的参数描述(单引号以及斜杠)都是linux环境下的,在windows的cmd下直接报错。可以使用Cygwin工具来执行命令,或者对命令中的路径进行转义。最终的命令如下:
生成静态库
bin\\gn gen out\\Static --args="is_official_build=false is_debug=false win_vc=\\"D:/Software/Program/VS2017/VC\\" win_sdk=\\"C:/Program Files (x86)/Windows Kits/10\\" target_cpu=\\"x86\\"" --ide="vs2017"
生成动态库
bin\\gn gen out\\Shared --args="is_official_build=false is_debug=false is_component_build=true win_vc=\\"D:/Software/Program/VS2017/VC\\" win_sdk=\\"C:/Program Files (x86)/Windows Kits/10\\" target_cpu=\\"x86\\"" --ide="vs2017"
这样就可以在skia\\out目录下看到生成的项目文件了,可以使用vs打开来查看代码。不过编译的话还是需要使用谷歌的ninja工具(depot_tools里有)。命令为:
ninja -C out/Static
但是这个生成的项目依然会编译失败,cmd解析Program Files(x86)中的空格会报错。
3.删除多余的命令
打开skia\\out\\Static\\toolchain.ninja文件,搜索所有的文本内容然后删掉:
cmd /c C:/Program Files (x86)/Windows Kits/10/bin/SetEnv.cmd /x86 &&
打开vs安装的目录,比如我的
D:\\Software\\Program\\VS2017\\VC\\Tools\\MSVC\\14.16.27023\\bin\\Hostx64\\x64
找到三个dll文件道北到skia\\out\\Static目录下:
- msobj140.dll
- mspdb140.dll
- mspdbcore.dll
接下来就可以执行ninja -C out/Static来编译了,大概需要3小时时间
用LLVM编译
官方文档里强烈建议使用LLVM的clang来编译,因为skia针对clang有专门优化,性能要比vs编译的更好。为了需要单独下载LLMV环境:https://releases.llvm.org/download.html。我直接安装到C:/LLVM,不然编译时又会因为Program Files(x86)中的空格而报错。这时需要改生成项目的命令加一个参数:
clang_win = "C:\\LLVM" cc="clang" cxx="clang"
示例如下:
bin\\gn gen out\\StaticLLVM --args="is_official_build=false is_debug=false win_vc=\\"D:/Software/Program/VS2017/VC\\" win_sdk=\\"C:/Program Files (x86)/Windows Kits/10\\" cc=\\"clang\\" cxx=\\"clang++\\" clang_win=\\"C:/LLVM\\" target_cpu=\\"x86\\"" --ide="vs2017"
LLVM编译速度比VS快了很多,大概只花了50分钟。vs编译的静态skia.lib大小为1.04G;LLVM编译的静态skia.lib大小是280M,动态库skia.dll大小为skia.dll
Skia剪裁
前面说到is_official_build参数用来配置只编译skia自身还是自动编译的三方库依赖。如果加入三方库,那么编译的静态库就会非常大。假如我们只需要skia核心功能或者针对某些功能进行剪裁,可以设置is_official_build为true,然后单独设置禁用或启用某个三方库功能。这是官方文档:
Most users of Skia should set
is_official_build=true
, and most developers should leave it to itsfalse
default.This mode configures Skia in a way that's suitable to ship: an optimized build with no debug symbols, dynamically linked against its third-party dependencies using the ordinary library search path.
In contrast, the developer-oriented default is an unoptimized build with full debug symbols and all third-party dependencies built from source and embedded into libskia. This is how we do all our manual and automated testing.
Skia offers several features that make use of third-party libraries, like libpng, libwebp, or libjpeg-turbo to decode images, or ICU and sftnly to subset fonts. All these third-party dependencies are optional and can be controlled by a GN argument that looks something like
skia_use_foo
for appropriatefoo
.If
skia_use_foo
is enabled, enablingskia_use_system_foo
will build and link Skia against the headers and libaries found on the system paths.is_official_build=true
enables allskia_use_system_foo
by default. You can useextra_cflags
andextra_ldflags
to add include or library paths if needed.
文档中说到:所有这些第三方依赖项都是可选的,并且可以由skia_use_foo来控制,如果设置skia_use_foo为false则会禁止这个foo功能。所有的参数信息参见:skia\\gn\\skia.gni。
有一个skia_use_system_foo配置项。当is_official_build=true时,并且开启了某个skia_use_foo,那么skia_use_system_foo也是默认开启的。skia_use_system_foo表示从系统里查找这个foo库来编译而不是是从skia自带的三方库。这个时候有两个方法来编译这个三方库:
- 在--args里增加extra_cflags和extra_ldflags参数来指定这个三方库的头文件好库文件路径
- 关闭skia_use_system_foo开关,那么依然会从skia自带的三方库里编译
实际上,我们一般直接用skia自带的三方库就可以,我们只是需要禁用某些三方库。比如我要禁用icu、xml、pdf、xps、webp编解码,只保留png、jpg图片编解码功能。
那么我要禁用:
- skia_use_icu=false
- skia_use_expat=false
- skia_use_libwebp_decode=false
- skia_use_libwebp_encode=false
- skia_use_xps=false
- skia_enable_pdf=false
再开启我需要的(默认的各种功能都是开的,所以其实不用单独设置):
- skia_use_libjpeg_turbo_decode = true
- skia_use_libjpeg_turbo_encode = true
- skia_use_libpng_decode = true
- skia_use_libpng_encode = true
- skia_use_zlib=true
另外我系统直接使用skia自带的三方库,而不是另外设置路径,那么需要:
- skia_use_system_libpng=false
- skia_use_system_libjpeg_turbo=false
- skia_use_system_zlib=false
所以最终的命令我:
bin\\gn gen out\\StaticLLVMSkiaOnlyWithImage --args="is_official_build=true skia_use_system_libpng=false skia_use_system_libjpeg_turbo=false skia_use_system_zlib=false skia_use_icu=false skia_use_expat=false skia_use_libwebp_decode=false skia_use_libwebp_encode=false skia_use_xps=false skia_enable_pdf=false is_debug=false win_vc=\\"D:/Software/Program/VS2017/VC\\" win_sdk=\\"C:/Program Files (x86)/Windows Kits/10\\" cc=\\"clang\\" cxx=\\"clang++\\" clang_win=\\"C:/LLVM\\" target_cpu=\\"x86\\"" --ide="vs2017"
最后用LLVM编出来的静态文件只有15.6M,大大减小了体积和编译时
手动去掉三方库依赖
skia虽然编译时会依赖很多三方库,包括字体相关freetype库,图片相关png、jpeg、gif等等。但是如果是单单windows平台的话,其实用不到这些依赖。字体功能windows系统有GDI和DriectWrite,图片功能使用WIC组件。所以这些三方库完全可以去掉,单单使用include和src文件夹里的代码来编译就可以。
去掉字体依赖
在src\\ports目录下,是skia为了适配各个平台而专门写的适配代码。其中字体相关的有:
其中SkFontHost_win.cpp是GDI字体渲染的实现,SkFontMgr_indirect.cpp、SkFontMgr_win_dw.cpp、SkScalerContext_win_dw.cpp、SkTypeface_win_dw.cpp是DirectWrite字体渲染的实现。SkFontMgr_win_gdi_factory.cpp是创建GDI实现的工厂,SkFontMgr_win_dw_factory.cpp是创建DirectWrite实现的工厂。skia默认使用DirectWrite功能,因为他效果和性能都更好。但是xp系统下不支持DirectWrite。所以可以修改DirectWrite工厂:
原代码:
sk_sp<SkFontMgr> SkFontMgr::Factory()
return SkFontMgr_New_DirectWrite();
修改后:
sk_sp<SkFontMgr> SkFontMgr::Factory()
auto fontMgr = SkFontMgr_New_DirectWrite();
if (fontMgr)
return fontMgr;
else
return SkFontMgr_New_GDI();
去掉图片依赖
src\\ports下图片相关的文件:
src\\images目录下:
其中SkImageEncoder.cpp文件里是解析图片的入口:
bool SkEncodeImage(SkWStream* dst, const SkPixmap& src,
SkEncodedImageFormat format, int quality)
#ifdef SK_USE_CG_ENCODER
(void)quality;
return SkEncodeImageWithCG(dst, src, format);
#elif SK_USE_WIC_ENCODER
return SkEncodeImageWithWIC(dst, src, format, quality);
#elif SK_ENABLE_NDK_IMAGES
return SkEncodeImageWithNDK(dst, src, format, quality);
#else
switch(format)
case SkEncodedImageFormat::kJPEG:
SkJpegEncoder::Options opts;
opts.fQuality = quality;
return SkJpegEncoder::Encode(dst, src, opts);
case SkEncodedImageFormat::kPNG:
SkPngEncoder::Options opts;
return SkPngEncoder::Encode(dst, src, opts);
case SkEncodedImageFormat::kWEBP:
SkWebpEncoder::Options opts;
if (quality == 100)
opts.fCompression = SkWebpEncoder::Compression::kLossless;
// Note: SkEncodeImage treats 0 quality as the lowest quality
// (greatest compression) and 100 as the highest quality (least
// compression). For kLossy, this matches libwebp's
// interpretation, so it is passed directly to libwebp. But
// with kLossless, libwebp always creates the highest quality
// image. In this case, fQuality is reinterpreted as how much
// effort (time) to put into making a smaller file. This API
// does not provide a way to specify this value (though it can
// be specified by using SkWebpEncoder::Encode) so we have to
// pick one arbitrarily. This value matches that chosen by
// blink::ImageEncoder::ComputeWebpOptions as well
// WebPConfigInit.
opts.fQuality = 75;
else
opts.fCompression = SkWebpEncoder::Compression::kLossy;
opts.fQuality = quality;
return SkWebpEncoder::Encode(dst, src, opts);
default:
return false;
#endif
我们可以开启SK_USE_WIC_ENCODER宏(skia没有开启),然后把SkJpegEncoder.cpp、SkJPEGWriteUtility.cpp、SkJPEGWriteUtility.h、SkPngEncoder.cpp、SkWebpEncoder.cpp从项目文件中去掉,就可以使用WIC来解析并去掉额外的三方库依赖了
针对skia老版本
这次搞得skia版本比较高,必须要c++17的支持,所以我专门搞过老版本的编译。编译的是m49分支(对应chrome49版本)。直接用cmkae生成vs2013工程,来编译。老版本的字体依赖的处理和前面的方法一直。图片依赖的处理,它默认就启用了WIC,只要把png、jpeg、gif等解析器的cpp文件从项目中去掉就可以了。
编译cmake
bin\\gn gen out\\config --ide=json --json-ide-script=..\\..\\gn\\gn_to_cmake.py --args="win_vc=\\"D:/Software/Program/VS2017/VC\\" win_sdk=\\"C:/Program Files (x86)/Windows Kits/10\\""
Redrain QQ:491646717 2020-12-25
以上是关于windows下编译skia的主要内容,如果未能解决你的问题,请参考以下文章