我希望扩展一个大型C编程项目(http://icecast.org/download/)以及一些额外的功能。虽然我有一般的编程经验,但这是我第一次在C中做任何事情并且有一些挣扎。
我决定在使用自己的模块扩展Icecast项目时,我会首先在我自己的机器上测试模块(使用Eclipse的Centos 6),一旦工作 - 我的意图是将更改集成到主要的Icecast项目中。 / p>
我的第一个集成是一个日志记录机制,它将简单的消息保存到本地MySQL数据库,我已经成功地在我的机器上运行了这个。我将代码复制到Icecast项目的模块中,确保所有相关的包含都被声明。当尝试使用./configure使用附加功能编译Icecast时,make - 我收到以下错误:
client.o: In function `logSingleMessage':
/home/hearme/radio/src/client.c:283: undefined reference to `mysql_init'
/home/hearme/radio/src/client.c:297: undefined reference to `mysql_real_connect'
/home/hearme/radio/src/client.c:305: undefined reference to `mysql_query'
/home/hearme/radio/src/client.c:307: undefined reference to `mysql_error'
/home/hearme/radio/src/client.c:308: undefined reference to `mysql_close'
/home/hearme/radio/src/client.c:293: undefined reference to `mysql_error'
/home/hearme/radio/src/client.c:312: undefined reference to `mysql_close'
有人可以解释为什么会这样吗?
谢谢
答案 0 :(得分:2)
您报告的消息是链接器错误。它们表明您的程序试图调用指定的函数,但没有实现它们的链接。应该将相应的库添加到链接中,可能是-lmysqlclient
,但可能是-lmysqlclient_r
。如何实现这一点很大程度上取决于构建系统的细节。
答案 1 :(得分:0)
您正在分发使用GNU Autotools构建的项目 不幸的是,你选择了一个自动化项目,为你在C的第一次冒险。 你不需要学习autools来学习C,而且真正了解构建C程序或者是非常重要的 在处理自动化项目之前,使用GNU make创建库。自动工具 本质上是一个makefile生成系统,它使其输出适应它对系统的调查结果 根据您提供的配置方向工作。
您需要了解使用已编译的autotools来处理典型的Unix / Linux OSS项目
语言。这不是一项简单的学习,但如果您在icecast
autoreconf
上取得很大进展,那么
要学习至少基本的知识。 autoconf
automake
是主要工具。谷歌搜索
" {autoconf | automake} {tutorial | hello world}"将是更有帮助,但不是
比你想象的更有帮助。存在一个名为autoconf
的附加驱动程序脚本
可以按正确的顺序自动运行automake
,icecast
和不太知名的自动工具,
但它不会让你不必阅读和写入这些工具的输入文件。
我可能会让您解决您的直接问题,这会给您留下可能或可能不会的印象
说服你推迟icecast
的分支,直到你从较小的挑战中毕业。我的建议
将是推迟。
令人遗憾的是autoconf
(我已经抓住它)的自动调整既复杂又过时。每当
您在其上运行automake
和libmysqlclient
的当前版本,它们会发出一些过时的警告
在项目中进行自动调整。我们先解决这些问题。
您正在为icecast添加新功能,这会在libmysqlclient
上引入构建时依赖性。
这意味着构建需要找到mysql
用于链接和mysql/mysql.h
标题
你编译。出于目前的目的,我假设./configure
是您唯一要提及的。
您需要让autotools在生成新的autoconf
脚本时处理这些功能要求
对于项目,它将反过来生成所有的makefile。要做到这一点,你将不得不修改
automake
和autoreconf
的相关输入文件,然后在项目中重新运行这些工具(我们将使用./configure
来执行此操作)。之后,
你有一个yum whatprovides autoconf automake libtool
脚本,直到你下次需要干扰构造时才会有用
该项目。
首先,如果您尚未安装autotools,请在您的开发系统上安装。我不知道Centos但是 片刻的谷歌搜索表明:
yum groupinstall 'Development Tools'
之类的应该告诉你所需的包裹,并且:
icecast
以root为基础将一次性完成所有这些工作。
您必须应用我要在原始TODO
2.4.2源代码树中描述的更改。
tarball。它们不依赖于您的任何新源代码,以及何时出现新的源代码
并自动化到包中(对于你来说是mysql
),它们将满足其autoreconf
依赖项。如果您将它们应用于您所在的源树上
已经对自动变速器进行了修改,当然所有的投注都已关闭。
<强>预赛强>
在原始源代码树中,运行aclocal: warning: autoconf input should be named 'configure.ac', not 'configure.in'
,看看它在获得包装时有什么说法。
我收到一堆警告: -
1)configure.in:106: warning: AC_LANG_CONFTEST: no AC_LANG_SOURCE call detected in body
../../lib/autoconf/lang.m4:193: AC_LANG_CONFTEST is expanded from...
../../lib/autoconf/general.m4:2729: _AC_RUN_IFELSE is expanded from...
../../lib/m4sugar/m4sh.m4:639: AS_IF is expanded from...
../../lib/autoconf/general.m4:2748: AC_RUN_IFELSE is expanded from...
m4/xiph_curl.m4:6: XIPH_PATH_CURL is expanded from...
configure.in:106: the top level
......反复,并且:
2)
src/avl/Makefile.am:13: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
......反复,并且:
3)src/httpp/Makefile.am:12: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
4)src/net/Makefile.am:13: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
5)src/thread/Makefile.am:13: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
6)configure.in
在进一步操作之前,您最好先解决这些问题,否则它们会掩盖您之后引发的诊断问题。 自己的错误。首先是明显的:
1)将configure.ac
重命名为src/avl/Makefile.am
3)修改INCLUDES
并将AM_CPPFLAGS
替换为src/httpp/Makefile.am
4)修改INCLUDES =
并将AM_CPPFLAGS +=
替换为m4/xiph_curl.m4
。 注意差异。
5)按照3。
6)按照3。
警告2)是由 AC_RUN_IFELSE(AC_LANG_SOURCE([
#include <curl/curl.h>
int main()
{
return 0;
}
]),,[curl_ok="no"],[curl_ok="yes"])
中缺少一对方括号引起的。编辑它
文件和替换:
AC_RUN_IFELSE([AC_LANG_SOURCE([
#include <curl/curl.h>
int main()
{
return 0;
}
]),,[curl_ok="no"],[curl_ok="yes"]])
使用:
autoreconf
现在再次运行./configure
,它应该没有任何抱怨。然后运行make
,
哪个应该成功完成,最后运行libmysqlclient
,这也应该是好的。
修复
现在,您已准备好对libmysqlclient
依赖项进行自己的更改。
出于演示目的,我假设你要添加的功能
取决于icecast
被称为&#34; Yoyo&#34;,并且你想要它
对于试图在他们身上构建./configure
的人来说,这是一个额外的而不是必需的
你的包中有自己的系统。因此,您不希望无法检测到该库或头文件
在configure.ac
时间致命。我假设您只想让构建禁用Yoyo
在这种情况下的支持。
修改configure.in
(以前为AC_CHECK_HEADERS([pwd.h unistd.h grp.h sys/types.h],,,AC_INCLUDES_DEFAULT)
)。找到这一行:
AC_CHECK_HEADERS(
[mysql/mysql.h],[AM_CONDITIONAL([HAVE_MYSQL_MYSQL_H],[true])],
[AM_CONDITIONAL([HAVE_MYSQL_MYSQL_H],[false])]
[AC_MSG_WARN([Header mysql/mysql.h not found. Yoyo support disabled])])
并在其后插入:
autoconf
在这里,您要插入一个./configure
宏来指示生成的mysql/mysql.h
脚本
检查是否有必要的标题configure.ac
,记录该检查的结果并导致脚本
如果未找到标头,则发出警告。见AC_CHECK_HEADERS
接下来,仍在XIPH_PATH_SPEEX(
[ XIPH_VAR_APPEND([XIPH_CPPFLAGS],[$SPEEX_CFLAGS])
XIPH_VAR_PREPEND([XIPH_LIBS],[$SPEEX_LIBS])
XIPH_VAR_APPEND([XIPH_LDFLAGS],[$SPEEX_LDFLAGS])
ICECAST_OPTIONAL="$ICECAST_OPTIONAL format_speex.o"
],
[ AC_MSG_WARN([Speex support disabled!])
])
中,找到节:
AC_CHECK_LIB(
[mysqlclient],[mysql_init],
[AC_DEFINE([HAVE_LIBMYSQLCLIENT],[1],[Define if you have libmysqlclient])]
[AM_CONDITIONAL([HAVE_LIBMYSQLCLIENT],[true])] [MYSQL_LIBS="-lmysqlclient"],
[AM_CONDITIONAL([HAVE_LIBMYSQLCLIENT],[false])]
[AC_MSG_WARN([libmysqlclient not found. Yoyo support is disabled])])
之后插入:
autoconf
在此,您需要插入./configure
宏,指示mysql_init
检查是否可以
链接一个测试程序,该程序调用外部函数libmysqlclient
对库./configure
。那&#39; S
对正确库的可用性进行身份验证检查。宏将再次MYSQL_LIBS
记录结果并在检查失败时发出警告。并且,如果检查成功,则变量
我会定义-lmysqlclient
= AC_SUBST(KATE_LIBS)
。见AC_CHECK_LIB
再向下,找到行:
AC_SUBST(MYSQL_LIBS)
之后插入:
@MYSQL_LIBS@
添加此行的一个影响是,如果您使用表达式MYSQL_LIBS
在automake的输入文件中的任何地方,然后在从它们生成的makefile中
表达式将替换为autoconf
时分配给configure.ac
的值(如果有)
-lmysqlclient
个进程libmysqlclient
。如果库可用,该值将为icecast
否则没什么。见AC_SUBST
最后阶段是利用最后一个事实。我会假设Yoyo需要Makefile.am
只是与./configure
可执行文件链接。如果它应该与任何其他目标相关联
对于冰球构造或者尚未存在的Yoyo目标,你可以用你现在看到的那种方式实现这一目标。
在构建某个目标的每个子目录中,您将找到src/Makefile.am
。该文件是架构
最终控制目标是如何在包裹着陆的任何系统上构建的,由指导
由icecast_LDADD = $(icecast_DEPENDENCIES) @XIPH_LIBS@ @KATE_LIBS@
提出的当地调查结果和偏好。你可以研究这个过程。
编辑文件_LDADD
。这是控制icecast可执行文件的模式的模式。
找到这一行:
icecast
此行示意性地指定icecast_LDADD = $(icecast_DEPENDENCIES) @XIPH_LIBS@ @KATE_LIBS@ @MYSQL_LIBS@
程序的附加链接器标志(autoreconf
)。更改
这一行:
./configure
这就是为了你眼前的问题。
查看
现在再次运行icecast
并且(如果没有出现错误)它将生成mysqlclient
能够使make clean
版本自动适应libmysqlclient
dev支持的可用性的脚本,
或者因此缺乏。
观察效果。运行./configure
以重新开始。暂时卸载
configure: WARNING: Header mysql/mysql.h not found. Yoyo support disabled
configure: WARNING: libmysqlclient not found. Yoyo support is disabled
及其标题(或暂时隐藏它们,例如通过重命名)。
然后运行make
。它会成功,但输出将包括
警告:
libmysqlclient
然后运行make clean
./configure
。它成功,构建与上次相同。
现在重新安装./configure
及其标题。运行:
Yoyo support disabled
src/Makefile
成功,但现在src/Makefile.in
警告消失了。
打开文件src/Makefile.am
(不是icecast
或MYSQL_LIBS
)。这个
是MYSQL_LIBS = -lmysqlclient
可执行文件的生成的makefile。搜索icecast_LDADD
你找到了设置:
-lmysqlclient
然后搜索make | grep '\-lmysqlclient'
,您会发现其设置包含libmysqlclient
运行icecast
。构建成功,您看到AC_CHECK...
在configure.ac
可执行文件中链接。你还没有做任何事情,但是
当你需要它时它会存在。
我说过你configure
中插入的mysql
宏会
使AM_CONDITIONAL
脚本记录结果。他们以两种方式记录这些结果
您可以使用有条件地集成Yoyo功能,取决于
AC_CHECK_HEADERS(
[mysql/mysql.h], # <-- Header to look for
[AM_CONDITIONAL([HAVE_MYSQL_MYSQL_H],[true])], #<-- Do this if found
# Else do this all...
[AM_CONDITIONAL([HAVE_MYSQL_MYSQL_H],[false])]
[AC_MSG_WARN([Header mysql/mysql.h not found. Yoyo support disabled])])
支持的可用性。
其中一种方式是我们使用的AM_CONDITIONAL
提供的,例如
automake
Makefile.am
的效果是让你写src/Makefile.am
个条件
在任何定义目标构建的if HAVE_LIBMYSQLCLIENT
# ... Do this if libmysqlclient is available
endif
中,例如你
编辑else...endif
并插入以下内容:
./configure
当然还有make
变体。 ./configure
生成时
从这个最终的makefile,它将包括在范围内的东西
真实的条件,省略其余的。
这种形式的检查结果记录可让您将结果传达给config.h
。
另一种方法是让您将结果直接传递给编译器。
在您运行/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
之后,您会发现有一个顶级的头文件
包树名为mysqlclient
。打开它,在顶部会告诉你
它是如何存在的:
HAVE_MYSQL_MYSQL_H
上次生成此文件时,您已安装/* Define to 1 if you have the <mysql/mysql.h> header file. */
#define HAVE_MYSQL_MYSQL_H 1
dev支持。
在文件中搜索HAVE_LIBMYSQLCLIENT
,您会发现:
/* Define if you have libmysqlclient */
#define HAVE_LIBMYSQLCLIENT 1
搜索config.h
,然后找到
./configure
您可以依赖它,这些宏将在-DHAVE_CONFIG_H
中定义
当且仅当它们所代表的检查成功时才为非零值
{{1次。您也可以依赖命令行预处理器
选项make
将自动传递给所有编译器命令
在-I
以及config.h
(包含搜索路径)选项中将启用
编译器来定位#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
。因此,您可以在任何C源文件中使用
写:
./configure
然后在源文件的主体中,您可以访问并使用预处理器
表示#if HAVE_MYSQL_MYSQL_H
#include <mysql/mysql.h>
#endif
- 时间检查结果的宏,例如
icecast
<强>最后强>
在这里, not 勾勒出正确的是将Yoyo整合到icecast-with-yoyo
中。
我已经草拟了一种方法,您可以制作icecast
Yoyo的依赖性得到满足,否则产生./configure
经典,
所以你仍然没有 的自动工具。但它会被评为粗鲁和业余自动调整。
提供Yoyo作为可选功能的正确方法是装备
带有命令行参数--enable-yoyo
的{{1}}脚本
并在./configure --help
中记录它,以便安装程序
打包并选择是否构建Yoyo支持。然后,如果我没有./configure
--enable-yoyo
,不会建立yoyo支持。但如果我确实指明了
如果不满足Yoyo的依赖关系,那么选项./configure
应该失败。
您使用AC_MESSAGE_ERROR
代替AC_MESSAGE_WARN
,
而你的configure.ac
会变得更精细。如果您想要调查如何实施此类./configure
您可以从AC_ARG_ENABLE