我正在尝试编译一个小型c ++程序,该程序使用libv4l2从摄像头捕获图像,然后通过UDP将其发送到使用asio的单独计算机。
项目的文件结构是:
project/
dependencies/
asio/
cpp/
cpp_server/
cpp_client/
Makefile
src/
cpp_client.cpp
ImageClient.cpp
ImageClient.h
ImageProtocol.h
该项目的Makefile是:
CC=g++
CPP_FILES := $(wildcard src/*.cpp)
OBJ_FILES := $(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
LD_FLAGS := -L../../dependencies/asio/asio
INCLUDES := -I../../dependencies/asio/asio/include
CC_FLAGS := -Wall $(INCLUDES) -fpermissive -std=c++14 -DASIO_STANDALONE
client.exe : $(OBJ_FILES)
$(CC) $(LD_FLAGS) -o $@ $^
obj/%.o: src/%.cpp
$(CC) $(CC_FLAGS) -c -o $@ $<
但是,当我尝试编译时,我的编译器会针对ASIO函数发出数十个undefined reference
错误:
cpp_client.cpp:(.text+0x15dc): undefined reference to `asio::error::get_netdb_category()'
cpp_client.cpp:(.text+0x15ec): undefined reference to `asio::error::get_addrinfo_category()'
cpp_client.cpp:(.text+0x15fc): undefined reference to `asio::error::get_misc_category()'
obj/cpp_client.o: In function `asio::error::get_system_category()':
cpp_client.cpp:(.text._ZN4asio5error19get_system_categoryEv[_ZN4asio5error19get_system_categoryEv]+0x8): undefined reference to `asio::system_category()'
obj/cpp_client.o: In function `asio::detail::posix_tss_ptr<asio::detail::call_stack<asio::detail::thread_context, asio::detail::thread_info_base>::context>::posix_tss_ptr()':
cpp_client.cpp:(.text._ZN4asio6detail13posix_tss_ptrINS0_10call_stackINS0_14thread_contextENS0_16thread_info_baseEE7contextEEC2Ev[_ZN4asio6detail13posix_tss_ptrINS0_10call_stackINS0_14thread_contextENS0_16thread_info_baseEE7contextEEC5Ev]+0x20): undefined reference to `asio::detail::posix_tss_ptr_create(unsigned int&)'
obj/cpp_client.o: In function `asio::detail::posix_tss_ptr<asio::detail::call_stack<asio::detail::thread_context, asio::detail::thread_info_base>::context>::~posix_tss_ptr()':
cpp_client.cpp:(.text._ZN4asio6detail13posix_tss_ptrINS0_10call_stackINS0_14thread_contextENS0_16thread_info_baseEE7contextEED2Ev[_ZN4asio6detail13posix_tss_ptrINS0_10call_stackINS0_14thread_contextENS0_16thread_info_baseEE7contextEED5Ev]+0x1c): undefined reference to `pthread_key_delete'
obj/cpp_client.o: In function `asio::detail::posix_global_impl<asio::system_executor::context_impl>::~posix_global_impl()':
cpp_client.cpp:(.text._ZN4asio6detail17posix_global_implINS_15system_executor12context_implEED2Ev[_ZN4asio6detail17posix_global_implINS_15system_executor12context_implEED5Ev]+0x24): undefined reference to `asio::system_executor::context_impl::~context_impl()'
obj/ImageClient.o: In function `ImageClient::ImageClient(FHCamera, unsigned short, std::string const&, unsigned short)':
ImageClient.cpp:(.text+0x898): undefined reference to `asio::io_context::io_context()'
我想问题是我的Makefile仍然没有正确地找到ASIO并尝试独立编译它。也就是说,我不确定还有什么可以尝试的 - 是否有其他人对我需要做些什么来建议让ASIO用Makefile独立编译?
谢谢!
答案 0 :(得分:2)
独立的Asio库是您程序的依赖。建设时 一个程序,一个也没有建立依赖性(除非特殊情况 情况)。如果这是必要的,那么建立几乎任何程序都会 递归地要求大量的重建依赖。
如果您的程序依赖于未提供打包的库 您的Linux发行版的包管理器然后您必须获取源包 根据其说明,在您的系统上构建和安装该库。
然后根据您的系统满足的(真实)假设构建自己的程序 库依赖。您不会重复构建库依赖项 在你的程序建设中。
独立名字对象可能已经建议您使用此库
意味着要在每个使用它的应用程序中重建。不是。它&#39; S
独立 asio
,因为它本身并不依赖于任何人
与boost
不同的boost::asio
库是派生的。 独立
并不意味着图书馆不依赖于其他图书馆
非增强库。例如。在您的链接错误中有一些错误
将未定义的引用从 asio
函数报告给pthread_key_delete
,
这意味着asio
依赖于Posix线程库libpthread
,
并且你没有链接它。
独立的Asio库可能在开发包中提供
由Linux发行版的软件包管理器提供。例如,Debian / Ubuntu发行版
在libasio-dev
中提供,您只需使用以下命令安装:
sudo apt-get install libasio-dev
调查您的发行版是否同样如此,如果是,请安装库 与您的包管理员。
否则,您必须从源安装库。它是一个 GNU autotools源包, 所以要构建和安装它,你必须先安装:
- GCC C++ toolchain
- GNU make
- GNU autotools (autoconf, automake at least)
然后:
从其下载源代码tarball,例如asio-1.10.8.tar.bz2
Sourceforge page和
提取包目录,例如asio-1.10.8
cd
进入包目录并运行:
$ autoreconf -i
$ ./configure
来自./configure
的错误将表明依赖性或其他要求
你的系统不满意。修复并重复直至成功。然后运行
$ make
构建包。如果一切顺利,以root身份运行:
$ make install
安装包。
从dev软件包或从中安装Standalone Asio后
来源,删除project/dependencies/asio
并构建您的程序
在project/cpp/cpp_client
中使用这样的makefile:
<强>生成文件强>
CXX=g++
SRCS := $(wildcard src/*.cpp)
OBJS := $(addprefix obj/,$(notdir $(SRCS:.cpp=.o)))
CXXFLAGS := -pthread
LDFLAGS := -pthread
#LDFLAGS := -L/path/to/your/libv4l2
#LDLIBS := -libv4l2
.PHONY: all clean
CXXFLAGS := -Wall -std=c++14 -DASIO_STANDALONE
all: client
client : $(OBJS)
$(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS)
obj/%.o: src/%.cpp | obj
$(CXX) $(CXXFLAGS) -c -o $@ $<
obj:
mkdir -p $@
clean:
rm -f obj/* client
对于排练,我建议首先使用此makefile来构建asio
聊天客户端
/asio-package-dir/src/examples/cpp11/chat
中提供的内容。只需chat_client.cpp
您chat_message.hpp
文件夹中的src
。
注意注释掉的行:
#LDFLAGS := -L/path/to/your/libv4l2
#LDLIBS := -lv4l2
您表示您的计划需要与图书馆libv4l2
相关联
但你自己的makefile没有提到任何这样的链接。如果你确实需要
与它链接然后你必须至少通过链接器告知链接器
取消注释:
LDLIBS := -lv4l2
如果您可以从软件包管理器安装此库的一个软件包,请执行此操作。除此以外
从源代码构建并安装它。 Debian / Ubuntu不提供此类功能
一个图书馆包,虽然他们确实提供了libv4l-0
,libv4l-dev
和libv4l2rds0
。也许你还不确定你需要什么样的库。
如果您从源安装此库并决定安装它
某个目录不是链接器的默认搜索路径之一
(/usr/lib
,/usr/local/lib/
等...)然后您还需要通知
链接器所在的位置,取消注释:
LDFLAGS := -L/path/to/your/libv4l2
请注意,将libv4l2
添加到与-lv4l2
的关联中,即可
要求链接器找到libv4l2
的任何其他库
反过来取决于。因此,如果您的链接现在因未定义的引用而失败
从libv4l2
到其他库libfoo
中的符号,您需要
延伸LDLIBS
如:
LDLIBS := -lv4l2 -lfoo
并且,如有必要,告诉链接器在哪里找到libfoo
:
LDFLAGS := -L/path/to/your/libv4l2 -L/path/to/libfoo
依此类推,直到联系成功。
从这个角度来看,你可能想知道为什么asio
库没有类似的数字
在联系中。不需要链接器选项-lasio
?你自己的makefile建议你
相信链接器需要被告知在哪里寻找这样的库,用
它的设置:
LD_FLAGS := -L../../dependencies/asio/asio
虽然告诉链接器在那里查找图书馆,但你不能告诉它任何链接
图书馆。
不需要-lasio
,因为这个库通常是非典型的,但不是
非典型的boost
或boost
- ish库 - 是仅限标头库。
它不提供共享对象文件libasio.so
,也不提供任何目标文件存档
libasio.a
您必须链接以获取函数的定义。代替,
它们完全由头文件中的内联定义实现。从而,
您需要在程序中调用的任何一个都将直接编译
如果您在源文件中只有#include <asio.hpp>
,那就进入它
那些电话。
由于它是一个仅限标题的库, 可以使用它来构建自己的库
程序只需提取源包,跳过常用的autotools ./configure;
make;make install
过程,并设置预处理器-I
选项
在你自己的makefile中正确(在CPPFLAGS
- C预处理器标志中)
它可以找到asio
标题,例如,
/home/me/downloads/asio/asio-1.10.8
。但如果你的目标是实现
那个,你犯了一些错误途中;如果包 自动缩减 -
如asio
那么 - 如果您尝试使用它,则所有投注都将关闭,除非由autotools提供
安装程序。 在系统中安装库也有
一旦你完成它,你可以忘记设置奇特的好处
每个使用它的项目中的编译器和链接器选项
像/home/me/downloads/asio/asio-1.10.8
一样,不需要成为一个
你的主目录的夹具。
你的makefile以及你对它的问题所说的话表明你是 试图通过猜测,试验和错误来使用GCC和GNU Make。这是 a fairly good starter tutorial in the use of those tools。 对于权威文档,这里是the GNU Make manual和 这是the GCC manual
顺便提一下,在Linux中,可执行文件仅通过其文件来区分
属性,而不是像在Windows中那样具有.exe
扩展名,所以
您的计划目标可以通常只调用client
,而不是client.exe
。链接器会在创建它时使其可执行。
答案 1 :(得分:0)
您收到错误,因为在链接步骤中您没有提供生成最终可执行文件所需的所有符号(全局变量或函数)。
您需要将ASIO库添加到链接步骤,或者通过定义Makefile
宏来ASIO_STANDALONE
建议,需要在您的某个源中包含ASIO的独立标头文件来编译它。