在编译时从目标文件中替换符号。例如换出主

Ant*_*ile 5 c++ g++

这是用例:

我有一个.cpp文件,其中实现了功能。举例来说,它具有以下特征:

[main.cpp]

#include <iostream>

int foo(int);

int foo(int a) {
    return a * a;
}

int main() {
    for (int i = 0; i < 5; i += 1) {
        std::cout << foo(i) << std::endl;
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想foo对该文件中的功能执行一些自动化测试,但需要替换该main()功能以进行测试。最好是我想有一个这样的单独文件,我可以在该文件的顶部进行链接:

[mymain.cpp]

#include <iostream>
#include <cassert>

extern int foo(int);

int main() {
    assert(foo(1) == 1);
    assert(foo(2) == 4);
    assert(foo(0) == 0);
    assert(foo(-2) == 4);        

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望(如果可能的话)避免更改原始.cpp文件以执行此操作-尽管如果无法这样做,这将是我的方法:

  1. 代替"(\s)main\s*\("==>"\1__oldmain\("
  2. 照常编译。

我的目标环境是带有g ++的linux环境。

Ant*_*ile 5

我讨厌回答我自己的问题,但这是我最终在 的手册页深处找到的解决方案g++,我已经对其进行了测试,并且可以达到我想要的效果...

g++具有-D允许您在编译目标文件时定义宏的标志。我知道你在想“呃宏”但听我说...你可以使用宏定义来有效地重命名一个符号。就我而言,我可以运行以下命令来生成我的学生代码的目标文件,而没有他们的主文件:g++ -D main=__students_main__ main.cpp -c -o main.nomain.o .

这将创建一个目标文件,其int main定义为int __students_main__. 现在,这并不一定是直接调用,因为它们可能已经定义主int main(void)或与各种组合argcargv,但它可以让我有效地编出自己的作用。

最终编译如下:

g++ -c -D main=__students_main__ main.cpp -o main.nomain.o
g++ -c mymain.cpp -o mymain.o
g++ main.nomain.o mymain.o -o mymainstudentsfoo.out
Run Code Online (Sandbox Code Playgroud)

出于我的目的,我想创建一个 Makefile 来自动完成此操作(ish),我觉得这与本次讨论有关,因此我将发布我的想法:

HDIR=./ # Not relevant to question, but we have headers in a separate directory
CC=g++
CFLAGS=-I $(HDIR)
NOMAIN=-D main=__student_main__ # The main renaming magic

.SECONDARY: # I forget exactly what this does, I seem to remember it is a hack to prevent deletion of .o files

cpp = $(wildcard *.cpp)
obj = $(patsubst %.cpp,%.o,$(cpp))
objnomain = $(patsubst %.cpp,%.nomain.o,$(cpp))

all: $(obj) $(objnomain)

clean:
        rm -f *.o *.out

%.nomain.o: %.cpp
        $(CC) $(CFLAGS) $(NOMAIN) -c $^ -o $@

%.o: %.cpp
        $(CC) $(CFLAGS) -c $^
Run Code Online (Sandbox Code Playgroud)

  • 预处理器方法的轻微风险在于它替换任何匹配的标记,不限于函数名称。在 UNIX 上使用 *objcopy* 重命名符号的替代方法:`objcopy --redefine-sym main=__students_main__ $@`(或基于文件名的计算替换?)。 (2认同)