Bug 1566178 - ld: cannot find -lgcc when using libgccjit
Summary: ld: cannot find -lgcc when using libgccjit
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Fedora
Classification: Fedora
Component: gcc
Version: 27
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Dave Malcolm
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2018-04-11 17:34 UTC by Marek Polacek
Modified: 2018-08-10 14:38 UTC (History)
10 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2018-08-10 14:38:52 UTC
Type: Bug


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
GNU Compiler Collection 85384 0 None None None 2018-04-12 18:36:00 UTC

Description Marek Polacek 2018-04-11 17:34:19 UTC
E.g. this:

#include <libgccjit.h>
int
main (int argc, char **argv)
{
  gcc_jit_context *ctxt;
  gcc_jit_result *result;
  typedef int (*some_fn_type) (const char *);
  ctxt = gcc_jit_context_acquire ();
  gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
  gcc_jit_type *const_char_ptr_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR);
  gcc_jit_param *param_name =
    gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "name");
  gcc_jit_function *func =
    gcc_jit_context_new_function (ctxt, NULL,
                                  GCC_JIT_FUNCTION_EXPORTED,
                                  void_type,
                                  "some_fn",
                                  1, &param_name,
                                  0);

  gcc_jit_param *param_format =
    gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "format");
  gcc_jit_function *printf_func =
    gcc_jit_context_new_function (ctxt, NULL,
                                  GCC_JIT_FUNCTION_IMPORTED,
                                  gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT),
                                  "printf",
                                  1, &param_format,
                                  1);
  gcc_jit_rvalue *args[2];
  args[0] = gcc_jit_context_new_string_literal (ctxt, "hello %s\n");
  args[1] = gcc_jit_param_as_rvalue (param_name);

  gcc_jit_block *block = gcc_jit_function_new_block (func, "initial");
  gcc_jit_block_add_eval (
    block, NULL,
    gcc_jit_context_new_call (ctxt,
                              NULL,
                              printf_func,
                              2, args));
  gcc_jit_block_end_with_void_return (block, NULL);
  result = gcc_jit_context_compile (ctxt);
  gcc_jit_context_release (ctxt);
  some_fn_type some_fn  = (some_fn_type)gcc_jit_result_get_code (result, "some_fn");
  some_fn ("foo");
  gcc_jit_result_release (result);
}

when compiled as
$ gcc -g -Wall -Werror jit.c -lgccjit
and run in e.g. /tmp/foo gives errors:
$ ./a.out 
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)

The problem is that libgccjit seems to use relative paths, as can be seen in
$ strace ./a.out
so the proper libraries aren't found.

If the binary is run e.g. from /tmp, it works as expected.

Comment 1 Dave Malcolm 2018-04-11 19:39:36 UTC
I can reproduce with:
  libgccjit-7.3.1-2.fc26.x86_64
  libgccjit-devel-7.3.1-2.fc26.x86_64

a.out fails the link, except when run from /tmp.

On trying with:
  gcc_jit_context_set_bool_use_external_driver (ctxt, 1);

it fails with:

libgccjit.so: error trying to exec 'x86_64-redhat-linux-gcc-7.3.1': execvp: No such file or directory
libgccjit.so: error: error invoking gcc driver: exit_status: 65280 err: 0
libgccjit.so: error: whilst attempting to run a driver named: x86_64-redhat-linux-gcc-7.3.1
libgccjit.so: error: PATH was: /usr/libexec/python2-sphinx:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/home/david/.local/bin:/home/david/bin
gcc_jit_result_get_code: NULL result
Segmentation fault (core dumped)


On adding:

  sudo ln -s /usr/bin/gcc /usr/bin/x86_64-redhat-linux-gcc-7.3.1

then it works:

$ ./a.out 
hello foo

...and with that symlink in place, it now works using the embedded driver, and that stops working if I remove that symlink.

Am investigating.

Comment 2 Jakub Jelinek 2018-04-11 19:48:48 UTC
We have just
/usr/bin/x86_64-redhat-linux-gcc-7
binary, not -7.3.1; and the reason for that is that Fedora gcc is configured with
--with-gcc-major-version-only
Perhaps something in jit doesn't honor this configure option then?

Comment 3 Dave Malcolm 2018-04-11 19:55:51 UTC
Running with the embedded driver (the default), and manually hacking in "-v" to the driver invocation via:

  (gdb) break gcc::jit::playback::context::invoke_embedded_driver
  (gdb) watch global_options->x_verbose_flag
  (gdb) set global_options->x_verbose_flag = 1

shows the following real differences between the outside vs inside /tmp cases (after manually hacking up the various irrelevant differences e.g. tmpdir names, process IDs, etc to be "XXXXXX").

diff -up outside-tmp.txt within-tmp.txt
--- outside-tmp.txt	2018-04-11 15:46:12.735802196 -0400
+++ within-tmp.txt	2018-04-11 15:46:21.544884909 -0400
@@ -11,10 +11,8 @@ COLLECT_GCC_OPTIONS='-m64' '-shared' '-o
  as --64 -o /tmp/ccXXXXXX.o /tmp/libgccjit-XXXXXX/fake.s
 Detaching after vfork from child process XXXXX.
 COMPILER_PATH=
-LIBRARY_PATH=/lib/../lib64/:/usr/lib/../lib64/:/lib/:/usr/lib/
+LIBRARY_PATH=../lib/gcc/x86_64-redhat-linux/7/:../lib/gcc/:../lib/gcc/x86_64-redhat-linux/7/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:../lib/gcc/x86_64-redhat-linux/7/../../../:/lib/:/usr/lib/
 COLLECT_GCC_OPTIONS='-m64' '-shared' '-o' '/tmp/libgccjit-XXXXXX/fake.so' '-fno-use-linker-plugin' '-mtune=generic' '-march=x86-64'
- ld --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -shared -o /tmp/libgccjit-XXXXXX/fake.so /lib/../lib64/crti.o crtbeginS.o -L/lib/../lib64 -L/usr/lib/../lib64 /tmp/ccXXXXXX.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed crtendS.o /lib/../lib64/crtn.o
+ ld --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -shared -o /tmp/libgccjit-XXXXXX/fake.so ../lib/gcc/x86_64-redhat-linux/7/../../../../lib64/crti.o ../lib/gcc/x86_64-redhat-linux/7/crtbeginS.o -L../lib/gcc/x86_64-redhat-linux/7 -L../lib/gcc -L../lib/gcc/x86_64-redhat-linux/7/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L../lib/gcc/x86_64-redhat-linux/7/../../.. /tmp/ccXXXXXX.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed ../lib/gcc/x86_64-redhat-linux/7/crtendS.o ../lib/gcc/x86_64-redhat-linux/7/../../../../lib64/crtn.o
 Detaching after vfork from child process XXXXX.
-ld: cannot find crtbeginS.o: No such file or directory
-ld: cannot find -lgcc
-ld: cannot find -lgcc_s
+COLLECT_GCC_OPTIONS='-m64' '-shared' '-o' '/tmp/libgccjit-XXXXXX/fake.so' '-fno-use-linker-plugin' '-mtune=generic' '-march=x86-64'

In particular, LIBRARY_PATH goes from:

  /lib/../lib64/
  /usr/lib/../lib64/
  /lib/
  /usr/lib/

to:

  ../lib/gcc/x86_64-redhat-linux/7/
  ../lib/gcc/
  ../lib/gcc/x86_64-redhat-linux/7/../../../../lib64/
  /lib/../lib64/
  /usr/lib/../lib64/
  ../lib/gcc/x86_64-redhat-linux/7/../../../
  /lib/
  /usr/lib/

and the "ld" invocations' options go from:

  ld --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu \
    -m elf_x86_64 -shared -o /tmp/libgccjit-XXXXXX/fake.so \
    /lib/../lib64/crti.o \
    crtbeginS.o \
    -L/lib/../lib64 \
    -L/usr/lib/../lib64 \
    /tmp/ccXXXXXX.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed \
    crtendS.o \
    /lib/../lib64/crtn.o

to:
  ld --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu \
    -m elf_x86_64 -shared -o /tmp/libgccjit-XXXXXX/fake.so \
    ../lib/gcc/x86_64-redhat-linux/7/../../../../lib64/crti.o \
    ../lib/gcc/x86_64-redhat-linux/7/crtbeginS.o \
    -L../lib/gcc/x86_64-redhat-linux/7 \
    -L../lib/gcc \
    -L../lib/gcc/x86_64-redhat-linux/7/../../../../lib64 \
    -L/lib/../lib64 \
    -L/usr/lib/../lib64 \
    -L../lib/gcc/x86_64-redhat-linux/7/../../.. \
    /tmp/ccXXXXXX.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed \
    ../lib/gcc/x86_64-redhat-linux/7/crtendS.o \
    ../lib/gcc/x86_64-redhat-linux/7/../../../../lib64/crtn.o

Comment 4 Dave Malcolm 2018-04-11 20:18:46 UTC
(In reply to Jakub Jelinek from comment #2)
> We have just
> /usr/bin/x86_64-redhat-linux-gcc-7
> binary, not -7.3.1; and the reason for that is that Fedora gcc is configured
> with
> --with-gcc-major-version-only

Aha - thanks.

> Perhaps something in jit doesn't honor this configure option then?

Indeed.

gcc/configure.ac has:

  # Determine what GCC version number to use in filesystem paths.
  GCC_BASE_VER

using config/acx.m4 to define get_gcc_base_ver honoring --with-gcc-major-version-only.

Later on it has:

# Generate gcc-driver-name.h containing GCC_DRIVER_NAME for the benefit
# of jit/jit-playback.c.
cat > gcc-driver-name.h <<EOF
#define GCC_DRIVER_NAME "${target_noncanonical}-gcc-${gcc_BASEVER}${exeext}"
EOF

So presumably the generation of GCC_DRIVER_NAME simply needs to use get_gcc_base_ver rather than gcc_BASEVER to properly respect  --with-gcc-major-version-only.

Am working on a fix for that.

Notes to self:

gcc/Makefile.in has:
  version     := $(shell @get_gcc_base_ver@ $(BASEVER))
and:

  # Install the driver program as $(target_noncanonical)-gcc,
  # $(target_noncanonical)-gcc-$(version), and also as gcc if native.
  install-driver: installdirs xgcc$(exeext)

Comment 5 Dave Malcolm 2018-04-12 18:36:00 UTC
(In reply to Jakub Jelinek from comment #2)
> We have just
> /usr/bin/x86_64-redhat-linux-gcc-7
> binary, not -7.3.1; and the reason for that is that Fedora gcc is configured
> with
> --with-gcc-major-version-only
> Perhaps something in jit doesn't honor this configure option then?

I've filed https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85384 to cover that.

Comment 6 Marek Polacek 2018-08-10 14:38:52 UTC
Should be fixed now.


Note You need to log in before you can comment on or make changes to this bug.