编译cairo

cartographer在绘制子图(submap)和将子图合成栅格地图(nav_msgs::OccupancyGrid)时,要使用cairo。

 

一、Windows下编译32位的cairo

cairo[01] Windows环境学习笔记——配置cairo”有写如何在Windows编译cairo,那里用到工具“Mozilla Build”,这里介绍的方法不使用该工具,但需要MinGW。流程基本和该文一样。

1.1 准备相关源码包

前三个是cairo的依赖项,最后一个是cairo本身,以上的包全部下载最新版。

须要安装编译工具Visual Studio、MinGW,它们的版本越新越好,像Microsoft Visual Studio Enterprise 2019(Version 16.11.1)。以下假设MinGW存放路径是“C:/MinGW”。

1.2 编译zlib和libpng

图1 4个源码包放到同一目录

将zlib、lingpng、pixman、cairo文件夹解压到同一个文件夹下,然后将文件夹的名字改成该源代码的项目名称。类似图1。

进入到 “<cairo>/libpng/projects/visualc71”,打开“libpng.sln”

Visual Studio提示升级项目,点击升级。

然后“Build”——“Build Solution”。Build会同时编译zlib,成功后“<cairo>/libpng/projects/visualc71/Win32_DLL_Debug”目录下会生成libpng.lib、libpng16d.dll;“<cairo>/libpng/projects/visualc71/Win32_DLL_Debug/ZLib“则有zlib.lib、zlib1d.dll。

1.3 编译pixman

编译pixman需要MinGW。

步骤1:开始菜单中运行“x86 Native Tools Command Prompt for VS 2019”

步骤2:启动MinGW。在命令行执行“C:\MinGW\msys\1.0\msys.bat”。

图2 x86 Native Tools Command Prompt for VS 2019中启动MINGW32

这时就会新弹出MINGW32窗口。在该窗口的命令行,切换到“<cairo>/pixman”目录下,运行“make -f MakeFile.win32 CFG=debug”。等一大串编译信息出来之后,正常来说,最后会有这几句:

图3 编译pixman

成功后查看“<cairo>/pixman/pixman/debug”目录,会发现里面有一个pixman-1.lib文件。

1.4 编译cairo

为让链接时不出错,先复制两个lib文件。

  • 把<cairo>/libpng/projects/visualc71/Win32_DLL_Debuglib/libpng.lib复制到<cairo>/libpng/目录。否则链接时会报错:LINK : fatal error LNK1181: cannot open input file '..\..\libpng\libpng.lib'
  • 把<cairo>/libpng/projects/visualc71/Win32_DLL_Debug/ZLib/zlib.lib复制到<cairo>/zlib,并改名为zdll.lib。否则链接时会报错:LINK : fatal error LNK1181: cannot open input file '..\..\zlib\zlib.lib'

执行“1.3 编译pixman”中的步骤1、步骤2。后绪操作都需要发生在MINGW32窗口。

步骤三:执行以下语句,修改INCLUDE环境变量

export INCLUDE="$INCLUDE;/../zlib;/../libpng;/../pixman/pixman;/../cairo/src;/../cairo/boilerplate"

步骤四:切换到“/cairo/src”里面,运行“make -f MakeFile.win32 CFG=debug”

图4 编译cairo

成功后,<cairo>/cairo/src/debug下会生成cairo.lib、cairo.dll。编译app时,需链接cairo.lib,不须要libpng.lib和zdll.lib。运行时则同时需要cairo.dll、libpng16d.dll、zlib1d.dll。

 

二、以静态库方式编译基础版cairo

基础版cairo是只通过编译cairo_sources中那些*.c就出来的cairo版本,此时cairo-features.h不定义任何额外功能宏。

<cairo>/src/Makefile.sources
------
cairo_sources = \
	cairo-analysis-surface.c \
	cairo-arc.c \
	cairo-array.c \
	cairo-atomic.c \
        ...
	cairo-user-font.c \
	cairo-version.c \
	cairo-wideint.c \
	cairo.c \
	$(NULL)
<cairo>/src/cairo-features.h
------
// Generating src/cairo-features.h
/* Generated by Makefile.win32.features-h.  Do not edit. */
#ifndef CAIRO_FEATURES_H
#define CAIRO_FEATURES_H

#ifdef _WIN32
#define CAIRO_HAS_PNG_FUNCTIONS 1
#endif

#endif

因为rose已内置了OpenCV + SDL,要不是为编译cartographer,个人不想用cairo。编译cairo不是件容易事,在勉强用它情况下,如何降低编译cairo难度?——看下cartographer用到的cairo api。

6>   Creating library C:\ddksample\apps-src\apps\projectfiles\vc\Release\launcher.lib and object C:\ddksample\apps-src\apps\projectfiles\vc\Release\launcher.exp
6>cartographer.lib(image.obj) : error LNK2019: unresolved external symbol __imp__cairo_destroy referenced in function "class std::unique_ptr<struct _cairo,void (__cdecl*)(struct _cairo *)> __cdecl cartographer::io::MakeUniqueCairoPtr(struct _cairo *)" (?MakeUniqueCairoPtr@io@cartographer@@YA?AV?$unique_ptr@U_cairo@@P6AXPAU1@@Z@std@@PAU_cairo@@@Z)
6>cartographer.lib(image.obj) : error LNK2019: unresolved external symbol __imp__cairo_surface_destroy referenced in function "class std::unique_ptr<struct _cairo_surface,void (__cdecl*)(struct _cairo_surface *)> __cdecl cartographer::io::MakeUniqueCairoSurfacePtr(struct _cairo_surface *)" (?MakeUniqueCairoSurfacePtr@io@cartographer@@YA?AV?$unique_ptr@U_cairo_surface@@P6AXPAU1@@Z@std@@PAU_cairo_surface@@@Z)
6>cartographer.lib(image.obj) : error LNK2019: unresolved external symbol __imp__cairo_surface_status referenced in function "public: void __thiscall cartographer::io::Image::WritePng(class cartographer::io::FileWriter * const)" (?WritePng@Image@io@cartographer@@QAEXQAVFileWriter@23@@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2001: unresolved external symbol __imp__cairo_surface_status
6>cartographer.lib(image.obj) : error LNK2019: unresolved external symbol __imp__cairo_surface_write_to_png_stream referenced in function "public: void __thiscall cartographer::io::Image::WritePng(class cartographer::io::FileWriter * const)" (?WritePng@Image@io@cartographer@@QAEXQAVFileWriter@23@@Z)
6>cartographer.lib(image.obj) : error LNK2019: unresolved external symbol __imp__cairo_format_stride_for_width referenced in function "void __cdecl cartographer::io::`anonymous namespace'::CheckStrideIsAsExpected(int)" (?CheckStrideIsAsExpected@?A0xd3515990@io@cartographer@@YAXH@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2001: unresolved external symbol __imp__cairo_format_stride_for_width
6>cartographer.lib(image.obj) : error LNK2019: unresolved external symbol __imp__cairo_image_surface_create_for_data referenced in function "public: class std::unique_ptr<struct _cairo_surface,void (__cdecl*)(struct _cairo_surface *)> __thiscall cartographer::io::Image::GetCairoSurface(void)" (?GetCairoSurface@Image@io@cartographer@@QAE?AV?$unique_ptr@U_cairo_surface@@P6AXPAU1@@Z@std@@XZ)
6>cartographer.lib(submap_painter.obj) : error LNK2001: unresolved external symbol __imp__cairo_image_surface_create_for_data
6>cartographer.lib(image.obj) : error LNK2019: unresolved external symbol __imp__cairo_image_surface_get_data referenced in function "public: __thiscall cartographer::io::Image::Image(class std::unique_ptr<struct _cairo_surface,void (__cdecl*)(struct _cairo_surface *)>)" (??0Image@io@cartographer@@QAE@V?$unique_ptr@U_cairo_surface@@P6AXPAU1@@Z@std@@@Z)
6>cartographer.lib(msg_conversion.obj) : error LNK2001: unresolved external symbol __imp__cairo_image_surface_get_data
6>cartographer.lib(image.obj) : error LNK2019: unresolved external symbol __imp__cairo_image_surface_get_format referenced in function "public: __thiscall cartographer::io::Image::Image(class std::unique_ptr<struct _cairo_surface,void (__cdecl*)(struct _cairo_surface *)>)" (??0Image@io@cartographer@@QAE@V?$unique_ptr@U_cairo_surface@@P6AXPAU1@@Z@std@@@Z)
6>cartographer.lib(image.obj) : error LNK2019: unresolved external symbol __imp__cairo_image_surface_get_width referenced in function "public: __thiscall cartographer::io::Image::Image(class std::unique_ptr<struct _cairo_surface,void (__cdecl*)(struct _cairo_surface *)>)" (??0Image@io@cartographer@@QAE@V?$unique_ptr@U_cairo_surface@@P6AXPAU1@@Z@std@@@Z)
6>cartographer.lib(msg_conversion.obj) : error LNK2001: unresolved external symbol __imp__cairo_image_surface_get_width
6>cartographer.lib(image.obj) : error LNK2019: unresolved external symbol __imp__cairo_image_surface_get_height referenced in function "public: __thiscall cartographer::io::Image::Image(class std::unique_ptr<struct _cairo_surface,void (__cdecl*)(struct _cairo_surface *)>)" (??0Image@io@cartographer@@QAE@V?$unique_ptr@U_cairo_surface@@P6AXPAU1@@Z@std@@@Z)
6>cartographer.lib(msg_conversion.obj) : error LNK2001: unresolved external symbol __imp__cairo_image_surface_get_height
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_create referenced in function "struct cartographer::io::PaintSubmapSlicesResult __cdecl cartographer::io::PaintSubmapSlices(class std::map<struct cartographer::mapping::SubmapId,struct cartographer::io::SubmapSlice,struct std::less<struct cartographer::mapping::SubmapId>,class std::allocator<struct std::pair<struct cartographer::mapping::SubmapId const ,struct cartographer::io::SubmapSlice> > > const &,double)" (?PaintSubmapSlices@io@cartographer@@YA?AUPaintSubmapSlicesResult@12@ABV?$map@USubmapId@mapping@cartographer@@USubmapSlice@io@3@U?$less@USubmapId@mapping@cartographer@@@std@@V?$allocator@U?$pair@$$CBUSubmapId@mapping@cartographer@@USubmapSlice@io@3@@std@@@7@@std@@N@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_save referenced in function "void __cdecl cartographer::io::`anonymous namespace'::CairoPaintSubmapSlices(double,class std::map<struct cartographer::mapping::SubmapId,struct cartographer::io::SubmapSlice,struct std::less<struct cartographer::mapping::SubmapId>,class std::allocator<struct std::pair<struct cartographer::mapping::SubmapId const ,struct cartographer::io::SubmapSlice> > > const &,struct _cairo *,class std::function<void __cdecl(struct cartographer::io::SubmapSlice const &)>)" (?CairoPaintSubmapSlices@?A0x52876b02@io@cartographer@@YAXNABV?$map@USubmapId@mapping@cartographer@@USubmapSlice@io@3@U?$less@USubmapId@mapping@cartographer@@@std@@V?$allocator@U?$pair@$$CBUSubmapId@mapping@cartographer@@USubmapSlice@io@3@@std@@@7@@std@@PAU_cairo@@V?$function@$$A6AXABUSubmapSlice@io@cartographer@@@Z@5@@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_restore referenced in function "void __cdecl cartographer::io::`anonymous namespace'::CairoPaintSubmapSlices(double,class std::map<struct cartographer::mapping::SubmapId,struct cartographer::io::SubmapSlice,struct std::less<struct cartographer::mapping::SubmapId>,class std::allocator<struct std::pair<struct cartographer::mapping::SubmapId const ,struct cartographer::io::SubmapSlice> > > const &,struct _cairo *,class std::function<void __cdecl(struct cartographer::io::SubmapSlice const &)>)" (?CairoPaintSubmapSlices@?A0x52876b02@io@cartographer@@YAXNABV?$map@USubmapId@mapping@cartographer@@USubmapSlice@io@3@U?$less@USubmapId@mapping@cartographer@@@std@@V?$allocator@U?$pair@$$CBUSubmapId@mapping@cartographer@@USubmapSlice@io@3@@std@@@7@@std@@PAU_cairo@@V?$function@$$A6AXABUSubmapSlice@io@cartographer@@@Z@5@@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_set_source_rgba referenced in function "struct cartographer::io::PaintSubmapSlicesResult __cdecl cartographer::io::PaintSubmapSlices(class std::map<struct cartographer::mapping::SubmapId,struct cartographer::io::SubmapSlice,struct std::less<struct cartographer::mapping::SubmapId>,class std::allocator<struct std::pair<struct cartographer::mapping::SubmapId const ,struct cartographer::io::SubmapSlice> > > const &,double)" (?PaintSubmapSlices@io@cartographer@@YA?AUPaintSubmapSlicesResult@12@ABV?$map@USubmapId@mapping@cartographer@@USubmapSlice@io@3@U?$less@USubmapId@mapping@cartographer@@@std@@V?$allocator@U?$pair@$$CBUSubmapId@mapping@cartographer@@USubmapSlice@io@3@@std@@@7@@std@@N@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_set_source_surface referenced in function "public: __thiscall <lambda_599ed861251a83e4696d63f87e808e16>::operator()(struct cartographer::io::SubmapSlice const &)const " (??R<lambda_599ed861251a83e4696d63f87e808e16>@@QBE@ABUSubmapSlice@io@cartographer@@@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_translate referenced in function "struct cartographer::io::PaintSubmapSlicesResult __cdecl cartographer::io::PaintSubmapSlices(class std::map<struct cartographer::mapping::SubmapId,struct cartographer::io::SubmapSlice,struct std::less<struct cartographer::mapping::SubmapId>,class std::allocator<struct std::pair<struct cartographer::mapping::SubmapId const ,struct cartographer::io::SubmapSlice> > > const &,double)" (?PaintSubmapSlices@io@cartographer@@YA?AUPaintSubmapSlicesResult@12@ABV?$map@USubmapId@mapping@cartographer@@USubmapSlice@io@3@U?$less@USubmapId@mapping@cartographer@@@std@@V?$allocator@U?$pair@$$CBUSubmapId@mapping@cartographer@@USubmapSlice@io@3@@std@@@7@@std@@N@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_scale referenced in function "void __cdecl cartographer::io::`anonymous namespace'::CairoPaintSubmapSlices(double,class std::map<struct cartographer::mapping::SubmapId,struct cartographer::io::SubmapSlice,struct std::less<struct cartographer::mapping::SubmapId>,class std::allocator<struct std::pair<struct cartographer::mapping::SubmapId const ,struct cartographer::io::SubmapSlice> > > const &,struct _cairo *,class std::function<void __cdecl(struct cartographer::io::SubmapSlice const &)>)" (?CairoPaintSubmapSlices@?A0x52876b02@io@cartographer@@YAXNABV?$map@USubmapId@mapping@cartographer@@USubmapSlice@io@3@U?$less@USubmapId@mapping@cartographer@@@std@@V?$allocator@U?$pair@$$CBUSubmapId@mapping@cartographer@@USubmapSlice@io@3@@std@@@7@@std@@PAU_cairo@@V?$function@$$A6AXABUSubmapSlice@io@cartographer@@@Z@5@@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_transform referenced in function "void __cdecl cartographer::io::`anonymous namespace'::CairoPaintSubmapSlices(double,class std::map<struct cartographer::mapping::SubmapId,struct cartographer::io::SubmapSlice,struct std::less<struct cartographer::mapping::SubmapId>,class std::allocator<struct std::pair<struct cartographer::mapping::SubmapId const ,struct cartographer::io::SubmapSlice> > > const &,struct _cairo *,class std::function<void __cdecl(struct cartographer::io::SubmapSlice const &)>)" (?CairoPaintSubmapSlices@?A0x52876b02@io@cartographer@@YAXNABV?$map@USubmapId@mapping@cartographer@@USubmapSlice@io@3@U?$less@USubmapId@mapping@cartographer@@@std@@V?$allocator@U?$pair@$$CBUSubmapId@mapping@cartographer@@USubmapSlice@io@3@@std@@@7@@std@@PAU_cairo@@V?$function@$$A6AXABUSubmapSlice@io@cartographer@@@Z@5@@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_user_to_device referenced in function "public: __thiscall <lambda_2ac1a5c5845d68154dcb0bd9e966c81b>::operator()(double,double)const " (??R<lambda_2ac1a5c5845d68154dcb0bd9e966c81b>@@QBE@NN@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_paint referenced in function "public: __thiscall <lambda_599ed861251a83e4696d63f87e808e16>::operator()(struct cartographer::io::SubmapSlice const &)const " (??R<lambda_599ed861251a83e4696d63f87e808e16>@@QBE@ABUSubmapSlice@io@cartographer@@@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_status_to_string referenced in function "class std::unique_ptr<struct _cairo_surface,void (__cdecl*)(struct _cairo_surface *)> __cdecl cartographer::io::DrawTexture(class std::vector<char,class std::allocator<char> > const &,class std::vector<char,class std::allocator<char> > const &,int,int,class std::vector<unsigned int,class std::allocator<unsigned int> > *)" (?DrawTexture@io@cartographer@@YA?AV?$unique_ptr@U_cairo_surface@@P6AXPAU1@@Z@std@@ABV?$vector@DV?$allocator@D@std@@@4@0HHPAV?$vector@IV?$allocator@I@std@@@4@@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_surface_flush referenced in function "struct cartographer::io::PaintSubmapSlicesResult __cdecl cartographer::io::PaintSubmapSlices(class std::map<struct cartographer::mapping::SubmapId,struct cartographer::io::SubmapSlice,struct std::less<struct cartographer::mapping::SubmapId>,class std::allocator<struct std::pair<struct cartographer::mapping::SubmapId const ,struct cartographer::io::SubmapSlice> > > const &,double)" (?PaintSubmapSlices@io@cartographer@@YA?AUPaintSubmapSlicesResult@12@ABV?$map@USubmapId@mapping@cartographer@@USubmapSlice@io@3@U?$less@USubmapId@mapping@cartographer@@@std@@V?$allocator@U?$pair@$$CBUSubmapId@mapping@cartographer@@USubmapSlice@io@3@@std@@@7@@std@@N@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_image_surface_create referenced in function "struct cartographer::io::PaintSubmapSlicesResult __cdecl cartographer::io::PaintSubmapSlices(class std::map<struct cartographer::mapping::SubmapId,struct cartographer::io::SubmapSlice,struct std::less<struct cartographer::mapping::SubmapId>,class std::allocator<struct std::pair<struct cartographer::mapping::SubmapId const ,struct cartographer::io::SubmapSlice> > > const &,double)" (?PaintSubmapSlices@io@cartographer@@YA?AUPaintSubmapSlicesResult@12@ABV?$map@USubmapId@mapping@cartographer@@USubmapSlice@io@3@U?$less@USubmapId@mapping@cartographer@@@std@@V?$allocator@U?$pair@$$CBUSubmapId@mapping@cartographer@@USubmapSlice@io@3@@std@@@7@@std@@N@Z)
6>cartographer.lib(submap_painter.obj) : error LNK2019: unresolved external symbol __imp__cairo_matrix_init referenced in function "void __cdecl cartographer::io::`anonymous namespace'::CairoPaintSubmapSlices(double,class std::map<struct cartographer::mapping::SubmapId,struct cartographer::io::SubmapSlice,struct std::less<struct cartographer::mapping::SubmapId>,class std::allocator<struct std::pair<struct cartographer::mapping::SubmapId const ,struct cartographer::io::SubmapSlice> > > const &,struct _cairo *,class std::function<void __cdecl(struct cartographer::io::SubmapSlice const &)>)" (?CairoPaintSubmapSlices@?A0x52876b02@io@cartographer@@YAXNABV?$map@USubmapId@mapping@cartographer@@USubmapSlice@io@3@U?$less@USubmapId@mapping@cartographer@@@std@@V?$allocator@U?$pair@$$CBUSubmapId@mapping@cartographer@@USubmapSlice@io@3@@std@@@7@@std@@PAU_cairo@@V?$function@$$A6AXABUSubmapSlice@io@cartographer@@@Z@5@@Z)
6>C:\ddksample\apps-src\apps\projectfiles\vc\Release\launcher.exe : fatal error LNK1120: 24 unresolved externals

除cairo_surface_write_to_png_stream,其它都是基础版cairo提供的api。到目前,我只用了cartographer中的cartographer_node、cartographer_occupancy_grid_node,这两个node好像都没调用到cairo_surface_write_to_png_stream(不熟悉源码,不能最终确定)。况且即使将来要用cairo_surface_write_to_png_stream,应该能把它改为用SDL的IMG_SavePNG。所以,单纯为编译cartographer这个目的,只须要编译基础版cairo。

为降低跨平台编译难度,在windows要以静态库方式编译cario,而android则是直接以原文件融入app编译。它们共性是要求以静态库方式编译。

修改1:api不用前缀__declspec(dllimport)修饰符

<cairo>/cairo.h
------
#  define cairo_public __declspec(dllimport)
改为
#  define cairo_public

上面报错时,cairo api都加了“__imp”前缀,像__imp__cairo_destroy,有这前缀就是__declspec(dllimport)导致的。

修改2:强制pixmal不查PACKAGE宏

<pixman>/pixman/pixman-private.h
------
#ifndef PACKAGE
#  error config.h must be included before pixman-private.h
#endif

免得要全局额外定义PACKAGE,注释掉以上的三行语句。

修改3:CAIRO_HAS_UTF8_TO_UTF16=1

<cairo>/src/cairoint.h
------
#if CAIRO_HAS_WIN32_FONT || CAIRO_HAS_QUARTZ_FONT || CAIRO_HAS_PDF_OPERATORS
# define CAIRO_HAS_UTF8_TO_UTF16 1
#endif
改为不要条件强制定义CAIRO_HAS_UTF8_TO_UTF16 = 1
# define CAIRO_HAS_UTF8_TO_UTF16 1

若不定义CAIRO_HAS_UTF8_TO_UTF16=1,cairo会不编译_cairo_utf8_to_utf16。

修改4:不调用cairo_surface_write_to_png_stream

<cartographer>/cartographer/io/image.cc
------
void Image::WritePng(FileWriter* const file_writer) {
  // 注释调用cairo_surface_write_to_png_stream,并确保执行过程中不会调用该函数  
  CHECK(false);
}

 

三、增加libpng

为调试,有时须要把cairo_surface_t存成png,作为验证。这里就需要调用cairo_surface_write_to_png,从而要依赖libpng。但只是在windows有这功能,其它系统不要使用,像android。

修改1:<cairo>/src/cairo-features.h

增加定义CAIRO_HAS_PNG_FUNCTIONS,见上面的cairo-features.h。

修改2:增加编译源文件

  • <cairo>/src/cairo-png.c
  • libpng库相关c文件

全部评论: 0

    写评论: