Skip to content

Conversation

@Flamefire
Copy link
Contributor

@Flamefire Flamefire commented Feb 4, 2025

Using buildcmd to pass options to setup.py is confusing and makes it impossible to fully replace the build command.
Introduce build_target similar to install_target and deprecate passing a target and optional options via buildcmd.

The old behavior is used when buildcmd is a known setup.py command such as build or build_ext or a single word, e.g. clean.

My first attempt was to only detect buildcmd = '%(python)s ...' as an immediate fix for #3570 but that would limit us to much going forward when a Python package build uses a custom command like ./build_wheel --foo

If this is acceptable I can open an accompanying PR to update the EasyConfigs to replace buildcmd.

@@ -408,17 +408,18 @@ def extra_options(extra_vars=None):
extra_vars = {}
extra_vars.update({
'buildcmd': [None, "Command for building the package (e.g. for custom builds resulting in a whl file). "
Copy link
Contributor

Choose a reason for hiding this comment

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

Please indicate that this is deprecated, e.g.

Suggested change
'buildcmd': [None, "Command for building the package (e.g. for custom builds resulting in a whl file). "
'buildcmd': [None, "DEPRECATED: Command for building the package (e.g. for custom builds resulting in a whl file). "

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not deprecated. It is exactly what it states: If set it will be used for building the package.

There is a deprecated (and undocumented) code path that it uses setup.py {buildcmd} when buildcmd starts with build or build_ext to avoid breaking existing code.

Copy link
Member

Choose a reason for hiding this comment

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

Does it make sense to keep both buildcmd and build_target supported though?

buildcmd clearly leaves room for confusion, so I'm also in favor of deprecating it, and using build_target instead. That should work, no?

Comment on lines 837 to +813
if not build_cmd:
build_cmd = 'build' # Default value for setup.py
build_cmd = f"{self.python_cmd} setup.py {build_cmd}"
build_cmd = f"{self.python_cmd} setup.py {self.cfg['build_target']}"
elif any(build_cmd.startswith(cmd) for cmd in ('build ', 'build_ext ')) or re.match(r'\w+', build_cmd):
if ' ' not in build_cmd:
self.log.deprecated("Use 'build_target' instead of 'buildcmd' "
"to pass the build target to setup.py", '5.1')
else:
self.log.deprecated("Use 'build_target' and 'buildopts' instead of 'buildcmd' "
"to pass arguments to setup.py", '5.1')
build_cmd = f"{self.python_cmd} setup.py {build_cmd}"
Copy link
Contributor

Choose a reason for hiding this comment

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

I would like to see a more direct discouragement of using buildcmd, now it would slip by without your knowing it was deprecated depending on what you set it to.

grepping through the easyconfigs, i think only PyTorch was treating buildcmd this was, rest was already treating it as build_target, so.. lets just fix PyTorch and forget about that silly case?

if self.cfg['buildcmd'] is not None:  # should never be set anymore
    build_target = buildcmd
    self.log.deprecated('use build target and buildopts instead of buildcmd blablabla')
else:
    build_target = buildcmd
    
...

    build_cmd = f'{self.python_cmd} setup.py {build_target}"

having it marked clearly deprecated, and the build_target being more clear in what it should contain, I think this is safe enough to change?
You can include a warning on not adding build_opts in there is we wanted, but i'm not sure we need to.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The idea here was to allow using a build command, not removing that. Imagine some Python package that requires ./build_python.sh to create a wheel. See the documentation of the option.

@Flamefire
Copy link
Contributor Author

Current behavior:

  1. When use_pip = True (preferred way) then buildcmd is used as a command to run if explicitely set. Usually it does nothing in the build step
  2. Otherwise (setup.py) buildcmd is (ab)used as a parameter(s) to python setup.py

So for 1. it works as intended, only 2 is basically broken/unintuitive.

The intention here is:

  1. If buildcmd is set it is used as-is
  2. Else
    If use_pip is not set then build_target is used, defaulting to "build" as the parameter to setup.py
    if use_pip is set then no build command is run
  3. To support the current abuse there is logic to detect when buildcmd is set to something intended for setup.py not as a command itself. This is deprecated

The jaxlib easyblock has use_pip=True, defaults buildcmd to build/build.py and will later issue pip install dist/*.whl by just setting install_src

We could have easyblocks implement build_step if required but IMO this would be a lot of boilerplate and one could forget e.g. (pre)buildopts. Additionally, the PythonPackage easyblock captures the output of the buildcmd to detect e.g. downloaded dependencies.
So IMO keeping the buildcmd can be useful.

Maybe: Add build_cmd and deprecate buildcmd. Handle buildcmd as currently done (in the surprising way) but push users of that to build_cmd or build_target. That would be consistent in naming to e.g. ConfigureMake etc., avoid heuristic detection of the intended meaning and give full flexibility when required.

@boegel boegel moved this from Blockers to Nice-to-have in EasyBuild v5.0 Mar 3, 2025
@boegel boegel modified the milestones: 5.0.0, release after 5.0.0 Mar 18, 2025
@boegel boegel changed the base branch from 5.0.x to develop March 19, 2025 11:10
@boegel
Copy link
Member

boegel commented Mar 19, 2025

@Flamefire I changed to target branch in this PR from 5.0.x to develop, you should synchronize your PR branch with current develop branch (which has received a massive update after the release of EasyBuild v5.0.0, see #3670)

@boegel boegel modified the milestones: next release (5.1.0), 5.x May 22, 2025
Flamefire added 2 commits May 23, 2025 11:10
Using `buildcmd` to pass options to `setup.py` is confusing and makes it
impossible to fully replace the build command.
Introduce `build_target` similar to `install_target` and deprecate
passing a target and optional options via `buildcmd`.

The old behavior is used when `buildcmd` is a known setup.py command
such as `build` or `build_ext` or a single word, e.g. `clean`.
@Flamefire Flamefire force-pushed the pythonpackage-build-setuppy branch from aa56a6b to ceefb81 Compare May 23, 2025 09:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

No open projects
Status: Nice-to-have

Development

Successfully merging this pull request may close these issues.

3 participants