From 016a7dd6ef15fc3e9bbdada9bb0db16c336add27 Mon Sep 17 00:00:00 2001 From: "Lukacs T. Berki" Date: Mon, 16 Aug 2021 14:07:55 +0200 Subject: [PATCH] Delete support for standalone Blueprint. Now that Blueprint has been merged with Soong, a large amount of code is unnecessary. Test: Presubmits. Change-Id: I8d30d8b80f37fdc6a9db630a1792c57c7d6edb38 --- Blueprints | 11 --- blueprint.bash | 54 -------------- blueprint_impl.bash | 44 ------------ bootstrap.bash | 135 ----------------------------------- bootstrap/bootstrap.go | 15 ++-- bootstrap/build.ninja | 23 ------ bootstrap/doc.go | 150 --------------------------------------- bootstrap/glob.go | 2 +- bootstrap/minibp/main.go | 56 --------------- bootstrap/writedocs.go | 47 +----------- 10 files changed, 6 insertions(+), 531 deletions(-) delete mode 100755 blueprint.bash delete mode 100644 blueprint_impl.bash delete mode 100755 bootstrap.bash delete mode 100644 bootstrap/build.ninja delete mode 100644 bootstrap/doc.go delete mode 100644 bootstrap/minibp/main.go diff --git a/Blueprints b/Blueprints index ab9fd3c..55a8d93 100644 --- a/Blueprints +++ b/Blueprints @@ -116,7 +116,6 @@ bootstrap_go_package { "bootstrap/cleanup.go", "bootstrap/command.go", "bootstrap/config.go", - "bootstrap/doc.go", "bootstrap/glob.go", "bootstrap/writedocs.go", ], @@ -141,16 +140,6 @@ bootstrap_go_package { ], } -bootstrap_go_binary { - name: "minibp", - deps: [ - "blueprint", - "blueprint-bootstrap", - "gotestmain-tests", - ], - srcs: ["bootstrap/minibp/main.go"], -} - bootstrap_go_binary { name: "bpglob", deps: ["blueprint-pathtools"], diff --git a/blueprint.bash b/blueprint.bash deleted file mode 100755 index 1c6e896..0000000 --- a/blueprint.bash +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -# This script is intented to wrap the execution of ninja so that we -# can do some checks before each ninja run. -# -# It can either be run with a standalone Blueprint checkout to generate -# the minibp binary, or can be used by another script as part of a custom -# Blueprint-based build system. When used by another script, the following -# environment variables can be set to configure this script, which are -# documented below: -# -# BUILDDIR -# NINJA -# SKIP_NINJA -# -# When run in a standalone Blueprint checkout, bootstrap.bash will install -# this script into the $BUILDDIR, where it may be executed. -# -# For embedding into a custom build system, the current directory when this -# script executes should be the same directory that $BOOTSTRAP should be -# called from. - -set -e - -# BUILDDIR should be set to the path to store build results. By default, -# this is the directory containing this script, but can be set explicitly -# if the custom build system only wants to install their own wrapper. -[ -z "$BUILDDIR" ] && BUILDDIR=`dirname "${BASH_SOURCE[0]}"` - -# NINJA should be set to the path of the ninja executable. By default, this -# is just "ninja", and will be looked up in $PATH. -[ -z "$NINJA" ] && NINJA=ninja - - -if [ ! -f "${BUILDDIR}/.blueprint.bootstrap" ]; then - echo "Please run bootstrap.bash (.blueprint.bootstrap missing)" >&2 - exit 1 -fi - -# .blueprint.bootstrap provides saved values from the bootstrap.bash script: -# -# BLUEPRINT_BOOTSTRAP_VERSION -# BLUEPRINTDIR -# SRCDIR -# GOROOT -# -source "${BUILDDIR}/.blueprint.bootstrap" - -if [ -z "$BLUEPRINTDIR" ]; then - echo "Please run bootstrap.bash (.blueprint.bootstrap outdated)" >&2 - exit 1 -fi - -source "${BLUEPRINTDIR}/blueprint_impl.bash" diff --git a/blueprint_impl.bash b/blueprint_impl.bash deleted file mode 100644 index 6f5abba..0000000 --- a/blueprint_impl.bash +++ /dev/null @@ -1,44 +0,0 @@ -if [ ! "${BLUEPRINT_BOOTSTRAP_VERSION}" -eq "2" ]; then - echo "Please run bootstrap.bash again (out of date)" >&2 - exit 1 -fi - - -# Allow the caller to pass in a list of module files -if [ -z "$BLUEPRINT_LIST_FILE" ]; then - # If the caller does not pass a list of module files, then do a search now - OUR_LIST_FILE="${BUILDDIR}/.bootstrap/bplist" - TEMP_LIST_FILE="${OUR_FILES_LIST}.tmp" - mkdir -p "$(dirname ${OUR_LIST_FILE})" - (cd "$SRCDIR"; - find . -mindepth 1 -type d \( -name ".*" -o -execdir test -e {}/.out-dir \; \) -prune \ - -o -name $TOPNAME -print | sort) >"${TEMP_LIST_FILE}" - if cmp -s "${OUR_LIST_FILE}" "${TEMP_LIST_FILE}"; then - rm "${TEMP_LIST_FILE}" - else - mv "${TEMP_LIST_FILE}" "${OUR_LIST_FILE}" - fi - BLUEPRINT_LIST_FILE="${OUR_LIST_FILE}" -fi - -export GOROOT -export BLUEPRINT_LIST_FILE - -source "${BLUEPRINTDIR}/microfactory/microfactory.bash" - -BUILDDIR="${BUILDDIR}/.minibootstrap" build_go minibp github.com/google/blueprint/bootstrap/minibp - -BUILDDIR="${BUILDDIR}/.minibootstrap" build_go bpglob github.com/google/blueprint/bootstrap/bpglob - -# Build the bootstrap build.ninja -"${NINJA}" -w dupbuild=err -f "${BUILDDIR}/.minibootstrap/build.ninja" - -# Build the primary builder and the main build.ninja -"${NINJA}" -w dupbuild=err -f "${BUILDDIR}/.bootstrap/build.ninja" - -# SKIP_NINJA can be used by wrappers that wish to run ninja themselves. -if [ -z "$SKIP_NINJA" ]; then - "${NINJA}" -w dupbuild=err -f "${BUILDDIR}/build.ninja" "$@" -else - exit 0 -fi diff --git a/bootstrap.bash b/bootstrap.bash deleted file mode 100755 index b08bf1e..0000000 --- a/bootstrap.bash +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/bash - -# This script serves two purposes. First, it can bootstrap the standalone -# Blueprint to generate the minibp binary. To do this simply run the script -# with no arguments from the desired build directory. -# -# It can also be invoked from another script to bootstrap a custom Blueprint- -# based build system. To do this, the invoking script must first set some or -# all of the following environment variables, which are documented below where -# their default values are set: -# -# BOOTSTRAP -# WRAPPER -# SRCDIR -# BLUEPRINTDIR -# BUILDDIR -# NINJA_BUILDDIR -# GOROOT -# -# The invoking script should then run this script, passing along all of its -# command line arguments. - -set -e - -EXTRA_ARGS="" - -# BOOTSTRAP should be set to the path of the bootstrap script. It can be -# either an absolute path or one relative to the build directory (which of -# these is used should probably match what's used for SRCDIR). -if [ -z "$BOOTSTRAP" ]; then - BOOTSTRAP="${BASH_SOURCE[0]}" - - # WRAPPER should only be set if you want a ninja wrapper script to be - # installed into the builddir. It is set to blueprint's blueprint.bash - # only if BOOTSTRAP and WRAPPER are unset. - [ -z "$WRAPPER" ] && WRAPPER="`dirname "${BOOTSTRAP}"`/blueprint.bash" -fi - -# SRCDIR should be set to the path of the root source directory. It can be -# either an absolute path or a path relative to the build directory. Whether -# its an absolute or relative path determines whether the build directory can -# be moved relative to or along with the source directory without re-running -# the bootstrap script. -[ -z "$SRCDIR" ] && SRCDIR=`dirname "${BOOTSTRAP}"` - -# BLUEPRINTDIR should be set to the path to the blueprint source. It generally -# should start with SRCDIR. -[ -z "$BLUEPRINTDIR" ] && BLUEPRINTDIR="${SRCDIR}" - -# BUILDDIR should be set to the path to store build results. By default, this -# is the current directory, but it may be set to an absolute or relative path. -[ -z "$BUILDDIR" ] && BUILDDIR=. - -# NINJA_BUILDDIR should be set to the path to store the .ninja_log/.ninja_deps -# files. By default this is the same as $BUILDDIR. -[ -z "$NINJA_BUILDDIR" ] && NINJA_BUILDDIR="${BUILDDIR}" - -# TOPNAME should be set to the name of the top-level Blueprints file -[ -z "$TOPNAME" ] && TOPNAME="Blueprints" - -# These variables should be set by auto-detecting or knowing a priori the host -# Go toolchain properties. -[ -z "$GOROOT" ] && GOROOT=`go env GOROOT` - -usage() { - echo "Usage of ${BOOTSTRAP}:" - echo " -h: print a help message and exit" - echo " -b : set the build directory" - echo " -t: run tests" - echo " -n: use validations to depend on tests" -} - -# Parse the command line flags. -while getopts ":b:hnt" opt; do - case $opt in - b) BUILDDIR="$OPTARG";; - n) USE_VALIDATIONS=true;; - t) RUN_TESTS=true;; - h) - usage - exit 1 - ;; - \?) - echo "Invalid option: -$OPTARG" >&2 - usage - exit 1 - ;; - :) - echo "Option -$OPTARG requires an argument." >&2 - exit 1 - ;; - esac -done - -# If RUN_TESTS is set, behave like -t was passed in as an option. -[ ! -z "$RUN_TESTS" ] && EXTRA_ARGS="${EXTRA_ARGS} -t" - -# If $USE_VALIDATIONS is set, pass --use-validations. -[ ! -z "$USE_VALIDATIONS" ] && EXTRA_ARGS="${EXTRA_ARGS} --use-validations" - -# If EMPTY_NINJA_FILE is set, have the primary build write out a 0-byte ninja -# file instead of a full length one. Useful if you don't plan on executing the -# build, but want to verify the primary builder execution. -[ ! -z "$EMPTY_NINJA_FILE" ] && EXTRA_ARGS="${EXTRA_ARGS} --empty-ninja-file" - -# Allow the caller to pass in a list of module files -if [ -z "${BLUEPRINT_LIST_FILE}" ]; then - BLUEPRINT_LIST_FILE="${BUILDDIR}/.bootstrap/bplist" -fi -EXTRA_ARGS="${EXTRA_ARGS} -l ${BLUEPRINT_LIST_FILE}" - -mkdir -p $BUILDDIR/.minibootstrap - -echo "bootstrapBuildDir = $BUILDDIR" > $BUILDDIR/.minibootstrap/build.ninja -echo "topFile = $SRCDIR/$TOPNAME" >> $BUILDDIR/.minibootstrap/build.ninja -echo "extraArgs = $EXTRA_ARGS" >> $BUILDDIR/.minibootstrap/build.ninja -echo "builddir = $NINJA_BUILDDIR" >> $BUILDDIR/.minibootstrap/build.ninja -echo "include $BLUEPRINTDIR/bootstrap/build.ninja" >> $BUILDDIR/.minibootstrap/build.ninja - -if [ ! -f "$BUILDDIR/.minibootstrap/build-globs.ninja" ]; then - touch "$BUILDDIR/.minibootstrap/build-globs.ninja" -fi - -echo "BLUEPRINT_BOOTSTRAP_VERSION=2" > $BUILDDIR/.blueprint.bootstrap -echo "SRCDIR=\"${SRCDIR}\"" >> $BUILDDIR/.blueprint.bootstrap -echo "BLUEPRINTDIR=\"${BLUEPRINTDIR}\"" >> $BUILDDIR/.blueprint.bootstrap -echo "NINJA_BUILDDIR=\"${NINJA_BUILDDIR}\"" >> $BUILDDIR/.blueprint.bootstrap -echo "GOROOT=\"${GOROOT}\"" >> $BUILDDIR/.blueprint.bootstrap -echo "TOPNAME=\"${TOPNAME}\"" >> $BUILDDIR/.blueprint.bootstrap - -touch "${BUILDDIR}/.out-dir" - -if [ ! -z "$WRAPPER" ]; then - cp $WRAPPER $BUILDDIR/ -fi diff --git a/bootstrap/bootstrap.go b/bootstrap/bootstrap.go index 5288683..225e2db 100644 --- a/bootstrap/bootstrap.go +++ b/bootstrap/bootstrap.go @@ -27,7 +27,6 @@ import ( const mainSubDir = ".primary" const bootstrapSubDir = ".bootstrap" -const miniBootstrapSubDir = ".minibootstrap" var ( pctx = blueprint.NewPackageContext("github.com/google/blueprint/bootstrap") @@ -162,11 +161,8 @@ var ( return toolDir(config), nil }) - mainDir = filepath.Join("$buildDir", mainSubDir) - bootstrapDir = filepath.Join("$buildDir", bootstrapSubDir) - miniBootstrapDir = filepath.Join("$buildDir", miniBootstrapSubDir) - - minibpFile = filepath.Join(miniBootstrapDir, "minibp") + mainDir = filepath.Join("$buildDir", mainSubDir) + bootstrapDir = filepath.Join("$buildDir", bootstrapSubDir) ) type GoBinaryTool interface { @@ -721,11 +717,8 @@ func (s *singleton) GenerateBuildActions(ctx blueprint.SingletonContext) { var primaryBuilderName string if len(primaryBuilders) == 0 { - // If there's no primary builder module then that means we'll use minibp - // as the primary builder. We can trigger its primary builder mode with - // the -p flag. - primaryBuilderName = "minibp" - primaryBuilderCmdlinePrefix = append(primaryBuilderCmdlinePrefix, "-p") + ctx.Errorf("no primary builder module present") + return } else if len(primaryBuilders) > 1 { ctx.Errorf("multiple primary builder modules present:") for _, primaryBuilder := range primaryBuilders { diff --git a/bootstrap/build.ninja b/bootstrap/build.ninja deleted file mode 100644 index 5787c72..0000000 --- a/bootstrap/build.ninja +++ /dev/null @@ -1,23 +0,0 @@ -# Included by .minibootstrap/build.ninja, which is written by bootstrap.bash -# -# Expected input variables: -# topFile - The path to the top-level Blueprints(etc) file -# extraArgs - Any extra arguments to pass to minibp (-t) -# bootstrapBuildDir - The path to the build directory - -ninja_required_version = 1.7.0 - -myGlobs = ${bootstrapBuildDir}/.minibootstrap/build-globs.ninja -subninja ${myGlobs} - -rule build.ninja - command = ${builder} ${extraArgs} -b ${bootstrapBuildDir} -n ${builddir} -d ${out}.d -globFile ${myGlobs} -o ${out} ${in} - deps = gcc - depfile = ${out}.d - description = ${builder} ${out} - -bootstrapNinja = ${bootstrapBuildDir}/.bootstrap/build.ninja - -build ${bootstrapNinja}: build.ninja ${topFile} | ${builder} - builder = ${bootstrapBuildDir}/.minibootstrap/minibp -default ${bootstrapNinja} diff --git a/bootstrap/doc.go b/bootstrap/doc.go deleted file mode 100644 index 69a1784..0000000 --- a/bootstrap/doc.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// The Blueprint bootstrapping mechanism is intended to enable building a -// source tree with minimal prebuilts. The only prerequisites for performing -// such a build are: -// -// 1. A Ninja binary -// 2. A script interpreter (e.g. Bash or Python) -// 3. A Go toolchain -// -// The Primary Builder -// -// As part of the bootstrapping process, a binary called the "primary builder" -// is created. This primary builder is the binary that includes both the core -// Blueprint library and the build logic specific to the source tree. It is -// used to generate the Ninja file that describes how to build the entire source -// tree. -// -// The primary builder must be a pure Go (i.e. no cgo) module built with the -// module type 'bootstrap_go_binary'. It should have the 'primaryBuilder' -// module property set to true in its Blueprints file. If more than one module -// sets primaryBuilder to true the build will fail. -// -// The primary builder main function should look something like: -// -// package main -// -// import ( -// "flag" -// "github.com/google/blueprint" -// "github.com/google/blueprint/bootstrap" -// "path/filepath" -// -// "my/custom/build/logic" -// ) -// -// func main() { -// // The primary builder should use the global flag set because the -// // bootstrap package registers its own flags there. -// flag.Parse() -// -// // The top-level Blueprints file is passed as the first argument. -// srcDir := filepath.Dir(flag.Arg(0)) -// -// // Create the build context. -// ctx := blueprint.NewContext() -// -// // Register custom module types -// ctx.RegisterModuleType("foo", logic.FooModule) -// ctx.RegisterModuleType("bar", logic.BarModule) -// -// // Register custom singletons -// ctx.RegisterSingleton("baz", logic.NewBazSingleton()) -// -// // Create and initialize the custom Config object. -// config := logic.NewConfig(srcDir) -// -// // This call never returns -// bootstrap.Main(ctx, config) -// } -// -// Required Source Files -// -// There are three files that must be included in the source tree to facilitate -// the build bootstrapping: -// -// 1. The top-level Blueprints file -// 2. The bootstrap script -// 3. The build wrapper script -// -// The top-level Blueprints file describes how the entire source tree should be -// built. It must have a 'subdirs' assignment that includes both the core -// Blueprint library and the custom build logic for the source tree. It should -// also include (either directly or through a subdirs entry) describe all the -// modules to be built in the source tree. -// -// The bootstrap script is a small script to setup the build directory, writing -// a couple configuration files (including the path the source directory, -// information about the Go build environment, etc), then copying the build -// wrapper into the build directory. -// -// The Bootstrapping Process -// -// There are three stages to the bootstrapping process, each with a -// corresponding Ninja file. The stages are referred to as the "bootstrap", -// "primary", and "main" stages. Each stage builds the next stage's Ninja file. -// -// The bootstrapping process begins with the user running the bootstrap script -// to initialize a new build directory. The script is run from the build -// directory, and creates a ".minibootstrap/build.ninja" file that sets a few -// variables then includes blueprint's "bootstrap/build.ninja". It also writes -// out a ".blueprint.bootstrap" file that contains a few variables for later use: -// -// BLUEPRINT_BOOTSTRAP_VERSION - Used to detect when a user needs to run -// bootstrap.bash again -// -// SRCDIR - The path to the source directory -// BLUEPRINTDIR - The path to the blueprints directory (includes $SRCDIR) -// GOROOT - The path to the root directory of the Go toolchain -// NINJA_BUILDDIR - The path to store .ninja_log, .ninja_deps -// -// Once the script completes the build directory is initialized and ready to run -// a build. A wrapper script (blueprint.bash by default) has been installed in -// order to run a build. It iterates through the three stages of the build: -// -// - Runs microfactory.bash to build minibp -// - Runs the .minibootstrap/build.ninja to build .bootstrap/build.ninja -// - Runs .bootstrap/build.ninja to build and run the primary builder -// - Runs build.ninja to build your code -// -// Microfactory takes care of building an up to date version of `minibp` and -// `bpglob` under the .minibootstrap/ directory. -// -// During /.minibootstrap/build.ninja, the following actions are -// taken, if necessary: -// -// - Run minibp to generate .bootstrap/build.ninja (Primary stage) -// - Includes .minibootstrap/build-globs.ninja, which defines rules to -// run bpglob during incremental builds. These outputs are listed in -// the dependency file output by minibp. -// -// During the /.bootstrap/build.ninja, the following actions are -// taken, if necessary: -// -// - Build the primary builder, anything marked `default: true`, and -// any dependencies. -// - Run the primary builder to generate build.ninja -// - Run the primary builder to extract documentation -// - Includes .bootstrap/build-globs.ninja, which defines rules to run -// bpglob during incremental builds. These outputs are listed in the -// dependency file output by the primary builder. -// -// Then the main stage is at /build.ninja, and will contain all the -// rules generated by the primary builder. In addition, the bootstrap code -// adds a phony rule "blueprint_tools" that depends on all blueprint_go_binary -// rules (bpfmt, bpmodify, etc). -// -package bootstrap diff --git a/bootstrap/glob.go b/bootstrap/glob.go index c843ae1..2666cea 100644 --- a/bootstrap/glob.go +++ b/bootstrap/glob.go @@ -44,7 +44,7 @@ import ( // in a build failure with a "missing and no known rule to make it" error. var ( - globCmd = filepath.Join(miniBootstrapDir, "bpglob") + globCmd = filepath.Join(bootstrapDir, "bpglob") // globRule rule traverses directories to produce a list of files that match $glob // and writes it to $out if it has changed, and writes the directories to $out.d diff --git a/bootstrap/minibp/main.go b/bootstrap/minibp/main.go deleted file mode 100644 index 165f058..0000000 --- a/bootstrap/minibp/main.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "flag" - "path/filepath" - - "github.com/google/blueprint" - "github.com/google/blueprint/bootstrap" -) - -var runAsPrimaryBuilder bool - -func init() { - flag.BoolVar(&runAsPrimaryBuilder, "p", false, "run as a primary builder") -} - -type Config struct { -} - -func (c Config) SrcDir() string { - return bootstrap.CmdlineArgs.BuildDir -} - -func (c Config) RemoveAbandonedFilesUnder(buildDir string) (under, exempt []string) { - if !runAsPrimaryBuilder { - under = []string{filepath.Join(buildDir, ".bootstrap")} - exempt = []string{filepath.Join(buildDir, ".bootstrap", "build.ninja")} - } - return -} - -func main() { - flag.Parse() - - ctx := blueprint.NewContext() - if !runAsPrimaryBuilder { - ctx.SetIgnoreUnknownModuleTypes(true) - } - - config := Config{} - bootstrap.Main(ctx, config, !runAsPrimaryBuilder) -} diff --git a/bootstrap/writedocs.go b/bootstrap/writedocs.go index 99df32f..91ffe1b 100644 --- a/bootstrap/writedocs.go +++ b/bootstrap/writedocs.go @@ -1,10 +1,7 @@ package bootstrap import ( - "bytes" "fmt" - "html/template" - "io/ioutil" "path/filepath" "reflect" @@ -20,28 +17,18 @@ func ModuleTypeDocs(ctx *blueprint.Context, config interface{}, factories map[st // creating the binary that we'll use to generate the non-bootstrap // build.ninja file. var primaryBuilders []*goBinary - var minibp *goBinary ctx.VisitAllModulesIf(isBootstrapBinaryModule, func(module blueprint.Module) { binaryModule := module.(*goBinary) if binaryModule.properties.PrimaryBuilder { primaryBuilders = append(primaryBuilders, binaryModule) } - if ctx.ModuleName(binaryModule) == "minibp" { - minibp = binaryModule - } }) - if minibp == nil { - panic("missing minibp") - } - var primaryBuilder *goBinary switch len(primaryBuilders) { case 0: - // If there's no primary builder module then that means we'll use minibp - // as the primary builder. - primaryBuilder = minibp + return nil, fmt.Errorf("no primary builder module present") case 1: primaryBuilder = primaryBuilders[0] @@ -75,38 +62,6 @@ func ModuleTypeDocs(ctx *blueprint.Context, config interface{}, factories map[st return bpdoc.AllPackages(pkgFiles, mergedFactories, ctx.ModuleTypePropertyStructs()) } -func writeDocs(ctx *blueprint.Context, config interface{}, filename string) error { - moduleTypeList, err := ModuleTypeDocs(ctx, config, nil) - if err != nil { - return err - } - - buf := &bytes.Buffer{} - - unique := 0 - - tmpl, err := template.New("file").Funcs(map[string]interface{}{ - "unique": func() int { - unique++ - return unique - }}).Parse(fileTemplate) - if err != nil { - return err - } - - err = tmpl.Execute(buf, moduleTypeList) - if err != nil { - return err - } - - err = ioutil.WriteFile(filename, buf.Bytes(), 0666) - if err != nil { - return err - } - - return nil -} - const ( fileTemplate = `