Skip to content
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 building a pip package using scikit-build #559

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ option (NLOPT_OCTAVE "build octave bindings" ON)
option (NLOPT_MATLAB "build matlab bindings" ON)
option (NLOPT_GUILE "build guile bindings" ON)
option (NLOPT_SWIG "use SWIG to build bindings" ON)
option (NLOPT_PYTHON_SCIKIT_BUILD "generate a project folder for scikit-build" OFF)

if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
option (NLOPT_TESTS "build unit tests" ON)
Expand Down
20 changes: 20 additions & 0 deletions doc/docs/NLopt_Installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,26 @@ To specify a particular version or location of Python, use the `Python_EXECUTABL
cmake -DPython_EXECUTABLE=/usr/bin/python ..
```

### Creating pip package

To create a pip compatible package using wheels, you have to install [scikit-build](https://scikit-build.readthedocs.io/en/latest) and then configure cmake to generate a python project.

```sh
cmake -DNLOPT_PYTHON_SCIKIT_BUILD=ON -DBUILD_SHARED_LIBS=NO ..
```

Then to install the python package:

```sh
pip install src/swig/python
```

or to create a wheel:
```sh
pip wheel src/swig/python
```


GNU Guile plugins
-----------------

Expand Down
35 changes: 34 additions & 1 deletion src/swig/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,40 @@ endif ()
include_directories (${NLOPT_PRIVATE_INCLUDE_DIRS})
set_source_files_properties (nlopt.i PROPERTIES CPLUSPLUS ON)

if (NUMPY_FOUND AND Python_FOUND)
if (NLOPT_PYTHON_SCIKIT_BUILD)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/python/CMakeLists.txt.in
${CMAKE_CURRENT_BINARY_DIR}/python/CMakeLists.txt
@ONLY
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/nlopt.i
${CMAKE_CURRENT_BINARY_DIR}/python/nlopt.i
Copy link
Owner

Choose a reason for hiding this comment

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

Is there a good reason why these have to be copied? Why can't they be used directly from the source dir?

COPYONLY
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/nlopt-python.i
${CMAKE_CURRENT_BINARY_DIR}/python/nlopt-python.i
COPYONLY
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/numpy.i
${CMAKE_CURRENT_BINARY_DIR}/python/numpy.i
COPYONLY
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/nlopt-exceptions.i
${CMAKE_CURRENT_BINARY_DIR}/python/nlopt-exceptions.i
COPYONLY
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/python/setup.py.in
${CMAKE_CURRENT_BINARY_DIR}/python/setup.py
@ONLY
)
endif()

if (NUMPY_FOUND AND Python_FOUND AND NOT NLOPT_PYTHON_SCIKIT_BUILD)

set (SWIG_MODULE_nlopt_python_EXTRA_DEPS nlopt-python.i numpy.i generate-cpp)

Expand Down
25 changes: 25 additions & 0 deletions src/swig/python/CMakeLists.txt.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.18...3.22)

project(_nlopt)

find_package(PythonExtensions REQUIRED)
find_package (NumPy REQUIRED)
find_package (SWIG 3)
include (UseSWIG)

# Find NLopt C++ package
set (NLopt_ROOT @CMAKE_CURRENT_BINARY_DIR@/../../)
find_package (NLopt CONFIG REQUIRED)

set (SWIG_MODULE__nlopt_EXTRA_DEPS nlopt-python.i numpy.i)
Copy link
Owner

Choose a reason for hiding this comment

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

Couldn't this depend on ../nlopt-python.i etcetera if the paths are set correctly?

Copy link
Author

Choose a reason for hiding this comment

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

I spent quite some time trying to set up paths correctly, but couldn't figure out how to do it.

set_source_files_properties (nlopt.i PROPERTIES CPLUSPLUS ON)
swig_add_library (_nlopt LANGUAGE python SOURCES nlopt.i)
set_property(TARGET _nlopt PROPERTY SWIG_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:NLopt::nlopt,INTERFACE_INCLUDE_DIRECTORIES>)
target_include_directories(_nlopt PRIVATE ${NumPy_INCLUDE_DIRS})
target_link_libraries(_nlopt NLopt::nlopt)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/__init__.py "from .nlopt import *")

python_extension_module(_nlopt)
install(TARGETS _nlopt LIBRARY DESTINATION nlopt)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/nlopt.py DESTINATION nlopt)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/__init__.py DESTINATION nlopt)
8 changes: 8 additions & 0 deletions src/swig/python/setup.py.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from skbuild import setup

setup(
name = 'nlopt',
version = '@NLOPT_MAJOR_VERSION@.@NLOPT_MINOR_VERSION@.@NLOPT_BUGFIX_VERSION@',
packages = ['nlopt'],
zip_safe = False
)