I found a lot of questions on the hidden symbol topic in C static library.
I tried a lot of things:
-> Add strip and optimisation -O3 -s CFLAGS
-> Add -Wl,--exclude-libs,ALL" "-Wl,-Bsymbolic LDFLAGS
-> Add -fvisibility=hidden and __attribute__ ((visibility ("hidden")))
I cannot make it work properly. Instead of a long explanation, nothing is better than a project example using a very simple source tree to demonstrate my issue: https://github.com/Evanok/static_library_hidden_test
In this repository, I am using CMake to generate a static library. The only public API is in tutu1.h. I also add a test directory to validate the linking and execution of the library with a main.
I was able to hide the source file name using a post bash-script, but I cannot hide symbols in the final static library file.
This is the current result:
rm -rf build/ && cmake -DDEBUG=OFF -B build -S . && cmake --build build && nm build/libtutu.a
(...)
[100%] Built target static_tutu_library
private_sklock0.o:
0000000000000000 r .LC0
U normal_tutu3_function
U __printf_chk
0000000000000000 T this_is_the_only_public_function_tutu1
private_sklock1.o:
0000000000000000 r .LC0
0000000000000000 r .LC1
U __printf_chk
0000000000000000 T unused_tutu2_function
private_sklock2.o:
0000000000000000 T normal_tutu3_function
I expect only the function this_is_the_only_public_function_tutu1 to be visible in my symbol/library definition list.
EDIT1:
Answer from the comment section -> This is not possible. Indeed after checking documentation from https://gcc.gnu.org/wiki/Visibility about hidden feature. This feature is only valid for shared library. Not static library.
EDIT2:
I run the test on a shared library. I was able to hide everything by using the CFLAGS -fvisibility=hidden + the attribute ((visibility ("default"))) on my public API.
If you want to test the result with shared library, I created a branch here that is using cmake shared library example instead of static one: https://github.com/Evanok/static_library_hidden_test/tree/shared_library
EDIT3:
This is also a script I am using to hide all the object filename, $1 is the argument of the script. It should be the original static library file:
[arthur] cat hide_object_name.sh
#!/bin/sh
i=0
echo "lets hide symbol from $1"
rm -f *.o *.obj *.c.obj
ar xv "$1"
for f in $(ls *.obj); do
if [ -f "$f" ]; then
echo "process $f.."
extension="${f##*.}"
new_name="private_$i.$extension"
echo "rename $f as $new_name"
mv "$f" "$new_name"
i=$((i + 1))
else
echo "File $f not found."
fi
done
rm -f "$1"
echo "generating new library $1..."
ar crs "$1" private_*.*
rm -f *.o *.obj *.c.obj
sync
*.oobject files. The only things that can be hidden in any way arestaticfunctions and variables inside individual sources files - things that have file scope. If hiding symbols and functions is not possible in static, why are there so many questions about it with answers? And do those answers work? If they did, why did you ask your question?-rswitch in the GNUldlinker), and then those symbols can be stripped.static. That has the additional advantage that it will also work on systems and with linkers that don't support partial linking.