github.phpd.cn/thought-machine/please@v12.2.0+incompatible/src/parse/rules/java_rules.build_defs (about)

     1  """Built-in rules to compile Java code."""
     2  
     3  
     4  def java_library(name:str, srcs:list=None, src_dir:str=None, resources:list=None, resources_root:str=None,
     5                   deps:list=[], modular:bool=False, exported_deps:list=None, visibility:list=None,
     6                   test_only:bool&testonly=False, javac_flags:list&javacopts=None):
     7      """Compiles Java source to a .jar which can be collected by other rules.
     8  
     9      Args:
    10        name (str): Name of the rule
    11        srcs (list): Java source files to compile for this library
    12        src_dir (str): Directory containing Java source files to compile.
    13        resources (list): Resources to include in the .jar file
    14        resources_root (str): Root directory to treat resources relative to; ie. if we are in
    15                              //project/main/resources and resources_root is project/main then
    16                              the resources in the .jar will be in the subdirectory 'resources'.
    17        deps (list): Dependencies of this rule.
    18        modular (bool): Whether the produced file should be modular. Only supported with java 9+.
    19        exported_deps (list): Exported dependencies, ie. dependencies that other things depending on this
    20                              rule will also receive when they're compiling. This is quite important for
    21                              Java; any dependency that forms part of the public API for your classes
    22                              should be an exported dependency.
    23        visibility (list): Visibility declaration of this rule.
    24        test_only (bool): If True, this rule can only be depended on by tests.
    25        javac_flags (list): List of flags passed to javac.
    26      """
    27      if srcs and src_dir:
    28          raise ParseError('You cannot pass both srcs and src_dir to java_library')
    29      if srcs or src_dir:
    30          if resources:
    31              # Split up resources into a separate rule so we don't have to try to build them here.
    32              res_rule = java_library(
    33                  name = '_%s#res' % name,
    34                  resources = resources,
    35                  resources_root = resources_root,
    36                  test_only=test_only,
    37              )
    38              deps += [res_rule]
    39  
    40          if javac_flags:
    41              # See http://bazel.io/blog/2015/06/25/ErrorProne.html for more info about this flag;
    42              # it doesn't mean anything to us so we must filter it out.
    43              # TODO(peterebden): Push this nonsense down into the javac_worker binary so we don't have to know about it here.
    44              javac_flags = ' '.join([flag for flag in javac_flags if flag != '-extra_checks:off'])
    45          else:
    46              javac_flags = CONFIG.JAVAC_TEST_FLAGS if test_only else CONFIG.JAVAC_FLAGS
    47  
    48          javac_flags = '-encoding utf8 %s' % javac_flags
    49  
    50          if CONFIG.JAVA_RELEASE_LEVEL:
    51              javac_flags = '--release %s %s' % (CONFIG.JAVA_RELEASE_LEVEL, javac_flags)
    52          else:
    53              javac_flags = '-encoding utf8 -source %s -target %s -g %s' % (
    54                  CONFIG.JAVA_SOURCE_LEVEL,
    55                  CONFIG.JAVA_TARGET_LEVEL,
    56                  javac_flags,
    57              )
    58  
    59          if not CONFIG.JAVAC_TOOL:
    60              javac_cmd = '$(worker %s) %s %s %s' % (CONFIG.JAVAC_WORKER, javac_flags, '--modular' if modular else '', '--src_dir' if src_dir else '')
    61          else:
    62              javac_cmd = 'mkdir -p _tmp/META-INF && $TOOLS_JAVAC %s -classpath .:%s -d _tmp %s' % (
    63                  javac_flags,
    64                  r'`find $TMP_DIR -name "*.jar" | tr \\\\n :`',
    65                  '$SRCS' if srcs else '`find $SRCS -name "*.java"`',
    66              )
    67  
    68          cmd = ' && '.join([
    69              javac_cmd,
    70              'find _tmp -name "*.class" | sed -e "s|_tmp/|${PKG} |g" -e "s/\\.class/.java/g" | sort > _tmp/META-INF/please_sourcemap',
    71              'cd _tmp',
    72              '$TOOLS_JARCAT z -d -o $OUT -i .',
    73          ])
    74          return build_rule(
    75              name=name,
    76              srcs=srcs or [src_dir],
    77              deps=deps,
    78              exported_deps=exported_deps,
    79              outs=[name + '.jar'],
    80              visibility=visibility,
    81              cmd=cmd,
    82              building_description="Compiling...",
    83              requires=['java'],
    84              test_only=test_only,
    85              tools={
    86                  'javac': [CONFIG.JAVAC_TOOL or CONFIG.JAVAC_WORKER],
    87                  'jarcat': [CONFIG.JARCAT_TOOL],
    88              },
    89          )
    90      elif resources:
    91          # Can't run javac since there are no java files.
    92          if resources_root:
    93              cmd = 'cd ${PKG}/%s && $TOOL z -d -o ${OUT} -i .' % resources_root
    94          else:
    95              cmd = '$TOOL z -d -o ${OUTS} -i .'
    96          return build_rule(
    97              name=name,
    98              srcs=resources,
    99              deps=deps,
   100              exported_deps=exported_deps,
   101              outs=[name + '.jar'],
   102              visibility=visibility,
   103              cmd=cmd,
   104              building_description="Linking...",
   105              requires=['java'],
   106              test_only=test_only,
   107              tools=[CONFIG.JARCAT_TOOL],
   108          )
   109      else:
   110          # If input is only jar files (as maven_jar produces in some cases) we simply collect them
   111          # all up for other rules to use.
   112          return filegroup(
   113              name=name,
   114              deps=deps,
   115              exported_deps=exported_deps,
   116              visibility=visibility,
   117              output_is_complete=False,
   118              requires=['java'],
   119              test_only=test_only,
   120          )
   121  
   122  
   123  def java_module(name:str, srcs:list=None, src_dir:str=None, resources:list=None, resources_root:str=None,
   124                  deps:list=None, visibility:list=None, test_only:bool&testonly=False, javac_flags:list&javacopts=None):
   125      """Compiles Java source to a modular .jar which can be collected by other rules.
   126  
   127      Args:
   128        name (str): Name of the rule
   129        srcs (list): Java source files to compile for this library
   130        src_dir (str): Directory containing Java source files to compile.
   131        resources (list): Resources to include in the .jar file
   132        resources_root (str): Root directory to treat resources relative to; ie. if we are in
   133                              //project/main/resources and resources_root is project/main then
   134                              the resources in the .jar will be in the subdirectory 'resources'.
   135        deps (list): Dependencies of this rule.
   136        exported_deps (list): Exported dependencies, ie. dependencies that other things depending on this
   137                              rule will also receive when they're compiling. This is quite important for
   138                              Java; any dependency that forms part of the public API for your classes
   139                              should be an exported dependency.
   140        visibility (list): Visibility declaration of this rule.
   141        test_only (bool): If True, this rule can only be depended on by tests.
   142        javac_flags (list): List of flags passed to javac.
   143      """
   144      return java_library(name=name,
   145                          srcs=srcs,
   146                          src_dir=src_dir,
   147                          resources=resources,
   148                          resources_root=resources_root,
   149                          deps=deps,
   150                          visibility=visibility,
   151                          test_only=test_only,
   152                          javac_flags=javac_flags,
   153                          modular=True)
   154  
   155  
   156  def java_runtime_image(name:str, main_module:str, main_class:str, modules:list, out:str=None,
   157                         deps:list=[], data:list=None, visibility:list=None,
   158                         jlink_args:str='--strip-debug --compress=2'):
   159      """Assembles a set of modules into an executable java runtime image.
   160  
   161      Args:
   162        name (str): Name of the rule.
   163        main_module (str): Main module to set in the manifest. Has to be included in 'modules'.
   164        main_class (str): Main class to set in the manifest. Has to belong to 'main_module'.
   165        modules (list): Modules to be included in the runtime image.
   166        out (str): Name of the folder that contains the runtime image and the binary contained by it. Defaults to 'name'.
   167        deps (list): Dependencies of this rule.
   168        data (list): Runtime data files for this rule.
   169        visibility (list): Visibility declaration of this rule.
   170        jlink_args (str): Arguments to pass to the JVM in the run script.
   171      """
   172      if not CONFIG.JAVA_HOME:
   173          raise Exception('Java home needs to be set to link java runtime images against jmods.')
   174      if not CONFIG.JLINK_TOOL:
   175          raise Exception('A jlink tool is required to build java runtime images.')
   176      if not modules:
   177          raise Exception('You cannot assemble a java runtime image without specifying any modules.')
   178      out = out or name
   179      cmd = ("$TOOL --module-path {deps}:{java_home}/jmods " +
   180             "--add-modules {modules} --launcher {name}={main_module}/{main_class} " +
   181             "--output {out_dir} {jlink_args}").format(
   182                 deps=r'`find $TMP_DIR -name "*.jar" | tr \\\\n :`',
   183                 java_home=CONFIG.JAVA_HOME,
   184                 modules=','.join(modules),
   185                 name=name,
   186                 main_module=main_module,
   187                 main_class=main_class,
   188                 out_dir=out,
   189                 jlink_args=jlink_args)
   190  
   191      build_rule(
   192          name=name,
   193          deps=deps,
   194          data=data,
   195          outs=[out],
   196          cmd=cmd,
   197          needs_transitive_deps=True,
   198          output_is_complete=True,
   199          binary=True,
   200          building_description="Creating runtime image...",
   201          requires=['java'],
   202          visibility=visibility,
   203          tools=[CONFIG.JLINK_TOOL],
   204      )
   205  
   206  
   207  def java_binary(name:str, main_class:str=None, out:str=None, srcs:list=None, deps:list=[],
   208                  data:list=None, visibility:list=None, jvm_args:str=None,
   209                  self_executable:bool=False, manifest:str=None):
   210      """Compiles a .jar from a set of Java libraries.
   211  
   212      Args:
   213        name (str): Name of the rule.
   214        main_class (str): Main class to set in the manifest.
   215        out (str): Name of output .jar file. Defaults to name + .jar.
   216        srcs (list): Source files to compile.
   217        deps (list): Dependencies of this rule.
   218        data (list): Runtime data files for this rule.
   219        visibility (list): Visibility declaration of this rule.
   220        jvm_args (str): Arguments to pass to the JVM in the run script.
   221        self_executable (bool): True to make the jar self executable.
   222        manifest (str): Manifest file to put into the jar. Can't be passed at the same time as
   223                        main_class.
   224      """
   225      if main_class and manifest:
   226          raise ParseError("Can't pass both main_class and manifest to java_binary")
   227      if srcs:
   228          lib_rule = java_library(
   229              name = '_%s#lib' % name,
   230              srcs = srcs,
   231              deps = deps,
   232          )
   233          deps.append(lib_rule)
   234      if self_executable:
   235          preamble = '#!/bin/sh\nexec java %s -jar $0 ${@}' % (jvm_args or '')
   236          cmd, tools = _jarcat_cmd(main_class, preamble, manifest=manifest)
   237      else:
   238          # This is essentially a hack to get past some Java things (notably Jersey) failing
   239          # in subtle ways when the jar has a preamble (srsly...).
   240          cmd, tools = _jarcat_cmd(main_class, manifest=manifest)
   241      build_rule(
   242          name=name,
   243          deps=deps,
   244          data=data,
   245          outs=[out or name + '.jar'],
   246          srcs=[manifest],
   247          cmd=cmd,
   248          needs_transitive_deps=True,
   249          output_is_complete=True,
   250          binary=True,
   251          building_description="Creating jar...",
   252          requires=['java'],
   253          visibility=visibility,
   254          tools=tools,
   255          labels=None if self_executable else ['java_non_exe'],
   256      )
   257  
   258  
   259  def java_test(name:str, srcs:list, resources:list=None, data:list=None, deps:list=None, labels:list&features&tags=None,
   260                visibility:list=None, flags:str='', container:bool|dict=False, sandbox:bool=None,
   261                timeout:int=0, flaky:bool|int=0, test_outputs:list=None, size:str=None,
   262                test_package:str=CONFIG.DEFAULT_TEST_PACKAGE, jvm_args:str=''):
   263      """Defines a Java test.
   264  
   265      Args:
   266        name (str): Name of the rule.
   267        srcs (list): Java files containing the tests.
   268        resources (list): Resources to include in the .jar file
   269        data (list): Runtime data files for this rule.
   270        deps (list): Dependencies of this rule.
   271        labels (list): Labels to attach to this test.
   272        visibility (list): Visibility declaration of this rule.
   273        flags (str): Flags to pass to the test invocation.
   274        container (bool | dict): True to run this test within a container (eg. Docker).
   275        sandbox (bool): Sandbox the test on Linux to restrict access to namespaces such as network.
   276        timeout (int): Maximum length of time, in seconds, to allow this test to run for.
   277        flaky (int | bool): True to mark this as flaky and automatically rerun.
   278        test_outputs (list): Extra test output files to generate from this test.
   279        size (str): Test size (enormous, large, medium or small).
   280        test_package (str): Java package to scan for test classes to run.
   281        jvm_args (str): Arguments to pass to the JVM in the run script.
   282      """
   283      timeout, labels = _test_size_and_timeout(size, timeout, labels)
   284      # It's a bit sucky doing this in two separate steps, but it is
   285      # at least easy and reuses the existing code.
   286      java_library(
   287          name='_%s#lib' % name,
   288          srcs=srcs,
   289          resources=resources,
   290          deps=deps,
   291          test_only=True,
   292          # Deliberately not visible outside this package.
   293      )
   294      # As above, would be nicer if we could make the jars self-executing again.
   295      cmd, tools = _jarcat_cmd('build.please.test.TestMain')
   296      tools['junit'] = [CONFIG.JUNIT_RUNNER]
   297      cmd = 'ln -s $TOOLS_JUNIT . && ' + cmd
   298      test_cmd = 'java -Dbuild.please.testpackage=%s %s -jar $(location :%s) %s' % (
   299          test_package, jvm_args, name, flags)
   300      build_rule(
   301          name=name,
   302          cmd=cmd,
   303          test_cmd=test_cmd,
   304          data=data,
   305          outs=[name + '.jar'],
   306          deps=[':_%s#lib' % name],
   307          visibility=visibility,
   308          container=container,
   309          test_sandbox=sandbox,
   310          labels=labels,
   311          test_timeout=timeout,
   312          flaky=flaky,
   313          test_outputs=test_outputs,
   314          requires=['java'],
   315          needs_transitive_deps=True,
   316          output_is_complete=True,
   317          test=True,
   318          binary=True,
   319          building_description="Creating jar...",
   320          tools=tools,
   321      )
   322  
   323  
   324  def maven_jars(name:str, id:str='', ids:list=[], repository:str|list=None, exclude:list=[],
   325                 hashes:list=None, combine:bool=False, hash:str|list=None, deps:list=[],
   326                 visibility:list=None, filename:str=None, deps_only:bool=False, optional:list=None):
   327      """Fetches a transitive set of dependencies from Maven.
   328  
   329      Args:
   330        name (str): Name of the output rule.
   331        id (str): Maven id of the artifact (e.g. org.junit:junit:4.1.0)
   332        ids (list): Maven ids of artifacts to fetch (e.g. org.junit:junit:4.1.0, io.grpc:grpc-all:1.4.0)
   333        repository (str | list): Maven repositories to fetch deps from.
   334        exclude (list): Dependencies to ignore when fetching this one.
   335        hashes (dict): Map of Maven id -> rule hash for each rule produced.
   336        combine (bool): If True, we combine all downloaded .jar files into one uberjar.
   337        hash (str | list): Hash of final produced .jar. For brevity, implies combine=True.
   338        deps (list): Labels of dependencies, as usual.
   339        visibility (list): Visibility label.
   340        filename (str): Filename we attempt to download. Defaults to standard Maven name.
   341        deps_only (bool): If True we fetch only dependent rules, not this one itself. Useful for some that
   342                          have a top-level target as a facade which doesn't have actual code.
   343        optional (list): List of optional dependencies to fetch. By default we fetch none of them.
   344      """
   345      if id:
   346          ids.append(id)
   347      for id in ids:
   348          if id.count(':') != 2:
   349              raise ValueError('Bad Maven id string: %s. Must be in the format group:artifact:id' % id)
   350      combine = combine or hash
   351      source_name = '_%s#src' % name
   352      repository = repository or CONFIG.DEFAULT_MAVEN_REPO
   353      repos = [repository] if isinstance(repository, str) else repository
   354  
   355      def get_hash(id, artifact=None):
   356          if hashes is None:
   357              return None
   358          artifact = artifact or id.split(':')[1]
   359          return hashes.get(id, hashes.get(artifact, '<not given>'))
   360  
   361      def create_maven_deps(_, output):
   362          for line in output:
   363              if not line:
   364                  continue
   365              group, artifact, version, sources, licences = _parse_maven_artifact(line)
   366              if artifact in exclude:
   367                  continue
   368              maven_jar(
   369                  name=artifact,
   370                  id=line,
   371                  repository=repos,
   372                  hash=get_hash(id, artifact),
   373                  licences=licences,
   374                  sources=sources,
   375                  # We deliberately don't make this rule visible externally.
   376              )
   377              # Have to account for require/provide on final rule if it's a jar
   378              final_name = name if deps_only or combine else '_%s#bin' % name
   379              add_exported_dep(final_name, ':' + artifact)
   380              if combine:
   381                  add_exported_dep(source_name, ':' + artifact)
   382  
   383      exclusions = ' '.join(['-e ' + excl for excl in exclude])
   384      options = ' '.join(['-o ' + option for option in optional]) if optional else ''
   385      repo_flags = ' '.join(['-r ' + repo for repo in repos])
   386      build_rule(
   387          name='_%s#deps' % name,
   388          cmd='$TOOL %s %s %s %s' % (repo_flags, ' '.join(ids), exclusions, options),
   389          post_build=create_maven_deps,
   390          building_description='Finding dependencies...',
   391          tools=[CONFIG.PLEASE_MAVEN_TOOL],
   392          sandbox=False,
   393      )
   394      if combine:
   395          download_name = '_%s#download' % name
   396          maven_jar(
   397              name=download_name,
   398              id=id,
   399              repository=repos,
   400              hash=get_hash(id),
   401              deps = deps,
   402              visibility=visibility,
   403              filename=filename,
   404          )
   405          # Combine the sources into a separate uberjar
   406          cmd, tools = _jarcat_cmd()
   407          build_rule(
   408              name=source_name,
   409              output_is_complete=True,
   410              needs_transitive_deps=True,
   411              building_description="Creating source jar...",
   412              deps=[':' + download_name, ':_%s#deps' % name] + deps,
   413              outs=[name + '_src.jar'],
   414              cmd=cmd + ' -s src.jar -e ""',
   415              tools=tools,
   416          )
   417          return build_rule(
   418              name=name,
   419              hashes=hash if isinstance(hash, list) else [hash] if hash else None,
   420              output_is_complete=True,
   421              needs_transitive_deps=True,
   422              building_description="Creating jar...",
   423              deps=[':' + download_name, ':' + source_name, ':_%s#deps' % name] + deps,
   424              outs=[name + '.jar'],
   425              requires=['java'],
   426              visibility=visibility,
   427              cmd=cmd + ' -e "_src.jar"',
   428              tools=tools,
   429          )
   430      elif not deps_only:
   431          return maven_jar(
   432              name=name,
   433              id=id,
   434              repository=repos,
   435              hash=get_hash(id),
   436              deps = deps + [':_%s#deps' % name],
   437              visibility=visibility,
   438              filename=filename,
   439          )
   440      else:
   441          return build_rule(
   442              name=name,
   443              deps=[':_%s#deps' % name],
   444              exported_deps=deps,
   445              cmd='true',  # do nothing!
   446              visibility=visibility,
   447              requires=['java'],
   448          )
   449  
   450  
   451  def maven_jar(name:str, id:str, repository:str|list=None, hash:str=None, hashes:list=None, deps:list=None,
   452                visibility:list=None, filename:str=None, sources:bool=True, licences:list=None,
   453                native:bool=False, artifact_type:str=None, test_only:bool&testonly=False,
   454                binary:bool=False, classifier:str='', classifier_sources_override:str=''):
   455      """Fetches a single Java dependency from Maven.
   456  
   457      Args:
   458        name (str): Name of the output rule.
   459        id (str): Maven id of the artifact (eg. org.junit:junit:4.1.0)
   460        repository (str | list): Maven repositories to fetch deps from.
   461        hash (str): Hash for produced rule.
   462        hashes (list): List of hashes for produced rule.
   463        deps (list): Labels of dependencies, as usual.
   464        visibility (list): Visibility label.
   465        filename (str): Filename we attempt to download. Defaults to standard Maven name.
   466        sources (bool): True to download source jars as well.
   467        licences (list): Licences this package is subject to.
   468        native (bool): Attempt to download a native jar (i.e. add "-linux-x86_64" etc to the URL).
   469        artifact_type (str): Type of artifact to download (defaults to jar but could be e.g. aar).
   470        test_only (bool): If True, this target can only be used by tests or other test_only rules.
   471        binary (bool): If True, we attempt to fetch and download an executable binary. The output
   472                       is marked as such. Implies native=True and sources=False.
   473        classifier (str): Maven classifier, allows to distinguish artifacts that were built from
   474                       the same POM but differ in their content.
   475        classifier_sources_override (str): Allows to override the classifier used to fetch the
   476                       source artifact.
   477                       e.g. logback-core-1.1.3-tests.jar and logback-core-1.1.3-test-sources.jar
   478      """
   479      if hash and hashes:
   480          raise ParseError('You can pass only one of hash or hashes to maven_jar')
   481      if not artifact_type:
   482          id, _, artifact_type = id.partition('@')
   483          artifact_type = artifact_type or 'jar'
   484      group, artifact, version, sources, licences = _parse_maven_artifact(id, sources, licences)
   485      artifact_type = '.' + artifact_type
   486      out_artifact_type = artifact_type
   487      repository = repository or CONFIG.DEFAULT_MAVEN_REPO
   488      repos = [repository] if isinstance(repository, str) else repository
   489      if classifier:
   490          classifier = '-' + classifier
   491      if binary:
   492          native = True
   493          sources = False
   494          artifact_type = '.exe'  # Maven always describes them this way, even for Linux :(
   495          out_artifact_type = ''  # But we're not peasants so we won't do the same.
   496      if native:
   497          filename = filename or '%s-%s-%s${XOS}-${XARCH}%s' % (artifact, version, classifier, artifact_type)
   498      else:
   499          filename = filename or '%s-%s%s%s' % (artifact, version, classifier, artifact_type)
   500  
   501      group = group.replace('.', '/')
   502      urls = ['/'.join([repo, group, artifact, version, filename]) for repo in repos]
   503      bin_rule  =  remote_file(
   504          name = name,
   505          _tag = 'bin',
   506          url = urls,
   507          out = name + out_artifact_type,
   508          licences = licences,
   509          exported_deps = deps,  # easiest to assume these are always exported.
   510          test_only = test_only,
   511          binary = binary,
   512      )
   513      provides = {'java': bin_rule}
   514      srcs = [bin_rule]
   515  
   516      if sources:
   517          if classifier_sources_override:
   518              classifier = '-' + classifier_sources_override
   519          filename = '%s-%s%s-sources.jar' % (artifact, version, classifier)
   520          urls = ['/'.join([repo, group, artifact, version, filename]) for repo in repos]
   521          src_rule = remote_file(
   522              name = name,
   523              _tag = 'src',
   524              url = urls,
   525              out = name + '_src' + artifact_type,
   526              licences = licences,
   527              test_only = test_only,
   528          )
   529          srcs.append(src_rule)
   530  
   531      # .aar's have an embedded classes.jar in them. Pull that out so other rules can use it.
   532      if artifact_type == '.aar':
   533          classes_rule = build_rule(
   534              name = name,
   535              tag = 'classes',
   536              srcs = [bin_rule],
   537              cmd = '$TOOL x $SRC classes.jar',
   538              outs = [name + '.jar'],
   539              visibility = visibility,
   540              licences = licences,
   541              requires = ['java'],
   542              exported_deps = deps,
   543              test_only=test_only,
   544              tools = [CONFIG.JARCAT_TOOL],
   545          )
   546          provides = {
   547              'java': classes_rule,
   548              'android': bin_rule,
   549          }
   550          local_deps = [classes_rule]
   551      else:
   552          local_deps = None
   553  
   554      return filegroup(
   555          name = name,
   556          srcs = srcs,
   557          provides = provides,
   558          exported_deps=deps,  # easiest to assume these are always exported.
   559          deps = local_deps,  # ensure the classes_rule gets built correctly if there is one.
   560          hashes = hashes if hashes else [hash] if hash else None,
   561          labels = ['mvn:' + id],
   562          visibility = visibility,
   563          test_only=test_only,
   564          output_is_complete = False,
   565          binary = binary,
   566      )
   567  
   568  
   569  def _parse_maven_artifact(id, sources=True, licences=None):
   570      """Parses a Maven artifact in group:artifact:version format, with possibly some extras."""
   571      parts = id.split(':')
   572      if len(parts) == 5:
   573          group, artifact, version = parts[:3]
   574          sources = parts[3] == 'src'
   575          licences = parts[4].split('|')
   576      elif len(parts) == 4:
   577          group, artifact, version = parts[:3]
   578          sources = parts[3] == 'src'
   579      elif len(parts) == 3:
   580          group, artifact, version = parts
   581      else:
   582          raise ParseError('Unknown artifact format: %s (should be group:artifact:version)' % id)
   583      return group, artifact, version, sources, licences
   584  
   585  
   586  def _jarcat_cmd(main_class=None, preamble=None, manifest=None):
   587      """Returns the command we'd use to invoke jarcat, and the tool paths required."""
   588      cmd = '$TOOLS_JARCAT z -i . -o ${OUTS} -j'
   589      if main_class:
   590          cmd += ' -m "%s"' % main_class
   591      if preamble:
   592          cmd += " -p '%s'" % preamble
   593      if manifest:
   594          cmd += ' --manifest "$SRCS"'
   595      return cmd, {'jarcat': [CONFIG.JARCAT_TOOL]}
   596  
   597  
   598  if CONFIG.BAZEL_COMPATIBILITY:
   599      def java_toolchain(javac=None, source_version=None, target_version=None):
   600          """Mimics some effort at Bazel compatibility.
   601  
   602          This doesn't really have the same semantics and ignores a bunch of arguments but it
   603          isn't easy for us to behave the same way that they do.
   604          """
   605          package(
   606              javac_tool = javac,
   607              java_source_level = source_version,
   608              java_target_level = target_version,
   609          )
   610  
   611      def java_import(name, jars, deps=None, exports=None, test_only=False, visibility=None):
   612          """Mimics java_import, as far as I can tell we don't need to do much here."""
   613          filegroup(
   614              name = name,
   615              srcs = jars,
   616              deps = deps,
   617              exported_deps = exports,
   618              test_only = test_only,
   619              visibility = visibility,
   620          )