gcc:目标文件或库中的重复标识符

时间:2011-09-06 07:10:39

标签: c gcc

归档器和链接器都会忽略重复的标识符。仅当源文件或目标文件直接传递给gcc时才会检测到它们,gcc将多个定义视为错误。它也应该。归档器/链接器只是忽略它们,我们最终只得到可执行文件中的一个标识符。它取决于目标文件或库传递的顺序。下面是一个演示此内容的脚本。

有没有办法让归档器/链接器认为这是一个错误?或者还有其他工具可以解决这个问题吗?

#!/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. Passing 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 $?)

示例输出:

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

1 个答案:

答案 0 :(得分:0)

我认为您可以通过传递给链接器的--whole-archive选项获得所需的行为。来自GNU ld docs:

  

--whole-archive

     

对于命令行后提到的每个档案   --whole-archive选项,包括存档中的每个目标文件   链接,而不是搜索存档中所需的对象   文件。这通常用于将存档文件转换为共享文件   库,强制每个对象都包含在生成的共享中   图书馆。此选项可能会被多次使用。

     

从gcc使用此选项时的两个注意事项:首先,gcc不知道   关于此选项,因此您必须使用-Wl,-whole-archive。第二,   不要忘记在档案列表后使用-Wl,-no-whole-archive,   因为gcc会将自己的档案列表添加到您的链接中,您可以   不希望这面旗帜影响那些。