-
Notifications
You must be signed in to change notification settings - Fork 61
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
Support for pip install
as a standard Python package
#737
Conversation
@juan-g-bonilla Please have a look at this. It's the minimal set of changes to get I had some issues with the old CMake findPython a while back, here I've pre-emptively added support for building with the limited Python API which we will need for generic builds, so I've made some minor changes to the CMake files (and upgraded the minimum CMake version required). This changes how Python is found by CMake a bit so there's a small chance it might break some people's existing builds (if they have Python installed in a weird place, I guess), but I recommend keeping these changes in place regardless. |
685b842
to
39271b6
Compare
@juan-g-bonilla I've converted back to draft, because I'm still not happy with some of this structure. Although this follows the latest standards, there's too many hacks to get around issues with |
Howdy @dpad , let's keep this at draft at the moment until we can fully iterate on this. I'll be on travel for the next two weeks and will be able to look at this in earnest. We definitely need to test this on all the supported platforms. I would like to minimize any changes to the user facing build system if possible to ease any disruption to other users build process. I see you added the legacy build option for now. Thanks. This will allow us to depreciate the old build system. Naturally we will have to update the build documentation :-) I'll definitely want to do many test builds on different computers. I have general questions.
Looking forward to playing with this branch more when I return from travel. |
Hi @schaubh , thanks for checking and the questions! There are some annoying limitations of
I included the
I'm not sure if these IDEs do anything special, but incremental builds are possible for editable installations, but it's a little tricky. Basically, there is a trade-off: Pip with build isolation (default): Pip without build isolation (
Conan arguments can be passed in directly through an environment variable:
I used an environment variable because
I have not noticed much difference personally, but I suspect it is a tad slower. It installs the build tools every time, so there are at least a few extra seconds at the beginning.
Thank you for checking on Mac+3.11! Actually, The reason for the error you noticed is that both If you need (In addition, I guess this scenario does not get exercised during unit tests, so this error is not caught automatically.)
Due to the above annoyances of
Yes, I think the
By default, we specify the Please let me know if anything is unclear, and enjoy your travels! |
Thanks for the info @dpad . From what you are explaining, it sounds like the I have pinged some other BSK developers to take a look at this branch as well to get broad community feedback. Making wheels would be very exciting ;-) |
3e2f39e
to
036c4b0
Compare
@schaubh Yes, for now, the
I considered some alternative build backends, but had issues with each of them for maintaining backwards compatibility. As dirty as the current Also note, I've added |
e382dd0
to
fab235d
Compare
Hi @dpad ! Awesome work with this PR. I've been trying to build in Windows these past days with little success. The installation seems to be failing to link a missing file
and the other for the failed build with this PR:
These are my env variables:
I tried changing the I can keep tinkering, but thought I would post to see if you had any ideas. |
Hi @juan-g-bonilla , thanks a lot for trying it out! I had a look at my old branch that did more work on the Windows side. It seems I had to add a hack-around for MSVC. Have a look at this: Alternatively, you could try reverting my Or, just disable the "PY_LIMITED_API" definition inside (I'll either add the above hack or revert to |
Thanks @dpad ! With following it builds correctly:
|
@juan-g-bonilla I pushed some additional minor changes, including one that should fix the above Windows build issue properly (without that "hacky" work-around). However, I believe last time I tried it, Windows had issues with more recent versions of CMake. Would you mind trying out the latest changes again? If they work on both Windows and Mac, then I think this is ready for review. |
f67ec6b
to
d8a981b
Compare
@juan-g-bonilla Thanks again for your help! I've finished cleaning up and have updated the main merge request comment above, including a new "Motivation & Rationale" section. I have maintained full backwards compatibility with the existing I'm going to take this off Draft for now and leave it with you, if that's okay.
|
Hi @dpad , thanks for all the work! Before we go through final review, would you find cleaning up the commits? In Basilisk, once we are satisfied with a PR, we usually rebase all commits and re-commit such that all related changes go together (while usually changes in commits appear chronologically as they are developed). Some commits might make better sense together or split, for example. A good example in this PR is the Moreover, it would be great if you could update the release notes with this change, as well as the documentation for how to setup Basilisk. |
23158d7
to
0c7c1c8
Compare
@juan-g-bonilla Thanks for getting back to me! I've cleaned up the commits and added some documentation + release notes. Please have a look. |
I'm back from my travel and catching up on lots of other work tasks. I plan to return to this PR early next week to review and test in more detail. I also want some of my researchers to pull and do test builds across more computers. |
Checked again that the PR builds on my Windows machine without issue. Don't know enough about the build system and libraries here to do little more than bikeshedding, but I reviewed the code and didn't find any obvious code smell. Let's get more people to build this on their systems and then run the workflows. |
Ok, did a clean macOS build of your branch using
Is this expected? Would it make sense to turn on "Based on dependency analysis"? Good news is the build worked as expected and all associated unit tests passed. Trying next with |
Built with |
@schaubh Thanks very much for your and your researchers' efforts in checking this! I'm sorry that I have not had a chance to make the requested review changes yet, I may have some time later this week or next, but if not please feel free of course to update this branch as you see fit. |
Howdy @dpad, you say "update the branch". I did add your fork to my BSK source setup so I can directly pull your branch. But, I can't push back any edits to it, I don't have write access. I applied my requested changes to |
Thanks, I'll give this a try. This would make collaboration with external contributors that much easier. I'll apply my edits and squash them into your commits to leave a clean, rebased branch that I was testing. |
Howdy @dpad , I pulled your latest branch, applied all my small tweaks and edits, fixed the footnote RST issue I found. However, when I try to force push the rebased branch to your fork I get this error:
Any idea what is happening here? |
- `python conanfile.py` still works as before and is recommended for development usage. - Added broader platform support by building using the limited Python API. - Added missing runtime dependencies (originally installed as dependencies of 'conan').
…applies during the first Conan run. Fixes AVSLab#525.
…duce size of generated wheels. Effectively reduces the wheel size from ~750MB to ~550MB.
…ing arguments (e.g. "--clean --no-clean").
make the depreciation warning explicit as to when this backwards compatibility will be removed.
Hi @schaubh , I also haven't used this feature before, but it sounds like potentially an issue with git-lfs. I'm not sure if it'll work, but could you try the setting below? (The
|
28685b0
to
39e023e
Compare
Wheels are working well though! I am wondering how to reduce their size though, the Spice data is the biggest hit. We should think about how this is packaged in the future. I don't see a reason the data files should be part of the wheel? If someone runs BSK scripts and loads up data files, then they have to ensure the files are in the proper location relative to the script? |
@schaubh It seems your push worked, no? Regarding wheel sizes, I haven't looked into or thought about it too much yet, but I definitely noticed the SPICE data being the biggest. One option could be to have a kind of "lazy load" of SPICE data, where it only downloads the data the first time it is used.1 Otherwise, you could just leave the data as is, since I guess most users will probably need the SPICE data anyway, it won't save much time or effort downloading them later. Looking into this though, I've just learned that Pypi apparently has a size limit of 100MB (although it can be increased in some cases), so we would probably have to host the wheel files ourselves anyway (e.g. as Github release artifacts), which is probably not a huge deal either. But any effort to reducing the size might be worth it. Footnotes
|
Glad to see this force push worked! It wasn't apparent from my side. Regarding the wheel size, we can refine that in a separate branch. The data files are loaded dynamically in the BSK scripts. They just need to be available to the script, they don't need to be part of the wheel. We can do a separate branch to refine the wheel size now that this is working. I would like to get rid of the LFS requirement as well and find an alternate way to install the data files that are just needed to run BSK sample scripts, not for the software package itself. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After reading further, I think my comment isn't necessary. This also seems like a solid change to the build system that can unlock distributing Basilisk as a binary package which is EXTREMELY COOL!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great contribution. Many users will appreciate the ability to generate and install via wheels.
@schaubh @spiggottCO Thanks a lot for all the efforts from you and the other maintainers! Hopefully this is helpful going forward. The next step I recommend is to build these wheels as part of the CI process using a tool called The biggest will be that the CI builds take a fairly long time, and I'm not sure what limits there are for CI on Github... For reference, I've been using |
Howdy @dpad , thanks for sharing the info on automated CI builds. I'm still very new to this process and appreciate your insight. I did create a PyPi account and need to read up on the process of contributing in my spare time. |
@dpad I spent a bit of time looking into
I'm now looking at the route of just exporting the wheels generated by the result of our pip-based install test that does work (I want the wheel for use in another CI system and thus don't need a full set of platforms and versions, so |
Hi @Mark2000 , thanks for looking into it! I'm not sure I can tell you much without seeing the full context of what you're trying, but it looks like you might be trying to use a pre-compiled version of protobuf? If this was running in Did the call to For reference, the settings below for [tool.cibuildwheel]
skip = [
# Don't build musllinux or on Pypy.
"*-musllinux_*",
"pp*",
# TODO: Fix support for Python 3.12+.
"cp312-*",
"cp313-*",
]
# Run simple build test
test-command = [
"ctest -C Release --test-dir {package}/dist3",
"pytest {package}/src/tests -m \"not scenarioTest\"",
]
test-extras = ["test"]
# Build using the future-compatible manylinux_2_28 image.
# NOTE: This image contains a version of gcc that is not used by Conan's build servers,
# so it forces Conan to build all dependencies from source instead of downloading prebuilt binaries.
manylinux-x86_64-image = "manylinux_2_28"
# Only compile on 64-bit architectures for now.
[tool.cibuildwheel.linux]
environment-pass = ["CONAN_ARGS"]
archs = "auto64"
repair-wheel-command = [
# Add --strip to the repair command to minimise the wheel size.
# See https://github.com/AVSLab/basilisk/issues/814#issuecomment-2377263412
"auditwheel repair --strip -w {dest_dir} {wheel}",
] |
Ah, okay. Some chatgpt-aided debugging got me to the point of realizing that I needed to get Conan to build protocol from source, but couldn't get the configs quite right. |
I have a basilisk build with some External Modules, so is this feature currently not applicable for that case? In that case, whats the best alternative to distribute, docker? |
@ephraim271 If you build with External Modules, the resulting wheel will have them, and you can distribute that just like you would any other python wheel. The separate External Modules compilation feature would be to be able to build separate wheels for the core Basilisk and the External Modules, e.g., a future where you could install Basilisk from the public pypi server, and your own External Modules from an internal server. |
pip install
, not when usingpython conanfile.py
:pip
as a subprocess from the Conanfile)pip install
method)pip install Basilisk
)Description
CC: @juan-g-bonilla @schaubh
This is the first part of moving towards a modern Python build system with distributable pre-compiled packages that users can install directly, as based on #614 .
pip install .
(-v
flag to monitor compilation progress)python -m build --sdist
generates a "source distribution" (.tar.gz) file that can bepip
-installed (don't needgit
).pip wheel --no-deps .
generates a "wheel" (.whl) that can bepip
-installed (no compilation required).CONAN_ARGS
environment variable. e.g.CONAN_ARGS="--opNav True"
.pip
now callsconan
, instead of the opposite).python conanfile.py
installation behaviour, continues to work as before.pip
).pip
, everything is built automatically within isolated temporary build environments.pip
itself is no longer upgraded automatically. The installation should error if the version ofpip
is too low to correctly support the above features.setup.py
takes care of compilation by calling the Conan build system.python setup.py
functionality. Do not runpython setup.py
, it is NOT supported in modern Python.Motivation & Rationale
In recent years, Python "wheels" have become the standard way to distribute pre-compiled Python packages to end-users. Until now, Basilisk has been compiled and installed by users manually, using some invocation of
python conanfile.py
. However, in future, it would be desirable for an end-user to simply install a pre-compiled Basilisk package, for example by callingpip install Basilisk
.The Python community has established several standards for which all build tools are expected to follow in the future. These include:
pyproject.toml
fileMost end-users interact directly with a frontend tool (e.g.
pip
) to install Python packages. However, the actual package is built by the "backend" tool, as specified in the[build-system]
part of thepyproject.toml
file. For Basilisk, we need a backend tool that can build custom "extension" modules (not just pure Python, but compiled from C/C++ source code).This merge request adds the above
pyproject.toml
file and configures thesetuptools
backend build tool to correctly build the Basilisk extension modules. It is a little hacky in places, butsetuptools
was selected because:--config-settings
, but we assume it will in the future.--global-option
and--build-option
pypa/pip#11859 (comment)CONAN_ARGS
environment variable.The following backends were also investigated, but rejected:
hatchling
doesn't support--config-settings
(no indication of whether it ever will) and isn't as well-supported as setuptools.scikit-build
andscikit-build-core
assume the invocation is "cmake", which conflicts with our use of Conan.flit
doesn't support build plugins at all.poetry
likes to do its own thing, doesn't always follow standards.pdm
works, but has some fiddly file discovery, and is not as well-supported as setuptools.meson-python
is the build tool for numpy/scipy now, and seems like a good alternative if we ever want to switch away from Conan.For further reference, refer to:
Verification
Verified to work on my local Linux (Ubuntu 22.04) machine:
pip install .
. Passes all tests, including scenario tests. (pytest src/
)pip wheel .
and install it. Passes all tests as above.python -m build --sdist
and install it. Passes all tests as above.python conanfile.py --opNav True
. Passes all tests as above.CONAN_ARGS="--opNav True"
, confirmed that opNav installs and all tests pass.TODO (I'm leaving these for the maintainers, CC @juan-g-bonilla ):
Documentation
TODO (I'm leaving these for the maintainers, CC @juan-g-bonilla ):
pip install
method.Editable Installations
Installation for developers with
pip
in editable mode is a little fiddly, so I've disabled the build step when callingpip install -e .
. This maintains backwards compatibility withpython conanfile.py
as per the current developer workflow, but might be a little confusing if people try topip install -e .
expecting Basilisk to work immediately. For that reason, I added an error case that checks whether the Conanfile has already prepared the packages in the "dist3" directory.Rationale
Basically,
pip
installs in an isolated build environment by default, including the appropriate build requirements (cmake
,parse
,setuptools
,swig
, etc.). This is very convenient, but when the CMake files get generated, they point to this temporary build environment (somewhere in/tmp
). For an editable install, ideally we want developers to just callmake
indist3
folder after they make changes to Basilisk C/C++ files, so they don't have to recompile everything from scratch.For pip, there are two options:
pip install --no-clean -e .
pip
to leave the temporary build environment intact (somewhere in/tmp
), so that all the CMake files which point to it will still work. I personally use this option, because I develop in Docker containers that don't get restarted, so I don't lose any temporary files.pip
is installing them automatically./tmp
, so it may get deleted at any time (e.g. when the system restarts?).pip install --no-build-isolation -e .
pip
to not create a temporary build environment at all. Instead, it basically works as a "raw" installation, where it will use any system-installed tools (includingsetuptools
,cmake
,swig
,parse
, etc). I don't like this option as much because developers have to manually manage their build tools, but it's more convenient for people who know what they're doing and have an environment that might delete their temporary files.pip
will not check them and there are no standard tools to extract them frompyproject.toml
.Future work
cibuildwheel
pip install Basilisk
cibuildwheel
whenever they want to release a new version.make
their modifications, if they add a new message file, it won't show up in the CMake build system until they run Conan again (i.e. bypip install
again). So, these scripts should be run and managed by the CMake build system instead.meson-python
backend instead, the same as numpy/scipy do.See also #614 for further context.