1 # Copyright Raimar Sandner 2012–2014. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.txt)
5 #! \brief Top level %CMake file for the C++QED cpypyqed component.
7 #! The file has the following structure:
10 cmake_minimum_required (VERSION 2.8.9)
14 include(FeatureSummary)
16 if(CPPQED_MONOLITHIC AND NOT ENABLE_CPYPYQED)
21 #! <!--#########################################################-->
23 #! <!--#########################################################-->
25 #! Find dependencies for cpypyqed, i.e. C++QED, boost-python, the python interpreter,
26 #! python libraries and numpy.
28 get_filename_component(CPPQED_CMAKE_MODULE_PATH "cmake/Modules" ABSOLUTE)
29 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CPPQED_CMAKE_MODULE_PATH})
30 message(STATUS "Debug: ${PYTHON_EXECUTABLE}")
32 find_package(CPPQED 2.100 REQUIRED)
33 include(${CPPQED_USE})
34 if(NOT PYTHONINTERP_FOUND)
35 find_package(PythonInterp 2.6 REQUIRED)
37 find_package(PythonLibs 2.6 REQUIRED)
38 find_package(Boost QUIET REQUIRED COMPONENTS python)
39 find_package(Numpy REQUIRED)
43 include_directories(${CPPQED_INCLUDE_DIRS})
45 include_directories(${CPPQED_INCLUDE_DIRS})
46 include_directories(SYSTEM ${NUMPY_INCLUDE_DIRS})
47 include_directories(SYSTEM ${PYTHON_INCLUDE_DIRS})
49 SET(MANDATORY_LIBRARIES ${CPPQED_LIBRARIES} ${Boost_PYTHON_LIBRARY})
52 #! <!--#########################################################-->
54 #! <!--#########################################################-->
56 #! Set \ref CMake::PYTHON_MAX_RANK "PYTHON_MAX_RANK" and the install paths where the module should end up.
57 #! Note that in debug build mode a `_d` suffix will be appended to the
58 #! module name. This way debug and release modules can be installed
61 #! The \ref CMake::PYTHON_MAX_RANK "PYTHON_MAX_RANK" variable ends up in a generated `cpypyqed_config.h`
62 #! header file and can be included where needed.
64 #! \name Project options
67 #! \brief The maximum rank up to which some class templates with RANK parameter should be
68 #! pre-initialized (must be even).
69 set(PYTHON_MAX_RANK 8 CACHE STRING "Pre-instantiate template classes up to this rank in Python bindings.")
71 set_property(CACHE PYTHON_MAX_RANK PROPERTY STRINGS 2 4 6 8 10)
73 set(CPYPYQED_INSTALL_PATH ${PYTHON_MODULES_PATH}/cpypyqed)
76 #! <!--#########################################################-->
78 #! <!--#########################################################-->
80 #! The helper macros python_cppmodule() and python_submodule().
83 #! \brief This macro selects the correct extension for Python modules according to the OS.
84 #! \param modulename The name of the Python module target.
86 #! It also links the module to whatever is currently set in the variable `MANDATORY_LIBRARIES`
87 #! and the Python libraries, and installs the module.
88 macro(python_cppmodule modulename)
89 SET_TARGET_PROPERTIES(${modulename} PROPERTIES
91 LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${PROJECT_NAME}
92 LIBRARY_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}
93 LIBRARY_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/${PROJECT_NAME})
95 SET_TARGET_PROPERTIES(${modulename} PROPERTIES SUFFIX ".pyd")
97 SET_TARGET_PROPERTIES(${modulename} PROPERTIES SUFFIX ".so")
99 TARGET_LINK_LIBRARIES(${modulename} ${MANDATORY_LIBRARIES} ${PYTHON_LIBRARIES})
100 INSTALL(TARGETS ${modulename}
101 RUNTIME DESTINATION ${CPYPYQED_INSTALL_PATH}
102 LIBRARY DESTINATION ${CPYPYQED_INSTALL_PATH}
107 #! \brief Macro used for Python submodule creation.
108 #! \param modulename The name of the Python module (without extension)
110 #! This macro is meant to be called from a `CMakeLists.txt` file residing in sub-directories of
111 #! the top-level cpypyqed directory.
113 #! This macro will take all source files in the current directory and search for functions
114 #! matching `export_.*`. The names of these functions are written into a boost preprocessor
115 #! sequence and saved in the variable `EXPORT_HELPER_SEQUENCE` (sorted alphabetically).
117 #! From the template file `helpers/build_module.cc.in`, a source file is generated, in which this
118 #! preprocessor sequence is used to declare and call all the export functions. A target is created
119 #! building the generated `build${modulename}.cc` together with all source files in the current
120 #! directory, and linking to the Python and boost libraries. Additional libraries needed
121 #! (e.g. elements libraries) have to be added to the variable `MANDATORY_LIBRARIES` before calling
124 #! Finally python_cppmodule() is called for correct linkage and installation.
125 macro(python_submodule modulename)
126 set(modulename ${modulename})
127 aux_source_directory(. PY_SOURCE_FILES)
129 foreach(s ${PY_SOURCE_FILES})
130 file( STRINGS ${s} EXPORT_HELPER_LINE REGEX "[ ]*void[ ]+export_" )
131 string(REGEX REPLACE ".*(export_.*)\\(.*" "\\1" EXPORT_HELPER "${EXPORT_HELPER_LINE}" )
132 set(EXPORT_HELPERS ${EXPORT_HELPERS} ${EXPORT_HELPER})
135 list(SORT EXPORT_HELPERS)
136 endif(EXPORT_HELPERS)
137 foreach(s ${EXPORT_HELPERS})
138 set(EXPORT_HELPER_SEQUENCE ${EXPORT_HELPER_SEQUENCE}\(${s}\))
141 configure_file(${PROJECT_SOURCE_DIR}/helpers/exportfunctions.h.in exportfunctions.h @ONLY)
142 include_directories(${CMAKE_CURRENT_BINARY_DIR})
144 configure_file(${PROJECT_SOURCE_DIR}/helpers/build_module.cc.in build${modulename}.cc @ONLY)
146 add_library(${modulename} SHARED build${modulename}.cc ${PY_SOURCE_FILES} ${ARGN})
147 add_dependencies(${modulename} cpypyqed_setup)
148 python_cppmodule(${modulename})
153 #! <!--#########################################################-->
155 #! <!--#########################################################-->
157 #! Add the sub-directories io, core and elements, which basically only call python_submodule().
159 include_directories(include)
160 include_directories(${PROJECT_BINARY_DIR})
162 add_custom_target(cpypyqed_setup)
165 add_subdirectory(core)
166 add_subdirectory(elements)
168 add_custom_target(cpypyqed ALL)
169 add_dependencies(cpypyqed io core elements)
171 add_custom_command(TARGET cpypyqed_setup PRE_BUILD
172 COMMAND ${CMAKE_COMMAND}
173 -DINPUT=${PROJECT_SOURCE_DIR}/helpers/config.h.in
174 -DOUTPUT=cpypyqed_config.h
175 -DDEBUG_SUFFIX="$<$<CONFIG:Debug>:_d>"
176 -DPACKAGE_NAME="cpypyqed$<$<CONFIG:Debug>:.debug>"
177 -DPYTHON_MAX_RANK=${PYTHON_MAX_RANK}
178 -P ${CMAKE_CURRENT_SOURCE_DIR}/generate.cmake
182 #! <!--#########################################################-->
183 #! ### Prepare Python package
184 #! <!--#########################################################-->
186 #! Copy all the files which are needed for the final Python package
187 #! to the build directory. The package name is `cpypyqed`. Because it is possible that the
188 #! build configuration is only available at build time (e.g. Mac OS X, XCode),
189 #! not at configure time, we cannot use `configure_file` directly.
191 #! Instead we use a little trick: The call to `configure_file` is wrapped in a
192 #! trivial %CMake script `generate.cmake`, which is called at build time.
193 #! For this, `add_custom_command` is used to set up a pre-dependency for the
194 #! `cpypyqed` target. All variables which should be available for substitution
195 #! have to be passed in by `add_custom_command` with `-D` defines. In the custom
196 #! command we can make use of the %CMake generator expression, e.g. `$<$<CONFIG:Debug>:_d>`,
197 #! which expands to `_d` in Debug mode and does nothing in Release mode.
199 #! This section also takes care to install the additional package files to the system.
201 set(INPUTS "__init__.py" "config.py" "compilation/ActTemplate.cc"
202 "compilation/CompositeTemplate.cc" "compilation/composite.py" "compilation/ondemand.py"
203 "compilation/__init__.py" "compilation/CMakeListsTemplate.txt" "debug/__init__.py" "tools/__init__.py"
204 "tools/quantumstate.py" "tools/expvalues.py" "tools/utils.py" "tools/initialconditions.py"
205 "tools/test_statevector.py" "tools/passthrough.py")
207 foreach(file ${INPUTS})
208 add_custom_command(TARGET cpypyqed PRE_BUILD
209 COMMAND ${CMAKE_COMMAND}
210 -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/${file}
211 -DOUTPUT=${PROJECT_NAME}/${file}
212 -DDEBUG_SUFFIX="$<$<CONFIG:Debug>:_d>"
213 -DCONF=$<CONFIGURATION>
214 -DCPPQED_CORE_GIT=${CPPQED_CORE_GIT}
215 -P ${CMAKE_CURRENT_SOURCE_DIR}/generate.cmake
217 get_filename_component(DIR ${file} PATH)
218 install(FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}/${file}
219 DESTINATION ${CPYPYQED_INSTALL_PATH}/${DIR}
224 #! <!--#########################################################-->
226 #! <!--#########################################################-->
228 #! Find Doxygen, Sphinx and Doxylink. If all these components are found,
229 #! build the documentation. Sphinx has the advantage that it actually loads
230 #! the modules with a python interpreter and looks at the docstrings.
231 #! Otherwise it would be very cumbersome to document a boost python module,
232 #! because all the signatures would have to be duplicated in the documentation
235 #! The relative path to the Doxygen tagfile `core.tag` is established, in order
236 #! to link to the C++QED API with Doxylink.
238 #! In monolithic mode, the file `doc`layout.html.in` is copied over to the
239 #! documentation build directory. This files contains links to the other C++QED
240 #! components and makes them appear on the Sphinx pages.
242 #! The sphinx source file `reference.rst` depends on the Python package name,
243 #! therefore we again have to generate this file at build time, when the
244 #! build configuration is known in any case. The solution is again, as in the
245 #! previous section, to let a custom command generate the file with a simple
248 #! Finally, the call to the sphinx binary is added as a custom command, the
249 #! target is named `cpypyqed_doc`. In monolithic mode, the resulting html
250 #! directory is installed to the system.
252 find_package(Doxygen 1.8)
254 find_package(Doxylink)
256 if(CPPQED_MONOLITHIC AND DOXYGEN_FOUND AND DOXYGEN_DOT_FOUND AND SPHINX_FOUND AND DOXYLINK_FOUND)
257 set(CPPQED_DOC_DIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/cppqed-doc-${CPPQED_ID}")
258 file(MAKE_DIRECTORY ${${PROJECT_NAME}_DOC_DIR})
259 file(RELATIVE_PATH core_RELATIVE_DOXYGEN_TAG ${${PROJECT_NAME}_DOC_DIR} ${core_DOXYGEN_TAG})
260 get_filename_component(core_RELATIVE_DOXYGEN_DIR ${core_RELATIVE_DOXYGEN_TAG} PATH)
261 configure_file(${PROJECT_SOURCE_DIR}/doc/conf.py.in ${${PROJECT_NAME}_DOC_DIR}/conf.py @ONLY)
262 if(CPPQED_MONOLITHIC)
263 configure_file(${PROJECT_SOURCE_DIR}/doc/layout.html.in ${${PROJECT_NAME}_DOC_DIR}/_templates/layout.html @ONLY)
265 foreach(AUXFILE index.rst userguide.rst tools.rst)
266 configure_file(${PROJECT_SOURCE_DIR}/doc/${AUXFILE} ${${PROJECT_NAME}_DOC_DIR} COPYONLY)
268 # Sphinx cache with pickled ReST documents
269 set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees")
270 # HTML output directory
271 set(SPHINX_HTML_DIR "${${PROJECT_NAME}_DOC_DIR}/html")
272 add_custom_command(OUTPUT ${${PROJECT_NAME}_DOC_DIR}/reference.rst
273 COMMAND ${CMAKE_COMMAND}
274 -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/doc/reference.rst.in
275 -DOUTPUT=${${PROJECT_NAME}_DOC_DIR}/reference.rst
276 -DDEBUG_SUFFIX="$<$<CONFIG:Debug>:_d>"
277 -P ${CMAKE_CURRENT_SOURCE_DIR}/generate.cmake
278 DEPENDS generate.cmake doc/reference.rst.in
280 add_custom_target(${PROJECT_NAME}_doc
283 -c "${${PROJECT_NAME}_DOC_DIR}"
284 -d "${SPHINX_CACHE_DIR}"
285 "${${PROJECT_NAME}_DOC_DIR}"
287 WORKING_DIRECTORY ${${PROJECT_NAME}_DOC_DIR}
288 COMMENT "Building HTML documentation with Sphinx"
289 DEPENDS ${${PROJECT_NAME}_DOC_DIR}/reference.rst
291 add_dependencies(${PROJECT_NAME}_doc cpypyqed)
292 if(CPPQED_MONOLITHIC)
293 add_dependencies(${PROJECT_NAME}_doc core_doc elements_doc)
294 install(DIRECTORY ${${PROJECT_NAME}_DOC_DIR}/html
295 DESTINATION ${CPPQED_DOC_DIR}/${PROJECT_NAME}
302 #! <!--#########################################################-->
303 #! ### Feature summary
304 #! <!--#########################################################-->
306 #! Generate a summary of the cpypyqed dependencies.
308 set_package_properties(Boost PROPERTIES URL "http://www.boost.org/"
309 DESCRIPTION "Collection of portable C++ source libraries."
311 PURPOSE "Python wrapper library for C++ libraries.")
312 set_package_properties(PythonLibs PROPERTIES URL "http://www.python.org/"
313 DESCRIPTION "General-purpose, high-level programming language."
315 PURPOSE "Access C++QED functionality through Python (work in progress, incomplete).")
316 set_package_properties(Numpy PROPERTIES URL "http://www.numpy.org/"
317 DESCRIPTION "NumPy is the fundamental package for scientific computing with Python"
319 PURPOSE "Data input/output with Python, testsuite.")
320 set_package_properties(Scipy PROPERTIES URL "http://www.scipy.org/"
321 DESCRIPTION "SciPy is a Python-based ecosystem of open-source software for mathematics, science, and engineering."
323 PURPOSE "The testsuite depends on this.")
324 set_package_properties(Sphinx PROPERTIES URL "http://sphinx-doc.org/"
325 DESCRIPTION "Sphinx is a documentation generator which converts reStructuredText files into HTML websites"
327 PURPOSE "Sphinx is needed to build the cpypyqed documentation.")
328 set_package_properties(Doxylink PROPERTIES URL "https://pypi.python.org/pypi/sphinxcontrib-doxylink"
329 DESCRIPTION "Doxylink is a Sphinx extension to link to external Doxygen API documentation."
330 PURPOSE "Needed to link to the rest of the C++QED in the cpypyqed documentation.")
332 if(NOT CPPQED_MONOLITHIC)
333 feature_summary( WHAT ALL )