--- a/python/mozbuild/mozbuild/backend/common.py
+++ b/python/mozbuild/mozbuild/backend/common.py
@@ -19,41 +19,55 @@ from mozbuild.frontend.context import (
Path,
RenamedSourcePath,
VARIABLES,
)
from mozbuild.frontend.data import (
BaseProgram,
ChromeManifestEntry,
ConfigFileSubstitution,
+ Defines,
+ DirectoryTraversal,
ExampleWebIDLInterface,
- IPDLFile,
+ FinalTargetFiles,
FinalTargetPreprocessedFiles,
- FinalTargetFiles,
GeneratedEventWebIDLFile,
+ GeneratedSources,
GeneratedWebIDLFile,
+ IPDLFile,
+ Linkable,
+ LocalInclude,
PreprocessedTestWebIDLFile,
PreprocessedWebIDLFile,
SharedLibrary,
+ SimpleProgram,
+ Sources,
TestManifest,
TestWebIDLFile,
UnifiedSources,
+ VariablePassthru,
+ WebIDLFile,
XPIDLFile,
- WebIDLFile,
)
from mozbuild.jar import (
DeprecatedJarManifest,
JarManifestParser,
)
from mozbuild.preprocessor import Preprocessor
from mozpack.chrome.manifest import parse_manifest_line
-from collections import defaultdict
+from collections import (
+ defaultdict,
+ OrderedDict,
+)
-from mozbuild.util import group_unified_files
+from mozbuild.util import (
+ expand_variables,
+ group_unified_files,
+)
class XPIDLManager(object):
"""Helps manage XPCOM IDLs in the context of the build system."""
def __init__(self, config):
self.config = config
self.topsrcdir = config.topsrcdir
self.topobjdir = config.topobjdir
@@ -223,16 +237,26 @@ class CommonBackend(BuildBackend):
def _init(self):
self._idl_manager = XPIDLManager(self.environment)
self._test_manager = TestManager(self.environment)
self._webidls = WebIDLCollection()
self._binaries = BinariesCollection()
self._configs = set()
self._ipdl_sources = set()
+ self._db = OrderedDict()
+ self._envs = {}
+ self._includes = defaultdict(list)
+ self._defines = defaultdict(list)
+ self._local_flags = defaultdict(dict)
+ self._extra_includes = defaultdict(list)
+ self._gyp_dirs = set()
+ self._dist_include_testing = '-I%s' % mozpath.join(
+ self.environment.topobjdir, 'dist', 'include', 'testing')
+
def consume_object(self, obj):
self._configs.add(obj.config)
if isinstance(obj, TestManifest):
for test in obj.tests:
self._test_manager.add(test, obj.flavor, obj.topsrcdir)
self._test_manager.add_defaults(obj.manifest)
self._test_manager.add_installs(obj, obj.topsrcdir)
@@ -318,22 +342,69 @@ class CommonBackend(BuildBackend):
if self.environment.is_artifact_build:
return True
if obj.have_unified_mapping:
self._write_unified_files(obj.unified_source_mapping, obj.objdir)
if hasattr(self, '_process_unified_sources'):
self._process_unified_sources(obj)
- elif isinstance(obj, BaseProgram):
- self._binaries.programs.append(obj)
+ elif isinstance(obj, Linkable):
+ if isinstance(obj.defines, Defines): # As opposed to HostDefines
+ for d in obj.defines.get_defines():
+ if d not in self._defines[obj.objdir]:
+ self._defines[obj.objdir].append(d)
+ self._defines[obj.objdir].extend(obj.lib_defines.get_defines())
+ if isinstance(obj, SimpleProgram):
+ if obj.is_unit_test:
+ if (self._dist_include_testing not in
+ self._extra_includes[obj.objdir]):
+ self._extra_includes[obj.objdir].append(
+ self._dist_include_testing)
+
+ if isinstance(obj, BaseProgram):
+ self._binaries.programs.append(obj)
+ elif isinstance(obj, SharedLibrary):
+ self._binaries.shared_libraries.append(obj)
+ return False
+
+ elif isinstance(obj, DirectoryTraversal):
+ self._envs[obj.objdir] = obj.config
+ for var in ('STL_FLAGS', 'VISIBILITY_FLAGS', 'WARNINGS_AS_ERRORS'):
+ value = obj.config.substs.get(var)
+ if value:
+ self._local_flags[obj.objdir][var] = value
return False
- elif isinstance(obj, SharedLibrary):
- self._binaries.shared_libraries.append(obj)
+ elif isinstance(obj, (Sources, GeneratedSources)):
+ # For other sources, include each source file.
+ for f in obj.files:
+ self._build_compiler_line(obj.objdir, obj.relativedir, obj.config, f,
+ obj.canonical_suffix)
+ return False
+
+ elif isinstance(obj, LocalInclude):
+ self._includes[obj.objdir].append('-I%s' % mozpath.normpath(
+ obj.path.full_path))
+ return False
+
+ elif isinstance(obj, VariablePassthru):
+ if obj.variables.get('IS_GYP_DIR'):
+ self._gyp_dirs.add(obj.objdir)
+ for var in ('MOZBUILD_CFLAGS', 'MOZBUILD_CXXFLAGS',
+ 'MOZBUILD_CMFLAGS', 'MOZBUILD_CMMFLAGS',
+ 'RTL_FLAGS', 'VISIBILITY_FLAGS'):
+ if var in obj.variables:
+ self._local_flags[obj.objdir][var] = obj.variables[var]
+ if (obj.variables.get('DISABLE_STL_WRAPPING') and
+ 'STL_FLAGS' in self._local_flags[obj.objdir]):
+ del self._local_flags[obj.objdir]['STL_FLAGS']
+ if (obj.variables.get('ALLOW_COMPILER_WARNINGS') and
+ 'WARNINGS_AS_ERRORS' in self._local_flags[obj.objdir]):
+ del self._local_flags[obj.objdir]['WARNINGS_AS_ERRORS']
return False
else:
return False
return True
def consume_finished(self):
@@ -388,16 +459,57 @@ class CommonBackend(BuildBackend):
# Write out a machine-readable file describing binaries.
with self._write_file(mozpath.join(topobjdir, 'binaries.json')) as fh:
d = {
'shared_libraries': [s.to_dict() for s in self._binaries.shared_libraries],
'programs': [p.to_dict() for p in self._binaries.programs],
}
json.dump(d, fh, sort_keys=True, indent=4)
+ # Finalize compiler command-lines by replacing deferred variables with
+ # their final values.
+ for (directory, filename), cmd in self._db.iteritems():
+ env = self._envs[directory]
+ cmd = list(cmd)
+ cmd.append(filename)
+ local_extra = list(self._extra_includes[directory])
+ if directory not in self._gyp_dirs:
+ for var in (
+ 'NSPR_CFLAGS',
+ 'NSS_CFLAGS',
+ 'MOZ_JPEG_CFLAGS',
+ 'MOZ_PNG_CFLAGS',
+ 'MOZ_ZLIB_CFLAGS',
+ 'MOZ_PIXMAN_CFLAGS',
+ ):
+ f = env.substs.get(var)
+ if f:
+ local_extra.extend(f)
+ variables = {
+ 'LOCAL_INCLUDES': self._includes[directory],
+ 'DEFINES': self._defines[directory],
+ 'EXTRA_INCLUDES': local_extra,
+ 'DIST': mozpath.join(env.topobjdir, 'dist'),
+ 'DEPTH': env.topobjdir,
+ 'MOZILLA_DIR': env.topsrcdir,
+ 'topsrcdir': env.topsrcdir,
+ 'topobjdir': env.topobjdir,
+ }
+ variables.update(self._local_flags[directory])
+ c = []
+ for a in cmd:
+ a = expand_variables(a, variables).split()
+ if not a:
+ continue
+ if isinstance(a, types.StringTypes):
+ c.append(a)
+ else:
+ c.extend(a)
+ self._db[(directory, filename)] = c
+
def _handle_webidl_collection(self, webidls):
if not webidls.all_stems():
return
bindings_dir = mozpath.join(self.environment.topobjdir, 'dom', 'bindings')
all_inputs = set(webidls.all_static_sources())
for s in webidls.all_non_static_basenames():
@@ -620,9 +732,9 @@ class CommonBackend(BuildBackend):
cmdline.append('$(WARNINGS_AS_ERRORS)')
cmdline.append('$(MOZBUILD_%s)' % self.CFLAGS[canonical_suffix])
if canonical_suffix == '.m':
append_var('OS_COMPILE_CMFLAGS')
cmdline.append('$(MOZBUILD_CMFLAGS)')
elif canonical_suffix == '.mm':
append_var('OS_COMPILE_CMMFLAGS')
cmdline.append('$(MOZBUILD_CMMFLAGS)')
- return cmdline
+ self._db[(objdir, filename)] = cmdline
--- a/python/mozbuild/mozbuild/compilation/database.py
+++ b/python/mozbuild/mozbuild/compilation/database.py
@@ -1,196 +1,76 @@
# 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 modules provides functionality for dealing with code completion.
import os
-import types
from mozbuild.compilation import util
from mozbuild.backend.common import CommonBackend
-from mozbuild.frontend.data import (
- Sources,
- GeneratedSources,
- DirectoryTraversal,
- Defines,
- Linkable,
- LocalInclude,
- VariablePassthru,
- SimpleProgram,
-)
from mozbuild.shellutil import (
quote as shell_quote,
)
-from mozbuild.util import expand_variables
-import mozpack.path as mozpath
-from collections import (
- defaultdict,
- OrderedDict,
-)
class CompileDBBackend(CommonBackend):
def _init(self):
CommonBackend._init(self)
if not util.check_top_objdir(self.environment.topobjdir):
raise Exception()
- # The database we're going to dump out to.
- self._db = OrderedDict()
-
- # The cache for per-directory flags
- self._flags = {}
-
- self._envs = {}
- self._includes = defaultdict(list)
- self._defines = defaultdict(list)
- self._local_flags = defaultdict(dict)
- self._extra_includes = defaultdict(list)
- self._gyp_dirs = set()
- self._dist_include_testing = '-I%s' % mozpath.join(
- self.environment.topobjdir, 'dist', 'include', 'testing')
-
def consume_object(self, obj):
# Those are difficult directories, that will be handled later.
if obj.relativedir in (
'build/unix/elfhack',
'build/unix/elfhack/inject',
'build/clang-plugin',
'build/clang-plugin/tests',
'security/sandbox/win/wow_helper',
'toolkit/crashreporter/google-breakpad/src/common'):
return True
- consumed = CommonBackend.consume_object(self, obj)
-
- if consumed:
- return True
-
- if isinstance(obj, DirectoryTraversal):
- self._envs[obj.objdir] = obj.config
- for var in ('STL_FLAGS', 'VISIBILITY_FLAGS', 'WARNINGS_AS_ERRORS'):
- value = obj.config.substs.get(var)
- if value:
- self._local_flags[obj.objdir][var] = value
-
- elif isinstance(obj, (Sources, GeneratedSources)):
- # For other sources, include each source file.
- for f in obj.files:
- self._build_db_line(obj.objdir, obj.relativedir, obj.config, f,
- obj.canonical_suffix)
-
- elif isinstance(obj, LocalInclude):
- self._includes[obj.objdir].append('-I%s' % mozpath.normpath(
- obj.path.full_path))
-
- elif isinstance(obj, Linkable):
- if isinstance(obj.defines, Defines): # As opposed to HostDefines
- for d in obj.defines.get_defines():
- if d not in self._defines[obj.objdir]:
- self._defines[obj.objdir].append(d)
- self._defines[obj.objdir].extend(obj.lib_defines.get_defines())
- if isinstance(obj, SimpleProgram) and obj.is_unit_test:
- if (self._dist_include_testing not in
- self._extra_includes[obj.objdir]):
- self._extra_includes[obj.objdir].append(
- self._dist_include_testing)
-
- elif isinstance(obj, VariablePassthru):
- if obj.variables.get('IS_GYP_DIR'):
- self._gyp_dirs.add(obj.objdir)
- for var in ('MOZBUILD_CFLAGS', 'MOZBUILD_CXXFLAGS',
- 'MOZBUILD_CMFLAGS', 'MOZBUILD_CMMFLAGS',
- 'RTL_FLAGS', 'VISIBILITY_FLAGS'):
- if var in obj.variables:
- self._local_flags[obj.objdir][var] = obj.variables[var]
- if (obj.variables.get('DISABLE_STL_WRAPPING') and
- 'STL_FLAGS' in self._local_flags[obj.objdir]):
- del self._local_flags[obj.objdir]['STL_FLAGS']
- if (obj.variables.get('ALLOW_COMPILER_WARNINGS') and
- 'WARNINGS_AS_ERRORS' in self._local_flags[obj.objdir]):
- del self._local_flags[obj.objdir]['WARNINGS_AS_ERRORS']
+ CommonBackend.consume_object(self, obj)
return True
def consume_finished(self):
CommonBackend.consume_finished(self)
db = []
for (directory, filename), cmd in self._db.iteritems():
- env = self._envs[directory]
- cmd = list(cmd)
- cmd.append(filename)
- local_extra = list(self._extra_includes[directory])
- if directory not in self._gyp_dirs:
- for var in (
- 'NSPR_CFLAGS',
- 'NSS_CFLAGS',
- 'MOZ_JPEG_CFLAGS',
- 'MOZ_PNG_CFLAGS',
- 'MOZ_ZLIB_CFLAGS',
- 'MOZ_PIXMAN_CFLAGS',
- ):
- f = env.substs.get(var)
- if f:
- local_extra.extend(f)
- variables = {
- 'LOCAL_INCLUDES': self._includes[directory],
- 'DEFINES': self._defines[directory],
- 'EXTRA_INCLUDES': local_extra,
- 'DIST': mozpath.join(env.topobjdir, 'dist'),
- 'DEPTH': env.topobjdir,
- 'MOZILLA_DIR': env.topsrcdir,
- 'topsrcdir': env.topsrcdir,
- 'topobjdir': env.topobjdir,
- }
- variables.update(self._local_flags[directory])
- c = []
- for a in cmd:
- a = expand_variables(a, variables).split()
- if not a:
- continue
- if isinstance(a, types.StringTypes):
- c.append(a)
- else:
- c.extend(a)
db.append({
'directory': directory,
- 'command': ' '.join(shell_quote(a) for a in c),
+ 'command': ' '.join(shell_quote(a) for a in cmd),
'file': filename,
})
import json
# Output the database (a JSON file) to objdir/compile_commands.json
outputfile = os.path.join(self.environment.topobjdir, 'compile_commands.json')
with self._write_file(outputfile) as jsonout:
json.dump(db, jsonout, indent=0)
def _process_unified_sources(self, obj):
# For unified sources, only include the unified source file.
# Note that unified sources are never used for host sources.
for f in obj.unified_source_mapping:
- self._build_db_line(obj.objdir, obj.relativedir, obj.config, f[0],
- obj.canonical_suffix)
+ self._build_compiler_line(obj.objdir, obj.relativedir, obj.config, f[0],
+ obj.canonical_suffix)
def _handle_idl_manager(self, idl_manager):
pass
def _handle_ipdl_sources(self, ipdl_dir, sorted_ipdl_sources,
unified_ipdl_cppsrcs_mapping):
for f in unified_ipdl_cppsrcs_mapping:
- self._build_db_line(ipdl_dir, None, self.environment, f[0],
- '.cpp')
+ self._build_compiler_line(ipdl_dir, None, self.environment, f[0],
+ '.cpp')
def _handle_webidl_build(self, bindings_dir, unified_source_mapping,
webidls, expected_build_output_files,
global_define_files):
for f in unified_source_mapping:
- self._build_db_line(bindings_dir, None, self.environment, f[0],
- '.cpp')
-
- def _build_db_line(self, objdir, reldir, cenv, filename, canonical_suffix):
- cmdline = self._build_compiler_line(objdir, reldir, cenv, filename, canonical_suffix)
- if cmdline:
- self._db[(objdir, filename)] = cmdline
+ self._build_compiler_line(bindings_dir, None, self.environment, f[0],
+ '.cpp')
--- a/python/mozbuild/mozbuild/test/backend/common.py
+++ b/python/mozbuild/mozbuild/test/backend/common.py
@@ -53,16 +53,18 @@ CONFIGS = defaultdict(lambda: {
},
},
'sources': {
'defines': {},
'non_global_defines': [],
'substs': {
'LIB_PREFIX': 'lib',
'LIB_SUFFIX': 'a',
+ 'CC': 'gcc',
+ 'CXX': 'g++',
},
},
'stub0': {
'defines': {
'MOZ_TRUE_1': '1',
'MOZ_TRUE_2': '1',
},
'non_global_defines': [