deleted file mode 100644
--- a/config/external/sqlite/Makefile.in
+++ /dev/null
@@ -1,5 +0,0 @@
-# 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/.
-
-LIB_IS_C_ONLY = 1
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -1155,16 +1155,18 @@ class RecursiveMakeBackend(CommonBackend
if libdef.variant == libdef.COMPONENT:
backend_file.write('IS_COMPONENT := 1\n')
if libdef.soname:
backend_file.write('DSO_SONAME := %s\n' % libdef.soname)
if libdef.is_sdk:
backend_file.write('SDK_LIBRARY := %s\n' % libdef.import_name)
if libdef.symbols_file:
backend_file.write('SYMBOLS_FILE := %s\n' % libdef.symbols_file)
+ if not libdef.cxx_link:
+ backend_file.write('LIB_IS_C_ONLY := 1\n')
def _process_static_library(self, libdef, backend_file):
backend_file.write_once('LIBRARY_NAME := %s\n' % libdef.basename)
backend_file.write('FORCE_STATIC_LIB := 1\n')
backend_file.write('REAL_LIBRARY := %s\n' % libdef.lib_name)
if libdef.is_sdk:
backend_file.write('SDK_LIBRARY := %s\n' % libdef.import_name)
if libdef.no_expand_lib:
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -308,35 +308,39 @@ class ExampleWebIDLInterface(ContextDeri
class LinkageWrongKindError(Exception):
"""Error thrown when trying to link objects of the wrong kind"""
class Linkable(ContextDerived):
"""Generic context derived container object for programs and libraries"""
__slots__ = (
+ 'cxx_link',
'lib_defines',
'linked_libraries',
'linked_system_libs',
)
def __init__(self, context):
ContextDerived.__init__(self, context)
+ self.cxx_link = False
self.linked_libraries = []
self.linked_system_libs = []
self.lib_defines = Defines(context, {})
def link_library(self, obj):
assert isinstance(obj, BaseLibrary)
if isinstance(obj, SharedLibrary) and obj.variant == obj.COMPONENT:
raise LinkageWrongKindError(
'Linkable.link_library() does not take components.')
if obj.KIND != self.KIND:
raise LinkageWrongKindError('%s != %s' % (obj.KIND, self.KIND))
self.linked_libraries.append(obj)
+ if obj.cxx_link:
+ self.cxx_link = True
obj.refs.append(self)
def link_system_library(self, lib):
# The '$' check is here as a special temporary rule, allowing the
# inherited use of make variables, most notably in TK_LIBS.
if not lib.startswith('$') and not lib.startswith('-'):
if self.config.substs.get('GNU_CC'):
lib = '-l%s' % lib
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -490,59 +490,65 @@ class TreeMetadataEmitter(LoggingMixin):
'crate-type %s is not permitted for %s' % (crate_type, libname),
context)
self._verify_local_paths(context, context.relsrcdir, config)
return RustLibrary(context, libname, cargo_file, crate_type, **static_args)
def _handle_linkables(self, context, passthru, generated_files):
- has_linkables = False
+ linkables = []
+ host_linkables = []
+ def add_program(prog, var):
+ if var.startswith('HOST_'):
+ host_linkables.append(prog)
+ else:
+ linkables.append(prog)
for kind, cls in [('PROGRAM', Program), ('HOST_PROGRAM', HostProgram)]:
program = context.get(kind)
if program:
if program in self._binaries:
raise SandboxValidationError(
'Cannot use "%s" as %s name, '
'because it is already used in %s' % (program, kind,
self._binaries[program].relativedir), context)
self._binaries[program] = cls(context, program)
self._linkage.append((context, self._binaries[program],
kind.replace('PROGRAM', 'USE_LIBS')))
- has_linkables = True
+ add_program(self._binaries[program], kind)
for kind, cls in [
('SIMPLE_PROGRAMS', SimpleProgram),
('CPP_UNIT_TESTS', SimpleProgram),
('HOST_SIMPLE_PROGRAMS', HostSimpleProgram)]:
for program in context[kind]:
if program in self._binaries:
raise SandboxValidationError(
'Cannot use "%s" in %s, '
'because it is already used in %s' % (program, kind,
self._binaries[program].relativedir), context)
self._binaries[program] = cls(context, program,
is_unit_test=kind == 'CPP_UNIT_TESTS')
self._linkage.append((context, self._binaries[program],
'HOST_USE_LIBS' if kind == 'HOST_SIMPLE_PROGRAMS'
else 'USE_LIBS'))
- has_linkables = True
+ add_program(self._binaries[program], kind)
host_libname = context.get('HOST_LIBRARY_NAME')
libname = context.get('LIBRARY_NAME')
if host_libname:
if host_libname == libname:
raise SandboxValidationError('LIBRARY_NAME and '
'HOST_LIBRARY_NAME must have a different value', context)
lib = HostLibrary(context, host_libname)
self._libs[host_libname].append(lib)
self._linkage.append((context, lib, 'HOST_USE_LIBS'))
- has_linkables = True
+ host_linkables.append(lib)
final_lib = context.get('FINAL_LIBRARY')
if not libname and final_lib:
# If no LIBRARY_NAME is given, create one.
libname = context.relsrcdir.replace('/', '_')
static_lib = context.get('FORCE_STATIC_LIB')
shared_lib = context.get('FORCE_SHARED_LIB')
@@ -679,17 +685,17 @@ class TreeMetadataEmitter(LoggingMixin):
'(resolved to %s)' % (symbols_file,
symbols_file.full_path), context)
shared_args['symbols_file'] = True
if shared_lib:
lib = SharedLibrary(context, libname, **shared_args)
self._libs[libname].append(lib)
self._linkage.append((context, lib, 'USE_LIBS'))
- has_linkables = True
+ linkables.append(lib)
generated_files.add(lib.lib_name)
if is_component and not context['NO_COMPONENTS_MANIFEST']:
yield ChromeManifestEntry(context,
'components/components.manifest',
ManifestBinaryComponent('components', lib.lib_name))
if symbols_file:
script = mozpath.join(
mozpath.dirname(mozpath.dirname(__file__)),
@@ -703,40 +709,39 @@ class TreeMetadataEmitter(LoggingMixin):
if static_lib:
is_rust_library = context.get('IS_RUST_LIBRARY')
if is_rust_library:
lib = self._rust_library(context, libname, static_args)
else:
lib = StaticLibrary(context, libname, **static_args)
self._libs[libname].append(lib)
self._linkage.append((context, lib, 'USE_LIBS'))
+ linkables.append(lib)
# Multiple staticlibs for a library means multiple copies
# of the Rust runtime, which will result in linking errors
# later on.
if is_rust_library:
staticlibs = [l for l in self._libs[libname]
if isinstance(l, RustLibrary) and l.crate_type == 'staticlib']
if len(staticlibs) > 1:
raise SandboxValidationError(
'Cannot have multiple Rust staticlibs in %s: %s' % (libname, ', '.join(l.basename for l in staticlibs)),
context)
- has_linkables = True
-
if lib_defines:
if not libname:
raise SandboxValidationError('LIBRARY_DEFINES needs a '
'LIBRARY_NAME to take effect', context)
lib.lib_defines.update(lib_defines)
# Only emit sources if we have linkables defined in the same context.
# Note the linkables are not emitted in this function, but much later,
# after aggregation (because of e.g. USE_LIBS processing).
- if not has_linkables:
+ if not (linkables or host_linkables):
return
sources = defaultdict(list)
gen_sources = defaultdict(list)
all_flags = {}
for symbol in ('SOURCES', 'HOST_SOURCES', 'UNIFIED_SOURCES'):
srcs = sources[symbol]
gen_srcs = gen_sources[symbol]
@@ -801,16 +806,20 @@ class TreeMetadataEmitter(LoggingMixin):
# A map from moz.build variables to the canonical suffixes of file
# kinds that can be listed therein.
all_suffixes = list(suffix_map.keys())
varmap = dict(
SOURCES=(Sources, GeneratedSources, all_suffixes),
HOST_SOURCES=(HostSources, None, ['.c', '.mm', '.cpp']),
UNIFIED_SOURCES=(UnifiedSources, None, ['.c', '.mm', '.cpp']),
)
+ # Track whether there are any C++ source files.
+ # Technically this won't do the right thing for SIMPLE_PROGRAMS in
+ # a directory with mixed C and C++ source, but it's not that important.
+ cxx_sources = dict((k, False) for k in varmap.keys())
for variable, (klass, gen_klass, suffixes) in varmap.items():
allowed_suffixes = set().union(*[suffix_map[s] for s in suffixes])
# First ensure that we haven't been given filetypes that we don't
# recognize.
for f in itertools.chain(sources[variable], gen_sources[variable]):
ext = mozpath.splitext(f)[1]
@@ -819,28 +828,40 @@ class TreeMetadataEmitter(LoggingMixin):
'%s has an unknown file type.' % f, context)
for srcs, cls in ((sources[variable], klass),
(gen_sources[variable], gen_klass)):
# Now sort the files to let groupby work.
sorted_files = sorted(srcs, key=canonical_suffix_for_file)
for canonical_suffix, files in itertools.groupby(
sorted_files, canonical_suffix_for_file):
+ if canonical_suffix in ('.cpp', '.mm'):
+ cxx_sources[variable] = True
arglist = [context, list(files), canonical_suffix]
if (variable.startswith('UNIFIED_') and
'FILES_PER_UNIFIED_FILE' in context):
arglist.append(context['FILES_PER_UNIFIED_FILE'])
obj = cls(*arglist)
yield obj
for f, flags in all_flags.iteritems():
if flags.flags:
ext = mozpath.splitext(f)[1]
yield PerSourceFlag(context, f, flags.flags)
+ # If there are any C++ sources, set all the linkables defined here
+ # to require the C++ linker.
+ for vars, linkable_items in ((('SOURCES', 'UNIFIED_SOURCES'), linkables),
+ (('HOST_SOURCES',), host_linkables)):
+ for var in vars:
+ if cxx_sources[var]:
+ for l in linkable_items:
+ l.cxx_link = True
+ break
+
def emit_from_context(self, context):
"""Convert a Context to tree metadata objects.
This is a generator of mozbuild.frontend.data.ContextDerived instances.
"""
# We only want to emit an InstallationTarget if one of the consulted
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -890,28 +890,30 @@ class TestRecursiveMakeBackend(BackendTe
+ '$(DEPTH)/dist/bin/components/components.manifest '
+ "'binary-component foo')\n",
'LIBRARY_NAME := foo\n',
'FORCE_SHARED_LIB := 1\n',
'IMPORT_LIBRARY := foo\n',
'SHARED_LIBRARY := foo\n',
'IS_COMPONENT := 1\n',
'DSO_SONAME := foo\n',
+ 'LIB_IS_C_ONLY := 1\n',
])
with open(mozpath.join(env.topobjdir, 'bar', 'backend.mk')) as fh:
lines = fh.readlines()[2:]
self.assertEqual(lines, [
'LIBRARY_NAME := bar\n',
'FORCE_SHARED_LIB := 1\n',
'IMPORT_LIBRARY := bar\n',
'SHARED_LIBRARY := bar\n',
'IS_COMPONENT := 1\n',
'DSO_SONAME := bar\n',
+ 'LIB_IS_C_ONLY := 1\n',
])
self.assertTrue(os.path.exists(mozpath.join(env.topobjdir, 'binaries.json')))
with open(mozpath.join(env.topobjdir, 'binaries.json'), 'rb') as fh:
binaries = json.load(fh)
self.assertEqual(binaries, {
'programs': [],
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/frontend/data/sources-just-c/moz.build
@@ -0,0 +1,27 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+@template
+def Library(name):
+ '''Template for libraries.'''
+ LIBRARY_NAME = name
+
+Library('dummy')
+
+SOURCES += [
+ 'd.c',
+]
+
+SOURCES += [
+ 'e.m',
+]
+
+SOURCES += [
+ 'g.S',
+]
+
+SOURCES += [
+ 'h.s',
+ 'i.asm',
+]
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/frontend/data/test-linkables-cxx-link/moz.build
@@ -0,0 +1,11 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+DIRS = ['one','two','three']
+@template
+def SharedLibrary(name):
+ LIBRARY_NAME = name
+ FORCE_SHARED_LIB = True
+
+SharedLibrary('cxx_shared')
+USE_LIBS += ['cxx_static']
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/frontend/data/test-linkables-cxx-link/one/moz.build
@@ -0,0 +1,9 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+@template
+def Library(name):
+ LIBRARY_NAME = name
+
+Library('cxx_static')
+SOURCES += ['foo.cpp']
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/frontend/data/test-linkables-cxx-link/three/moz.build
@@ -0,0 +1,5 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+SharedLibrary('just_c_shared')
+USE_LIBS += ['just_c_static']
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/frontend/data/test-linkables-cxx-link/two/moz.build
@@ -0,0 +1,9 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+@template
+def Library(name):
+ LIBRARY_NAME = name
+
+Library('just_c_static')
+SOURCES += ['foo.c']
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
@@ -827,18 +827,19 @@ class TestEmitterBasic(unittest.TestCase
defines[lib.basename] = ' '.join(lib.lib_defines.get_defines())
self.assertEqual(expected, defines)
def test_sources(self):
"""Test that SOURCES works properly."""
reader = self.reader('sources')
objs = self.read_topsrcdir(reader)
- # The last object is a Linkable, ignore it
- objs = objs[:-1]
+ # The last object is a Linkable.
+ linkable = objs.pop()
+ self.assertTrue(linkable.cxx_link)
self.assertEqual(len(objs), 6)
for o in objs:
self.assertIsInstance(o, Sources)
suffix_map = {obj.canonical_suffix: obj for obj in objs}
self.assertEqual(len(suffix_map), 6)
expected = {
@@ -850,23 +851,47 @@ class TestEmitterBasic(unittest.TestCase
'.s': ['h.s', 'i.asm'],
}
for suffix, files in expected.items():
sources = suffix_map[suffix]
self.assertEqual(
sources.files,
[mozpath.join(reader.config.topsrcdir, f) for f in files])
+ def test_sources_just_c(self):
+ """Test that a linkable with no C++ sources doesn't have cxx_link set."""
+ reader = self.reader('sources-just-c')
+ objs = self.read_topsrcdir(reader)
+
+ # The last object is a Linkable.
+ linkable = objs.pop()
+ self.assertFalse(linkable.cxx_link)
+
+ def test_linkables_cxx_link(self):
+ """Test that linkables transitively set cxx_link properly."""
+ reader = self.reader('test-linkables-cxx-link')
+ got_results = 0
+ for obj in self.read_topsrcdir(reader):
+ if isinstance(obj, SharedLibrary):
+ if obj.basename == 'cxx_shared':
+ self.assertTrue(obj.cxx_link)
+ got_results += 1
+ elif obj.basename == 'just_c_shared':
+ self.assertFalse(obj.cxx_link)
+ got_results += 1
+ self.assertEqual(got_results, 2)
+
def test_generated_sources(self):
"""Test that GENERATED_SOURCES works properly."""
reader = self.reader('generated-sources')
objs = self.read_topsrcdir(reader)
- # The last object is a Linkable, ignore it
- objs = objs[:-1]
+ # The last object is a Linkable.
+ linkable = objs.pop()
+ self.assertTrue(linkable.cxx_link)
self.assertEqual(len(objs), 6)
generated_sources = [o for o in objs if isinstance(o, GeneratedSources)]
self.assertEqual(len(generated_sources), 6)
suffix_map = {obj.canonical_suffix: obj for obj in generated_sources}
self.assertEqual(len(suffix_map), 6)
@@ -884,18 +909,19 @@ class TestEmitterBasic(unittest.TestCase
sources.files,
[mozpath.join(reader.config.topobjdir, f) for f in files])
def test_host_sources(self):
"""Test that HOST_SOURCES works properly."""
reader = self.reader('host-sources')
objs = self.read_topsrcdir(reader)
- # The last object is a Linkable, ignore it
- objs = objs[:-1]
+ # The last object is a Linkable
+ linkable = objs.pop()
+ self.assertTrue(linkable.cxx_link)
self.assertEqual(len(objs), 3)
for o in objs:
self.assertIsInstance(o, HostSources)
suffix_map = {obj.canonical_suffix: obj for obj in objs}
self.assertEqual(len(suffix_map), 3)
expected = {