rizsotto / Bear

Bear is a tool that generates a compilation database for clang tooling.
GNU General Public License v3.0
4.64k stars 306 forks source link

Running 'nrfutil pkg' through bear won't find GLIBCXX_3.4.30 - add a "de-wrapper"? #556

Closed pengi closed 7 months ago

pengi commented 7 months ago

Describe the bug In our build system, we depend on nrfutil pkg to be able to pack firmwares. Therefore, that is well integerated in our makefiles.

Running those makefiles through bear causes problems on the nrfutil pkg ... line.

To simplify even:

root@0a85e4983f2c:/# bear -- nrfutil pkg
/usr/lib/x86_64-linux-gnu/bear/wrapper: /tmp/_MEID3Luz1/libstdc++.so.6: version `GLIBCXX_3.4.30' not found (required by /lib/x86_64-linux-gnu/libspdlog.so.1.10)

While on same machine (docker container in this case):

root@0a85e4983f2c:/# nrfutil pkg
Usage: pc_nrfutil_legacy_v6.1.7 pkg [OPTIONS] COMMAND [ARGS]...
...

I can build everything with the bear --force-wrapper argument, but then it only catches the files compiled with gcc, and not the ones compiled with arm-none-eabi-gcc, for what I can tell, which is the majority of our project. Therefore I seem to need to use the preload method.

There is one thing about those tools that don't work, I don't care about the output of them in bear, since I'm trying to integrate with cppcheck. Therefore, it would be a fully workable solution for me to have a command that explicitly tells bear to unload before running the command, so that command would not be logged.

I can't really find a way to properly create such de-wrapper myself. So if that is possible to make easily, then I guess this ticket is also a request for how to make one?

To Reproduce Steps to reproduce the behavior:

Easiest way I managed to reproduce it is to use docker:

Creeate a file Dockerfile in an empty directory:

FROM debian:bookworm-20231120
RUN apt update && apt install -y wget bear
ADD https://developer.nordicsemi.com/.pc-tools/nrfutil/x64-linux/nrfutil /usr/local/bin/nrfutil
RUN chmod +x /usr/local/bin/nrfutil && nrfutil install nrf5sdk-tools

In same directory, type:

docker build -t bear_nrfutil_test .
docker run --rm -t bear_nrfutil_test bear -- nrfutil pkg # not working
docker run --rm -t bear_nrfutil_test nrfutil pkg # working

or if you want to enter docker container interactively:

docker run --rm -t -i bear_nrfutil_test

Expected behavior Expect the behaviour to be the same with and without bear

Environment:

Additional context

Before you send...

rizsotto commented 7 months ago

Hey @pengi , thanks for the report. I have not spent time to reconstruct the bug on my machine, because I strongly believe it's not much to do with Bear code base. The error is coming from the dynamic linker, which loads the binaries into memory.

Why would a binary linked against /tmp/_MEID3Luz1/libstdc++.so.6 a file from the /tmp directory? That looks very fishy!

pengi commented 7 months ago

Yes, I agree that is odd. But it doesn't explain why it works all the time without bear, but adding bear breaks it.

But yes, I am going to open a bug report to nrfutil too.

But I see more nrfutil as an example in this case, and the one I've ended up with. The fact is that bear is to some extent intrusive to the environment for the commands running within make. And most of the cases it's fine and works well.

So my suggestion would be, possibly just documentation if it's an easy thing to do, but to add a wrapper to unload bear for a single command in make.

For example, create a makefile like this:

my_target:
    $(NOBEAR) sensitive command

# Target that we want to track
%.o: %.c
    $(CC) -c -o $@ $<

When just calling make, then everything would be fine.

But lets say making a tool, lets call it nobear.sh, that can wrap the command and undo what bear does for that single command. Then it would be possible to call it using bear -- make NOBEAR=./nobear.sh

There are many tools out there that have questionable implementation, or using dynamic loading. And even though it would be nice to fix all of them, compatibility comes from expecting and providing a system that works according to specifications, but accepting as much as possible.

I think this ticket was more like a feature request or ask for help rather than actually bug report though.

rizsotto commented 7 months ago

I have no experience with the nrfutils, but my theory is this... It looks to me, that nrftools are delivering the development tools (compilers, linkers, etc..) in their installation. These tools are "self contained", in a sense that they bringing their own libraries (libC, libC++, etc...). And those tools are linked against a different version of libC++ than the wrapper tool in Bear. When wrapper is executed and forced to load their libC++, and it fails with version mismatch.

To solve this issue, Bear might want to statically link the wrapper. (This is hard, because it's mostly depends on the package creators.) But that would still not solve the issue completely, because after the wrapper is executed, it executes their compiler, and force to load the libexec.so into that process, which is again linked against a different libC++.

If they are deliver the development tools, they might want to deliver Bear too. :) Or you could try to compile Bear against that version of libC++.