Makefile 在运行可执行文件时找不到 .so 文件

问题描述 投票:0回答:2

我在使用 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
.

c++ linux makefile .so
2个回答
1
投票

对于动态库链接分两步完成:

首先是在构建时完成的静态链接。对于安装在非标准位置的库,您可以使用

-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

0
投票

更新:我遵循了问题回复中的建议,但这次我使用前缀冒号

:
和后缀
.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
© www.soinside.com 2019 - 2024. All rights reserved.