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

devpkg: auto-patch python #2250

Merged
merged 1 commit into from
Sep 6, 2024
Merged

devpkg: auto-patch python #2250

merged 1 commit into from
Sep 6, 2024

Conversation

gcurtis
Copy link
Collaborator

@gcurtis gcurtis commented Sep 4, 2024

Add a devbox add --patch <mode> flag that replaces --patch-glibc and a corresponding patch JSON field that replaces patch_glibc. The new name reflects the new patching behavior, which affects more than just glibc.

The new patch flag/field is a string instead of a bool. Valid values are auto, always and never. The default is auto.

devbox add --patch <auto/always/never>
  • auto - let Devbox decide if a package should be patched. Currently only enables patching for Python or if patch_glibc is true in the config.
  • always - always attempt to patch a package. Corresponds to the --patch-glibc=true behavior.
  • never - never patch a package, even if auto would.

If a config has an existing package with the "patch_glibc": true field, it's interpreted as "patch": "always" but the config itself isn't modified. However, if the user runs a command that does write to the config, then patch_glibc will be migrated to patch.

Example devbox.json:

{
  "packages": {
    "ruby": {
      "version": "latest",
      "patch":   "always"
    },
    "python": {
      "version": "latest"

      // No patch field implies "auto".
      // "patch": "auto"
    }
  }
}

@@ -238,6 +238,12 @@ func (p *Package) IsInstallable() bool {
}

func (p *Package) PatchGlibc() bool {
if p.CanonicalName() == "python" {
if p.patchGlibc != nil && !p.patchGlibc() {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this actually still needs a tweak to distinguish between missing and false.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Lagoja
Copy link
Contributor

Lagoja commented Sep 4, 2024

  1. Should we rename this option from patch_glibc?
  2. Would enabling this option for other non-Python packages have a similar effect?

@mikeland73
Copy link
Contributor

Should we add a feature flag for the opt out? Or just go for it?

Copy link
Contributor

@mikeland73 mikeland73 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve pending opt-out option.

I think we should either feature flag it, or make sure the opt out works before releasing.

@Lagoja
Copy link
Contributor

Lagoja commented Sep 5, 2024

I would suggest that we do a beta release, test it a bunch internally + with the community, and then release. I think an opt-in/flag is too hard for users to discover and activate. I would be open to an opt-out, maybe with a differently named flag.

@gcurtis
Copy link
Collaborator Author

gcurtis commented Sep 5, 2024

@Lagoja

  1. Should we rename this option from patch_glibc?

That's probably a good idea since it does a bit more now. What about autopatch or just patch? I'll leave patch_glibc in as an alias for backwards compatibility.

  1. Would enabling this option for other non-Python packages have a similar effect?

I haven't tested it on any other packages, but the patching logic is pretty general. It'll look for any ELF binaries in the package's bin directory, update glibc, and convert RUNPATH to RPATH on all of them.

The stuff with restoring build inputs is specific to Python and will just be a no-op on other packages.

@Lagoja
Copy link
Contributor

Lagoja commented Sep 5, 2024

Prefer autopatch for resemblance to autopatchElf

@gcurtis
Copy link
Collaborator Author

gcurtis commented Sep 6, 2024

@savil @mikeland73 I made some pretty substantial changes if you want to take another look. I switched things over to use a new --patch auto/always/never flag instead.

Add a `devbox add --patch <mode>` flag that replaces `--patch-glibc` and
a corresponding `patch` JSON field that replaces `patch_glibc`. The new
name reflects the new patching behavior, which affects more than just
glibc.

The new patch flag/field is a string instead of a bool. Valid values are
`auto`, `always` and `never`. The default is `auto`.

	devbox add --patch <auto/always/never>

- `auto` - let Devbox decide if a package should be patched. Currently
  only enables patching for Python or if `patch_glibc` is true in the
  config.
- `always` - always attempt to patch a package. Corresponds to the
  `--patch-glibc=true` behavior.
- `never` - never patch a package, even if `auto` would.

If a config has an existing package with the `"patch_glibc": true`
field, it's interpreted as `"patch": "always"` but the config itself
isn't modified. However, if the user runs a command that does write to
the config, then `patch_glibc` will be migrated to `patch`.

Example `devbox.json`:

```json5
{
  "packages": {
    "ruby": {
      "version": "latest",
      "patch":   "always"
    }
    "python": {
      "version": "latest"

      // No patch field implies "auto".
      // "patch": "auto"
    }
  }
}
```
Copy link
Contributor

@mikeland73 mikeland73 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

in a follow up could we add a warning if patch_glibc is set in config?

patch_glibc is deprecated and will be removed in a future version. Use patch: always instead.

@@ -216,7 +216,72 @@ func (c *configAST) appendAllowInsecure(name, fieldName string, whitelist []stri
c.appendStringSliceField(name, fieldName, whitelist)
}

func (c *configAST) FindPkgObject(name string) *hujson.Object {
// removePatch removes the patch field from the named package.
func (c *configAST) removePatch(name string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we generalize these similar to setPackageBool ?

removePackageField for removing.
setPackageString for adding.

setPatch could wrap these (remove patch_glibc add patch) or you could not special case at all and have the code in packages.go do that logic). That keeps the ast more logic agnostic.

Honestly, you could also not remove patch_glibc. It doesn't really do harm and would allow us to have simpler code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making them more general sounds good to me. I'd like to do in a follow-up PR though just to get the patching stuff out the door.

@gcurtis gcurtis merged commit 74f4a2a into main Sep 6, 2024
24 checks passed
@gcurtis gcurtis deleted the gcurtis/patchpkg-auto branch September 6, 2024 22:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants