--- a/browser/base/moz.build
+++ b/browser/base/moz.build
@@ -1,15 +1,16 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-SPHINX_TREES['sslerrorreport'] = 'content/docs/sslerrorreport'
+with Sphinx():
+ TREES['sslerrorreport'] = 'content/docs/sslerrorreport'
TESTING_JS_MODULES += [
'content/test/BrowserUITestUtils.jsm',
]
MOCHITEST_MANIFESTS += [
'content/test/general/mochitest.ini',
]
--- a/browser/experiments/moz.build
+++ b/browser/experiments/moz.build
@@ -10,9 +10,10 @@ EXTRA_COMPONENTS += [
]
EXTRA_JS_MODULES.experiments += [
'Experiments.jsm',
]
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
-SPHINX_TREES['experiments'] = 'docs'
+with Sphinx():
+ TREES['experiments'] = 'docs'
--- a/browser/moz.build
+++ b/browser/moz.build
@@ -1,17 +1,18 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
CONFIGURE_SUBST_FILES += ['installer/Makefile']
-SPHINX_TREES['browser'] = 'docs'
+with Sphinx():
+ TREES['browser'] = 'docs'
DIRS += [
'base',
'components',
'experiments',
'fuel',
'locales',
'modules',
--- a/build/moz.build
+++ b/build/moz.build
@@ -1,16 +1,17 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-# This cannot be named "build" because of bug 922191.
-SPHINX_TREES['buildsystem'] = 'docs'
+with Sphinx():
+ # This cannot be named "build" because of bug 922191.
+ TREES['buildsystem'] = 'docs'
if CONFIG['OS_ARCH'] == 'WINNT':
DIRS += ['win32']
else:
DIRS += ['unix']
if CONFIG['OS_TARGET'] == 'Android' and not CONFIG['MOZ_ANDROID_LIBSTDCXX']:
DIRS += ['stlport']
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -86,18 +86,19 @@ include('/ipc/chromium/chromium-config.m
if CONFIG['MOZ_AUDIO_CHANNEL_MANAGER']:
LOCAL_INCLUDES += [
'/dom/system/gonk',
]
FINAL_LIBRARY = 'xul'
-SPHINX_TREES['webidl'] = 'docs'
-SPHINX_PYTHON_PACKAGE_DIRS += ['mozwebidlcodegen']
+with Sphinx():
+ TREES['webidl'] = 'docs'
+ PYTHON_PACKAGE_DIRS += ['mozwebidlcodegen']
if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']:
# This is needed for Window.webidl
DEFINES['HAVE_SIDEBAR'] = True
PYTHON_UNIT_TESTS += [
'mozwebidlcodegen/test/test_mozwebidlcodegen.py',
]
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -1,16 +1,18 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += ['locales']
-SPHINX_TREES['fennec'] = 'docs'
+
+with Sphinx():
+ TREES['fennec'] = 'docs'
include('android-services.mozbuild')
thirdparty_source_dir = TOPSRCDIR + '/mobile/android/thirdparty/'
constants_jar = add_java_jar('constants')
constants_jar.sources = [
'SysInfo.java',
--- a/python/moz.build
+++ b/python/moz.build
@@ -1,22 +1,22 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-SPHINX_PYTHON_PACKAGE_DIRS += [
- 'mach',
- 'mozbuild/mozbuild',
- 'mozbuild/mozpack',
- 'mozversioncontrol/mozversioncontrol',
-]
-
-SPHINX_TREES['mach'] = 'mach/docs'
+with Sphinx():
+ TREES['mach'] = 'mach/docs'
+ PYTHON_PACKAGE_DIRS += [
+ 'mach',
+ 'mozbuild/mozbuild',
+ 'mozbuild/mozpack',
+ 'mozversioncontrol/mozversioncontrol',
+ ]
PYTHON_UNIT_TESTS += [
'mach/mach/test/__init__.py',
'mach/mach/test/common.py',
'mach/mach/test/test_conditions.py',
'mach/mach/test/test_config.py',
'mach/mach/test/test_entry_point.py',
'mach/mach/test/test_error_output.py',
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -391,25 +391,46 @@ def ContextDerivedTypedList(type, base_c
def __new__(cls, obj):
return type(context, obj)
self.TYPE = _Type
super(_TypedList, self).__init__(iterable)
return _TypedList
+class Sphinx(SubContext):
+ """Describes how Sphinx documentation should be built.
+ """
+
+ VARIABLES = {
+ 'TREES': (dict, dict,
+ """Describes what the Sphinx documentation tree will look like.
+
+ Keys are relative directories inside the final Sphinx documentation
+ tree to install files into. Values are directories (relative to
+ this file) whose content to copy into the Sphinx documentation
+ tree.
+ """, None),
+
+ 'PYTHON_PACKAGE_DIRS': (StrictOrderingOnAppendList, list,
+ """Directories containing Python packages that Sphinx documents.
+ """, None),
+ }
+
+
# This defines functions that create sub-contexts.
#
# Values are classes that are SubContexts. The class name will be turned into
# a function that when called emits an instance of that class.
#
# Arbitrary arguments can be passed to the class constructor. The first
# argument is always the parent context. It is up to each class to perform
# argument validation.
SUBCONTEXTS = [
+ Sphinx,
]
for cls in SUBCONTEXTS:
if not issubclass(cls, SubContext):
raise ValueError('SUBCONTEXTS entry not a SubContext class: %s' % cls)
if not hasattr(cls, 'VARIABLES'):
raise ValueError('SUBCONTEXTS entry does not have VARIABLES: %s' % cls)
@@ -1150,28 +1171,16 @@ VARIABLES = {
GYP_DIRS['foo'].input = 'foo/foo.gyp'
GYP_DIRS['foo'].variables = {
'foo': 'bar',
(...)
}
(...)
""", None),
- 'SPHINX_TREES': (dict, dict,
- """Describes what the Sphinx documentation tree will look like.
-
- Keys are relative directories inside the final Sphinx documentation
- tree to install files into. Values are directories (relative to this
- file) whose content to copy into the Sphinx documentation tree.
- """, None),
-
- 'SPHINX_PYTHON_PACKAGE_DIRS': (StrictOrderingOnAppendList, list,
- """Directories containing Python packages that Sphinx documents.
- """, None),
-
'CFLAGS': (List, list,
"""Flags passed to the C compiler for all of the C source files
declared in this directory.
Note that the ordering of flags matters here, these flags will be
added to the compiler's command line in the same order as they
appear in the moz.build file.
""", None),
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -69,17 +69,20 @@ from .data import (
UnifiedSources,
VariablePassthru,
WebIDLFile,
XPIDLFile,
)
from .reader import SandboxValidationError
-from .context import Context
+from .context import
+ Context,
+ SubContext,
+)
class TreeMetadataEmitter(LoggingMixin):
"""Converts the executed mozbuild files into data structures.
This is a bridge between reader.py and data.py. It takes what was read by
reader.BuildReader and converts it into the classes defined in the data
module.
@@ -130,16 +133,21 @@ class TreeMetadataEmitter(LoggingMixin):
def emit_objs(objs):
for o in objs:
yield o
if not o._ack:
raise Exception('Unhandled object of type %s' % type(o))
for out in output:
+ # Nothing in sub-contexts is currently of interest to us. Filter
+ # them all out.
+ if isinstance(out, SubContext):
+ continue
+
if isinstance(out, Context):
# Keep all contexts around, we will need them later.
contexts[out.objdir] = out
start = time.time()
# We need to expand the generator for the timings to work.
objs = list(self.emit_from_context(out))
emitter_time += time.time() - start
--- a/python/mozbuild/mozbuild/frontend/reader.py
+++ b/python/mozbuild/mozbuild/frontend/reader.py
@@ -13,17 +13,16 @@ this file, which is represented by the S
to fill a Context, representing the output of an individual mozbuild file. The
The BuildReader contains basic logic for traversing a tree of mozbuild files.
It does this by examining specific variables populated during execution.
"""
from __future__ import print_function, unicode_literals
-import ast
import inspect
import logging
import os
import sys
import textwrap
import time
import tokenize
import traceback
@@ -818,124 +817,16 @@ class BuildReader(object):
ignore=ignore)
# The root doesn't get picked up by FileFinder.
yield 'moz.build'
for path, f in finder.find('**/moz.build'):
yield path
- def find_sphinx_variables(self):
- """This function finds all assignments of Sphinx documentation variables.
-
- This is a generator of tuples of (moz.build path, var, key, value). For
- variables that assign to keys in objects, key will be defined.
-
- With a little work, this function could be made more generic. But if we
- end up writing a lot of ast code, it might be best to import a
- high-level AST manipulation library into the tree.
- """
- # This function looks for assignments to SPHINX_TREES and
- # SPHINX_PYTHON_PACKAGE_DIRS variables.
- #
- # SPHINX_TREES is a dict. Keys and values should both be strings. The
- # target of the assignment should be a Subscript node. The value
- # assigned should be a Str node. e.g.
- #
- # SPHINX_TREES['foo'] = 'bar'
- #
- # This is an Assign node with a Subscript target. The Subscript's value
- # is a Name node with id "SPHINX_TREES." The slice of this target
- # is an Index node and its value is a Str with value "foo."
- #
- # SPHINX_PYTHON_PACKAGE_DIRS is a simple list. The target of the
- # assignment should be a Name node. Values should be a List node, whose
- # elements are Str nodes. e.g.
- #
- # SPHINX_PYTHON_PACKAGE_DIRS += ['foo']
- #
- # This is an AugAssign node with a Name target with id
- # "SPHINX_PYTHON_PACKAGE_DIRS." The value is a List node containing 1
- # Str elt whose value is "foo."
- relevant = [
- 'SPHINX_TREES',
- 'SPHINX_PYTHON_PACKAGE_DIRS',
- ]
-
- def assigned_variable(node):
- # This is not correct, but we don't care yet.
- if hasattr(node, 'targets'):
- # Nothing in moz.build does multi-assignment (yet). So error if
- # we see it.
- assert len(node.targets) == 1
-
- target = node.targets[0]
- else:
- target = node.target
-
- if isinstance(target, ast.Subscript):
- if not isinstance(target.value, ast.Name):
- return None, None
- name = target.value.id
- elif isinstance(target, ast.Name):
- name = target.id
- else:
- return None, None
-
- if name not in relevant:
- return None, None
-
- key = None
- if isinstance(target, ast.Subscript):
- assert isinstance(target.slice, ast.Index)
- assert isinstance(target.slice.value, ast.Str)
- key = target.slice.value.s
-
- return name, key
-
- def assigned_values(node):
- value = node.value
- if isinstance(value, ast.List):
- for v in value.elts:
- assert isinstance(v, ast.Str)
- yield v.s
- else:
- assert isinstance(value, ast.Str)
- yield value.s
-
- assignments = []
-
- class Visitor(ast.NodeVisitor):
- def helper(self, node):
- name, key = assigned_variable(node)
- if not name:
- return
-
- for v in assigned_values(node):
- assignments.append((name, key, v))
-
- def visit_Assign(self, node):
- self.helper(node)
-
- def visit_AugAssign(self, node):
- self.helper(node)
-
- for p in self.all_mozbuild_paths():
- assignments[:] = []
- full = os.path.join(self.config.topsrcdir, p)
-
- with open(full, 'rb') as fh:
- source = fh.read()
-
- tree = ast.parse(source, full)
- Visitor().visit(tree)
-
- for name, key, value in assignments:
- yield p, name, key, value
-
def read_mozbuild(self, path, config, read_tiers=False, descend=True,
metadata={}):
"""Read and process a mozbuild file, descending into children.
This starts with a single mozbuild file, executes it, and descends into
other referenced files per our traversal logic.
The traversal logic is to iterate over the *DIRS variables, treating
--- a/services/cloudsync/moz.build
+++ b/services/cloudsync/moz.build
@@ -1,15 +1,16 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-SPHINX_TREES['cloudsync'] = 'docs'
+with Sphinx():
+ TREES['cloudsync'] = 'docs'
EXTRA_JS_MODULES += [
'CloudSync.jsm',
'CloudSyncAdapters.jsm',
'CloudSyncBookmarks.jsm',
'CloudSyncBookmarksFolderCache.jsm',
'CloudSyncEventSource.jsm',
'CloudSyncLocal.jsm',
--- a/services/healthreport/moz.build
+++ b/services/healthreport/moz.build
@@ -1,15 +1,16 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-SPHINX_TREES['healthreport'] = 'docs'
+with Sphinx():
+ TREES['healthreport'] = 'docs'
XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
EXTRA_PP_COMPONENTS += [
'HealthReportComponents.manifest',
]
EXTRA_PP_JS_MODULES += [
--- a/services/moz.build
+++ b/services/moz.build
@@ -26,9 +26,10 @@ if CONFIG['MOZ_SERVICES_SYNC']:
DIRS += ['sync']
if CONFIG['MOZ_B2G']:
DIRS += ['mobileid']
if CONFIG['MOZ_SERVICES_CLOUDSYNC']:
DIRS += ['cloudsync']
-SPHINX_TREES['services'] = 'docs'
+with Sphinx():
+ TREES['services'] = 'docs'
--- a/toolkit/components/crashes/moz.build
+++ b/toolkit/components/crashes/moz.build
@@ -1,15 +1,16 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-SPHINX_TREES['crash-manager'] = 'docs'
+with Sphinx():
+ TREES['crash-manager'] = 'docs'
EXTRA_COMPONENTS += [
'CrashService.js',
'CrashService.manifest',
]
EXTRA_JS_MODULES += [
'CrashManager.jsm',
--- a/toolkit/components/telemetry/moz.build
+++ b/toolkit/components/telemetry/moz.build
@@ -55,9 +55,10 @@ GENERATED_FILES = [
if CONFIG['MOZILLA_OFFICIAL']:
DEFINES['MOZILLA_OFFICIAL'] = True
LOCAL_INCLUDES += [
'/xpcom/build',
'/xpcom/threads',
]
-SPHINX_TREES['telemetry'] = 'docs'
+with Sphinx():
+ TREES['telemetry'] = 'docs'
--- a/toolkit/crashreporter/moz.build
+++ b/toolkit/crashreporter/moz.build
@@ -1,15 +1,16 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-SPHINX_TREES['crashreporter'] = 'docs'
+with Sphinx():
+ TREES['crashreporter'] = 'docs'
if CONFIG['OS_ARCH'] == 'WINNT':
DIRS += [
'google-breakpad/src/common',
'google-breakpad/src/processor',
'breakpad-windows-libxul'
]
--- a/toolkit/modules/moz.build
+++ b/toolkit/modules/moz.build
@@ -4,17 +4,18 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini']
MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
-SPHINX_TREES['toolkit_modules'] = 'docs'
+with Sphinx():
+ TREES['toolkit_modules'] = 'docs'
EXTRA_JS_MODULES += [
'Battery.jsm',
'BinarySearch.jsm',
'BrowserUtils.jsm',
'CharsetMenu.jsm',
'debug.js',
'DeferredTask.jsm',
--- a/tools/docs/index.rst
+++ b/tools/docs/index.rst
@@ -22,37 +22,34 @@ This documentation is generated via the
`Sphinx <http://sphinx-doc.org/>`_ tool from sources in the tree.
To build the documentation, run ``mach build-docs``. Run
``mach help build-docs`` to see configurable options.
Adding Documentation
--------------------
-To add new documentation, define the ``SPHINX_TREES`` and
-``SPHINX_PYTHON_PACKAGE_DIRS`` variables in ``moz.build`` files in
-the tree and documentation will automatically get picked up.
+To add new documentation, the
+:ref:`Sphinx sub-context <mozbuild_subcontext_Sphinx>` should be used.
Say you have a directory ``featureX`` you would like to write some
documentation for. Here are the steps to create Sphinx documentation
for it:
1. Create a directory for the docs. This is typically ``docs``. e.g.
``featureX/docs``.
2. Create an ``index.rst`` file in this directory. The ``index.rst`` file
is the root documentation for that section. See ``build/docs/index.rst``
for an example file.
-3. In a ``moz.build`` file (typically the one in the parent directory of
- the ``docs`` directory), define ``SPHINX_TREES`` to hook up the plumbing.
- e.g. ``SPHINX_TREES['featureX'] = 'docs'``. This says *the ``docs``
- directory under the current directory should be installed into the
- Sphinx documentation tree under ``/featureX``*.
-4. If you have Python packages you would like to generate Python API
- documentation for, you can use ``SPHINX_PYTHON_PACKAGE_DIRS`` to
- declare directories containing Python packages. e.g.
- ``SPHINX_PYTHON_PACKAGE_DIRS += ['mozpackage']``.
+3. Add the following to your moz.build file::
+
+ with Sphinx():
+ TREES['featureX'] = 'docs'
+
+This says *the docs directory under the current directory should be
+installed into the Sphinx documentation tree under /featureX*.
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
--- a/tools/docs/moztreedocs/__init__.py
+++ b/tools/docs/moztreedocs/__init__.py
@@ -1,17 +1,21 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, # You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import unicode_literals
import os
-from mozbuild.frontend.reader import BuildReader
+from mozbuild.frontend.context import Sphinx
+from mozbuild.frontend.reader import (
+ EmptyConfig,
+ BuildReader,
+)
from mozpack.copier import FileCopier
from mozpack.files import FileFinder
from mozpack.manifests import InstallManifest
import sphinx
import sphinx.apidoc
@@ -25,35 +29,30 @@ class SphinxManager(object):
self._conf_py_path = os.path.join(main_path, 'conf.py')
self._index_path = os.path.join(main_path, 'index.rst')
self._trees = {}
self._python_package_dirs = set()
def read_build_config(self):
"""Read the active build config and add docs to this instance."""
- # Reading the Sphinx variables doesn't require a full build context.
- # Only define the parts we need.
- class fakeconfig(object):
- def __init__(self, topsrcdir):
- self.topsrcdir = topsrcdir
-
- config = fakeconfig(self._topsrcdir)
+ config = EmptyConfig(self._topsrcdir)
reader = BuildReader(config)
- for path, name, key, value in reader.find_sphinx_variables():
- reldir = os.path.dirname(path)
+ paths, contexts = reader.read_relevant_mozbuilds(reader.all_mozbuild_paths())
+ for context in contexts:
+ if not isinstance(context, Sphinx):
+ continue
- if name == 'SPHINX_TREES':
- assert key
- self.add_tree(os.path.join(reldir, value),
- os.path.join(reldir, key))
+ for tree, path in context['TREES'].items():
+ self.add_tree(os.path.join(context.relsrcdir, path),
+ os.path.join(context.relsrcdir, tree))
- if name == 'SPHINX_PYTHON_PACKAGE_DIRS':
- self.add_python_package_dir(os.path.join(reldir, value))
+ for path in context['PYTHON_PACKAGE_DIRS']:
+ self.add_python_package_dir(os.path.join(context.relsrcdir, path))
def add_tree(self, source_dir, dest_dir):
"""Add a directory from where docs should be sourced."""
if dest_dir in self._trees:
raise Exception('%s has already been registered as a destination.'
% dest_dir)
self._trees[dest_dir] = source_dir