xref: /aosp_15_r20/external/angle/build/3pp_common/maven.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker# Copyright 2024 The Chromium Authors
2*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
3*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file.
4*8975f5c5SAndroid Build Coastguard Worker"""The fetch.py and install.py helpers for a 3pp Maven module."""
5*8975f5c5SAndroid Build Coastguard Worker
6*8975f5c5SAndroid Build Coastguard Workerimport os
7*8975f5c5SAndroid Build Coastguard Workerimport pathlib
8*8975f5c5SAndroid Build Coastguard Workerimport re
9*8975f5c5SAndroid Build Coastguard Workerimport shutil
10*8975f5c5SAndroid Build Coastguard Workerimport subprocess
11*8975f5c5SAndroid Build Coastguard Workerimport urllib.request
12*8975f5c5SAndroid Build Coastguard Worker
13*8975f5c5SAndroid Build Coastguard Workerimport common
14*8975f5c5SAndroid Build Coastguard Worker
15*8975f5c5SAndroid Build Coastguard WorkerAPACHE_MAVEN_URL = 'https://repo.maven.apache.org/maven2'
16*8975f5c5SAndroid Build Coastguard Worker
17*8975f5c5SAndroid Build Coastguard Worker_POM_TEMPLATE = """\
18*8975f5c5SAndroid Build Coastguard Worker<project>
19*8975f5c5SAndroid Build Coastguard Worker  <modelVersion>4.0.0</modelVersion>
20*8975f5c5SAndroid Build Coastguard Worker  <groupId>group</groupId>
21*8975f5c5SAndroid Build Coastguard Worker  <artifactId>artifact</artifactId>
22*8975f5c5SAndroid Build Coastguard Worker  <version>1</version>
23*8975f5c5SAndroid Build Coastguard Worker  <dependencies>
24*8975f5c5SAndroid Build Coastguard Worker    <dependency>
25*8975f5c5SAndroid Build Coastguard Worker      <groupId>{group_id}</groupId>
26*8975f5c5SAndroid Build Coastguard Worker      <artifactId>{artifact_id}</artifactId>
27*8975f5c5SAndroid Build Coastguard Worker      <version>{version}</version>
28*8975f5c5SAndroid Build Coastguard Worker      <scope>runtime</scope>
29*8975f5c5SAndroid Build Coastguard Worker    </dependency>
30*8975f5c5SAndroid Build Coastguard Worker  </dependencies>
31*8975f5c5SAndroid Build Coastguard Worker  <build>
32*8975f5c5SAndroid Build Coastguard Worker    <plugins>
33*8975f5c5SAndroid Build Coastguard Worker      <plugin>
34*8975f5c5SAndroid Build Coastguard Worker        <artifactId>maven-assembly-plugin</artifactId>
35*8975f5c5SAndroid Build Coastguard Worker        <version>3.3.0</version>
36*8975f5c5SAndroid Build Coastguard Worker        <configuration>
37*8975f5c5SAndroid Build Coastguard Worker          <descriptorRefs>
38*8975f5c5SAndroid Build Coastguard Worker            <descriptorRef>jar-with-dependencies</descriptorRef>
39*8975f5c5SAndroid Build Coastguard Worker          </descriptorRefs>
40*8975f5c5SAndroid Build Coastguard Worker        </configuration>
41*8975f5c5SAndroid Build Coastguard Worker        <executions>
42*8975f5c5SAndroid Build Coastguard Worker          <execution>
43*8975f5c5SAndroid Build Coastguard Worker            <phase>package</phase>
44*8975f5c5SAndroid Build Coastguard Worker            <goals>
45*8975f5c5SAndroid Build Coastguard Worker              <goal>single</goal>
46*8975f5c5SAndroid Build Coastguard Worker            </goals>
47*8975f5c5SAndroid Build Coastguard Worker          </execution>
48*8975f5c5SAndroid Build Coastguard Worker        </executions>
49*8975f5c5SAndroid Build Coastguard Worker      </plugin>
50*8975f5c5SAndroid Build Coastguard Worker    </plugins>
51*8975f5c5SAndroid Build Coastguard Worker  </build>
52*8975f5c5SAndroid Build Coastguard Worker  <repositories>
53*8975f5c5SAndroid Build Coastguard Worker    <repository>
54*8975f5c5SAndroid Build Coastguard Worker      <id>placeholder_id</id>
55*8975f5c5SAndroid Build Coastguard Worker      <name>placeholder_name</name>
56*8975f5c5SAndroid Build Coastguard Worker      <url>{maven_url}</url>
57*8975f5c5SAndroid Build Coastguard Worker    </repository>
58*8975f5c5SAndroid Build Coastguard Worker  </repositories>
59*8975f5c5SAndroid Build Coastguard Worker</project>
60*8975f5c5SAndroid Build Coastguard Worker"""
61*8975f5c5SAndroid Build Coastguard Worker
62*8975f5c5SAndroid Build Coastguard Worker
63*8975f5c5SAndroid Build Coastguard Workerdef _detect_latest(maven_url, package):
64*8975f5c5SAndroid Build Coastguard Worker    metadata_url = '{}/{}/maven-metadata.xml'.format(
65*8975f5c5SAndroid Build Coastguard Worker        maven_url,
66*8975f5c5SAndroid Build Coastguard Worker        package.replace('.', '/').replace(':', '/'))
67*8975f5c5SAndroid Build Coastguard Worker    metadata = urllib.request.urlopen(metadata_url).read().decode('utf-8')
68*8975f5c5SAndroid Build Coastguard Worker    # Do not parse xml with the Python included parser since it is susceptible
69*8975f5c5SAndroid Build Coastguard Worker    # to maliciously crafted xmls. Only use regular expression parsing to be
70*8975f5c5SAndroid Build Coastguard Worker    # safe. RE should be enough to handle what we need to extract.
71*8975f5c5SAndroid Build Coastguard Worker    # TODO(agrieve): Use 'if m := ..." once docker image updates from Python 3.6.
72*8975f5c5SAndroid Build Coastguard Worker    m = re.search('<latest>([^<]+)</latest>', metadata)
73*8975f5c5SAndroid Build Coastguard Worker    if m:
74*8975f5c5SAndroid Build Coastguard Worker        latest = m.group(1)
75*8975f5c5SAndroid Build Coastguard Worker    else:
76*8975f5c5SAndroid Build Coastguard Worker        # If no latest info was found just hope the versions are sorted and the
77*8975f5c5SAndroid Build Coastguard Worker        # last one is the latest (as is commonly the case).
78*8975f5c5SAndroid Build Coastguard Worker        latest = re.findall('<version>([^<]+)</version>', metadata)[-1]
79*8975f5c5SAndroid Build Coastguard Worker    return latest
80*8975f5c5SAndroid Build Coastguard Worker
81*8975f5c5SAndroid Build Coastguard Worker
82*8975f5c5SAndroid Build Coastguard Workerdef _install(output_prefix,
83*8975f5c5SAndroid Build Coastguard Worker             deps_prefix,
84*8975f5c5SAndroid Build Coastguard Worker             maven_url,
85*8975f5c5SAndroid Build Coastguard Worker             package,
86*8975f5c5SAndroid Build Coastguard Worker             version,
87*8975f5c5SAndroid Build Coastguard Worker             jar_name=None,
88*8975f5c5SAndroid Build Coastguard Worker             post_process_func=None):
89*8975f5c5SAndroid Build Coastguard Worker    # Runs in a docker container.
90*8975f5c5SAndroid Build Coastguard Worker    group_id, artifact_id = package.split(':')
91*8975f5c5SAndroid Build Coastguard Worker    if not jar_name:
92*8975f5c5SAndroid Build Coastguard Worker        jar_name = f'{artifact_id}.jar'
93*8975f5c5SAndroid Build Coastguard Worker
94*8975f5c5SAndroid Build Coastguard Worker    pathlib.Path('pom.xml').write_text(
95*8975f5c5SAndroid Build Coastguard Worker        _POM_TEMPLATE.format(version=version,
96*8975f5c5SAndroid Build Coastguard Worker                             group_id=group_id,
97*8975f5c5SAndroid Build Coastguard Worker                             artifact_id=artifact_id,
98*8975f5c5SAndroid Build Coastguard Worker                             maven_url=maven_url))
99*8975f5c5SAndroid Build Coastguard Worker
100*8975f5c5SAndroid Build Coastguard Worker    # Set up JAVA_HOME for the mvn command to find the JDK.
101*8975f5c5SAndroid Build Coastguard Worker    env = os.environ.copy()
102*8975f5c5SAndroid Build Coastguard Worker    env['JAVA_HOME'] = common.path_within_checkout('third_party/jdk/current')
103*8975f5c5SAndroid Build Coastguard Worker
104*8975f5c5SAndroid Build Coastguard Worker    # Ensure that mvn works and the environment is set up correctly.
105*8975f5c5SAndroid Build Coastguard Worker    subprocess.run(['mvn', '-v'], check=True, env=env)
106*8975f5c5SAndroid Build Coastguard Worker
107*8975f5c5SAndroid Build Coastguard Worker    # Build the jar file, explicitly specify -f to reduce sources of error.
108*8975f5c5SAndroid Build Coastguard Worker    subprocess.run(['mvn', 'clean', 'assembly:single', '-f', 'pom.xml'],
109*8975f5c5SAndroid Build Coastguard Worker                   check=True,
110*8975f5c5SAndroid Build Coastguard Worker                   env=env)
111*8975f5c5SAndroid Build Coastguard Worker
112*8975f5c5SAndroid Build Coastguard Worker    src_jar_path = 'target/artifact-1-jar-with-dependencies.jar'
113*8975f5c5SAndroid Build Coastguard Worker    dst_jar_path = os.path.join(output_prefix, jar_name)
114*8975f5c5SAndroid Build Coastguard Worker    if post_process_func:
115*8975f5c5SAndroid Build Coastguard Worker        post_process_func(src_jar_path, dst_jar_path)
116*8975f5c5SAndroid Build Coastguard Worker    else:
117*8975f5c5SAndroid Build Coastguard Worker        shutil.move(src_jar_path, dst_jar_path)
118*8975f5c5SAndroid Build Coastguard Worker
119*8975f5c5SAndroid Build Coastguard Worker
120*8975f5c5SAndroid Build Coastguard Workerdef main(*,
121*8975f5c5SAndroid Build Coastguard Worker         package,
122*8975f5c5SAndroid Build Coastguard Worker         jar_name=None,
123*8975f5c5SAndroid Build Coastguard Worker         maven_url='https://dl.google.com/android/maven2',
124*8975f5c5SAndroid Build Coastguard Worker         post_process_func=None,
125*8975f5c5SAndroid Build Coastguard Worker         version_override=None):
126*8975f5c5SAndroid Build Coastguard Worker    """3pp entry point for fetch.py.
127*8975f5c5SAndroid Build Coastguard Worker
128*8975f5c5SAndroid Build Coastguard Worker    Args:
129*8975f5c5SAndroid Build Coastguard Worker      package: E.g.: some.package:some-thing
130*8975f5c5SAndroid Build Coastguard Worker      jar_name: Name of .jar. Defaults to |some-thing|.jar
131*8975f5c5SAndroid Build Coastguard Worker      maven_url: URL of Maven repository.
132*8975f5c5SAndroid Build Coastguard Worker      post_process_func: Called to finish. Args: src_jar_path, dst_jar_path
133*8975f5c5SAndroid Build Coastguard Worker      version_override: Use this version instead of the latest one.
134*8975f5c5SAndroid Build Coastguard Worker    """
135*8975f5c5SAndroid Build Coastguard Worker
136*8975f5c5SAndroid Build Coastguard Worker    def do_latest():
137*8975f5c5SAndroid Build Coastguard Worker        return version_override or _detect_latest(maven_url, package)
138*8975f5c5SAndroid Build Coastguard Worker
139*8975f5c5SAndroid Build Coastguard Worker    def do_install(args):
140*8975f5c5SAndroid Build Coastguard Worker        _install(args.output_prefix, args.deps_prefix, maven_url, package,
141*8975f5c5SAndroid Build Coastguard Worker                 args.version, jar_name, post_process_func)
142*8975f5c5SAndroid Build Coastguard Worker
143*8975f5c5SAndroid Build Coastguard Worker    common.main(do_latest=do_latest,
144*8975f5c5SAndroid Build Coastguard Worker                do_install=do_install,
145*8975f5c5SAndroid Build Coastguard Worker                runtime_deps=['//third_party/jdk/current'])
146