1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 from __future__
import absolute_import
, print_function
, unicode_literals
18 from collections
.abc
import Iterable
20 from collections
import Iterable
23 base_dir
= os
.path
.abspath(os
.path
.dirname(__file__
))
24 sys
.path
.insert(0, os
.path
.join(base_dir
, "python", "mach"))
25 sys
.path
.insert(0, os
.path
.join(base_dir
, "python", "mozboot"))
26 sys
.path
.insert(0, os
.path
.join(base_dir
, "python", "mozbuild"))
27 sys
.path
.insert(0, os
.path
.join(base_dir
, "third_party", "python", "packaging"))
28 sys
.path
.insert(0, os
.path
.join(base_dir
, "third_party", "python", "pyparsing"))
29 sys
.path
.insert(0, os
.path
.join(base_dir
, "third_party", "python", "six"))
30 from mozbuild
.configure
import (
34 from mozbuild
.pythonutil
import iter_modules_in_path
35 from mozbuild
.backend
.configenvironment
import PartialConfigEnvironment
36 from mozbuild
.util
import write_indented_repr
37 import mozpack
.path
as mozpath
44 if "OLD_CONFIGURE" not in os
.environ
:
45 os
.environ
["OLD_CONFIGURE"] = os
.path
.join(base_dir
, "old-configure")
47 sandbox
= ConfigureSandbox(config
, os
.environ
, argv
)
49 clobber_file
= "CLOBBER"
50 if not os
.path
.exists(clobber_file
):
51 # Simply touch the file.
52 with
open(clobber_file
, "a"):
55 if os
.environ
.get("MOZ_CONFIGURE_TRACE"):
56 sandbox
._logger
.setLevel(TRACE
)
58 sandbox
.run(os
.path
.join(os
.path
.dirname(__file__
), "moz.configure"))
63 logging
.getLogger("moz.configure").info("Creating config.status")
65 old_js_configure_substs
= config
.pop("OLD_JS_CONFIGURE_SUBSTS", None)
66 old_js_configure_defines
= config
.pop("OLD_JS_CONFIGURE_DEFINES", None)
67 if old_js_configure_substs
or old_js_configure_defines
:
68 js_config
= config
.copy()
74 if e
.errno
!= errno
.EEXIST
:
78 js_config
["OLD_CONFIGURE_SUBSTS"] = old_js_configure_substs
79 js_config
["OLD_CONFIGURE_DEFINES"] = old_js_configure_defines
80 # The build system frontend expects $objdir/js/src/config.status
81 # to have $objdir/js/src as topobjdir.
82 # We want forward slashes on all platforms.
83 js_config
["TOPOBJDIR"] += "/js/src"
84 config_status(js_config
, execute
=False)
88 return config_status(config
)
91 def check_unicode(obj
):
92 """Recursively check that all strings in the object are unicode strings."""
93 if isinstance(obj
, dict):
95 for k
, v
in six
.iteritems(obj
):
96 if not check_unicode(k
):
97 print("%s key is not unicode." % k
, file=sys
.stderr
)
99 elif not check_unicode(v
):
100 print("%s value is not unicode." % k
, file=sys
.stderr
)
103 if isinstance(obj
, bytes
):
105 if isinstance(obj
, six
.text_type
):
107 if isinstance(obj
, Iterable
):
108 return all(check_unicode(o
) for o
in obj
)
112 def config_status(config
, execute
=True):
113 # Sanitize config data to feed config.status
114 # Ideally, all the backend and frontend code would handle the booleans, but
115 # there are so many things involved, that it's easier to keep config.status
117 def sanitize_config(v
):
122 # Serialize types that look like lists and tuples as lists.
123 if not isinstance(v
, (bytes
, six
.text_type
, dict)) and isinstance(v
, Iterable
):
127 sanitized_config
= {}
128 sanitized_config
["substs"] = {
129 k
: sanitize_config(v
)
130 for k
, v
in six
.iteritems(config
)
136 "CONFIG_STATUS_DEPS",
137 "OLD_CONFIGURE_SUBSTS",
138 "OLD_CONFIGURE_DEFINES",
141 for k
, v
in config
["OLD_CONFIGURE_SUBSTS"]:
142 sanitized_config
["substs"][k
] = sanitize_config(v
)
143 sanitized_config
["defines"] = {
144 k
: sanitize_config(v
) for k
, v
in six
.iteritems(config
["DEFINES"])
146 for k
, v
in config
["OLD_CONFIGURE_DEFINES"]:
147 sanitized_config
["defines"][k
] = sanitize_config(v
)
148 sanitized_config
["topsrcdir"] = config
["TOPSRCDIR"]
149 sanitized_config
["topobjdir"] = config
["TOPOBJDIR"]
150 sanitized_config
["mozconfig"] = config
.get("MOZCONFIG")
152 if not check_unicode(sanitized_config
):
153 print("Configuration should be all unicode.", file=sys
.stderr
)
154 print("Please file a bug for the above.", file=sys
.stderr
)
157 # Some values in sanitized_config also have more complex types, such as
158 # EnumString, which using when calling config_status would currently
159 # break the build, as well as making it inconsistent with re-running
160 # config.status, for which they are normalized to plain strings via
161 # indented_repr. Likewise for non-dict non-string iterables being
162 # converted to lists.
164 if isinstance(obj
, dict):
165 return {k
: normalize(v
) for k
, v
in six
.iteritems(obj
)}
166 if isinstance(obj
, six
.text_type
):
167 return six
.text_type(obj
)
168 if isinstance(obj
, Iterable
):
169 return [normalize(o
) for o
in obj
]
172 sanitized_config
= normalize(sanitized_config
)
174 # Create config.status. Eventually, we'll want to just do the work it does
175 # here, when we're able to skip configure tests/use cached results/not rely
177 with codecs
.open("config.status", "w", "utf-8") as fh
:
183 from __future__ import unicode_literals
186 % {"python": config
["PYTHON3"]}
188 for k
, v
in sorted(six
.iteritems(sanitized_config
)):
189 fh
.write("%s = " % k
)
190 write_indented_repr(fh
, v
)
192 "__all__ = ['topobjdir', 'topsrcdir', 'defines', " "'substs', 'mozconfig']"
199 if __name__ == '__main__':
200 from mozbuild.config_status import config_status
201 args = dict([(name, globals()[name]) for name in __all__])
202 config_status(**args)
207 partial_config
= PartialConfigEnvironment(config
["TOPOBJDIR"])
208 partial_config
.write_vars(sanitized_config
)
210 # Write out a file so the build backend knows to re-run configure when
211 # relevant Python changes.
212 with io
.open("config_status_deps.in", "w", encoding
="utf-8", newline
="\n") as fh
:
215 config
["CONFIG_STATUS_DEPS"],
216 iter_modules_in_path(config
["TOPOBJDIR"], config
["TOPSRCDIR"]),
219 fh
.write("%s\n" % mozpath
.normpath(f
))
221 # Other things than us are going to run this file, so we need to give it
222 # executable permissions.
223 os
.chmod("config.status", 0o755)
225 from mozbuild
.config_status
import config_status
227 return config_status(args
=[], **sanitized_config
)
231 if __name__
== "__main__":
232 sys
.exit(main(sys
.argv
))