github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/java/droiddoc.go (about)

     1  // Copyright 2018 Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package java
    16  
    17  import (
    18  	"android/soong/android"
    19  	"android/soong/java/config"
    20  	"fmt"
    21  	"strings"
    22  
    23  	"github.com/google/blueprint"
    24  )
    25  
    26  var (
    27  	javadoc = pctx.AndroidStaticRule("javadoc",
    28  		blueprint.RuleParams{
    29  			Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` +
    30  				`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
    31  				`${config.JavadocCmd} -encoding UTF-8 @$out.rsp @$srcJarDir/list ` +
    32  				`$opts $bootclasspathArgs $classpathArgs -sourcepath $sourcepath ` +
    33  				`-d $outDir -quiet  && ` +
    34  				`${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` +
    35  				`${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir`,
    36  			CommandDeps: []string{
    37  				"${config.ZipSyncCmd}",
    38  				"${config.JavadocCmd}",
    39  				"${config.SoongZipCmd}",
    40  				"$JsilverJar",
    41  				"$DoclavaJar",
    42  			},
    43  			Rspfile:        "$out.rsp",
    44  			RspfileContent: "$in",
    45  			Restat:         true,
    46  		},
    47  		"outDir", "srcJarDir", "stubsDir", "srcJars", "opts",
    48  		"bootclasspathArgs", "classpathArgs", "sourcepath", "docZip", "JsilverJar", "DoclavaJar")
    49  )
    50  
    51  func init() {
    52  	android.RegisterModuleType("droiddoc", DroiddocFactory)
    53  	android.RegisterModuleType("droiddoc_host", DroiddocHostFactory)
    54  	android.RegisterModuleType("droiddoc_template", DroiddocTemplateFactory)
    55  	android.RegisterModuleType("javadoc", JavadocFactory)
    56  	android.RegisterModuleType("javadoc_host", JavadocHostFactory)
    57  }
    58  
    59  type JavadocProperties struct {
    60  	// list of source files used to compile the Java module.  May be .java, .logtags, .proto,
    61  	// or .aidl files.
    62  	Srcs []string `android:"arch_variant"`
    63  
    64  	// list of directories rooted at the Android.bp file that will
    65  	// be added to the search paths for finding source files when passing package names.
    66  	Local_sourcepaths []string `android:"arch_variant"`
    67  
    68  	// list of source files that should not be used to build the Java module.
    69  	// This is most useful in the arch/multilib variants to remove non-common files
    70  	// filegroup or genrule can be included within this property.
    71  	Exclude_srcs []string `android:"arch_variant"`
    72  
    73  	// list of of java libraries that will be in the classpath.
    74  	Libs []string `android:"arch_variant"`
    75  
    76  	// If set to false, don't allow this module(-docs.zip) to be exported. Defaults to true.
    77  	Installable *bool `android:"arch_variant"`
    78  
    79  	// if not blank, set to the version of the sdk to compile against
    80  	Sdk_version *string `android:"arch_variant"`
    81  }
    82  
    83  type DroiddocProperties struct {
    84  	// directory relative to top of the source tree that contains doc templates files.
    85  	Custom_template *string `android:"arch_variant"`
    86  
    87  	// directories relative to top of the source tree which contains html/jd files.
    88  	Html_dirs []string `android:"arch_variant"`
    89  
    90  	// set a value in the Clearsilver hdf namespace.
    91  	Hdf []string `android:"arch_variant"`
    92  
    93  	// proofread file contains all of the text content of the javadocs concatenated into one file,
    94  	// suitable for spell-checking and other goodness.
    95  	Proofread_file *string `android:"arch_variant"`
    96  
    97  	// a todo file lists the program elements that are missing documentation.
    98  	// At some point, this might be improved to show more warnings.
    99  	Todo_file *string `android:"arch_variant"`
   100  
   101  	// local files that are used within user customized droiddoc options.
   102  	Arg_files []string `android:"arch_variant"`
   103  
   104  	// user customized droiddoc args.
   105  	// Available variables for substitution:
   106  	//
   107  	//  $(location <label>): the path to the arg_files with name <label>
   108  	Args *string `android:"arch_variant"`
   109  
   110  	// names of the output files used in args that will be generated
   111  	Out []string `android:"arch_variant"`
   112  
   113  	// a list of files under current module source dir which contains known tags in Java sources.
   114  	// filegroup or genrule can be included within this property.
   115  	Knowntags []string `android:"arch_variant"`
   116  }
   117  
   118  type Javadoc struct {
   119  	android.ModuleBase
   120  	android.DefaultableModuleBase
   121  
   122  	properties JavadocProperties
   123  
   124  	srcJars     android.Paths
   125  	srcFiles    android.Paths
   126  	sourcepaths android.Paths
   127  
   128  	docZip   android.WritablePath
   129  	stubsJar android.WritablePath
   130  }
   131  
   132  type Droiddoc struct {
   133  	Javadoc
   134  
   135  	properties DroiddocProperties
   136  }
   137  
   138  func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
   139  	android.InitAndroidArchModule(module, hod, android.MultilibCommon)
   140  	android.InitDefaultableModule(module)
   141  }
   142  
   143  func JavadocFactory() android.Module {
   144  	module := &Javadoc{}
   145  
   146  	module.AddProperties(&module.properties)
   147  
   148  	InitDroiddocModule(module, android.HostAndDeviceSupported)
   149  	return module
   150  }
   151  
   152  func JavadocHostFactory() android.Module {
   153  	module := &Javadoc{}
   154  
   155  	module.AddProperties(&module.properties)
   156  
   157  	InitDroiddocModule(module, android.HostSupported)
   158  	return module
   159  }
   160  
   161  func DroiddocFactory() android.Module {
   162  	module := &Droiddoc{}
   163  
   164  	module.AddProperties(&module.properties,
   165  		&module.Javadoc.properties)
   166  
   167  	InitDroiddocModule(module, android.HostAndDeviceSupported)
   168  	return module
   169  }
   170  
   171  func DroiddocHostFactory() android.Module {
   172  	module := &Droiddoc{}
   173  
   174  	module.AddProperties(&module.properties,
   175  		&module.Javadoc.properties)
   176  
   177  	InitDroiddocModule(module, android.HostSupported)
   178  	return module
   179  }
   180  
   181  func (j *Javadoc) addDeps(ctx android.BottomUpMutatorContext) {
   182  	if ctx.Device() {
   183  		sdkDep := decodeSdkDep(ctx, String(j.properties.Sdk_version))
   184  		if sdkDep.useDefaultLibs {
   185  			ctx.AddDependency(ctx.Module(), bootClasspathTag, config.DefaultBootclasspathLibraries...)
   186  			ctx.AddDependency(ctx.Module(), libTag, []string{"ext", "framework"}...)
   187  		} else if sdkDep.useModule {
   188  			ctx.AddDependency(ctx.Module(), bootClasspathTag, sdkDep.module)
   189  		}
   190  	}
   191  
   192  	ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
   193  
   194  	android.ExtractSourcesDeps(ctx, j.properties.Srcs)
   195  
   196  	// exclude_srcs may contain filegroup or genrule.
   197  	android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
   198  }
   199  
   200  func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
   201  	var deps deps
   202  
   203  	sdkDep := decodeSdkDep(ctx, String(j.properties.Sdk_version))
   204  	if sdkDep.invalidVersion {
   205  		ctx.AddMissingDependencies([]string{sdkDep.module})
   206  	} else if sdkDep.useFiles {
   207  		deps.bootClasspath = append(deps.bootClasspath, sdkDep.jar)
   208  	}
   209  
   210  	ctx.VisitDirectDeps(func(module android.Module) {
   211  		otherName := ctx.OtherModuleName(module)
   212  		tag := ctx.OtherModuleDependencyTag(module)
   213  
   214  		switch dep := module.(type) {
   215  		case Dependency:
   216  			switch tag {
   217  			case bootClasspathTag:
   218  				deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars()...)
   219  			case libTag:
   220  				deps.classpath = append(deps.classpath, dep.ImplementationJars()...)
   221  			default:
   222  				panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
   223  			}
   224  		case android.SourceFileProducer:
   225  			switch tag {
   226  			case libTag:
   227  				checkProducesJars(ctx, dep)
   228  				deps.classpath = append(deps.classpath, dep.Srcs()...)
   229  			case android.DefaultsDepTag, android.SourceDepTag:
   230  				// Nothing to do
   231  			default:
   232  				ctx.ModuleErrorf("dependency on genrule %q may only be in srcs, libs", otherName)
   233  			}
   234  		default:
   235  			switch tag {
   236  			case android.DefaultsDepTag, android.SourceDepTag, droiddocTemplateTag:
   237  				// Nothing to do
   238  			default:
   239  				ctx.ModuleErrorf("depends on non-java module %q", otherName)
   240  			}
   241  		}
   242  	})
   243  	// do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
   244  	// may contain filegroup or genrule.
   245  	srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
   246  
   247  	// srcs may depend on some genrule output.
   248  	j.srcJars = srcFiles.FilterByExt(".srcjar")
   249  	j.srcFiles = srcFiles.FilterOutByExt(".srcjar")
   250  
   251  	j.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip")
   252  	j.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
   253  
   254  	if j.properties.Local_sourcepaths == nil {
   255  		j.properties.Local_sourcepaths = append(j.properties.Local_sourcepaths, ".")
   256  	}
   257  	j.sourcepaths = android.PathsForModuleSrc(ctx, j.properties.Local_sourcepaths)
   258  	j.sourcepaths = append(j.sourcepaths, deps.bootClasspath...)
   259  	j.sourcepaths = append(j.sourcepaths, deps.classpath...)
   260  
   261  	return deps
   262  }
   263  
   264  func (j *Javadoc) DepsMutator(ctx android.BottomUpMutatorContext) {
   265  	j.addDeps(ctx)
   266  }
   267  
   268  func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
   269  	deps := j.collectDeps(ctx)
   270  
   271  	var implicits android.Paths
   272  	implicits = append(implicits, deps.bootClasspath...)
   273  	implicits = append(implicits, deps.classpath...)
   274  
   275  	var bootClasspathArgs, classpathArgs string
   276  	if ctx.Config().UseOpenJDK9() {
   277  		if len(deps.bootClasspath) > 0 {
   278  			// For OpenJDK 9 we use --patch-module to define the core libraries code.
   279  			// TODO(tobiast): Reorganize this when adding proper support for OpenJDK 9
   280  			// modules. Here we treat all code in core libraries as being in java.base
   281  			// to work around the OpenJDK 9 module system. http://b/62049770
   282  			bootClasspathArgs = "--patch-module=java.base=" + strings.Join(deps.bootClasspath.Strings(), ":")
   283  		}
   284  	} else {
   285  		if len(deps.bootClasspath.Strings()) > 0 {
   286  			// For OpenJDK 8 we can use -bootclasspath to define the core libraries code.
   287  			bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath")
   288  		}
   289  	}
   290  	if len(deps.classpath.Strings()) > 0 {
   291  		classpathArgs = "-classpath " + strings.Join(deps.classpath.Strings(), ":")
   292  	}
   293  
   294  	implicits = append(implicits, j.srcJars...)
   295  
   296  	opts := "-J-Xmx1024m -XDignore.symbol.file -Xdoclint:none"
   297  
   298  	ctx.Build(pctx, android.BuildParams{
   299  		Rule:           javadoc,
   300  		Description:    "Javadoc",
   301  		Output:         j.stubsJar,
   302  		ImplicitOutput: j.docZip,
   303  		Inputs:         j.srcFiles,
   304  		Implicits:      implicits,
   305  		Args: map[string]string{
   306  			"outDir":            android.PathForModuleOut(ctx, "docs", "out").String(),
   307  			"srcJarDir":         android.PathForModuleOut(ctx, "docs", "srcjars").String(),
   308  			"stubsDir":          android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
   309  			"srcJars":           strings.Join(j.srcJars.Strings(), " "),
   310  			"opts":              opts,
   311  			"bootClasspathArgs": bootClasspathArgs,
   312  			"classpathArgs":     classpathArgs,
   313  			"sourcepath":        strings.Join(j.sourcepaths.Strings(), ":"),
   314  			"docZip":            j.docZip.String(),
   315  		},
   316  	})
   317  }
   318  
   319  func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) {
   320  	d.Javadoc.addDeps(ctx)
   321  
   322  	if String(d.properties.Custom_template) == "" {
   323  		// TODO: This is almost always droiddoc-templates-sdk
   324  		ctx.PropertyErrorf("custom_template", "must specify a template")
   325  	} else {
   326  		ctx.AddDependency(ctx.Module(), droiddocTemplateTag, String(d.properties.Custom_template))
   327  	}
   328  
   329  	// extra_arg_files may contains filegroup or genrule.
   330  	android.ExtractSourcesDeps(ctx, d.properties.Arg_files)
   331  
   332  	// knowntags may contain filegroup or genrule.
   333  	android.ExtractSourcesDeps(ctx, d.properties.Knowntags)
   334  }
   335  
   336  func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
   337  	deps := d.Javadoc.collectDeps(ctx)
   338  
   339  	var implicits android.Paths
   340  	implicits = append(implicits, deps.bootClasspath...)
   341  	implicits = append(implicits, deps.classpath...)
   342  
   343  	argFiles := ctx.ExpandSources(d.properties.Arg_files, nil)
   344  	argFilesMap := map[string]android.Path{}
   345  
   346  	for _, f := range argFiles {
   347  		implicits = append(implicits, f)
   348  		if _, exists := argFilesMap[f.Rel()]; !exists {
   349  			argFilesMap[f.Rel()] = f
   350  		} else {
   351  			ctx.ModuleErrorf("multiple arg_files for %q, %q and %q",
   352  				f, argFilesMap[f.Rel()], f.Rel())
   353  		}
   354  	}
   355  
   356  	args, err := android.Expand(String(d.properties.Args), func(name string) (string, error) {
   357  		if strings.HasPrefix(name, "location ") {
   358  			label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
   359  			if f, ok := argFilesMap[label]; ok {
   360  				return f.String(), nil
   361  			} else {
   362  				return "", fmt.Errorf("unknown location label %q", label)
   363  			}
   364  		} else if name == "genDir" {
   365  			return android.PathForModuleGen(ctx).String(), nil
   366  		}
   367  		return "", fmt.Errorf("unknown variable '$(%s)'", name)
   368  	})
   369  
   370  	if err != nil {
   371  		ctx.PropertyErrorf("extra_args", "%s", err.Error())
   372  		return
   373  	}
   374  
   375  	var bootClasspathArgs, classpathArgs string
   376  	if len(deps.bootClasspath.Strings()) > 0 {
   377  		bootClasspathArgs = "-bootclasspath " + strings.Join(deps.bootClasspath.Strings(), ":")
   378  	}
   379  	if len(deps.classpath.Strings()) > 0 {
   380  		classpathArgs = "-classpath " + strings.Join(deps.classpath.Strings(), ":")
   381  	}
   382  
   383  	var templateDir string
   384  	ctx.VisitDirectDepsWithTag(droiddocTemplateTag, func(m android.Module) {
   385  		if t, ok := m.(*DroiddocTemplate); ok {
   386  			implicits = append(implicits, t.deps...)
   387  			templateDir = t.dir.String()
   388  		} else {
   389  			ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_template", ctx.OtherModuleName(m))
   390  		}
   391  	})
   392  
   393  	var htmlDirArgs string
   394  	if len(d.properties.Html_dirs) > 0 {
   395  		htmlDir := android.PathForModuleSrc(ctx, d.properties.Html_dirs[0])
   396  		implicits = append(implicits, ctx.Glob(htmlDir.Join(ctx, "**/*").String(), nil)...)
   397  		htmlDirArgs = "-htmldir " + htmlDir.String()
   398  	}
   399  
   400  	var htmlDir2Args string
   401  	if len(d.properties.Html_dirs) > 1 {
   402  		htmlDir2 := android.PathForModuleSrc(ctx, d.properties.Html_dirs[1])
   403  		implicits = append(implicits, ctx.Glob(htmlDir2.Join(ctx, "**/*").String(), nil)...)
   404  		htmlDir2Args = "-htmldir2 " + htmlDir2.String()
   405  	}
   406  
   407  	if len(d.properties.Html_dirs) > 2 {
   408  		ctx.PropertyErrorf("html_dirs", "Droiddoc only supports up to 2 html dirs")
   409  	}
   410  
   411  	knownTags := ctx.ExpandSources(d.properties.Knowntags, nil)
   412  	implicits = append(implicits, knownTags...)
   413  
   414  	for _, kt := range knownTags {
   415  		args = args + " -knowntags " + kt.String()
   416  	}
   417  	for _, hdf := range d.properties.Hdf {
   418  		args = args + " -hdf " + hdf
   419  	}
   420  
   421  	if String(d.properties.Proofread_file) != "" {
   422  		proofreadFile := android.PathForModuleOut(ctx, String(d.properties.Proofread_file))
   423  		args = args + " -proofread " + proofreadFile.String()
   424  	}
   425  	if String(d.properties.Todo_file) != "" {
   426  		// tricky part:
   427  		// we should not compute full path for todo_file through PathForModuleOut().
   428  		// the non-standard doclet will get the full path relative to "-o".
   429  		args = args + " -todo " + String(d.properties.Todo_file)
   430  	}
   431  
   432  	implicits = append(implicits, d.Javadoc.srcJars...)
   433  
   434  	opts := "-source 1.8 -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
   435  		"-doclet com.google.doclava.Doclava -docletpath ${config.JsilverJar}:${config.DoclavaJar} " +
   436  		"-templatedir " + templateDir + " " + htmlDirArgs + " " + htmlDir2Args + " " +
   437  		"-hdf page.build " + ctx.Config().BuildId() + "-" + ctx.Config().BuildNumberFromFile() + " " +
   438  		"-hdf page.now " + `"$$(date -d @$$(cat ` + ctx.Config().Getenv("BUILD_DATETIME_FILE") + `) "+%d %b %Y %k:%M")"` + " " +
   439  		args + " -stubs " + android.PathForModuleOut(ctx, "docs", "stubsDir").String()
   440  
   441  	var implicitOutputs android.WritablePaths
   442  	implicitOutputs = append(implicitOutputs, d.Javadoc.docZip)
   443  	for _, o := range d.properties.Out {
   444  		implicitOutputs = append(implicitOutputs, android.PathForModuleGen(ctx, o))
   445  	}
   446  
   447  	ctx.Build(pctx, android.BuildParams{
   448  		Rule:            javadoc,
   449  		Description:     "Droiddoc",
   450  		Output:          d.Javadoc.stubsJar,
   451  		Inputs:          d.Javadoc.srcFiles,
   452  		Implicits:       implicits,
   453  		ImplicitOutputs: implicitOutputs,
   454  		Args: map[string]string{
   455  			"outDir":            android.PathForModuleOut(ctx, "docs", "out").String(),
   456  			"srcJarDir":         android.PathForModuleOut(ctx, "docs", "srcjars").String(),
   457  			"stubsDir":          android.PathForModuleOut(ctx, "docs", "stubsDir").String(),
   458  			"srcJars":           strings.Join(d.Javadoc.srcJars.Strings(), " "),
   459  			"opts":              opts,
   460  			"bootclasspathArgs": bootClasspathArgs,
   461  			"classpathArgs":     classpathArgs,
   462  			"sourcepath":        strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
   463  			"docZip":            d.Javadoc.docZip.String(),
   464  			"JsilverJar":        "${config.JsilverJar}",
   465  			"DoclavaJar":        "${config.DoclavaJar}",
   466  		},
   467  	})
   468  }
   469  
   470  var droiddocTemplateTag = dependencyTag{name: "droiddoc-template"}
   471  
   472  type DroiddocTemplateProperties struct {
   473  	// path to the directory containing the droiddoc templates.
   474  	Path *string
   475  }
   476  
   477  type DroiddocTemplate struct {
   478  	android.ModuleBase
   479  
   480  	properties DroiddocTemplateProperties
   481  
   482  	deps android.Paths
   483  	dir  android.Path
   484  }
   485  
   486  func DroiddocTemplateFactory() android.Module {
   487  	module := &DroiddocTemplate{}
   488  	module.AddProperties(&module.properties)
   489  	android.InitAndroidModule(module)
   490  	return module
   491  }
   492  
   493  func (d *DroiddocTemplate) DepsMutator(android.BottomUpMutatorContext) {}
   494  
   495  func (d *DroiddocTemplate) GenerateAndroidBuildActions(ctx android.ModuleContext) {
   496  	path := android.PathForModuleSrc(ctx, String(d.properties.Path))
   497  	d.dir = path
   498  	d.deps = ctx.Glob(path.Join(ctx, "**/*").String(), nil)
   499  }