diff --git a/BUILD.bazel b/BUILD.bazel index ab1444d9f..8d00a4079 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -17,8 +17,14 @@ haskell_toolchain_library(name = "bytestring") haskell_toolchain_library(name = "containers") +haskell_toolchain_library(name = "deepseq") + +haskell_toolchain_library(name = "filepath") + +haskell_toolchain_library(name = "text") + haskell_repl( name = "hie-bios", collect_data = False, - deps = ["//semantic:lib"], + deps = ["//semantic"], ) diff --git a/WORKSPACE b/WORKSPACE index 2700e4fe8..81953de3b 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -55,16 +55,13 @@ stack_snapshot( "aeson-pretty", "algebraic-graphs", "ansi-terminal", - "array", "async", "attoparsec", "bazel-runfiles", "bifunctors", - "deepseq", "directory", "directory-tree", "doctest", - "filepath", "fused-effects", "fused-effects-exceptions", "fused-effects-readline", @@ -118,7 +115,6 @@ stack_snapshot( "template-haskell", "temporary", "terminal-size", - "text", "time", "transformers", "tree-sitter", diff --git a/build/common.bzl b/build/common.bzl index d64ece859..1b6dc11c2 100644 --- a/build/common.bzl +++ b/build/common.bzl @@ -62,13 +62,13 @@ def semantic_language_library(language, name, srcs, nodetypes = "", **kwargs): extra_srcs = [nodetypes], deps = [ "//:base", - "//semantic-analysis:lib", - "//semantic-ast:lib", - "//semantic-core:lib", - "//semantic-proto:lib", - "//semantic-scope-graph:lib", - "//semantic-source:lib", - "//semantic-tags:lib", + "//semantic-analysis", + "//semantic-ast", + "//semantic-core", + "//semantic-proto", + "//semantic-scope-graph", + "//semantic-source", + "//semantic-tags", "@stackage//:aeson", "@stackage//:algebraic-graphs", "//:containers", @@ -81,7 +81,7 @@ def semantic_language_library(language, name, srcs, nodetypes = "", **kwargs): "@stackage//:pathtype", "@stackage//:semilattices", "@stackage//:template-haskell", - "@stackage//:text", + "//:text", "@stackage//:tree-sitter", "@stackage//:tree-sitter-" + language, ], diff --git a/docs/build.md b/docs/build.md index 26711d478..6708910cb 100644 --- a/docs/build.md +++ b/docs/build.md @@ -4,24 +4,58 @@ The Semantic project supports builds with the Bazel build system. This is unconv * Bazel uses content-addressed hashing and reproducible builds to provide sophisticated caching. Situations where Cabal invalidates caches can result in cascading build requirements, causing many rebuilds of the language syntax packages. * Bazel's tooling is (on Emacs with lsp-mode and lsp-haskell) more reliable. +* Bazel gets Haskell dependencies from Stackage LTS versions, so we avoid the rebuilds associated with living on the latest Hackage snapshot. ## How do I get started? Assuming you're on macOS, run the script located at ~script/bootstrap-bazel~. This uses Homebrew to install Bazel and creates the `.bazel-cache` directory. +The first time you run `bazel build` + ## `cabal` → `stack` cheatsheet -| Operation | `cabal` | `bazel` | -|---------------------------|-------------------------------------|-------------------------------------| -| Build all | `cabal build all` | `bazel build //...` | -| Build `TARGET` library | `cabal build semantic-source:lib` | `bazel build //semantic-source/...` | -| Build semantic executable | `cabal build semantic:exe:semantic` | `bazel build //semantic:exe` | -| Build/run executable | `cabal run semantic -- ARGS` | `bazel run //semantic:exe -- ARGS` | -| Load REPL component | `script/ghci` and `:load` | `bazel build //TARGET:lib@repl` | -| Run tests | `cabal test all` | `bazel test //...` | +| Operation | `cabal` | `bazel` | +|---------------------------|-------------------------------------|------------------------------------| +| Build all | `cabal build all` | `bazel build //...` | +| Build `TARGET` library | `cabal build TARGET:lib` | `bazel build //TARGET` | +| Build semantic executable | `cabal build semantic:exe:semantic` | `bazel build //semantic:exe` | +| Build/run executable | `cabal run semantic -- ARGS` | `bazel run //semantic:exe -- ARGS` | +| Load REPL component | `script/ghci` and `:load` | `bazel build //TARGET@repl` | +| Run tests | `cabal test all` | `bazel test //...` | + +## Adding a new dependency + +Here's a breakdown of how to add a new package. + +1. Make sure it's present in [Stackage LTS 13.15](https://www.stackage.org/lts-13.15). If not, add the package (versioned exactly) to the `stack-snapshot.yaml` file. +2. Make sure it's linked into the `WORKSPACE` file, in the `stack_snapshot` call. +3. Make sure it's present in your target's `deps` field. + +If this seems complicated, don't worry: most of the time you'll be able to skip this first point, and you'll often be able to skip the second. + +## Things to know + +1. **Don't generally run `bazel clean`**. Since Bazel builds are reproducible, there's very little reason to clean, unless somehow your whole cache got irrevocably corrupted. +2. **You can load a REPL for any target by appending `@repl`.** +3. **Some packages come with GHC and are not loaded from Stackage**. These include `base`, `containers`, and [others](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/8.10.1-notes.html?highlight=bytestring#included-libraries). To depend on those packages, you use `//:base`, `//:containers`, etc. ## Quick reference links -### Target syntax +* **Bazel manual**: https://docs.bazel.build/versions/3.3.0/bazel-overview.html +* **`rules_haskell` manual**: https://rules-haskell.readthedocs.io +* **`rules_haskell` API docs**: https://api.haskell.build -By convention, we give library targets the same name as their subproject. Test targets are called `test`. +## Conventions + +We give library targets the same name as their subproject. Test targets are called `test`, and executable targets are `exe`. + +The default `.bazelrc` file imports a `.bazelrc.local` file if it's present; use that for any Bazel customizations you want. + +## Shared variables + +* `STANDARD_GHC_WARNINGS`: the standard set of Cabal flags that all targets should use. +* `STANDARD_EXECUTABLE_FLAGS`: ditto, but with executable-specific flags. + +## Custom rules + +We have two custom rules, defined in `build/common.bzl`. The first, `tree_sitter_node_types_archive`, uses the `http_archive` rule to download a specified tree-sitter grammar's `node-types.json` file. These calls declare new top-level targets, so they're only present in the top-level `WORKSPACE` file. The second, `semantic_language_library`, takes care of the boilerplate associated with declaring a target for a `semantic-LANG` language package (as these packages' contents are identical, their target declarations are almost identical). diff --git a/semantic-analysis/BUILD.bazel b/semantic-analysis/BUILD.bazel index fd6713382..f01d39751 100644 --- a/semantic-analysis/BUILD.bazel +++ b/semantic-analysis/BUILD.bazel @@ -19,16 +19,17 @@ load( # You can add your own libraries with haskell_library. haskell_library( - name = "lib", + name = "semantic-analysis", srcs = glob(["src/**/*.hs"]), compiler_flags = STANDARD_GHC_WARNINGS + ["-XOverloadedStrings"], deps = [ "//:base", "//:containers", - "//semantic-source:lib", + "//:filepath", + "//:text", + "//semantic-source", "@stackage//:aeson", "@stackage//:algebraic-graphs", - "@stackage//:filepath", "@stackage//:fused-effects", "@stackage//:fused-effects-readline", "@stackage//:fused-syntax", @@ -39,7 +40,6 @@ haskell_library( "@stackage//:prettyprinter-ansi-terminal", "@stackage//:semilattices", "@stackage//:terminal-size", - "@stackage//:text", "@stackage//:transformers", ], ) diff --git a/semantic-ast/BUILD.bazel b/semantic-ast/BUILD.bazel index 8d9c89f35..6598b3c79 100644 --- a/semantic-ast/BUILD.bazel +++ b/semantic-ast/BUILD.bazel @@ -19,20 +19,21 @@ load( # You can add your own libraries with haskell_library. haskell_library( - name = "lib", + name = "semantic-ast", srcs = glob(["src/**/*.hs"]), compiler_flags = STANDARD_GHC_WARNINGS + ["-XOverloadedStrings"], deps = [ "//:base", "//:bytestring", "//:containers", - "//semantic-source:lib", + "//:filepath", + "//:text", + "//semantic-source", "@stackage//:Glob", "@stackage//:aeson", "@stackage//:aeson-pretty", "@stackage//:attoparsec", "@stackage//:directory", - "@stackage//:filepath", "@stackage//:fused-effects", "@stackage//:hedgehog", "@stackage//:optparse-applicative", @@ -42,7 +43,6 @@ haskell_library( "@stackage//:tasty-hedgehog", "@stackage//:tasty-hunit", "@stackage//:template-haskell", - "@stackage//:text", "@stackage//:tree-sitter", "@stackage//:tree-sitter-python", "@stackage//:unordered-containers", diff --git a/semantic-codeql/BUILD.bazel b/semantic-codeql/BUILD.bazel index 9e4e6dad8..66c690c48 100644 --- a/semantic-codeql/BUILD.bazel +++ b/semantic-codeql/BUILD.bazel @@ -6,7 +6,7 @@ load( ) semantic_language_library( - name = "lib", + name = "semantic-codeql", srcs = glob(["src/**/*.hs"]), language = "ql", ) diff --git a/semantic-core/BUILD.bazel b/semantic-core/BUILD.bazel index 2da91e5f0..4c0a290a3 100644 --- a/semantic-core/BUILD.bazel +++ b/semantic-core/BUILD.bazel @@ -20,13 +20,14 @@ load( # You can add your own libraries with haskell_library. haskell_library( - name = "lib", + name = "semantic-core", srcs = glob(["src/**/*.hs"]), compiler_flags = STANDARD_GHC_WARNINGS, deps = [ "//:base", - "//semantic-analysis:lib", - "//semantic-source:lib", + "//:text", + "//semantic-analysis", + "//semantic-source", "@stackage//:fused-effects", "@stackage//:fused-syntax", "@stackage//:hashable", @@ -34,7 +35,6 @@ haskell_library( "@stackage//:pathtype", "@stackage//:prettyprinter", "@stackage//:prettyprinter-ansi-terminal", - "@stackage//:text", "@stackage//:trifecta", "@stackage//:unordered-containers", ], @@ -48,17 +48,17 @@ haskell_test( ]), compiler_flags = STANDARD_GHC_WARNINGS + STANDARD_EXECUTABLE_FLAGS, deps = [ - ":lib", "//:base", - "//semantic-analysis:lib", - "//semantic-source:lib", + "//:text", + "//semantic-analysis", + "//semantic-core", + "//semantic-source", "@stackage//:fused-effects", "@stackage//:fused-syntax", "@stackage//:hedgehog", "@stackage//:tasty", "@stackage//:tasty-hedgehog", "@stackage//:tasty-hunit", - "@stackage//:text", "@stackage//:trifecta", ], ) diff --git a/semantic-go/BUILD.bazel b/semantic-go/BUILD.bazel index 1e3ffe5d7..6ebcf8b8e 100644 --- a/semantic-go/BUILD.bazel +++ b/semantic-go/BUILD.bazel @@ -6,7 +6,7 @@ load( ) semantic_language_library( - name = "lib", + name = "semantic-go", srcs = glob(["src/**/*.hs"]), language = "go", ) diff --git a/semantic-java/BUILD.bazel b/semantic-java/BUILD.bazel index 34cab2131..8ed6dd660 100644 --- a/semantic-java/BUILD.bazel +++ b/semantic-java/BUILD.bazel @@ -6,7 +6,7 @@ load( ) semantic_language_library( - name = "lib", + name = "semantic-java", srcs = glob(["src/**/*.hs"]), language = "java", ) diff --git a/semantic-json/BUILD.bazel b/semantic-json/BUILD.bazel index 28f94fbeb..d06b757da 100644 --- a/semantic-json/BUILD.bazel +++ b/semantic-json/BUILD.bazel @@ -6,7 +6,7 @@ load( ) semantic_language_library( - name = "lib", + name = "semantic-json", srcs = glob(["src/**/*.hs"]), language = "json", ) diff --git a/semantic-parse/BUILD.bazel b/semantic-parse/BUILD.bazel index 0f849e388..5851a6466 100644 --- a/semantic-parse/BUILD.bazel +++ b/semantic-parse/BUILD.bazel @@ -19,14 +19,14 @@ load( # compiler_flags = STANDARD_GHC_WARNINGS, # deps = [ # ":base", -# "//semantic-ast:lib", -# "//semantic-python:lib", -# "//semantic-source:lib", +# "//semantic-ast", +# "//semantic-python", +# "//semantic-source", # "@stackage//:aeson", # "@stackage//:aeson-pretty", # "//:bytestring", # "@stackage//:optparse-applicative", # "@stackage//:pretty-simple", -# "@stackage//:text", +# "//:text", # ], # ) diff --git a/semantic-php/BUILD.bazel b/semantic-php/BUILD.bazel index 5c5fa1779..90399eaa9 100644 --- a/semantic-php/BUILD.bazel +++ b/semantic-php/BUILD.bazel @@ -6,7 +6,7 @@ load( ) semantic_language_library( - name = "lib", + name = "semantic-php", srcs = glob(["src/**/*.hs"]), language = "php", ) diff --git a/semantic-proto/BUILD.bazel b/semantic-proto/BUILD.bazel index 499eeaf80..752546b9e 100644 --- a/semantic-proto/BUILD.bazel +++ b/semantic-proto/BUILD.bazel @@ -15,14 +15,14 @@ load( # You can add your own libraries with haskell_library. haskell_library( - name = "lib", + name = "semantic-proto", srcs = glob(["src/**/*.hs"]), deps = [ "//:base", + "//:text", "@stackage//:aeson", "@stackage//:proto-lens", "@stackage//:proto-lens-jsonpb", "@stackage//:proto-lens-runtime", - "@stackage//:text", ], ) diff --git a/semantic-python/BUILD.bazel b/semantic-python/BUILD.bazel index f59fa67f8..a3d6a3511 100644 --- a/semantic-python/BUILD.bazel +++ b/semantic-python/BUILD.bazel @@ -7,7 +7,7 @@ load( ) semantic_language_library( - name = "lib", + name = "semantic-python", srcs = glob( include = ["src/**/*.hs"], exclude = [ diff --git a/semantic-ruby/BUILD.bazel b/semantic-ruby/BUILD.bazel index ef48cd9bd..2955dc5cf 100644 --- a/semantic-ruby/BUILD.bazel +++ b/semantic-ruby/BUILD.bazel @@ -6,7 +6,7 @@ load( ) semantic_language_library( - name = "lib", + name = "semantic-ruby", srcs = glob(["src/**/*.hs"]), language = "ruby", nodetypes = "@tree-sitter-ruby//:src/node-types.json", diff --git a/semantic-scope-graph/BUILD.bazel b/semantic-scope-graph/BUILD.bazel index 8dabb6ae8..94eb0347a 100644 --- a/semantic-scope-graph/BUILD.bazel +++ b/semantic-scope-graph/BUILD.bazel @@ -19,14 +19,15 @@ load( # You can add your own libraries with haskell_library. haskell_library( - name = "lib", + name = "semantic-scope-graph", srcs = glob(["src/**/*.hs"]), compiler_flags = STANDARD_GHC_WARNINGS + ["-XOverloadedStrings"], deps = [ "//:base", "//:containers", - "//semantic-analysis:lib", - "//semantic-source:lib", + "//:text", + "//semantic-analysis", + "//semantic-source", "@stackage//:aeson", "@stackage//:algebraic-graphs", "@stackage//:fused-effects", @@ -36,6 +37,5 @@ haskell_library( "@stackage//:lens", "@stackage//:pathtype", "@stackage//:semilattices", - "@stackage//:text", ], ) diff --git a/semantic-source/BUILD.bazel b/semantic-source/BUILD.bazel index 4158a1d96..2c366fcc4 100644 --- a/semantic-source/BUILD.bazel +++ b/semantic-source/BUILD.bazel @@ -19,22 +19,22 @@ load( ) haskell_library( - name = "lib", + name = "semantic-source", srcs = glob(["src/**/*.hs"]), compiler_flags = STANDARD_GHC_WARNINGS + ["-XOverloadedStrings"], deps = [ "//:base", "//:bytestring", "//:containers", + "//:deepseq", + "//:filepath", + "//:text", "@lingo", "@stackage//:aeson", - "@stackage//:deepseq", - "@stackage//:filepath", "@stackage//:generic-monoid", "@stackage//:hashable", "@stackage//:pathtype", "@stackage//:semilattices", - "@stackage//:text", ], ) @@ -46,12 +46,12 @@ haskell_test( ], compiler_flags = STANDARD_GHC_WARNINGS + STANDARD_EXECUTABLE_FLAGS, deps = [ - ":lib", + ":semantic-source", "//:base", + "//:text", "@stackage//:hedgehog", "@stackage//:tasty", "@stackage//:tasty-hedgehog", "@stackage//:tasty-hunit", - "@stackage//:text", ], ) diff --git a/semantic-tags/BUILD.bazel b/semantic-tags/BUILD.bazel index d8ae23183..4936a2e8a 100644 --- a/semantic-tags/BUILD.bazel +++ b/semantic-tags/BUILD.bazel @@ -19,14 +19,14 @@ load( # You can add your own libraries with haskell_library. haskell_library( - name = "lib", + name = "semantic-tags", srcs = glob(["src/**/*.hs"]), compiler_flags = STANDARD_GHC_WARNINGS, deps = [ "//:base", - "//semantic-proto:lib", - "//semantic-source:lib", + "//:text", + "//semantic-proto", + "//semantic-source", "@stackage//:fused-effects", - "@stackage//:text", ], ) diff --git a/semantic-tsx/BUILD.bazel b/semantic-tsx/BUILD.bazel index 17cdead5f..0ef0ca8a8 100644 --- a/semantic-tsx/BUILD.bazel +++ b/semantic-tsx/BUILD.bazel @@ -6,7 +6,7 @@ load( ) semantic_language_library( - name = "lib", + name = "semantic-tsx", srcs = glob(["src/**/*.hs"]), language = "tsx", nodetypes = "@tree-sitter-typescript//:tsx/src/node-types.json", diff --git a/semantic-typescript/BUILD.bazel b/semantic-typescript/BUILD.bazel index 12bdb0b89..adf570c4a 100644 --- a/semantic-typescript/BUILD.bazel +++ b/semantic-typescript/BUILD.bazel @@ -6,7 +6,7 @@ load( ) semantic_language_library( - name = "lib", + name = "semantic-typescript", srcs = glob(["src/**/*.hs"]), language = "typescript", nodetypes = "@tree-sitter-typescript//:typescript/src/node-types.json", diff --git a/semantic/BUILD.bazel b/semantic/BUILD.bazel index 49bea340a..fe4986f11 100644 --- a/semantic/BUILD.bazel +++ b/semantic/BUILD.bazel @@ -25,9 +25,9 @@ haskell_toolchain_library(name = "ghc-prim") semantic_common_dependencies = [ "//:bytestring", "//:containers", - "//semantic-analysis:lib", - "//semantic-ast:lib", - "//semantic-source:lib", + "//semantic-analysis", + "//semantic-ast", + "//semantic-source", "@stackage//:aeson", "@stackage//:algebraic-graphs", "@stackage//:async", @@ -44,37 +44,37 @@ semantic_common_dependencies = [ "@stackage//:scientific", "@stackage//:semilattices", "@stackage//:streaming", - "@stackage//:text", + "//:text", "@stackage//:unix", ] # You can add your own libraries with haskell_library. haskell_library( - name = "lib", + name = "semantic", srcs = glob(["src/**/*.hs"]), compiler_flags = STANDARD_GHC_WARNINGS + ["-XStrictData"], + version = "0.11.0.0", deps = semantic_common_dependencies + [ "//:base", + "//:deepseq", ":ghc-prim", - "//semantic-codeql:lib", - "//semantic-go:lib", - "//semantic-java:lib", - "//semantic-json:lib", - "//semantic-php:lib", - "//semantic-proto:lib", - "//semantic-python:lib", - "//semantic-ruby:lib", - "//semantic-scope-graph:lib", - "//semantic-tags:lib", - "//semantic-tsx:lib", - "//semantic-typescript:lib", + "//semantic-codeql", + "//semantic-go", + "//semantic-java", + "//semantic-json", + "//semantic-php", + "//semantic-proto", + "//semantic-python", + "//semantic-ruby", + "//semantic-scope-graph", + "//semantic-tags", + "//semantic-tsx", + "//semantic-typescript", "@stackage//:ansi-terminal", - "@stackage//:array", "@stackage//:attoparsec", "@stackage//:bifunctors", - "@stackage//:deepseq", "@stackage//:directory-tree", - "@stackage//:filepath", + "//:filepath", "@stackage//:fused-syntax", "@stackage//:generic-lens", "@stackage//:generic-monoid", @@ -113,8 +113,13 @@ haskell_binary( srcs = glob(["app/**/*.hs"]), compiler_flags = STANDARD_GHC_WARNINGS + STANDARD_EXECUTABLE_FLAGS + ["-XStrictData"], deps = [ + ":semantic", "//:base", - "//semantic:lib", + "//:filepath", + "//semantic-analysis", + "//semantic-proto", + "@stackage//:optparse-applicative", + "@stackage//:unix", ], ) @@ -140,10 +145,10 @@ haskell_test( ]), deps = semantic_common_dependencies + [ "//:base", - "//semantic:lib", - "//semantic-proto:lib", - "//semantic-json:lib", - "//semantic-tags:lib", + "//semantic", + "//semantic-proto", + "//semantic-json", + "//semantic-tags", "@stackage//:Glob", "@stackage//:HUnit", "@stackage//:bazel-runfiles",