Bug 902619 - Write mozinfo.json as part of config.status; r=ted

There are both mechanical and logical changes in this patch.

The mechanical changes involve moving some files into the mozbuild
package.

The logical changes include move writing of mozinfo.json into
config.status (from configure.in). There were some variable assignments
being performed in configure.in. These variables were read from
writemozinfo.py. However, these variables don't appear to be necessary!
Now that mozinfo has full access to the underlying config.status data
structure, it can now access these variables directly. I verified that
every variable being assigned in configure.in had a corresponding
AC_SUBST earlier in the file.

The only variable that's a bit weird is the TOPSRCDIR and MOZCONFIG
environment variables. mozinfo continues to look in the environment for
MOZCONFIG. However TOPSRCDIR is now coming from config.status.

As part of moving the code, I also modernized the test file, cleaned up
some style, and removed some unused imports.
This commit is contained in:
Gregory Szorc
2013-08-07 23:48:41 -07:00
parent e1d2a9517e
commit b64a99c4bb
6 changed files with 298 additions and 255 deletions

View File

@@ -0,0 +1,96 @@
# 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 module produces a JSON file that provides basic build info and
# configuration metadata.
import os
import re
import json
def build_dict(config, env=os.environ):
"""
Build a dict containing data about the build configuration from
the environment.
"""
substs = config.substs
# Check that all required variables are present first.
required = ["TARGET_CPU", "OS_TARGET", "MOZ_WIDGET_TOOLKIT"]
missing = [r for r in required if r not in substs]
if missing:
raise Exception("Missing required environment variables: %s" %
', '.join(missing))
d = {}
d['topsrcdir'] = config.topsrcdir
if 'MOZCONFIG' in env:
mozconfig = env["MOZCONFIG"]
mozconfig = os.path.join(config.topsrcdir, mozconfig)
d['mozconfig'] = os.path.normpath(mozconfig)
# os
o = substs["OS_TARGET"]
known_os = {"Linux": "linux",
"WINNT": "win",
"Darwin": "mac",
"Android": "b2g" if substs["MOZ_WIDGET_TOOLKIT"] == "gonk" else "android"}
if o in known_os:
d["os"] = known_os[o]
else:
# Allow unknown values, just lowercase them.
d["os"] = o.lower()
# Widget toolkit, just pass the value directly through.
d["toolkit"] = substs["MOZ_WIDGET_TOOLKIT"]
# Application name
if 'MOZ_APP_NAME' in substs:
d["appname"] = substs["MOZ_APP_NAME"]
# processor
p = substs["TARGET_CPU"]
# for universal mac builds, put in a special value
if d["os"] == "mac" and "UNIVERSAL_BINARY" in substs and substs["UNIVERSAL_BINARY"] == "1":
p = "universal-x86-x86_64"
else:
# do some slight massaging for some values
#TODO: retain specific values in case someone wants them?
if p.startswith("arm"):
p = "arm"
elif re.match("i[3-9]86", p):
p = "x86"
d["processor"] = p
# hardcoded list of 64-bit CPUs
if p in ["x86_64", "ppc64"]:
d["bits"] = 64
# hardcoded list of known 32-bit CPUs
elif p in ["x86", "arm", "ppc"]:
d["bits"] = 32
# other CPUs will wind up with unknown bits
d['debug'] = substs.get('MOZ_DEBUG') == '1'
d['crashreporter'] = substs.get('MOZ_CRASHREPORTER') == '1'
d['asan'] = substs.get('MOZ_ASAN') == '1'
d['tests_enabled'] = substs.get('ENABLE_TESTS') == "1"
d['bin_suffix'] = substs.get('BIN_SUFFIX', '')
return d
def write_mozinfo(file, config, env=os.environ):
"""Write JSON data about the configuration specified in config and an
environment variable dict to |file|, which may be a filename or file-like
object.
See build_dict for information about what environment variables are used,
and what keys are produced.
"""
build_conf = build_dict(config, env)
if isinstance(file, basestring):
with open(file, "w") as f:
json.dump(build_conf, f)
else:
json.dump(build_conf, file)

View File

@@ -0,0 +1,271 @@
#!/usr/bin/env 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/.
import json
import os
import tempfile
import unittest
from StringIO import StringIO
import mozunit
from mozbuild.backend.configenvironment import ConfigEnvironment
from mozbuild.mozinfo import (
build_dict,
write_mozinfo,
)
class Base(object):
def _config(self, substs={}):
d = os.path.dirname(__file__)
return ConfigEnvironment(d, d, substs=substs)
class TestBuildDict(unittest.TestCase, Base):
def test_missing(self):
"""
Test that missing required values raises.
"""
with self.assertRaises(Exception):
build_dict(self._config(substs=dict(OS_TARGET='foo')))
with self.assertRaises(Exception):
build_dict(self._config(substs=dict(TARGET_CPU='foo')))
with self.assertRaises(Exception):
build_dict(self._config(substs=dict(MOZ_WIDGET_TOOLKIT='foo')))
def test_win(self):
d = build_dict(self._config(dict(
OS_TARGET='WINNT',
TARGET_CPU='i386',
MOZ_WIDGET_TOOLKIT='windows',
)))
self.assertEqual('win', d['os'])
self.assertEqual('x86', d['processor'])
self.assertEqual('windows', d['toolkit'])
self.assertEqual(32, d['bits'])
def test_linux(self):
d = build_dict(self._config(dict(
OS_TARGET='Linux',
TARGET_CPU='i386',
MOZ_WIDGET_TOOLKIT='gtk2',
)))
self.assertEqual('linux', d['os'])
self.assertEqual('x86', d['processor'])
self.assertEqual('gtk2', d['toolkit'])
self.assertEqual(32, d['bits'])
d = build_dict(self._config(dict(
OS_TARGET='Linux',
TARGET_CPU='x86_64',
MOZ_WIDGET_TOOLKIT='gtk2',
)))
self.assertEqual('linux', d['os'])
self.assertEqual('x86_64', d['processor'])
self.assertEqual('gtk2', d['toolkit'])
self.assertEqual(64, d['bits'])
def test_mac(self):
d = build_dict(self._config(dict(
OS_TARGET='Darwin',
TARGET_CPU='i386',
MOZ_WIDGET_TOOLKIT='cocoa',
)))
self.assertEqual('mac', d['os'])
self.assertEqual('x86', d['processor'])
self.assertEqual('cocoa', d['toolkit'])
self.assertEqual(32, d['bits'])
d = build_dict(self._config(dict(
OS_TARGET='Darwin',
TARGET_CPU='x86_64',
MOZ_WIDGET_TOOLKIT='cocoa',
)))
self.assertEqual('mac', d['os'])
self.assertEqual('x86_64', d['processor'])
self.assertEqual('cocoa', d['toolkit'])
self.assertEqual(64, d['bits'])
def test_mac_universal(self):
d = build_dict(self._config(dict(
OS_TARGET='Darwin',
TARGET_CPU='i386',
MOZ_WIDGET_TOOLKIT='cocoa',
UNIVERSAL_BINARY='1',
)))
self.assertEqual('mac', d['os'])
self.assertEqual('universal-x86-x86_64', d['processor'])
self.assertEqual('cocoa', d['toolkit'])
self.assertFalse('bits' in d)
d = build_dict(self._config(dict(
OS_TARGET='Darwin',
TARGET_CPU='x86_64',
MOZ_WIDGET_TOOLKIT='cocoa',
UNIVERSAL_BINARY='1',
)))
self.assertEqual('mac', d['os'])
self.assertEqual('universal-x86-x86_64', d['processor'])
self.assertEqual('cocoa', d['toolkit'])
self.assertFalse('bits' in d)
def test_android(self):
d = build_dict(self._config(dict(
OS_TARGET='Android',
TARGET_CPU='arm',
MOZ_WIDGET_TOOLKIT='android',
)))
self.assertEqual('android', d['os'])
self.assertEqual('arm', d['processor'])
self.assertEqual('android', d['toolkit'])
self.assertEqual(32, d['bits'])
def test_x86(self):
"""
Test that various i?86 values => x86.
"""
d = build_dict(self._config(dict(
OS_TARGET='WINNT',
TARGET_CPU='i486',
MOZ_WIDGET_TOOLKIT='windows',
)))
self.assertEqual('x86', d['processor'])
d = build_dict(self._config(dict(
OS_TARGET='WINNT',
TARGET_CPU='i686',
MOZ_WIDGET_TOOLKIT='windows',
)))
self.assertEqual('x86', d['processor'])
def test_arm(self):
"""
Test that all arm CPU architectures => arm.
"""
d = build_dict(self._config(dict(
OS_TARGET='Linux',
TARGET_CPU='arm',
MOZ_WIDGET_TOOLKIT='gtk2',
)))
self.assertEqual('arm', d['processor'])
d = build_dict(self._config(dict(
OS_TARGET='Linux',
TARGET_CPU='armv7',
MOZ_WIDGET_TOOLKIT='gtk2',
)))
self.assertEqual('arm', d['processor'])
def test_unknown(self):
"""
Test that unknown values pass through okay.
"""
d = build_dict(self._config(dict(
OS_TARGET='RandOS',
TARGET_CPU='cptwo',
MOZ_WIDGET_TOOLKIT='foobar',
)))
self.assertEqual("randos", d["os"])
self.assertEqual("cptwo", d["processor"])
self.assertEqual("foobar", d["toolkit"])
# unknown CPUs should not get a bits value
self.assertFalse("bits" in d)
def test_debug(self):
"""
Test that debug values are properly detected.
"""
d = build_dict(self._config(dict(
OS_TARGET='Linux',
TARGET_CPU='i386',
MOZ_WIDGET_TOOLKIT='gtk2',
)))
self.assertEqual(False, d['debug'])
d = build_dict(self._config(dict(
OS_TARGET='Linux',
TARGET_CPU='i386',
MOZ_WIDGET_TOOLKIT='gtk2',
MOZ_DEBUG='1',
)))
self.assertEqual(True, d['debug'])
def test_crashreporter(self):
"""
Test that crashreporter values are properly detected.
"""
d = build_dict(self._config(dict(
OS_TARGET='Linux',
TARGET_CPU='i386',
MOZ_WIDGET_TOOLKIT='gtk2',
)))
self.assertEqual(False, d['crashreporter'])
d = build_dict(self._config(dict(
OS_TARGET='Linux',
TARGET_CPU='i386',
MOZ_WIDGET_TOOLKIT='gtk2',
MOZ_CRASHREPORTER='1',
)))
self.assertEqual(True, d['crashreporter'])
class TestWriteMozinfo(unittest.TestCase, Base):
"""
Test the write_mozinfo function.
"""
def setUp(self):
fd, self.f = tempfile.mkstemp()
os.close(fd)
def tearDown(self):
os.unlink(self.f)
def test_basic(self):
"""
Test that writing to a file produces correct output.
"""
c = self._config(dict(
OS_TARGET='WINNT',
TARGET_CPU='i386',
MOZ_WIDGET_TOOLKIT='windows',
))
c.topsrcdir = '/tmp'
write_mozinfo(self.f, c, {'MOZCONFIG': 'foo'})
with open(self.f) as f:
d = json.load(f)
self.assertEqual('win', d['os'])
self.assertEqual('x86', d['processor'])
self.assertEqual('windows', d['toolkit'])
self.assertEqual('/tmp', d['topsrcdir'])
self.assertEqual(os.path.normpath('/tmp/foo'), d['mozconfig'])
self.assertEqual(32, d['bits'])
def test_fileobj(self):
"""
Test that writing to a file-like object produces correct output.
"""
s = StringIO()
c = self._config(dict(
OS_TARGET='WINNT',
TARGET_CPU='i386',
MOZ_WIDGET_TOOLKIT='windows',
))
write_mozinfo(s, c)
d = json.loads(s.getvalue())
self.assertEqual('win', d['os'])
self.assertEqual('x86', d['processor'])
self.assertEqual('windows', d['toolkit'])
self.assertEqual(32, d['bits'])
if __name__ == '__main__':
mozunit.main()