C++QED  2.100.2 (v2 Milestone 10 Development branch)
a framework for simulating open quantum dynamics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Modules Pages
CMakeLists.cmake
1 # Copyright Raimar Sandner 2012–2014. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.txt)
2 
3 #! \ingroup Main
4 #! \file
5 #! \brief Top level %CMake file for the C++QED cpypyqed component.
6 #!
7 #! The file has the following structure:
8 
9 
10 cmake_minimum_required (VERSION 2.8.9)
11 
12 project(cpypyqed)
13 
14 include(FeatureSummary)
15 
16 if(CPPQED_MONOLITHIC AND NOT ENABLE_CPYPYQED)
17  return()
18 endif()
19 
20 #! \file
21 #! <!--#########################################################-->
22 #! ### Dependencies
23 #! <!--#########################################################-->
24 #!
25 #! Find dependencies for cpypyqed, i.e. C++QED, boost-python, the python interpreter,
26 #! python libraries and numpy.
27 
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}")
31 
32 find_package(CPPQED 2.100 REQUIRED)
33 include(${CPPQED_USE})
34 if(NOT PYTHONINTERP_FOUND)
35  find_package(PythonInterp 2.6 REQUIRED)
36 endif()
37 find_package(PythonLibs 2.6 REQUIRED)
38 find_package(Boost QUIET REQUIRED COMPONENTS python)
39 find_package(Numpy REQUIRED)
40 
41 include(PythonSetup)
42 CPPQED_SETUP()
43 include_directories(${CPPQED_INCLUDE_DIRS})
44 
45 include_directories(${CPPQED_INCLUDE_DIRS})
46 include_directories(SYSTEM ${NUMPY_INCLUDE_DIRS})
47 include_directories(SYSTEM ${PYTHON_INCLUDE_DIRS})
48 
49 SET(MANDATORY_LIBRARIES ${CPPQED_LIBRARIES} ${Boost_PYTHON_LIBRARY})
50 
51 #! \file
52 #! <!--#########################################################-->
53 #! ### Configuration
54 #! <!--#########################################################-->
55 #!
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
59 #! simultaneously.
60 #!
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.
63 
64 #! \name Project options
65 #! @{
66 
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.")
70 #! @}
71 set_property(CACHE PYTHON_MAX_RANK PROPERTY STRINGS 2 4 6 8 10)
72 
73 set(CPYPYQED_INSTALL_PATH ${PYTHON_MODULES_PATH}/cpypyqed)
74 
75 #! \file
76 #! <!--#########################################################-->
77 #! ### Helper macros
78 #! <!--#########################################################-->
79 #!
80 #! The helper macros python_cppmodule() and python_submodule().
81 
82 #! \ingroup Helpers
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.
85 #!
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
90  PREFIX ""
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})
94  IF(PYDEXTENSION)
95  SET_TARGET_PROPERTIES(${modulename} PROPERTIES SUFFIX ".pyd")
96  ELSEIF(SOEXTENSION)
97  SET_TARGET_PROPERTIES(${modulename} PROPERTIES SUFFIX ".so")
98  ENDIF(PYDEXTENSION)
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}
103  )
104 endmacro()
105 
106 #! \ingroup Helpers
107 #! \brief Macro used for Python submodule creation.
108 #! \param modulename The name of the Python module (without extension)
109 #!
110 #! This macro is meant to be called from a `CMakeLists.txt` file residing in sub-directories of
111 #! the top-level cpypyqed directory.
112 #!
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).
116 #!
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
122 #! this macro.
123 #!
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)
128 
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})
133  endforeach(s)
134  if(EXPORT_HELPERS)
135  list(SORT EXPORT_HELPERS)
136  endif(EXPORT_HELPERS)
137  foreach(s ${EXPORT_HELPERS})
138  set(EXPORT_HELPER_SEQUENCE ${EXPORT_HELPER_SEQUENCE}\(${s}\))
139  endforeach(s)
140 
141  configure_file(${PROJECT_SOURCE_DIR}/helpers/exportfunctions.h.in exportfunctions.h @ONLY)
142  include_directories(${CMAKE_CURRENT_BINARY_DIR})
143 
144  configure_file(${PROJECT_SOURCE_DIR}/helpers/build_module.cc.in build${modulename}.cc @ONLY)
145 
146  add_library(${modulename} SHARED build${modulename}.cc ${PY_SOURCE_FILES} ${ARGN})
147  add_dependencies(${modulename} cpypyqed_setup)
148  python_cppmodule(${modulename})
149 
150 endmacro()
151 
152 #! \file
153 #! <!--#########################################################-->
154 #! ### Compilation
155 #! <!--#########################################################-->
156 #!
157 #! Add the sub-directories io, core and elements, which basically only call python_submodule().
158 
159 include_directories(include)
160 include_directories(${PROJECT_BINARY_DIR})
161 
162 add_custom_target(cpypyqed_setup)
163 
164 add_subdirectory(io)
165 add_subdirectory(core)
166 add_subdirectory(elements)
167 
168 add_custom_target(cpypyqed ALL)
169 add_dependencies(cpypyqed io core elements)
170 
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
179  )
180 
181 #! \file
182 #! <!--#########################################################-->
183 #! ### Prepare Python package
184 #! <!--#########################################################-->
185 #!
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.
190 #!
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.
198 #!
199 #! This section also takes care to install the additional package files to the system.
200 
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")
206 
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
216  )
217  get_filename_component(DIR ${file} PATH)
218  install(FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}/${file}
219  DESTINATION ${CPYPYQED_INSTALL_PATH}/${DIR}
220  )
221 endforeach()
222 
223 #! \file
224 #! <!--#########################################################-->
225 #! ### Documentation
226 #! <!--#########################################################-->
227 #!
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
233 #! code.
234 #!
235 #! The relative path to the Doxygen tagfile `core.tag` is established, in order
236 #! to link to the C++QED API with Doxylink.
237 #!
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.
241 #!
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
246 #! cmake script.
247 #!
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.
251 
252 find_package(Doxygen 1.8)
253 find_package(Sphinx)
254 find_package(Doxylink)
255 
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)
264  endif()
265  foreach(AUXFILE index.rst userguide.rst tools.rst)
266  configure_file(${PROJECT_SOURCE_DIR}/doc/${AUXFILE} ${${PROJECT_NAME}_DOC_DIR} COPYONLY)
267  endforeach()
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
279  )
280  add_custom_target(${PROJECT_NAME}_doc
281  ${SPHINX_EXECUTABLE}
282  -q -b html
283  -c "${${PROJECT_NAME}_DOC_DIR}"
284  -d "${SPHINX_CACHE_DIR}"
285  "${${PROJECT_NAME}_DOC_DIR}"
286  "${SPHINX_HTML_DIR}"
287  WORKING_DIRECTORY ${${PROJECT_NAME}_DOC_DIR}
288  COMMENT "Building HTML documentation with Sphinx"
289  DEPENDS ${${PROJECT_NAME}_DOC_DIR}/reference.rst
290  )
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}
296  OPTIONAL
297  )
298  endif()
299 endif()
300 
301 #! \file
302 #! <!--#########################################################-->
303 #! ### Feature summary
304 #! <!--#########################################################-->
305 #!
306 #! Generate a summary of the cpypyqed dependencies.
307 
308 set_package_properties(Boost PROPERTIES URL "http://www.boost.org/"
309  DESCRIPTION "Collection of portable C++ source libraries."
310  TYPE REQUIRED
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."
314  TYPE OPTIONAL
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"
318  TYPE OPTIONAL
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."
322  TYPE OPTIONAL
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"
326  TYPE OPTIONAL
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.")
331 
332 if(NOT CPPQED_MONOLITHIC)
333  feature_summary( WHAT ALL )
334 endif()