gcc: duplicate identifiers in object files or libraries
Duplicate identifiers are simply ignored by the archiver and also by the linker. They are detected only if the source or object files are passed directly to gcc, which considers multiple definitions an error. As well it should. The archiver/linker simply ignores them and we end up with only one of the identifiers in the executable. Which one it is depends on the order in which the object file or library gets passed. Below is a script to demonstrate this.
Is there any way to make the archiver/linker consider this an error? Or are there other tools to deal with this?
#!/bin/sh
dir=$(mktemp -d)
echo "Using temporary directory: $dir"
echo
cd "$dir"
create_lib()
{
lib=$1
shift
rm -f $lib
ar r $lib "$@" 2>/dev/null
}
make_file()
{
base=file$1
cat >$base.c <<-EOF
int f()
{
return $1;
}
EOF
gcc $base.c -o $base.o -c
create_lib lib$base.a $base.o
}
make_file 1
make_file 2
cat >main.c <<EOF
int main()
{
extern int f();
return f();
}
EOF
gcc main.c -omain.o -c
cat <<EOF
1. P开发者_JAVA百科assing duplicate functions to archiver in different order
produces no error, but different result:
EOF
create_lib libfile.a file1.o file2.o
gcc main.o libfile.a -omain
(echo -n "ar file1.o file2.o: "; ./main; echo $?)
create_lib libfile.a file2.o file1.o
gcc main.o libfile.a -omain
(echo -n "ar file2.o file1.o: "; ./main; echo $?)
echo
cat <<EOF
2. Passing duplicate libraries to linker in different order
produces no error, but different result:
EOF
gcc main.o libfile2.a libfile1.a -omain
(echo -n "gcc libfile2.a libfile1.a: "; ./main; echo $?)
gcc main.o libfile1.a libfile2.a -omain
(echo -n "gcc libfile1.a libfile2.a: "; ./main; echo $?)
Sample output:
Using temporary directory: /tmp/tmp.AaXzxGcSdd
1. Passing duplicate functions to archiver in different order
produces no error, but different result:
ar file1.o file2.o: 1
ar file2.o file1.o: 2
2. Passing duplicate libraries to linker in different order
produces no error, but different result:
gcc libfile2.a libfile1.a: 2
gcc libfile1.a libfile2.a: 1
I think you can get the behavior you want with the --whole-archive
option passed to the linker. From the GNU ld docs:
--whole-archive
For each archive mentioned on the command line after the
--whole-archive
option, include every object file in the archive in the link, rather than searching the archive for the required object files. This is normally used to turn an archive file into a shared library, forcing every object to be included in the resulting shared library. This option may be used more than once.Two notes when using this option from gcc: First, gcc doesn't know about this option, so you have to use
-Wl,-whole-archive
. Second, don't forget to use-Wl,-no-whole-archive
after your list of archives, because gcc will add its own list of archives to your link and you may not want this flag to affect those as well.
精彩评论