Bri*_*fin 9 ubuntu gcc cobol ld gnucobol
我想,最近发生了一些变化.
GnuCOBOL依赖于动态链接,在运行时使用dlsym查找符号.这个CALL运行时支持代码已经在OpenCOBOL中使用了大约7年.它不再适用于Ubuntu 14.04,但在Fedora 19/20下运行.
ldd不再显示使用-l列出的任何库
例如,作为测试,Ubuntu 14.04.1
以下COBOL计划
identification division.
program-id. simple.
procedure division.
call "gtk_init" using
by value 0
by reference null
returning omitted
end-call
goback.
end program simple.
$ cobc -x -v -lgtk-3 simple.cob
preprocessing simple.cob into /tmp/cob710_0.cob
parsing /tmp/cob710_0.cob (simple.cob)
Return status: 0
translating /tmp/cob710_0.cob into /tmp/cob710_0.c (simple.cob)
gcc -pipe -c -I/usr/local/include -Wno-unused -fsigned-char -Wno-pointer-sign -o "/tmp/cob710_0.o" "/tmp/cob710_0.c"
gcc -pipe -Wl,--export-dynamic -o simple /tmp/cob710_0.o -L/usr/local/lib -lcob -lm -lgmp -lncurses -ldb -ldl -l"gtk-3"
Run Code Online (Sandbox Code Playgroud)
二进制没有指示libgtk-3.so在混合中.
./simple
libcob: Cannot find module 'gtk_init'
$ ldd simple
linux-vdso.so.1 => (0x00007fff2c9fe000)
libcob.so.1 => /usr/local/lib/libcob.so.1 (0x00007f2549b06000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2549740000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f2549439000)
libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f25491c5000)
libncurses.so.5 => /lib/x86_64-linux-gnu/libncurses.so.5 (0x00007f2548fa2000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f2548d78000)
libdb-5.3.so => /usr/lib/x86_64-linux-gnu/libdb-5.3.so (0x00007f25489d6000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f25487d2000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2549d56000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f25485b3000)
Run Code Online (Sandbox Code Playgroud)
然后在Fedora 20上,相同版本的编译器(构建稍有不同,找到ncursesw而不是ncurses - 假设这不是手头问题的一部分)
$ cobc -x -v -lgtk-3 simple.cob
Command line: cobc -x -v -lgtk-3 simple.cob
Preprocessing: simple.cob -> /tmp/cob20658_0.cob
Return status: 0
Parsing: /tmp/cob20658_0.cob (simple.cob)
Return status: 0
Translating: /tmp/cob20658_0.cob -> /tmp/cob20658_0.c (simple.cob)
Executing: gcc -std=gnu99 -c -I/usr/local/include -pipe -Wno-unused
-fsigned-char -Wno-pointer-sign -o "/tmp/cob20658_0.o"
"/tmp/cob20658_0.c"
Return status: 0
Executing: gcc -std=gnu99 -Wl,--export-dynamic -o "simple"
"/tmp/cob20658_0.o" -L/usr/local/lib -lcob -lm -lgmp
-lncursesw -ldb -ldl -l"gtk-3"
Return status: 0
$ ldd simple
linux-vdso.so.1 => (0x00007fffae9cf000)
libcob.so.4 => /usr/local/lib/libcob.so.4 (0x00007f4ff2548000)
libm.so.6 => /lib64/libm.so.6 (0x0000003e5ae00000)
libgmp.so.10 => /lib64/libgmp.so.10 (0x0000003e7a200000)
libncursesw.so.5 => /lib64/libncursesw.so.5 (0x0000003e5d200000)
libtinfo.so.5 => /lib64/libtinfo.so.5 (0x0000003e69800000)
libdb-5.3.so => /lib64/libdb-5.3.so (0x0000003e6ac00000)
libdl.so.2 => /lib64/libdl.so.2 (0x0000003e5b200000)
libgtk-3.so.0 => /lib64/libgtk-3.so.0 (0x0000003e6ba00000)
libc.so.6 => /lib64/libc.so.6 (0x0000003e5aa00000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003e5b600000)
/lib64/ld-linux-x86-64.so.2 (0x0000003e5a600000)
libgdk-3.so.0 => /lib64/libgdk-3.so.0 (0x0000003e6a800000)
libgmodule-2.0.so.0 => /lib64/libgmodule-2.0.so.0 (0x0000003e65600000)
libpangocairo-1.0.so.0 => /lib64/libpangocairo-1.0.so.0 (0x0000003e75200000)
libX11.so.6 => /lib64/libX11.so.6 (0x00007f4ff2206000)
libXi.so.6 => /lib64/libXi.so.6 (0x0000003e62600000)
libXfixes.so.3 => /lib64/libXfixes.so.3 (0x0000003e5fe00000)
libcairo-gobject.so.2 => /lib64/libcairo-gobject.so.2 (0x0000003e6a400000)
libcairo.so.2 => /lib64/libcairo.so.2 (0x0000003e71000000)
libgdk_pixbuf-2.0.so.0 => /lib64/libgdk_pixbuf-2.0.so.0 (0x0000003e6e000000)
libatk-1.0.so.0 => /lib64/libatk-1.0.so.0 (0x0000003e75600000)
libatk-bridge-2.0.so.0 => /lib64/libatk-bridge-2.0.so.0 (0x0000003e6c600000)
libpangoft2-1.0.so.0 => /lib64/libpangoft2-1.0.so.0 (0x0000003e71c00000)
libpango-1.0.so.0 => /lib64/libpango-1.0.so.0 (0x0000003e73600000)
libfontconfig.so.1 => /lib64/libfontconfig.so.1 (0x0000003e61600000)
libgio-2.0.so.0 => /lib64/libgio-2.0.so.0 (0x0000003e66600000)
libgobject-2.0.so.0 => /lib64/libgobject-2.0.so.0 (0x0000003e5fa00000)
libglib-2.0.so.0 => /lib64/libglib-2.0.so.0 (0x0000003e5e600000)
libXinerama.so.1 => /lib64/libXinerama.so.1 (0x0000003e61e00000)
libXrandr.so.2 => /lib64/libXrandr.so.2 (0x0000003e62200000)
libXcursor.so.1 => /lib64/libXcursor.so.1 (0x0000003e62e00000)
libXcomposite.so.1 => /lib64/libXcomposite.so.1 (0x0000003e74e00000)
libXdamage.so.1 => /lib64/libXdamage.so.1 (0x0000003e67e00000)
libwayland-client.so.0 => /lib64/libwayland-client.so.0 (0x0000003e6ec00000)
libxkbcommon.so.0 => /lib64/libxkbcommon.so.0 (0x0000003e6b000000)
libwayland-cursor.so.0 => /lib64/libwayland-cursor.so.0 (0x0000003e69c00000)
libXext.so.6 => /lib64/libXext.so.6 (0x0000003e5ea00000)
librt.so.1 => /lib64/librt.so.1 (0x0000003e5ce00000)
libgthread-2.0.so.0 => /lib64/libgthread-2.0.so.0 (0x0000003e61a00000)
libharfbuzz.so.0 => /lib64/libharfbuzz.so.0 (0x0000003e6f000000)
libfreetype.so.6 => /lib64/libfreetype.so.6 (0x0000003e60e00000)
libxcb.so.1 => /lib64/libxcb.so.1 (0x0000003e5da00000)
libpixman-1.so.0 => /lib64/libpixman-1.so.0 (0x0000003e6f800000)
libEGL.so.1 => /lib64/libEGL.so.1 (0x0000003e73200000)
libpng16.so.16 => /lib64/libpng16.so.16 (0x0000003e5f600000)
libxcb-shm.so.0 => /lib64/libxcb-shm.so.0 (0x0000003e6e800000)
libxcb-render.so.0 => /lib64/libxcb-render.so.0 (0x0000003e70800000)
libXrender.so.1 => /lib64/libXrender.so.1 (0x0000003e61200000)
libz.so.1 => /lib64/libz.so.1 (0x0000003e5ba00000)
libGL.so.1 => /lib64/libGL.so.1 (0x0000003e68200000)
libatspi.so.0 => /lib64/libatspi.so.0 (0x0000003e6c200000)
libdbus-1.so.3 => /lib64/libdbus-1.so.3 (0x0000003e62a00000)
libexpat.so.1 => /lib64/libexpat.so.1 (0x0000003e60a00000)
libffi.so.6 => /lib64/libffi.so.6 (0x0000003e5ee00000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003e5ca00000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x0000003e5e200000)
libgraphite2.so.3 => /lib64/libgraphite2.so.3 (0x0000003e6fc00000)
libXau.so.6 => /lib64/libXau.so.6 (0x0000003e5d600000)
libX11-xcb.so.1 => /lib64/libX11-xcb.so.1 (0x0000003e65e00000)
libxcb-dri2.so.0 => /lib64/libxcb-dri2.so.0 (0x0000003e67200000)
libxcb-xfixes.so.0 => /lib64/libxcb-xfixes.so.0 (0x0000003e70400000)
libxcb-shape.so.0 => /lib64/libxcb-shape.so.0 (0x0000003e72a00000)
libgbm.so.1 => /lib64/libgbm.so.1 (0x0000003e70c00000)
libudev.so.1 => /lib64/libudev.so.1 (0x0000003e63200000)
libwayland-server.so.0 => /lib64/libwayland-server.so.0 (0x0000003e74a00000)
libglapi.so.0 => /lib64/libglapi.so.0 (0x0000003e67600000)
libdrm.so.2 => /lib64/libdrm.so.2 (0x0000003e67a00000)
libxcb-glx.so.0 => /lib64/libxcb-glx.so.0 (0x0000003e66e00000)
libXxf86vm.so.1 => /lib64/libXxf86vm.so.1 (0x0000003e66200000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x0000003e5c600000)
liblzma.so.5 => /lib64/liblzma.so.5 (0x0000003e5c200000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003e5be00000)
Run Code Online (Sandbox Code Playgroud)
在Ubuntu上生成的C代码(GnuCOBOL使用C中间体)
/* Line: 4 : CALL : simple.cob */
cob_procedure_params[0] = (cob_field *)&c_1;
cob_procedure_params[1] = NULL;
cob_glob_ptr->cob_call_params = 2;
if (unlikely(call_gtk_init.funcvoid == NULL)) {
call_gtk_init.funcvoid = cob_resolve_cobol ("gtk_init", 0, 1);
}
call_gtk_init.funcnull ((cob_s32_t)0LL, NULL);
b_1 = 0;
Run Code Online (Sandbox Code Playgroud)
和Fedora
/* Line: 4 : CALL : simple.cob */
cob_procedure_params[0] = (cob_field *)&c_1;
cob_procedure_params[1] = NULL;
cob_glob_ptr->cob_call_params = 2;
if (unlikely(call_gtk_init.funcvoid == NULL)) {
call_gtk_init.funcvoid = cob_resolve_cobol ("gtk_init", 0, 1);
}
call_gtk_init.funcnull ((cob_s32_t)0LL, NULL);
b_1 = 0;
Run Code Online (Sandbox Code Playgroud)
当从C调用gtk_init时,我在Ubuntu(完整的ELF链接提示)上得到了很好的结果,而不是作为传递给cob_resolve的字符串.用gcc -o simple simple-gtk.c -lgtk-3测试
那么围绕-llibname的假设改变了什么?它似乎没有包含在dlopen的ELF数据中甚至打扰尝试寻找libgtk-3.so
更多信息:Ubuntu上的错误编译行确实使它看起来应该正常工作.(拼错gtk)
$ cobc -x -v -lgkt-3 simple.cob
Command line: cobc -x -v -lgkt-3 simple.cob
Preprocessing: simple.cob -> /tmp/cob13556_0.cob
Return status: 0
Parsing: /tmp/cob13556_0.cob (simple.cob)
Return status: 0
Translating: /tmp/cob13556_0.cob -> /tmp/cob13556_0.c (simple.cob)
Executing: gcc -std=gnu99 -c -I/usr/local/include -pipe -Wno-unused
-fsigned-char -Wno-pointer-sign -o "/tmp/cob13556_0.o"
"/tmp/cob13556_0.c"
Return status: 0
Executing: gcc -std=gnu99 -Wl,--export-dynamic -o "simple"
"/tmp/cob13556_0.o" -L/usr/local/lib -lcob -lm -lgmp -lncurses
-ldb -ldl -l"gkt-3"
/usr/bin/ld: cannot find -lgkt-3
collect2: error: ld returned 1 exit status
Return status: 256
Run Code Online (Sandbox Code Playgroud)
然而,使用正确的编译行,ELF没有显示gtk-3的链接提示
我现在已经开始关注这个问题一段时间了.寻找关于Ubuntu和gcc和/或ld和/或dlopen dlsym改变了什么假设的提示.
open-cobol软件包已经在Debian和Ubuntu存储库中工作了很多年.甚至Ubuntu上的旧版本的GnuCOBOL(GNU Cobol和/或OpenCOBOL)现在也都失败了.有些东西改变了,我们没有收到备忘录.不仅愿意改变编译器源,而且首先寻找友好的StackOverflow见解.
这似乎不是一个本地环境问题,因为这个Ubuntu问题也出现在其他人身上.这也感觉就像其中一个DOH!简单地解决问题.
超过愿意添加更多编译日志,LD_DEBUG =所有转储或straces等.
从输出中可以看出,动态查找的C代码gtk_init不知道libgtk-3.so在运行时加载实际的共享对象.
您可以使用该-fstatic-call选项使用cobc进行编译.这将gtk_init直接调用您的库函数,而不是通过调用dlopen/dlsym.有关此选项的更多信息,请参阅信息页面中的命令info opencobol:
使用编译器选项-fstatic-call,将生成更高效的代码,如下所示:
Run Code Online (Sandbox Code Playgroud)subr(X);请注意,只有当被调用的程序名称是文字(如
CALL "subr".'). With a data name (likeCALL SUBR.)时,此选项才有效,程序仍然是动态调用的.
如果你想进入动态路线,我只能建议告诉你的Cobol应用程序你想要在运行时加载哪些动态对象.为此,您可以COB_PRE_LOAD在启动应用程序之前设置环境变量.有关此环境变量的信息,请参见此Open Cobol 文档.特别是它说:
COB_PRE_LOAD是一个环境变量,用于控制运行中包含的动态链接模块.
$ cobc occurl.c
$ cobc occgi.c
$ cobc -x myprog.cob
$ export COB_PRE_LOAD=occurl:occgi
$ ./myprog
Run Code Online (Sandbox Code Playgroud)
这将允许OpenCOBOL运行时链接解析器在werel.so模块中找到CALL"CBL_OC_CURL_INIT"的入口点.注意:COB_PRE_LOAD环境变量中列出的模块没有扩展名.OpenCOBOL将在各种平台上做正确的事情.
你可以用两种方式做(使用bash):
COB_PRE_LOAD=libgtk-3 ./simple
Run Code Online (Sandbox Code Playgroud)
这将设置COB_PRE_LOAD为使用libgtk-3.so(你离开.so)启动你的应用程序,并在完成重置COB_PRE_LOAD回原来的时候.您还可以使用export在会话期间设置环境变量:
export COB_PRE_LOAD=libgtk-3
./simple
Run Code Online (Sandbox Code Playgroud)
您可以使用COB_PRE_LOAD冒号分隔多个共享对象.因此,如果您需要libgtk-3,libgmp例如,您可以这样做:
COB_PRE_LOAD=libgtk-3:libgmp ./simple
Run Code Online (Sandbox Code Playgroud)
这看起来是对ubuntu的编译器驱动程序所做的更改 - 它--as-needed在将代码发送到collect2链接器时将选项添加到编译行.
为了理解发生了什么,我们需要反汇编cobc的执行而不是显示它:
cobc -x -v simple.cob -lgtk-3
preprocessing simple.cob into /tmp/cob2743_0.cob
translating /tmp/cob2743_0.cob into /tmp/cob2743_0.c
gcc -pipe -c -Wno-unused -fsigned-char -Wno-pointer-sign -o /tmp/cob2743_0.o /tmp/cob2743_0.c
gcc -pipe -Wl,--export-dynamic -o simple /tmp/cob2743_0.o -L/usr/lib -lcob -lm -lgmp -lncurses -ldb -ldl -lgtk-3
Run Code Online (Sandbox Code Playgroud)
如果我们将其分解为生成C代码,然后编译它我们得到:
cobc -C -x -v simple.cob
gcc -pipe -c -Wno-unused -fsigned-char -Wno-pointer-sign -o simple.o simple.c
gcc -pipe -Wl,--export-dynamic -o simple simple.o -L/usr/lib -lcob -lm -lgmp -lncurses -ldb -ldl -lgtk-3
Run Code Online (Sandbox Code Playgroud)
我们需要进一步将最后一个gcc行拆解成:
gcc -### -pipe -Wl,--export-dynamic -o simple simple.o -L/usr/lib -lcob -lm -lgmp -lncurses -ldb -ldl -lgtk-3
Run Code Online (Sandbox Code Playgroud)
产量为:
/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 "--sysroot=/" --build-id --eh-frame-hdr -m elf_x86_64 "--hash-style=gnu" --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o simple /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. --export-dynamic simple.o -lcob -lm -lgmp -lncurses -ldb -ldl -lgtk-3 -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o
Run Code Online (Sandbox Code Playgroud)
问题是第一个 --as-needed选项的存在- 它推翻-l了命令行上的所有显式选项 - 如果在.o组成依赖于库的文件中找不到任何内容,它将不会链接库 - 这是确切的动态加载情况.
这似乎是Oneiric以来的情况.
这个最简单的解决方法是添加:
COB_LDFLAGS=-Wl,--no-as-needed
Run Code Online (Sandbox Code Playgroud)
你的环境应该解决链接问题.