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
16 from collections
.abc
import Iterable
18 base_dir
= os
.path
.abspath(os
.path
.dirname(__file__
))
19 sys
.path
.insert(0, os
.path
.join(base_dir
, "python", "mach"))
20 sys
.path
.insert(0, os
.path
.join(base_dir
, "python", "mozboot"))
21 sys
.path
.insert(0, os
.path
.join(base_dir
, "python", "mozbuild"))
22 sys
.path
.insert(0, os
.path
.join(base_dir
, "third_party", "python", "packaging"))
23 sys
.path
.insert(0, os
.path
.join(base_dir
, "third_party", "python", "pyparsing"))
24 sys
.path
.insert(0, os
.path
.join(base_dir
, "third_party", "python", "six"))
25 from mozbuild
.configure
import (
29 from mozbuild
.pythonutil
import iter_modules_in_path
30 from mozbuild
.backend
.configenvironment
import PartialConfigEnvironment
31 from mozbuild
.util
import write_indented_repr
32 import mozpack
.path
as mozpath
39 if "OLD_CONFIGURE" not in os
.environ
:
40 os
.environ
["OLD_CONFIGURE"] = os
.path
.join(base_dir
, "old-configure")
42 sandbox
= ConfigureSandbox(config
, os
.environ
, argv
)
44 clobber_file
= "CLOBBER"
45 if not os
.path
.exists(clobber_file
):
46 # Simply touch the file.
47 with
open(clobber_file
, "a"):
50 if os
.environ
.get("MOZ_CONFIGURE_TRACE"):
51 sandbox
._logger
.setLevel(TRACE
)
53 sandbox
.run(os
.path
.join(os
.path
.dirname(__file__
), "moz.configure"))
58 logging
.getLogger("moz.configure").info("Creating config.status")
60 old_js_configure_substs
= config
.pop("OLD_JS_CONFIGURE_SUBSTS", None)
61 old_js_configure_defines
= config
.pop("OLD_JS_CONFIGURE_DEFINES", None)
62 if old_js_configure_substs
or old_js_configure_defines
:
63 js_config
= config
.copy()
69 if e
.errno
!= errno
.EEXIST
:
73 js_config
["OLD_CONFIGURE_SUBSTS"] = old_js_configure_substs
74 js_config
["OLD_CONFIGURE_DEFINES"] = old_js_configure_defines
75 # The build system frontend expects $objdir/js/src/config.status
76 # to have $objdir/js/src as topobjdir.
77 # We want forward slashes on all platforms.
78 js_config
["TOPOBJDIR"] += "/js/src"
79 config_status(js_config
, execute
=False)
83 return config_status(config
)
86 def check_unicode(obj
):
87 """Recursively check that all strings in the object are unicode strings."""
88 if isinstance(obj
, dict):
90 for k
, v
in six
.iteritems(obj
):
91 if not check_unicode(k
):
92 print("%s key is not unicode." % k
, file=sys
.stderr
)
94 elif not check_unicode(v
):
95 print("%s value is not unicode." % k
, file=sys
.stderr
)
98 if isinstance(obj
, bytes
):
100 if isinstance(obj
, six
.text_type
):
102 if isinstance(obj
, Iterable
):
103 return all(check_unicode(o
) for o
in obj
)
107 def config_status(config
, execute
=True):
108 # Sanitize config data to feed config.status
109 # Ideally, all the backend and frontend code would handle the booleans, but
110 # there are so many things involved, that it's easier to keep config.status
112 def sanitize_config(v
):
117 # Serialize types that look like lists and tuples as lists.
118 if not isinstance(v
, (bytes
, six
.text_type
, dict)) and isinstance(v
, Iterable
):
122 sanitized_config
= {}
123 sanitized_config
["substs"] = {
124 k
: sanitize_config(v
)
125 for k
, v
in six
.iteritems(config
)
131 "CONFIG_STATUS_DEPS",
132 "OLD_CONFIGURE_SUBSTS",
133 "OLD_CONFIGURE_DEFINES",
136 for k
, v
in config
["OLD_CONFIGURE_SUBSTS"]:
137 sanitized_config
["substs"][k
] = sanitize_config(v
)
138 sanitized_config
["defines"] = {
139 k
: sanitize_config(v
) for k
, v
in six
.iteritems(config
["DEFINES"])
141 for k
, v
in config
["OLD_CONFIGURE_DEFINES"]:
142 sanitized_config
["defines"][k
] = sanitize_config(v
)
143 sanitized_config
["topsrcdir"] = config
["TOPSRCDIR"]
144 sanitized_config
["topobjdir"] = config
["TOPOBJDIR"]
145 sanitized_config
["mozconfig"] = config
.get("MOZCONFIG")
147 if not check_unicode(sanitized_config
):
148 print("Configuration should be all unicode.", file=sys
.stderr
)
149 print("Please file a bug for the above.", file=sys
.stderr
)
152 # Some values in sanitized_config also have more complex types, such as
153 # EnumString, which using when calling config_status would currently
154 # break the build, as well as making it inconsistent with re-running
155 # config.status, for which they are normalized to plain strings via
156 # indented_repr. Likewise for non-dict non-string iterables being
157 # converted to lists.
159 if isinstance(obj
, dict):
160 return {k
: normalize(v
) for k
, v
in six
.iteritems(obj
)}
161 if isinstance(obj
, six
.text_type
):
162 return six
.text_type(obj
)
163 if isinstance(obj
, Iterable
):
164 return [normalize(o
) for o
in obj
]
167 sanitized_config
= normalize(sanitized_config
)
169 # Create config.status. Eventually, we'll want to just do the work it does
170 # here, when we're able to skip configure tests/use cached results/not rely
172 with codecs
.open("config.status", "w", "utf-8") as fh
:
178 from __future__ import unicode_literals
181 % {"python": config
["PYTHON3"]}
183 for k
, v
in sorted(six
.iteritems(sanitized_config
)):
184 fh
.write("%s = " % k
)
185 write_indented_repr(fh
, v
)
187 "__all__ = ['topobjdir', 'topsrcdir', 'defines', " "'substs', 'mozconfig']"
194 if __name__ == '__main__':
195 from mozbuild.config_status import config_status
196 args = dict([(name, globals()[name]) for name in __all__])
197 config_status(**args)
202 partial_config
= PartialConfigEnvironment(config
["TOPOBJDIR"])
203 partial_config
.write_vars(sanitized_config
)
205 # Write out a file so the build backend knows to re-run configure when
206 # relevant Python changes.
207 with io
.open("config_status_deps.in", "w", encoding
="utf-8", newline
="\n") as fh
:
210 config
["CONFIG_STATUS_DEPS"],
211 iter_modules_in_path(config
["TOPOBJDIR"], config
["TOPSRCDIR"]),
214 fh
.write("%s\n" % mozpath
.normpath(f
))
216 # Other things than us are going to run this file, so we need to give it
217 # executable permissions.
218 os
.chmod("config.status", 0o755)
220 from mozbuild
.config_status
import config_status
222 return config_status(args
=[], **sanitized_config
)
226 if __name__
== "__main__":
227 sys
.exit(main(sys
.argv
))