github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/docs/best_practices.md (about)

     1  # Build System Best Practices
     2  
     3  ## Read only source tree
     4  
     5  Never write to the source directory during the build, always write to
     6  `$OUT_DIR`. We expect to enforce this in the future.
     7  
     8  If you want to verify / provide an update to a checked in generated source
     9  file, generate that file into `$OUT_DIR` during the build, fail the build
    10  asking the user to run a command (either a straight command, checked in script,
    11  generated script, etc) to explicitly copy that file from the output into the
    12  source tree.
    13  
    14  ## Network access
    15  
    16  Never access the network during the build. We expect to enforce this in the
    17  future, though there will be some level of exceptions for tools like `distcc`
    18  and `goma`.
    19  
    20  ## Paths
    21  
    22  Don't use absolute paths in Ninja files (with make's `$(abspath)` or similar),
    23  as that could trigger extra rebuilds when a source directory is moved.
    24  
    25  Assume that the source directory is `$PWD`. If a script is going to change
    26  directories and needs to convert an input from a relative to absolute path,
    27  prefer to do that in the script.
    28  
    29  Don't encode absolute paths in build intermediates or outputs. This would make
    30  it difficult to reproduce builds on other machines.
    31  
    32  Don't assume that `$OUT_DIR` is `out`. The source and output trees are very
    33  large these days, so some people put these on different disks. There are many
    34  other uses as well.
    35  
    36  Don't assume that `$OUT_DIR` is under `$PWD`, users can set it to a relative path
    37  or an absolute path.
    38  
    39  ## $(shell) use in Android.mk files
    40  
    41  Don't use `$(shell)` to write files, create symlinks, etc. We expect to
    42  enforce this in the future. Encode these as build rules in the build graph
    43  instead.  This can be problematic in a number of ways:
    44  
    45  * `$(shell)` calls run at the beginning of every build, at minimum this slows
    46    down build startup, but it can also trigger more build steps to run than are
    47    necessary, since these files will change more often than necessary.
    48  * It's no longer possible for a stripped-down product configuration to opt-out
    49    of these created files. It's better to have actual rules and dependencies set
    50    up so that space isn't wasted, but the files are there when necessary.
    51  
    52  ## Headers
    53  
    54  `LOCAL_COPY_HEADERS` is deprecated. Soong modules cannot use these headers, and
    55  when the VNDK is enabled, System modules in Make cannot declare or use them
    56  either.
    57  
    58  The set of global include paths provided by the build system is also being
    59  removed. They've been switched from using `-isystem` to `-I` already, and are
    60  removed entirely in some environments (vendor code when the VNDK is enabled).
    61  
    62  Instead, use `LOCAL_EXPORT_C_INCLUDE_DIRS`/`export_include_dirs`. These allow
    63  access to the headers automatically if you link to the associated code.
    64  
    65  If your library uses `LOCAL_EXPORT_C_INCLUDE_DIRS`/`export_include_dirs`, and
    66  the exported headers reference a library that you link to, use
    67  `LOCAL_EXPORT_SHARED_LIBRARY_HEADERS`/`LOCAL_EXPORT_STATIC_LIBRARY_HEADERS`/`LOCAL_EXPORT_HEADER_LIBRARY_HEADERS`
    68  (`export_shared_lib_headers`/`export_static_lib_headers`/`export_header_lib_headers`)
    69  to re-export the necessary headers to your users.
    70  
    71  Don't use non-local paths in your `LOCAL_EXPORT_C_INCLUDE_DIRS`, use one of the
    72  `LOCAL_EXPORT_*_HEADERS` instead. Non-local exported include dirs are not
    73  supported in Soong. You may need to either move your module definition up a
    74  directory (for example, if you have ./src/ and ./include/, you probably want to
    75  define the module in ./Android.bp, not ./src/Android.bp), define a header
    76  library and re-export it, or move the headers into a more appropriate location.
    77  
    78  Prefer to use header libraries (`BUILD_HEADER_LIBRARY`/ `cc_library_headers`)
    79  only if the headers are actually standalone, and do not have associated code.
    80  Sometimes there are headers that have header-only sections, but also define
    81  interfaces to a library. Prefer to split those header-only sections out to a
    82  separate header-only library containing only the header-only sections, and
    83  re-export that header library from the existing library. This will prevent
    84  accidentally linking more code than you need (slower at build and/or runtime),
    85  or accidentally not linking to a library that's actually necessary.
    86  
    87  Prefer `LOCAL_EXPORT_C_INCLUDE_DIRS` over `LOCAL_C_INCLUDES` as well.
    88  Eventually we'd like to remove `LOCAL_C_INCLUDES`, though significant cleanup
    89  will be required first. This will be necessary to detect cases where modules
    90  are using headers that shouldn't be available to them -- usually due to the
    91  lack of ABI/API guarantees, but for various other reasons as well: layering
    92  violations, planned deprecations, potential optimizations like C++ modules,
    93  etc.
    94  
    95  ## Use defaults over variables
    96  
    97  Soong supports variable definitions in Android.bp files, but in many cases,
    98  it's better to use defaults modules like `cc_defaults`, `java_defaults`, etc.
    99  
   100  * It moves more information next to the values -- that the array of strings
   101    will be used as a list of sources is useful, both for humans and automated
   102    tools.  This is even more useful if it's used inside an architecture or
   103    target specific property.
   104  * It can collect multiple pieces of information together into logical
   105    inheritable groups that can be selected with a single property.
   106  
   107  ## Custom build tools
   108  
   109  If writing multiple files from a tool, declare them all in the build graph.
   110  * Make: Use `.KATI_IMPLICIT_OUTPUTS`
   111  * Android.bp: Just add them to the `out` list in genrule
   112  * Custom Soong Plugin: Add to `Outputs` or `ImplicitOutputs`
   113  
   114  Declare all files read by the tool, either with a dependency if you can, or by
   115  writing a dependency file. Ninja supports a fairly limited set of dependency
   116  file formats. You can verify that the dependencies are read correctly with:
   117  
   118  ```
   119  NINJA_ARGS="-t deps <output_file>" m
   120  ```
   121  
   122  Prefer to list input files on the command line, otherwise we may not know to
   123  re-run your command when a new input file is added. Ninja does not treat a
   124  change in dependencies as something that would invalidate an action -- the
   125  command line would need to change, or one of the inputs would need to be newer
   126  than the output file. If you don't include the inputs in your command line, you
   127  may need to add the the directories to your dependency list or dependency file,
   128  so that any additions or removals from those directories would trigger your
   129  tool to be re-run. That can be more expensive than necessary though, since many
   130  editors will write temporary files into the same directory, so changing a
   131  README could trigger the directory's timestamp to be updated.
   132  
   133  Only control output files based on the command line, not by an input file. We
   134  need to know which files will be created before any inputs are read, since we
   135  generate the entire build graph before reading source files, or running your
   136  tool. This comes up with Java based tools fairly often -- they'll generate
   137  different output files based on the classes declared in their input files.
   138  We've worked around these tools with the "srcjar" concept, which is just a jar
   139  file containing the generated sources. Our Java compilation tasks understand
   140  *.srcjar files, and will extract them before passing them on to the compiler.
   141  
   142  ## Libraries in PRODUCT_PACKAGES
   143  
   144  Most libraries aren't necessary to include in `PRODUCT_PACKAGES`, unless
   145  they're used dynamically via `dlopen`. If they're only used via
   146  `LOCAL_SHARED_LIBRARIES` / `shared_libs`, then those dependencies will trigger
   147  them to be installed when necessary. Adding unnecessary libraries into
   148  `PRODUCT_PACKAGES` will force them to always be installed, wasting space.