As you provide no source code is it difficult to give you a point to the solution. I suggest you the following to get to the traitor:
Provide a fake version for the aux() function, so the linker can continue linking your code.
Run it in the debugger. Put a breakpoint on aux sy mbol.
Run the code, when the debugger stops at aux() show a trace of the function calls to that point using the debugger command where.
This should help you find the path to the aux function without any imprecision.
If the aux() function is not called at all using the debugger, then there's another alternative that allows you to check why de linker decided to include de aux() function:
Generate a map file, for that just include a
--map=your_program.map
to the linker command, or using
-Wl,--map=your_program.map
if you invoke the linker through the compiler.
The linker generates a list of library dependencies satisfied, indicating the module that triggered the dependency to be included. This will help without any chance of failing.
Remember, the linker never generates a dependency error if there''s no reference to be solved. The linker will never know anything about your aux() function if it is actually never mentioned in the main program. Si it must be mentioned somewhere.
By the way, if you want to put (as it seems to by your question) two sets of functions that are unrelated (f() -> aux() and unrelated g() -> nothing) then never put them in the same compilation unit (this means they will never be linked into a .so shared unit) use f.c and g.c You will only require aux() when you have selected f.c in your program.
The linker cannot subdivide a compilation unit to include only part of the functions. (and more when creating a C --this is not C++-- project) You need to structure your library to use compilation unit that will represent the sufficient granularity to allow you to do what you want. If you have included two functions in the compilation unit, they will be included both, or none of them. This is most probably where the unknown dependence appears. The language is flexible enough to allow you to subdivide the library into a set of different .o objects. If you are building a shared library, it is linked as a shared object (not a library archive, where the linker can select the appropiate compilation units to include only the ones referenced in the main program) and the linker doesn't know which functions will the program to be using the library will need, so the shared objects are loaded at runtime in full, as they are shared between all programs that use the library.
The linker doesn't know anything about the internal relationships of the functions included in a compilation library (this doesn't need to be a callable symbol, but a reference to a global variable shared by both functions, which makes impossible to detect where to split the compilation unit without knows how the source was compiled)
A solution would be to put f() in a separate compilation unit, so you will need to include the compilation unit providing aux() only in the case you have included also f() and put both in a .a library archive. This makes the linker to select from the .a archive only the objects (.o or .so) that are required to solve references.
It's not clear what you try to solve, because IMHO you are not understanding the use of a shared library. You cannot link it including only the functions you need in your exact program, you link all, because the library doesn't actually know how many programs will make use of it (the text and read only data of a library are shared between all processes that load that shared library, so there's no penalty on having it replicated to all complete, probably a different program making use of that library will use the function you try to evict)
qsort()which requires a callback function? Or wasf()reliant on anaux()function which doesn't appear in any compilation unit?fto have to know what library to link with to get the definition ofauxor else I suppose that user would get the same linking error? If you don't want to split thefandglibrary in two, add a dependency to the library containingauxso that linking with thefandglibrary automatically links with theauxlibrary.target_link_libraries(f_and_g_lib PUBLIC aux_lib)in cmake lingo.f()with an argument providing the user's auxiliary function, then no callback function is needed. Is this an X-Y question?