Skip to content

Commit

Permalink
[GR-48321] Rebuild jars if excluded list changes
Browse files Browse the repository at this point in the history
PullRequest: mx/1670
  • Loading branch information
patrick96 committed Sep 4, 2023
2 parents 33839d8 + 970372d commit c86b9e8
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 41 deletions.
2 changes: 1 addition & 1 deletion common.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"Jsonnet files should not include this file directly but use ci/common.jsonnet instead."
],

"mx_version": "6.44.2",
"mx_version": "6.45.0",

"COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet",
"jdks": {
Expand Down
2 changes: 1 addition & 1 deletion mx.py
Original file line number Diff line number Diff line change
Expand Up @@ -18783,7 +18783,7 @@ def alarm_handler(signum, frame):
abort(1, killsig=signal.SIGINT)

# The version must be updated for every PR (checked in CI) and the comment should reflect the PR's issue
version = VersionSpec("6.45.0") # multi-arch layout dirs
version = VersionSpec("6.45.1") # GR-48321 Fix JARDistribution exclude list not triggering rebuild

_mx_start_datetime = datetime.utcnow()
_last_timestamp = _mx_start_datetime
Expand Down
89 changes: 50 additions & 39 deletions mx_jardistribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ def paths_to_clean(self):
self.original_path() + _staging_dir_suffix,
self.sourcesPath + _staging_dir_suffix,
self._stripped_path(),
self.strip_mapping_file()
self.strip_mapping_file(),
self._config_save_file(),
]
jdk = mx.get_jdk(tag='default')
if jdk.javaCompliance >= '9':
Expand Down Expand Up @@ -323,19 +324,16 @@ def make_archive(self, javac_daemon=None):
latest_bin_archive = join(self.suite.get_output_root(False, False), "dists", os.path.basename(bin_archive.path))
_stage_file_impl(bin_archive.path, latest_bin_archive)

with mx.open(self._config_save_file(), 'w') as fp:
fp.write(self._config_as_json())

self.notify_updated()
compliance = self._compliance_for_build()
if compliance is not None and compliance >= '9':
jdk = mx.get_jdk(compliance)
jmd = mx.make_java_module(self, jdk, stager.bin_archive, javac_daemon=javac_daemon)
if jmd:
setattr(self, '.javaModule', jmd)
mi_file = self._module_info_save_file()
with mx.open(mi_file, 'w') as fp:
fp.write(self._module_info_as_json())
dependency_file = self._jmod_build_jdk_dependency_file()
with mx.open(dependency_file, 'w') as fp:
fp.write(jdk.home)

if self.is_stripped():
self.strip_jar()
Expand Down Expand Up @@ -570,26 +568,44 @@ def getArchivableResults(self, use_relpath=True, single=False):
if self.is_stripped():
yield self.strip_mapping_file(), self.default_filename() + JARDistribution._strip_map_file_suffix

def _jmod_build_jdk_dependency_file(self):
def _config_save_file(self) -> str:
"""
Gets the path to the file recording the JAVA_HOME of the JDK last used to
build the modular jar for this distribution.
Gets the path to the file saving :meth:`_config_as_json`.
"""
return self.original_path() + '.jdk'
return self.original_path() + ".json"

def _module_info_save_file(self):
def _config_as_json(self) -> str:
"""
Gets the path to the file saving `_module_info_as_json()`.
Creates a sorted json dump of attributes that trigger a rebuild when they're changed (see :meth:`needsUpdate`).
"""
return self.original_path() + '.module-info'
config = {}

def add_attribute(key, value):
"""
Adds an attribute to the config dict and makes sure no entry is
overwritten, because otherwise attributes are ignored when checking
for updated.
"""
assert key not in config, f"Duplicate value in distribution config: {key}"
config[key] = value

# The `exclude` list can change the jar file contents and needs to trigger a rebuild
add_attribute("excludedLibs", list(map(str, self.excludedLibs)))

compliance = self._compliance_for_build()
if compliance is not None and compliance >= '9':
if mx.get_java_module_info(self):
# Module info change triggers a rebuild.
for name in dir(self):
if name == 'moduleInfo' or name.startswith('moduleInfo:'):
add_attribute(name, getattr(self, name))

# The jmod file needs to be rebuilt if a different JDK was used previously
jdk = mx.get_jdk(compliance)
add_attribute("jdk", str(jdk.home))

def _module_info_as_json(self):
"""
Gets the moduleInfo attribute(s) as sorted json.
"""
import json
module_infos = {name:getattr(self, name) for name in dir(self) if name == 'moduleInfo' or name.startswith('moduleInfo:')}
return json.dumps(module_infos, sort_keys=True, indent=2)
return json.dumps(config, sort_keys=True, indent=2)

def needsUpdate(self, newestInput):
res = mx._needsUpdate(newestInput, self.path)
Expand Down Expand Up @@ -619,31 +635,26 @@ def needsUpdate(self, newestInput):
res = mx._needsUpdate(self.original_path(), pickle_path)
if res:
return res
jdk = mx.get_jdk(compliance)

# Rebuild if module info changed
mi_file = self._module_info_save_file()
if exists(mi_file):
module_info = self._module_info_as_json()
with mx.open(mi_file) as fp:
saved_module_info = fp.read()
if module_info != saved_module_info:
import difflib
mx.log(f'{self} module info changed:' + os.linesep + ''.join(difflib.unified_diff(saved_module_info.splitlines(1), module_info.splitlines(1))))
return 'module-info changed'

# Rebuild the jmod file if different JDK used previously
dependency_file = self._jmod_build_jdk_dependency_file()
if exists(dependency_file):
with mx.open(dependency_file) as fp:
last_build_jdk = fp.read()
if last_build_jdk != jdk.home:
return f'build JDK changed from {last_build_jdk} to {jdk.home}'
try:
with open(pickle_path, 'rb') as fp:
pickle.load(fp)
except ValueError as e:
return f'Bad or incompatible module pickle: {e}'

# Rebuild if the saved config file changed or doesn't exist
config_file = self._config_save_file()
if exists(config_file):
current_config = self._config_as_json()
with mx.open(config_file) as fp:
saved_config = fp.read()
if current_config != saved_config:
import difflib
mx.log(f'{self} distribution config changed:' + os.linesep + ''.join(difflib.unified_diff(saved_config.splitlines(True), current_config.splitlines(True))))
return f'{config_file} changed'
else:
return f'{config_file} does not exist'

if self.is_stripped():
previous_strip_configs = []
dependency_file = self.strip_config_dependency_file()
Expand Down

0 comments on commit c86b9e8

Please sign in to comment.