【问题标题】:Why I got "clang: error: cannot specify -o when generating multiple output files"?为什么我得到“clang:错误:生成多个输出文件时无法指定 -o”?
【发布时间】:2017-09-18 21:56:12
【问题描述】:

我是 C 的新手。我有两个简单的源代码文件 f1.cf2.c

f1.c 看起来像:

#include <stdio.h>
#include "f.h"

void f1(void) {
    // some code ...
}

f2.c 中的函数f2() 依赖于f1.c 中的f1()

#include <stdio.h>
#include "f.h"

void f2(void) {
    f1();
}

f1.cf2.c 共享同一个标头f.h

void f1(void);
void f2(void);

没有main()的访问权限,我只想把这两个文件编译成一个没有链接器的.o文件(使用-c选项),

gcc -c f1.c f2.c -o f2.o

然后我得到了,

clang: error: cannot specify -o when generating multiple output files

但是当我只提到f2.c时,它运作良好,

gcc -c f2.c -o f2.o

那么问题是什么?谢谢!

【问题讨论】:

  • 每个.o文件只能有一个.c文件
  • 如果没有-c-o 标志会告诉它在将所有内容链接在一起后将最终可执行文件放在哪里。对于-c-o 表示将.o 文件与.c 文件放在哪里。但是如果你说-c你说-o你指定了两个.c文件,.c文件与-o一起使用?
  • 谢谢@SteveSummit!所以如果我只用命令gcc -c f2.c -o f2.o编译f2.c,编译器会自动找到f.h头文件中提到的函数f1()
  • @wei 如果您不想链接,那么是的,在f2.c 中添加#include "f.h" 行为编译器 提供了编译@ 所需的所有信息987654360@ 转为f2.o。但是,稍后,当您进行链接时,您 必须告诉它在哪里可以找到函数f() 的编译代码,这可能在单独编译的f1.o 中。但是您还需要更多地考虑“链接”的含义,因为如果您不进行链接,那么您不会将“将这两个文件编译为.o 文件”,正如您所说;您大概要将这两个文件编译成 two .o 文件。

标签: c gcc compiler-errors compilation


【解决方案1】:

您应该查看 C 的编译过程。第一阶段是将.c 源代码编译为.o 目标文件。 .c 文件不需要查看其他.c 文件;他们接受你告诉他们的关于外部功能存在的事实。直到链接器出现,它才真正需要查看函数,因为实现细节对您的.c 文件无关紧要,只是接口,您可能已经在标题中给出了它。

如果您愿意,您可以做的是删除-o 标志,指定您要创建的输出文件。只需编译 gcc -c f1.c f2.c 并且它会知道创建f1.of2.o,当您确实想要进行链接过程时,它们将能够相互链接。

但是,我很好奇,您希望在不链接的情况下编译这些文件的意图是什么。我只是在您称自己为新手时才问,所以我想知道您是否有一个最终目标,并且可能没有提出正确的问题。

【讨论】:

  • 感谢您的回答@ChristianGibbons!因为我有很多模块,例如a.c,b.c,...,z.c。其中一些可以组合成一个.exe 可执行文件。我更喜欢将每个.c 文件编译成.o 文件一次,然后重用目标文件。我倾向于找到编译我的 c 项目的最佳实践。正如你提到的,gcc -c f1.c f2.c 很好。
  • 好的,看起来你可能真正想要的是一个构建系统。每当我将一个小项目放在一起时,我通常都会启动Makefile,但我猜您使用的是 Windows 而不是 Unix 衍生产品。我对 Windows 上的选项并不十分熟悉,但也许可以尝试从 nmake 开始,因为它似乎是他们的 make 版本。像这样的构建系统能够避免重新编译已经与最新更改保持同步的源文件,因此即使您对项目进行更改,它也会知道只重新编译受更改影响的部分。
  • 不错的提示。我只想在使用Makefile 之前弄清楚gcc 的工作原理:>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多