@@ -107,30 +107,49 @@ if(BUILD_TESTING)
107107 endif ()
108108endif ()
109109
110- if (BUILD_TESTING)
111- # add_python_test()
112- # CMake function to generate and build python test.
113- # Parameters:
114- # the python filename
115- # e.g.:
116- # add_python_test(foo.py)
117- function (add_python_test FILE_NAME)
118- message (STATUS "Configuring test ${FILE_NAME} ..." )
119- get_filename_component (TEST_NAME ${FILE_NAME} NAME_WE )
110+ # add_python_test()
111+ # CMake function to generate and build python test.
112+ # Parameters:
113+ # FILE_NAME: the python filename
114+ # COMPONENT_NAME: name of the ortools/ subdir where the test is located
115+ # note: automatically determined if located in ortools/<component>/python/
116+ # e.g.:
117+ # add_python_test(
118+ # FILE_NAME
119+ # ${PROJECT_SOURCE_DIR}/ortools/foo/python/bar_test.py
120+ # COMPONENT_NAME
121+ # foo
122+ # )
123+ function (add_python_test)
124+ set (options "" )
125+ set (oneValueArgs FILE_NAME)
126+ set (multiValueArgs "" )
127+ cmake_parse_arguments (TEST
128+ "${options} "
129+ "${oneValueArgs} "
130+ "${multiValueArgs} "
131+ ${ARGN}
132+ )
133+ if (NOT TEST_FILE_NAME)
134+ message (FATAL_ERROR "no FILE_NAME provided" )
135+ endif ()
136+ get_filename_component (TEST_NAME ${TEST_FILE_NAME} NAME_WE )
137+
138+ message (STATUS "Configuring test ${TEST_FILE_NAME} ..." )
139+
140+ if (BUILD_TESTING)
120141 add_test (
121142 NAME python_test_${TEST_NAME}
122- COMMAND ${VENV_Python3_EXECUTABLE} -m pytest ${FILE_NAME }
143+ COMMAND ${VENV_Python3_EXECUTABLE} -m pytest ${TEST_FILE_NAME }
123144 WORKING_DIRECTORY ${VENV_DIR} )
124- message ( STATUS "Configuring test ${FILE_NAME} done" )
125- endfunction ( )
126- endif ()
145+ endif ( )
146+ message ( STATUS "Configuring test ${TEST_FILE_NAME} ...DONE" )
147+ endfunction ()
127148
128149#######################
129150## PYTHON WRAPPERS ##
130151#######################
131- list (APPEND CMAKE_SWIG_FLAGS "-I${PROJECT_SOURCE_DIR} " )
132-
133- set (PYTHON_PROJECT cmakepybind11)
152+ set (PYTHON_PROJECT ${PROJECT_NAMESPACE} )
134153message (STATUS "Python project: ${PYTHON_PROJECT} " )
135154set (PYTHON_PROJECT_DIR ${PROJECT_BINARY_DIR} /python/${PYTHON_PROJECT} )
136155message (STATUS "Python project build path: ${PYTHON_PROJECT_DIR} " )
@@ -139,11 +158,28 @@ message(STATUS "Python project build path: ${PYTHON_PROJECT_DIR}")
139158## Python Packaging ##
140159#######################
141160#file(MAKE_DIRECTORY python/${PYTHON_PROJECT})
142- file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /__init__.py CONTENT "__version__ = \" ${PROJECT_VERSION} \"\n " )
161+ configure_file (
162+ ${PROJECT_SOURCE_DIR} /python/__init__.py.in
163+ ${PROJECT_BINARY_DIR} /python/__init__.py.in
164+ @ONLY)
165+ file (GENERATE
166+ OUTPUT ${PYTHON_PROJECT_DIR} /__init__.py
167+ INPUT ${PROJECT_BINARY_DIR} /python/__init__.py.in)
143168
144169file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /foo/__init__.py CONTENT "" )
170+ file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /foo/python/__init__.py CONTENT "" )
145171file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /bar/__init__.py CONTENT "" )
172+ file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /bar/python/__init__.py CONTENT "" )
146173file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /foobar/__init__.py CONTENT "" )
174+ file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /foobar/python/__init__.py CONTENT "" )
175+
176+ # Adds py.typed to make typed packages.
177+ file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /foo/py.typed CONTENT "" )
178+ file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /foo/python/py.typed CONTENT "" )
179+ file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /bar/py.typed CONTENT "" )
180+ file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /bar/python/py.typed CONTENT "" )
181+ file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /foobar/py.typed CONTENT "" )
182+ file (GENERATE OUTPUT ${PYTHON_PROJECT_DIR} /foobar/python/py.typed CONTENT "" )
147183
148184# setup.py.in contains cmake variable e.g. @PYTHON_PROJECT@ and
149185# generator expression e.g. $<TARGET_FILE_NAME:pyFoo>
@@ -161,7 +197,76 @@ file(GENERATE
161197# COMMAND ${CMAKE_COMMAND} -E copy setup.py setup.py
162198# WORKING_DIRECTORY python)
163199
164- # Look for python modules
200+ set (is_windows "$<PLATFORM_ID:Windows>" )
201+ set (is_not_windows "$<NOT:$<PLATFORM_ID:Windows>>" )
202+
203+ set (is_foo_shared "$<STREQUAL:$<TARGET_PROPERTY:Foo,TYPE>,SHARED_LIBRARY>" )
204+ set (need_unix_foo_lib "$<AND:${is_not_windows} ,${is_foo_shared} >" )
205+ set (need_windows_foo_lib "$<AND:${is_windows} ,${is_foo_shared} >" )
206+
207+ set (is_bar_shared "$<STREQUAL:$<TARGET_PROPERTY:Bar,TYPE>,SHARED_LIBRARY>" )
208+ set (need_unix_bar_lib "$<AND:${is_not_windows} ,${is_bar_shared} >" )
209+ set (need_windows_bar_lib "$<AND:${is_windows} ,${is_bar_shared} >" )
210+
211+ set (is_foobar_shared "$<STREQUAL:$<TARGET_PROPERTY:FooBar,TYPE>,SHARED_LIBRARY>" )
212+ set (need_unix_foobar_lib "$<AND:${is_not_windows} ,${is_foobar_shared} >" )
213+ set (need_windows_foobar_lib "$<AND:${is_windows} ,${is_foobar_shared} >" )
214+
215+ add_custom_command (
216+ OUTPUT python/libs_timestamp
217+ COMMAND ${CMAKE_COMMAND} -E remove -f libs_timestamp
218+ COMMAND ${CMAKE_COMMAND} -E make_directory ${PYTHON_PROJECT} /.libs
219+
220+ COMMAND ${CMAKE_COMMAND} -E
221+ $<IF:${is_foo_shared} ,copy,true >
222+ $<${need_unix_foo_lib} :$<TARGET_SONAME_FILE:Foo>>
223+ $<${need_windows_foo_lib} :$<TARGET_FILE:Foo>>
224+ ${PYTHON_PROJECT} /.libs
225+
226+ COMMAND ${CMAKE_COMMAND} -E
227+ $<IF:${is_bar_shared} ,copy,true >
228+ $<${need_unix_bar_lib} :$<TARGET_SONAME_FILE:Bar>>
229+ $<${need_windows_bar_lib} :$<TARGET_FILE:Bar>>
230+ ${PYTHON_PROJECT} /.libs
231+
232+ COMMAND ${CMAKE_COMMAND} -E
233+ $<IF:${is_foobar_shared} ,copy,true >
234+ $<${need_unix_foobar_lib} :$<TARGET_SONAME_FILE:FooBar>>
235+ $<${need_windows_foobar_lib} :$<TARGET_FILE:FooBar>>
236+ ${PYTHON_PROJECT} /.libs
237+
238+ COMMAND ${CMAKE_COMMAND} -E touch ${PROJECT_BINARY_DIR} /python/libs_timestamp
239+ MAIN_DEPENDENCY
240+ python/setup.py.in
241+ DEPENDS
242+ python/setup.py
243+ ${PROJECT_NAMESPACE} ::Foo
244+ ${PROJECT_NAMESPACE} ::Bar
245+ ${PROJECT_NAMESPACE} ::FooBar
246+ WORKING_DIRECTORY python
247+ COMMAND_EXPAND_LISTS )
248+
249+ add_custom_command (
250+ OUTPUT python/pybind11_timestamp
251+ COMMAND ${CMAKE_COMMAND} -E remove -f pybind11_timestamp
252+ COMMAND ${CMAKE_COMMAND} -E copy
253+ $<TARGET_FILE:pyFoo> ${PYTHON_PROJECT} /foo/python
254+ COMMAND ${CMAKE_COMMAND} -E copy
255+ $<TARGET_FILE:pyBar> ${PYTHON_PROJECT} /bar/python
256+ COMMAND ${CMAKE_COMMAND} -E copy
257+ $<TARGET_FILE:pyFooBar> ${PYTHON_PROJECT} /foobar/python
258+ COMMAND ${CMAKE_COMMAND} -E touch ${PROJECT_BINARY_DIR} /python/pybind11_timestamp
259+ MAIN_DEPENDENCY
260+ python/setup.py.in
261+ DEPENDS
262+ ${PROJECT_NAMESPACE} ::pyFoo
263+ ${PROJECT_NAMESPACE} ::pyBar
264+ ${PROJECT_NAMESPACE} ::pyFooBar
265+ WORKING_DIRECTORY python
266+ COMMAND_EXPAND_LISTS )
267+
268+
269+ # Look for required python modules
165270search_python_module(
166271 NAME setuptools
167272 PACKAGE setuptools)
@@ -172,31 +277,16 @@ search_python_module(
172277add_custom_command (
173278 OUTPUT python/dist_timestamp
174279 COMMAND ${CMAKE_COMMAND} -E remove_directory dist
175- COMMAND ${CMAKE_COMMAND} -E make_directory ${PYTHON_PROJECT} /.libs
176- # Don't need to copy static lib on Windows.
177- COMMAND ${CMAKE_COMMAND} -E $<IF:$<STREQUAL :$<TARGET_PROPERTY:Foo,TYPE >,SHARED_LIBRARY>,copy,true >
178- $<$<STREQUAL :$<TARGET_PROPERTY:Foo,TYPE >,SHARED_LIBRARY>:$<TARGET_SONAME_FILE:Foo>>
179- ${PYTHON_PROJECT} /.libs
180- COMMAND ${CMAKE_COMMAND} -E $<IF:$<STREQUAL :$<TARGET_PROPERTY:Bar,TYPE >,SHARED_LIBRARY>,copy,true >
181- $<$<STREQUAL :$<TARGET_PROPERTY:Bar,TYPE >,SHARED_LIBRARY>:$<TARGET_SONAME_FILE:Bar>>
182- ${PYTHON_PROJECT} /.libs
183- COMMAND ${CMAKE_COMMAND} -E $<IF:$<STREQUAL :$<TARGET_PROPERTY:FooBar,TYPE >,SHARED_LIBRARY>,copy,true >
184- $<$<STREQUAL :$<TARGET_PROPERTY:FooBar,TYPE >,SHARED_LIBRARY>:$<TARGET_SONAME_FILE:FooBar>>
185- ${PYTHON_PROJECT} /.libs
186- COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:pyFoo> ${PYTHON_PROJECT} /foo
187- COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:pyBar> ${PYTHON_PROJECT} /bar
188- COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:pyFooBar> ${PYTHON_PROJECT} /foobar
189280 #COMMAND ${Python3_EXECUTABLE} setup.py bdist_egg bdist_wheel
190281 COMMAND ${Python3_EXECUTABLE} setup.py bdist_wheel
191282 COMMAND ${CMAKE_COMMAND} -E touch ${PROJECT_BINARY_DIR} /python/dist_timestamp
192283 MAIN_DEPENDENCY
193284 python/setup.py.in
194285 DEPENDS
195286 python/setup.py
196- ${PROJECT_NAMESPACE} ::Foo
197- ${PROJECT_NAMESPACE} ::pyFoo
198- ${PROJECT_NAMESPACE} ::pyBar
199- ${PROJECT_NAMESPACE} ::pyFooBar
287+ python/libs_timestamp
288+ python/pybind11_timestamp
289+ $<$<BOOL :${GENERATE_PYTHON_STUB} >:python/stub_timestamp>
200290 BYPRODUCTS
201291 python/${PYTHON_PROJECT}
202292 python/${PYTHON_PROJECT} .egg-info
@@ -226,7 +316,8 @@ if(BUILD_TESTING)
226316 COMMAND ${VENV_Python3_EXECUTABLE} -m pip install
227317 --find -links=${CMAKE_CURRENT_BINARY_DIR} /python/dist ${PYTHON_PROJECT} ==${PROJECT_VERSION}
228318 # install modules only required to run examples
229- COMMAND ${VENV_Python3_EXECUTABLE} -m pip install pytest
319+ COMMAND ${VENV_Python3_EXECUTABLE} -m pip install
320+ pytest
230321 BYPRODUCTS ${VENV_DIR}
231322 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
232323 COMMENT "Create venv and install ${PYTHON_PROJECT} "
0 commit comments