Почему использование extern позволяет выполнять связывание во время выполнения?

У меня есть этот фрагмент кода:

    extern crate blas;
    extern crate openblas_src;
    pub fn eigen_decompose_symmetric_tri_diagonal(
        main_diag: &Vec<f64>,
        sub_diag: &Vec<f64>,
    )
    {
     /* code */
    lapack::dsteqr(/* args */);
    /* code */
    }

Здесь используется привязка Lapack. Чего я не понимаю, так это того, что если я закомментирую два внешних оператора, я получу ошибку компоновщика, где dsteqr не найден. Я хотел бы понять, почему это происходит.

пожалуйста, включите зависимости Cargo.toml и покажите ошибку компоновщика

kmdreko 18.07.2024 06:22
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
1
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Компилятор не будет связывать зависимость, если считает, что она не используется.

В книге Rusc о параметре --extern (именно так Cargo предоставляет зависимости):

Указание --extern имеет одно отличие в поведении от extern crate: --extern просто делает ящик кандидатом на привязку; на самом деле он не связывает его, если он не используется активно. В редких случаях вам может потребоваться обеспечить связь с крейтом, даже если вы не используете его активно из своего кода: например, если он меняет глобальный распределитель или содержит символы #[no_mangle] для использования другими языками программирования. В таких случаях вам нужно использовать extern crate.

Таким образом, добавление extern crate openblas_src; гарантирует, что он будет связан с системной библиотекой openblas.

Однако обычно это не проблема, о которой вам стоит беспокоиться. Если вы добавляете зависимость груза и просто не используете ее, вероятно, лучше, чтобы она не требовала этой связи во время выполнения. И даже если вы не используете крейт -sys напрямую, использование крейта, который сам зависит от него и использует его, будет считаться «использованным» и автоматически связываться.

Встреча с этой ошибкой довольно уникальна для blas/lapack, поскольку существуют конкурирующие системные библиотеки (accelerate, blis, intel-mkl, netlib, openblas), которые обеспечивают функциональность, на которую полагаются библиотеки более высокого уровня. Крейты blas/lapack опираются на свои аналоги -sys, но это всего лишь объявления функций и в них отсутствуют ссылки= на конкретную системную библиотеку. Таким образом, они просто полагаются на глобальные символы, чтобы связать их во время компоновки, что, как указано выше, не будет гарантировано, если extern crate не будет добавлен конечным пользователем для одного из -src ящиков реализации. Немного дополнительной информации на их blas-lapack-rs вики.

@eggyal очень признателен! Я включил это в ответ

kmdreko 18.07.2024 20:35

Другие вопросы по теме