├── .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 | --------------------------------------------------------------------------------