开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜