Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fromager: vendor_rust behavior broken in workspaces with example code (eg cryptography) #529

Closed
pnasrat opened this issue Jan 9, 2025 · 4 comments · Fixed by #532
Closed

Comments

@pnasrat
Copy link
Contributor

pnasrat commented Jan 9, 2025

Summary

vendoring breaks with error for docs file cryptography-44.0.0/cryptography-44.0.0/docs/development/custom-vectors/aes-192-gcm-siv/verify-aes192gcmsiv/Cargo.toml

failed with error: current package believes it's in a workspace when it's not:

I tried to add a patch that adds exclude to the workspace members but it looks as if the vendor rust behavior of fromager is not aware of workspaces

excludes = [
    "docs/development/",
]

Analysis

Looking at the source fromager assumes any Cargo.toml in the source tree is included and does not honor workspace configuration as it just uses a glob. This seems brittle to projects using workspaces with example code in docs as cryptography have

manifests = list(project_dir.glob("**/Cargo.toml"))

Steps to reproduce

Added a branch with the patch and an e2e test demonstrating here

https://github.com/pnasrat/fromager/tree/vendor-cryptography-fails

@dhellmann wondering what the right behavior to do here, I wonder if rust vendoring should be configurable at the top level of fromager maybe via an env variable as different rebuilders may want different behavior from fromager here.

Logs

fromager log
cryptography: preparing source for cryptography==44.0.0 from /home/pnasrat/src/fromager/e2e-output/sdists-repo/downloads/cryptography-44.0.0.tar.gz
cryptography: updating vendored rust dependencies in /home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0
['cargo', 'vendor', '--manifest-path=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/docs/development/custom-vectors/aes-192-gcm-siv/verify-aes192gcmsiv/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/cryptography-cffi/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/cryptography-keepalive/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/cryptography-key-parsing/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/cryptography-openssl/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/cryptography-x509-verification/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/cryptography-x509/Cargo.toml', '/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/vendor'] failed with error: current package believes it's in a workspace when it's not:
current:   /home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/docs/development/custom-vectors/aes-192-gcm-siv/verify-aes192gcmsiv/Cargo.toml
workspace: /home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/Cargo.toml

this may be fixable by adding `docs/development/custom-vectors/aes-192-gcm-siv/verify-aes192gcmsiv` to the `workspace.members` array of the manifest located at: /home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/Cargo.toml
Alternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest.

  0%|                                                                                                                                                                                                                             | 0/1 [00:00<?, ?pkg/s]
ERROR: Command '['cargo', 'vendor', '--manifest-path=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/docs/development/custom-vectors/aes-192-gcm-siv/verify-aes192gcmsiv/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/cryptography-cffi/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/cryptography-keepalive/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/cryptography-key-parsing/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/cryptography-openssl/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/cryptography-x509-verification/Cargo.toml', '--sync=/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/src/rust/cryptography-x509/Cargo.toml', '/home/pnasrat/src/fromager/e2e-output/work-dir/cryptography-44.0.0/cryptography-44.0.0/vendor']' returned non-zero exit status 101.
+ on_exit
@dhellmann
Copy link
Member

dhellmann commented Jan 9, 2025

We have a similar issue with meson. We solved it by using a prepare_source hook to move the sources in the doc tree during the vendoring step. That's janky, so if we can add something to fromager to make it smarter, that would be great.

What would configuration options look like? Maybe something to override that default glob pattern (either as a separate glob or a list of globs)? Or does it need more information to describe what to do? @tiran is more familiar with rust, so he might have some ideas, too.

Here's our plugin, for reference:

import logging
import pathlib
import shutil

from fromager import context, sources, vendor_rust
from packaging.requirements import Requirement
from packaging.version import Version

logger = logging.getLogger(__name__)


def prepare_source(
    ctx: context.WorkContext,
    req: Requirement,
    source_filename: pathlib.Path,
    version: Version,
) -> tuple[pathlib.Path, bool]:
    source_root_dir, is_new = sources.unpack_source(
        ctx=ctx,
        req=req,
        version=version,
        source_filename=source_filename,
    )
    if is_new:
        # Move the 'test cases' directory out of the way to eliminate
        # issues with vendoring tests that try to deal with optional
        # packages that do not exist anywhere. We move it back after
        # vendoring because we want to keep the directory because we
        # want the tests to go into the source distribution when we
        # repackage it.
        test_dir = source_root_dir / "test cases"
        dest_dir = source_root_dir.parent / test_dir.name
        move_tests = test_dir.exists()

        if move_tests:
            logger.debug("saving %s", test_dir)
            shutil.move(test_dir, dest_dir)
        try:
            vendor_rust.vendor_rust(req, source_root_dir)
        finally:
            if move_tests:
                logger.debug("restoring %s", test_dir)
                shutil.move(dest_dir, test_dir)

    return source_root_dir, is_new

@pnasrat
Copy link
Contributor Author

pnasrat commented Jan 9, 2025

Off the top of my head:

  • fromager could parse the top level Cargo.toml and if there is a workspace table just invoke cargo vendor without using the glob.
  • As we expect cargo (given the cargo vendor command invoked the other alternative is to do something like cargo --offline metadata and parse the json metadata to build the vendor command args

Taking a step back here - what is the goal for doing the vendoring here, is it purely due to running with network isolation to allow for offline build - if so if network isolation is turned off perhaps a similar or connected setting/env var to disable vendoring.

For reference just invoking cargo vendor in cryptography does the following

cryptography ❯ cargo vendor 
   Vendoring asn1 v0.20.0 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/asn1-0.20.0) to vendor/asn1
   Vendoring asn1_derive v0.20.0 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/asn1_derive-0.20.0) to vendor/asn1_derive
   Vendoring autocfg v1.4.0 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/autocfg-1.4.0) to vendor/autocfg
   Vendoring base64 v0.22.1 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/base64-0.22.1) to vendor/base64
   Vendoring bitflags v2.6.0 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bitflags-2.6.0) to vendor/bitflags
   Vendoring cc v1.2.1 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.2.1) to vendor/cc
   Vendoring cfg-if v1.0.0 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cfg-if-1.0.0) to vendor/cfg-if
   Vendoring foreign-types v0.3.2 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/foreign-types-0.3.2) to vendor/foreign-types
   Vendoring foreign-types-shared v0.1.1 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/foreign-types-shared-0.1.1) to vendor/foreign-types-shared
   Vendoring heck v0.5.0 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/heck-0.5.0) to vendor/heck
   Vendoring indoc v2.0.5 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/indoc-2.0.5) to vendor/indoc
   Vendoring itoa v1.0.14 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/itoa-1.0.14) to vendor/itoa
   Vendoring libc v0.2.166 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libc-0.2.166) to vendor/libc
   Vendoring memoffset v0.9.1 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/memoffset-0.9.1) to vendor/memoffset
   Vendoring once_cell v1.20.2 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.20.2) to vendor/once_cell
   Vendoring openssl v0.10.68 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/openssl-0.10.68) to vendor/openssl
   Vendoring openssl-macros v0.1.1 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/openssl-macros-0.1.1) to vendor/openssl-macros
   Vendoring openssl-sys v0.9.104 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/openssl-sys-0.9.104) to vendor/openssl-sys
   Vendoring pem v3.0.4 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/pem-3.0.4) to vendor/pem
   Vendoring pkg-config v0.3.31 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/pkg-config-0.3.31) to vendor/pkg-config
   Vendoring portable-atomic v1.10.0 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/portable-atomic-1.10.0) to vendor/portable-atomic
   Vendoring proc-macro2 v1.0.92 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.92) to vendor/proc-macro2
   Vendoring pyo3 v0.23.2 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/pyo3-0.23.2) to vendor/pyo3
   Vendoring pyo3-build-config v0.23.2 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/pyo3-build-config-0.23.2) to vendor/pyo3-build-config
   Vendoring pyo3-ffi v0.23.2 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/pyo3-ffi-0.23.2) to vendor/pyo3-ffi
   Vendoring pyo3-macros v0.23.2 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/pyo3-macros-0.23.2) to vendor/pyo3-macros
   Vendoring pyo3-macros-backend v0.23.2 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/pyo3-macros-backend-0.23.2) to vendor/pyo3-macros-backend
   Vendoring quote v1.0.37 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/quote-1.0.37) to vendor/quote
   Vendoring self_cell v1.0.4 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/self_cell-1.0.4) to vendor/self_cell
   Vendoring shlex v1.3.0 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/shlex-1.3.0) to vendor/shlex
   Vendoring syn v2.0.89 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.89) to vendor/syn
   Vendoring target-lexicon v0.12.16 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/target-lexicon-0.12.16) to vendor/target-lexicon
   Vendoring unicode-ident v1.0.14 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-ident-1.0.14) to vendor/unicode-ident
   Vendoring unindent v0.2.3 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/unindent-0.2.3) to vendor/unindent
   Vendoring vcpkg v0.2.15 (/home/pnasrat/.cargo/registry/src/index.crates.io-6f17d22bba15001f/vcpkg-0.2.15) to vendor/vcpkg

@tiran
Copy link
Collaborator

tiran commented Jan 9, 2025

I agree with @pnasrat analysis. My Rust vendor code is naive and brute force. It got the job done and I haven't spent any additional time on it. Let's first try to make the code more clever before we resort to a new option.

Until cryptography 44.x, there was no top-level Cargo.toml. The build backend and location of Cargo.lock has changed, too.

We need to deal with all cases.

@dhellmann
Copy link
Member

Yes, the vendoring had to do with isolated builds. So, I agree that we could probably skip that step if isolation is disabled. Maybe just log a warning and skip it, without adding a separate option?

I also like some of the ideas proposed for making the logic smarter. I imagine we could take that, too far, though. Is there a minimal change that would fix this issue, without trying to solve for all possible cases? Then we could tackle other cases individually.

tiran added a commit to tiran/fromager that referenced this issue Jan 10, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Fromager was vendoring crates from all `Cargo.toml` files in a project.
This approach is causing issues for projects that have cargo files in
tests and example directories.

The `vendor_rust()` function now only vendors crates from `Cargo.toml`
in the project's root directory and additional cargo files listed in
`tools.maturin` or `tools.setuptools-rust` entries.

Fixes: python-wheel-build#529
Signed-off-by: Christian Heimes <cheimes@redhat.com>
pnasrat added a commit to pnasrat/fromager that referenced this issue Jan 10, 2025
See: python-wheel-build#529

While improving the vendor logic for more complex source cases this fixes building cryptography if network isolation turned off

Signed-off-by: Pris Nasrat <pris.nasrat@chainguard.dev>
tiran added a commit to tiran/fromager that referenced this issue Jan 22, 2025
Fromager was vendoring crates from all `Cargo.toml` files in a project.
This approach is causing issues for projects that have cargo files in
tests and example directories.

The `vendor_rust()` function now only vendors crates from `Cargo.toml`
in the project's root directory and additional cargo files listed in
`tools.maturin` or `tools.setuptools-rust` entries.

Fixes: python-wheel-build#529
Signed-off-by: Christian Heimes <cheimes@redhat.com>
tiran added a commit to tiran/fromager that referenced this issue Jan 23, 2025
Fromager was vendoring crates from all `Cargo.toml` files in a project.
This approach is causing issues for projects that have cargo files in
tests and example directories.

The `vendor_rust()` function now only vendors crates from `Cargo.toml`
in the project's root directory and additional cargo files listed in
`tools.maturin` or `tools.setuptools-rust` entries.

Fixes: python-wheel-build#529
Signed-off-by: Christian Heimes <cheimes@redhat.com>
tiran added a commit to tiran/fromager that referenced this issue Jan 23, 2025
Fromager was vendoring crates from all `Cargo.toml` files in a project.
This approach is causing issues for projects that have cargo files in
tests and example directories.

The `vendor_rust()` function now only vendors crates from `Cargo.toml`
in the project's root directory and additional cargo files listed in
`tools.maturin` or `tools.setuptools-rust` entries.

Fixes: python-wheel-build#529
Signed-off-by: Christian Heimes <cheimes@redhat.com>
tiran added a commit to tiran/fromager that referenced this issue Jan 23, 2025
Fromager was vendoring crates from all `Cargo.toml` files in a project.
This approach is causing issues for projects that have cargo files in
tests and example directories.

The `vendor_rust()` function now only vendors crates from `Cargo.toml`
in the project's root directory and additional cargo files listed in
`tools.maturin` or `tools.setuptools-rust` entries.

Fixes: python-wheel-build#529
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants