Git Product home page Git Product logo

robotpy-build's Introduction

robotpy-build

This is a build tool intended to be generally useful for any python project that has binary dependencies. It is especially designed to meet the needs of RobotPy's various wrapper libraries, chiefly around:

  • Managing upstream binary dependencies
  • Autogenerating pybind11 wrappers around those dependencies
  • Building wheels from those generated wrappers

Requires Python 3.8+

Documentation

Documentation can be found at https://robotpy-build.readthedocs.io/

Author

Dustin Spicuzza is the primary author of robotpy-build, but it is the culmination of many years of experimentation with automated wrapper generation by members of the RobotPy community.

robotpy-build is available under the BSD 3-clause license.

robotpy-build's People

Contributors

agelsomini avatar archduketim avatar auscompgeek avatar crispybacon1999 avatar jawadhalabimtb avatar prensing avatar thetriplev avatar virtuald avatar zacbir avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

robotpy-build's Issues

building with robotpy-build fails to delete lib folder on Windows

On Windows, robotpy-build deletes the lib folder then errors out:
error: [WinError 183] Cannot create a file when that file already exists: 'C:\\...\\command2\\lib' . This folder does not need to be manually deleted. If python setup.py develop is run again, it succeeds.

Theory: robotpy-build tries to delete the folder but does not release it's descriptors on the folder. When the descriptor is released (upon error / exit). the folder is deleted.

Fix potential circular dependencies

I believe the way to fix this is make each class wrapper a class, where the declarations are initialized in the constructor (called in toposort order), and then methods are called

class XWrapper {
  py::class<X> cls_X;

  XWrapper(py::module &m) : cls_X(m, "X") {}

  init_methods() {
     cls_X.def( ) ... 
  }
}

For now, I'm going to provide a manual way to override the ordering.

Functions that take enums as parameters do not accept ints

Example:

accelerometer_obj.setRange( accelerometer_obj.Range.kRange_2G )

and

accelerometer_obj.setRange( accelerometer_obj.Range(0) )

work.

But,

accelerometer_obj.setRange( 0 )

does not as it did in 2019.

Potential Solutions:

  1. Overload these functions with type int and static cast them to the enum type. This will cast any int to enum. If a user specifies a bad number, we would need to add in a check (or hope the code crashes somewhere else).

Tag linux wheels with new manylinux platform tags

The accepted PEP 600 defines new manylinux tags corresponding to glibc versions. By my understanding, WPILib's linuxx86-64 corresponds to Ubuntu 18.04, which would correspond to the platform tag manylinux_2_27_x86_64.

PEP 599 (manylinux2014) also explicitly allows the armv7l and aarch64 platforms, so we should be good to publish wheels for all WPILib Linux platforms once we have the infrastructure.

Generate python documentation without requiring compilation

We can't easily build these modules on readthedocs -- and honestly, we probably don't want to anyways. Instead, if we had an rst generator template, then readthedocs could just run that and then we'd have docs.

This seems easier than trying to get sphinx to read from pyi files -- and the pyi files would have references to other non-installed modules (which aren't really required to create documentation), so the imports would fail.

Maybe @auscompgeek has a better idea?

Autogen/warnings check for pointers

Some require keepalive, some don't.

The autogen/warnings stuff should be as follows?

  • If a keepalive section is present or empty, no warning
  • Not present, issue missing warning
  • On autogen, print out keepalive for each pointer parameter.. but comment it out?

Add mechanism to inject new methods directly

Instead of using the inline_cpp block.

In particular, this would be useful for __repr__ methods. Not sure how this would work out..

extra_methods:
  __repr__:
    cpp_code: |
       [](Type * self) { return "<Type>"; }

create-gen: Ignore functions with void* param

We can't automatically generate appropriate bindings for functions that take a void pointer, so at the very least the create-gen tool should ignore them, similarly to how it already generates an ignore: true for functions that take initializer_list.

Switch back to schematics from pydantic

The whole point of using something like schematics is not just massaging data types (which is useful), but it also validates the data and tells the user that they messed up.

pydantic might get this in the future (pydantic/pydantic#1098) but until it does we just end up with erroneous data which you'll never figure out why it's an error.

Check for module export function as part of build process

In

PYBIND11_MODULE(module, m) {
}

the first argument needs to match the extension name.

Another alternative to this is to make it a #define created automatically, then robotpy-build can manage that for you. Maybe RPYBUILD_PYBIND11_MODULE(m)?

Generate .pyi files for all generated modules

This will improve our user experience significantly.

Much of the work for extracting appropriate annotations has actually already been done in the pybind11 for robotpy-rev (which these hooks/templates were derived from). I had removed them because I mistakenly assumed we would only need them for generating sim backends.

Don't write files whose contents haven't changed

Let distutils try to save us some time?

It's tricky because we try to delete all the generated files, so we'd need to keep track of this, and track hashes, etc... but it would probably result in a more pleasant development experience assuming distutils does the right thing and doesn't rebuild things that aren't modified.

ccache instructions for macos

export CC="ccache gcc"

is recommended in the docs.

This fails to build the .so file on macos.

export CC="ccache clang"
export CXX="ccache clang++"

works. I suppose gcc and g++ instead of clang would work but I haven't tried it.

OSX issues linking to libraries

Loading libraries dynamically via ctypes.LoadLibrary doesn't resolve dependencies, even if you load the dependent libraries first. Seems to be an OSX specific thing, and other python libraries have ran into this (tensorflow)

Indeed, even the default pybind11 library that was generated by robotpy-build isn't able to find the library that it linked to. I suspect this could be addressed by changing the import path.

One potential solution is to install libraries to ~/lib: tensorflow/tensorflow#6729 (comment) ... this is doable with a post-install step but we would want to properly version the library file if we took that approach.

Other potential solutions include changing the libraries via install_name_tool.

Support ARM platforms that aren't roborio

Environment markers figure into this.

Environment markers are described in several places, including PEP 508. We'd need to figure out an appropriate marker that would differentiate the roborio platform, allow linux, but also work when downloading via pip. I think it might be doable by specifying Linux + CPU type, but maybe we can make it simpler?

RoboRIO:

Python 3.8.1 (default, Dec 30 2019, 05:47:38) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os,sys,platform
>>> os.name
'posix'
>>> sys.platform
'linux'
>>> platform.machine()
'armv7l'
>>> platform.python_implementation()
'CPython'
>>> platform.release()
'4.14.87-rt49-cg-7.0.0f0-xilinx-zynq-189'
>>> platform.system()
'Linux'
>>> platform.version()
'#1 SMP PREEMPT RT Fri Mar 15 19:11:24 UTC 2019'
>>> '.'.join(platform.python_version_tuple()[:2])
'3.8'
>>> platform.python_version()
'3.8.1'
>>> sys.implementation.name
'cpython'
>>> sys.implementation.version
sys.version_info(major=3, minor=8, micro=1, releaselevel='final', serial=0)

From Peter:

A pi with 32-bit raspbian (frcvision image to be precise)

Python 3.7.3 (default, Apr  3 2019, 05:39:12) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os,sys,platform
>>> os.name
'posix'
>>> sys.platform
'linux'
>>> platform.machine()
'armv7l'
>>> platform.python_implementation()
'CPython'
>>> platform.release()
'4.19.75-v7l+'
>>> platform.system()
'Linux'
>>> platform.version()
'#1270 SMP Tue Sep 24 18:51:41 BST 2019'
>>> '.'.join(platform.python_version_tuple()[:2])
'3.7'
>>> platform.python_version
<function python_version at 0xb65b16a8>
>>> platform.python_version()
'3.7.3'
>>> sys.implementation.name
'cpython'
>>> sys.implementation.version
sys.version_info(major=3, minor=7, micro=3, releaselevel='final', serial=0)

@auscompgeek had recommended the distro module in #37 ... which seems sensible, unfortunately.

Add runtime warning to deprecated things

Info about what is deprecated is in the headers. We should use that info, reusing the message if possible.

For the classes intended for subclassing in particular, we should add a __init_subclass__ to spit out that warning so that the warning points to where the class is subclassed. Other classes we'd have to add a thing before __init__.

doxygen bug in pcpp

Reference in ned14/pcpp#38

The pcpp maintainer doesn't seem to make releases very often, so we might have to either fork or implement a workaround to make the documentation work for kickoff.

Enums are not detected by IDE (Vscode)

Environment: Python 3.8.x in Vscode with the python and Intellicode extensions.

The IDE does not provide enums as suggestions to users.

Example:

wpilib.BuiltInAccelerometer.
# OR
wpilib.BuiltInAccelerometer().

At this point, methods such as setRange appear in the menu but Range does not.

Another user faced this issue in pybind/pybind11#1504.

Potential Solutions mentioned in the above issue:

  • Use py::class_ instead of py::enum_
  • Generate .pyi files

Related to #1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.