Summary: | gcc_lib_dir is missing from libgccjit's search path when driver is not installed | ||
---|---|---|---|
Product: | gcc | Reporter: | Matthias Klose <doko> |
Component: | jit | Assignee: | David Malcolm <dmalcolm> |
Status: | ASSIGNED --- | ||
Severity: | normal | CC: | leonard, sjames, slyfox, ulm |
Priority: | P3 | ||
Version: | 9.0 | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | 2019-07-22 00:00:00 |
Description
Matthias Klose
2018-10-30 10:31:34 UTC
it looks like the code can run without the external driver, but it cannot find the needed files in the install location. playback::context::invoke_driver builds the command line for the driver. Does it work with each of these: gcc_jit_context_set_bool_use_external_driver (ctxt, 1); gcc_jit_context_set_bool_use_external_driver (ctxt, 0); If you call: gcc_jit_context_set_logfile (ctxt, stderr, 0, 0); a verbose log will be written to stderr. See e.g.: https://gcc.gnu.org/onlinedocs/jit/internals/index.html#example-of-log-file In particular, the log for gcc::jit::playback::context::invoke_driver will show the arguments that the driver is being called with. Does it successfully link if you manually invoke the driver with those arguments? You definitely need binutils for libgccjit; it calls the driver (embedded internally in the .so by default), which invokes the assembler and linker. Understood, that I need binutils. However if you remove the driver (or rename it on your system), then the debug output reads: JIT: entering: virtual void gcc::jit::playback::compile_to_memory::postprocess(const char*) JIT: entering: void gcc::jit::playback::context::convert_to_dso(const char*) JIT: entering: void gcc::jit::playback::context::invoke_driver(const char*, const char*, const char*, timevar_id_t, bool, bool) JIT: entering: void gcc::jit::playback::context::add_multilib_driver_arguments(vec<char*, va_heap, vl_ptr>*) JIT: exiting: void gcc::jit::playback::context::add_multilib_driver_arguments(vec<char*, va_heap, vl_ptr>*) JIT: argv[0]: x86_64-linux-gnu-gcc-9 JIT: argv[1]: -m64 JIT: argv[2]: -shared JIT: argv[3]: /tmp/libgccjit-p43Zl1/fake.s JIT: argv[4]: -o JIT: argv[5]: /tmp/libgccjit-p43Zl1/fake.so JIT: argv[6]: -fno-use-linker-plugin JIT: entering: void gcc::jit::playback::context::invoke_embedded_driver(const vec<char*, va_heap, vl_ptr>*) ld: cannot find crtbeginS.o: No such file or directory ld: cannot find -lgcc ld: cannot find -lgcc_s JIT: entering: void gcc::jit::recording::context::add_error_va(gcc::jit::recording::location*, const char*, __va_list_tag*) JIT: error 0: error invoking gcc driver libgccjit.so: error: error invoking gcc driver JIT: exiting: void gcc::jit::recording::context::add_error_va(gcc::jit::recording::location*, const char*, __va_list_tag*) JIT: exiting: void gcc::jit::playback::context::invoke_embedded_driver(const vec<char*, va_heap, vl_ptr>*) JIT: exiting: void gcc::jit::playback::context::invoke_driver(const char*, const char*, const char*, timevar_id_t, bool, bool) JIT: exiting: void gcc::jit::playback::context::convert_to_dso(const char*) JIT: exiting: virtual void gcc::jit::playback::compile_to_memory::postprocess(const char*) so something is calling the external driver ... Log of our chat about this on IRC: <doko> dmalcolm: so the driver has to be present to use libgccjit? <dmalcolm> doko: if you call gcc_jit_context_set_bool_use_external_driver (ctxt, 1) it does; it defaults to using an internal driver though iirc * dmalcolm checks <dmalcolm> yup <doko> dmalcolm: looking at https://paste.ubuntu.com/p/Sz2hJ8rKZX/ the external driver is called despite explicitly calling gcc_jit_context_set_bool_use_external_driver (ctxt, 0); at least that's how I interpret the debug output <dmalcolm> doko: I don't think it is. I see calls that invoke_driver is calling invoke_embedded_driver <dmalcolm> s/calls // <doko> dmalcolm: no, https://paste.ubuntu.com/p/KZV5jJQNRf/ this is with the x86_64-linux-gnu-gcc-9 removed <dmalcolm> bother <dmalcolm> doko: maybe try passing gcc_jit_context_add_command_line_option (ctxt, "-v") or similar to get a more verbose output from the embedded driver <dmalcolm> s/passing/calling/ <dmalcolm> doko: sorry, gcc_jit_context_add_driver_option, I meant to say <doko> dmalcolm: https://paste.ubuntu.com/p/vRKRqXy65Y/ this is clearly output from the external driver ... <doko> or maybe I'm misunderstanding what the internal driver is, if it calls the external one <dmalcolm> doko: the "internal driver" is gcc.o linked inside libgccjit.so It's the same code as the regular "gcc" binary, but called as a function. The log shows it calling "invoke_embedded_driver" <dmalcolm> doko: so yes, it looks remarkably like as if it had fork&exec-ed gcc, but it's running that code in-process <doko> dmalcolm: ok, but why do I see these errors, when I remove the external driver? <dmalcolm> doko: good question <dmalcolm> doko: I see in that log: <dmalcolm> COMPILER_PATH= <dmalcolm> LIBRARY_PATH=/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/lib/:/usr/lib/ <dmalcolm> doko: does that change when reinstalling the external driver? <dmalcolm> doko: presumably you're not uninstalling the .o and libs it's looking for, right? I'm assuming this is just a "choosing the right directory to look in" issue <doko> dmalcolm: yes, just removing the driver, nothing else. See https://paste.ubuntu.com/p/T7J9DDDTqW/ look at COMPILER_PATH and LIBRARY_PATH <dmalcolm> doko: interesting. It's also calling collect2 vs calling ld <doko> that explains why it succeeds without the driver, and manually setting LIBRARY_PATH <dmalcolm> doko: looking at gcc.c I see various places using gcc_exec_prefix where it's locating things relative to the driver binary <dmalcolm> doko: I think make_relative_prefix is looking for the driver based on PATH <dmalcolm> doko: when the driver binary is present, the gcc.c code finds its directory, via get_relative_prefix, and sets gcc_exec_prefix and gcc_libexec_prefix, I think <dmalcolm> doko: when the driver binary is not in PATH, it doesn't find it, and those vars don't get set up <dmalcolm> doko: does it work if you set GCC_EXEC_PREFIX in the environment? presumably to /usr/lib/gcc/x86_64-linux-gnu/9/ or somesuch <doko> dmalcolm: yes <dmalcolm> doko: I wonder if we can get it work by having it look relative to the .so, rather than relative to the driver <dmalcolm> doko: oh, that's not going to work; make_relative_prefix looks for the thing on the PTH <dmalcolm> PATH, even <doko> dmalcolm: yep, that's what I just found as well <dmalcolm> doko: I think the pertinent comment here is: <dmalcolm> /* From this point onward, gcc_exec_prefix is non-null if the toolchain <dmalcolm> is relocated. The toolchain was either relocated using GCC_EXEC_PREFIX <dmalcolm> or an automatically created GCC_EXEC_PREFIX from <dmalcolm> decoded_options[0].arg. */ <dmalcolm> doko: and the logic for the latter depends on locating decoded_options[0].arg <dmalcolm> doko: by finding it on PATH <doko> ... which doesn't cover libgccjit's use case <doko> dmalcolm: should libgccjit set GCC_EXEC_PREFIX in the environment when it's not set? <dmalcolm> doko: perhaps. But it's good to be relocatable. I'm not sure what the value it would set it to should be <dmalcolm> doko: is there a way for a .so to ask: what location am I linked from? <dmalcolm> (analogous to how the driver binary is querying PATH to try to find where it's been run from) <doko> dmalcolm: /proc/self/maps ? <dmalcolm> gahh <dmalcolm> doko: that could work, but sounds like a portability nightmare <dmalcolm> doko: if this is a purely packaging thing, can we ignore relocatability for this use-case, and hardcode where the installation path will be? <dmalcolm> doko: then have libgccjit set GCC_EXEC_PREFIX to the correct (hardcoded) path for packaged builds <doko> dmalcolm: +1, otherwise I would have to add a gcc dependency tp libgccjit0 <dmalcolm> doko: in Fedora we have a gcc dep for libgccjit <doko> yes, that's the other option <doko> dmalcolm: when adding that, where should this go? <dmalcolm> doko: totally untested: https://paste.fedoraproject.org/paste/sPA97QW4RkS5LHPjGAcxFg <dmalcolm> doko: (plus it needs a comment explaining why we're doing it) <doko> dmalcolm: ok, I'll look into that tomorrow <dmalcolm> doko: or just add the dep :) I'm also seeing this same problem simply from not having the gcc driver in PATH. Using the example from downstream redhat BZ 1566178: [sawdey@marlin trunk]$ /home2/sawdey/work/gcc/trunk/install/bin/gcc -Wl,-rpath,/home2/sawdey/work/gcc/trunk/install/lib -g -Wall -Werror t.c -lgccjit [sawdey@marlin trunk]$ ./a.out ld: cannot find crtbeginS.o: No such file or directory ld: cannot find -lgcc ld: cannot find -lgcc_s libgccjit.so: error: error invoking gcc driver gcc_jit_result_get_code: NULL result Segmentation fault (core dumped) [sawdey@marlin trunk]$ PATH=/home2/sawdey/work/gcc/trunk/install/bin:$PATH ./a.out hello foo Using strace the failing version makes this ld command, with no path for crtbeginS.o: /usr/bin/ld --eh-frame-hdr -shared -m elf64lppc -o /tmp/libgccjit-lMbVEL/fake.so /usr/lib/powerpc64le-linux-gnu/crti.o crtbeginS.o -L/lib/powerpc64le-linux-gnu -L/lib/../lib64 -L/usr/lib/powerpc64le-linux-gnu /tmp/cchtuxH0.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state crtendS.o /usr/lib/powerpc64le-linux-gnu/crtn.o When it can find the driver, this is the ld command, with the full path to the correct installed bits: /usr/bin/ld --eh-frame-hdr -shared -m elf64lppc -o /tmp/libgccjit-t81bpM/fake.so /usr/lib/powerpc64le-linux-gnu/crti.o /home2/sawdey/work/gcc/trunk/install/lib/gcc/powerpc64le-unknown-linux-gnu/10.0.0/crtbeginS.o -L/home2/sawdey/work/gcc/trunk/install/lib/gcc/powerpc64le-unknown-linux-gnu/10.0.0 -L/home2/sawdey/work/gcc/trunk/install/lib/gcc/powerpc64le-unknown-linux-gnu/10.0.0/../../../../lib64 -L/lib/powerpc64le-linux-gnu -L/lib/../lib64 -L/usr/lib/powerpc64le-linux-gnu -L/home2/sawdey/work/gcc/trunk/install/lib/gcc/powerpc64le-unknown-linux-gnu/10.0.0/../../.. /tmp/ccD4Cbi4.o -lgcc --push-state --as-needed -lgcc_s -pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /home2/sawdey/work/gcc/trunk/install/lib/gcc/powerpc64le-unknown-linux-gnu/10.0.0/crtendS.o /usr/lib/powerpc64le-linux-gnu/crtn.o This is with trunk, configured with --disable-bootstrap --enable-languages=c,c++,jit --enable-host-shared --prefix=/home2/sawdey/work/gcc/trunk/install a patch was posted at https://gcc.gnu.org/ml/gcc-patches/2019-03/msg01045.html Is there any blocker preventing the patch to be merged? This bug can be easily reproduced by masquerading gcc binary with ccache compiler cache. ln -s ccache /usr/local/bin/gcc See https://ccache.dev/manual/4.2.1.html#_run_modes Then % which gcc /usr/lib/ccache/bin/gcc % ./tut01-hello-world ld: cannot find crtbeginS.o: No such file or directory ld: cannot find -lgcc ld: cannot find -lgcc_s libgccjit.so: error: error invoking gcc driver NULL result% and % PATH=/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin which gcc /usr/bin/gcc % PATH=/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin ./tut01-hello-world hello world Gentoo also noticed that ccache presence breaks programs using gccjit: https://bugs.gentoo.org/801580#c2 |