ubuntu+arm64+qt获取应用的全部动态库、打包

1.概要

2.内容

ubuntu+arm64环境,查看一个应用程序依赖的全部动态库

在 Ubuntu ARM64 环境下,要查看一个应用程序依赖的全部动态库,可以使用 ldd 命令。这个命令会列出指定可执行文件或共享库文件依赖的所有共享库。以下是具体步骤:

  1. 确保你有目标可执行文件:假设你的应用程序名为 myapp

  2. 打开终端:你需要使用一个终端来运行命令。

  3. 运行 ldd 命令

    ldd /path/to/myapp

    替换 /path/to/myapp 为你的应用程序的实际路径。例如,如果你的应用程序在当前目录,你可以直接运行:

    ldd ./myapp

  4. 查看输出ldd 命令会输出应用程序依赖的所有动态库及其路径。例如:

    linux-vdso.so.1 (0x0000ffff8b9f7000)
    libm.so.6 => /lib64/libm.so.6 (0x0000ffff8b6f7000)
    libc.so.6 => /lib64/libc.so.6 (0x0000ffff8b33d000)
    /lib64/ld-linux-aarch64.so.1 (0x0000ffff8b9fc000)

注意事项

  • 权限问题:确保你有权限运行 ldd 命令和访问目标可执行文件。某些情况下,你可能需要使用 sudo 来提升权限。

  • 缺少库:如果某些库未找到,ldd 输出中会显示 not found。这可能是因为库不在标准库路径中,或者库本身未安装。

  • 静态链接:如果应用程序是静态链接的,ldd 将不会显示任何依赖库,因为所有必要的代码已经包含在可执行文件本身中。

  • 安全性:不要在不信任的可执行文件上运行 ldd,因为它可能会尝试加载恶意库。

通过 ldd 命令,你可以方便地查看应用程序在运行时所需的所有动态库,从而帮助你进行调试、依赖管理和问题排查。

3.关联链接

4.关联知识

1.将一个程序全部依赖的动态库拷贝到该应用根目录下的一个lib目录中

在 Ubuntu ARM64 环境下,如果你有一个 Qt 程序,并且希望将该程序的所有依赖动态库拷贝到应用根目录下的一个 lib 目录中,你可以按照以下步骤进行操作。

前提条件

  1. 已安装 Qt:确保你的系统上安装了 Qt 开发环境。
  2. 已编译程序:假设你的 Qt 程序已经编译好,并且生成了一个可执行文件,比如 myapp

步骤

  1. 创建 lib 目录
    在你的应用程序根目录下创建一个 lib 目录,用于存放动态库。

    mkdir -p /path/to/your/app/lib

  2. 使用 ldd 列出依赖库
    使用 ldd 命令列出你的 Qt 程序依赖的所有动态库。

    ldd /path/to/your/app/myapp

    这将输出类似以下的内容:

    linux-vdso.so.1 (0x0000ffff8b9f7000)
    libQt5Core.so.5 => /usr/lib/aarch64-linux-gnu/libQt5Core.so.5 (0x0000ffff8b6f7000)
    libstdc++.so.6 => /usr/lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000ffff8b33d000)
    libc.so.6 => /lib64/libc.so.6 (0x0000ffff8af83000)
    /lib64/ld-linux-aarch64.so.1 (0x0000ffff8b9fc000)
    libm.so.6 => /lib64/libm.so.6 (0x0000ffff8aceb000)

  3. 拷贝依赖库到 lib 目录
    根据 ldd 的输出,找到每个库的路径,并将它们拷贝到 lib 目录中。你可以手动拷贝,或者使用脚本自动化这一过程。

    手动拷贝示例:

    cp /usr/lib/aarch64-linux-gnu/libQt5Core.so.5 /path/to/your/app/lib/
    cp /usr/lib/aarch64-linux-gnu/libstdc++.so.6 /path/to/your/app/lib/
    cp /lib64/libc.so.6 /path/to/your/app/lib/
    cp /lib64/ld-linux-aarch64.so.1 /path/to/your/app/lib/
    cp /lib64/libm.so.6 /path/to/your/app/lib/

    或者使用 Bash 脚本自动化:

    #!/bin/bash
    
    APP_PATH="/path/to/your/app"
    EXECUTABLE="$APP_PATH/myapp"
    LIB_DIR="$APP_PATH/lib"
    
    mkdir -p "$LIB_DIR"
    
    ldd "$EXECUTABLE" | while read -r line; do
        # Extract the library path from the line
        LIB_PATH=$(echo "$line" | awk '{ if ($3 != "") print $3 }')
        if [ -n "$LIB_PATH" ] && [ -f "$LIB_PATH" ]; then
            # Copy the library to the lib directory
            cp "$LIB_PATH" "$LIB_DIR/"
        fi
    done

    将上述脚本保存为 copy_libs.sh,然后运行:

    chmod +x copy_libs.sh
    ./copy_libs.sh
  4. 设置 LD_LIBRARY_PATH(可选):
    当你运行你的应用程序时,你可能需要设置 LD_LIBRARY_PATH 环境变量,以便程序在 lib 目录中查找动态库。

    export LD_LIBRARY_PATH=/path/to/your/app/lib:$LD_LIBRARY_PATH
    ./myapp

    或者,你可以在脚本中设置并运行:

    #!/bin/bash
    export LD_LIBRARY_PATH=/path/to/your/app/lib:$LD_LIBRARY_PATH
    ./myapp

通过这些步骤,你可以将 Qt 程序的所有依赖动态库拷贝到应用根目录下的 lib 目录中,并确保程序能够正确找到这些库。

2.将上面的脚本写成一个qt的程序

将依赖库的拷贝过程集成到一个 Qt 程序中是可行的,但需要注意的是,Qt 程序本身是一个 GUI 或控制台应用程序,而拷贝文件这样的操作通常更适合在构建系统(如 CMake 或 qmake)或部署脚本中完成。不过,如果你确实需要在 Qt 程序中执行这样的操作,你可以使用 Qt 的文件处理功能来实现。

下面是一个简单的 Qt 控制台应用程序示例,它演示了如何在程序中查找并拷贝依赖库。这个程序假设你已经知道如何获取依赖库的路径(通常是通过外部工具如 ldd),因为 Qt 本身没有直接提供解析 ELF 文件依赖的功能。

示例 Qt 程序

首先,确保你有一个基本的 Qt 项目结构。以下是一个简单的 main.cpp 示例,它演示了如何使用 QFile 和 QDir 来拷贝文件。

#include <QCoreApplication>
#include <QFile>
#include <QDir>
#include <QDebug>
#include <QProcess>

void copyLibrary(const QString &sourcePath, const QString &destinationDir) {
    QFile sourceFile(sourcePath);
    if (!sourceFile.exists()) {
        qWarning() << "Source file does not exist:" << sourcePath;
        return;
    }

    QDir destinationDirObj(destinationDir);
    if (!destinationDirObj.exists()) {
        destinationDirObj.mkpath("."); // Create the directory if it doesn't exist
    }

    QString destinationPath = destinationDir + "/" + sourceFile.fileName();
    if (QFile::copy(sourcePath, destinationPath)) {
        qDebug() << "Copied" << sourcePath << "to" << destinationPath;
    } else {
        qWarning() << "Failed to copy" << sourcePath << "to" << destinationPath;
    }
}

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    // Example: Hardcoded paths for demonstration
    QString executablePath = "/path/to/your/app/myapp"; // Your application path
    QString libDir = "/path/to/your/app/lib"; // Destination lib directory

    // Normally, you would use an external tool like `ldd` to get these paths
    // Here, we hardcode some example library paths
    QStringList libraryPaths = {
        "/usr/lib/aarch64-linux-gnu/libQt5Core.so.5",
        "/usr/lib/aarch64-linux-gnu/libstdc++.so.6",
        "/lib64/libc.so.6",
        "/lib64/ld-linux-aarch64.so.1",
        "/lib64/libm.so.6"
    };

    // Copy each library to the lib directory
    for (const QString &libPath : libraryPaths) {
        copyLibrary(libPath, libDir);
    }

    return a.exec();
}

说明

  1. QFile 和 QDir
    • QFile 用于检查文件是否存在以及执行文件拷贝操作。
    • QDir 用于检查和创建目录。
  2. 硬编码路径
    • 示例中使用了硬编码的路径和库列表。在实际应用中,你需要通过某种方式(如运行 ldd 并解析其输出)动态获取这些路径。
  3. QProcess
    • 如果你需要在程序中运行 ldd 并解析其输出,可以使用 QProcess 来执行外部命令并捕获其输出。

注意事项

  • 安全性:确保你有权限访问和拷贝这些文件。
  • 可移植性:硬编码路径和库名会使程序缺乏可移植性。在实际应用中,应该根据目标系统的环境动态获取这些信息。
  • 错误处理:示例中包含基本的错误处理,但在实际应用中,你可能需要更详细的错误日志和处理机制。

如果你需要在 Qt 程序中动态获取依赖库路径,建议结合使用 QProcess 来运行 ldd,并解析其输出以获取库路径列表。

3.把获取动态库的部分,也变成自动获取 

要在 Qt 程序中自动获取可执行文件的动态库依赖路径,你可以使用 QProcess 来运行 ldd 命令,并解析其输出。下面是一个示例程序,它演示了如何自动获取一个可执行文件的依赖库路径,并将这些库拷贝到指定的目录中。

示例 Qt 程序

#include <QCoreApplication>
#include <QFile>
#include <QDir>
#include <QDebug>
#include <QProcess>
#include <QStringList>

void copyLibrary(const QString &sourcePath, const QString &destinationDir) {
    QFile sourceFile(sourcePath);
    if (!sourceFile.exists()) {
        qWarning() << "Source file does not exist:" << sourcePath;
        return;
    }

    QDir destinationDirObj(destinationDir);
    if (!destinationDirObj.exists()) {
        destinationDirObj.mkpath("."); // Create the directory if it doesn't exist
    }

    QString destinationPath = destinationDir + "/" + QFileInfo(sourceFile).fileName();
    if (QFile::copy(sourcePath, destinationPath)) {
        qDebug() << "Copied" << sourcePath << "to" << destinationPath;
    } else {
        qWarning() << "Failed to copy" << sourcePath << "to" << destinationPath;
    }
}

QStringList getDependentLibraries(const QString &executablePath) {
    QStringList libraryPaths;
    QProcess process;

    // Run the ldd command
    process.start("ldd", QStringList() << executablePath);
    process.waitForFinished();

    // Read the output
    QString output = process.readAllStandardOutput();
    QStringList lines = output.split("\n");

    // Parse the output to extract library paths
    for (const QString &line : lines) {
        if (line.contains("=>")) {
            QStringList parts = line.split("=>");
            if (parts.length() > 1) {
                QString libraryPath = parts[1].trimmed();
                // Remove parentheses and version information if present
                libraryPath = libraryPath.left(libraryPath.indexOf(' '));
                libraryPath = libraryPath.trimmed();
                if (!libraryPath.isEmpty() && libraryPath != "not found") {
                    libraryPaths.append(libraryPath);
                }
            }
        }
    }

    return libraryPaths;
}

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    QString executablePath = "/path/to/your/app/myapp"; // Your application path
    QString libDir = "/path/to/your/app/lib"; // Destination lib directory

    // Get the list of dependent libraries
    QStringList libraryPaths = getDependentLibraries(executablePath);

    // Copy each library to the lib directory
    for (const QString &libPath : libraryPaths) {
        copyLibrary(libPath, libDir);
    }

    return a.exec();
}

说明

  1. QProcess
    • 使用 QProcess 来运行 ldd 命令,并捕获其输出。
    • process.start("ldd", QStringList() << executablePath) 启动 ldd 进程。
    • process.waitForFinished() 等待进程完成。
    • process.readAllStandardOutput() 读取标准输出。
  2. 解析 ldd 输出
    • ldd 的输出通常包含行如 libname.so => /path/to/libname.so
    • 通过分割和修剪字符串来提取库路径。
    • 去除路径中的版本信息和括号。
  3. 拷贝库文件
    • 使用 QFile 和 QDir 来拷贝库文件到指定目录。

注意事项

  • 错误处理:示例中包含基本的错误处理。在实际应用中,你可能需要更详细的错误日志和处理机制,尤其是处理 ldd 输出中的 "not found" 情况。
  • 权限:确保程序有权限访问和拷贝这些文件。
  • 环境:该程序假设在类 Unix 系统上运行,因为 ldd 是 Unix 特有的工具。

通过这种方式,你可以在 Qt 程序中自动获取和拷贝动态库依赖,从而简化部署过程。

4.ldd 命令 

ldd 命令是 Linux 系统下用于打印程序或者库文件所依赖的共享库列表的工具。以下是关于 ldd 命令的详细介绍:

一、命令功能

ldd 命令用于列出可执行文件或共享库文件在运行时所需的共享库文件及其路径。它可以帮助开发人员和系统管理员排查因缺少库文件或库文件路径不正确导致的程序无法运行的问题。

二、命令格式

ldd [选项] <可执行文件或共享库文件>

三、常用选项

  • -v 或 --verbose:详细信息模式,打印所有相关信息,包括版本号、加载方式等。
  • -u 或 --unused:打印未使用的直接依赖。
  • -d 或 --data-relocs:执行重定位和报告任何丢失的数据对象。
  • -r 或 --function-relocs:执行数据对象和函数的重定位,并报告任何丢失的对象和函数。
  • --version:打印 ldd 命令的版本号。
  • --help:显示帮助信息。

四、命令原理

ldd 命令通过调用动态链接器(通常是 /lib/ld-linux.so.*)来获取可执行文件或共享库文件所依赖的共享库列表。它实际上执行的是类似于以下命令的操作:

/lib/ld-linux.so.* --list <可执行文件或共享库文件>

五、命令输出

ldd 命令的输出格式通常为:

<库文件> => <库文件路径>

如果库文件未找到,输出将显示 not found。此外,输出还可能包含库文件的状态信息,如版本不匹配、不兼容等。

六、使用示例

  1. 查看可执行文件所依赖的库

    ldd /path/to/executable

    这将列出可执行文件 /path/to/executable 所依赖的所有共享库文件及其路径。

  2. 查看共享库文件的依赖关系

    ldd /path/to/shared_library.so

    这将列出共享库文件 /path/to/shared_library.so 所依赖的其他共享库文件及其路径。

  3. 显示详细的依赖库信息

    ldd -v /path/to/executable

    这将以详细信息模式列出可执行文件 /path/to/executable 所依赖的所有共享库文件及其路径,包括版本号、加载方式等详细信息。

七、注意事项

  • ldd 命令只能用于 ELF 格式的可执行文件和共享库文件。对于其他格式的文件,如 a.out 格式,ldd 命令将无法正常工作。
  • 如果 ldd 命令未找到某个库文件,可能是因为该库文件未安装或未配置在动态链接器的搜索路径中。此时,可以通过修改 /etc/ld.so.conf 文件并运行 ldconfig 命令来更新动态链接器的搜索路径。

八、总结

ldd 命令是 Linux 系统下用于排查程序依赖库问题的有力工具。通过它,开发人员和系统管理员可以方便地查看程序所需的共享库文件及其路径,从而快速定位和解决因缺少库文件或库文件路径不正确导致的程序无法运行的问题。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值