> ## Documentation Index
> Fetch the complete documentation index at: https://site.aspect.build/llms.txt
> Use this file to discover all available pages before exploring further.

# Things a program must not do under Bazel

> Ensure Bazel program compliance: no implicit environment assumptions, write only to output directory, avoid stdin/stdout reliance, and more

export const BlogPost = ({title, date, authors, tags, image, children}) => {
  const tagList = tags ? tags.split(", ").filter(Boolean) : [];
  const tagSlug = t => t.toLowerCase().replace(/&/g, "").replace(/\+/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
  const formattedDate = date ? new Date(date + "T00:00:00").toLocaleDateString("en-US", {
    year: "numeric",
    month: "long",
    day: "numeric"
  }) : "";
  return <section className="w-full flex justify-center px-4 py-12 md:py-16">
      <div style={{
    maxWidth: "800px",
    width: "100%"
  }}>
        {image && (typeof image === "string" ? <img noZoom src={image} alt={title} className="w-full rounded-xl mb-8" style={{
    maxHeight: "400px",
    objectFit: "cover"
  }} /> : <div className="blog-post-hero-image">{image}</div>)}
        <h1 className="text-3xl md:text-4xl font-bold text-zinc-900 dark:text-white">
          {title}
        </h1>
        <div className="flex flex-wrap items-center gap-3 mt-4 text-sm text-zinc-500 dark:text-zinc-400">
          {authors && <span>{authors}</span>}
          {authors && formattedDate && <span>·</span>}
          {formattedDate && <span>{formattedDate}</span>}
        </div>
        {tagList.length > 0 && <div className="flex flex-wrap gap-2 mt-3">
            {tagList.map(tag => <a key={tag} href={"/blog/tags/" + tagSlug(tag)} className="px-2 py-0.5 rounded-full text-xs bg-zinc-100 dark:bg-zinc-800 text-zinc-600 dark:text-zinc-400 hover:bg-blue-100 dark:hover:bg-blue-900/40 hover:text-blue-700 dark:hover:text-blue-300 transition">
                {tag}
              </a>)}
          </div>}
        <hr className="my-8 border-zinc-200 dark:border-zinc-700" />
        <div className="prose dark:prose-invert max-w-none">{children}</div>
      </div>
    </section>;
};

export const MarketingPage = () => <div className="marketing-page-marker" style={{
  display: "none"
}} />;

export const Section = ({children, className = "", gray = false, dark = false, id}) => <section id={id} className={`w-full flex justify-center px-4 py-16 md:py-24 ${gray ? "bg-gray-50 dark:bg-zinc-900" : dark ? "bg-zinc-900 dark:bg-zinc-950" : ""} ${className}`}>
    <div className="w-full" style={{
  maxWidth: "1140px"
}}>
      {children}
    </div>
  </section>;

<MarketingPage />

<BlogPost title="Things a program must not do under Bazel" date="2020-04-29" authors="Alex Eagle" tags="Bazel">
  <img noZoom src="https://mintcdn.com/aspectbuild/x1L7Iep716jCyJVo/images/blog/hashnode/hn-47e1e69412.jpeg?fit=max&auto=format&n=x1L7Iep716jCyJVo&q=85&s=ac38857ed53f95c3e7add3744bd448ba" alt="" className="blog-post-cover" width="5184" height="3456" data-path="images/blog/hashnode/hn-47e1e69412.jpeg" />

  Don't expect the environment to have implicit things like tools in the PATH. Bazel builds are meant to be portable so you can invoke them remotely or share cache hits with your coworkers. Be explicit about getting tools you need as inputs, or using Bazel's toolchain feature to locate them on the disk.

  Don't rely on the working directory to be next to the inputs. Bazel always sets the working directory in the root of the workspace, next to the WORKSPACE file. (Of course you can always chdir inside the process after Bazel starts it. In NodeJS, for example, you can do this with a [`--require` script](https://github.com/bazelbuild/rules_nodejs/issues/1840#issuecomment-619277667).)

  Don't try to write to the sources. The input directory will be in a read-only filesystem by default. For example Angular CLI runs the `ngcc` program which tries to edit `package.json` files in the inputs: [https://github.com/angular/angular/pull/33366](https://github.com/angular/angular/pull/33366)

  Don't try to write in a subdirectory of the sources either. Only write to the output directory.

  Don't resolve symlinks of the inputs. Node programs often try to read symlinks because of a common pattern of linking build outputs of one package to be dependencies of another. Bazel creates an execroot (for build actions) and a runfiles root (for test/run) filled with symlinks to sources or other outputs. Resolving the symlinks causes non-hermeticity by finding undeclared input files, or causes logic bugs in the program if it compares a symlink target path and expects them to be the same.

  Don't rely on stdin/stdout to communicate inputs and outputs. Bazel will sometimes use stdin for a protocol that communicates with the program, like worker mode or ibazel watch mode. It's possible to work around this with a genrule but that introduces a bash dependency.

  Don't rely on accepting all the configuration over command line arguments. You will likely run into argv length limits. Consider accepting a configuration file or params file with the CLI flags written into it.

  My earlier post about getting Nativescript tools to run under Bazel: [https://medium.com/@Jakeherringbone/running-tools-under-bazel-8aa416e7090c](https://medium.com/@Jakeherringbone/running-tools-under-bazel-8aa416e7090c)
</BlogPost>
