Cargo lambda 构建找不到 OpenSSL 开发标头

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

我正在尝试使用 Cargo-lambda 在 Rust 中为 AWS 编写一个 lambda 函数。当我调用

cargo lambda new
时,由
cargo lambda build --release --arm64
生成的示例函数构建得很好。但是,当我尝试构建代码时,我按照 https://github.com/awslabs/aws-lambda-rust-runtimehttps://www.cargo-lambda.info/ 上的说明和示例进行编写guide/getting-started.html,构建无法找到 OpenSSL 的标头。我已经使用
pacman -S openssl
安装了 OpenSSL,并运行了
pacman -S linux-headers
,并尝试运行
export OPENSSL_LIB_DIR=/usr/lib/
export OPENSSL_INCLUDE_DIR=/usr/include/openssl/
以及在我的 Fish 配置文件中设置它们,但都不起作用。我过不去:

cargo:warning=build/expando.c:1:10: fatal error: 'openssl/opensslv.h' file not found
cargo:warning=#include <openssl/opensslv.h>

我已经目视验证了该文件存在于目录中,但由于某种原因

openssl-sys-0.9.87
无法找到它并出现恐慌。有其他人遇到过这种情况,或者有人有任何我可以尝试的想法吗?我不确定问题是否出在我的 Cargo-lambda 设置、我的 OpenSSL 设置、我的代码或其他方面。

此代码是使用

cargo lambda new project_name
生成的并且构建良好:

use lambda_runtime::{run, service_fn, Error, LambdaEvent};
use serde::{Deserialize, Serialize};

/// Main function generated by cargo-lambda
#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        // disable printing the name of the module in every log line.
        .with_target(false)
        // disabling time is handy because CloudWatch will add the ingestion time.
        .without_time()
        .init();

    lambda_runtime::run(service_fn(function_handler)).await
}

/// This is a made-up example.
#[derive(Deserialize)]
struct Request {
    command: String,
}

/// This is a made-up example of what a response structure may look like.
#[derive(Serialize)]
struct Response {
    req_id: String,
    msg: String,
}

/// This is the main body for the function.
/// Write your code inside it.
async fn function_handler(event: LambdaEvent<Request>) -> Result<Response, Error> {
    // Extract some useful info from the request
    let command = event.payload.command;

    // Prepare the response
    let resp = Response {
        req_id: event.context.request_id,
        msg: format!("Command {}.", command),
    };

    // Return `Response` (it will be serialized to JSON automatically by the runtime)
    Ok(resp)
}

这是我正在尝试构建的代码,但从

openssl-sys-0.9.87
中收到错误,即使它是在同一个项目中编写的并且遵循在线文档中的示例:

use lambda_runtime::{run, service_fn, Error, LambdaEvent};
use reqwest::blocking::Client;
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};

#[tokio::main]
async fn main() -> Result<(), lambda_runtime::Error> {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        // disable printing the name of the module in every log line.
        .with_target(false)
        // disabling time is handy because CloudWatch will add the ingestion time.
        .without_time()
        .init();

    let query = service_fn(query_handler);
    run(query).await
}

async fn query_handler(event: LambdaEvent<Value>) -> Result<Value, Error> {
    let (event, _context) = event.into_parts();
    let symbol = event["symbol"].to_string();
    let message = query_price(symbol)?;
    Ok(json!({ "message": format!("{}", message) }))
}

#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
struct PriceQuote {
    pub s: String,
    pub symbol: Vec<String>,
    pub ask: Vec<f32>,
    pub askSize: Vec<u32>,
    pub bid: Vec<f32>,
    pub bidSize: Vec<u32>,
    pub mid: Vec<f32>,
    pub last: Vec<f32>,
    pub volume: Vec<u32>,
    pub updated: Vec<u32>,
}

fn query_price(symbol: String) -> Result<String, reqwest::Error> {
    //let symbol = "AAPL";

    let url = format!("https://api.marketdata.app/v1/stocks/quotes/{}", symbol);
    let client = Client::new();
    let response = client.get(url).send()?;
    let price_quote: PriceQuote = response.json()?;

    let symbol: &String = &price_quote.symbol[0];
    let last_price: &f32 = &price_quote.last[0];

    Ok(format!("Last price for {} is {}", symbol, last_price).to_string())
}

为什么一个会建造而另一个却不会?我添加的依赖项是否会扰乱它?我的 OpenSSL 版本是否错误?我做错了吗?我缺少什么?抱歉,如果这些都是愚蠢的问题,我是 AWS 新手,我的头在旋转。

rust aws-lambda openssl cargo-lambda
2个回答
5
投票

不确定到底出了什么问题,但似乎 reqwest 板条箱是问题的根源。我从来没有遇到过这个问题,除了通过 Cargo-lambda 构建时,所以我想它与 Zig 有关?

无论哪种方式,都可以通过直接在 Cargo.toml 中添加 openssl 来解决:

openssl = { version = "0.10.35", features = ["vendored"] }

这似乎为 reqwest 提供了正确的链接,并允许构建 Cargo lambda。还没有测试 reqwest 是否仍然有效,但我认为没有理由不应该。

更新:该功能部署并且 reqwest 工作正常


0
投票

AWS Lambda 函数在 Amazon Linux 2 沙箱内执行,其中仅包含运行 Rust 二进制文件的最低限度功能,不包含 OpenSSL。

cargo lambda build
不是针对主机(构建)系统上可用的内容进行构建,而是针对来宾(运行时)Linux 沙箱上可用的内容进行构建,因此无法找到 OpenSSL 标头。 Cargo Lambda 文档提及:

`*-sys` libraries are not guaranteed to work unless they are completely linked to your binary

Rust

openssl
crate 可以切换为与
openssl = { version = "0.10.35", features = ["vendored"] }
中的
Cargo.toml
进行静态编译和链接(如 j-stach 已经提到的)。类似地,Rust
reqwest
crate(依赖于 OpenSSL 的 HTTPS 客户端)可以切换为使用
reqwest = { version = "0.11.23", features = ["native-tls-vendored"] }
reqwest = { version = "0.11.23", default-features = false, features = ["rustls"] }
进行静态编译和链接。

最后,如果你遇到心爱的

cargo lambda build
issue “不支持的链接器参数:--no-undefined-version”,只需使用
rustup default 1.69
将你的 Rust 降级到 1.69。

© www.soinside.com 2019 - 2024. All rights reserved.