Windows下使用CMake静态编译libaom的正确姿势

av1编码

Posted by MetaNetworks on May 21, 2023
本页面总访问量

libaom是AV1编码/解码的一个静态库,由C编写,跨平台支持。VCPKG也把aom集成到自己的ports当中,可以很方便的完成编译。但是VCPKG还是存在以下不足:

  1. 版本不够新。对于libaom这种新库来说,每个版本性能都有非常大的提升以及资源优化改进。vcpkg目前只到了3.5.0,但是官方以及更新到3.6.0版本。
  2. 多target编译兼容不足。

RustDesk是一个跨移动/桌面平台的高性能虚拟化桌面软件,在兼容多个平台的同时,还需要满足arm、arm64下的编译。vcpkg的默认triplet往往不能满足所有平台的成功编译,老版本在部分平台上可能还会有代码问题。

在编译层面本应不是问题,但是集成到RustDesk中,出现了链接错误。

1
3\xc1\xcb\xb8\xc3\xb7\xfb\xba\xc5\r\nlibscrap-ee1d8b31da778732.rlib(tpl_model.obj) : error LNK2019: \xce\xde\xb7\xa8\xbd\xe2\xce\xf6\xb5\xc4\xcd\xe2\xb2\xbf\xb7\xfb\xba\xc5 __imp_fmax\xa3\xac\xba\xaf\xca\xfd av1_estimate_coeff_entropy \xd6\xd0\xd2\xfd\xd3\xc3\xc1\xcb\xb8\xc3\xb7\xfb\xba\xc5\r\nlibscrap-ee1d8b31da778732.rlib(tx_search.obj) : error LNK2019: \xce\xde\xb7\xa8\xbd\xe2\xce\xf6\xb5\xc4\xcd\xe2\xb2\xbf\xb7\xfb\xba\xc5 __imp_log1pf\xa3\xac\xba\xaf\xca\xfd ml_predict_intra_tx_depth_prune \xd6\xd0\xd2\xfd\xd3\xc3\xc1\xcb\xb8\xc3\xb7\xfb\xba\xc5\r\nlibscrap-ee1d8b31da778732.rlib(partition_strategy.obj) : error LNK2001: \xce\xde\xb7\xa8\xbd\xe2\xce\xf6\xb5\xc4\xcd\xe2\xb2\xbf\xb7\xfb\xba\xc5 __imp_log1pf\r\nC:\\Users\\a1147\\Documents\\projects\\rustdesk\\target\\debug\\deps\\librustdesk.dll : fatal error LNK1120: 5 \xb8\xf6\xce\xde\xb7\xa8\xbd\xe2\xce\xf6\xb5\xc4\xcd\xe2\xb2\xbf\xc3\xfc\xc1\xee\r\n

看上去__imp_log1pf是找不到,我们再细看。

寻找问题

使用Git clone下载仓库源码:

1
git clone https://aomedia.googlesource.com/aom.git --depth=1 

官方README.md并未对Windows编译选项有过多的叙述。我们看到log1pf,发现来自于ucrt库,看来是ucrt无法找到。RustDesk为了不同Windows平台的兼容性,静态链接了ucrt,故我们的第三方库也需要静态链接ucrt,否则最终链接成链接库时会出现link error。

对于CMAKE_MSVC_RUNTIME_LIBRARY属性,cmake在3.15中支持,用来设置MSVC的运行库是否是静态的、debuggable的。为了兼容win7,这处根据提供的README.md,设置了WIN32_WINNT参数。

解决办法

最终编译命令如下:

1
 cmake .. -G "Visual Studio 17 2022" -A x64 -DCMAKE_INSTALL_PREFIX="C:\Users\a1147\Documents\projects\rustdesk_thirdparty_lib\vcpkg\installed\x64-windows-static" -D_WIN32_WINNT=0x0601 -DBUILD_SHARED_LIBS=OFF -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$<CONFIG:Debug>:Debug>"

MultiThreaded$<$<CONFIG:Debug>:Debug>中,$<$<CONFIG:Debug>:Debug>为CMake的表达式,表示:如果是Debug模式,将表达为Debug,否则为空。

所以,当当前设置为Debug版本,那么链接的是MultiThreadedDebug ucrt,否则就是MultiThreaded ucrt版本。

结语

静态链接是软件应用的一个好习惯,虽然一定程度上增加了代码体积大小,但在兼容性上会带来非常大的优势。作为程序员应该很好的衡量二者的关系。