Skip to content

BUG: ensure build options are preserved from an existing build directory#852

Open
Alvaro-Kothe wants to merge 2 commits into
mesonbuild:mainfrom
Alvaro-Kothe:fix/build-overwrite
Open

BUG: ensure build options are preserved from an existing build directory#852
Alvaro-Kothe wants to merge 2 commits into
mesonbuild:mainfrom
Alvaro-Kothe:fix/build-overwrite

Conversation

@Alvaro-Kothe

@Alvaro-Kothe Alvaro-Kothe commented Jun 15, 2026

Copy link
Copy Markdown

This ensures build options specified by the user when the build was first initialized are preserved, unless explicitly overridden.

Fixes #851.

@rgommers rgommers left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @Alvaro-Kothe, this PR is helpful, it looks like a clean solution. It shows that this can be done without anything special, and it makes these build options behave like all other options on a reconfigure, so they're less special while keeping their intended defaults.

This is a behavior change, but I think we can get away with it. The one relevant situation we had before is building invoking meson setup separately to pass build options, before a subsequent pip install command. That was necessary in some cases in the early days, because IIRC there were some limitations on what could be passed directly via pip or pypa/build, especially relevant for cross compilation. Here is an example I remember:

It's possible that on less actively maintained distros, such recipes are still in place. If they don't pass -Dbuildtype=release and the other options themselves (-Dn_debug=if-release is likely to be missing), then that will be broken by this PR, possibly silently at build time.

I think the change is a good one, but we'll have to do some more digging to find cases like the one above that could be affected, and see if they can be updated.

Comment thread mesonpy/__init__.py Outdated
setup_args.insert(0, '--reconfigure')
self._run(self._meson + ['setup', *setup_args])

if not reconfigure:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is the only change, the rest is just a reshuffle. It would be useful to expand the code comment, something like:

# default build options, overriding Meson's defaults for them.
# on a reconfigure, the values will persist unless the user explicitly
# passes new values for them.

Comment thread tests/test_project.py

# reconfiguration with a new option
project = mesonpy.Project(package_simple, tmp_path, meson_args={
'setup': ['-Doptimization=2'],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This test is correct but a little obscure, given that it doesn't directly checks default/updated values of any of the build options that meson-python actually overrides. Perhaps also assert that the buildtype is and remains debug.

While we're at it here, it looks like there is no test that checks that the default buildtype is release nor the default for b_vscrt. There is an test for ndebug in test_options.py. Would you mind adding a new test there checking that the defaults are as expected on a clean build?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Perhaps also assert that the buildtype is and remains debug.

I added some assertions in the initial configuration and in the reconfiguration, but I feel like most of them were redundant, considering the last assertion initial_options == reconfigure_options

There is an test for ndebug in test_options.py. Would you mind adding a new test there checking that the defaults are as expected on a clean build?

Created a new test in test_options.py, but I am not sure if the vscrt assertion is correct, since I am not on Windows and couldn't test it.

@rgommers

Copy link
Copy Markdown
Contributor

I think the change is a good one, but we'll have to do some more digging to find cases like the one above that could be affected, and see if they can be updated.

I checked these distros: conda-forge, Spack, Nix, OpenEmbedded/Yocto, Buildroot, Arch, Alpine, Void, Gentoo, Debian, Fedora. None would be affected.

There are some usages in individual packages and end user dev recipes with the meson setup && pip install pattern, e.g.:

https://github.com/veethahavya-CU-cz/gwswex/blob/b07177a0e9c4cd6992782f287f5d9379a2ad7c8d/pixi.toml#L65

https://github.com/numpy/numpy-user-dtypes/blob/5942234b1b88bd360e56eb6f3f5f520ffaa19890/stringdtype/reinstall.sh#L11-L13

https://github.com/scipy/scipy/blob/2b736e79c05f4df3a9ab0ae0f7f368dbfecfe117/.github/workflows/wheels.yml#L214-L220

That all uses patterns that are no longer needed, but used to be - so if we want to make this change, we should probably at a minimum emit clear warnings for one release cycle.

Comment thread mesonpy/__init__.py Outdated
Comment on lines +902 to +928
setup_args = [
setup_cmd = self._meson + ['setup']

if reconfigure:
setup_cmd.append('--reconfigure')

setup_cmd += [
os.fspath(self._source_dir),
os.fspath(self._build_dir),
# default build options
'-Dbuildtype=release',
'-Db_ndebug=if-release',
'-Db_vscrt=md',
# user build options
*self._meson_args['setup'],
# pass native file last to have it override the python
# interpreter path that may have been specified in user
# provided native files
f'--native-file={os.fspath(self._meson_native_file)}',
]
if reconfigure:
setup_args.insert(0, '--reconfigure')
self._run(self._meson + ['setup', *setup_args])

if not reconfigure:
# default build options
setup_cmd += [
'-Dbuildtype=release',
'-Db_ndebug=if-release',
'-Db_vscrt=md',
]

# user build options
setup_cmd += self._meson_args['setup']

# pass native file last to have it override the python
# interpreter path that may have been specified in user
# provided native files
setup_cmd.append(f'--native-file={os.fspath(self._meson_native_file)}')

self._run(setup_cmd)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I haven't thought much about the implications of this change. However, the implementation can be much more linear:

# Override Meson default build options to adjust the build
# process to the task of building Python wheels. These 
# defaults can be overridden by user options. To preserve
# user specified build options, do not pass these defaults
# when reconfiguring an existing build directory.
defaults = [
    '-Dbuildtype=release',
    '-Db_ndebug=if-release',
    '-Db_vscrt=md',
] if not reconfigure else []

setup_args = [
    os.fspath(self._source_dir),
    os.fspath(self._build_dir),
    # default build options
    *defaults
    # user build options
    *self._meson_args['setup'],
    # pass native file last to have it override the python
    # interpreter path that may have been specified in user
    # provided native files
    f'--native-file={os.fspath(self._meson_native_file)}',
]

and the rest remains the same.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Changed. I opted to not use the ternary, since the list is a little big.

@dnicolodi

dnicolodi commented Jun 16, 2026

Copy link
Copy Markdown
Member

I don't think this satisfies the user requirement in all cases.

Let's assume that the pyproject.toml has a setting like this:

[tool.meson-python.args]
setup = ['-Dbuildtype=release']

If the user installs the package like this pip install . -Csetup-args=-Dbuildtype=debug -Cbuild-dir=debug they get a debug build. However, when they re-install it like this pip install . -Cbuild-dir=debug they get a release build because the user options specified in pyproject.toml are still applied.

@rgommers

Copy link
Copy Markdown
Contributor

I think that's a different requirement, and I'm not sure how valid it is (it's certainly more niche). I'd expect that package authors only hardcode build options in [tool.meson-python.args] if they always want them - and for buildtype specifically, I'm not sure it makes sense to do that.

It could be addressed, but wouldn't that require keeping track of state explicitly? Right now everything is stateless, aside from what's in meson-info/intro-buildoptions.json.

Comment thread mesonpy/__init__.py
@@ -899,23 +899,33 @@ def _run(self, cmd: Sequence[str]) -> None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is also an imprecision in the commit message: the reconfigure argument is passed when the specified build directory is detected to contain a Meson build dir, not when it merely exist. And, as @rgommers already pointed out (IIRC) buildtype is not the only default argument passed. I would reword the commit message like this

BUG: do no pass default options when reconfiguring

This ensures build options specified by the user when the build was
first initialized are preserved, unless explicitly overridden.

Fixes #851.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated. Do I need to change the PR description too?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks. Updating the PR description as well may be useful - at least for me, this captured the essence of the change, and I didn't quite get it from the initial issue or PR description.

This ensures build options specified by the user when the build was
first initialized are preserved, unless explicitly overridden.

Fixes mesonbuild#851.
@Alvaro-Kothe Alvaro-Kothe force-pushed the fix/build-overwrite branch from 210b727 to 8538505 Compare June 16, 2026 17:23
@Alvaro-Kothe

Copy link
Copy Markdown
Author

From #852 (comment)

It could be addressed, but wouldn't that require keeping track of state explicitly?

_meson_args combine the CLI and pyproject.toml arguments, but seems to be possible to pass the cli arguments directly to _configure.


From #852 (comment)

That all uses patterns that are no longer needed, but used to be - so if we want to make this change, we should probably at a minimum emit clear warnings for one release cycle.

How do I emit warnings? I tried to use warnings.warn and _log and they don't show up when I use pip install unless I add --verbose.

Also, should the warning be a deprecation warning, i.e., create another PR/commit just for the warning, or should it warn on the current behaviour change?

The first link seems a little bit problematic with this change... It seems that they will end up creating debug builds instead of release builds because they do meson setup without setting the buildtype option.

@rgommers

Copy link
Copy Markdown
Contributor

How do I emit warnings?

Let's first check with @dnicolodi whether he agrees with a one-release warning cycle or not. One could also make a case about that probably not reaching the people who need to see it most.

they don't show up when I use pip install unless I add --verbose.

That's unavoidable I think, since it swallows all output.

@Alvaro-Kothe Alvaro-Kothe force-pushed the fix/build-overwrite branch from 8538505 to 59cbf82 Compare June 16, 2026 21:16
@Alvaro-Kothe Alvaro-Kothe force-pushed the fix/build-overwrite branch from 59cbf82 to 1af9044 Compare June 16, 2026 21:36
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 this pull request may close these issues.

pip install overrides existing build configuration

3 participants