# 2018-09-30:目前慎用CGAL的header-only模式 **因为这个模式是新出来的,好像不是那么完善** 今天我尝试在`mingw-w64`下编译一个带`CGAL`的程序,结果`msys2`里面自带的包管理器里面的`CGAL`有问题,虽然二进制文件是好的,但`cmake`文件中还残留了不少编译时留下的绝对路径信息,显然是没法用了。 于是下载`CGAL`源码自己编译。`CGAL`新版中有那么一个`header-only`模式,也就是不编译,就把源文件放在那里,等真正要用时一起。考虑到以前`CGAL`动不动就要编译几十分钟,毫不犹豫选了这个模式——其实,这个模式我之前已经用过好多次了。 然而这次就出了幺蛾子,程序编译到`98%`进入链接阶段时,报了一堆`undefined reference`错误类似这样: ``` c:/ming64gcc48/projects/CGAL/rel-mpfr-3.1.2w64gcc48/lib/libmpfr.a(init2.o):init2.c:(.text+0x70): undefined reference to `__gmp_get_memory_functions' c:/ming64gcc48/projects/CGAL/rel-mpfr-3.1.2w64gcc48/lib/libmpfr.a(clear.o):clear.c:(.text+0x1e): undefined reference to `__gmp_get_memory_functions' c:/ming64gcc48/projects/CGAL/rel-mpfr-3.1.2w64gcc48/lib/libmpfr.a(div.o):div.c:(.text+0x234): undefined reference to `__gmpn_divrem' c:/ming64gcc48/projects/CGAL/rel-mpfr-3.1.2w64gcc48/lib/libmpfr.a(round_prec.o):round_prec.c:(.text+0xa76): undefined reference to `__gmp_get_memory_functions' c:/ming64gcc48/projects/CGAL/rel-mpfr-3.1.2w64gcc48/lib/libmpfr.a(mulders.o):mulders.c:(.text+0x5c2): undefined reference to `__gmpn_divrem' c:/ming64gcc48/projects/CGAL/rel-mpfr-3.1.2w64gcc48/lib/libmpfr.a(mulders.o):mulders.c:(.text+0x94c): undefined reference to `__gmpn_divrem' c:/ming64gcc48/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.8.0/../../../../x86_64-w64-mingw32/bin/ld.exe: c:/ming64gcc48/projects/CGAL/rel-mpfr-3.1.2w64gcc48/lib/libmpfr.a(mulders.o): bad reloc address 0x0 in section `.pdata' collect2.exe: error: ld returned 1 exit status ``` 然而`nm`查看库文件时,明明时有那些符号的。没办法,放狗搜吧,找到两个信息: * [这里报告说用cmake链接GMP和MPRF时,MPRF必须在前面](http://trac.osgeo.org/postgis/ticket/2333) * [这里的意思是一样的](https://github.com/Oslandia/SFCGAL/issues/59) * [这里说其实新版CGAL不要MPRF和GMP也是可以凑合用的](https://ethiy.github.io/2016/12/27/CGAL/) 我首先尝试了第三种做法,把`MPRF`和`GMP`的依赖项去掉,再配置`CGAL`的`header-only`模式,结果一样。但是那俩选项明明已经去掉了。研究`cmake`日志发现这俩货仍然出现再日志文件中。清除`CGAL`目录重新配置,未果。在`CGAL`的`cmake`脚本里交换这俩货的顺序,未果。 走投无路,我甚至怀疑是同时用上的`libigl`又把这俩选项偷偷打开了(`libigl`有这样搞`boost`的黑历史,当时我还提供了一个PR作为临时解决方案),但找了半天也没证据。 反复研究之后,`cmake`的输出里面有个地方引起了我的兴趣: ``` Requested component: MPFR Requested component: GMP Requested component: MPFR ``` 为啥`MPRF`被请求了两次呢?加了几条输出,确定这句话是第一包含`CGAL`时输出的,并非`libigl`搞鬼。那么是不是按上面前两条链接里面写的,最后一次`MPRF`引用搞坏事了? 于是决定编译一个正常版本的`CGAL`,编译前灵光一现,决定先试试带`MPRF`和`GMP`的编译版。编译出来`CGAL`之后,再在自己的程序里引用,编译,链接,一切正常。 所以,`msys`库里带的`MPRF`和`GMP`一点问题都没有,`CGAL`的经典版本也没问题,但`CGAL`的`header-only`版本就会在`mingw-w64`平台下闹出上面那个顺序依赖。 > P.S. 其实现在的`CGAL 4.12`版本,编译也只需要一分钟,比后面的安装过程还快。