github.phpd.cn/thought-machine/please@v12.2.0+incompatible/docs/intermediate.html (about) 1 2 <h1>Intermediate Please</h1> 3 4 <p>Okay, you've read the <a href="basics.html">basics</a>, so what's next?</p> 5 6 <h2>BUILD file format</h2> 7 <p>We didn't talk much about the actual format of BUILD files last time, but an astute observer may 8 have noticed that the rule invocations look rather like Python. This is not coincidence; BUILD files 9 are interpreted as a (slightly) restricted subset of Python.</p> 10 11 <p>So what can you do with them? Well, let's say you want to translate your documentation to a bunch of languages: 12 <pre><code> 13 for language in ['en_NZ', 'en_GB', 'it_IT', 'es_MX', 'el_GR']: 14 genrule( 15 name = 'txt_documentation_' + language, 16 srcs = ['docs.txt'], 17 outs = ['docs_%s.txt' % language], 18 cmd = 'cat $SRC | $(exe //tools:translate_tool) --language %s > $OUT' % language, 19 ) 20 21 genrule( 22 name = 'documentation_' + language, 23 srcs = [':txt_documentation_' + language], 24 outs = ['docs_%s.html' % language], 25 cmd = '$(exe //tools:html_doc_tool) --src $SRC --out $OUT', 26 visibility = ['PUBLIC'], 27 ) 28 </code></pre> 29 30 Obviously this would be a bit repetitive if you redefined the rules separately for each language. Instead, we can take 31 advantage of the build language to genericise them across languages; for each language we translate it and then 32 format it as HTML. 33 </p> 34 35 <h2>Custom build rules</h2> 36 37 <p>While the above is perfectly readable, having to define two rules each time is a bit tedious; 38 maybe we'd rather define one rule to perform the translation & HTML conversion in one pass. 39 40 <b>docs/documentation_rules.build_defs:</b><br/> 41 <pre><code> 42 def create_html_docs(name, language, srcs, visibility=None): 43 """Converts documentation to the given language and then to HTML.""" 44 genrule( 45 name = '_%s_%s#translate' % (name, language), 46 srcs=srcs, 47 outs = ['_%s_%s_translated.txt' % (name, language)], 48 cmd = 'cat $SRC | $(exe //tools:translate_tool) --language %s > $OUT' % language, 49 ) 50 genrule( 51 name = '%s_%s' % (name, language), 52 srcs = [':_%s_%s#translate' % (name, language)], 53 outs = ['%s_%s.html' % (name, language)], 54 cmd = '$(exe //tools:html_doc_tool) --src $SRC --out $OUT', 55 visibility = ['PUBLIC'], 56 ) 57 </code></pre> 58 <b>docs/BUILD:</b><br/> 59 <pre><code> 60 include_defs('//docs/documentation_rules.build_defs') 61 for language in ['en_NZ', 'en_GB', 'it_IT', 'es_MX', 'el_GR']: 62 create_html_docs( 63 name = 'docs', 64 language = language, 65 srcs = ['docs.txt'], 66 visibility = ['PUBLIC'], 67 ) 68 </code></pre> 69 </p> 70 71 <p>This example is getting a little strained, but serves to illustrate how you can create something that acts 72 like a single build rule, but internally creates multiple steps to produce the final result. Since the BUILD 73 files are essentially Python it's as simple as defining a function.</p> 74 75 <p>Note the microformat of defining 'internal' private rules with a leading underscore and trailing hashtag; 76 in the interactive build mode those will be omitted to make it appear to users as though they're building 77 the rule they defined by name, even though internally it's split into multiple rules.</p> 78 79 <h2>Transitive dependencies</h2> 80 81 <p>Writing some rules requires that the transitive set of dependencies are available when they're built.</p> 82 83 <p>For example, consider <code>cc_binary</code>; all your <code>cc_library</code> rules have created a bunch of .o files, 84 but each of those only has its own set of symbols. The final binary rule must link all of them together to produce 85 a working executable.</p> 86 87 <p>Fortunately, this is pretty easy in Please. You can apply <code>needs_transitive_deps = True</code> to a 88 <code>genrule</code> to make them all available at build time. This is easy to do but of course shouldn't be taken 89 lightly since it will slow the rule down (needs more time to prepare sources) and may harm incrementality.<br/> 90 The typical pattern is that <code>_library</code> rules don't need this but <code>_binary</code> and <code>_test</code> 91 rules do, although this is somewhat dependent on the language.</p> 92 93 <h2>gentest</h2> 94 95 <p><code>gentest</code> is similar to <code>genrule</code> but defines a target that runs an arbitrary test. The 96 <code>test_cmd</code> attribute defines the command to run; this is often simply <code>$(exe :rule_name)</code> 97 to run its own output.</p> 98 99 <p>The protocol for tests to follow is pretty simple; the test command should return zero on success or nonzero 100 for failure (Unix FTW). The test should also write either a file called <code>test.results</code> or multiple files 101 into a directory named the same; these are parsed as one of the formats Please understands (currently either 102 xUnit XML or Go's test output format). Optionally a test can be marked with <code>no_test_output = True</code> 103 to indicate that it writes no files, in which case its return value is the only indicator of success.</p> 104 105 <h2>Labels</h2> 106 107 <p>Rules, particularly the various <code>_test</code> rules can have an optional set of <em>labels</em> associated with 108 them. These are essentially just a set of tags that can be used to filter them when run via <code>plz test</code>, 109 for example <code>plz test ... --include py</code> will run all your tests labelled with 'py', 110 and <code>plz test ... --exclude slow</code> will run all your tests except those labelled with 'slow'.</p> 111 112 <p>The syntax looks like: 113 <pre><code> 114 go_test( 115 name = 'my_test', 116 srcs = ['my_test.go'], 117 labels = ['slow', 'integration'], 118 ) 119 </code></pre> 120 </p> 121 122 <p>There is one special label, <code>manual</code> which always excludes tests from autodetection when being run with 123 <code>plz test //mypackage:all</code> or <code>plz test //mypackage/...</code>. This is often useful to disable tests 124 from general usage if needed (for example, if a test starts failing, you can disable it while investigating).</p> 125 126 <h2>Flaky tests</h2> 127 128 <p>Tests can be marked as <em>flaky</em> which causes them to be automatically re-run several times. They are considered 129 to pass if any one run passes.</p> 130 131 <p>The syntax looks like: 132 <pre><code> 133 go_test( 134 name = 'my_test', 135 srcs = ['my_test.go'], 136 flaky = True, 137 ) 138 </code></pre> 139 By default they are run three times, you can alter this on a per-test basis by passing an integer instead of a boolean. 140 </p> 141 142 <p>The <code>--max_flakes</code> flag can be used to cap the number of re-runs allowed on a single invocation.</p> 143 144 <h2>Containerised tests</h2> 145 146 <p>Tests can also be marked as <em>containerised</em> so they are isolated within a container for the duration of their run. 147 One main advantage of this is for integration tests that need to open ports and start servers, which are then insulated 148 from port clashes against one another.</p> 149 150 <p>Within the container the test will have access only to the data it's declared it needs at runtime, so you will have 151 to be correct about declaring all such dependencies (but of course one would do that anyway...).</p> 152 153 <p>The syntax looks like: 154 <pre><code> 155 go_test( 156 name = 'my_test', 157 srcs = ['my_test.go'], 158 container = True, 159 ) 160 </code></pre> 161 </p> 162 163 <p>Currently we support Docker as a container format, we plan to support rkt containers in a future release.</p> 164 165 <h2>build_rule</h2> 166 167 <p><code>build_rule</code> is the fundamental unit all other build rules are built from. We discussed <code>genrule</code> 168 just now which is very similar; <code>build_rule</code> allows control over more esoteric features of the system.</p> 169 170 <p>The difference between <code>genrule</code> and <code>build_rule</code> from a user's perspective is pretty arbitrary; 171 conventionally we use <code>genrule</code> in build files for defining arbitrary build transformations and 172 <code>build_rule</code> for defining other rules, but there's no particularly principled reason for this.</p> 173 174 <h2>What else?</h2> 175 176 <p>If you're still curious about what more can be done, try <a href="advanced.html">the advanced stuff</a>.</p>