# Define add_sphinx_document() and helpers. # Is a helper macro for add_sphinx_document() to add the arguments passed to # the macro to all the commands that will be passed to add_custom_target(). MACRO(sphinx_helper_add_to_commands) IF(Sphinx_FOUND) LIST(APPEND _COMMAND ${ARGV}) FOREACH(_X ${_EXTRA_COMMANDS}) LIST(APPEND ${_X} ${ARGV}) ENDFOREACH() ENDIF() ENDMACRO() # Is a helper macro for add_sphinx_document() to set the first argument to # the path in the second argument with the third argument used as the base # for relative paths. If the fourth argument evaluates to be true, the # path will be converted to the native format. MACRO(sphinx_helper_convert_path _OUT _IN _BASE _NATIVE) IF("${_IN}" MATCHES "^[/~]") IF(${_NATIVE}) FILE(TO_NATIVE_PATH "${_IN}" ${_OUT}) ELSE() SET(${_OUT} "${_IN}") ENDIF() ELSEIF("${_BASE}" MATCHES "/$") IF(${_NATIVE}) FILE(TO_NATIVE_PATH "${_BASE}${_IN}" ${_OUT}) ELSE() SET(${_OUT} "${_BASE}${_IN}") ENDIF() ELSE() IF(${_NATIVE}) FILE(TO_NATIVE_PATH "${_BASE}/${_IN}" ${_OUT}) ELSE() SET(${_OUT} "${_BASE}/${_IN}") ENDIF() ENDIF() ENDMACRO() # add_sphinx_document( # # SOURCE_DIR | # SOURCE_TARGET [SOURCE_TARGET_DIR ] # [[NOCONF] [[CONF_DIR [CONF_TARGET_DIR ]]]] # [OUTPUT_FORMATS ...] # [OUTPUT_DIR ] # [CONF_OPTIONS ...] # [ALL] # [BUILD_FAIL_NO_SPHINX] [BUILD_MESSAGE_NO_SPHINX message_part ...] # ) # is the name of the target that will build a set of documention # with sphinx-build. The target will be created with add_custom_target(). # If sphinx-build was not found with find_package(Sphinx), the target will # generate a message, customizable with BUILD_MESSAGE_NO_SPHINX, and, if # configured with BUILD_FAIL_NO_SPHINX, cause that build step to fail. # SOURCE_DIR specifies that is the source directory to be used # with sphinx-build for the target. If is a relative path, # it is evaluated with respect to CMAKE_CURRENT_SOURCE_DIR. # SOURCE_TARGET specifies that the source directory for the target will be # generated by another target, , created by # add_custom_target(). SOURCE_TARGET_DIR specifies the directory, # , that is created by and will be passed # to sphinx-build as the source directory for the documentation. If # is a relative path, it is interpreted relative to the # value of the RUNTIME_OUTPUT_DIRECTORY property of . # If SOURCE_TARGET_DIR is not present, the source directory will be the # value of the RUNTIME_OUTPUT_DIRECTORY property of . # will be added as a prerequisite for with # add_dependencies(). # NOCONF specifies that the target will not have a configuration file and # all configuration will have to be done via the options set with # CONF_OPTIONS. # CONF_DIR specifies that is the directory with the conf.py file # that sphinx-build should use for the target. If is a # relative path, it is evaluated with respect to CMAKE_CURRENT_SOURCE_DIR. # If NOCONF is not set and neither CONF_DIR nor CONF_TARGET are used, the # path to conf.py in the directory set by SOURCE_DIR or SOURCE_TARGET. # CONF_TARGET specifies that the configuration file for the target will be # generated by another target, , created by # add_custom_target(). CONF_TARGET_DIR specifies the directory, # , that is created by and will be passed as the # location of the conf.py file to sphinx-build. If is a # relative path, it will be interpreted relative to the value of the # RUNTIME_OUTPUT_DIRECTORY property of . If CONF_TARGET_DIR # is not present, the path to conf.py will be the value of the # RUNTIME_OUTPUT_DIRECTORY property of . # will be added as a prerequisite for with # add_dependencies(). If NOCONF is not set and neither CONF_DIR nor # CONF_TARGET are used, the path to conf.py will be the directory set by # SOURCE_DIR or SOURCE_TARGET. # OUTPUT_FORMATS specifies the output formats that the target will generate. # Each output format must be an allowed value for the "-b" option to # sphinx-build. One a target is created, use # sphinx_document_get_output_formats() on it to get the formts it will # generate. # OUTPUT_DIR specifies that is the base directory for where # results and intermediates will be written. If is a relative # path, it will be interpreted relative to CMAKE_CURRENT_BINARY_DIR. # If not set, the base output directory will be # CMAKE_RUNTIME_OUTPUT_DIRECTORY. Once a target is created, use # sphinx_document_get_output_directory() on it to get the subdirectory of # the base directory where the generated documentation will be written. # Use sphinx_document_get_output_formats() to get the list of the names # of the output formats generated. The result for each format will be # stored in a subdirectory, with the same name as the name of the format, # of the directory returned by sphinx_document_get_output_directory(). # CONF_OPTIONS specifies one or more options to override what is in the # configuration file: each option will be passed to sphinx-build with # a "-D" option. # ALL causes the generated target to be added to the default build target. # BUILD_FAIL_NO_SPHINX causes the target to fail if triggered during a build # and sphinx-build was not available. # BUILD_MESSAGE_NO_SPHINX customizes the message shown when the target is # triggered during a build and sphinx-build was not available. Set the # message to an empty string to not have any message printed. # # Usage notes: # If you are using CONF_TARGET to pick up a conf.py generated in the build # directories, the things that conf.py pulls in, like the _static or # _templates directories, will have to be copied to the build directory # (or generated some other way there) so they can be found by sphinx-build # at the same locations relative to conf.py. # # Limitations: # Currently provides no way to allow the caller to pass "-a", "-E", "-t", # "-j", "-A", "-n", "-N", "-v", "-q", "-Q", "-w", "-W", "--keep-going", # "-T", or "-P" options to sphinx-build. # FUNCTION(add_sphinx_document _TARGET_NAME) FIND_PACKAGE(Sphinx) # Parse the arguments. SET( _OPTIONS NOCONF ALL BUILD_FAIL_NO_SPHINX ) SET( _ONE_VALUE_ARGS SOURCE_DIR SOURCE_TARGET SOURCE_TARGET_DIR CONF_DIR CONF_TARGET CONF_TARGET_DIR OUTPUT_DIR ) SET( _MULT_VALUE_ARGS OUTPUT_FORMATS CONF_OPTIONS BUILD_MESSAGE_NO_SPHINX ) CMAKE_PARSE_ARGUMENTS(_IN "${_OPTIONS}" "${_ONE_VALUE_ARGS}" "${_MULT_VALUE_ARGS}" ${ARGN}) IF(DEFINED _IN_UNPARSED_ARGUMENTS) MESSAGE(FATAL_ERROR "add_sphinx_document() was called with one or more unrecognized arguments: ${_IN_UNPARSED_ARGUMENTS}") ENDIF() # Initialize a list of the target dependencies. UNSET(_TARGET_DEPENDS) # Initialize the list, _COMMAND, that will be the first command passed to # add_custom_target(). Also initialize the list of the other commands that # will be passed. UNSET(_EXTRA_COMMANDS) SET(_EXTRA_INDEX -1) IF(Sphinx_FOUND) SET(_COMMAND "${SPHINX_EXECUTABLE}") ELSE() IF(DEFINED _IN_BUILD_MESSAGE_NO_SPHINX) IF(NOT _IN_BUILD_MESSAGE_NO_SPHINX STREQUAL "") SET( _COMMAND "${CMAKE_COMMAND}" "-E" "echo" ${_IN_BUILD_MESSAGE_NO_SPHINX} ) ELSE() UNSET(_COMMAND) ENDIF() ELSE() SET( _COMMAND "${CMAKE_COMMAND}" "-E" "echo" "sphinx-build not found; cannot build ${_TARGET_NAME}" ) ENDIF() IF(_IN_BUILD_FAIL_NO_SPHINX) IF(DEFINED _COMMAND) MATH(EXPR _EXTRA_INDEX "${_EXTRA_INDEX} + 1") SET(_Y "_EXTRA_COMMAND_${_EXTRA_INDEX}") LIST(APPEND _EXTRA_COMMANDS ${_Y}) SET(${_Y} "${CMAKE_COMMAND}" "-E" "false") ELSE() SET(_COMMAND "${CMAKE_COMMAND}" "-E" "false") ENDIF() ENDIF() ENDIF() IF((DEFINED _IN_OUTPUT_FORMATS) AND Sphinx_FOUND) FOREACH(_X ${_IN_OUTPUT_FORMATS}) IF(_EXTRA_INDEX EQUAL -1) LIST(APPEND _COMMAND "-b" "${_X}") ELSE() SET(_Y "_EXTRA_COMMAND_${_EXTRA_INDEX}") LIST(APPEND _EXTRA_COMMANDS "${_Y}") SET(${_Y} "${SPHINX_EXECUTABLE}" "-b" "${_X}") ENDIF() MATH(EXPR _EXTRA_INDEX "${_EXTRA_INDEX} + 1") ENDFOREACH() ENDIF() # Handle the source directory. IF(DEFINED _IN_SOURCE_DIR) IF((DEFINED _IN_SOURCE_TARGET) OR (DEFINED _IN_SOURCE_TARGET_DIR)) MESSAGE(FATAL_ERROR "add_sphinx_document() was called with SOURCE_DIR and one or more of SOURCE_TARGET and SOURCE_TARGET_DIR") ENDIF() SPHINX_HELPER_CONVERT_PATH( _NATIVE_SOURCE_DIR "${_IN_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" YES ) ELSEIF(DEFINED _IN_SOURCE_TARGET) IF(NOT DEFINED _IN_SOURCE_TARGET_DIR) SET(_IN_SOURCE_TARGET_DIR "") ENDIF() GET_PROPERTY( _X TARGET ${_IN_SOURCE_TARGET} PROPERTY "RUNTIME_OUTPUT_DIRECTORY" ) SPHINX_HELPER_CONVERT_PATH( _NATIVE_SOURCE_TARGET_DIR "${_IN_SOURCE_TARGET_DIR}" "${_X}" YES ) LIST(APPEND _TARGET_DEPENDS "${_IN_SOURCE_TARGET}") ELSE() MESSAGE(FATAL_ERROR "add_sphinx_document() was called without either SOURCE_DIR or SOURCE_TARGET") ENDIF() # Handle the configuration file. IF(_IN_NOCONF) IF((DEFINED _IN_CONF_DIR) OR (DEFINED _IN_CONF_TARGET) OR (DEFINED _IN_CONF_TARGET_DIR)) MESSAGE(FATAL_ERROR "add_sphinx_document() was called with NOCONF and one or more of CONF_DIR, CONF_TARGET, or CONF_TARGET_DIR") ENDIF() SPHINX_HELPER_ADD_TO_COMMANDS("-C") ELSEIF(DEFINED _IN_CONF_DIR) IF(DEFINED _IN_CONF_TARGET) MESSAGE(FATAL_ERROR "add_sphinx_document() was called with both CONF_DIR and CONF_TARGET") ENDIF() SPHINX_HELPER_CONVERT_PATH( _NATIVE_CONF_DIR "${_IN_CONF_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" YES ) ELSEIF(DEFINED _IN_CONF_TARGET) IF(NOT DEFINED _IN_CONF_TARGET_DIR) SET(_IN_CONF_TARGET_DIR "") ENDIF() GET_PROPERTY( _X TARGET ${_IN_CONF_TARGET} PROPERTY "RUNTIME_OUTPUT_DIRECTORY" ) SPHINX_HELPER_CONVERT_PATH( _NATIVE_CONF_TARGET_DIR "${_IN_CONF_TARGET_DIR}" "${_X}" YES ) LIST(APPEND _TARGET_DEPENDS "${_IN_CONF_TARGET}") SPHINX_HELPER_ADD_TO_COMMANDS("-c" "${_NATIVE_CONF_TARGET_DIR}") ELSE() IF(DEFINED _IN_SOURCE_DIR) SET(_IN_CONF_DIR "${_IN_SOURCE_DIR}") SET(_X "${CMAKE_CURRENT_SOURCE_DIR}") ELSE() SET(_IN_CONF_DIR "${_IN_SOURCE_TARGET_DIR}") GET_PROPERTY( _X TARGET ${_IN_CONF_TARGET} PROPERTY "RUNTIME_OUTPUT_DIRECTORY" ) ENDIF() SPHINX_HELPER_CONVERT_PATH( _NATIVE_CONF_DIR "${_IN_CONF_DIR}" "${_X}" YES ) ENDIF() # Handle the output directory. IF(NOT (DEFINED _IN_OUTPUT_DIR)) SET(_IN_OUTPUT_DIR "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") ENDIF() SPHINX_HELPER_CONVERT_PATH( _OUT_OUTPUT_BASE_DIR "${_IN_OUTPUT_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" NO ) SPHINX_HELPER_CONVERT_PATH( _NATIVE_OUTPUT_CACHE_DIR "_doctree" "${_OUT_OUTPUT_BASE_DIR}" YES ) SPHINX_HELPER_ADD_TO_COMMANDS("-d" "${_NATIVE_OUTPUT_CACHE_DIR}") # Handle the overrides for values set in the configuration file. IF(DEFINED _IN_CONF_OPTIONS) FOREACH(_X ${_IN_CONF_OPTIONS}) SPHINX_HELPER_ADD_TO_COMMANDS("-D" "${_X}") ENDFOREACH() ENDIF() # Add the source directory as the first non-option to the command. IF(DEFINED _IN_SOURCE_DIR) SPHINX_HELPER_ADD_TO_COMMANDS("${_NATIVE_SOURCE_DIR}") ELSE() SPHINX_HELPER_ADD_TO_COMMANDS("${_NATIVE_SOURCE_TARGET_DIR}") ENDIF() # Add the output directory for documents as the second non-option to the # the command. Put each format in a separate directory, like the make # mode for sphinx-build does. IF((DEFINED _IN_OUTPUT_FORMATS) AND Sphinx_FOUND) SET(_EXTRA_INDEX -1) FOREACH(_X ${_IN_OUTPUT_FORMATS}) SPHINX_HELPER_CONVERT_PATH( _NATIVE_OUTPUT_DOC_DIR "${_X}" "${_OUT_OUTPUT_BASE_DIR}" YES ) IF(_EXTRA_INDEX EQUAL -1) LIST(APPEND _COMMAND "${_NATIVE_OUTPUT_DOC_DIR}") ELSE() SET(_Y "_EXTRA_COMMAND_${_EXTRA_INDEX}") LIST(APPEND ${_Y} "${_NATIVE_OUTPUT_DOC_DIR}") ENDIF() MATH(EXPR _EXTRA_INDEX "${_EXTRA_INDEX} + 1") ENDFOREACH() ELSEIF(Sphinx_FOUND) # There were no formats specified so use the bare output directory. SPHINX_HELPER_CONVERT_PATH( _NATIVE_OUTPUT_DOC_DIR "${_OUT_OUTPUT_BASE_DIR}" "" YES ) SPHINX_HELPER_ADD_TO_COMMANDS("${_NATIVE_OUTPUT_DOC_DIR}") ENDIF() # Convert some variables for convenient expansion in create_custom_target(). IF(_IN_ALL) SET(_IN_ALL "ALL") ELSE() SET(_IN_ALL "") ENDIF() SET(_EXTRA "") IF (NOT (_EXTRA_COMMANDS STREQUAL "")) FOREACH(_X ${_EXTRA_COMMANDS}) SET(_EXTRA ${_EXTRA} "COMMAND" ${${_X}}) ENDFOREACH() ENDIF() # Create the target. Modify and restore CMAKE_RUNTIME_OUTPUT_DIRECTORY # so that the target's RUNTIME_OUTPUT_DIRECTORY property reflects what # was set by the OUTPUT_DIR argument. IF(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY) SET(_OLD "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") ELSE() UNSET(_OLD) ENDIF() SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${_OUT_OUTPUT_BASE_DIR}") ADD_CUSTOM_TARGET(${_TARGET_NAME} ${_IN_ALL} ${_COMMAND} ${_EXTRA} VERBATIM) IF(DEFINED _OLD) SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${_OLD}") ELSE() UNSET(CMAKE_RUNTIME_OUTPUT_DIRECTORY) ENDIF() # Add the target dependencies. IF(NOT ("${_TARGET_DEPENDS}" STREQUAL "")) ADD_DEPENDENCIES(${_TARGET_NAME} ${_TARGET_DEPENDS}) ENDIF() # Define properties on the target to describe the placement of the output. # That's to allow downstream targets (installation or packaging, for # instance) to query it with sphinx_document_get_output_directory() and # sphinx_document_get_output_formats(). GET_PROPERTY( _PROP_DEFINED TARGET ${_TARGET_NAME} PROPERTY "SPHINX_OUTPUT_DIRECTORY" DEFINED ) IF(NOT _PROP_DEFINED) DEFINE_PROPERTY( TARGET PROPERTY "SPHINX_OUTPUT_DIRECTORY" BRIEF_DOCS "output directory for documention generated by sphinx-build" FULL_DOCS "Is the output directory associated with a target for documentation generated by sphinx-build. The path is a full one and is in CMake's format. The property reflects the directory configure into the target; changing the property won't affect the behavior of the target." ) ENDIF() SET_PROPERTY( TARGET ${_TARGET_NAME} PROPERTY "SPHINX_OUTPUT_DIRECTORY" "${_OUT_OUTPUT_BASE_DIR}" ) GET_PROPERTY( _PROP_DEFINED TARGET ${_TARGET_NAME} PROPERTY "SPHINX_OUTPUT_FORMATS" DEFINED ) IF(NOT _PROP_DEFINED) DEFINE_PROPERTY( TARGET PROPERTY "SPHINX_OUTPUT_FORMATS" BRIEF_DOCS "list of output formats generated by sphinx-build" FULL_DOCS "Is the list of output formats generate by sphinx-build for a target. The output for each format will be in its own subdirectory of the directory named by the target's SPHINX_OUTPUT_DIRECTORY property. The name of the subdirectory will be the same as the name of the format. The property reflects which formats were configured into the target; changing the property won't affect the behavior of the target." ) ENDIF() IF(DEFINED _IN_OUTPUT_FORMATS) SET_PROPERTY( TARGET ${_TARGET_NAME} PROPERTY "SPHINX_OUTPUT_FORMATS" ${_IN_OUTPUT_FORMATS} ) ENDIF() ENDFUNCTION() # sphinx_document_get_output_directory( target) # Queries the given target for its output directory with the documentation # generated by sphinx-build. If that has not been set, it will set # to -NOTFOUND. Otherwise it will set to the path to the # directory. FUNCTION(sphinx_document_get_output_directory _OUT _TARGET) GET_TARGET_PROPERTY(_RESULT ${_TARGET} "SPHINX_OUTPUT_DIRECTORY") SET(${_OUT} "${_RESULT}" PARENT_SCOPE) ENDFUNCTION() # sphinx_document_get_output_formats( target) # Queries the given target for its list of output formats generated by # sphinx-build. If that has not been set, it will set to # -NOTFOUND. Otherwise it will set to the list of the formats. # The location of the documentation generated for a particular format will # be a subdirectory, with the same name as the name of the format, of the # directory returned by sphinx_document_get_output_directory(). FUNCTION(sphinx_document_get_output_formats _OUT _TARGET) GET_TARGET_PROPERTY(_RESULT ${_TARGET} "SPHINX_OUTPUT_FORMATS") SET(${_OUT} "${_RESULT}" PARENT_SCOPE) ENDFUNCTION()