Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test does not run from inside statically linked library (gcc) #141

Open
aganm opened this issue Dec 2, 2023 · 4 comments
Open

Test does not run from inside statically linked library (gcc) #141

aganm opened this issue Dec 2, 2023 · 4 comments

Comments

@aganm
Copy link
Contributor

aganm commented Dec 2, 2023

I started organizing groups of related test files into their own static libraries such that all the static libraries will get linked together into a single test executable. The reason for this is because I need to compile multiple test executables which have different characteristics, which does not affect test code, but can affect the code under test. So instead of recompiling the tests everytime, I want to put the tests in a static library which will be reused for all of my test executables, cutting down my compile times by a significant amount.

The issue is that test cases that are inside a static library do not get run from the executable's UTEST_MAIN.

I tested __attribute__((constructor)) from inside a static library and the attribute works as expected. Could it be something with UTEST global arrays not being shared across the static library and the executable?

Edit: I think I tested the __attribute__((constructor)) wrong, I'm trying it again and it won't run anymore. I'm getting hella confused.

Edit 2: Okay.. I think I know what is going on here.

  1. main executable + static library __attribute__((constructor)) function, the constructor does not run.

  2. main executable + static library __attribute__((constructor)) + regular function,
    when the main executable calls the regular function from the same file as the constructor in the static library,
    the constructors inside the static library get called!

So the solution would seem to be: put a bootstrap function inside each test file in the static library, and call each bootstrap function from the executable to trigger the constructors in the static library.

Ooooff.

@sheredom
Copy link
Owner

sheredom commented Dec 2, 2023

I'll guess it is something with the constructors yeah. We'll need a test case for this probably, so I'll keep the issue around for when I have the energy.

@aganm
Copy link
Contributor Author

aganm commented Feb 13, 2024

I found the solution to my problem on this stack overflow answer .

unreferenced symbols from archive does not make it to the output binary, because linker discards them by default.

So it's not a constructor attribute issue, any translation unit that does not get explicitly called to will get discarded by the linker. But there is an easier solution than what I did initially:

To override this behaviour when linking with static library, --whole-archive/--no-whole-archive options for the linker may be used [...] This may lead to bloated binary, because all symbols from foo.a will be included by the linker to the output, but sometimes it is justified.

Not sure what I'll do about this because I've already spent the time updating my tests with bootstrap functions as explained in my original message. But at the same time I would gladly delete all this bootstrap boilerplate.

I should write a note about this in the readme.

@sheredom
Copy link
Owner

I wonder if we can mark the symbol with attribute((used)) or something to stop it ripping them out?

@aganm
Copy link
Contributor Author

aganm commented Feb 15, 2024

I tried attribute((used)) to no avail. Thank you for your suggestion nonetheless!

Also I might have to backtrack on the stack overflow solution --whole-archive, I can't get it to work in my larger project. 😫

Bootstraps will remain for now. Until a better solution comes up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants