diff options
-rw-r--r-- | CMakeLists.txt | 10 | ||||
-rw-r--r-- | cmake/QbsBuildConfig.cmake | 2 | ||||
-rw-r--r-- | cmake/QbsDocumentation.cmake | 285 | ||||
-rw-r--r-- | doc/CMakeLists.txt | 84 |
4 files changed, 296 insertions, 85 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d32301116..4129bc911 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(FeatureSummary) include(QbsBuildConfig) +include(QbsDocumentation) file(STRINGS VERSION QBS_VERSION) project(Qbs VERSION ${QBS_VERSION}) @@ -57,6 +58,15 @@ else() endif() endif() +if (QBS_INSTALL_HTML_DOCS OR QBS_INSTALL_QCH_DOCS) + find_package(Python3 COMPONENTS Interpreter) + if (Qt6_FOUND) + find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Tools REQUIRED) + else() + find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Help REQUIRED) + endif() +endif() + add_subdirectory(src) add_subdirectory(doc) add_subdirectory(share) diff --git a/cmake/QbsBuildConfig.cmake b/cmake/QbsBuildConfig.cmake index 08e36bc67..28827268d 100644 --- a/cmake/QbsBuildConfig.cmake +++ b/cmake/QbsBuildConfig.cmake @@ -3,8 +3,6 @@ option(WITH_UNIT_TESTS "Build Unit Tests" OFF) option(INSTALL_PUBLIC_HEADERS "Whether to install public headers" ON) option(QBS_ENABLE_RPATH "Whether to enable RPATH" ON) option(QBS_USE_BUNDLED_QT_SCRIPT "Whether to use bundled QtScript module" OFF) -option(QBS_INSTALL_HTML_DOCS "Whether to install HTML Documentation" OFF) -option(QBS_INSTALL_QCH_DOCS "Whether to install QCH Documentation" OFF) set(QBS_APP_INSTALL_DIR "bin" CACHE STRING "Relative install location for Qbs binaries.") # default paths diff --git a/cmake/QbsDocumentation.cmake b/cmake/QbsDocumentation.cmake new file mode 100644 index 000000000..dad04d312 --- /dev/null +++ b/cmake/QbsDocumentation.cmake @@ -0,0 +1,285 @@ +# Options: +option(QBS_INSTALL_HTML_DOCS "Whether to install Qbs HTML Documentation" OFF) +option(QBS_INSTALL_QCH_DOCS "Whether to install Qbs QCH Documentation" OFF) + +# Get information on directories from qmake +# as this is not yet exported by cmake. +# Used for QT_INSTALL_DOCS +function(qt_query_qmake) + if (NOT TARGET Qt${QT_VERSION_MAJOR}::qmake) + message(FATAL_ERROR "Qmake was not found. Add find_package(Qt5 COMPONENTS Core) to CMake to enable.") + endif() + # dummy check for if we already queried qmake + if (QT_INSTALL_BINS) + return() + endif() + + get_target_property(_qmake_binary Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION) + execute_process(COMMAND "${_qmake_binary}" "-query" + TIMEOUT 10 + RESULT_VARIABLE _qmake_result + OUTPUT_VARIABLE _qmake_stdout + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if (NOT "${_qmake_result}" STREQUAL "0") + message(FATAL_ERROR "Qmake did not execute successfully: ${_qmake_result}.") + endif() + + # split into lines: + string(REPLACE "\n" ";" _lines "${_qmake_stdout}") + + foreach(_line ${_lines}) + # split line into key/value pairs + string(REPLACE ":" ";" _parts "${_line}") + list(GET _parts 0 _key) + list(REMOVE_AT _parts 0) + string(REPLACE ";" ":" _value "${_parts}") + + set("${_key}" "${_value}" CACHE PATH "qmake import of ${_key}" FORCE) + endforeach() +endfunction() + +# Find programs: +function(_qbs_doc_find_program result_var) + if (NOT TARGET Qt${QT_VERSION_MAJOR}::qmake) + message(FATAL_ERROR "QDoc is only available in Qt projects") + endif() + + get_target_property(_qmake_binary Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION) + get_filename_component(_qmake_dir "${_qmake_binary}" DIRECTORY) + find_program("_prg_${result_var}" ${ARGN} HINTS "${_qmake_dir}") + if ("_prg_${result_var}" STREQUAL "_prg_${result_var}-NOTFOUND") + set("_prg_${result_var}" "${result_var}-NOTFOUND") + message(WARNING "Could not find binary for ${result_var}") + endif() + + set(${result_var} "${_prg_${result_var}}" PARENT_SCOPE) +endfunction() + +function(_qbs_setup_doc_targets) + # Set up important targets: + if (NOT TARGET qbs_html_docs) + add_custom_target(qbs_html_docs COMMENT "Build HTML documentation") + endif() + if (NOT TARGET qbs_qch_docs) + add_custom_target(qbs_qch_docs COMMENT "Build QCH documentation") + endif() + if (NOT TARGET BuildQbsDocumentation) + add_custom_target( + BuildQbsDocumentation ALL COMMENT "Build Qbs documentation") + add_dependencies(BuildQbsDocumentation qbs_html_docs qbs_qch_docs) + endif() +endfunction() + +function(_find_python_module module) + string(TOUPPER ${module} module_upper) + if (NOT PY_${module_upper}) + if (ARGC GREATER 1 AND ARGV1 STREQUAL "REQUIRED") + set(${module}_FIND_REQUIRED TRUE) + endif() + # A module's location is usually a directory, but for binary modules + # it's a .so file. + execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" + "import re, ${module}; print(re.compile('/__init__.py.*').sub('',${module}.__file__))" + RESULT_VARIABLE _${module}_status + OUTPUT_VARIABLE _${module}_location + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if (NOT _${module}_status) + set(PY_${module_upper} ${_${module}_location} CACHE STRING + "Location of Python module ${module}") + endif() + endif() + find_package_handle_standard_args(PY_${module} DEFAULT_MSG PY_${module_upper}) +endfunction() + +function(_qbs_setup_qdoc_targets _qdocconf_file _retval) + cmake_parse_arguments(_arg "" "HTML_DIR;INSTALL_DIR;POSTFIX" + "INDEXES;INCLUDE_DIRECTORIES;FRAMEWORK_PATHS;ENVIRONMENT_EXPORTS" ${ARGN}) + + foreach(_index ${_arg_INDEXES}) + list(APPEND _qdoc_index_args "-indexdir;${_index}") + endforeach() + + set(_env "") + foreach(_export ${_arg_ENVIRONMENT_EXPORTS}) + if (NOT DEFINED "${_export}") + message(FATAL_ERROR "${_export} is not known when trying to export it to qdoc.") + endif() + list(APPEND _env "${_export}=${${_export}}") + endforeach() + + set(_full_qdoc_command "${_qdoc}") + if (_env) + set(_full_qdoc_command "${CMAKE_COMMAND}" "-E" "env" ${_env} "${_qdoc}") + endif() + + if (_arg_HTML_DIR STREQUAL "") + set(_arg_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc") + endif() + + get_filename_component(_target "${_qdocconf_file}" NAME_WE) + + # message(${_target}) + # set(_html_outputdir "${_arg_HTML_DIR}/${_target}${_arg_POSTFIX}") + set(_html_outputdir "${_arg_HTML_DIR}") + file(MAKE_DIRECTORY "${_html_outputdir}") + + set(_qdoc_include_args "") + if (_arg_INCLUDE_DIRECTORIES OR _arg_FRAMEWORK_PATHS) + # pass include directories to qdoc via hidden @ option, since we need to generate a file + # to be able to resolve the generators inside the include paths + set(_qdoc_includes "${CMAKE_CURRENT_BINARY_DIR}/cmake/qdoc_${_target}.inc") + set(_qdoc_include_args "@${_qdoc_includes}") + set(_includes "") + if (_arg_INCLUDE_DIRECTORIES) + set(_includes "-I$<JOIN:${_arg_INCLUDE_DIRECTORIES},\n-I>\n") + endif() + set(_frameworks "") + if (_arg_FRAMEWORK_PATHS) + set(_frameworks "-F$<JOIN:${_arg_FRAMEWORK_PATHS},\n-F>\n") + endif() + file(GENERATE + OUTPUT "${_qdoc_includes}" + CONTENT "${_includes}${_frameworks}" + ) + endif() + + set(_html_target "html_docs_${_target}") + add_custom_target("${_html_target}" + ${_full_qdoc_command} -outputdir "${_html_outputdir}" "${_qdocconf_file}" + ${_qdoc_index_args} ${_qdoc_include_args} + COMMENT "Build HTML documentation from ${_qdocconf_file}" + DEPENDS "${_qdocconf_file}" + SOURCES "${_qdocconf_file}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + VERBATIM + ) + + if (NOT Python3_Interpreter_FOUND) + message(WARNING "Cannot find python3 binary. Qbs documentation will not be built.") + endif() + _find_python_module(lxml) + _find_python_module(bs4) + if (NOT PY_LXML OR NOT PY_BS4) + message(FATAL_ERROR "Cannot import lxml and bs4 python modules. Qbs documentation will not be built.") + endif() + + set(_fixed_html_target "fixed_html_docs_${_target}") + set(_fix_qml_imports_script ${Qbs_SOURCE_DIR}/doc/fix-qmlimports.py) + add_custom_target("${_fixed_html_target}" + ${Python3_EXECUTABLE} "${_fix_qml_imports_script}" ${_html_outputdir} + DEPENDS "${_html_target}" + SOURCES "${_fix_qml_imports_script}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + VERBATIM + ) + add_dependencies(qbs_html_docs "${_fixed_html_target}") + + set("${_retval}" "${_html_outputdir}" PARENT_SCOPE) +endfunction() + +function(_qbs_setup_qhelpgenerator_targets _qdocconf_file _html_outputdir) + cmake_parse_arguments(_arg "" "QCH_DIR;INSTALL_DIR" "" ${ARGN}) + if (_arg_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "qdoc_build_qdocconf_file has unknown arguments: ${_arg_UNPARSED_ARGUMENTS}.") + endif() + + if (NOT _arg_QCH_DIR) + set(_arg_QCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc") + endif() + + if (NOT TARGET Qt${QT_VERSION_MAJOR}::qhelpgenerator) + message(WARNING "qhelpgenerator missing: No QCH documentation targets were generated. Add find_package(Qt5 COMPONENTS Help) to CMake to enable.") + return() + endif() + + get_filename_component(_target "${_qdocconf_file}" NAME_WE) + + set(_qch_outputdir "${_arg_QCH_DIR}") + file(MAKE_DIRECTORY "${_qch_outputdir}") + + set(_qch_target "qch_docs_${_target}") + set(_html_target "html_docs_${_target}") + add_custom_target("${_qch_target}" + Qt${QT_VERSION_MAJOR}::qhelpgenerator "${_html_outputdir}/${_target}.qhp" -o "${_qch_outputdir}/${_target}.qch" + COMMENT "Build QCH documentation from ${_qdocconf_file}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + VERBATIM + ) + add_dependencies("${_qch_target}" "${_html_target}") + add_dependencies(qbs_qch_docs "${_qch_target}") + + install(FILES "${_qch_outputdir}/${_target}.qch" DESTINATION "${_arg_INSTALL_DIR}" + COMPONENT qbs_qch_docs) +endfunction() + +# Helper functions: +function(_qbs_qdoc_build_qdocconf_file _qdocconf_file) + _qbs_setup_doc_targets() + + _qbs_doc_find_program(_qdoc NAMES qdoc qdoc-qt5) + if (_qdoc STREQUAL "_prg__qdoc-NOTFOUND") + message(WARNING "No qdoc binary found: No documentation targets were generated") + return() + endif() + + cmake_parse_arguments(_arg "QCH" "HTML_DIR;QCH_DIR;INSTALL_DIR;POSTFIX" + "INDEXES;INCLUDE_DIRECTORIES;FRAMEWORK_PATHS;ENVIRONMENT_EXPORTS" ${ARGN}) + if (_arg_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "qdoc_build_qdocconf_file has unknown arguments: ${_arg_UNPARSED_ARGUMENTS}.") + endif() + + if (NOT _arg_INSTALL_DIR) + message(FATAL_ERROR "No INSTALL_DIR set when calling qdoc_build_qdocconf_file") + endif() + + _qbs_setup_qdoc_targets("${_qdocconf_file}" _html_outputdir + HTML_DIR "${_arg_HTML_DIR}" INSTALL_DIR "${_arg_INSTALL_DIR}" + INDEXES ${_arg_INDEXES} ENVIRONMENT_EXPORTS ${_arg_ENVIRONMENT_EXPORTS} + POSTFIX "${_arg_POSTFIX}" + INCLUDE_DIRECTORIES ${_arg_INCLUDE_DIRECTORIES} + FRAMEWORK_PATHS ${_arg_FRAMEWORK_PATHS} + ) + + if (_arg_QCH) + _qbs_setup_qhelpgenerator_targets("${_qdocconf_file}" "${_html_outputdir}" + QCH_DIR "${_arg_QCH_DIR}" INSTALL_DIR "${_arg_INSTALL_DIR}") + endif() + +endfunction() + +function(add_qbs_documentation qdocconf_file) + cmake_parse_arguments(_arg "" "" + "INCLUDE_DIRECTORIES;FRAMEWORK_PATHS" ${ARGN}) + if (_arg_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "add_qbs_documentation has unknown arguments: ${_arg_UNPARSED_ARGUMENTS}.") + endif() + + ### Skip docs setup if that is not needed! + if (NOT QBS_INSTALL_HTML_DOCS AND NOT QBS_INSTALL_QCH_DOCS) + return() + endif() + + qt_query_qmake() + set(SRCDIR "${Qbs_SOURCE_DIR}/doc") + + set(_qch_params) + if (QBS_INSTALL_QCH_DOCS) + set(_qch_params QCH QCH_DIR "${CMAKE_CURRENT_BINARY_DIR}") + endif() + set(_qdoc_params HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/html") + list(APPEND _qdoc_params INSTALL_DIR "${QBS_DOC_INSTALL_DIR}") + + # Set up environment for qdoc: + string(REPLACE "." "" QBS_VERSION_TAG "${QBS_VERSION}") + + list(APPEND _qdoc_params ENVIRONMENT_EXPORTS + SRCDIR QBS_VERSION QBS_VERSION_TAG + QT_INSTALL_DOCS + ) + + _qbs_qdoc_build_qdocconf_file(${qdocconf_file} ${_qch_params} ${_qdoc_params} + INCLUDE_DIRECTORIES ${_arg_INCLUDE_DIRECTORIES} + FRAMEWORK_PATHS ${_arg_FRAMEWORK_PATHS} + ) +endfunction() diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 96cdab897..57dcbe33e 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,83 +1 @@ -if (QBS_INSTALL_HTML_DOCS OR QBS_INSTALL_QCH_DOCS) - - find_package(Python3 COMPONENTS Interpreter) - - function(find_python_module module) - string(TOUPPER ${module} module_upper) - if (NOT PY_${module_upper}) - if (ARGC GREATER 1 AND ARGV1 STREQUAL "REQUIRED") - set(${module}_FIND_REQUIRED TRUE) - endif() - # A module's location is usually a directory, but for binary modules - # it's a .so file. - execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" - "import re, ${module}; print(re.compile('/__init__.py.*').sub('',${module}.__file__))" - RESULT_VARIABLE _${module}_status - OUTPUT_VARIABLE _${module}_location - ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) - if (NOT _${module}_status) - set(PY_${module_upper} ${_${module}_location} CACHE STRING - "Location of Python module ${module}") - endif() - endif() - find_package_handle_standard_args(PY_${module} DEFAULT_MSG PY_${module_upper}) - endfunction() - - if (Python3_Interpreter_FOUND) - find_python_module(lxml) - find_python_module(bs4) - if (PY_LXML AND PY_BS4) - - get_target_property(_QBS_OUTPUT_DIR qbs RUNTIME_OUTPUT_DIRECTORY) - - if (QBS_INSTALL_HTML_DOCS) - set(_INSTALL_HTML_DOCS true) - else() - set(_INSTALL_HTML_DOCS false) - endif() - - if (QBS_INSTALL_QCH_DOCS) - set(_INSTALL_QCH_DOCS true) - else() - set(_INSTALL_QCH_DOCS false) - endif() - - get_target_property(_QT_QMAKE_EXECUTABLE Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION) - get_update_path_command(UPDATE_PATH_COMMAND) - add_custom_target( - BuildQbsDocumentation ALL - COMMAND ${CMAKE_COMMAND} -E env "${UPDATE_PATH_COMMAND}" ${_QBS_OUTPUT_DIR}/qbs - resolve - --settings-dir ${PROJECT_BINARY_DIR}/settings - -f ${PROJECT_SOURCE_DIR}/qbs.qbs - -d ${PROJECT_BINARY_DIR}/ - config:doc-build - qbs.installPrefix:undefined - qbs.buildVariant:release - project.withCode:false - project.withDocumentation:true - profile:none - "products.qbs documentation.pythonPath:${Python3_EXECUTABLE}" - modules.qbsbuildconfig.installHtml:${_INSTALL_HTML_DOCS} - modules.qbsbuildconfig.installQch:${_INSTALL_QCH_DOCS} - moduleProviders.Qt.qmakeFilePaths:${_QT_QMAKE_EXECUTABLE} - COMMAND ${CMAKE_COMMAND} -E env "${UPDATE_PATH_COMMAND}" ${_QBS_OUTPUT_DIR}/qbs - build - --settings-dir ${PROJECT_BINARY_DIR}/settings - -f ${PROJECT_SOURCE_DIR}/qbs.qbs - -d ${PROJECT_BINARY_DIR}/ - config:doc-build - -p "qbs documentation" - DEPENDS qbs copy-runtime-files-qbs qbs_processlauncher - ) - install( - DIRECTORY ${PROJECT_BINARY_DIR}/doc-build/install-root/share/doc/qbs/html/ - DESTINATION "${QBS_DOC_INSTALL_DIR}" - ) - else() - message(WARNING "Cannot import lxml and bs4 python modules. Qbs documentation will not be built.") - endif() - else() - message(WARNING "Cannot find python3 binary. Qbs documentation will not be built.") - endif() -endif() +add_qbs_documentation("qbs.qdocconf") |