在 Makefile.am 的 C++ 库中编译 C 文件

Posted

技术标签:

【中文标题】在 Makefile.am 的 C++ 库中编译 C 文件【英文标题】:Compile C file within C++ library in Makefile.am 【发布时间】:2017-07-11 08:44:29 【问题描述】:

我正在对 Github 上的一个现有项目进行分叉,我想对其进行一些更改。我想做的一件事是添加一个额外的文件。此文件应位于 Makefile.am 生成的库之一中。问题是我要添加的文件是.c文件,而项目中的其他所有文件都是.cpp。

应该包含该文件的库在makefile中使用如下:

MYLIBRARY=path/mylibrary.a

...

path_mylibrary_a_CPPFLAGS = $(AM_CPPFLAGS)
path_mylibrary_a_CXXFLAGS = $(AM_CXXFLAGS)
path_mylibrary_a_SOURCES = \
  path/cppfile1.cpp \
  path/cppfile1.h \
  path/cppfile2.cpp \
  path/cppfile2.h \
  path/cppfile3.cpp \
  path/cppfile3.h

...

mybinary_LDADD = $(MYLIBRARY)

只需将path/cfile.cpath/cfile.h 添加到源列表中就会出现以下错误:

CXXLD    mybinary
/usr/bin/ld: path/mylibrary.a(path_mylibrary_a-cfile.o): relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
path/mylibrary.a: error adding symbols: Bad value

我该怎么做才能使 Makefile.am 将 c 文件编译到一个项目中,否则该项目是用 c++ 构建的?

【问题讨论】:

也许您应该添加一个path_mylibrary_a_CFLAGS 变量?当然适当地初始化了。 【参考方案1】:

解决这个问题的典型方法是有一个方便的库,你可以在其中编译你的 c 代码:

path_mylibrary_a_LDADD = cfile.la

noinst_LTLIBRARIES = cfile.la
cfile_la_CPPFLAGS = -std=c11
cfile_la_SOURCES = cfile.c

有关更多信息,请参阅此answer。

【讨论】:

我已经尝试了很多变体,但它会产生不同的问题。在我引用 .c 文件的 .cpp 文件中,我收到一条错误消息,指出引用未定义,这与我在 makefile 中根本不包含 .c 文件一样。 引用未定义是链接器问题。如果符号已定义,您可能需要使用 objdump 检查。 除非您使用 extern "C" 块,否则在 .cpp 文件中包含 .c 文件也不起作用 尝试只在cpp文件中包含头文件 我只包含头文件。【参考方案2】:

我猜你的cfile.h 有这个结构

#ifndef MYLIBRARY_CFILE_H
#define MYLIBRARY_CFILE_H

#ifdef __cplusplus
extern "C" 
#endif

/* your C declarations here */

#ifdef __cplusplus

#endif

#endif /* MYLIBRARY_CFILE_H */

此外,作为一般提示:如果您想在 Makefile.am 文件中的库或程序中添加一些源文件,只需添加以下行

path_mylibrary_a_SOURCES += cfile.c cfile.h

这是一个非常干净的补丁,只添加了一行,不涉及其他行,等等。

另外,我同意path_mylibrary_a_CFLAGS 上的https://***.com/users/440558/some-programmer-dude,您可能还需要添加它。

【讨论】:

这仍然使用 C 编译器,而不是 C++ 编译器,用于源文件。 C 和 C++ 是不同的语言。对用 C 编写的源文件使用 C 编译器是正确的做法。然后,C++ 编译器和链接器将使用 C 链接链接到 C 编译器创建的目标文件,并且 C++ 程序可以从 C 源访问这些目标。 “对用 C 编写的源文件使用 C 编译器是正确的做法” - 谁说的?编译器人员告诉我们使用相同的编译器和标志来编译项目中的源文件。对于 C++ 项目,这意味着对 C 源文件使用 C++ 编译器。它确保 C 源文件 git 获得所需的选项,例如 -frtti-fexceptions “编译器人员告诉我们”在哪里使用 C++ 编译器来编译 C 代码? (分别用g++gcc 使用g++链接 从C++ 和C 生成的目标文件与编译 不同。)

以上是关于在 Makefile.am 的 C++ 库中编译 C 文件的主要内容,如果未能解决你的问题,请参考以下文章

makefile.in与makefile.am

makefile.am 变量在 make 命令中的目标文件之后设置一些库

编译pluma: pluma/Makefile.am:192: error: HAVE_INTROSPECTION does not appear in AM_CONDITIONAL

Makefile.am文件配置

Makefile.am 规则和实例详解

Configure,Makefile.am, Makefile.in, Makefile文件之间关系