SIGN IN SIGN UP
google / or-tools UNCLAIMED

Google's Operations Research tools:

0 0 17 C++
2022-03-24 17:19:17 +01:00
Linux | macOS | Windows
------------------------------------------------ | ------------------------------------------------ | -------
[![Status][linux_python_svg]][linux_python_link] | [![Status][macos_python_svg]][macos_python_link] | [![Status][windows_python_svg]][windows_python_link]
2020-03-04 17:42:26 +01:00
[linux_python_svg]: https://github.com/google/or-tools/actions/workflows/cmake_linux_python.yml/badge.svg?branch=main
2021-10-27 17:42:45 +02:00
[linux_python_link]: https://github.com/google/or-tools/actions/workflows/cmake_linux_python.yml
[macos_python_svg]: https://github.com/google/or-tools/actions/workflows/cmake_macos_python.yml/badge.svg?branch=main
2021-10-27 17:42:45 +02:00
[macos_python_link]: https://github.com/google/or-tools/actions/workflows/cmake_macos_python.yml
[windows_python_svg]: https://github.com/google/or-tools/actions/workflows/cmake_windows_python.yml/badge.svg?branch=main
2021-10-27 17:42:45 +02:00
[windows_python_link]: https://github.com/google/or-tools/actions/workflows/cmake_windows_python.yml
2020-03-04 17:42:26 +01:00
2022-03-24 17:19:17 +01:00
# Introduction
2020-03-04 17:42:26 +01:00
2022-03-24 17:19:17 +01:00
To be compliant with
[PEP513](https://www.python.org/dev/peps/pep-0513/#the-manylinux1-policy) a
python package should embbed all its C++ shared libraries.
Creating a Python native package containing all `.py` and `.so` (with good
rpath/loaderpath) is not so easy...
## Build the Binary Package
2020-03-04 17:42:26 +01:00
To build the Python wheel package, simply run:
2022-03-24 17:19:17 +01:00
2020-03-04 17:42:26 +01:00
```sh
cmake -S. -Bbuild -DBUILD_PYTHON=ON
cmake --build build --target python_package -v
```
2022-03-24 17:19:17 +01:00
note: Since `python_package` is in target `all`, you can also omit the
2020-03-04 17:42:26 +01:00
`--target` option.
2022-03-24 17:19:17 +01:00
## Testing
2020-09-19 17:21:22 +02:00
To list tests:
2022-03-24 17:19:17 +01:00
2020-09-19 17:21:22 +02:00
```sh
cd build
ctest -N
```
To only run Python tests:
2022-03-24 17:19:17 +01:00
2020-09-19 17:21:22 +02:00
```sh
cd build
ctest -R "python_.*"
```
2022-03-24 17:19:17 +01:00
## Technical Notes
First you should take a look at the
[ortools/python/README.md](../../ortools/python/README.md) to understand the
layout. \
2020-10-08 12:15:58 +02:00
Here I will only focus on the CMake/SWIG tips and tricks.
2022-03-24 17:19:17 +01:00
### Build directory layout
2020-03-04 17:42:26 +01:00
Since Python use the directory name where `__init__.py` file is located and we
2022-03-24 17:19:17 +01:00
want to use the
[CMAKE_BINARY_DIR](https://cmake.org/cmake/help/latest/variable/CMAKE_BINARY_DIR.html)
to generate the Python binary package.
2020-03-04 17:42:26 +01:00
We want this layout:
2022-03-24 17:19:17 +01:00
2020-03-04 17:42:26 +01:00
```shell
<CMAKE_BINARY_DIR>/python
├── setup.py
└── ortools
├── __init__.py
├── algorithms
2022-03-24 17:19:17 +01:00
│ ├── __init__.py
│ ├── _pywrap.so
│ └── pywrap.py
2020-03-04 17:42:26 +01:00
├── graph
2022-03-24 17:19:17 +01:00
│ ├── __init__.py
│ ├── pywrapgraph.py
│ └── _pywrapgraph.so
├── ...
2020-03-04 17:42:26 +01:00
└── .libs
├── libXXX.so.1.0
└── libXXX.so.1.0
```
2022-03-24 17:19:17 +01:00
2020-03-04 17:42:26 +01:00
src: `tree build --prune -U -P "*.py|*.so*" -I "build"`
2022-03-24 17:19:17 +01:00
note: On UNIX you always need `$ORIGIN/../../${PROJECT_NAME}/.libs` since
`_pywrapXXX.so` will depend on `libortools.so`. \
note: On APPLE you always need
`"@loader_path;@loader_path/../../${PROJECT_NAME}/.libs` since `_pywrapXXX.so`
will depend on `libortools.dylib`. \
note: on Windows since we are using static libraries we won't have the `.libs`
directory...
So we also need to create few `__init__.py` files to be able to use the build
directory to generate the Python package.
2020-03-04 17:42:26 +01:00
2022-03-24 17:19:17 +01:00
### Why on APPLE lib must be .so
2020-03-04 17:42:26 +01:00
Actually, the cpython code responsible for loading native libraries expect `.so`
on all UNIX platforms.
```c
const char *_PyImport_DynLoadFiletab[] = {
#ifdef __CYGWIN__
".dll",
#else /* !__CYGWIN__ */
"." SOABI ".so",
#ifdef ALT_SOABI
"." ALT_SOABI ".so",
#endif
".abi" PYTHON_ABI_STRING ".so",
".so",
#endif /* __CYGWIN__ */
NULL,
};
```
2022-03-24 17:19:17 +01:00
ref:
2022-05-16 11:59:15 +02:00
https://github.com/python/cpython/blob/main/Python/dynload_shlib.c#L37-L49
2020-03-04 17:42:26 +01:00
i.e. `pywrapXXX` -> `_pywrapXXX.so` -> `libortools.dylib`
2022-03-24 17:19:17 +01:00
### Why setup.py has to be generated
To avoid to put hardcoded path to SWIG `.so/.dylib` generated files, we could
use `$<TARGET_FILE_NAME:tgt>` to retrieve the file (and also deal with
Mac/Windows suffix, and target dependencies). \
2020-03-04 17:42:26 +01:00
In order for `setup.py` to use
[cmake generator expression](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#informational-expressions)
2022-03-24 17:19:17 +01:00
(e.g. `$<TARGET_FILE_NAME:_pyFoo>`). We need to generate it at build time (e.g.
using
[add_custom_command()](https://cmake.org/cmake/help/latest/command/add_custom_command.html)).
note: This will also add automatically a dependency between the command and the
TARGET !
2020-03-04 17:42:26 +01:00
2022-03-24 17:19:17 +01:00
todo(mizux): try to use
[`file(GENERATE ...)`](https://cmake.org/cmake/help/latest/command/file.html#generate)
instead.