├── .gitignore
├── CONTRIBUTING.md
├── ChangeLog.md
├── LICENSE
├── README.md
├── Setup.hs
├── WORKSPACE
├── app
└── Main.hs
├── bzl
├── BUILD
├── README.md
├── alex.bzl
├── binary_with_runfiles.bzl
├── blazerc
├── c2hs.bzl
├── cabal_package.bzl
├── cabal_package
│ ├── BUILD
│ ├── cabal_paths.bzl
│ ├── core_packages_list.bzl
│ ├── forward_binary.bzl
│ ├── overrides.bzl
│ ├── paths.template
│ └── test.template
├── check_module_names
│ ├── BUILD
│ ├── CheckModuleNames.hs
│ └── CheckModuleNamesTest.hs
├── config.bzl
├── def.bzl
├── g3doc
│ ├── BUILD
│ ├── dynamic.md
│ └── generated_stardoc.bzl
├── generate_core_libraries.bzl
├── happy.bzl
├── hsc2hs.bzl
├── paths.bzl
├── private
│ ├── BUILD
│ ├── action.bzl
│ ├── archive.bzl
│ ├── binary.bzl
│ ├── cc.bzl
│ ├── cc_api_test
│ │ ├── BUILD
│ │ ├── lib.cc
│ │ └── link.bzl
│ ├── compile.bzl
│ ├── compile_srcs_options.bzl
│ ├── default_packages.bzl
│ ├── ghc_options.bzl
│ ├── info.bzl
│ ├── library.bzl
│ ├── link.bzl
│ ├── module_names.bzl
│ ├── package.bzl
│ ├── proto_file.bzl
│ ├── providers.bzl
│ ├── runfiles.bzl
│ └── toolchains.bzl
├── settings.bzl
└── tests
│ ├── attrs
│ ├── BUILD
│ ├── DefaultOptions.hs
│ ├── GhcOptsTest.hs
│ ├── GhcRtsoptsTest.hs
│ ├── LinkoptsTest.hs
│ ├── LiterateHaskell.lhs
│ ├── MainIs.hs
│ ├── RunfilesLib.hs
│ ├── RunfilesMain.hs
│ ├── file_c.txt
│ ├── file_lib.txt
│ ├── file_main.txt
│ └── runfiles_c.h
│ ├── cabal_path
│ ├── BUILD
│ ├── PathsTest.hs
│ ├── foo.txt
│ └── subdir
│ │ └── bar.txt
│ ├── dep_on_haskell
│ ├── BUILD
│ ├── CDep.hs
│ ├── Internal
│ │ └── Inc.hs
│ ├── Lib.hs
│ ├── Sub
│ │ └── Lib.hs
│ ├── cdep_test.cc
│ ├── clib.c
│ └── test.cc
│ ├── dynamic
│ ├── BUILD
│ ├── Binary.hs
│ ├── BinaryRunfilesTest.hs
│ ├── FfiTest.hs
│ ├── FlagProviderTest.hs
│ ├── Library.hs
│ ├── bin.cc
│ ├── flag_provider.cc
│ └── subdir
│ │ ├── BUILD
│ │ ├── CLibrary.hs
│ │ ├── Library.hs
│ │ └── clib.cc
│ ├── ffi
│ ├── AlwaysLinkTest.hs
│ ├── BUILD
│ ├── ExtraObjsForward.hs
│ ├── ExtraObjsJoinedTest.hs
│ ├── ExtraObjsLib.hs
│ ├── ExtraObjsTest.hs
│ ├── Foo.hs
│ ├── HeadersLib.hs
│ ├── HeadersTest.hs
│ ├── LinkInputsTest.hs
│ ├── SimpleFFI.hs
│ ├── Stub.hs
│ ├── StubTest.hs
│ ├── TemplateHaskellBaseTest.hs
│ ├── TransitiveFFI.hs
│ ├── dynamic.lds
│ ├── extra_objs_direct.cc
│ ├── foo.cc
│ ├── provider.cc
│ ├── three.cc
│ ├── three.h
│ ├── transitive_objs.cc
│ └── user.cc
│ ├── hierarchical
│ ├── BUILD
│ ├── Baz.hs
│ ├── Baz2.hs
│ ├── DupeName.hs
│ ├── DupeNameTest.hs
│ ├── Foo.hs
│ ├── Foo
│ │ └── Bar.hs
│ ├── Main.hs
│ └── Sub
│ │ ├── BUILD
│ │ ├── DupeName.hs
│ │ ├── Foo.hs
│ │ └── FooTest.hs
│ ├── hsc2hs
│ ├── BUILD
│ └── Foo.hsc
│ ├── plugins
│ ├── BUILD
│ ├── PluginsLib.hs
│ ├── PluginsLibTest.hs
│ └── PluginsTest.hs
│ ├── preprocessor
│ ├── BUILD
│ ├── PreprocessedLib.hs
│ ├── PreprocessedTest.hs
│ └── pp.sh
│ ├── proto
│ ├── BUILD
│ ├── BarTest.hs
│ ├── CamelCASE.proto
│ ├── CamelCaseDir
│ │ ├── BUILD
│ │ ├── CamelCaseDirTest.hs
│ │ └── foo.proto
│ ├── DashedFilePathTest.hs
│ ├── GeneratedTest.hs
│ ├── SubTest.hs
│ ├── bar.proto
│ ├── dashed-file_path.proto
│ ├── foo.proto
│ └── sub_dir
│ │ └── sub.proto
│ ├── recursive
│ ├── BUILD
│ ├── Boot.hs
│ ├── Boot.hs-boot
│ ├── RecursiveTest.hs
│ └── Regular.hs
│ ├── rules
│ ├── BUILD
│ ├── Binary.hs
│ ├── CoreLibraryTest.hs
│ ├── Data
│ │ └── ByteString.hs
│ ├── DefaultPackageTest.hs
│ ├── Library.hs
│ ├── NoDefaultPackagesTest.hs
│ ├── PackageImportsTest.hs
│ ├── ReexportPreludeTest.hs
│ ├── ReexportTest1.hs
│ ├── ReexportTest2.hs
│ └── UnicodeLib.hs
│ ├── template_haskell
│ ├── ANNTest.hs
│ ├── BUILD
│ ├── Dependency.hs
│ ├── TestDependency.hs
│ ├── TestDependencyLib.hs
│ ├── TestDependencyLibTest.hs
│ └── TransitiveDependency.hs
│ ├── transitive_data
│ ├── BUILD
│ ├── Provider.hs
│ ├── TransitiveDataTest.hs
│ └── data
│ │ ├── cc_data.txt
│ │ └── foo.txt
│ └── version_macros
│ ├── BUILD
│ ├── Dependency.hs
│ └── VersionTest.hs
├── cabal2bazel.cabal
├── rule_info
├── BUILD
└── rule_info.proto
├── settings
└── BUILD
├── src
└── Google
│ ├── Google3.hs
│ ├── Google3
│ ├── Buildifier.hs
│ ├── Name.hs
│ ├── Package.hs
│ ├── Tools
│ │ └── Cabal2Build
│ │ │ ├── Actions.hs
│ │ │ ├── Build.hs
│ │ │ ├── Configuration.hs
│ │ │ ├── Description.hs
│ │ │ ├── Download.hs
│ │ │ ├── License.hs
│ │ │ ├── Options.hs
│ │ │ ├── PackageName.hs
│ │ │ ├── Plan.hs
│ │ │ ├── Stackage.hs
│ │ │ └── VersionAgnosticThirdParty.hs
│ └── VCSClient.hs
│ ├── Runtime
│ ├── BuildHelper.hs
│ └── FindFiles.hs
│ └── Utils
│ ├── DirectoryUtils.hs
│ ├── Env.hs
│ ├── Expn.hs
│ ├── List.hs
│ ├── Monad.hs
│ ├── Pick.hs
│ ├── ReadPUtils.hs
│ └── When.hs
├── stack.yaml
├── test
├── ActionsTest.hs
├── BuildTest.hs
├── DownloadTest.hs
├── LicenseTest.hs
└── testdata
│ ├── awesome-1.2
│ ├── LICENSE
│ ├── README.markdown
│ └── awesome.cabal
│ ├── expected_package_description.bzl
│ ├── third_party
│ └── haskell
│ │ ├── awesome
│ │ └── v1_2
│ │ │ └── awesome.cabal
│ │ ├── cool
│ │ └── v1_8
│ │ │ └── cool.cabal
│ │ ├── groovy
│ │ └── v1_3
│ │ │ └── groovy.cabal
│ │ ├── knarly
│ │ └── v1_4
│ │ │ └── knarly.cabal
│ │ └── sweet
│ │ └── v1_4
│ │ └── sweet.cabal
│ └── verify_package
│ └── fake_package.txt
├── test_support
├── BUILD
└── includes
│ ├── header_provider.h
│ └── hsc2hs_dep.h
└── third_party
└── haskell
└── ghc
├── BUILD
├── v8_6_4
├── BUILD
└── global_packages.bzl
└── versions.bzl
/.gitignore:
--------------------------------------------------------------------------------
1 | .stack-work/
2 | *~
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement. You (or your employer) retain the copyright to your contribution;
10 | this simply gives us permission to use and redistribute your contributions as
11 | part of the project. Head over to to see
12 | your current agreements on file or to sign a new one.
13 |
14 | You generally only need to submit a CLA once, so if you've already submitted one
15 | (even if it was for a different project), you probably don't need to do it
16 | again.
17 |
18 | ## Code reviews
19 |
20 | All submissions, including submissions by project members, require review. We
21 | use GitHub pull requests for this purpose. Consult
22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
23 | information on using pull requests.
24 |
25 | ## Community Guidelines
26 |
27 | This project follows [Google's Open Source Community
28 | Guidelines](https://opensource.google.com/conduct/).
29 |
--------------------------------------------------------------------------------
/ChangeLog.md:
--------------------------------------------------------------------------------
1 | # Changelog for cabal2bazel
2 |
3 | ## Unreleased changes
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # cabal2bazel
2 |
3 | A tool to help with fetching Cabal packages from Hackage and importing
4 | them as packages into cabal2bazel.
5 |
6 |
7 | Usage:
8 | cabal2bazel --fetch
9 |
10 | Examples:
11 | cabal2bazel --fetch binary
12 | cabal2bazel --fetch binary-0.5.0.2
13 | cabal2bazel --recursive --fetch lens
14 |
15 | The process for installing third-party Haskell packages is specified at:
16 | https://opensource.google.com/docs/thirdparty/haskell/
17 | cabal2bazel does not (yet) capture all the subtleties of this process,
18 | and is no substitute for code review. But it will automate the bulk of
19 | chores, including:
20 |
21 | - fetching the Cabal package;
22 | - unpacking it into an appropriate directory;
23 | - ensuring the license file is in the expected location;
24 | - generating a BUILD file with suitable rules.
25 | - if --recursive is specified, traversing graph of all dependencies of
26 | selected package and importing all of them.
27 |
28 | cabal2bazel attempts to map the dependencies of a Cabal library or
29 | executable to the 'deps' attribute of the resulting Bazel target.
30 |
31 | Things that still need manual attention include:
32 | - optimization modes need to be removed from ghcopts, because Bazel
33 | chooses them itself;
34 | - cabal2bazel adds '-Wwarn' to all rules' ghcopts; this might not be
35 | desired;
36 | - correct choice of license attributes should be checked;
37 | - generated dependencies might need to be adjusted to point to specific
38 | versions of the packages depended upon.
39 |
40 | NOTE: You will need an appropriate version of 'cabal' to be available
41 | on your path; cabal2bazel uses it for downloading and unpacking packages.
42 |
43 | NOTE: Sometimes it is necessary to edit the cabal file and re-run
44 | cabal2bazel. In such cases rerun cabal2bazel as follows to resume
45 | installation:
46 |
47 | cabal2bazel --wire-up
48 |
49 | Example:
50 | cabal2bazel --wire-up //third_party/haskell/binary/v0_5_0_2
51 |
52 |
--------------------------------------------------------------------------------
/Setup.hs:
--------------------------------------------------------------------------------
1 | import Distribution.Simple
2 | main = defaultMain
3 |
--------------------------------------------------------------------------------
/WORKSPACE:
--------------------------------------------------------------------------------
1 | workspace(name = "cabal2bazel")
2 |
3 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
4 |
5 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
6 | http_archive(
7 | name = "bazel_skylib",
8 | urls = [
9 | "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
10 | "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
11 | ],
12 | sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
13 | )
14 | load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
15 | bazel_skylib_workspace()
16 |
17 | http_archive(
18 | name = "com_google_protobuf",
19 | strip_prefix = "protobuf-3.11.4",
20 | sha256 = "9748c0d90e54ea09e5e75fb7fac16edce15d2028d4356f32211cfa3c0e956564",
21 | urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.11.4.zip"],
22 | )
23 |
24 | load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
25 |
26 | git_repository(
27 | name = "io_bazel_stardoc",
28 | remote = "https://github.com/bazelbuild/stardoc.git",
29 | commit = "4378e9b6bb2831de7143580594782f538f461180",
30 | shallow_since = "1570829166 -0400"
31 | )
32 |
33 | load("@io_bazel_stardoc//:setup.bzl", "stardoc_repositories")
34 | stardoc_repositories()
35 |
36 | http_archive(
37 | name = "com_google_absl",
38 | urls = ["https://github.com/abseil/abseil-cpp/archive/c512f118dde6ffd51cb7d8ac8804bbaf4d266c3a.zip"],
39 | strip_prefix = "abseil-cpp-c512f118dde6ffd51cb7d8ac8804bbaf4d266c3a",
40 | sha256 = "8400c511d64eb4d26f92c5ec72535ebd0f843067515244e8b50817b0786427f9",
41 | )
42 |
43 | # Used by com_google_protobuf:
44 | http_archive(
45 | name = "rules_python",
46 | sha256 = "fa53cc0afe276d8f6675df1a424592e00e4f37b2a497e48399123233902e2e76",
47 | strip_prefix = "rules_python-0.0.1",
48 | urls = ["https://github.com/bazelbuild/rules_python/archive/0.0.1.tar.gz"],
49 | )
50 | http_archive(
51 | name = "zlib",
52 | build_file = "@com_google_protobuf//:third_party/zlib.BUILD",
53 | sha256 = "629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff",
54 | strip_prefix = "zlib-1.2.11",
55 | urls = ["https://github.com/madler/zlib/archive/v1.2.11.tar.gz"],
56 | )
57 |
58 |
59 |
--------------------------------------------------------------------------------
/app/Main.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE OverloadedStrings, NoMonomorphismRestriction #-}
16 |
17 | -- | Tool to help with fetching Cabal packages from Hackage and installing
18 | -- them as Google3 packages under //third_party/haskell.
19 | --
20 | -- This module is largely about interacting with the Real World, including
21 | -- the user.
22 |
23 | module Main (main) where
24 |
25 | import Control.Monad (void)
26 | import Options.Applicative (progDesc, execParser, info)
27 |
28 | import Google.Google3.Name (parsePackageName)
29 | import Google.Google3.Tools.Cabal2Build.Actions
30 | import Google.Google3.Tools.Cabal2Build.Options
31 | import Google.Google3.Tools.Cabal2Build.Stackage
32 |
33 | import Google.Google3.VCSClient (g3Dir, vcsForGivenDirectory)
34 |
35 | main = do
36 | let infoMod = progDesc "cabal2bazel"
37 | opts <- execParser $ info options infoMod
38 | -- TODO(judahjacobson): Locate the top-level directory.
39 | vcs <- vcsForGivenDirectory "."
40 | putStrLn ("Using google3 directory: " <> g3Dir vcs)
41 | case operation opts of
42 | Install cabalPackageName -> do
43 | name <- parseNameOrId cabalPackageName
44 | snapshot <- getSnapshot (resolverOpt opts)
45 | fetchAndInstall opts snapshot vcs name
46 |
47 | WireUp path -> do
48 | snapshot <- getSnapshot (resolverOpt opts)
49 | wireUpInstalledPackage opts snapshot vcs path
50 |
51 | ReplaceOwner google3packageName ->
52 | void $ replaceOwner opts vcs $
53 | parsePackageName google3packageName
54 |
--------------------------------------------------------------------------------
/bzl/BUILD:
--------------------------------------------------------------------------------
1 | # Skylark rules for compiling Haskell code.
2 | load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
3 |
4 | package(default_visibility = ["//visibility:public"])
5 |
6 | exports_files([
7 | "cabal_package.bzl",
8 | "def.bzl",
9 | "hsc2hs.bzl",
10 | ])
11 |
12 | filegroup(
13 | name = "haskell",
14 | srcs = glob(["*.bzl"]),
15 | visibility = ["//visibility:public"],
16 | )
17 |
18 | bzl_library(
19 | name = "def",
20 | srcs = ["def.bzl"],
21 | visibility = [
22 | "//bzl:__subpackages__",
23 | ],
24 | deps = [
25 | ":config",
26 | "@bazel_skylib//lib:collections",
27 | "@bazel_skylib//lib:dicts",
28 | "@bazel_skylib//lib:new_sets",
29 | "//bzl/private",
30 | ],
31 | )
32 |
33 | bzl_library(
34 | name = "config",
35 | srcs = [":config.bzl"],
36 | )
37 |
38 | bzl_library(
39 | name = "binary_with_runfiles",
40 | srcs = [":binary_with_runfiles.bzl"],
41 | )
42 |
43 | bzl_library(
44 | name = "hsc2hs",
45 | srcs = [":hsc2hs.bzl"],
46 | deps = [
47 | ":config",
48 | "@bazel_skylib//lib:dicts",
49 | "//bzl/private",
50 | ],
51 | )
52 |
53 | bzl_library(
54 | name = "paths",
55 | srcs = ["paths.bzl"],
56 | deps = [
57 | "@bazel_skylib//lib:paths",
58 | ],
59 | )
60 |
61 | bzl_library(
62 | name = "settings",
63 | srcs = ["settings.bzl"],
64 | deps = ["@bazel_skylib//rules:common_settings"],
65 | )
66 |
67 | bzl_library(
68 | name = "happy",
69 | srcs = ["happy.bzl"],
70 | )
71 | bzl_library(
72 | name = "alex",
73 | srcs = ["alex.bzl"],
74 | )
75 | bzl_library(
76 | name = "c2hs",
77 | srcs = ["c2hs.bzl"],
78 | )
79 |
--------------------------------------------------------------------------------
/bzl/README.md:
--------------------------------------------------------------------------------
1 | # Haskell Build Rules
2 |
3 | This directory defines build rules for the Haskell programming language.
4 |
--------------------------------------------------------------------------------
/bzl/alex.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Genrule for the Alex scanner generator."""
16 |
17 | def genalex(src, out, **kwargs):
18 | """Runs the Alex lexer generator to create a Haskell source file.
19 |
20 | For more information, see https://haskell.org/alex.
21 |
22 | Example:
23 |
24 | load("//third_party/haskell/alex:build_defs.bzl", "genalex")
25 |
26 | genalex(
27 | src = "MyScanner.x",
28 | out = "MyScanner.hs"
29 | )
30 |
31 | haskell_binary(
32 | name = "MyScanner",
33 | srcs = [ "MyScanner.y.hs" ]
34 | ...
35 | )
36 |
37 | Args:
38 | src: The input Alex file (.x)
39 | out: The output Haskell source file (.hs).
40 | **kwargs: Other parameters for the underlying genrule.
41 | """
42 | native.genrule(
43 | name = out + ".hs_alex",
44 | srcs = [src],
45 | outs = [out],
46 | tools = ["//third_party/haskell/alex:alex_bin"],
47 | cmd = "//third_party/haskell/alex:alex_bin -g -o $(OUTS) $(SRCS)",
48 | **kwargs
49 | )
50 |
51 |
52 |
--------------------------------------------------------------------------------
/bzl/blazerc:
--------------------------------------------------------------------------------
1 | # Global bazelrc for Haskell rules.
2 | #
3 | # To use, add an import to ~/.bazelrc:
4 | #
5 | # import %workspace%/tools/build_defs/haskell/bazelrc
6 | # TODO(judahjacobson): Switch this to build:haskell_check after publicizing
7 | # the --config=haskell_check way of doing things.
8 | build --strategy=HaskellCheck=local
9 |
10 | # --config=haskell_check is preferable to directly calling --output_groups:
11 | # - It gives you an error if you misspell "haskell_check"
12 | # - It hides the exact Bazel implementation from the user.
13 | build:haskell_check --output_groups=haskell_check
14 |
15 | # HaskellCheckModuleNames should also run locally, since each HaskellCheck
16 | # action depends on the HaskellCheckModuleNames of its deps.
17 | build:haskell_check --strategy=HaskellCheckModuleNames=local
18 |
19 | # Add flags so we can identify use of this file in Dremel queries.
20 | build --define=HASKELL_BLAZERC=1
21 | build:haskell_check --define=HASKELL_CHECK=1
22 |
--------------------------------------------------------------------------------
/bzl/cabal_package/BUILD:
--------------------------------------------------------------------------------
1 | # Support files for the cabal_haskell_package macro.
2 | load("//bzl/cabal_package:core_packages_list.bzl", "core_packages_list")
3 | load("//bzl:def.bzl", "haskell_library")
4 | load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
5 |
6 | package(default_visibility = ["//bzl:__subpackages__"])
7 |
8 | exports_files([
9 | "paths.template",
10 | "test.template",
11 | ])
12 |
13 | # cabal2build will build this target on-demand to get the list of core packages.
14 | # Having a separate target lets it be up-to-date with the current client,
15 | # rather than the released version of the cabal2build binary.
16 | core_packages_list(
17 | name = "core_packages",
18 | )
19 |
20 | bzl_library(
21 | name = "cabal_paths",
22 | srcs = ["cabal_paths.bzl"],
23 | )
24 |
25 | bzl_library(
26 | name = "overrides",
27 | srcs = ["overrides.bzl"],
28 | )
29 |
30 | # A forwarding library that any user of cabal_paths should depend on.
31 | haskell_library(
32 | name = "PathDeps",
33 | default_packages = [],
34 | visibility = [
35 | "//bzl/tests:__subpackages__",
36 | ],
37 | deps = [
38 | # TODO
39 | ],
40 | )
41 |
--------------------------------------------------------------------------------
/bzl/cabal_package/cabal_paths.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Rules for auto-generating the Paths_* module needed in third-party.
16 |
17 | Some third-party Haskell packages use a Paths_{package_name}.hs file
18 | which is auto-generated by Cabal. That file lets them
19 | - Get the package's current version number
20 | - Find useful data file
21 |
22 | This file exports the "cabal_paths" rule for auto-generating that Paths module.
23 | For usage information, see the below documentation for that rule.
24 | """
25 |
26 | def _impl_path_module_gen(ctx):
27 | base_dir = ctx.label.package + (
28 | ("/" + ctx.attr.data_dir) if ctx.attr.data_dir else ""
29 | )
30 |
31 | ctx.actions.expand_template(
32 | template = ctx.file._template,
33 | output = ctx.outputs.out,
34 | substitutions = {
35 | "%{module}": "Paths_" + ctx.attr.package,
36 | "%{base_dir}": base_dir,
37 | "%{version}": str(ctx.attr.version),
38 | },
39 | )
40 | return [DefaultInfo(files = depset([ctx.outputs.out]))]
41 |
42 | cabal_paths = rule(
43 | implementation = _impl_path_module_gen,
44 | attrs = {
45 | "out": attr.output(mandatory = True),
46 | "data_dir": attr.string(),
47 | "package": attr.string(),
48 | "version": attr.int_list(mandatory = True, allow_empty = False),
49 | "_template": attr.label(
50 | allow_single_file = True,
51 | default = Label(
52 | "//bzl/cabal_package:paths.template",
53 | ),
54 | ),
55 | },
56 | )
57 | """Generate a Cabal Paths_* module.
58 |
59 | Generates a Paths_ module for use by Cabal packages.
60 |
61 | Example usage:
62 |
63 | haskell_binary(
64 | name = "hlint",
65 | srcs = [":paths"],
66 | )
67 |
68 | cabal_paths(
69 | name = "paths",
70 | package = "hlint",
71 | version = [1, 18, 5],
72 | # Corresponds to the Cabal "data-dir" field.
73 | data_dir = "datafiles",
74 | )
75 |
76 |
77 | Args:
78 | name: The name of the resulting library target.
79 | package: The name (string) of the Cabal package that's being built.
80 | data_dir: The subdirectory (relative to this package) that contains the
81 | data files (if any). If empty, assumes the data files are at the top
82 | level of the package.
83 | data: The data files that this package depends on to run.
84 | version: The version number of this package (list of ints)
85 | **kwargs: Additonal parameters to the haskell_library.
86 | """
87 |
--------------------------------------------------------------------------------
/bzl/cabal_package/core_packages_list.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """A build rule for exposing the list of core packages to Cabal2Build."""
16 |
17 | load("//bzl/private:default_packages.bzl", "core_package_names")
18 |
19 | def _impl(ctx):
20 | output = ctx.actions.declare_file(ctx.label.name)
21 | ctx.actions.write(
22 | output = output,
23 | content = "\n".join(core_package_names),
24 | )
25 | return [DefaultInfo(files = depset([output]))]
26 |
27 | core_packages_list = rule(
28 | implementation = _impl,
29 | )
30 |
--------------------------------------------------------------------------------
/bzl/cabal_package/forward_binary.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """A build rule to forward a binary from another rule without affecting shared linking.
16 |
17 | Consider the alternative of using an sh_binary to forward a rule:
18 |
19 | sh_binary(
20 | name = "link",
21 | srcs = ["//path/to:rule"],
22 | )
23 |
24 | That will create a symlink named "link" that points to the original rule. Unfortunately,
25 | if the original rule is a shared binary, that will break any rpaths using $EXEC_ORIGIN
26 | (e.g., "$EXEC_ORIGIN/../../_solib_k8"). Since $EXEC_ORIGIN doesn't follow symlinks,
27 | it will try to resolve them relative to "link" instead of "rule".
28 |
29 | Instead, using
30 |
31 | forward_binary(
32 | name = "forward",
33 | src = "//path/to:rule",
34 | )
35 |
36 | will create an executable shell script named "forward" that invokes the original rule.
37 | In that case, $EXEC_ORIGIN will be the location of the original rule, as expected.
38 | """
39 |
40 | def _impl(ctx):
41 | output = ctx.actions.declare_file(ctx.label.name)
42 |
43 | # Point to the top-level directory (bazel-bin or runfiles).
44 | prefix = "$(dirname \"$BASH_SOURCE\")/" + "../" * (len(output.short_path.split("/")) - 1)
45 | ctx.actions.write(
46 | output,
47 | "\n".join(
48 | [
49 | "#!/bin/bash",
50 | "set -euo pipefail",
51 | "exec {} \"$@\"".format(prefix + ctx.executable.src.short_path),
52 | ],
53 | ),
54 | is_executable = True,
55 | )
56 | return [DefaultInfo(
57 | executable = output,
58 | files = ctx.attr.src[DefaultInfo].files,
59 | runfiles = ctx.runfiles(files = [output, ctx.executable.src]).merge(
60 | ctx.attr.src[DefaultInfo].data_runfiles,
61 | ),
62 | )]
63 |
64 | forward_binary = rule(
65 | implementation = _impl,
66 | executable = True,
67 | attrs = {
68 | "src": attr.label(executable = True, cfg = "target"),
69 | },
70 | )
71 |
--------------------------------------------------------------------------------
/bzl/cabal_package/overrides.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Declares nonstandard locations of third-party haskell libraries."""
16 |
17 | load("@bazel_skylib//lib:dicts.bzl", "dicts")
18 | load(
19 | "//bzl/private:default_packages.bzl",
20 | "default_package_names",
21 | "nondefault_core_package_names",
22 | )
23 |
24 | common_package_overrides = dicts.add(
25 | {
26 | name: "//third_party/haskell/ghc:" + name
27 | for name in nondefault_core_package_names + default_package_names
28 | },
29 | {
30 | "clash-ghc": "//third_party/haskell/clash/clash-ghc:clash_ghc",
31 | "clash-lib": "//third_party/haskell/clash/clash-lib:clash_lib",
32 | "clash-prelude": "//third_party/haskell/clash/clash-prelude:clash_prelude",
33 | "haskell-indexer-backend-core": "//third_party/haskell/haskell_indexer:haskell_indexer_backend_core",
34 | "haskell-indexer-backend-ghc": "//third_party/haskell/haskell_indexer:haskell_indexer_backend_ghc",
35 | "haskell-indexer-frontend-kythe": "//third_party/haskell/haskell_indexer:haskell_indexer_frontend_kythe",
36 | "haskell-indexer-pathutil": "//third_party/haskell/haskell_indexer:haskell_indexer_pathutil",
37 | "haskell-indexer-pipeline-ghckythe": "//third_party/haskell/haskell_indexer:haskell_indexer_pipeline_ghckythe",
38 | "haskell-indexer-translate": "//third_party/haskell/haskell_indexer:haskell_indexer_translate",
39 | "kythe-schema": "//third_party/haskell/haskell_indexer:kythe_schema",
40 | "proto-lens-runtime": "//third_party/haskell/proto_lens:proto_lens_runtime",
41 | "text-offset": "//third_party/haskell/haskell_indexer:text_offset",
42 | },
43 | )
44 |
--------------------------------------------------------------------------------
/bzl/cabal_package/paths.template:
--------------------------------------------------------------------------------
1 | module %{module} (
2 | version,
3 | getDataDir,
4 | getDataFileName,
5 | ) where
6 |
7 | import Data.Version (Version, makeVersion)
8 | import Google.Runtime.BuildHelper
9 | import Prelude -- In case the package has NoImplicitPrelude
10 | import System.FilePath ((>))
11 |
12 | getDataDir :: IO FilePath
13 | getDataDir = do
14 | dir <- findRunfilesDirOrDie
15 | return $ dir > "%{workspace}" > "%{base_dir}"
16 |
17 | getDataFileName :: FilePath -> IO FilePath
18 | getDataFileName name = do
19 | dir <- getDataDir
20 | return (dir > name)
21 |
22 | -- TODO:
23 | version :: Version
24 | version = makeVersion %{version}
25 |
--------------------------------------------------------------------------------
/bzl/cabal_package/test.template:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # A wrapper script for running a third-party test similarly to how
4 | # it would be run under Cabal.
5 |
6 | set -ueo pipefail
7 |
8 | # A directory which contains all source files and is also writeable.
9 | WORKING_DIR="${TEST_TMPDIR}"/working-dir
10 |
11 | cp -R "${TEST_SRCDIR}"/{WORKSPACE}/"%{extra_srcs_dir}" "${WORKING_DIR}"
12 | chmod -R +w "${WORKING_DIR}"
13 | cd "${WORKING_DIR}"
14 |
15 | # Set the base library's default encoding via the LANG variable.
16 | # By default, System.IO checks LANG to determine the input/output
17 | # encoding of non-binary handles.
18 | # Several Haskell packages expect UTF-8 for their tests.
19 | exec env \
20 | LANG=en_US.UTF-8 \
21 | "${TEST_SRCDIR}"/{WORKSPACE}/"%{binary}" "${@:1}"
22 |
--------------------------------------------------------------------------------
/bzl/check_module_names/BUILD:
--------------------------------------------------------------------------------
1 | load("//bzl:def.bzl", "haskell_bootstrap_binary", "haskell_test")
2 |
3 | # Since other haskell_binary rules will depend on it in their attrs,
4 | # this target can't itself be a haskell_binary. We break the cycle
5 | # by making it a haskell_bootstrap_binary instead.
6 | haskell_bootstrap_binary(
7 | name = "CheckModuleNames",
8 | srcs = ["CheckModuleNames.hs"],
9 | visibility = ["//visibility:public"],
10 | # Note: we use this target to build haskell_library targets.
11 | # As a result, it cannot itself depend on a haskell_library, and can
12 | # only use core packages like base or ghc.
13 | deps = [
14 | # TODO
15 | ],
16 | )
17 |
18 | haskell_test(
19 | name = "CheckModuleNamesTest",
20 | srcs = ["CheckModuleNamesTest.hs"],
21 | data = [
22 | ":CheckModuleNames",
23 | "//third_party/haskell/ghc:settings",
24 | ],
25 | deps = [
26 | # TODO
27 | ],
28 | )
29 |
--------------------------------------------------------------------------------
/bzl/def.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """This file reexports all of the Haskell build rules.
16 |
17 | For more information, see go/haskell-rules.
18 | """
19 |
20 | load(
21 | "//bzl/private:binary.bzl",
22 | _haskell_binary = "haskell_binary",
23 | _haskell_bootstrap_binary = "haskell_bootstrap_binary",
24 | _haskell_test = "haskell_test",
25 | )
26 | load(
27 | "//bzl/private:library.bzl",
28 | _haskell_core_library = "haskell_core_library",
29 | _haskell_library = "haskell_library",
30 | _haskell_proto_aspect = "haskell_proto_aspect",
31 | _haskell_proto_library = "haskell_proto_library",
32 | )
33 |
34 | haskell_binary = _haskell_binary
35 | haskell_bootstrap_binary = _haskell_bootstrap_binary
36 | haskell_core_library = _haskell_core_library
37 | haskell_library = _haskell_library
38 | haskell_proto_aspect = _haskell_proto_aspect
39 | haskell_proto_library = _haskell_proto_library
40 | haskell_test = _haskell_test
41 |
--------------------------------------------------------------------------------
/bzl/g3doc/BUILD:
--------------------------------------------------------------------------------
1 | load(":generated_stardoc.bzl", "generated_stardoc")
2 |
3 | generated_stardoc(
4 | name = "rules",
5 | input = "//bzl:def.bzl",
6 | deps = [
7 | "@bazel_skylib//lib:collections",
8 | "@bazel_skylib//lib:dicts",
9 | "@bazel_skylib//lib:new_sets",
10 | "//bzl:config",
11 | "//bzl/private",
12 | ],
13 | )
14 |
15 | generated_stardoc(
16 | name = "hsc2hs",
17 | input = "//bzl:hsc2hs.bzl",
18 | deps = [
19 | "@bazel_skylib//lib:dicts",
20 | "//bzl:config",
21 | "//bzl/private",
22 | ],
23 | )
24 |
25 | generated_stardoc(
26 | name = "cabal_package",
27 | input = "//bzl:cabal_package.bzl",
28 | deps = [
29 | "@bazel_skylib//lib:collections",
30 | "@bazel_skylib//lib:dicts",
31 | "@bazel_skylib//lib:paths",
32 | "//bzl:alex",
33 | "//bzl:happy",
34 | "//third_party/haskell/ghc:versions",
35 | "//bzl:binary_with_runfiles",
36 | "//bzl:def",
37 | "//bzl:hsc2hs",
38 | "//bzl/cabal_package:cabal_paths",
39 | "//bzl/cabal_package:overrides",
40 | "@bazel_skylib//rules:build_test",
41 | ],
42 | )
43 |
44 | generated_stardoc(
45 | name = "happy",
46 | input = "//bzl:happy.bzl",
47 | )
48 |
49 | generated_stardoc(
50 | name = "alex",
51 | input = "//bzl:alex.bzl",
52 | )
53 |
54 | generated_stardoc(
55 | name = "c2hs",
56 | input = "//bzl:c2hs.bzl",
57 | deps = [
58 | "@bazel_skylib//lib:dicts",
59 | "//bzl:config",
60 | "//bzl/private",
61 | ],
62 | )
63 |
--------------------------------------------------------------------------------
/bzl/g3doc/generated_stardoc.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """TODO(judahjacobson): Write module docstring."""
16 |
17 | load("@io_bazel_stardoc//stardoc:stardoc.bzl", "stardoc")
18 | load("@bazel_skylib//rules:build_test.bzl", "build_test")
19 |
20 | def generated_stardoc(name = "", input = "", deps = [], **kwargs):
21 | """Generates a Stardoc file and an associated build test.
22 |
23 | This rule generates a Markdown rule documentation file, using
24 | Stardoc.
25 |
26 | The generated file name will be {name}.md.
27 |
28 | Args:
29 | name: The basename of the output Markdown file (without an extension).
30 | input: The .bzl file to process.
31 | deps: A list of bzl_library targets imported by this file.
32 | **kwargs: Other parameters to the stardoc() macro.
33 | """
34 | doc_rule_name = name + "-stardoc"
35 | doc_name = name + "-doc.md"
36 | genrule_name = name + "-genrule"
37 | stardoc(
38 | name = doc_rule_name,
39 | input = input,
40 | deps = deps,
41 | out = doc_name,
42 | **kwargs
43 | )
44 |
45 | # Verify that the rule builds.
46 | build_test(
47 | name = name + "_test",
48 | targets = [genrule_name],
49 | )
50 |
--------------------------------------------------------------------------------
/bzl/generate_core_libraries.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Provides a macro to generate haskell_core_library rules for a GHC build."""
16 |
17 | load(
18 | "//bzl:def.bzl",
19 | "haskell_core_library",
20 | "haskell_library",
21 | )
22 | load(
23 | "//bzl/private:default_packages.bzl",
24 | "default_package_names",
25 | "nondefault_core_package_names",
26 | )
27 | load("@bazel_skylib//rules:build_test.bzl", "build_test")
28 |
29 | def generate_core_library_rules():
30 | """Creates haskell_core_library rules for the GHC build."""
31 | for name in nondefault_core_package_names + default_package_names:
32 | haskell_core_library(
33 | name = name,
34 | package = name,
35 | )
36 |
37 | default_packages_rule = "default_packages"
38 | haskell_library(
39 | name = default_packages_rule,
40 | visibility = ["//visibility:private"],
41 | deps = default_package_names,
42 | )
43 |
44 | build_test(
45 | name = "default_packages_build_test",
46 | targets = [default_packages_rule],
47 | )
48 |
--------------------------------------------------------------------------------
/bzl/happy.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Genrule for the Happy parser generator."""
16 |
17 | def genhappy(src, out, **kwargs):
18 | """Runs the Happy parser generator to create a Haskell source file.
19 |
20 | For more information, see https://haskell.org/happy.
21 |
22 | Example:
23 |
24 | load("//third_party/haskell/happy:build_defs.bzl", "genhappy")
25 |
26 | genhappy(
27 | src = "MyParser.y",
28 | out = "MyParser.hs"
29 | )
30 |
31 | haskell_binary(
32 | name = "MyParser",
33 | srcs = [ "MyParser.hs" ]
34 | ...
35 | )
36 |
37 | Args:
38 | src: The input Happy file (.y)
39 | out: The output Haskell source file (.hs).
40 | **kwargs: Other parameters for the underlying genrule.
41 | """
42 |
43 | native.genrule(
44 | name = out + ".hs_happy",
45 | srcs = [src],
46 | outs = [out],
47 | tools = ["//third_party/haskell/happy:happy_bin"],
48 | cmd = "$(location //third_party/haskell/happy:happy_bin) -g -a -c -o $(OUTS) $(SRCS)",
49 | **kwargs
50 | )
51 |
--------------------------------------------------------------------------------
/bzl/paths.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Utilities for handling filepaths."""
16 |
17 | def split_dirname(dirname):
18 | """Splits the capitalized suffix out from the given directories.
19 |
20 | Looks for the longest suffix that is CamelCased;
21 | specifically, where each directory starts with a capitalized letter.
22 |
23 | See go/haskell-standard-names for the motivation of this scheme.
24 |
25 | For example:
26 | split_dirname("abc/Def/Ghi") == ("abc", "Def/Ghi")
27 | split_dirname("abc/def") == ("abc/def", "")
28 |
29 | Args:
30 | dirname: A string; a path of directories separated by "/".
31 |
32 | Returns:
33 | A pair of (prefix, suffix) strings.
34 | """
35 | dirs = dirname.split("/")
36 |
37 | for i in range(len(dirs) - 1, -1, -1):
38 | if not dirs[i][0:1].isupper(): # Make sure to exclude symbols
39 | return ("/".join(dirs[0:(i + 1)]), "/".join(dirs[(i + 1):]))
40 |
41 | # Every component is lower-cased:
42 | return (dirname, "")
43 |
--------------------------------------------------------------------------------
/bzl/private/BUILD:
--------------------------------------------------------------------------------
1 | # Internal functions for the Haskell build rules.
2 | load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
3 |
4 | package(default_visibility = ["//bzl:__subpackages__"])
5 |
6 | bzl_library(
7 | name = "private",
8 | srcs = [
9 | "action.bzl",
10 | "archive.bzl",
11 | "binary.bzl",
12 | "cc.bzl",
13 | "compile.bzl",
14 | "compile_srcs_options.bzl",
15 | "default_packages.bzl",
16 | "ghc_options.bzl",
17 | "info.bzl",
18 | "library.bzl",
19 | "link.bzl",
20 | "module_names.bzl",
21 | "package.bzl",
22 | "proto_file.bzl",
23 | "providers.bzl",
24 | "runfiles.bzl",
25 | "toolchains.bzl",
26 | "@bazel_tools//tools/build_defs/cc:action_names.bzl",
27 | "@bazel_tools//tools/cpp:toolchain_utils.bzl",
28 | ],
29 | deps = [
30 | "@bazel_skylib//lib:paths",
31 | "//bzl:paths",
32 | "//bzl:settings",
33 | ],
34 | )
35 |
--------------------------------------------------------------------------------
/bzl/private/cc_api_test/BUILD:
--------------------------------------------------------------------------------
1 | # Tests of how we use the C++ Skylark API.
2 |
3 | load(":link.bzl", "cc_api_binary")
4 |
5 | cc_library(
6 | name = "lib",
7 | srcs = ["lib.cc"],
8 | )
9 |
10 | cc_api_binary(
11 | name = "binary",
12 | deps = [":lib"],
13 | )
14 |
15 | cc_binary(
16 | name = "comparison_binary",
17 | deps = [":lib"],
18 | )
19 |
--------------------------------------------------------------------------------
/bzl/private/cc_api_test/lib.cc:
--------------------------------------------------------------------------------
1 | #include
2 | int main() {
3 | std::cout << "Hello, world!\n";
4 | return 0;
5 | }
6 |
--------------------------------------------------------------------------------
/bzl/private/cc_api_test/link.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Example file for creating a C++ binary from the Starlark API."""
16 |
17 | load(
18 | "//bzl/private:cc.bzl",
19 | "cc_toolchain_attrs",
20 | "get_configured_cc_toolchain",
21 | "get_object_linking_args",
22 | "get_static_runtime_libs",
23 | "link_executable_command",
24 | )
25 | load("@bazel_skylib//lib:dicts.bzl", "dicts")
26 |
27 | def _impl_binary(ctx):
28 | output = ctx.actions.declare_file(ctx.label.name)
29 | libs = [
30 | lib
31 | for dep in ctx.attr.deps
32 | for lib in dep[CcInfo].linking_context.libraries_to_link.to_list()
33 | ]
34 |
35 | cc_toolchain = get_configured_cc_toolchain(ctx)
36 | static_runtime_libs = get_static_runtime_libs(ctx)
37 | object_args = [get_object_linking_args(lib) for lib in libs]
38 | link = link_executable_command(
39 | cc_toolchain,
40 | is_linking_dynamic_library = False,
41 | is_static_linking_mode = True,
42 | output_file = output.path,
43 | user_link_flags =
44 | [arg for oarg in object_args for arg in oarg.arguments] +
45 | [f.path for f in static_runtime_libs],
46 | )
47 |
48 | ctx.actions.run(
49 | executable = link.executable,
50 | arguments = link.arguments,
51 | inputs = depset(
52 | [input for oarg in object_args for input in oarg.inputs] +
53 | static_runtime_libs,
54 | transitive = [cc_toolchain.toolchain.all_files],
55 | ),
56 | outputs = [output],
57 | mnemonic = "HaskellTestCcLink",
58 | )
59 |
60 | return [DefaultInfo(executable = output)]
61 |
62 | cc_api_binary = rule(
63 | implementation = _impl_binary,
64 | executable = True,
65 | fragments = ["cpp"],
66 | attrs = dicts.add({
67 | "deps": attr.label_list(providers = [CcInfo]),
68 | }, cc_toolchain_attrs),
69 | )
70 |
--------------------------------------------------------------------------------
/bzl/private/default_packages.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """ A list of packages that every Haskell rule implicitly depends on.
16 |
17 | TODO(b/120225063): Reduce this list (or remove it entirely).
18 | """
19 | default_package_names = [
20 | "array",
21 | "base",
22 | "binary",
23 | "bytestring",
24 | "containers",
25 | "deepseq",
26 | "directory",
27 | "filepath",
28 | "ghc-prim",
29 | "integer-gmp",
30 | "mtl", # TODO(judahjacobson): Remove this
31 | "pretty",
32 | "process",
33 | "template-haskell",
34 | "terminfo",
35 | "text", # TODO(judahjacobson): Remove this
36 | "time",
37 | "transformers",
38 | "unix",
39 | ]
40 |
41 | # Packages that are:
42 | # - Part of the "core" GHC package DB
43 | # - Not otherwise present in //third_party/haskell, for example because
44 | # it's a dependency of the "ghc" package
45 | # - Not otherwise considered "default" packages. To use them, a rule
46 | # needs to depend on a corresponding haskell_core_library rule.
47 | nondefault_core_package_names = [
48 | "ghc",
49 | "ghc-boot",
50 | "ghc-boot-th",
51 | "ghci",
52 | "hpc",
53 | ]
54 |
55 | # All "core" packages that we get from the GHC installation,
56 | # rather than adding separately under third_party/haskell.
57 | core_package_names = default_package_names + nondefault_core_package_names
58 |
--------------------------------------------------------------------------------
/bzl/private/runfiles.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Functions for collecting runfiles of a rule."""
16 |
17 | def collect_runfiles(
18 | ctx,
19 | files = [],
20 | data = [],
21 | deps = []):
22 | """Collects runfiles for the current rule.
23 |
24 | Args:
25 | ctx: The current rule context.
26 | files: A list of Files to explicitly include in the output runfiles.
27 | Usually concerns the outputs of this rule.
28 | data: A list of targets to treat as "data". Their files and runfiles
29 | will both be collected into the output runfiles.
30 | deps: A list of targets to treat as "deps". Their runfiles
31 | (but not files) will be collected into the output runfiles.
32 |
33 | Returns:
34 | A ctx.runfiles that aggregates all of the inputs.
35 | """
36 | return ctx.runfiles(
37 | files = files,
38 | transitive_files = depset(
39 | transitive =
40 | [t[DefaultInfo].files for t in data] +
41 | [t[DefaultInfo].default_runfiles.files for t in data + deps],
42 | ),
43 | )
44 |
45 | runfile_attrs = {
46 | "data": attr.label_list(
47 | allow_files = True,
48 | doc = "Files needed by this rule at runtime.",
49 | ),
50 | }
51 |
--------------------------------------------------------------------------------
/bzl/private/toolchains.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Attributes and functions for getting build rule toolchains."""
16 |
17 | load("@bazel_skylib//lib:dicts.bzl", "dicts")
18 | load("//bzl:config.bzl", "HaskellCompilerInfo")
19 | load(
20 | "//bzl/private:cc.bzl",
21 | "cc_toolchain_attrs",
22 | "get_configured_cc_toolchain",
23 | )
24 |
25 | def get_toolchains(ctx):
26 | """Returns the GHC and C++ toolchains for a Haskell rule.
27 |
28 | Returns:
29 | A struct containing two fields:
30 | - haskell: A HaskellCompilerInfo provider
31 | - cc: A struct as returned by get_configured_cc_toolchain.
32 | """
33 | return struct(
34 | haskell = ctx.attr._ghc_config[HaskellCompilerInfo],
35 | cc = get_configured_cc_toolchain(ctx),
36 | )
37 |
38 | toolchains_attrs = dicts.add({
39 | "_ghc_config": attr.label(
40 | default = Label("//third_party/haskell/ghc:config"),
41 | ),
42 | }, cc_toolchain_attrs)
43 |
44 | toolchains_bootstrap_attrs = dicts.add({
45 | "_ghc_config": attr.label(
46 | default = Label("//third_party/haskell/ghc:config"),
47 | ),
48 | }, cc_toolchain_attrs)
49 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/BUILD:
--------------------------------------------------------------------------------
1 | load("//bzl:def.bzl", "haskell_library", "haskell_test")
2 |
3 | haskell_test(
4 | name = "GhcOptsTest",
5 | srcs = ["GhcOptsTest.hs"],
6 | ghcopts = [
7 | "-XCPP",
8 | "-DABC=123",
9 | "-DDEF=456",
10 | ],
11 | )
12 |
13 | # Test that we are passing linkopts when linking.
14 | # Set the number of capabilities
15 | haskell_test(
16 | name = "LinkoptsTest",
17 | srcs = ["LinkoptsTest.hs"],
18 | linkopts = ["-with-rtsopts=-N2"],
19 | )
20 |
21 | # Test that we are passing RTS options at compile time.
22 | haskell_test(
23 | name = "GhcRtsoptsTest",
24 | srcs = ["GhcRtsoptsTest.hs"],
25 | executes_deps_in_compile = True,
26 | ghc_rtsopts = ["-N2"], # Sets the number of capabilities
27 | )
28 |
29 | haskell_test(
30 | name = "MainIs",
31 | srcs = ["MainIs.hs"],
32 | main_is = "MainIs.foo",
33 | )
34 |
35 | cc_library(
36 | name = "runfiles_c",
37 | hdrs = ["runfiles_c.h"],
38 | data = ["file_c.txt"],
39 | )
40 |
41 | haskell_library(
42 | name = "RunfilesLib",
43 | srcs = ["RunfilesLib.hs"],
44 | data = ["file_lib.txt"],
45 | )
46 |
47 | # Test the "data" attribute by checking that this binary can read the files
48 | # specified by it and by its dependencies.
49 | haskell_test(
50 | name = "RunfilesMain",
51 | srcs = ["RunfilesMain.hs"],
52 | data = ["file_main.txt"],
53 | deps = [
54 | ":RunfilesLib",
55 | ":runfiles_c",
56 | ],
57 | )
58 |
59 | haskell_test(
60 | name = "LiterateHaskell",
61 | srcs = ["LiterateHaskell.lhs"],
62 | )
63 |
64 | haskell_test(
65 | name = "DefaultOptions",
66 | srcs = ["DefaultOptions.hs"],
67 | )
68 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/DefaultOptions.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- Test that we use the ghc_config rule's "default_options" attr
16 | -- when compiling Haskell code.
17 | -- This test in particular checks that we've enabled ScopedTypeVariables,
18 | -- which is currently a default option.
19 | -- If we remove ScopedTypeVariables as a default option, this test may start
20 | -- failing, in which case we should check for a different flag.
21 | module Main where
22 |
23 | main = myId $ return ()
24 |
25 | -- NOTE: this tests that we use the config default_options field.
26 | -- Specifically, it checks that we enable ScopedTypeVariables. Without that
27 | -- option, we'd get an error like "Illegal symbol '.' in type".
28 | -- If that behavior ever changes, this test will need to be updated.
29 | myId :: forall a . a -> a
30 | myId = id
31 |
32 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/GhcOptsTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Control.Monad (guard)
18 |
19 | main = do
20 | guard (foo1 == 123)
21 | guard (foo2 == 456)
22 |
23 | foo1, foo2 :: Int
24 | foo1 = ABC
25 | foo2 = DEF
26 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/GhcRtsoptsTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE TemplateHaskell #-}
16 | module Main (main) where
17 |
18 | import Control.Monad (guard)
19 | import GHC.Conc (numCapabilities)
20 | import Language.Haskell.TH (litE, Lit(..))
21 |
22 | main :: IO ()
23 | main = do
24 | -- Record the number of capabilities at compile-time.
25 | -- Note: don't *check* the value at compile-time, since that would unnecessary
26 | -- break analysis tools like Grok.
27 | let compileTimeCapabilities = $(litE $ IntegerL $ toEnum numCapabilities)
28 | putStrLn $ "Number of capabilities: " ++ show compileTimeCapabilities
29 | guard (compileTimeCapabilities == 2)
30 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/LinkoptsTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main (main) where
16 |
17 | import Control.Monad (guard)
18 | import GHC.Conc (numCapabilities)
19 |
20 | main :: IO ()
21 | main = do
22 | putStrLn $ "Number of capabilities: " ++ show numCapabilities
23 | guard (numCapabilities == 2)
24 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/LiterateHaskell.lhs:
--------------------------------------------------------------------------------
1 | This is a comment.
2 |
3 | > module Main where
4 |
5 | Another comment
6 |
7 | > main = return ()
8 |
9 |
10 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/MainIs.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module MainIs where
16 |
17 | foo = print "hello"
18 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/RunfilesLib.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module RunfilesLib where
16 |
17 | libFileName :: String
18 | libFileName = "file_lib.txt"
19 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/RunfilesMain.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import RunfilesLib
18 |
19 | -- | Check that we can read the runfiles from this binary rule and its
20 | -- dependencies.
21 | -- Don't bother using any special logic to find the runfiles dir,
22 | -- since the Haskell code for that isn't ported to Skylark yet.
23 | -- In general, anyway, we'll only run this test from "bazel test" or on
24 | -- Forge, where no special logic is necessary.
25 | main = mapM_ (\f -> readFile ("tools/build_defs/haskell/tests/attrs/" ++ f)
26 | >>= putStrLn)
27 | [libFileName, "file_c.txt", "file_main.txt"]
28 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/file_c.txt:
--------------------------------------------------------------------------------
1 | c
2 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/file_lib.txt:
--------------------------------------------------------------------------------
1 | lib
2 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/file_main.txt:
--------------------------------------------------------------------------------
1 | main
2 |
--------------------------------------------------------------------------------
/bzl/tests/attrs/runfiles_c.h:
--------------------------------------------------------------------------------
1 | #ifndef TOOLS_BUILD_DEFS_HASKELL_TESTS_ATTRS_RUNFILES_C_H_
2 | #define TOOLS_BUILD_DEFS_HASKELL_TESTS_ATTRS_RUNFILES_C_H_
3 |
4 | // Dummy file to test runfiles propagating from deps
5 |
6 | #endif // TOOLS_BUILD_DEFS_HASKELL_TESTS_ATTRS_RUNFILES_C_H_
7 |
--------------------------------------------------------------------------------
/bzl/tests/cabal_path/BUILD:
--------------------------------------------------------------------------------
1 | load("//bzl:def.bzl", "haskell_test")
2 | load("//bzl/cabal_package:cabal_paths.bzl", "cabal_paths")
3 |
4 | cabal_paths(
5 | name = "foo_paths",
6 | out = "Paths_foo.hs",
7 | package = "foo",
8 | version = [
9 | 1,
10 | 2,
11 | ],
12 | )
13 |
14 | cabal_paths(
15 | name = "bar_paths",
16 | out = "Paths_bar.hs",
17 | data_dir = "subdir",
18 | package = "bar",
19 | version = [
20 | 3,
21 | 4,
22 | ],
23 | )
24 |
25 | haskell_test(
26 | name = "PathsTest",
27 | srcs = [
28 | "PathsTest.hs",
29 | ":bar_paths",
30 | ":foo_paths",
31 | ],
32 | data = [
33 | "foo.txt",
34 | "subdir/bar.txt",
35 | ],
36 | default_packages = [],
37 | # TODO(b/139358194): build_cleaner can't handle this mix of generated and
38 | # checked-in sources.
39 | tags = ["nofixdeps"],
40 | deps = ["//bzl/cabal_package:PathDeps"],
41 | )
42 |
--------------------------------------------------------------------------------
/bzl/tests/cabal_path/PathsTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import qualified Paths_foo
18 | import qualified Paths_bar
19 |
20 | import Data.Version (versionBranch)
21 | import System.FilePath ((>))
22 | import Control.Monad (guard)
23 |
24 | main = do
25 | -- Test getDataDir for a cabal_paths rule with a trivial data_dir.
26 | fooDir <- Paths_foo.getDataDir
27 | fooContents <- readFile (fooDir > "foo.txt")
28 | guard (fooContents == "foo\n")
29 | guard (versionBranch Paths_foo.version == [1, 2])
30 | -- Test getDataDir with a nontrivial data_dir.
31 | barDir <- Paths_bar.getDataDir
32 | barContents <- readFile (barDir > "bar.txt")
33 | guard (barContents == "bar\n")
34 | guard (versionBranch Paths_bar.version == [3, 4])
35 | -- Test getDataFileName.
36 | fooByName <- Paths_bar.getDataFileName "bar.txt" >>= readFile
37 | guard (fooByName == "bar\n")
38 |
--------------------------------------------------------------------------------
/bzl/tests/cabal_path/foo.txt:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/bzl/tests/cabal_path/subdir/bar.txt:
--------------------------------------------------------------------------------
1 | bar
2 |
--------------------------------------------------------------------------------
/bzl/tests/dep_on_haskell/BUILD:
--------------------------------------------------------------------------------
1 | # Test that C++ can depend on Haskell.
2 |
3 | load("//bzl:def.bzl", "haskell_library")
4 |
5 | haskell_library(
6 | name = "Lib",
7 | srcs = [
8 | "Internal/Inc.hs",
9 | "Lib.hs",
10 | "Sub/Lib.hs",
11 | ],
12 | foreign_exports = [
13 | "Lib",
14 | "Sub.Lib",
15 | ],
16 | )
17 |
18 | # A C++ binary than depends on a Haskell library.
19 | cc_test(
20 | name = "test",
21 | size = "small",
22 | srcs = ["test.cc"],
23 | # TODO(b/144594873): Don't require this.
24 | features = ["-layering_check"],
25 | deps = [
26 | ":Lib",
27 | "//third_party/haskell/ghc:headers",
28 | ],
29 | )
30 |
31 | cc_library(
32 | name = "clib",
33 | srcs = ["clib.c"],
34 | )
35 |
36 | haskell_library(
37 | name = "CDep",
38 | srcs = ["CDep.hs"],
39 | foreign_exports = [
40 | "CDep",
41 | ],
42 | deps = [":clib"],
43 | )
44 |
45 | cc_test(
46 | name = "cdep_test",
47 | srcs = ["cdep_test.cc"],
48 | # TODO(b/144594873): Don't require this.
49 | features = ["-layering_check"],
50 | deps = [
51 | ":CDep",
52 | "//third_party/haskell/ghc:headers",
53 | ],
54 | )
55 |
--------------------------------------------------------------------------------
/bzl/tests/dep_on_haskell/CDep.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE ForeignFunctionInterface #-}
16 | module CDep () where
17 |
18 | foreign import ccall "plus_42" plus42 :: Int -> Int
19 | foreign export ccall plus43 :: Int -> Int
20 |
21 | plus43 :: Int -> Int
22 | plus43 x = 1 + plus42 x
23 |
--------------------------------------------------------------------------------
/bzl/tests/dep_on_haskell/Internal/Inc.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Internal.Inc (inc) where
16 |
17 | inc :: Int -> Int
18 | inc x = x + 1
19 |
--------------------------------------------------------------------------------
/bzl/tests/dep_on_haskell/Lib.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE ForeignFunctionInterface #-}
16 |
17 | module Lib where
18 |
19 | import Internal.Inc (inc)
20 |
21 | inc2 :: Int -> Int
22 | inc2 = inc . inc
23 |
24 | foreign export ccall inc2 :: Int -> Int
25 |
--------------------------------------------------------------------------------
/bzl/tests/dep_on_haskell/Sub/Lib.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE ForeignFunctionInterface #-}
16 |
17 | module Sub.Lib where
18 |
19 | import Internal.Inc (inc)
20 |
21 | inc3 :: Int -> Int
22 | inc3 = inc . inc . inc
23 |
24 | foreign export ccall inc3 :: Int -> Int
25 |
--------------------------------------------------------------------------------
/bzl/tests/dep_on_haskell/cdep_test.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "HsFFI.h"
4 | #include "tools/build_defs/haskell/tests/dep_on_haskell/CDep.stub/CDep_stub.h"
5 |
6 | int main(int argc, char **argv) {
7 | hs_init(&argc, &argv);
8 | int result = plus43(1);
9 | hs_exit();
10 | if (result != 44) {
11 | std::cerr << "Incorrect result; expected 43, got: " << result << "\n";
12 | return 1;
13 | }
14 | return 0;
15 | }
16 |
--------------------------------------------------------------------------------
/bzl/tests/dep_on_haskell/clib.c:
--------------------------------------------------------------------------------
1 | int plus_42(int x) { return x + 42; }
2 |
--------------------------------------------------------------------------------
/bzl/tests/dep_on_haskell/test.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "HsFFI.h"
4 | #include "tools/build_defs/haskell/tests/dep_on_haskell/Lib.stub/Lib_stub.h"
5 | #include "tools/build_defs/haskell/tests/dep_on_haskell/Lib.stub/Sub/Lib_stub.h"
6 |
7 | int main(int argc, char **argv) {
8 | hs_init(&argc, &argv);
9 | std::cout << inc2(1) << "\n";
10 | std::cout << inc3(1) << "\n";
11 | hs_exit();
12 | return 0;
13 | }
14 |
--------------------------------------------------------------------------------
/bzl/tests/dynamic/BUILD:
--------------------------------------------------------------------------------
1 | # Test Haskell targets with the "linkstatic" option.
2 |
3 | load("//bzl:def.bzl", "haskell_binary", "haskell_library", "haskell_test")
4 |
5 | haskell_library(
6 | name = "Library",
7 | srcs = ["Library.hs"],
8 | )
9 |
10 | haskell_binary(
11 | name = "Binary",
12 | srcs = ["Binary.hs"],
13 | linkstatic = False,
14 | deps = [":Library"],
15 | )
16 |
17 | haskell_test(
18 | name = "BinaryRunfilesTest",
19 | srcs = ["BinaryRunfilesTest.hs"],
20 | args = ["Binary"],
21 | data = [":Binary"],
22 | deps = [
23 | # TODO
24 | ],
25 | )
26 |
27 | haskell_test(
28 | name = "Test",
29 | srcs = ["Binary.hs"],
30 | linkstatic = False,
31 | deps = [":Library"],
32 | )
33 |
34 | # Link against a library in a different directory, to confirm
35 | # that we wire up the rpath correctly.
36 | haskell_test(
37 | name = "SubdirTest",
38 | srcs = ["Binary.hs"],
39 | linkstatic = False,
40 | deps = ["//bzl/tests/dynamic/subdir:Library"],
41 | )
42 |
43 | haskell_test(
44 | name = "FfiTest",
45 | srcs = ["FfiTest.hs"],
46 | linkstatic = False,
47 | deps = ["//bzl/tests/dynamic/subdir:CLibrary"],
48 | )
49 |
50 | haskell_binary(
51 | name = "FfiBinary",
52 | srcs = ["FfiTest.hs"],
53 | linkstatic = False,
54 | deps = ["//bzl/tests/dynamic/subdir:CLibrary"],
55 | )
56 |
57 | haskell_test(
58 | name = "FfiBinaryRunfilesTest",
59 | srcs = ["BinaryRunfilesTest.hs"],
60 | args = ["FfiBinary"],
61 | data = [":FfiBinary"],
62 | deps = [
63 | # TODO
64 | ],
65 | )
66 |
67 | cc_test(
68 | name = "cbin",
69 | srcs = ["bin.cc"],
70 | )
71 |
72 | cc_library(
73 | name = "flag_provider",
74 | srcs = ["flag_provider.cc"],
75 | deps = [
76 | "@com_google_absl//absl/flags:flag",
77 | ],
78 | alwayslink = 1,
79 | )
80 |
81 | haskell_test(
82 | name = "FlagProviderDynamicTest",
83 | srcs = ["FlagProviderTest.hs"],
84 | linkstatic = False,
85 | deps = [
86 | ":flag_provider",
87 | # TODO
88 | ],
89 | )
90 |
91 | # For comparison, a version of the test that links statically:
92 | haskell_test(
93 | name = "FlagProviderStaticTest",
94 | srcs = ["FlagProviderTest.hs"],
95 | linkstatic = True,
96 | deps = [
97 | ":flag_provider",
98 | # TODO
99 | ],
100 | )
101 |
--------------------------------------------------------------------------------
/bzl/tests/dynamic/Binary.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Library
18 |
19 | main = print value
20 |
--------------------------------------------------------------------------------
/bzl/tests/dynamic/BinaryRunfilesTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- | This test checks that a linkstatic=False binary can be run
16 | -- in isolation, using its .runfiles directory to load the shared libraries it
17 | -- depends on.
18 | --
19 | -- Binary
20 | -- Binary.runfiles/{WORKSPACE}/...
21 | --
22 | -- This file organization might happen in the deployment of such a binary.
23 | module Main (main) where
24 |
25 | import Google.Runtime.BuildHelper (findRunfilesDirOrDie)
26 | import System.Directory (createDirectory, setCurrentDirectory)
27 | import System.Environment (getArgs)
28 | import System.FilePath ((>))
29 | import System.IO.Temp -- (withSystemTempDirectory)
30 | import System.Process (callProcess)
31 |
32 | main :: IO ()
33 | main = do
34 | -- This test is parameterized on the particular binary that we're testing.
35 | [binaryName] <- getArgs
36 | runfiles <- findRunfilesDirOrDie
37 | let binary = runfiles >
38 | "cabal2bazel/tools/build_defs/haskell/tests/dynamic" >
39 | binaryName
40 | withSystemTempDirectory "BinaryRunfilesTest" $ \tmp -> do
41 | -- Move into a temporary directory, to confirm that we're only using
42 | -- guidance from the binary and not the setup of this test.
43 | let workingDir = tmp > "working"
44 | createDirectory workingDir
45 | setCurrentDirectory workingDir
46 |
47 | -- Run the binary as it is in the runfiles directory. This is the same
48 | -- setup as in a "bazel test" of a target, other than using a different
49 | -- working directory.
50 | callProcess binary []
51 |
52 | -- Run the binary in a separate directory, with a parallel ".runfiles"
53 | -- directory next to it.
54 | -- Note: the .runfiles contains all the runfiles of this *test*, which is
55 | -- strictly greater than just of the binary that the test uses. But
56 | -- that shouldn't matter for this purpose.
57 | let isolatedBinary = tmp > binaryName
58 | callProcess "cp" ["-R", binary, isolatedBinary]
59 | callProcess "cp" ["-R", runfiles, isolatedBinary ++ ".runfiles"]
60 | callProcess isolatedBinary []
61 |
--------------------------------------------------------------------------------
/bzl/tests/dynamic/FfiTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main (main) where
16 |
17 | import Control.Monad (guard)
18 |
19 | import CLibrary (triple)
20 |
21 | main :: IO ()
22 | main = guard (triple 14 == 42)
23 |
--------------------------------------------------------------------------------
/bzl/tests/dynamic/FlagProviderTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE OverloadedStrings #-}
16 | -- | Tests that we run the constructors for alwayslink dependencies.
17 | -- Nothing in this module explicitly links against the C++ library
18 | -- that defines the "flag_provider_test_flag"; we're relying on the constructor
19 | -- in that library to define the flag automatically.
20 | module Main (main) where
21 |
22 | import Control.Monad (guard, void)
23 | import Google.Base.Flags (getAll, Info(..))
24 |
25 | main :: IO ()
26 | main = do
27 | allFlags <- getAll
28 | guard (any isExpectedTestFlag allFlags)
29 |
30 | isExpectedTestFlag :: Info -> Bool
31 | isExpectedTestFlag i = fiName i == "flag_provider_test_flag"
32 |
--------------------------------------------------------------------------------
/bzl/tests/dynamic/Library.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Library where
16 |
17 | value = "hello"
18 |
--------------------------------------------------------------------------------
/bzl/tests/dynamic/bin.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main() {
4 | std::cout << "Hello\n";
5 | return 0;
6 | }
7 |
--------------------------------------------------------------------------------
/bzl/tests/dynamic/flag_provider.cc:
--------------------------------------------------------------------------------
1 | #include "third_party/absl/flags/flag.h"
2 |
3 | ABSL_FLAG(std::string, flag_provider_test_flag, "test_value", "A test flag");
4 |
--------------------------------------------------------------------------------
/bzl/tests/dynamic/subdir/BUILD:
--------------------------------------------------------------------------------
1 | # Helper targets for testing the linkstatic attribute.
2 | load("//bzl:def.bzl", "haskell_library")
3 |
4 | package(default_visibility = ["//bzl/tests/dynamic:__pkg__"])
5 |
6 | haskell_library(
7 | name = "Library",
8 | srcs = ["Library.hs"],
9 | )
10 |
11 | cc_library(
12 | name = "clib",
13 | srcs = ["clib.cc"],
14 | )
15 |
16 | haskell_library(
17 | name = "CLibrary",
18 | srcs = ["CLibrary.hs"],
19 | deps = [":clib"],
20 | )
21 |
--------------------------------------------------------------------------------
/bzl/tests/dynamic/subdir/CLibrary.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE ForeignFunctionInterface #-}
16 | module CLibrary (triple) where
17 |
18 | foreign import ccall triple :: Int -> Int
19 |
--------------------------------------------------------------------------------
/bzl/tests/dynamic/subdir/Library.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Library where
16 |
17 | value = "hello"
18 |
--------------------------------------------------------------------------------
/bzl/tests/dynamic/subdir/clib.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | extern "C" {
4 | int triple(int x) {
5 | std::cout << "Input=" << x << "\n";
6 | return 3 * x;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/AlwaysLinkTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE ForeignFunctionInterface #-}
16 | module Main where
17 |
18 | import Foreign.C.Types (CInt(..))
19 |
20 | foreign import ccall user :: CInt -> CInt
21 |
22 | main = print $ user 3
23 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/ExtraObjsForward.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module ExtraObjsForward (quadruple) where
16 |
17 | import ExtraObjsLib (triple)
18 |
19 | -- Create a new definition to force linking to go through this library
20 | quadruple :: Integer -> Integer
21 | quadruple x = triple x + x
22 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/ExtraObjsJoinedTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE TemplateHaskell #-}
16 | module Main (main) where
17 |
18 | import Control.Monad (guard)
19 | import ExtraObjsForward (quadruple)
20 | import Language.Haskell.TH
21 |
22 | result :: Integer
23 | result = $(litE $ IntegerL $ quadruple 2) -- Use the FFI within TemplateHaskell
24 |
25 | main :: IO ()
26 | main = guard (8 == result)
27 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/ExtraObjsLib.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE TemplateHaskell #-}
16 | {-# LANGUAGE ForeignFunctionInterface #-}
17 | module ExtraObjsLib (triple) where
18 |
19 | import Foreign.C (CInt(..))
20 |
21 | triple :: Integer -> Integer
22 | triple = fromIntegral . c_triple . fromIntegral
23 |
24 | foreign import ccall "triple" c_triple :: CInt -> CInt
25 |
26 | -- Test that we can use TemplateHaskell in a module with FFI.
27 | -- Note that GHC has a staging restriction that prevents the splice
28 | -- from using functions defined or imported directly in this module.
29 | $(return [])
30 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/ExtraObjsTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE TemplateHaskell #-}
16 | module Main (main) where
17 |
18 | import Control.Monad (guard)
19 | import ExtraObjsLib (triple)
20 | import Language.Haskell.TH
21 |
22 | result :: Integer
23 | result = $(litE $ IntegerL $ triple 2) -- Use the FFI within TemplateHaskell
24 |
25 | main :: IO ()
26 | main = guard (6 == result)
27 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/Foo.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE ForeignFunctionInterface #-}
16 | module Foo (foo) where
17 |
18 | import Foreign.C.Types
19 |
20 | foreign import ccall foo :: CInt -> CInt
21 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/HeadersLib.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE CPP #-}
16 | module HeadersLib (bar) where
17 |
18 | #include "header_provider.h"
19 |
20 | bar = BAR
21 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/HeadersTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE CPP #-}
16 | module Main(main) where
17 |
18 | import HeadersLib (bar)
19 | import Control.Monad (guard)
20 |
21 | #include "header_provider.h"
22 |
23 | foo = FOO
24 | main = do
25 | guard (foo == 42)
26 | guard (bar == 17)
27 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/LinkInputsTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main (main) where
16 |
17 | main :: IO ()
18 | main = return ()
19 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/SimpleFFI.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE ForeignFunctionInterface #-}
16 | module Main where
17 |
18 | import Foreign.C.Types (CInt(..))
19 |
20 | foreign import ccall foo :: CInt -> CInt
21 |
22 | main = print $ foo 3
23 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/Stub.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE ForeignFunctionInterface #-}
16 | module Stub (wrapCallback) where
17 |
18 | import Foreign.Ptr (FunPtr)
19 |
20 | type Callback = IO ()
21 | foreign import ccall "wrapper"
22 | wrapCallback :: Callback -> IO (FunPtr Callback)
23 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/StubTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Stub
18 |
19 | main = wrapCallback (return ()) >>= print
20 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/TemplateHaskellBaseTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE TemplateHaskell #-}
16 | module Main (main) where
17 |
18 | import Control.Monad (guard)
19 | import Foo (foo)
20 | import Language.Haskell.TH
21 |
22 | result :: Integer
23 | -- Uses the FFI within TemplateHaskell:
24 | result = $(litE $ IntegerL $ fromIntegral $ foo 3)
25 |
26 | main :: IO ()
27 | main = guard (15 == result)
28 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/TransitiveFFI.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Foo (foo)
18 |
19 | main = print $ foo 3
20 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/dynamic.lds:
--------------------------------------------------------------------------------
1 | {foo;};
2 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/extra_objs_direct.cc:
--------------------------------------------------------------------------------
1 | extern "C" int triple(int x) {
2 | return 3 * x;
3 | }
4 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/foo.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "third_party/absl/strings/str_format.h"
4 |
5 | extern "C" int foo(int x) {
6 | std::cout << absl::StrFormat("HELLO %d\n", x);
7 | return 5 * x;
8 | }
9 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/provider.cc:
--------------------------------------------------------------------------------
1 | int provider(int x) { return 5 * x; }
2 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/three.cc:
--------------------------------------------------------------------------------
1 | int three() { return 3; }
2 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/three.h:
--------------------------------------------------------------------------------
1 | #ifndef TOOLS_BUILD_DEFS_HASKELL_TESTS_FFI_THREE_H_
2 | #define TOOLS_BUILD_DEFS_HASKELL_TESTS_FFI_THREE_H_
3 |
4 | int three();
5 |
6 | #endif // TOOLS_BUILD_DEFS_HASKELL_TESTS_FFI_THREE_H_
7 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/transitive_objs.cc:
--------------------------------------------------------------------------------
1 | // Test an implicit dependency on libsdtc++
2 | #include
3 |
4 | #include "tools/build_defs/haskell/tests/ffi/three.h"
5 |
6 | extern "C" int triple(int x) {
7 | std::cout << "Hello\n";
8 | return three() * x;
9 | }
10 |
--------------------------------------------------------------------------------
/bzl/tests/ffi/user.cc:
--------------------------------------------------------------------------------
1 | // Defined in provider.cc
2 | int provider(int x);
3 |
4 | extern "C" {
5 | int user(int x) { return 3 * provider(x); }
6 | };
7 |
--------------------------------------------------------------------------------
/bzl/tests/hierarchical/BUILD:
--------------------------------------------------------------------------------
1 | # Test that we handle all the corner cases of hierarchical modules.
2 | # (See also the "Sub" subdirectory.)
3 |
4 | load("//bzl:def.bzl", "haskell_library", "haskell_test")
5 |
6 | # A rule where the srcs correspond to the module hierarchy.
7 | haskell_library(
8 | name = "FooGroup",
9 | srcs = [
10 | "Foo.hs",
11 | "Foo/Bar.hs",
12 | ],
13 | )
14 |
15 | # Re-export a library (since this rule doesn't have any srcs).
16 | haskell_library(
17 | name = "ReExport",
18 | deps = [":FooGroup"],
19 | )
20 |
21 | # A module that uses the functions in FooGroup.
22 | haskell_library(
23 | name = "Baz",
24 | srcs = ["Baz.hs"],
25 | deps = [":ReExport"],
26 | )
27 |
28 | # Another layer of indirection, to make sure that the FooGroup's GHC package DB
29 | # is passed up transitively.
30 | haskell_library(
31 | name = "Baz2",
32 | srcs = ["Baz2.hs"],
33 | deps = [":Baz"],
34 | )
35 |
36 | # A binary that depends on everything above.
37 | haskell_test(
38 | name = "mybinary",
39 | srcs = ["Main.hs"],
40 | deps = [":Baz2"],
41 | )
42 |
43 | # A rule with the same name as one in the "Sub" directory.
44 | haskell_library(
45 | name = "DupeName",
46 | srcs = ["DupeName.hs"],
47 | deps = [
48 | "//bzl/tests/hierarchical/Sub:DupeName",
49 | ],
50 | )
51 |
52 | # Check that we can link against two libraries with the same name in different
53 | # directories.
54 | haskell_test(
55 | name = "DupeNameTest",
56 | srcs = ["DupeNameTest.hs"],
57 | deps = [":DupeName"],
58 | )
59 |
--------------------------------------------------------------------------------
/bzl/tests/hierarchical/Baz.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Baz where
16 |
17 | import Foo
18 | import Foo.Bar
19 |
20 | baz = foo + bar
21 |
--------------------------------------------------------------------------------
/bzl/tests/hierarchical/Baz2.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Baz2 where
16 |
17 | import Baz
18 |
19 | baz2 = 2 * baz
20 |
--------------------------------------------------------------------------------
/bzl/tests/hierarchical/DupeName.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module DupeName (parentFoo) where
16 |
17 | import Sub.DupeName
18 |
19 | parentFoo = length subFoo
20 |
--------------------------------------------------------------------------------
/bzl/tests/hierarchical/DupeNameTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main (main) where
16 |
17 | import Control.Monad (guard)
18 |
19 | import DupeName (parentFoo)
20 |
21 | main = guard (parentFoo == 100)
22 |
--------------------------------------------------------------------------------
/bzl/tests/hierarchical/Foo.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Foo where
16 |
17 | -- We should be able to use the "containers" package automatically,
18 | -- since it's a default GHC package.
19 | import qualified Data.Map as Map
20 |
21 | foo :: Int
22 | foo = length $ Map.toList $ Map.fromList [(1,1),(2,2),(3,3)]
23 |
--------------------------------------------------------------------------------
/bzl/tests/hierarchical/Foo/Bar.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Foo.Bar where
16 |
17 | bar :: Int
18 | bar = 5
19 |
--------------------------------------------------------------------------------
/bzl/tests/hierarchical/Main.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Baz2
18 |
19 | main = print baz2
20 |
--------------------------------------------------------------------------------
/bzl/tests/hierarchical/Sub/BUILD:
--------------------------------------------------------------------------------
1 | # Test that "package_prefix" lets us build modules within the module hierarchy.
2 |
3 | load("//bzl:def.bzl", "haskell_library", "haskell_test")
4 |
5 | # A rule to generate the Sub.Foo module.
6 | haskell_library(
7 | name = "Foo",
8 | srcs = ["Foo.hs"],
9 | )
10 |
11 | haskell_test(
12 | name = "FooTest",
13 | srcs = ["FooTest.hs"],
14 | deps = [":Foo"],
15 | )
16 |
17 | # A rule that has the same name as something in the parent directory.
18 | haskell_library(
19 | name = "DupeName",
20 | srcs = ["DupeName.hs"],
21 | visibility = [
22 | "//bzl/tests/hierarchical:__pkg__",
23 | ],
24 | )
25 |
--------------------------------------------------------------------------------
/bzl/tests/hierarchical/Sub/DupeName.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Sub.DupeName (subFoo) where
16 |
17 | subFoo = [1..100]
18 |
--------------------------------------------------------------------------------
/bzl/tests/hierarchical/Sub/Foo.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Sub.Foo where
16 |
17 | foo = 3
18 |
--------------------------------------------------------------------------------
/bzl/tests/hierarchical/Sub/FooTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Control.Monad (guard)
18 |
19 | import Sub.Foo (foo)
20 |
21 | main = guard (foo == 3)
22 |
--------------------------------------------------------------------------------
/bzl/tests/hsc2hs/BUILD:
--------------------------------------------------------------------------------
1 | load("//bzl:def.bzl", "haskell_test")
2 | load("//bzl:hsc2hs.bzl", "hsc2hs")
3 | load("@bazel_skylib//rules:build_test.bzl", "build_test")
4 |
5 | hsc2hs(
6 | name = "Foo",
7 | src = "Foo.hsc",
8 | out = "Foo.hs",
9 | deps = ["//test_support:hsc2hs_dep"],
10 | )
11 |
12 | haskell_test(
13 | name = "FooTest",
14 | srcs = [":Foo"],
15 | )
16 |
17 | # Test we can have two hsc2hs() rules on the same input file:
18 | hsc2hs(
19 | name = "Foo2",
20 | src = "Foo.hsc",
21 | out = "Foo2.hsc",
22 | deps = ["//test_support:hsc2hs_dep"],
23 | )
24 |
25 | build_test(
26 | name = "Foo2BuildTest",
27 | targets = [":Foo2"],
28 | )
29 |
--------------------------------------------------------------------------------
/bzl/tests/hsc2hs/Foo.hsc:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | #include "hsc2hs_dep.h"
4 |
5 | fooSize = #size foo
6 |
7 | #ifndef __GLASGOW_HASKELL__
8 | #error "The macro __GLASGOW_HASKELL__ isn't defined"
9 | #endif
10 |
11 | main = print fooSize
12 |
--------------------------------------------------------------------------------
/bzl/tests/plugins/BUILD:
--------------------------------------------------------------------------------
1 | load(
2 | "//bzl:def.bzl",
3 | "haskell_library",
4 | "haskell_test",
5 | )
6 |
7 | haskell_test(
8 | name = "PluginsTest",
9 | srcs = ["PluginsTest.hs"],
10 | plugins = [
11 | # TODO: ghc-typelits-knownnat
12 | ],
13 | )
14 |
15 | haskell_library(
16 | name = "PluginsLib",
17 | srcs = ["PluginsLib.hs"],
18 | plugins = [
19 | # TODO: ghc-typelits-knownnat
20 | ],
21 | )
22 |
23 | haskell_test(
24 | name = "PluginsLibTest",
25 | srcs = ["PluginsLibTest.hs"],
26 | deps = [":PluginsLib"],
27 | )
28 |
--------------------------------------------------------------------------------
/bzl/tests/plugins/PluginsLib.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- | Test that we can load and use GHC plugins.
16 | {-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-}
17 | {-# LANGUAGE DataKinds #-}
18 | {-# LANGUAGE ScopedTypeVariables #-}
19 | {-# LANGUAGE TypeOperators #-}
20 | module PluginsLib (two) where
21 |
22 | import Data.Proxy
23 | import GHC.TypeLits
24 |
25 | -- | Requires ghc-typelits-knownnat to solve its constraints:
26 | plusOne :: forall n . KnownNat n => Proxy n -> Integer
27 | plusOne _ = natVal (Proxy :: Proxy (n + 1))
28 |
29 | two :: Integer
30 | two = plusOne (Proxy :: Proxy 1)
31 |
--------------------------------------------------------------------------------
/bzl/tests/plugins/PluginsLibTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- | Test that we can load and use GHC plugins in a library.
16 | module Main (main) where
17 |
18 | import Control.Monad (guard)
19 | import PluginsLib (two)
20 |
21 | main :: IO ()
22 | main = guard (2 == two)
23 |
--------------------------------------------------------------------------------
/bzl/tests/plugins/PluginsTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- | Test that we can load and use GHC plugins.
16 | {-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-}
17 | {-# LANGUAGE DataKinds #-}
18 | {-# LANGUAGE ScopedTypeVariables #-}
19 | {-# LANGUAGE TypeOperators #-}
20 | module Main (main) where
21 |
22 | import Control.Monad (guard)
23 | import Data.Proxy
24 | import GHC.TypeLits
25 |
26 | -- | Requires ghc-typelits-knownnat to solve its constraints:
27 | plusOne :: forall n . KnownNat n => Proxy n -> Integer
28 | plusOne _ = natVal (Proxy :: Proxy (n + 1))
29 |
30 | two :: Integer
31 | two = plusOne (Proxy :: Proxy 1)
32 |
33 | main :: IO ()
34 | main = guard (2 == two)
35 |
--------------------------------------------------------------------------------
/bzl/tests/preprocessor/BUILD:
--------------------------------------------------------------------------------
1 | load("//bzl:def.bzl", "haskell_library", "haskell_test")
2 |
3 | haskell_library(
4 | name = "PreprocessedLib",
5 | srcs = ["PreprocessedLib.hs"],
6 | preprocessor = ":pp",
7 | # Preprocessors aren't supported in the indexer (b/23957150)
8 | tags = ["no_grok"],
9 | )
10 |
11 | haskell_test(
12 | name = "PreprocessedTest",
13 | srcs = ["PreprocessedTest.hs"],
14 | preprocessor = ":pp",
15 | # Preprocessors aren't supported in the indexer (b/23957150)
16 | tags = ["no_grok"],
17 | deps = [":PreprocessedLib"],
18 | )
19 |
20 | sh_binary(
21 | name = "pp",
22 | srcs = ["pp.sh"],
23 | )
24 |
--------------------------------------------------------------------------------
/bzl/tests/preprocessor/PreprocessedLib.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module PreprocessedLib (one) where
16 |
17 | two = "one"
18 | -- pp.sh replaces TWO below with two defined above.
19 | one = TWO
20 |
--------------------------------------------------------------------------------
/bzl/tests/preprocessor/PreprocessedTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | import System.Exit (exitSuccess, exitFailure)
16 | import PreprocessedLib (one)
17 |
18 | two = "two"
19 |
20 | -- pp.sh replaces TWO below with two defined above.
21 | main = if one ++ TWO == "onetwo" then exitSuccess else exitFailure
22 |
--------------------------------------------------------------------------------
/bzl/tests/preprocessor/pp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -eu
4 |
5 | sed s/TWO/two/ < $2 > $3
6 |
--------------------------------------------------------------------------------
/bzl/tests/proto/BUILD:
--------------------------------------------------------------------------------
1 | load("//bzl:def.bzl", "haskell_proto_library", "haskell_test")
2 | load("@bazel_skylib//rules:build_test.bzl", "build_test")
3 |
4 | proto_library(
5 | name = "foo_proto",
6 | srcs = ["foo.proto"],
7 | )
8 |
9 | proto_library(
10 | name = "bar_proto",
11 | srcs = ["bar.proto"],
12 | deps = [":foo_proto"],
13 | )
14 |
15 | # A haskell_proto_library rule that depends (only) transitively on foo_proto.
16 | haskell_proto_library(
17 | name = "bar_haskell_pb",
18 | deps = [":bar_proto"],
19 | )
20 |
21 | haskell_test(
22 | name = "BarTest",
23 | srcs = ["BarTest.hs"],
24 | deps = [
25 | ":bar_haskell_pb",
26 | # TODO
27 | ],
28 | )
29 |
30 | proto_library(
31 | name = "bar_forwarded_proto",
32 | deps = [":bar_proto"],
33 | )
34 |
35 | haskell_proto_library(
36 | name = "bar_forwarded_haskell_pb",
37 | deps = [":bar_forwarded_proto"],
38 | )
39 |
40 | haskell_test(
41 | name = "BarForwardedTest",
42 | srcs = ["BarTest.hs"],
43 | deps = [
44 | ":bar_forwarded_haskell_pb",
45 | # TODO
46 | ],
47 | )
48 |
49 | # Make sure that proto-lens works with generated .proto files. It's a little
50 | # more tricky than hprotoc since proto-lens outputs the generated files
51 | # separately instead of as one tarball.
52 | genrule(
53 | name = "generate_proto_file",
54 | outs = ["generated.proto"],
55 | cmd = "echo 'syntax = \"proto2\";message Generated{};' > $@",
56 | )
57 |
58 | proto_library(
59 | name = "generated_proto",
60 | srcs = ["generated.proto"],
61 | )
62 |
63 | haskell_proto_library(
64 | name = "generated_haskell_pb",
65 | deps = [":generated_proto"],
66 | )
67 |
68 | haskell_test(
69 | name = "GeneratedTest",
70 | srcs = ["GeneratedTest.hs"],
71 | deps = [
72 | ":generated_haskell_pb",
73 | # TODO
74 | ],
75 | )
76 |
77 | # Check that we can use .proto files from subdirectories.
78 | proto_library(
79 | name = "sub_proto",
80 | srcs = ["sub_dir/sub.proto"],
81 | )
82 |
83 | haskell_proto_library(
84 | name = "sub_haskell_pb",
85 | deps = [":sub_proto"],
86 | )
87 |
88 | haskell_test(
89 | name = "SubTest",
90 | srcs = ["SubTest.hs"],
91 | deps = [
92 | ":sub_haskell_pb",
93 | # TODO
94 | ],
95 | )
96 |
97 | # Test that we can handle the camel-casing behavior of proto-lens-protoc.
98 | # In practice, our filenames will not be camel-cased, but path components might.
99 | # And in particular we should handle filenames with consecutive upper-case letters.
100 | proto_library(
101 | name = "camel_case_proto",
102 | srcs = ["CamelCASE.proto"],
103 | )
104 |
105 | haskell_proto_library(
106 | name = "camel_case_haskell_pb",
107 | deps = [":camel_case_proto"],
108 | )
109 |
110 | build_test(
111 | name = "camel_case_test",
112 | targets = [":camel_case_haskell_pb"],
113 | )
114 |
115 | # A proto library containing both a dash and an underscore.
116 | proto_library(
117 | name = "dashed-file_path_proto",
118 | srcs = ["dashed-file_path.proto"],
119 | )
120 |
121 | haskell_proto_library(
122 | name = "dashed-file_path_haskell_pb",
123 | deps = [":dashed-file_path_proto"],
124 | )
125 |
126 | haskell_test(
127 | name = "DashedFilePathTest",
128 | srcs = ["DashedFilePathTest.hs"],
129 | deps = [
130 | ":dashed-file_path_haskell_pb",
131 | # TODO
132 | ],
133 | )
134 |
--------------------------------------------------------------------------------
/bzl/tests/proto/BarTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Proto.Tools.BuildDefs.Haskell.Tests.Proto.Bar
18 | import Data.ProtoLens (defMessage)
19 |
20 | main = print (defMessage :: Bar)
21 |
--------------------------------------------------------------------------------
/bzl/tests/proto/CamelCASE.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto2";
2 |
3 | package camel_case;
4 |
5 | message CamelCase {}
6 |
--------------------------------------------------------------------------------
/bzl/tests/proto/CamelCaseDir/BUILD:
--------------------------------------------------------------------------------
1 | # Checks that haskell_proto_library/aspect work in CamelCased directories.
2 | load("//bzl:def.bzl", "haskell_proto_library", "haskell_test")
3 |
4 | proto_library(
5 | name = "foo_proto",
6 | srcs = ["foo.proto"],
7 | )
8 |
9 | haskell_proto_library(
10 | name = "foo_haskell_pb",
11 | deps = [":foo_proto"],
12 | )
13 |
14 | haskell_test(
15 | name = "CamelCaseDirTest",
16 | srcs = ["CamelCaseDirTest.hs"],
17 | deps = [
18 | ":foo_haskell_pb",
19 | # TODO
20 | ],
21 | )
22 |
23 | # Make sure this works even in the unlikely case that the rule name is upper-cased.
24 | proto_library(
25 | name = "UpperFoo_proto",
26 | srcs = ["foo.proto"],
27 | )
28 |
29 | haskell_proto_library(
30 | name = "UpperFoo_haskell_pb",
31 | deps = [":UpperFoo_proto"],
32 | )
33 |
34 | haskell_test(
35 | name = "CamelCaseDirUpperRuleTest",
36 | srcs = ["CamelCaseDirTest.hs"],
37 | deps = [
38 | ":foo_haskell_pb",
39 | # TODO
40 | ],
41 | )
42 |
--------------------------------------------------------------------------------
/bzl/tests/proto/CamelCaseDir/CamelCaseDirTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Proto.Tools.BuildDefs.Haskell.Tests.Proto.CamelCaseDir.Foo
18 | import Data.ProtoLens (defMessage)
19 |
20 | main = print (defMessage :: Foo)
21 |
--------------------------------------------------------------------------------
/bzl/tests/proto/CamelCaseDir/foo.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto2";
2 |
3 | package foo;
4 |
5 | message Foo {}
6 |
--------------------------------------------------------------------------------
/bzl/tests/proto/DashedFilePathTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Proto.Tools.BuildDefs.Haskell.Tests.Proto.DashedFilePath
18 | import Data.ProtoLens (defMessage)
19 |
20 | main = print (defMessage :: Foo)
21 |
--------------------------------------------------------------------------------
/bzl/tests/proto/GeneratedTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Proto.Tools.BuildDefs.Haskell.Tests.Proto.Generated
18 | import Data.ProtoLens (defMessage)
19 |
20 | main = print (defMessage :: Generated)
21 |
--------------------------------------------------------------------------------
/bzl/tests/proto/SubTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Proto.Tools.BuildDefs.Haskell.Tests.Proto.SubDir.Sub
18 | import Data.ProtoLens (defMessage)
19 |
20 | main = print (defMessage :: Sub)
21 |
--------------------------------------------------------------------------------
/bzl/tests/proto/bar.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto2";
2 |
3 | package bar;
4 |
5 | import "tools/build_defs/haskell/tests/proto/foo.proto";
6 |
7 | message Bar {
8 | optional foo.Foo foo = 1;
9 |
10 | optional Recurse recurse = 2;
11 | }
12 |
13 | // Test that recursive protos can be rendered,
14 | // since we've explicitly patched hprotoc for that case.
15 | message Recurse {
16 | optional Bar bar = 1;
17 | }
18 |
--------------------------------------------------------------------------------
/bzl/tests/proto/dashed-file_path.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto2";
2 |
3 | package dashed;
4 |
5 | message Foo {}
6 |
--------------------------------------------------------------------------------
/bzl/tests/proto/foo.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto2";
2 |
3 | package foo;
4 |
5 | message Foo {
6 | optional int32 foo = 1;
7 | }
8 |
--------------------------------------------------------------------------------
/bzl/tests/proto/sub_dir/sub.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto2";
2 |
3 | package sub;
4 |
5 | message Sub {}
6 |
--------------------------------------------------------------------------------
/bzl/tests/recursive/BUILD:
--------------------------------------------------------------------------------
1 | # Unit test that we can compile recursive modules with .hs-boot files.
2 |
3 | load("//bzl:def.bzl", "haskell_library", "haskell_test")
4 |
5 | haskell_library(
6 | name = "Recursive",
7 | srcs = [
8 | "Boot.hs",
9 | "Boot.hs-boot",
10 | "Regular.hs",
11 | ],
12 | )
13 |
14 | haskell_test(
15 | name = "RecursiveTest",
16 | srcs = ["RecursiveTest.hs"],
17 | deps = [":Recursive"],
18 | )
19 |
20 | haskell_test(
21 | name = "RecursiveBinaryTest",
22 | srcs = [
23 | "Boot.hs",
24 | "Boot.hs-boot",
25 | "RecursiveTest.hs",
26 | "Regular.hs",
27 | ],
28 | )
29 |
--------------------------------------------------------------------------------
/bzl/tests/recursive/Boot.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Boot where
16 |
17 | import Regular
18 |
19 | data Boot = Boot Regular
20 |
--------------------------------------------------------------------------------
/bzl/tests/recursive/Boot.hs-boot:
--------------------------------------------------------------------------------
1 | module Boot where
2 |
3 | data Boot
4 |
--------------------------------------------------------------------------------
/bzl/tests/recursive/RecursiveTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
16 | module Main where
17 |
18 | import Regular
19 | import Boot
20 |
21 | import Control.Monad (guard)
22 |
23 | main = do
24 | -- Check that we can import names from both modules.
25 | let Regular x (Boot _) = Regular 42 (Boot Nil)
26 | guard (x == 42)
27 |
--------------------------------------------------------------------------------
/bzl/tests/recursive/Regular.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Regular where
16 |
17 | import {-# SOURCE #-} Boot
18 |
19 | data Regular = Regular Int Boot | Nil
20 |
--------------------------------------------------------------------------------
/bzl/tests/rules/Binary.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Library
18 |
19 | main = print value
20 |
--------------------------------------------------------------------------------
/bzl/tests/rules/CoreLibraryTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main (main) where
16 |
17 | import Control.Monad (guard)
18 | import qualified Pretty
19 |
20 | main :: IO ()
21 | main = guard ("Hello, world" == show doc)
22 | where
23 | -- A trivial computation that uses the GHC API
24 | doc = Pretty.text "Hello, " Pretty.<> Pretty.text "world"
25 |
--------------------------------------------------------------------------------
/bzl/tests/rules/Data/ByteString.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- | This module checks postential conflicts against the relevant module from
16 | -- "bytestring". It checks that default_packages = [] works properly
17 | -- and allows importing this file without conflicts.
18 | module Data.ByteString (foo) where
19 |
20 | foo :: Int
21 | foo = 42
22 |
23 |
--------------------------------------------------------------------------------
/bzl/tests/rules/DefaultPackageTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main (main) where
16 |
17 | import Control.Monad (guard)
18 | import qualified Data.Set as Set
19 |
20 | main :: IO ()
21 | main = guard (3 == Set.size (Set.fromList [1..3]))
22 |
--------------------------------------------------------------------------------
/bzl/tests/rules/Library.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Library where
16 |
17 | value = "hello"
18 |
--------------------------------------------------------------------------------
/bzl/tests/rules/NoDefaultPackagesTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main (main) where
16 |
17 | import Control.Monad (guard)
18 | import Data.ByteString (foo)
19 |
20 | main :: IO ()
21 | main = guard (foo == 42)
22 |
--------------------------------------------------------------------------------
/bzl/tests/rules/PackageImportsTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- Tests that PackageImports get referenced by Bazel label name.
16 | {-# LANGUAGE PackageImports #-}
17 | module Main where
18 |
19 | import "//bzl/tests/rules:Library" Library
20 |
21 | main = print value
22 |
--------------------------------------------------------------------------------
/bzl/tests/rules/ReexportPreludeTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE NoImplicitPrelude #-}
16 | module Main where
17 |
18 | import ReexportPrelude
19 |
20 | main :: IO ()
21 | main = return ()
22 |
--------------------------------------------------------------------------------
/bzl/tests/rules/ReexportTest1.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Reexport1
18 |
19 | main = print value
20 |
--------------------------------------------------------------------------------
/bzl/tests/rules/ReexportTest2.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Reexport2
18 |
19 | main = print value
20 |
--------------------------------------------------------------------------------
/bzl/tests/rules/UnicodeLib.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- | A library whose header contains Unicode.
16 | -- Makes sure that the CheckModuleNames program can parse it.
17 | module UnicodeLib(α) where
18 |
19 | α = 42
20 |
--------------------------------------------------------------------------------
/bzl/tests/template_haskell/ANNTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- | Test compilation of modules with "ANN" pragmas, which trigger the dynamic
16 | -- linker similarly to template-haskell.
17 | module Main (main) where
18 |
19 | {-# ANN module () #-}
20 |
21 | main :: IO ()
22 | main = return ()
23 |
--------------------------------------------------------------------------------
/bzl/tests/template_haskell/BUILD:
--------------------------------------------------------------------------------
1 | # Test that TemplateHaskell works and can link against multiple layers of
2 | # dependencies.
3 | # (It's still broken for code that depends on FFI; see b/19372897.)
4 |
5 | load("//bzl:def.bzl", "haskell_library", "haskell_test")
6 |
7 | # A library that depends on another one.
8 | haskell_library(
9 | name = "Dependency",
10 | srcs = ["Dependency.hs"],
11 | deps = [":TransitiveDependency"],
12 | )
13 |
14 | haskell_library(
15 | name = "TransitiveDependency",
16 | srcs = ["TransitiveDependency.hs"],
17 | )
18 |
19 | # A library that depends only on "Dependency" but (implicitly) needs to link
20 | # against TransitiveDependency for TemplateHaskell.
21 | haskell_library(
22 | name = "TestDependencyLib",
23 | srcs = ["TestDependencyLib.hs"],
24 | executes_deps_in_compile = True,
25 | deps = [":Dependency"],
26 | )
27 |
28 | haskell_test(
29 | name = "TestDependencyLibTest",
30 | srcs = ["TestDependencyLibTest.hs"],
31 | deps = [":TestDependencyLib"],
32 | )
33 |
34 | # A test that depends only on "Dependency" but (implicitly) needs to link
35 | # against TransitiveDependency for TemplateHaskell.
36 | haskell_test(
37 | name = "TestDependency",
38 | srcs = ["TestDependency.hs"],
39 | executes_deps_in_compile = True,
40 | deps = [":Dependency"],
41 | )
42 |
43 | # A test that puts all of the files in a single rule.
44 | haskell_test(
45 | name = "TestJoined",
46 | srcs = [
47 | "Dependency.hs",
48 | "TestDependency.hs",
49 | ],
50 | executes_deps_in_compile = True,
51 | deps = [":TransitiveDependency"],
52 | )
53 |
54 | haskell_test(
55 | name = "ANNTest",
56 | srcs = ["ANNTest.hs"],
57 | )
58 |
--------------------------------------------------------------------------------
/bzl/tests/template_haskell/Dependency.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Dependency where
16 |
17 | import TransitiveDependency (myThing)
18 | import qualified Data.Map as Map
19 |
20 | foo :: Integer -> Integer
21 | foo n = n + toEnum (Map.size myThing)
22 |
--------------------------------------------------------------------------------
/bzl/tests/template_haskell/TestDependency.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE TemplateHaskell #-}
16 | module Main where
17 |
18 | import Control.Monad (guard)
19 | import Language.Haskell.TH
20 |
21 | import Dependency
22 |
23 | bar :: Int
24 | bar = $(litE $ IntegerL $ foo 40)
25 |
26 | main :: IO ()
27 | main = guard (bar == 42)
28 |
--------------------------------------------------------------------------------
/bzl/tests/template_haskell/TestDependencyLib.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE TemplateHaskell #-}
16 | module TestDependencyLib where
17 |
18 | import Language.Haskell.TH
19 |
20 | import Dependency
21 |
22 | bar :: Int
23 | bar = $(litE $ IntegerL $ foo 40)
24 |
--------------------------------------------------------------------------------
/bzl/tests/template_haskell/TestDependencyLibTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Control.Monad (guard)
18 | import TestDependencyLib (bar)
19 |
20 | main :: IO ()
21 | main = guard (bar == 42)
22 |
--------------------------------------------------------------------------------
/bzl/tests/template_haskell/TransitiveDependency.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module TransitiveDependency where
16 |
17 | import qualified Data.Map as Map
18 |
19 | myThing :: Map.Map Integer String
20 | myThing = Map.fromList [(1, "one"), (2, "two")]
21 |
--------------------------------------------------------------------------------
/bzl/tests/transitive_data/BUILD:
--------------------------------------------------------------------------------
1 | # Test that "pass through" rules, like haskell_library without srcs, forward transitive
2 | # data dependencies correctly.
3 |
4 | load("//bzl:def.bzl", "haskell_library", "haskell_test")
5 |
6 | cc_library(
7 | name = "cc_with_data",
8 | data = ["data/cc_data.txt"],
9 | )
10 |
11 | haskell_library(
12 | name = "Provider",
13 | srcs = ["Provider.hs"],
14 | data = ["data/foo.txt"],
15 | #deps = ["//haskell/Google/Runtime"],
16 | )
17 |
18 | # A rule that has no srcs and only forwards its immediate deps.
19 | haskell_library(
20 | name = "foo",
21 | deps = [
22 | ":Provider",
23 | ":cc_with_data",
24 | ],
25 | )
26 |
27 | haskell_test(
28 | name = "TransitiveDataTest",
29 | srcs = ["TransitiveDataTest.hs"],
30 | # Intentionally depend on the forwarding rule:
31 | tags = ["nofixdeps"],
32 | deps = [":foo"],
33 | )
34 |
--------------------------------------------------------------------------------
/bzl/tests/transitive_data/Provider.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Provider (readFoo, readCcData) where
16 |
17 | import Google.Runtime.BuildHelper
18 |
19 | readFoo :: IO String
20 | readFoo = findHostDependencyOrDie
21 | "tools/build_defs/haskell/tests/transitive_data/data/foo.txt"
22 | >>= readFile
23 |
24 | readCcData :: IO String
25 | readCcData = findHostDependencyOrDie
26 | "tools/build_defs/haskell/tests/transitive_data/data/cc_data.txt"
27 | >>= readFile
28 |
--------------------------------------------------------------------------------
/bzl/tests/transitive_data/TransitiveDataTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import Control.Monad (when)
18 | import Provider (readFoo, readCcData)
19 |
20 | main = do
21 | fooContents <- readFoo
22 | when (fooContents /= "foo\n") $
23 | error $ "Unexpected fooContents: " ++ show fooContents
24 | ccDataContents <- readCcData
25 | when (ccDataContents /= "cc data\n") $
26 | error $ "Unexpected ccDataContents: " ++ show ccDataContents
27 |
--------------------------------------------------------------------------------
/bzl/tests/transitive_data/data/cc_data.txt:
--------------------------------------------------------------------------------
1 | cc data
2 |
--------------------------------------------------------------------------------
/bzl/tests/transitive_data/data/foo.txt:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/bzl/tests/version_macros/BUILD:
--------------------------------------------------------------------------------
1 | load("//bzl:def.bzl", "haskell_library", "haskell_test")
2 |
3 | haskell_library(
4 | name = "dependency_lib",
5 | srcs = ["Dependency.hs"],
6 | # The Cabal macros should use this name:
7 | cabal_name = "dependency",
8 | cabal_version = "1.2.3",
9 | )
10 |
11 | haskell_test(
12 | name = "VersionTest",
13 | srcs = ["VersionTest.hs"],
14 | deps = [":dependency_lib"],
15 | )
16 |
--------------------------------------------------------------------------------
/bzl/tests/version_macros/Dependency.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Dependency () where
16 |
--------------------------------------------------------------------------------
/bzl/tests/version_macros/VersionTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE CPP #-}
16 | module Main (main) where
17 |
18 | import Control.Monad (guard)
19 | import Dependency ()
20 |
21 | -- Check that we get macros for default packages:
22 | versionBase :: Bool
23 | #if MIN_VERSION_base(1,2,3)
24 | versionBase = True
25 | #else
26 | versionBase = False
27 | #endif
28 |
29 | -- Check that we get macros for dependencies with the
30 | -- package_name/package_version attribute:
31 | dependencyVersionMet, dependencyVersionTooLow :: Bool
32 | #if MIN_VERSION_dependency(1,2,3)
33 | dependencyVersionMet = True
34 | #else
35 | dependencyVersionMet = False
36 | #endif
37 |
38 | #if !MIN_VERSION_dependency(1,2,4)
39 | dependencyVersionTooLow = True
40 | #else
41 | dependencyVersionTooLow = False
42 | #endif
43 |
44 | main = do
45 | guard versionBase
46 | guard dependencyVersionMet
47 | guard dependencyVersionTooLow
48 | guard (VERSION_dependency == "1.2.3")
49 |
--------------------------------------------------------------------------------
/rule_info/BUILD:
--------------------------------------------------------------------------------
1 | exports_files(["rule_info.proto"])
2 |
--------------------------------------------------------------------------------
/rule_info/rule_info.proto:
--------------------------------------------------------------------------------
1 | // Proto messages that Haskell build rules output, for use by tools like
2 | // "hrepl".
3 | syntax = "proto3";
4 |
5 | package haskell;
6 |
7 | // Information about a HaskellCompile action.
8 | message CompileInfo {
9 | reserved 1, 3, 4, 7, 8, 10, 13, 14;
10 | // The source files that are being compiled (.hs and .lhs files).
11 | // Does not contain "boot" files (e.g. ".hs-boot").
12 | repeated string source_files = 2;
13 | // Modules that should not be exposed. (For libraries only.)
14 | repeated string hidden_modules = 12;
15 | // The runfiles that should be collected for this target.
16 | repeated Runfile runfiles = 5;
17 | // The Haskell package name. Should only be set for third-party libraries
18 | // (namely, those with the "cabal_version" attribute).
19 | string package_name = 6;
20 |
21 | // Arguments to GHC for compiling this target. Does not include source files,
22 | // nor flags related to dependent packages ("-package-id" and "-package-db").
23 | repeated string options = 9;
24 |
25 | // Libraries for cc_library rules that this target depends on
26 | // transitively. Should be either static or dynamic, depending on how the
27 | // GHC RTS was linked.
28 | repeated string transitive_cc_libs = 11;
29 | }
30 |
31 | // Information about a built library.
32 | message LibraryInfo {
33 | reserved 3;
34 | // The GHC package ID of this target.
35 | string package_id = 1;
36 |
37 | // The package DBs that we need to explicitly pass to GHC in order to use
38 | // this target. Namely, the DBs needed for all dependencies transitively,
39 | // including itself.
40 | // Does not include the "core" package DB which is part of the GHC build
41 | // itself and produces packages like "base", "ghc", etc.
42 | repeated string transitive_package_dbs = 2;
43 |
44 | // The package IDs of all libraries that this target depends on transitively,
45 | // including itself.
46 | repeated string transitive_package_ids = 4;
47 | }
48 |
49 | message Runfile {
50 | // The path under the execution root. For example, "foo/bar.txt"
51 | // for a source file, or "bazel-out/k8-fastbuild/bin/foo/bar.txt" for a
52 | // generated file.
53 | string full_path = 1;
54 | // The path where this file is expected to be in the runfiles directory.
55 | // For example, "foo/bar.txt" in both of the above cases.
56 | string short_path = 2;
57 | }
58 |
59 | // Information about the Haskell compiler.
60 | // This is similar information as in the ghc_paths library, but comes directly
61 | // from the build rules, rather than being embedded in a Haskell binary (which
62 | // might have been compiled with a different version of GHC).
63 | message GhcConfig {
64 | // The path to the GHC executable.
65 | string ghc = 1;
66 | // The directory containing GHC's libraries, which should be the
67 | // argument of the "-B" flag.
68 | // TODO(judahjacobson): Currently, rules_haskell does not set this
69 | // flag. hrepl doesn't need it since it calls GHC as a binary.
70 | string library_root = 2;
71 | // Arguments that should be passed to every invocation of GHC.
72 | // Note that this does *not* contain "-B". It is not relevant for users of
73 | // the GHC API, which should pull that value from library_root instead.
74 | repeated string common_options = 3;
75 | }
76 |
--------------------------------------------------------------------------------
/settings/BUILD:
--------------------------------------------------------------------------------
1 | load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
2 | load(
3 | "//bzl:settings.bzl",
4 | "ghcopts",
5 | "per_target_ghcopts",
6 | )
7 |
8 | per_target_ghcopts(
9 | name = "per_target_ghcopts",
10 | build_setting_default = "",
11 | visibility = ["//visibility:public"],
12 | )
13 |
14 | bool_flag(
15 | name = "profile",
16 | build_setting_default = False,
17 | visibility = ["//visibility:public"],
18 | )
19 |
20 | config_setting(
21 | name = "profile_mode",
22 | flag_values = {
23 | ":profile": "True",
24 | },
25 | )
26 |
27 | ghcopts(
28 | name = "profile_ghcopts",
29 | build_setting_default = "-fprof-auto",
30 | visibility = ["//visibility:public"],
31 | )
32 |
33 | ghcopts(
34 | name = "ghcopts",
35 | build_setting_default = "",
36 | visibility = ["//visibility:public"],
37 | )
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/Google/Google3.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2018 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- https://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Google.Google3 (
16 | module Google.Google3.Name,
17 | module Google.Google3.Package) where
18 |
19 | import Google.Google3.Name
20 | import Google.Google3.Package
21 |
--------------------------------------------------------------------------------
/src/Google/Google3/Buildifier.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- | Utility to format BUILD files using Buildifier tool.
16 |
17 | module Google.Google3.Buildifier (call) where
18 |
19 | import System.Process (callProcess)
20 |
21 | import Google.Runtime.BuildHelper (findHostDependencyOrDie)
22 |
23 | -- | Runs buildifier on files with the specified paths.
24 | call :: [FilePath] -> IO ()
25 | call args = do
26 | bin <- findHostDependencyOrDie "devtools/buildifier/buildifier"
27 | callProcess bin ("--lint=fix" : args)
28 |
--------------------------------------------------------------------------------
/src/Google/Google3/Name.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE OverloadedStrings #-}
16 |
17 | -- | Utilities related to the names of Google3 packages and targets.
18 |
19 | module Google.Google3.Name where
20 |
21 | import Data.Char
22 | import Data.Text (Text)
23 | import qualified Data.Text as Text
24 | import System.FilePath
25 |
26 | -- | A package name such as //foo/bar, represented as a list of
27 | -- path segments.
28 | newtype PackageName = PackageName [Text]
29 | deriving (Eq, Ord)
30 | instance Show PackageName where
31 | show = ("//" ++) . google3relativePath
32 |
33 | -- | An unqualified target name.
34 | newtype TargetName = TargetName { unTargetName :: Text }
35 | deriving (Eq, Ord)
36 | instance Show TargetName where
37 | show = Text.unpack . unTargetName
38 |
39 | -- | The fully qualified label of a target: its name qualifed by its package.
40 | data Label = Label PackageName TargetName
41 | deriving (Eq, Ord)
42 | instance Show Label where
43 | show (Label pn tn) = show pn ++ ":" ++ show tn
44 |
45 | -- > parsePackageName "//foo/bar" == PackageName ["foo", "bar"]
46 | parsePackageName :: Text -> PackageName
47 | parsePackageName = PackageName . dropWhile Text.null . Text.splitOn "/"
48 |
49 | -- | Note that this expects a fully qualified label, so things like
50 | -- ":target_name" or "target_name" won't work.
51 | -- > parseLabel "//foo/bar:baz" == Label (PackageName ["foo", "bar"])
52 | -- > (TargetName "baz")
53 | parseLabel :: Text -> Label
54 | parseLabel l = Label (parsePackageName x) (TargetName $ Text.tail y)
55 | where (x, y) = Text.break (== ':') l
56 |
57 | -- | Glorified list concatenation.
58 | -- > subPackageName (PackageName "foo") ["bar", "baz"] ==
59 | -- > PackageName ["foo", "bar", "baz"]
60 | subpackageName :: PackageName -> [Text] -> PackageName
61 | subpackageName (PackageName segs) moreSegs = PackageName (segs ++ moreSegs)
62 |
63 | -- | Package //foo/bar is found at foo/bar relative to a Google3 root.
64 | google3relativePath :: PackageName -> FilePath
65 | google3relativePath (PackageName p) = foldr1 (>) . fmap Text.unpack $ p
66 |
67 | -- | Absolute path for the given package given the Google3 root.
68 | google3absolutePath :: FilePath -> PackageName -> FilePath
69 | google3absolutePath g3dir (PackageName p) =
70 | g3dir > foldr1 (>) (Text.unpack <$> p)
71 |
72 | -- | Package directories' names must only contain alphanumeric
73 | -- characters, dashes, underscores and forward slashes.
74 | isValidPackageDirectoryName :: Text -> Bool
75 | isValidPackageDirectoryName = Text.all isValidChar where
76 | isValidChar a = isAlphaNum a || a `elem` ("-_/" :: String)
77 |
--------------------------------------------------------------------------------
/src/Google/Google3/Tools/Cabal2Build/Configuration.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- TODO(judahjacobson): Fix the deprecated use of finalizePackageDescription.
16 | {-# OPTIONS_GHC -Wno-deprecations #-}
17 | {-# LANGUAGE LambdaCase #-}
18 |
19 | -- | Tools for dealing with Cabal packages' configuration flags.
20 | -- In fact, nothing in here has anything to do with Google
21 | -- packages, so it could be moved to a more general
22 | -- Cabal-related tree.
23 | module Google.Google3.Tools.Cabal2Build.Configuration (
24 | FlagAssignmentList,
25 | targetPackageDesc,
26 | requestFlags,
27 | displayFlagName,
28 | makeFlagName) where
29 |
30 | import Data.Char (toLower)
31 | import Distribution.Compiler
32 | import qualified Distribution.PackageDescription as Cabal
33 | import qualified Distribution.PackageDescription.Configuration as Cabal (
34 | finalizePackageDescription)
35 | import Distribution.System
36 | import qualified Distribution.Text as Cabal (display)
37 | import qualified Distribution.Version as Cabal (Version)
38 | import System.IO (hFlush, stdout)
39 |
40 | type FlagAssignmentList = [(Cabal.FlagName, Bool)]
41 |
42 | mkFlagAssignment :: FlagAssignmentList -> Cabal.FlagAssignment
43 | mkFlagAssignment = Cabal.mkFlagAssignment
44 |
45 | unFlagAssignment :: Cabal.FlagAssignment -> FlagAssignmentList
46 | unFlagAssignment = Cabal.unFlagAssignment
47 |
48 | displayFlagName :: Cabal.FlagName -> String
49 | displayFlagName = Cabal.display
50 |
51 | makeFlagName :: String -> Cabal.FlagName
52 | makeFlagName =
53 | -- Cabal lowercases the flag name before mkFlagName. Mimic that.
54 | -- See b/134632412 and https://github.com/haskell/cabal/issues/5043.
55 | Cabal.mkFlagName . map toLower
56 |
57 | -- | Finalizes a package description for the target configuration.
58 | targetPackageDesc :: Cabal.GenericPackageDescription
59 | -> Cabal.Version -- ^ GHC version to target.
60 | -> FlagAssignmentList
61 | -> (Cabal.PackageDescription, FlagAssignmentList)
62 | targetPackageDesc pkg ghcVersion explicitFlags =
63 | let compilerInfo = unknownCompilerInfo (CompilerId GHC ghcVersion) NoAbiTag
64 | in case Cabal.finalizePackageDescription (mkFlagAssignment explicitFlags)
65 | (const True)
66 | (Platform X86_64 Linux)
67 | compilerInfo
68 | []
69 | pkg
70 | of
71 | Right (desc, flags) -> (desc, unFlagAssignment flags)
72 | Left deps ->
73 | error $ "targetPackageDesc: missing dependencies: " ++ show deps
74 |
75 | -- | Prompts the user to supply values for configuration flags.
76 | requestFlags :: FlagAssignmentList -- ^ Default flags.
77 | -> IO FlagAssignmentList -- ^ User specified flags.
78 | requestFlags = mapM requestFlag where
79 | requestFlag (flag, defaultValue) = do
80 | putStr $ displayFlagName flag ++ " [" ++ defaultStr defaultValue ++ "] "
81 | hFlush stdout
82 | value <- map toLower <$> getLine >>= \ case
83 | "y" -> return True
84 | "n" -> return False
85 | "" -> return defaultValue
86 | _ -> fail "Must specify y or n, or Enter for default"
87 | return (flag, value)
88 | defaultStr True = "Y"
89 | defaultStr False = "N"
90 |
--------------------------------------------------------------------------------
/src/Google/Google3/Tools/Cabal2Build/License.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- TODO(judahjacobson): Remove this module after migrating to ghc-8.4
16 | -- (really, to Cabal>=2.2) which supports SPDX naming.
17 | module Google.Google3.Tools.Cabal2Build.License (showCabalLicense) where
18 |
19 | import Data.List (intercalate)
20 | import Distribution.Version (
21 | Version,
22 | versionNumbers,
23 | )
24 | import qualified Distribution.License as Cabal
25 |
26 | -- | Representation of Cabal license specifications in generated Google
27 | -- files (specifically BUILD). Where possible we generate names from
28 | -- https://spdx.org/licenses/.
29 | showCabalLicense :: Cabal.License -> String
30 | showCabalLicense (Cabal.AGPL v) = "AGPL" ++ maybe "" showVersion v
31 | showCabalLicense (Cabal.Apache v) = "Apache" ++ maybe "" showVersion v
32 | showCabalLicense Cabal.BSD2 = "BSD-2-Clause"
33 | showCabalLicense Cabal.BSD3 = "BSD-3-Clause"
34 | showCabalLicense Cabal.BSD4 = "BSD-4-Clause"
35 | showCabalLicense (Cabal.GPL v) = "GPL" ++ maybe "" showVersion v
36 | showCabalLicense Cabal.ISC = "ISC"
37 | showCabalLicense (Cabal.LGPL v) = "LGPL" ++ maybe "" showVersion v
38 | showCabalLicense Cabal.MIT = "MIT"
39 | showCabalLicense (Cabal.MPL v) = "MPL" ++ showVersion v
40 | showCabalLicense (Cabal.UnknownLicense s) = "Unknown/" ++ s
41 | showCabalLicense l = show l
42 |
43 | -- | Translate a Distribution.Version to an SPDX compatible string.
44 | showVersion :: Version -> String
45 | showVersion v =
46 | case versionNumbers v of
47 | [] -> ""
48 | [x] -> "-" ++ show x ++ ".0"
49 | xs -> "-" ++ intercalate "." (map show xs)
50 |
--------------------------------------------------------------------------------
/src/Google/Google3/Tools/Cabal2Build/PackageName.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE OverloadedStrings #-}
16 |
17 | -- | Defines conversion between Cabal package names and
18 | -- Google3 package names.
19 | module Google.Google3.Tools.Cabal2Build.PackageName (
20 | google3packageNameForCabalPackageName,
21 | google3packageNameForCabalPackageId,
22 | cabalVersionForSegment) where
23 |
24 | import qualified Data.Text as Text
25 | import qualified Distribution.Package as Cabal
26 | import qualified Distribution.Text as Cabal
27 | import qualified Distribution.Version as Cabal
28 | import qualified Google.Google3.Name as Google3
29 | import Text.Read (readMaybe)
30 |
31 | -- | Converts an unversioned Cabal package name to a valid Google3 package
32 | -- name. Dashes become underscores.
33 | --
34 | -- e.g. "utf8-string" becomes "//third_party/haskell/utf8_string"
35 | google3packageNameForCabalPackageName :: Cabal.PackageName
36 | -> Google3.PackageName
37 | google3packageNameForCabalPackageName name =
38 | Google3.PackageName [
39 | "third_party",
40 | "haskell",
41 | Text.pack $ map mungeChar (Cabal.display name)
42 | ]
43 | where mungeChar '-' = '_'
44 | mungeChar x = x
45 |
46 | -- | Converts a versioned Cabal package name to a valid Google3 package
47 | -- name.
48 | -- e.g. "utf8-string-0.3.6" becomes "//third_party/haskell/utf8_string/v0_3_6"
49 | google3packageNameForCabalPackageId :: Cabal.PackageIdentifier
50 | -> Google3.PackageName
51 | google3packageNameForCabalPackageId (Cabal.PackageIdentifier name version)
52 | = Google3.subpackageName unversionedPackageName [versionSegment]
53 | where unversionedPackageName = google3packageNameForCabalPackageName name
54 | versionSegment =
55 | Text.cons 'v' $
56 | Text.intercalate "_" $
57 | map (Text.pack . show) branch
58 | branch = Cabal.versionNumbers version
59 |
60 | -- | Converts a Google3 version directory name into a Cabal version.
61 | -- For example, "v0_3_6" becomes 0.3.6.
62 | cabalVersionForSegment :: Text.Text -> Maybe Cabal.Version
63 | cabalVersionForSegment v = do
64 | ('v', v') <- Text.uncons v
65 | vs <- mapM (readMaybe . Text.unpack)
66 | $ Text.splitOn "_" v'
67 | return $ Cabal.mkVersion vs
68 |
--------------------------------------------------------------------------------
/src/Google/Google3/VCSClient.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Google.Google3.VCSClient
16 | ( VCSClient(..)
17 | , vcsForGivenDirectory
18 | , withOpenFile
19 | ) where
20 |
21 | import Control.Exception (throwIO)
22 | import Control.Monad (unless)
23 | import Data.Tuple.Extra (fst3)
24 | import System.Directory (doesFileExist)
25 | import System.Exit (ExitCode(..))
26 | import System.IO.Error (mkIOError, userErrorType)
27 | import qualified System.Process as Proc
28 |
29 | -- | Generic command action.
30 | type Command = [FilePath] -> IO ()
31 |
32 | -- | VCS Client type, holding the commands to run and the directory it
33 | -- works in.
34 | data VCSClient = VCSClient
35 | { cmdAdd :: Command -- ^ Add files to VCS command.
36 | , cmdIntegrate :: Command -- ^ Marks a file as a copy of a previous one,
37 | -- preserving VCS history.
38 | , cmdRecord :: Command -- ^ Records that a file has been edited (after).
39 | , cmdDelete :: Command -- ^ Marks files for removal.
40 | , cmdMove :: Command -- ^ Moves an already-tracked file.
41 | , cmdFix :: Command -- ^ Autoformats the given files.
42 | , g3Dir :: FilePath -- ^ Top level google3 directory.
43 | }
44 |
45 | -- | Like @rawSystem@ but throws an informative exception upon failure.
46 | checkRawSystem :: FilePath -> String -> [String] -> IO ()
47 | checkRawSystem workDir cmd args = do
48 | ec <- runProcessIn workDir cmd args
49 | case ec of
50 | ExitSuccess -> return ()
51 | ExitFailure r ->
52 | throwIO (mkIOError userErrorType ("rawSystem: " ++ cmd ++
53 | ' ':unwords (map show args) ++
54 | " (exit " ++ show r ++ ")")
55 | Nothing Nothing)
56 |
57 | runProcessIn :: FilePath -> String -> [String] -> IO ExitCode
58 | runProcessIn workDir cmd args = do
59 | let process = (Proc.proc cmd args) { Proc.cwd = Just workDir }
60 | Proc.withCreateProcess process $ \_ _ _ ph -> Proc.waitForProcess ph
61 |
62 | noop :: a -> IO ()
63 | noop = return . const ()
64 |
65 | type CmdRunner = String -> [String] -> IO()
66 |
67 | hgClient :: FilePath -> VCSClient
68 | hgClient g3dir = VCSClient
69 | { cmdAdd = hgop "add"
70 | -- Use --force to overwrite any existing, committed files.
71 | , cmdIntegrate = hgop "cp" . (["--after", "--force"] ++)
72 | , cmdRecord = hgop "add"
73 | , cmdDelete = hgop "rm"
74 | , cmdMove = hgop "mv"
75 | , cmdFix = hgop "fix"
76 | , g3Dir = g3dir
77 | }
78 | where
79 | hgop :: CmdRunner
80 | hgop op files = unless (null files) $ checkRawSystem g3dir "hg" (op:files)
81 |
82 | -- | Runs an action that creates a file, and adds it if it didn't exist
83 | -- beforehand.
84 | withOpenFile :: VCSClient -> FilePath -> IO a -> IO a
85 | withOpenFile client file action = do
86 | existed <- doesFileExist file
87 | r <- action
88 | unless existed $ cmdAdd client [file]
89 | return r
90 |
91 | -- | Returns a 'VCSClient' for use with the given directory (e.g. hg).
92 | vcsForGivenDirectory :: FilePath -> IO VCSClient
93 | vcsForGivenDirectory g3dir = do
94 | let runProcessSilently cmd args = do
95 | let process = (Proc.proc cmd args) { Proc.cwd = Just g3dir }
96 | fst3 <$> Proc.readCreateProcessWithExitCode process ""
97 | isHg <- runProcessSilently "hg" ["stat"]
98 | return $ case isHg of
99 | ExitSuccess -> hgClient g3dir
100 | _ -> error "Working directory is not an hg client."
101 |
--------------------------------------------------------------------------------
/src/Google/Runtime/FindFiles.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2018 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- https://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE LambdaCase #-}
16 | {-# LANGUAGE TupleSections #-}
17 | -- |File system traversal helpers.
18 |
19 | module Google.Runtime.FindFiles
20 | ( findFiles
21 | , findInTestDirectory
22 | , findSrcDir
23 | , findSrcDirOrDie
24 | , findParentRunfilesDir
25 | , Path) where
26 |
27 | import Control.Monad (filterM)
28 | import Data.List (findIndices, isPrefixOf, isSuffixOf)
29 | import System.Directory (doesDirectoryExist, getCurrentDirectory,
30 | getDirectoryContents)
31 | import System.Environment (getEnv, lookupEnv)
32 | import System.FilePath ((>), joinPath, splitPath, normalise)
33 |
34 | -- |A pair comprising a directory and a file name.
35 | type Path = (FilePath, FilePath)
36 |
37 | -- |Looks for the files satisfying the given predicate under the given
38 | -- directory.
39 | findFiles :: (Path -> IO Bool) -> FilePath -> IO [Path]
40 | findFiles predicate path = do
41 | children <- filter (`notElem` [".", ".."]) <$> getDirectoryContents path
42 | localMatches <- filterM predicate ((path,) <$> children)
43 | childDirs <- filterM doesDirectoryExist ((path >) <$> children)
44 | childMatches <- mapM (findFiles predicate) childDirs
45 | return $ localMatches ++ concat childMatches
46 |
47 | -- |Finds the file with the given base name under TEST_SRCDIR. There must
48 | -- be one and only one such file or else the function calls error.
49 | findInTestDirectory :: FilePath -> IO FilePath
50 | findInTestDirectory fileName = do
51 | testSrcDir <- getEnv "TEST_SRCDIR"
52 | foundFiles <- findFiles (return . (== fileName) . snd) testSrcDir
53 | case foundFiles of
54 | [(dir, file)] -> return $ dir > file
55 | _ -> error $ "Expected one file named " ++ fileName ++
56 | " in " ++ testSrcDir ++ ". Found " ++ show foundFiles
57 |
58 | -- |Determines the location of the top of the source tree. If there is
59 | -- TEST_SRCDIR environment variable - it gets used with "google3/"
60 | -- appended. Otherwise the current directory is traversed up until
61 | -- there is "google3".
62 | findSrcDir :: IO (Maybe FilePath)
63 | findSrcDir = lookupEnv "TEST_SRCDIR" >>= \ case
64 | Just dir -> return $ Just (dir > "google3")
65 | Nothing -> do
66 | components <- splitPath <$> getCurrentDirectory
67 | let matches = findIndices (isPrefixOf "google3") components
68 | case matches of
69 | [] -> return Nothing
70 | _ -> return . Just $ joinPath (take (last matches + 1) components)
71 |
72 | -- |Determines the location of the top of the source tree via
73 | -- 'findSrcDir', otherwise it throws an error.
74 | findSrcDirOrDie :: IO FilePath
75 | findSrcDirOrDie = findSrcDir >>= \ case
76 | Just path -> return path
77 | Nothing -> do
78 | cwd <- getCurrentDirectory
79 | error $ "Needs to run in google3, not " ++ cwd
80 |
81 | -- |Determines the eventual location of the parent last ".runfiles"
82 | -- directory. This happens when the binary is part of a "data"
83 | -- dependency of another target, in which case the binary itself (and
84 | -- all its dependencies as well) lives already under a single, merged
85 | -- runfiles directory (see
86 | findParentRunfilesDir :: FilePath -> Maybe FilePath
87 | findParentRunfilesDir binary =
88 | let components = splitPath $ normalise binary
89 | matches = findIndices (".runfiles/" `isSuffixOf`) components
90 | in case matches of
91 | [] -> Nothing
92 | _ -> Just $ joinPath (take (last matches + 1) components)
93 |
--------------------------------------------------------------------------------
/src/Google/Utils/DirectoryUtils.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2018 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- https://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE CPP #-}
16 | module Google.Utils.DirectoryUtils where
17 |
18 | import Control.Exception (bracket)
19 | import Control.Monad ((<=<), when)
20 | #if __GLASGOW_HASKELL__ < 800
21 | import Data.Bool (bool)
22 | #endif
23 | import Data.Maybe (fromMaybe)
24 | import System.Directory
25 | ( createDirectoryIfMissing
26 | #if __GLASGOW_HASKELL__ < 800
27 | , doesDirectoryExist
28 | , doesFileExist
29 | #endif
30 | , getDirectoryContents
31 | , getTemporaryDirectory
32 | , removeFile
33 | )
34 | import System.Environment (lookupEnv)
35 | import System.IO (Handle, hClose, hIsOpen, openTempFile)
36 |
37 | -- | @mkdir -p@
38 | createPath :: FilePath -> IO ()
39 | createPath = createDirectoryIfMissing True
40 |
41 | #if __GLASGOW_HASKELL__ < 800
42 | -- | Returns true if and only if the given path is a file or a directory.
43 | doesPathExist :: FilePath -> IO Bool
44 | doesPathExist p = doesFileExist p >>= bool (doesDirectoryExist p) (return True)
45 | #endif
46 |
47 | -- | Returns the contents of a directory, except for '.' and '..'.
48 | getSimpleDirectoryContents :: FilePath -> IO [FilePath]
49 | getSimpleDirectoryContents =
50 | return . filter (not . special) <=< getDirectoryContents
51 | where special e = e `elem` [".", ".."]
52 |
53 | -- | Return a directory suitable for storing temporary files.
54 | getTempDir :: IO FilePath
55 | getTempDir = fromMaybe <$> getTemporaryDirectory <*> lookupEnv "TEST_DIR"
56 |
57 | -- | Run a computation with a temporary file named from the given
58 | -- template. The file is cleaned up automatically.
59 | withTempFile :: String -> (FilePath -> Handle -> IO a) -> IO a
60 | withTempFile template = bracket openTemp cleanupTemp . uncurry
61 | where
62 | openTemp = getTempDir >>= flip openTempFile template
63 | cleanupTemp (path, h) = do
64 | open <- hIsOpen h
65 | when open $ hClose h
66 | removeFile path
67 |
--------------------------------------------------------------------------------
/src/Google/Utils/Env.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2018 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- https://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-|
16 | Module: Google.utils.Env
17 | Description: Convinience functions to work with environment variables.
18 | -}
19 |
20 | module Google.Utils.Env
21 | ( readMay
22 | , maybeFormatEnv
23 | , lookupReadMaybe
24 | ) where
25 |
26 | import Control.Monad ( guard )
27 | import Data.Maybe ( listToMaybe )
28 | import System.Environment ( lookupEnv )
29 |
30 | -- | A version of 'read' that returns 'Nothing' on failure instead of
31 | -- 'error' @"..."@.
32 | readMay :: Read a => String -> Maybe a
33 | readMay s = listToMaybe $ do
34 | (parse, remain) <- reads s
35 | guard (null remain)
36 | return parse
37 |
38 | -- | Try to read an environment variable into @a@.
39 | lookupReadMaybe :: Read a => String -> IO (Maybe a)
40 | lookupReadMaybe n = (readMay =<<) <$> lookupEnv n
41 |
42 | -- | This looks up an environment variable and applies the formatting function
43 | -- if the variable exists.
44 | maybeFormatEnv :: String -- ^ The environment variable.
45 | -> (String -> IO a) -- ^ How to format the variable into @a@.
46 | -> IO (Maybe a)
47 | maybeFormatEnv envVar format =
48 | lookupEnv envVar >>= maybe (return Nothing) (fmap Just . format)
49 |
--------------------------------------------------------------------------------
/src/Google/Utils/Expn.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2018 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- https://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE LambdaCase #-}
16 | -- | Utility module to interact with "expn" tool used to expand group
17 | -- membership.
18 | module Google.Utils.Expn (tryExpand, expand) where
19 |
20 | import Control.Monad ((>=>))
21 | import System.Process (readProcessWithExitCode)
22 | import System.Exit (ExitCode(..))
23 |
24 | -- | Tries expanding a group, returns either exit code with outputs or
25 | -- a list of emails in the group.
26 | tryExpand :: String -> IO (Either (Int, String, String) [String])
27 | tryExpand group = readProcessWithExitCode "/usr/bin/expn" [group] "" <$$> \ case
28 | (ExitSuccess, output, _) -> Right $ lines output
29 | (ExitFailure code, output, stderr) -> Left (code, output, stderr)
30 | where (<$$>) = flip fmap
31 |
32 | -- | The same as tryExpand, but errors out if it fails.
33 | expand :: String -> IO [String]
34 | expand = tryExpand >=> either (error . show) return
35 |
--------------------------------------------------------------------------------
/src/Google/Utils/List.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | {-# LANGUAGE BangPatterns #-}
16 |
17 | module Google.Utils.List (ordNub, ordNubOn, hashNub) where
18 |
19 | import Data.Hashable (Hashable (..))
20 | import qualified Data.HashSet as HashSet
21 | import qualified Data.Set as Set
22 |
23 | -- | Removes duplicates, preserving order.
24 | ordNub :: (Ord a) => [a] -> [a]
25 | ordNub = ordNubOn id
26 |
27 | -- | Removes duplicates, preserving order. Two elements are considered
28 | -- duplicates if they map to the same 'b'.
29 | ordNubOn :: (Ord b) => (a -> b) -> [a] -> [a]
30 | ordNubOn f =
31 | let go _ [] = []
32 | go s (x:xs) = let y = f x
33 | in if y `Set.member` s
34 | then go s xs
35 | else x : go (Set.insert y s) xs
36 | in go Set.empty
37 |
38 | hashNub :: (Eq a, Hashable a) => [a] -> [a]
39 | hashNub = nub_impl HashSet.insert HashSet.member HashSet.empty
40 | {-# INLINE hashNub #-}
41 |
42 | nub_impl :: (a -> set a -> set a) -> (a -> set a -> Bool) -> set a -> [a] -> [a]
43 | nub_impl insert member = go
44 | where go _ [] = []
45 | go !xs (y:ys)
46 | | member y xs = go xs ys
47 | | otherwise = y : go (insert y xs) ys
48 | {-# INLINE nub_impl #-}
49 |
--------------------------------------------------------------------------------
/src/Google/Utils/Monad.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2018 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- https://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Google.Utils.Monad where
16 |
17 | import Control.Monad
18 |
19 | bind2 :: Monad m => m a -> m b -> (a -> b -> m c) -> m c
20 | bind2 m_x m_y f = join $ liftM2 f m_x m_y
21 |
--------------------------------------------------------------------------------
/src/Google/Utils/Pick.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2018 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- https://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- | Utility module with a naive implementation of a random selection
16 | -- from a list.
17 | module Google.Utils.Pick (partialPick, pick) where
18 |
19 | import System.Random (randomRIO)
20 |
21 | -- | Very naive implementation of selecting a random element from a
22 | -- list. Errors out on empty list.
23 | partialPick :: [a] -> IO a
24 | partialPick [] = error "unsafePick: empty list"
25 | partialPick xs = randomRIO (0, length xs - 1) >>= return . (xs !!)
26 |
27 | -- | The same as partialPick, but returns Maybe instead.
28 | pick :: [a] -> IO (Maybe a)
29 | pick [] = return Nothing
30 | pick xs = fmap Just $ partialPick xs
31 |
--------------------------------------------------------------------------------
/src/Google/Utils/ReadPUtils.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2018 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- https://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Google.Utils.ReadPUtils where
16 |
17 | import Data.Maybe (listToMaybe)
18 | import Text.ParserCombinators.ReadP
19 |
20 | -- | Given a parser, produces another parser that behaves the same, but that
21 | -- only succeeds if it consumes the entire input.
22 | parseFully :: ReadP a -> ReadP a
23 | parseFully p = p <* eof
24 |
25 | -- | Returns just the first match of a parser on some input, or Nothing if
26 | -- there were no matches at all.
27 | parseUniquely :: ReadP a -> String -> Maybe a
28 | parseUniquely p = listToMaybe . map fst . readP_to_S p
29 |
--------------------------------------------------------------------------------
/src/Google/Utils/When.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2018 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- https://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | -- | Utilities for using 'Bool's, 'Maybe's, and 'Either's to control 'Monad's.
16 | --
17 | -- Alternatively, a module giving names to a few common ways to combine
18 | -- 'maybe', 'either', 'return', 'pure', 'id', and 'mzero'.
19 |
20 | module Google.Utils.When
21 | (
22 | -- * Monad
23 | -- ** Bool
24 | -- | This is simply re-exported from Control.Monad.
25 | when
26 | -- ** Maybe
27 | , whenJust
28 | , whenNothing
29 | -- ** Either
30 | , whenLeft
31 | , whenRight
32 | , whenLeft_
33 | , whenRight_
34 | -- * MonadPlus
35 | -- ** Maybe
36 | , filterJust
37 | -- ** Either
38 | , filterLeft
39 | , filterRight
40 | ) where
41 |
42 | import Control.Monad (MonadPlus(mzero), when, void)
43 |
44 | -- | Run an action using the contents of a @Maybe a@ only if it is 'Just'.
45 | whenJust :: Monad m => Maybe a -> (a -> m ()) -> m ()
46 | whenJust x m = maybe (return ()) m x
47 |
48 | -- | Use the given action to provide a fallback value when given 'Nothing'.
49 | -- The fallback value is last to allow do-notation to be used comfortably. For
50 | -- example:
51 | --
52 | -- > whenNothing maybeUser $ do
53 | -- > uid <- askUserName
54 | -- > fetchUserFromDatabase uid
55 | whenNothing :: Applicative f => Maybe a -> f a -> f a
56 | whenNothing x ma = maybe ma pure x
57 |
58 | -- | Run an action only when the given @Either a b@ is @'Left' _@.
59 | whenLeft :: Applicative f => Either a b -> (a -> f b) -> f b
60 | whenLeft x mb = either mb pure x
61 |
62 | -- | Run an action only when the given @Either a b@ is @'Right' _@.
63 | whenRight :: Applicative f => Either a b -> (b -> f a) -> f a
64 | whenRight x ma = either pure ma x
65 |
66 | -- | Equivalent of 'whenLeft' where the continuation returns @()@. Note that
67 | -- 'whenLeft' can't be used directly for this case because it unifies the
68 | -- 'Right' type and the continuation result type.
69 | whenLeft_ :: Applicative f => Either a b -> (a -> f ()) -> f ()
70 | whenLeft_ = whenLeft . void
71 |
72 | -- | Equivalent of 'whenRight' where the continuation returns @()@.
73 | whenRight_ :: Applicative f => Either a b -> (b -> f ()) -> f ()
74 | whenRight_ = whenRight . either (const $ Left ()) Right
75 |
76 | -- | Use the value in 'Just' if present, or 'mzero' otherwise. Particularly
77 | -- useful in 'STM' where 'TVars' containing 'Maybe's are commonly used.
78 | --
79 | -- For example, an equivalent definition of
80 | -- 'Control.Concurrent.STM.TMVar.readMVar' is:
81 | --
82 | -- > readTMVar (TMVar tvar) = filterJust (readTVar tvar)
83 | filterJust :: MonadPlus m => m (Maybe a) -> m a
84 | filterJust = (>>= maybe mzero return)
85 |
86 | -- | Use the value in 'Left' if present, or 'mzero' otherwise.
87 | filterLeft :: MonadPlus m => m (Either a b) -> m a
88 | filterLeft = (>>= either return (const mzero))
89 |
90 | -- | Use the value in 'Right' if present, or 'mzero' otherwise.
91 | filterRight :: MonadPlus m => m (Either a b) -> m b
92 | filterRight = (>>= either (const mzero) return)
93 |
--------------------------------------------------------------------------------
/stack.yaml:
--------------------------------------------------------------------------------
1 | resolver: lts-14.27
2 |
3 | packages:
4 | - .
5 | extra-deps:
6 | - FindBin-0.0.5
7 |
--------------------------------------------------------------------------------
/test/BuildTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import qualified Data.Map as Map
18 | import qualified Distribution.Package as Package
19 | import Distribution.Version (mkVersion)
20 | import System.FilePath
21 | import Test.Framework (defaultMain)
22 | import Test.Framework.Providers.HUnit (testCase)
23 | import Test.HUnit (assertEqual)
24 |
25 | import Google.Google3.Tools.Cabal2Build.Actions
26 | import Google.Google3.Tools.Cabal2Build.Build
27 | import Google.Google3.Tools.Cabal2Build.Stackage
28 |
29 | mkPackageName :: String -> Package.PackageName
30 | mkPackageName = Package.mkPackageName
31 |
32 | main = do
33 | defaultMain [ testCase "getDependencies" testGetDependencies ]
34 |
35 | baseDir = "test/testdata/awesome-1.2"
36 |
37 | testGetDependencies = do
38 | (packageDesc, _) <-
39 | loadCabalFile [] testPlan (baseDir > "awesome.cabal")
40 | let expectedDeps = map mkPackageName ["array", "containers", "lens", "package2"]
41 | assertEqual "dependencies" expectedDeps $
42 | getDependencies packageDesc
43 |
44 | testPlan :: Snapshot
45 | testPlan = Snapshot
46 | { corePackageVersions = Map.empty
47 | , ghcVersion = mkVersion [8]
48 | , snapshotPackages = Map.empty
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/test/DownloadTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main (main) where
16 |
17 | import Control.Exception (Exception, try)
18 | import qualified Data.Map as M
19 | import Google.Google3.Tools.Cabal2Build.Download
20 | ( PackageJSON (..),
21 | PkgVerificationError (..),
22 | verifyPackage',
23 | )
24 | import Test.Framework (defaultMain)
25 | import Test.Framework.Providers.API (testGroup)
26 | import Test.Framework.Providers.HUnit (testCase)
27 | import Test.HUnit.Base ((@?=), assertFailure)
28 | import Test.HUnit.Lang (Assertion)
29 |
30 | assertThrows :: (Exception e, Eq e) => e -> IO a -> Assertion
31 | assertThrows expected action = do
32 | result <- try action
33 | case result of
34 | Left thrown -> thrown @?= expected
35 | Right _ ->
36 | assertFailure $ "No exception thrown, expected: " ++ show expected
37 |
38 | fakePackagePath :: FilePath
39 | fakePackagePath =
40 | "test/testdata/verify_package/fake_package.txt"
41 |
42 | fakePackageHash :: String
43 | fakePackageHash =
44 | "cf75eb023a0d96d7f5af5449f87a4667f126f0e3356b9545fe990dbee78d5697"
45 |
46 | testVerifyPackage :: Assertion
47 | testVerifyPackage = do
48 | let f = fakePackagePath
49 | let pkg = PackageJSON (M.fromList [("SHA256", fakePackageHash)]) 29
50 | verifyPackage' f pkg
51 |
52 | testVerifyPackageWrongFileSize :: Assertion
53 | testVerifyPackageWrongFileSize = do
54 | let f = fakePackagePath
55 | let pkg = PackageJSON (M.fromList [("SHA256", fakePackageHash)]) 30
56 | assertThrows (PkgVerificationError "Wrong file size: expected 30, got 29") $
57 | verifyPackage' f pkg
58 |
59 | testVerifyPackageNoSHA256 :: Assertion
60 | testVerifyPackageNoSHA256 = do
61 | let f = fakePackagePath
62 | let pkg = PackageJSON M.empty 29
63 | assertThrows
64 | ( PkgVerificationError
65 | "SHA256 is not found in package JSON: PackageJSON \
66 | \{packageHashes = fromList [], packageSize = 29}"
67 | )
68 | $ verifyPackage' f pkg
69 |
70 | testVerifyPackageWrongSHA256 :: Assertion
71 | testVerifyPackageWrongSHA256 = do
72 | let f = fakePackagePath
73 | let pkg = PackageJSON (M.fromList [("SHA256", "badsha256hash")]) 29
74 | assertThrows
75 | ( PkgVerificationError $
76 | "Wrong SHA256: expected badsha256hash, got " ++ fakePackageHash
77 | )
78 | $ verifyPackage' f pkg
79 |
80 | main :: IO ()
81 | main =
82 | defaultMain
83 | [ testGroup
84 | "verifyPackage'"
85 | [ testCase "ok" testVerifyPackage,
86 | testCase "wrong file size" testVerifyPackageWrongFileSize,
87 | testCase "no sha256" testVerifyPackageNoSHA256,
88 | testCase "wrong sha256" testVerifyPackageWrongSHA256
89 | ]
90 | ]
91 |
--------------------------------------------------------------------------------
/test/LicenseTest.hs:
--------------------------------------------------------------------------------
1 | -- Copyright 2020 Google LLC
2 | --
3 | -- Licensed under the Apache License, Version 2.0 (the "License");
4 | -- you may not use this file except in compliance with the License.
5 | -- You may obtain a copy of the License at
6 | --
7 | -- http://www.apache.org/licenses/LICENSE-2.0
8 | --
9 | -- Unless required by applicable law or agreed to in writing, software
10 | -- distributed under the License is distributed on an "AS IS" BASIS,
11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | -- See the License for the specific language governing permissions and
13 | -- limitations under the License.
14 |
15 | module Main where
16 |
17 | import qualified Distribution.License as Cabal
18 | import Distribution.Version (mkVersion)
19 | import Test.Framework (defaultMain)
20 | import Test.Framework.Providers.HUnit (testCase)
21 | import Test.HUnit (assertEqual)
22 |
23 | import Google.Google3.Tools.Cabal2Build.License
24 |
25 | main = do
26 | defaultMain [ testCase "getDependencies" testLicenseText ]
27 |
28 | caseApache = Cabal.Apache Nothing
29 | caseGPL = Cabal.GPL Nothing
30 | caseLGPL_1_0 = Cabal.LGPL (Just (mkVersion [1,0]))
31 | caseLGPL_2_1 = Cabal.LGPL (Just (mkVersion [2,1]))
32 | caseLGPL_3 = Cabal.LGPL (Just (mkVersion [3]))
33 | caseLGPL = Cabal.LGPL Nothing
34 | caseMPL_2_0 = Cabal.MPL (mkVersion [2])
35 | caseUnknownFoo = Cabal.UnknownLicense "Foo"
36 |
37 | testLicenseText = do
38 | -- Check various version forms.
39 | assertEqual "Explicit trailing .0" (showCabalLicense caseLGPL_1_0) "LGPL-1.0"
40 | assertEqual "Implicit trailing .0" (showCabalLicense caseLGPL_3) "LGPL-3.0"
41 | assertEqual "Multi-digit" (showCabalLicense caseLGPL_2_1) "LGPL-2.1"
42 | assertEqual "Unversioned" (showCabalLicense caseLGPL) "LGPL"
43 |
44 | -- Check spellings of generated license names.
45 | assertEqual "Apache" (showCabalLicense caseApache) "Apache"
46 | assertEqual "BSD2" (showCabalLicense Cabal.BSD2) "BSD-2-Clause"
47 | assertEqual "BSD3" (showCabalLicense Cabal.BSD3) "BSD-3-Clause"
48 | assertEqual "BSD4" (showCabalLicense Cabal.BSD4) "BSD-4-Clause"
49 | assertEqual "GPL" (showCabalLicense caseGPL) "GPL"
50 | assertEqual "ISC" (showCabalLicense Cabal.ISC) "ISC"
51 | assertEqual "MIT" (showCabalLicense Cabal.MIT) "MIT"
52 | assertEqual "MPL" (showCabalLicense caseMPL_2_0) "MPL-2.0"
53 | assertEqual "PubDomain" (showCabalLicense Cabal.PublicDomain) "PublicDomain"
54 | assertEqual "Unknown/foo" (showCabalLicense caseUnknownFoo) "Unknown/Foo"
55 |
56 |
--------------------------------------------------------------------------------
/test/testdata/awesome-1.2/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2015 Google
2 |
--------------------------------------------------------------------------------
/test/testdata/awesome-1.2/README.markdown:
--------------------------------------------------------------------------------
1 | More stuff here.
2 |
--------------------------------------------------------------------------------
/test/testdata/awesome-1.2/awesome.cabal:
--------------------------------------------------------------------------------
1 | Name: awesome
2 | Version: 1.2
3 | Synopsis: An awesome library.
4 | Description: Fake description.
5 | Another description line.
6 | .
7 | New paragraph.
8 | Homepage: http://example.com/awesome
9 | License: BSD3
10 | License-file: LICENSE
11 | Author: John Doe
12 | Maintainer: user@example.org
13 | Bug-reports: http://b/
14 | Category: General
15 | Build-type: Simple
16 | Cabal-version: >=1.10
17 | tested-with: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.1
18 | Extra-source-files: README.markdown
19 |
20 | Source-repository head
21 | type: git
22 | location: git://github.com/awesome/awesome.git
23 |
24 | Flag flag1
25 | Description: Enable some flag
26 | Default: False
27 | Manual: True
28 |
29 | Flag flag2
30 | Description: Enable another flag
31 | Default: True
32 | Manual: False
33 |
34 | Library
35 | Build-depends: array >= 1.3 && < 1.4,
36 | containers >= 1.3 && < 1.4,
37 | lens >= 1.3 && < 1.4
38 |
39 | if flag(flag1)
40 | Build-depends: package1 >= 1.3 && < 1.4
41 |
42 | if flag(flag2)
43 | Build-depends: package2 >= 1.3 && < 1.4
44 |
45 | Default-language: Haskell2010
46 |
--------------------------------------------------------------------------------
/test/testdata/expected_package_description.bzl:
--------------------------------------------------------------------------------
1 | """Package description auto-generated from awesome.cabal by cabal2build.
2 |
3 | Configured with Cabal flags:
4 | flag1: False
5 | flag2: True
6 | """
7 | description = struct(
8 | specVersionRaw = ">=1.10",
9 | package = struct(pkgName = "awesome", pkgVersion = "1.2"),
10 | licenseRaw = "BSD3",
11 | licenseFiles = ["LICENSE"],
12 | copyright = "",
13 | maintainer = "user@example.org",
14 | author = "John Doe",
15 | stability = "",
16 | testedWith = [
17 | ("ghc", "==7.6.3"), ("ghc", "==7.8.4"), ("ghc", "==7.10.1")
18 | ],
19 | homepage = "http://example.com/awesome",
20 | pkgUrl = "",
21 | bugReports = "http://b/",
22 | sourceRepos = [
23 | struct(
24 | repoKind = "RepoHead",
25 | repoType = "Git",
26 | repoLocation = "git://github.com/awesome/awesome.git",
27 | repoModule = None,
28 | repoBranch = None,
29 | repoTag = None,
30 | repoSubdir = None
31 | )
32 | ],
33 | synopsis = "An awesome library.",
34 | description = "Fake description.\nAnother description line.\n\nNew paragraph.",
35 | category = "General",
36 | customFieldsPD = [],
37 | buildTypeRaw = "Simple",
38 | setupBuildInfo = None,
39 | library = struct(
40 | libName = None,
41 | exposedModules = [],
42 | reexportedModules = [],
43 | signatures = [],
44 | libExposed = True,
45 | libBuildInfo = struct(
46 | buildable = True,
47 | buildTools = [],
48 | buildToolDepends = [],
49 | cppOptions = [],
50 | asmOptions = [],
51 | cmmOptions = [],
52 | ccOptions = [],
53 | cxxOptions = [],
54 | ldOptions = [],
55 | pkgconfigDepends = [],
56 | frameworks = [],
57 | extraFrameworkDirs = [],
58 | asmSources = [],
59 | cmmSources = [],
60 | cSources = [],
61 | cxxSources = [],
62 | jsSources = [],
63 | hsSourceDirs = ["."],
64 | otherModules = [],
65 | virtualModules = [],
66 | autogenModules = [],
67 | defaultLanguage = "Haskell2010",
68 | otherLanguages = [],
69 | defaultExtensions = [],
70 | otherExtensions = [],
71 | oldExtensions = [],
72 | extraLibs = [],
73 | extraGHCiLibs = [],
74 | extraBundledLibs = [],
75 | extraLibFlavours = [],
76 | extraLibDirs = [],
77 | includeDirs = [],
78 | includes = [],
79 | installIncludes = [],
80 | options = [],
81 | profOptions = [],
82 | sharedOptions = [],
83 | staticOptions = [],
84 | customFieldsBI = [],
85 | targetBuildDepends = [
86 | struct(name = "array", version = ">=1.3 && <1.4"),
87 | struct(name = "containers", version = ">=1.3 && <1.4"),
88 | struct(name = "lens", version = ">=1.3 && <1.4"),
89 | struct(name = "package2", version = ">=1.3 && <1.4")
90 | ],
91 | mixins = []
92 | )
93 | ),
94 | subLibraries = [],
95 | executables = [],
96 | foreignLibs = [],
97 | testSuites = [],
98 | benchmarks = [],
99 | dataFiles = [],
100 | dataDir = "",
101 | extraSrcFiles = ["README.markdown"],
102 | extraTmpFiles = [],
103 | extraDocFiles = []
104 | )
105 |
--------------------------------------------------------------------------------
/test/testdata/third_party/haskell/awesome/v1_2/awesome.cabal:
--------------------------------------------------------------------------------
1 | Name: awesome
2 | Version: 1.2
3 | Synopsis: An awesome library.
4 | Description: Fake description.
5 | Another description line.
6 | .
7 | New paragraph.
8 | Homepage: http://example.com/awesome
9 | License: BSD3
10 | License-file: LICENSE
11 | Author: John Doe
12 | Maintainer: user@example.org
13 | Bug-reports: http://b/
14 | Category: General
15 | Build-type: Simple
16 | Cabal-version: >=1.10
17 | tested-with: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.1
18 | Extra-source-files: README.markdown
19 |
20 | Source-repository head
21 | type: git
22 | location: git://github.com/awesome/awesome.git
23 |
24 | Flag flag1
25 | Description: Enable some flag
26 | Default: False
27 | Manual: True
28 |
29 | Flag flag2
30 | Description: Enable another flag
31 | Default: True
32 | Manual: False
33 |
34 | Library
35 | Build-depends: knarly >= 1.4 && < 1.6
36 |
37 | if flag(flag1)
38 | Build-depends: package1 >= 1.3 && < 1.4
39 |
40 | if flag(flag2)
41 | Build-depends: groovy >= 1.2 && < 1.4
42 |
43 | Default-language: Haskell2010
44 |
--------------------------------------------------------------------------------
/test/testdata/third_party/haskell/cool/v1_8/cool.cabal:
--------------------------------------------------------------------------------
1 | Name: awesome
2 | Version: 1.2
3 | Synopsis: An awesome library.
4 | Description: Fake description.
5 | Another description line.
6 | .
7 | New paragraph.
8 | Homepage: http://example.com/awesome
9 | License: BSD3
10 | License-file: LICENSE
11 | Author: John Doe
12 | Maintainer: user@example.org
13 | Bug-reports: http://b/
14 | Category: General
15 | Build-type: Simple
16 | Cabal-version: >=1.10
17 | tested-with: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.1
18 | Extra-source-files: README.markdown
19 |
20 | Source-repository head
21 | type: git
22 | location: git://github.com/awesome/awesome.git
23 |
24 | Library
25 |
26 | Default-language: Haskell2010
27 |
--------------------------------------------------------------------------------
/test/testdata/third_party/haskell/groovy/v1_3/groovy.cabal:
--------------------------------------------------------------------------------
1 | Name: awesome
2 | Version: 1.2
3 | Synopsis: An awesome library.
4 | Description: Fake description.
5 | Another description line.
6 | .
7 | New paragraph.
8 | Homepage: http://example.com/awesome
9 | License: BSD3
10 | License-file: LICENSE
11 | Author: John Doe
12 | Maintainer: user@example.org
13 | Bug-reports: http://b/
14 | Category: General
15 | Build-type: Simple
16 | Cabal-version: >=1.10
17 | tested-with: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.1
18 | Extra-source-files: README.markdown
19 |
20 | Source-repository head
21 | type: git
22 | location: git://github.com/awesome/awesome.git
23 |
24 | Flag flag1
25 | Description: Enable some flag
26 | Default: True
27 | Manual: False
28 |
29 | Flag flag2
30 | Description: Enable another flag
31 | Default: True
32 | Manual: False
33 |
34 | Library
35 | if flag(flag1)
36 | Build-depends: cool >= 1.8 && < 2.0
37 |
38 | if flag(flag2)
39 | Build-depends: sweet >= 1.4 && < 1.8
40 |
41 | Default-language: Haskell2010
42 |
--------------------------------------------------------------------------------
/test/testdata/third_party/haskell/knarly/v1_4/knarly.cabal:
--------------------------------------------------------------------------------
1 | Name: awesome
2 | Version: 1.2
3 | Synopsis: An awesome library.
4 | Description: Fake description.
5 | Another description line.
6 | .
7 | New paragraph.
8 | Homepage: http://example.com/awesome
9 | License: BSD3
10 | License-file: LICENSE
11 | Author: John Doe
12 | Maintainer: user@example.org
13 | Bug-reports: http://b/
14 | Category: General
15 | Build-type: Simple
16 | Cabal-version: >=1.10
17 | tested-with: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.1
18 | Extra-source-files: README.markdown
19 |
20 | Source-repository head
21 | type: git
22 | location: git://github.com/awesome/awesome.git
23 |
24 | Flag flag1
25 | Description: Enable some flag
26 | Default: False
27 | Manual: True
28 |
29 | Flag flag2
30 | Description: Enable another flag
31 | Default: True
32 | Manual: False
33 |
34 | Library
35 | if flag(flag1)
36 | Build-depends: package1 >= 1.3 && < 1.4
37 |
38 | if flag(flag2)
39 | Build-depends: cool >= 1.8 && < 1.9
40 |
41 | Default-language: Haskell2010
42 |
--------------------------------------------------------------------------------
/test/testdata/third_party/haskell/sweet/v1_4/sweet.cabal:
--------------------------------------------------------------------------------
1 | Name: awesome
2 | Version: 1.2
3 | Synopsis: An awesome library.
4 | Description: Fake description.
5 | Another description line.
6 | .
7 | New paragraph.
8 | Homepage: http://example.com/awesome
9 | License: BSD3
10 | License-file: LICENSE
11 | Author: John Doe
12 | Maintainer: user@example.org
13 | Bug-reports: http://b/
14 | Category: General
15 | Build-type: Simple
16 | Cabal-version: >=1.10
17 | tested-with: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.1
18 | Extra-source-files: README.markdown
19 |
20 | Source-repository head
21 | type: git
22 | location: git://github.com/awesome/awesome.git
23 |
24 | Library
25 | Build-depends: cool >= 1.8 && < 1.9
26 |
27 | Default-language: Haskell2010
28 |
--------------------------------------------------------------------------------
/test/testdata/verify_package/fake_package.txt:
--------------------------------------------------------------------------------
1 | This is a fake package data.
2 |
--------------------------------------------------------------------------------
/test_support/BUILD:
--------------------------------------------------------------------------------
1 | # Test support files for the Haskell build rules.
2 | # In some of the tests, we want to check our handling of
3 | # the "includes" attribute, which is used
4 | # by the cabal_package macro.
5 | licenses(["unencumbered"])
6 |
7 | cc_library(
8 | name = "hsc2hs_dep",
9 | hdrs = ["includes/hsc2hs_dep.h"],
10 | includes = ["includes"],
11 | visibility = ["//bzl/tests/hsc2hs:__pkg__"],
12 | )
13 |
14 | cc_library(
15 | name = "header_provider",
16 | hdrs = ["includes/header_provider.h"],
17 | includes = ["includes"],
18 | visibility = ["//bzl/tests/ffi:__pkg__"],
19 | )
20 |
--------------------------------------------------------------------------------
/test_support/includes/header_provider.h:
--------------------------------------------------------------------------------
1 | /* Common defines for HeadersTest and HeadersLib.
2 | * Note: lint wants us to put "#ifndef..." guards on C++ header (*.h files),
3 | * including a trailing "//".
4 | * Unfortunately, that badly breaks the compile chain, in part because
5 | * this file will be spliced into Haskell code instead of C++ code.
6 | * Normally we'd just add a "// NOLINT" pragma but, for the same reason, we
7 | * can't use "//" comments here.
8 | */
9 | #define FOO 42
10 | #define BAR 17
11 |
--------------------------------------------------------------------------------
/test_support/includes/hsc2hs_dep.h:
--------------------------------------------------------------------------------
1 | #ifndef TOOLS_BUILD_DEFS_HASKELL_TESTS_HSC2HS_INCLUDES_C_DEP_H_
2 | #define TOOLS_BUILD_DEFS_HASKELL_TESTS_HSC2HS_INCLUDES_C_DEP_H_
3 |
4 | typedef struct {
5 | int x;
6 | int y;
7 | } foo;
8 |
9 | #endif // TOOLS_BUILD_DEFS_HASKELL_TESTS_HSC2HS_INCLUDES_C_DEP_H_
10 |
--------------------------------------------------------------------------------
/third_party/haskell/ghc/BUILD:
--------------------------------------------------------------------------------
1 | # Description: GHC binaries to be used by Blaze.
2 | # This is a redirector file so that the Haskell version compilation switch
3 | # can be thrown with minimal BUILD config changes.
4 |
5 | licenses(["restricted"])
6 |
7 | load(":versions.bzl", "GHC_VERSION_SETTINGS", "ghc_config_settings")
8 | load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
9 | load("//bzl:config.bzl", "ghc_config", "haskell_cc_toolchain_files")
10 | load("//bzl:generate_core_libraries.bzl", "generate_core_library_rules")
11 |
12 | package(default_visibility = ["//visibility:public"])
13 |
14 | ghc_config_settings()
15 |
16 | # To avoid unwanted dependencies, we declare a visibility that only allows
17 | # //third_party/haskell/ghc to access and forward these targets.
18 | package_group(
19 | name = "main_ghc",
20 | packages = ["//third_party/haskell/ghc"],
21 | )
22 |
23 | # C/C++ code that needs to include headers from GHC (such as ) should
24 | # depend on this target.
25 | alias(
26 | name = "headers",
27 | actual = select({
28 | version: GHC_VERSION_SETTINGS[version].package + ":headers"
29 | for version in GHC_VERSION_SETTINGS
30 | }),
31 | )
32 |
33 | # The GHC library directory is needed for using the GHC API.
34 | # Applications can use //third_party/haskell/ghc-paths:ghc_paths to
35 | # add those files as a dependency and find the correct location.
36 | filegroup(
37 | name = "library_bundle",
38 | srcs = select({
39 | version: [GHC_VERSION_SETTINGS[version].package + ":library-bundle"]
40 | for version in GHC_VERSION_SETTINGS
41 | }),
42 | )
43 |
44 | # Support files for ghaddock.
45 | filegroup(
46 | name = "haddock_support",
47 | srcs = select({
48 | version: [GHC_VERSION_SETTINGS[version].package + ":haddock_support"]
49 | for version in GHC_VERSION_SETTINGS
50 | }),
51 | )
52 |
53 | filegroup(
54 | name = "everything",
55 | srcs = select({
56 | version: [GHC_VERSION_SETTINGS[version].package + ":everything"]
57 | for version in GHC_VERSION_SETTINGS
58 | }),
59 | )
60 |
61 | # A minimum set of files which the GHC API loads when it initializes.
62 | filegroup(
63 | name = "settings",
64 | srcs = select({
65 | version: [GHC_VERSION_SETTINGS[version].package + ":settings"]
66 | for version in GHC_VERSION_SETTINGS
67 | }),
68 | )
69 |
70 | ghc_config(
71 | name = "config",
72 | config = select({
73 | version: GHC_VERSION_SETTINGS[version].package + ":config"
74 | for version in GHC_VERSION_SETTINGS
75 | }),
76 | )
77 |
78 | generate_core_library_rules()
79 |
80 | # A target that provides all of the C++ toolchain's files.
81 | haskell_cc_toolchain_files(
82 | name = "cc_toolchain",
83 | visibility = ["//devtools/grok/lang/haskell:__subpackages__"],
84 | )
85 |
86 | bzl_library(
87 | name = "versions",
88 | srcs = ["versions.bzl"],
89 | deps = [
90 | "@bazel_skylib//lib:dicts",
91 | ],
92 | )
93 |
--------------------------------------------------------------------------------
/third_party/haskell/ghc/versions.bzl:
--------------------------------------------------------------------------------
1 | """Definitions to support multiple GHC versions.
2 | """
3 |
4 | load("@bazel_skylib//lib:dicts.bzl", "dicts")
5 |
6 | # The list of wired-up GHC builds.
7 | # Note that two builds of GHC may have the same major version number;
8 | # for example, if we're doing a minor version bump, or if we
9 | # built GHC with a different configuration.
10 | _GHC_VERSIONS = {
11 | "8.6": struct(
12 | major_version = "8.6",
13 | package = "//third_party/haskell/ghc/v8_6_4",
14 | src_package = "//third_party/haskell/ghc/vendor_src/v8_6_4",
15 | ),
16 | }
17 |
18 | # The build of GHC that we will use without any explicit "--define GHC=..."
19 | _DEFAULT_VERSION = "8.6"
20 |
21 | def ghc_config_settings():
22 | """Function to generate config_setting rules."""
23 | native.config_setting(
24 | name = "v8.6",
25 | define_values = {
26 | "GHC": "8.6",
27 | },
28 | )
29 |
30 | # A map keyed by config_settings (as defined by ghc_config_settings())
31 | # which can be used to construct a select() statement.
32 | GHC_VERSION_SETTINGS = dicts.add(
33 | {
34 | "//third_party/haskell/ghc:v" + k: _GHC_VERSIONS[k]
35 | for k in _GHC_VERSIONS
36 | },
37 | # Blaze doesn't have a defaulting mechanism for "--define",
38 | # so add an explicit entry to this map.
39 | {"//conditions:default": _GHC_VERSIONS[_DEFAULT_VERSION]},
40 | )
41 |
42 | def select_by_ghc_version(version_map):
43 | """Constructs a select() statement for different GHC versions.
44 |
45 | Useful for third-party packages that need to choose their own
46 | version based on the version of GHC.
47 |
48 | This function only allows selecting by major GHC version,
49 | since minor versions are generally API-compatible with each other.
50 |
51 | The map must specify a value for the default GHC version. Any other GHC
52 | versions not explicitly specified will also use that default value.
53 |
54 | Example:
55 |
56 | haskell_library(
57 | name = "singletons",
58 | deps = select_by_ghc_version({
59 | "8.4": ["//third_party/haskell/singletons/v2_4_1:singletons"],
60 | "8.0": ["//third_party/haskell/singletons/v2_2_2:singletons"],
61 | }),
62 | )
63 |
64 | Args:
65 | version_map: A map keyed by strings which are major GHC versions (e.g., "8.6").
66 |
67 | Returns:
68 | A select() statement with one entry for each built GHC.
69 | """
70 | return select(dict_by_ghc_version(version_map))
71 |
72 | def dict_by_ghc_version(version_map):
73 | return {
74 | k: version_map.get(
75 | GHC_VERSION_SETTINGS[k].major_version,
76 | version_map[_DEFAULT_VERSION],
77 | )
78 | for k in GHC_VERSION_SETTINGS
79 | }
80 |
81 | def unless_ghc_version(version):
82 | """Tests whether the given GHC version is the default.
83 |
84 | Useful for marking targets as "disabled" so TAP doesn't build them.
85 |
86 | Example usage:
87 |
88 | cabal_haskell_package(
89 | description = description,
90 | disabled = unless_ghc_version("8.6"),
91 | )
92 |
93 | Args:
94 | version: A string; GHC major version; e.g., "8.6".
95 |
96 | Returns:
97 | A boolean; True iff the given version is *not* the default.
98 | """
99 |
100 | # Sanity-check that this is a know version.
101 | if version not in _GHC_VERSIONS:
102 | fail("Unknown version " + version)
103 | return _DEFAULT_VERSION != version
104 |
--------------------------------------------------------------------------------