链接C程序时使用第一个发生的实现

时间:2016-02-05 18:02:33

标签: c gcc linker

我有一个a.h和a.c,它提供了函数的接口和实现

//a.h
#ifndef A_H
#define A_H
int op();
#endif

//a.c
#include "a.h"
int op(){
    return 1;
}

类似地,我有b.h和b.c,它给出了一个具有相同名称但具有不同实现的函数的接口

//b.h
#ifndef B_H
#define B_H
int op();
#endif

//b.c
#include "b.h"
int op(){
    return 2;
}

现在,我想将它们与主程序链接

#include <stdio.h>

int op();

int main(){
printf( "returned = %d\n ", op());
}

为此,我首先将a.c和b.c分别编译为a.o和b.o。

gcc -c a.c; gcc -c b.c

然后我想把它们连在一起。这里的一个通常目标是让main.c选择&#39; op&#39;使用链接命令中首先出现的实现。所以,理想情况下:

gcc a.o b.o main.c应该给我一个执行时返回1的可执行文件,gcc b.o a.o main.c应该给我一个执行时返回2的可执行文件。但我收到错误消息

ld: 1 duplicate symbol for architecture x86_64
其实我并不感到惊讶。我的问题是:如何让main.c使用第一个实现的实现?感谢。

2 个答案:

答案 0 :(得分:3)

根据链接器参数顺序选择使用哪个函数通常是一个坏主意。但是,您的要求可以使用weak symbols实现。

要使函数“弱”,即由另一个实现覆盖,请使用GCC __attribute__((weak))标记它,例如:

int op(void) __attribute__((weak));
int op(void){
    return 2;
}

如果以这种方式将两个实现声明为“弱”,那么首先出现的实现将是首选。

如果您只将一个标记为弱,则无论链接顺序如何,都将严格优先选择另一个。我建议采用这种方式来提高代码的可维护性。

答案 1 :(得分:3)

一个选项:

  1. 制作两个静态库 - 一个来自a.o,另一个来自b.o

    ar libA.a a.o
    ar libB.a b.o
    
  2. 在链接行中,使用您希望在另一个库之前获得更高优先级的库。

    gcc main.c -L. -lA -lB