我在使用 mosquitto MQTT 协议的 VScode 和 Ubuntu 中创建一个带有 Makefile 的 C++ 应用程序。
我在 /usr/src/
目录下克隆了
official repo,我正在尝试使用变量将我的 makefile 与必要的共享对象文件链接起来。
CXX := g++
CXXFLAGS := -Wall -Wextra -pedantic
INCLUDES += -I/usr/src/mosquitto/lib/cpp
INCLUDES += -I/usr/src/mosquitto/include
LIBS += -L/usr/src/mosquitto/lib/cpp -l:libmosquittopp.so.1
LIBS += -L/usr/src/mosquitto/lib -l:libmosquitto.so.1
BIN = bin
all: main.cpp
$(CXX) $(CXXFLAGS) $(INCLUDES) -o $(BIN)/main $< $(LIBS)
run:
@./bin/*
clean:`
rm -rf ./bin/*
项目结构由一个带有 makefile 和一个
main.cpp
文件的目录组成,此外还有一个 bin
文件夹来存储可执行文件。
├── bin
├── main.cpp
├── makefile
到目前为止,
main.cpp
唯一的外部依赖是mosquittopp
头文件。
#include <iostream>
#include <mosquittopp.h>
int main() {
int mid_val {235};
int* mid = &mid_val;
const char* device_name {"mqtt_c8y_1234abc"};
const char* username {[username]};
const char* password {[password]};
const char* host {"[domain].cumulocity.com"};
const int port {1883};
mosqpp::lib_init();
mosqpp::mosquittopp mosq_client {device_name, true};
int auth_status { mosq_client.username_pw_set(username, password)};
if(auth_status == MOSQ_ERR_SUCCESS){
std::cout << "User authentication success!\n";
}
return 0;
}
我能够毫无问题地运行
build
目标,但是当我尝试执行 run
目标时,出现以下错误:
./bin/main: error while loading shared libraries: libmosquittopp.so.1: cannot open shared object file: No such file or directory
make: *** [makefile:15: run] Error 127
即使我可以验证库的正确位置及其在我的文件系统中的名称,也会发生这种情况 [强调 添加]:
/usr/src/mosquitto/lib$ tree
.
.
.
├── connect.c
├── connect.o
├── cpp
│ ├── CMakeLists.txt
│ ├── **libmosquittopp.so.1**
│ ├── Makefile
│ ├── mosquittopp.cpp
│ ├── mosquittopp.h
│ └── mosquittopp.o
├── dummypthread.h
├── handle_auth.c
.
.
.
├── helpers.c
├── helpers.o
├── **libmosquitto.so.1**
├── linker.version
请注意:我已经尝试通过将它们列为
-lmosquittopp
和 -lmosquitto
来给出库文件的简写名称,但是当尝试运行时 makefile 无法找到它们 all
.
对于动态库链接分两步完成:
首先是在构建时完成的静态链接。对于安装在非标准位置的库,您可以使用
-L
选项告诉链接器库所在的位置,如 -L/path/to/library/directory
.
然后是运行时链接,由操作系统在加载和运行程序时完成。它还需要知道库的位置,如果它们不在标准位置,将找不到它们,您将在尝试运行应用程序时遇到错误。使用
g++
驱动程序时,您需要添加选项 -Wl,-rpath,/path/to/library/directory
.
请注意,这些选项传递给库所在的目录,而不是库本身。
你得到的错误来自第二个操作系统级链接。
另一方面,当与标准位置的库链接时,或者其目录添加了
-L
时,您不需要提供完整的文件名,只需提供没有 lib
前缀或 的库名.so
后缀.
所以不是用
libmosquitto.so.1
链接,而是用mosquitto
链接。
把它们放在一起,像这样改变你的
LIBS
变量:
LIBS += -L/usr/src/mosquitto/lib/cpp -lmosquittopp -Wl,-rpath,/usr/src/mosquitto/lib/cpp
LIBS += -L/usr/src/mosquitto/lib -lmosquitto -Wl,-rpath,/usr/src/mosquitto/lib
更新:我遵循了问题回复中的建议,但这次我使用前缀冒号
:
和后缀.so.1
将实际共享库文件的名称设置为其全名,并且成功了!
这里是
LIBS
变量的完整代码:
LIBS += -L/usr/src/mosquitto/lib/cpp -l:libmosquittopp.so.1 -Wl,-rpath,/usr/src/mosquitto/lib/cpp
LIBS += -L/usr/src/mosquitto/lib -l:libmosquitto.so.1 -Wl,-rpath,/usr/src/mosquitto/lib