美文网首页
WPS ungrib编译报错 undefined referen

WPS ungrib编译报错 undefined referen

作者: 别有路 | 来源:发表于2023-03-26 21:39 被阅读0次

最近在一个新机子上用Spack配置好编译器, hdf5, netcdf-c, netcdf-fortran, jasper等一系列依赖库后编译了最新版本的WRF-4.4.2WPS-4.4

WRF没问题, WPS-4.4这边的ungrib.exe怎么都不行, 报如下错:

./ngl/libg2_4.a(dec_jpeg2000.o): In function `dec_jpeg2000_':
dec_jpeg2000.c:(.text+0x61): undefined reference to `jpc_decode'
collect2: error: ld returned 1 exit status
make[1]: [Makefile:19: ungrib.exe] Error 1 (ignored)

但是很奇怪的是, 我用nmlibjasper.so里是有jpc_decode这个函数的, LD_LIBRARY_PATH, LIBRARY_PATH之类的改了半天, 也都没有用, 最后研究了小半天才解决, 这里记录一下



Update @2023-03-28 16:33:34
mdzz, 结果按下面编译出来跑起来又报错了

jas_init.c:919: jas_get_ctx_internal: Assertion `ctx' failed.

不搞了, 老老实实切回了jasper-1.900.1, 淦!



省流

解决方案(选一):

  • 装个老版本的jasper
  • 修改jasper源码, 手动编译, 暴露jpc_decode函数
  • 修改ungrib里的代码, 将jpc_decode替换为jas_image_decode

其实装个老版本应该就行了, 但是由于实在奇怪, 我还是搞清楚选择了修改ungrib的源码....

Bug分析

首先通过Google发现这么一个帖子 :

https://github.com/NOAA-EMC/NCEPLIBS-g2c/issues/245

提到jpc_decode现在是个内部函数, 开发者希望改为用jas_image_decode

include/jasper/jas_image.h中可以看到:

#if defined(JAS_INCLUDE_JPC_CODEC)
/* Format-dependent operations for JPEG-2000 code stream support. */
//JAS_EXPORT
jas_image_t *jpc_decode(jas_stream_t *in, const char *optstr);
//JAS_EXPORT
int jpc_encode(jas_image_t *image, jas_stream_t *out, const char *optstr);
//JAS_EXPORT
int jpc_validate(jas_stream_t *in);
#endif

然后这个JAS_INCLUDE_JPC_CODEC是在include/jasper/jas_config.hdefine过了的:

#define JAS_INCLUDE_JPC_CODEC

但是呢, 和jas_image_decode相比, jpc_decode缺少这个东西 : JAS_EXPORT

JAS_EXPORT
jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, const char *optstr);

JAS_EXPORT是在include/jasper/jas_export_cmake.h中定义的:

#      define JAS_EXPORT __attribute__((visibility("default")))

而visibility的影响参考这里提到的:

而编译时使用internal和hidden选项时,如果函数内没有:__attribute ((visibility("default")))声明,动态库使隐藏的不可被外界调用。

由于我是用spack配置环境的, 进到这里后(关键是最后的.spack):

opt/spack/linux-centos7-zen/gcc-7.5.0/jasper-3.0.3-zliofrszjxt7h7xjmjnn3scbccxkyq7k/.spack

grep可以发现这样的编译指令 : -fvisibility=hidden

ok, 所以其实jpc_decode在动态库中实际上是不可见的

因此, 理论上修改源码或者更改编译指令后, 重新编译即可, 但是我是spack编译的, 懒得搞的


那么就去修改ungrib里的源码, 找到ungrib/src/ngl/g2/dec_jpeg2000.c里出错的行:

// jas_image_t *jpc_decode(jas_stream_t *in, const char *optstr)
image=jpc_decode(jpcstream,opts);

改为:

// jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, const char *optstr)
image=jas_image_decode(jpcstream,4,opts);

这里解释一下参数, 首先从declaration上看, 就是中间多了一个指定格式的int参数 : fmt

然后这里在jasper的源码里的src/libjasper/base/jas_init.c里看到一个数组jas_image_fmts, 里面jpeg-2000(jpc)的index是4, 所以这里改成4

然后就编译出来了

总结

之前都是手动编译的, jasper都用的巨老的版本, 从来没遇到过这个问题, 这次用spack配置, 爽是爽, 下次考虑酌情选择老一点的版本, 不选的话默认就是最新的, 是真的容易出问题... ...

相关文章

网友评论

      本文标题:WPS ungrib编译报错 undefined referen

      本文链接:https://www.haomeiwen.com/subject/fvdardtx.html