packages feed

cabal-buck2 0.3.0.0 → 0.4.0.0

raw patch · 34 files changed

+443/−48 lines, 34 filesdep ~CabalPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: Cabal

API changes (from Hackage documentation)

+ Distribution.Client.Buck2.Flags: [buck2CustomSetup] :: Buck2Flags -> Flag Bool
+ Distribution.Client.Buck2.LocalPackages: [bpCustomSetup] :: BuiltPackage -> Bool
+ Distribution.Client.Buck2.LocalPackages: translateCustomSetups :: Verbosity -> DependencyMode -> DistDirLayout -> ElaboratedInstallPlan -> IO (ElaboratedInstallPlan, Set PackageId)
+ Distribution.Client.Buck2.Prebuilt: prebuiltLinkerFlags :: InstalledPackageInfo -> [String]
+ Distribution.Client.Buck2.Spec: SrcProvided :: Src
+ Distribution.Client.Buck2.Spec: [scBootSrcs] :: SpecComponent -> [(String, FilePath)]
+ Distribution.Client.Buck2.Spec: [scExtraLibDirs] :: SpecComponent -> [FilePath]
+ Distribution.Client.Buck2.Spec: [scLdOptions] :: SpecComponent -> [String]
+ Distribution.Client.Buck2.Spec: [specExtraSourceFiles] :: BuildSpec -> [FilePath]
- Distribution.Client.Buck2.Flags: Buck2Flags :: Flag String -> Flag Bool -> Flag Bool -> Buck2Flags
+ Distribution.Client.Buck2.Flags: Buck2Flags :: Flag String -> Flag Bool -> Flag Bool -> Flag Bool -> Buck2Flags
- Distribution.Client.Buck2.Generate: generatePackageTargets :: LocalPackageIndex -> FilePath -> Map (PackageName, ComponentName) LocalBuildInfo -> Set String -> Map (PackageName, ComponentName) [PathTemplate] -> Set FilePath -> Set (PackageName, LibraryName) -> Bool -> PackageDescription -> (PackageTargets, [String])
+ Distribution.Client.Buck2.Generate: generatePackageTargets :: LocalPackageIndex -> FilePath -> Map (PackageName, ComponentName) LocalBuildInfo -> Set String -> Map (PackageName, ComponentName) [PathTemplate] -> Set FilePath -> Set (PackageName, LibraryName) -> Bool -> Bool -> PackageDescription -> (PackageTargets, [String])
- Distribution.Client.Buck2.LocalPackages: BuiltPackage :: FilePath -> PackageDescription -> Bool -> BuiltPackage
+ Distribution.Client.Buck2.LocalPackages: BuiltPackage :: FilePath -> PackageDescription -> Bool -> Bool -> BuiltPackage
- Distribution.Client.Buck2.LocalPackages: builtLocalPackages :: Verbosity -> DependencyMode -> DistDirLayout -> ElaboratedInstallPlan -> IO [BuiltPackage]
+ Distribution.Client.Buck2.LocalPackages: builtLocalPackages :: Verbosity -> DependencyMode -> DistDirLayout -> Set PackageId -> ElaboratedInstallPlan -> IO [BuiltPackage]
- Distribution.Client.Buck2.Spec: BuildSpec :: String -> String -> [String] -> FilePath -> [FilePath] -> [SpecComponent] -> BuildSpec
+ Distribution.Client.Buck2.Spec: BuildSpec :: String -> String -> [String] -> FilePath -> [FilePath] -> [FilePath] -> [SpecComponent] -> BuildSpec
- Distribution.Client.Buck2.Spec: SpecComponent :: ComponentKind -> String -> Maybe String -> Maybe Src -> [(String, Src)] -> [String] -> [String] -> [String] -> Maybe String -> [String] -> [String] -> [SpecDep] -> [SpecReexport] -> [SpecBuildTool] -> [FilePath] -> [String] -> [FilePath] -> [String] -> [FilePath] -> [FilePath] -> [String] -> [FilePath] -> [String] -> [FilePath] -> [String] -> SpecComponent
+ Distribution.Client.Buck2.Spec: SpecComponent :: ComponentKind -> String -> Maybe String -> Maybe Src -> [(String, Src)] -> [(String, FilePath)] -> [String] -> [String] -> [String] -> Maybe String -> [String] -> [String] -> [String] -> [FilePath] -> [SpecDep] -> [SpecReexport] -> [SpecBuildTool] -> [FilePath] -> [String] -> [FilePath] -> [String] -> [FilePath] -> [FilePath] -> [String] -> [FilePath] -> [String] -> [FilePath] -> [String] -> SpecComponent

Files

README.md view
@@ -169,6 +169,21 @@ targets - take a look at the comments in the generated code to see how. +The overrides can also go in a `cabal-buck2.bzl` file in the root of+the project, for all of its packages at once, which is useful when a+package's directory isn't yours to add files to (a git submodule, say):++```+OVERRIDES = {+    # package name -> component name -> extra attributes+    "my-package": {+        "my-package": {"compiler_flags": ["-O2"]},+    },+}+```++Re-run `cabal buck2` after adding or removing `cabal-buck2.bzl`.+ You can also completely override the generated targets and write a `BUCK` file with your own rules, while still making use of the pre-built dependencies that `cabal buck2` produces.  For example, the@@ -387,6 +402,22 @@ also applies to dependencies when `--source-deps` is being used.  As with other unsupported features, you can use `--keep-going` to just skip all the affected packages.++If a package's `Setup.hs` isn't needed by your build, or what it+does can be done some other way, `--enable-custom-setup` builds it as+if it had `build-type: Simple` (or `Configure`, if it has a+`configure` script). The modules that its `Setup.hs` would generate+(its `autogen-modules`) must then be given by the project, in the+overrides of the component (see [Customising the build](#customising-the-build)),+for example++```+OVERRIDES = {+    "my-package": {+        "my-package": {"srcs": {"My.Generated.Module": "//gen:my-module"}},+    },+}+```  ## Hooks build type 
cabal-buck2.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.8 name:               cabal-buck2-version:            0.3.0.0+version:            0.4.0.0  -- To ship a new version: --   - bump the version above@@ -37,6 +37,8 @@   test/fixtures/**/*.cabal   test/fixtures/**/*.h   test/fixtures/**/*.hs+  test/fixtures/**/*.hs-boot+  test/fixtures/**/*.pc   test/fixtures/**/*.project   test/fixtures/**/.buckconfig   test/fixtures/**/.gitkeep@@ -121,6 +123,7 @@   build-depends:     , base          >=4.17 && <4.24     , bytestring    >=0.11.5 && <0.12+    , Cabal     , cabal-buck2     , containers    >=0.6.7 && <0.7     , directory
changelog.md view
@@ -1,3 +1,24 @@+# 0.4.0.0++  * For `cabal-install` version 3.18+  * `--enable-custom-setup` builds the packages with `build-type:+    Custom` as if they had `build-type: Configure` (if they have a+    `configure` script) or `Simple`, instead of skipping them. Their+    `Setup.hs` isn't run, so the modules it would generate (its+    `autogen-modules`) must be provided by the project.+  * A project can override the generated targets of its packages in a+    `cabal-buck2.bzl` at its root, rather than in each package's+    `BUCK` file.+  * A package's `extra-source-files` are a target,+    `<package>-extra-source-files`, for other targets that need them+    (a generator of the package's sources, say).+  * The `.hs-boot` file of a module is an input of the module's+    compilation, and is found next to its source when that is+    generated (by `happy`, say).+  * Pass `extra-lib-dirs` and `ld-options` through to Buck2. This+    fixes some cases of `pkgconfig-depends` not working correctly+    with Buck2, amongst other things.+ # 0.3.0.0    * For `cabal-install` version 3.18
src/Distribution/Client/Buck2/Flags.hs view
@@ -20,10 +20,11 @@   { buck2CacheAddress :: Flag String   , buck2NoCache :: Flag Bool   , buck2SourceDeps :: Flag Bool+  , buck2CustomSetup :: Flag Bool   }  defaultBuck2Flags :: Buck2Flags-defaultBuck2Flags = Buck2Flags{buck2CacheAddress = mempty, buck2NoCache = mempty, buck2SourceDeps = mempty}+defaultBuck2Flags = Buck2Flags{buck2CacheAddress = mempty, buck2NoCache = mempty, buck2SourceDeps = mempty, buck2CustomSetup = mempty}  buck2FlagOptions :: ShowOrParseArgs -> [OptionField Buck2Flags] buck2FlagOptions _ =@@ -47,6 +48,13 @@       "Build the dependencies with buck2, from their sources (unpacked under dist-newstyle), like the packages of the project, instead of having cabal build them into its store. Nothing is then taken from the store."       buck2SourceDeps       (\v f -> f{buck2SourceDeps = v})+      trueArg+  , option+      []+      ["enable-custom-setup"]+      "Build the packages with build-type: Custom as if they had build-type: Configure (if they have a configure script) or Simple, rather than skipping them. Their Setup.hs isn't run: the modules it would generate must be provided (see buck2/cabal.bzl)."+      buck2CustomSetup+      (\v f -> f{buck2CustomSetup = v})       trueArg   ] 
src/Distribution/Client/Buck2/Generate.hs view
@@ -27,7 +27,7 @@ import Distribution.Client.Compat.Prelude import Prelude () -import System.FilePath (isRelative, makeRelative, normalise, (<.>), (</>))+import System.FilePath (isRelative, makeRelative, normalise, replaceExtension, (<.>), (</>))  import Data.Either (fromLeft) import qualified Data.Map as Map@@ -52,6 +52,7 @@   , buildToolDepends   , asmOptions   , asmSources+  , autogenModules   , cSources   , cmmSources   , jsSources@@ -61,8 +62,11 @@   , cxxSources   , dataDir   , dataFiles+  , extraSrcFiles   , usedExtensions   , defaultLanguage+  , extraLibDirs+  , ldOptions   , extraLibs   , hcOptions   , hsSourceDirs@@ -176,6 +180,15 @@ componentTargets :: SpecComponent -> [AutogenFile] -> ComponentTargets componentTargets component files = mempty{ctSpec = [component], ctAutogen = files} +-- | What the modules of a package's components are found in.+data Sources = Sources+  { sourceFiles :: Set FilePath+  -- ^ The package's source files, relative to its directory.+  , providedModules :: Set ModuleName.ModuleName+  -- ^ The modules that the package's own @Setup.hs@ would have generated,+  -- which the project provides instead (see 'SrcProvided').+  }+ -- | Generate the buck2 targets for every buildable component of a local -- package, along with the warnings for the components that had to be -- skipped (and why). This does no IO: the source files it looks for are@@ -201,12 +214,26 @@   -- ^ Whether this is a package of the project, as opposed to a dependency   -- that is built like one. A dependency has components that nothing   -- needs (its tests, say), which are skipped without a warning.+  -> Bool+  -- ^ Whether the package has @build-type: Custom@, and is built as if it+  -- didn't (@--enable-custom-setup@), so its @Setup.hs@ isn't run: the+  -- modules that would have generated (its @autogen-modules@, other than+  -- the ones generated here) are up to the project.   -> PackageDescription   -> (PackageTargets, [String])-generatePackageTargets localIndex projectRoot componentLBIs externalBuildTools projectTestOptions sources skippedLibs inProject pkgDesc =+generatePackageTargets localIndex projectRoot componentLBIs externalBuildTools projectTestOptions sources skippedLibs inProject customSetup pkgDesc =   (targets, concatMap ctWarnings results)   where-    generate = generateComponent localIndex projectRoot componentLBIs externalBuildTools projectTestOptions sources skippedLibs inProject pkgDesc+    generate = generateComponent localIndex projectRoot componentLBIs externalBuildTools projectTestOptions (Sources sources provided) skippedLibs inProject pkgDesc+    provided+      | customSetup =+          Set.fromList+            [ m+            | comp <- pkgBuildableComponents pkgDesc+            , m <- autogenModules (componentBuildInfo comp)+            , m /= autogenPathsModuleName pkgDesc+            ]+      | otherwise = Set.empty     comps = map configured (pkgBuildableComponents pkgDesc)      -- The component as configuring left it: with what a @configure@ script@@ -216,7 +243,7 @@       lookupComponent (localPkgDescr lbi) (componentName comp)      results = map generate comps-    components = concatMap ctSpec results+    components = [c{scBootSrcs = bootSources sources (scSrcs c)} | c <- concatMap ctSpec results]     targets =       PackageTargets         { ptSpec = packageSpec pkgDesc (packageGhcOptions pkgDesc componentLBIs) components@@ -253,7 +280,7 @@   -> Map (PackageName, ComponentName) LocalBuildInfo   -> Set String   -> Map (PackageName, ComponentName) [PathTemplate]-  -> Set FilePath+  -> Sources   -> Set (PackageName, LibraryName)   -> Bool   -> PackageDescription@@ -294,7 +321,7 @@     ifNotOnSkippedLib bi targetName kind act       | isNothing (lbiClbiFor pkgDesc componentLBIs comp) = notConfigured (kindName kind ++ " " ++ targetName)       | buildType pkgDesc == Custom =-          skip (kindName kind ++ " " ++ targetName ++ " (build-type: Custom needs its Setup.hs to be run)")+          skip (kindName kind ++ " " ++ targetName ++ " (build-type: Custom needs its Setup.hs to be run, unless --enable-custom-setup)")       | unsupported : _ <- unsupportedSources bi =           skip (kindName kind ++ " " ++ targetName ++ " (" ++ unsupported ++ " aren't supported)")       | otherwise =@@ -345,7 +372,7 @@     -- test-suite and benchmark: a @main-is@ file over the @other-modules@.     mainIsComponent kind targetName bi mainIs extra = case lbiClbiFor pkgDesc componentLBIs comp of       Nothing -> notConfigured (kindName kind ++ " " ++ targetName)-      Just (lbi, clbi) -> case (resolveMainIs sources bi mainIs, resolveModules sources pkgDesc (Just (lbi, clbi)) bi (otherModules bi)) of+      Just (lbi, clbi) -> case (resolveMainIs (sourceFiles sources) bi mainIs, resolveModules sources pkgDesc (Just (lbi, clbi)) bi (otherModules bi)) of         (Right mainSrc, Right (otherSrcs, srcAutogen)) ->           executableLike kind targetName lbi clbi bi (SrcFile mainSrc) otherSrcs (extra lbi) srcAutogen         (mainRes, othersRes) ->@@ -466,6 +493,7 @@     , specGhcOptions = projectGhcOptions     , specDataDir = getSymbolicPath (dataDir pkgDesc)     , specDataFiles = map getSymbolicPath (dataFiles pkgDesc)+    , specExtraSourceFiles = map getSymbolicPath (extraSrcFiles pkgDesc)     , specComponents = components     } @@ -479,6 +507,7 @@     , scExeName = Nothing     , scMainIs = Nothing     , scSrcs = []+    , scBootSrcs = []     , scTestArgs = []     , scGhcOptions = hcOptions GHC bi     , scCppOptions = cppOptions bi@@ -486,6 +515,8 @@       scLanguage = Just (prettyShow (fromMaybe Haskell98 (defaultLanguage bi)))     , scExtensions = map prettyShow (usedExtensions bi)     , scExtraLibraries = extraLibs bi+    , scLdOptions = ldOptions bi+    , scExtraLibDirs = map getSymbolicPath (extraLibDirs bi)     , scDeps = map specDep (libraryDeps bi)     , scReexports = []     , scBuildTools = mapMaybe buildToolSpec (ordNub [(pn, exe) | ExeDependency pn exe _ <- buildToolDepends bi])@@ -689,13 +720,13 @@ -- while evaluating the @BUCK@ file, which (since a @buck2 build //...@ -- evaluates every @BUCK@ file up front) would otherwise take the *entire* -- build down over one unresolvable module in one component of one package.-resolveModules :: Set FilePath -> PackageDescription -> Maybe (LocalBuildInfo, ComponentLocalBuildInfo) -> BuildInfo -> [ModuleName.ModuleName] -> Either [String] ([(String, Src)], [AutogenFile])+resolveModules :: Sources -> PackageDescription -> Maybe (LocalBuildInfo, ComponentLocalBuildInfo) -> BuildInfo -> [ModuleName.ModuleName] -> Either [String] ([(String, Src)], [AutogenFile]) resolveModules sources pkgDesc mlbiClbi bi mods =   case partitionEithers (map (resolveOne sources pkgDesc mlbiClbi bi) mods) of     ([], triples) -> Right ([(n, v) | (n, v, _) <- triples], concat [fs | (_, _, fs) <- triples])     (problems, _) -> Left problems -resolveOne :: Set FilePath -> PackageDescription -> Maybe (LocalBuildInfo, ComponentLocalBuildInfo) -> BuildInfo -> ModuleName.ModuleName -> Either String (String, Src, [AutogenFile])+resolveOne :: Sources -> PackageDescription -> Maybe (LocalBuildInfo, ComponentLocalBuildInfo) -> BuildInfo -> ModuleName.ModuleName -> Either String (String, Src, [AutogenFile]) resolveOne sources pkgDesc mlbiClbi bi m   | m == autogenPathsModuleName pkgDesc = case mlbiClbi of       Nothing ->@@ -703,14 +734,16 @@       Just (lbi, clbi) ->         let file = pathsModuleFile pkgDesc lbi clbi m          in Right (prettyShow m, SrcAutogen (autogenName file), [file])-  | otherwise = case firstExisting sources (moduleCandidates bi m) of+  | otherwise = case firstExisting (sourceFiles sources) (moduleCandidates bi m) of       Just real -> Right (prettyShow m, SrcFile real, [])-      Nothing ->-        Left $-          "cabal buck2: couldn't find a source file for module "-            ++ prettyShow m-            ++ " under "-            ++ intercalate ", " (sourceDirs bi)+      Nothing+        | m `Set.member` providedModules sources -> Right (prettyShow m, SrcProvided, [])+        | otherwise ->+            Left $+              "cabal buck2: couldn't find a source file for module "+                ++ prettyShow m+                ++ " under "+                ++ intercalate ", " (sourceDirs bi)  -- | Cabal's own Setup.hs generates a @Paths_\<pkg\>@ module fresh at -- configure\/build time (giving @version@\/@getDataFileName@\/etc) - no@@ -776,6 +809,15 @@ moduleCandidates :: BuildInfo -> ModuleName.ModuleName -> [FilePath] moduleCandidates bi m = [normalise (dir </> ModuleName.toFilePath m <.> ext) | dir <- sourceDirs bi, ext <- ["hs", "lhs", "hsc", "x", "y", "ly"]] +-- | Where GHC looks for the boot file of a module whose source is the given+-- file: next to it.+bootCandidates :: FilePath -> [FilePath]+bootCandidates src = [replaceExtension src ext | ext <- ["hs-boot", "lhs-boot"]]++-- | The boot files of the modules with the given sources, that exist.+bootSources :: Set FilePath -> [(String, Src)] -> [(String, FilePath)]+bootSources sources srcs = [(m, boot) | (m, SrcFile src) <- srcs, Just boot <- [firstExisting sources (bootCandidates src)]]+ mainIsCandidates :: BuildInfo -> FilePath -> [FilePath] mainIsCandidates bi mainIs = [normalise (dir </> mainIs) | dir <- sourceDirs bi] @@ -810,7 +852,7 @@       CFLib _ -> []       where         bi = componentBuildInfo comp-    modules bi = concatMap (moduleCandidates bi)+    modules bi = concatMap (\m -> let cs = moduleCandidates bi m in cs ++ concatMap bootCandidates cs)     mainIs = mainIsCandidates  sourceDirs :: BuildInfo -> [FilePath]
src/Distribution/Client/Buck2/LocalPackages.hs view
@@ -12,6 +12,7 @@   , componentNamesFor   , BuiltPackage (..)   , builtLocalPackages+  , translateCustomSetups   , rootRelativeDir   , nonLibraryTargetName   , ToolTarget (..)@@ -31,6 +32,7 @@  import Distribution.Client.DistDirLayout (DistDirLayout (distUnpackedSrcDirectory, distUnpackedSrcRootDirectory)) import qualified Distribution.Client.InstallPlan as InstallPlan+import qualified Distribution.Compat.Graph as Graph import Distribution.Client.ProjectPlanning   ( ElaboratedConfiguredPackage (..)   , ElaboratedInstallPlan@@ -47,11 +49,11 @@ import Distribution.Client.Types.PackageLocation (PackageLocation (..)) import Distribution.Types.UnitId (UnitId, newSimpleUnitId) -import Distribution.Package (HasUnitId (installedUnitId), PackageInstalled (installedDepends), PackageName, packageId, packageName, unPackageName)+import Distribution.Package (HasUnitId (installedUnitId), PackageId, PackageInstalled (installedDepends), PackageName, packageId, packageName, unPackageName) import Distribution.PackageDescription (PackageDescription) import qualified Distribution.PackageDescription as PD import Distribution.Simple.InstallDirs (PathTemplate)-import Distribution.Simple.Utils (die', info, ordNub)+import Distribution.Simple.Utils (die', info, ordNub, warn) import Distribution.Types.Component (componentBuildInfo, componentName) import Distribution.Types.ComponentName (ComponentName (CTestName)) import Distribution.Types.Dependency (depPkgName)@@ -204,19 +206,59 @@   , bpInProject :: Bool   -- ^ A package of the project, as opposed to a dependency that is built   -- like one.+  , bpCustomSetup :: Bool+  -- ^ A package with @build-type: Custom@ that is built as if it didn't+  -- (see 'translateCustomSetups'): 'bpDescription' has the build type it is+  -- built as.   } +-- | For @--enable-custom-setup@: the plan, with each package that buck2+-- builds and that has @build-type: Custom@ built as if it had @build-type:+-- Configure@ if it has a @configure@ script, or @Simple@ if not (as Hadrian+-- does), and the packages that are. Their @Setup.hs@ isn't run, so whatever+-- it does is up to the project.+translateCustomSetups :: Verbosity -> DependencyMode -> DistDirLayout -> ElaboratedInstallPlan -> IO (ElaboratedInstallPlan, Set PackageId)+translateCustomSetups verbosity mode distDirLayout plan = do+  pkgs <- traverse translate (InstallPlan.toList plan)+  let translated = Map.fromList (mapMaybe snd pkgs)+  for_ (Map.toList translated) $ \(pkgId, buildType) ->+    warn verbosity $+      "cabal buck2: building "+        ++ prettyShow pkgId+        ++ " as if it had build-type: "+        ++ prettyShow buildType+        ++ " (--enable-custom-setup), so its Setup.hs isn't run"+  return (InstallPlan.new (InstallPlan.planIndepGoals plan) (Graph.fromDistinctList (map fst pkgs)), Map.keysSet translated)+  where+    translate pkg = case pkg of+      InstallPlan.Configured elab+        | isBuiltLocally mode elab+        , PD.buildType desc == PD.Custom -> do+            dir <- packageSourceDir verbosity distDirLayout elab+            hasConfigure <- doesFileExist (dir </> "configure")+            let buildType = if hasConfigure then PD.Configure else PD.Simple+            return (InstallPlan.Configured elab{elabPkgDescription = desc{PD.buildTypeRaw = Just buildType}}, Just (packageId elab, buildType))+        where+          desc = elabPkgDescription elab+      _ -> return (pkg, Nothing)+ -- | Every package buck2 builds from source. Per-component elaboration gives -- each such package one 'ElaboratedConfiguredPackage' per component, all -- sharing the same directory and 'PackageDescription', so there is one -- entry per directory here.-builtLocalPackages :: Verbosity -> DependencyMode -> DistDirLayout -> ElaboratedInstallPlan -> IO [BuiltPackage]-builtLocalPackages verbosity mode distDirLayout plan = do+builtLocalPackages :: Verbosity -> DependencyMode -> DistDirLayout -> Set PackageId -> ElaboratedInstallPlan -> IO [BuiltPackage]+builtLocalPackages verbosity mode distDirLayout customSetups plan = do   pkgs <-     fmap (nubBy ((==) `on` bpDir)) . sequenceA $       [ do         dir <- packageSourceDir verbosity distDirLayout elab-        return BuiltPackage{bpDir = dir, bpDescription = elabPkgDescription elab, bpInProject = elabLocalToProject elab}+        return+          BuiltPackage+            { bpDir = dir+            , bpDescription = elabPkgDescription elab+            , bpInProject = elabLocalToProject elab+            , bpCustomSetup = packageId elab `Set.member` customSetups+            }       | elab <- builtLocalElabs mode plan       ]   -- Everything that refers to a package does so by its name (a dependency in
src/Distribution/Client/Buck2/Prebuilt.hs view
@@ -23,6 +23,7 @@   ( generatePrebuilt   , RepoPaths (..)   , externalDirs+  , prebuiltLinkerFlags   , toRepoRelative   ) where @@ -506,8 +507,22 @@     profiled = rel (rpProfiledLibs p)     globalDbRel = ("ghc-" ++ rpGhcVersion paths) </> "package.conf.d"     headerDirs = mapMaybe (toRepoRelative paths) (includeDirs info)-    extraLinkerFlags = ["-l" ++ lib | lib <- extraLibraries info]+    extraLinkerFlags = prebuiltLinkerFlags info     depTargets = ordNub [":" ++ t | d <- depends info, Just t <- [Map.lookup d uidToTarget]]++-- | The linker flags a package's @.conf@ file asks for: its @extra-libraries@,+-- and where to find them. The @library-dirs@ of a package that needs a+-- system library are also where that library is, when it isn't on the+-- linker's default path: Cabal records the directory it was found in at+-- configure time (@extra-lib-dirs@, or a Nix store path), and GHC passes+-- them all as @-L@ when it links against the package. Without them the+-- @-l@ flag alone can't be satisfied.+prebuiltLinkerFlags :: InstalledPackageInfo -> [String]+prebuiltLinkerFlags info =+  ["-L" ++ dir | not (null libs), dir <- ordNub (libraryDirs info)]+    ++ ["-l" ++ lib | lib <- libs]+  where+    libs = extraLibraries info  -- | Convert an absolute path under GHC's libdir, the cabal store or one of the -- 'externalDirs' into one relative to @third-party\/haskell@, via whichever
src/Distribution/Client/Buck2/Setup.hs view
@@ -66,10 +66,10 @@ -- | Copy @.buckconfig@ and @PACKAGE@ if they don't exist ensureBuckconfigAndPackage :: Verbosity -> FilePath -> IO () ensureBuckconfigAndPackage verbosity projectRoot = do-  copyIfMissing verbosity (exampleDir </> ".buckconfig") (projectRoot </> ".buckconfig")-  copyIfMissing verbosity (exampleDir </> "PACKAGE") (projectRoot </> "PACKAGE")+  copyIfMissing verbosity (templateDir </> ".buckconfig") (projectRoot </> ".buckconfig")+  copyIfMissing verbosity (templateDir </> "PACKAGE") (projectRoot </> "PACKAGE")   where-    exampleDir = projectRoot </> "buck2" </> "example"+    templateDir = projectRoot </> "buck2" </> "template"  copyIfMissing :: Verbosity -> FilePath -> FilePath -> IO () copyIfMissing verbosity src dest = do
src/Distribution/Client/Buck2/Spec.hs view
@@ -27,6 +27,10 @@   -- ^ The package's @data-dir@, relative to its directory.   , specDataFiles :: [FilePath]   -- ^ Its @data-files@, as patterns, relative to 'specDataDir'.+  , specExtraSourceFiles :: [FilePath]+  -- ^ Its @extra-source-files@, as patterns, relative to its directory:+  -- what its build needs, other than its sources, which something+  -- elsewhere in the project may need too (a generator, say).   , specComponents :: [SpecComponent]   } @@ -53,6 +57,8 @@   -- ^ The main module's source; not for a library.   , scSrcs :: [(String, Src)]   -- ^ Every other module (by module name) and its source.+  , scBootSrcs :: [(String, FilePath)]+  -- ^ The @.hs-boot@ file of each module that has one, next to its source.   , scTestArgs :: [String]   -- ^ The project's @test-options@ for a test-suite, with template variables   -- expanded.@@ -61,6 +67,13 @@   , scLanguage :: Maybe String   , scExtensions :: [String]   , scExtraLibraries :: [String]+  , scLdOptions :: [String]+  -- ^ The @ld-options@, as configured: so including the other linker flags of+  -- the @pkgconfig-depends@, such as an rpath.+  , scExtraLibDirs :: [FilePath]+  -- ^ Where to look for the 'scExtraLibraries': the component's+  -- @extra-lib-dirs@, as configured, so including the directories of its+  -- @pkgconfig-depends@ (Cabal adds those at configure time).   , scDeps :: [SpecDep]   , scReexports :: [SpecReexport]   -- ^ Modules a library re-exports from the library of another package (or@@ -87,8 +100,10 @@ -- | A source file of a component: either a real file in the package -- (relative to its directory), or one generated into the package's -- @cabal-buck2\/autogen@ directory, named by its @export_file()@ entry there--- (see 'Distribution.Client.Buck2.Generate.AutogenFile').-data Src = SrcFile FilePath | SrcAutogen String+-- (see 'Distribution.Client.Buck2.Generate.AutogenFile'), or a module that+-- the package's @Setup.hs@ would have generated, which the project must+-- provide (@--enable-custom-setup@).+data Src = SrcFile FilePath | SrcAutogen String | SrcProvided  -- | A library a component depends on. data SpecDep = SpecDep
src/Distribution/Client/Buck2/Write.hs view
@@ -75,7 +75,7 @@   traverse_ (writeOnePackage verbosity projectRoot) results   where     generate skipped pkg srcs =-      generatePackageTargets localIndex projectRoot componentLBIs externalBuildTools projectTestOptions srcs skipped (bpInProject pkg) (bpDescription pkg)+      generatePackageTargets localIndex projectRoot componentLBIs externalBuildTools projectTestOptions srcs skipped (bpInProject pkg) (bpCustomSetup pkg) (bpDescription pkg)      librariesWithoutRule pkg (targets, _) =       [ (packageName desc, libName lib)@@ -98,22 +98,32 @@ -- loads it to find the targets of the packages that a package depends on, and -- the paths of its own directory. Nothing in a package's @BUCK.cabal.bzl@ is -- relative to the project, so only this file changes when a package moves.+--+-- It also passes on the project's own customisation of the generated+-- targets: the @OVERRIDES@ of a @cabal-buck2.bzl@ in the project root, if+-- there is one (see @buck2\/cabal.bzl@). writePackagesFile :: Verbosity -> FilePath -> [BuiltPackage] -> IO () writePackagesFile verbosity projectRoot pkgs = do   createDirectoryIfMissing True (takeDirectory path)-  writeFile path contents+  hasOverrides <- doesFileExist (projectRoot </> "cabal-buck2.bzl")+  writeFile path (contents hasOverrides)   notice verbosity $ "cabal buck2: generated cabal-buck2" </> "packages.bzl" ++ " (" ++ show (length pkgs) ++ " package(s))"   where     path = projectRoot </> "cabal-buck2" </> "packages.bzl"-    contents =+    contents hasOverrides =       unlines-        [ "# @generated by `cabal buck2` - do not edit by hand."-        , "# Re-run `cabal buck2` after adding, removing or moving a package."-        , "#"-        , "# The directory of each package that this project builds, from the root of"-        , "# the project. See buck2/cabal.bzl."-        , ""-        ]+        ( [ "# @generated by `cabal buck2` - do not edit by hand."+          , "# Re-run `cabal buck2` after adding, removing or moving a package, or"+          , "# adding or removing cabal-buck2.bzl."+          , "#"+          , "# The directory of each package that this project builds, from the root of"+          , "# the project, and the project's overrides of the generated targets. See"+          , "# buck2/cabal.bzl."+          , ""+          ]+            ++ ["load(\"//:cabal-buck2.bzl\", _OVERRIDES = \"OVERRIDES\")" | hasOverrides]+            ++ ["", "OVERRIDES = " ++ (if hasOverrides then "_OVERRIDES" else "{}"), ""]+        )         ++ renderBinding "PACKAGES" (VDict (Map.toList packages))     packages =       Map.fromList@@ -204,6 +214,7 @@       ++ [ ("data", VDict [("dir", str (specDataDir spec)), ("files", strList (specDataFiles spec))])          | not (null (specDataFiles spec))          ]+      ++ listField "extra_source_files" (specExtraSourceFiles spec)       ++ [("components", VList (map componentValue (specComponents spec)))]  componentValue :: SpecComponent -> Value@@ -213,12 +224,15 @@       ++ [("exe_name", str exe) | Just exe <- [scExeName c]]       ++ [("main_is", srcValue src) | Just src <- [scMainIs c]]       ++ [("srcs", VDict [(m, srcValue src) | (m, src) <- scSrcs c]) | not (null (scSrcs c))]+      ++ [("boot_srcs", VDict [(m, str boot) | (m, boot) <- scBootSrcs c]) | not (null (scBootSrcs c))]       ++ listField "test_args" (scTestArgs c)       ++ listField "ghc_options" (scGhcOptions c)       ++ listField "cpp_options" (scCppOptions c)       ++ [("language", str lang) | Just lang <- [scLanguage c]]       ++ listField "extensions" (scExtensions c)       ++ listField "extra_libraries" (scExtraLibraries c)+      ++ listField "extra_lib_dirs" (scExtraLibDirs c)+      ++ listField "ld_options" (scLdOptions c)       ++ valuesField "deps" (map depValue (scDeps c))       ++ valuesField "reexports" (map reexportValue (scReexports c))       ++ valuesField "build_tools" (map buildToolValue (scBuildTools c))@@ -237,6 +251,7 @@ srcValue :: Src -> Value srcValue (SrcFile path) = str path srcValue (SrcAutogen name) = VDict [("autogen", str name)]+srcValue SrcProvided = VDict [("provided", VBool True)]  depValue :: SpecDep -> Value depValue d =
src/Distribution/Client/CmdBuck2.hs view
@@ -36,6 +36,8 @@ import Distribution.Client.Compat.Prelude import Prelude () +import qualified Data.Set as Set+ import Distribution.Client.DistDirLayout (DistDirLayout (distProjectRootDirectory)) import Distribution.Client.NixStyleOptions   ( NixStyleFlags (..)@@ -70,9 +72,10 @@ import Distribution.Client.Buck2.BuildDependencies (buildDependencies) import Distribution.Client.Buck2.Cache (cacheSetting, configureCache) import Distribution.Client.Buck2.Configure (configureComponents)-import Distribution.Client.Buck2.Flags (Buck2Flags, buck2FlagOptions, defaultBuck2Flags, dependencyMode)+import Distribution.Client.Buck2.Flags (Buck2Flags (buck2CustomSetup), buck2FlagOptions, defaultBuck2Flags, dependencyMode) import Distribution.Client.Buck2.LocalPackages   ( builtLocalPackages+  , translateCustomSetups   , localBuildTools   , prebuiltUnits   , localToolTargets@@ -144,12 +147,17 @@       let projectRoot = distProjectRootDirectory (distDirLayout baseCtx)       checkBuck2Prelude verbosity projectRoot -      buildCtx <- buildDependencies verbosity mode baseCtx targetSelectors+      builtCtx <- buildDependencies verbosity mode baseCtx targetSelectors+      (plan, customSetups) <-+        if fromFlagOrDefault False (buck2CustomSetup (extraFlags flags))+          then translateCustomSetups verbosity mode (distDirLayout baseCtx) (elaboratedPlanOriginal builtCtx)+          else return (elaboratedPlanOriginal builtCtx, Set.empty)+      let buildCtx = builtCtx{elaboratedPlanOriginal = plan}        ensureBuckconfigAndPackage verbosity projectRoot       configureCache verbosity projectRoot cache -      localPkgs <- builtLocalPackages verbosity mode (distDirLayout baseCtx) (elaboratedPlanOriginal buildCtx)+      localPkgs <- builtLocalPackages verbosity mode (distDirLayout baseCtx) customSetups (elaboratedPlanOriginal buildCtx)        (externalBuildTools, resolvedDeps) <-         generatePrebuilt
test/Main.hs view
@@ -29,8 +29,9 @@  import Distribution.Client.Buck2.Cache (cacheBlock, spliceBlock) import Distribution.Client.Buck2.Fingerprint (ccFingerprintOf, fingerprintOf)-import Distribution.Client.Buck2.Prebuilt (RepoPaths (..), externalDirs, toRepoRelative)+import Distribution.Client.Buck2.Prebuilt (RepoPaths (..), externalDirs, prebuiltLinkerFlags, toRepoRelative) import Distribution.Client.Buck2.Version (cabalBuck2Version)+import Distribution.InstalledPackageInfo (InstalledPackageInfo (..), emptyInstalledPackageInfo)  main :: IO () main = do@@ -52,7 +53,7 @@     exitFailure  unitTests :: [(String, IO ())]-unitTests = [("fingerprint", fingerprint), ("cc-fingerprint", ccFingerprint), ("splice-block", spliceBlockTest), ("external-dirs", externalDirsTest)]+unitTests = [("fingerprint", fingerprint), ("cc-fingerprint", ccFingerprint), ("splice-block", spliceBlockTest), ("external-dirs", externalDirsTest), ("linker-flags", linkerFlagsTest)]  runUnitTest :: (String, IO ()) -> IO Bool runUnitTest (name, test) = do@@ -73,8 +74,31 @@   , ("custom-setup", customSetup)   , ("reexports", reexports)   , ("buck2-version", buck2Version)+  , ("project-overrides", projectOverrides)+  , ("pkgconfig", pkgconfig)+  , ("project-overrides", projectOverrides)+  , ("same-name", sameName)   ] +-- | A library and an executable with the same name in one package, and+-- another package that needs that executable as a build tool.+sameName :: Project -> IO ()+sameName project = do+  _ <- buck2 project []++  -- The executable can't have the library's target name, so it gets a+  -- suffix - and a build-tool-depends on it from another package has to+  -- name it the same way, or buck2 won't find the target.+  toolBzl <- readIn project ("tool" </> "BUCK.cabal.bzl")+  let tool = assertContains "tool/BUCK.cabal.bzl"+  tool "'kind': 'library'" toolBzl+  tool "'name': 'tool'" toolBzl+  tool "'kind': 'executable'" toolBzl+  tool "'name': 'tool-exe'" toolBzl+  userBzl <- readIn project ("user" </> "BUCK.cabal.bzl")+  assertContains "user/BUCK.cabal.bzl" "'exe': 'tool-exe'" userBzl+  assertContains "user/BUCK.cabal.bzl" "'package': 'tool'" userBzl+ -- | A copy of a fixture project, and how to run @cabal-buck2@ in it. data Project = Project   { projectDir :: FilePath@@ -100,6 +124,7 @@       "disabled-stanzas" -> "basic"       "cache-config" -> "basic"       "buck2-version" -> "basic"+      "project-overrides" -> "basic"       _ -> name     setup dir = do       cleanup dir@@ -114,9 +139,11 @@       -- config (which $CABAL_DIR and $CABAL_CONFIG may point to, as in       -- haskell-ci) are neither used nor changed.       let cabalDir = dir </> "cabal-dir"+          -- A fixture can have pkg-config files of its own, in pkgconfig/.+          pkgConfigPath = dir </> "project" </> "pkgconfig" ++ maybe "" (':' :) (lookup "PKG_CONFIG_PATH" env)           cabalEnv =-            [("CABAL_DIR", cabalDir), ("CABAL_CONFIG", cabalDir </> "config")]-              ++ [kv | kv@(k, _) <- env, k `notElem` ["CABAL_DIR", "CABAL_CONFIG"]]+            [("CABAL_DIR", cabalDir), ("CABAL_CONFIG", cabalDir </> "config"), ("PKG_CONFIG_PATH", pkgConfigPath)]+              ++ [kv | kv@(k, _) <- env, k `notElem` ["CABAL_DIR", "CABAL_CONFIG", "PKG_CONFIG_PATH"]]           run args = do             (code, out, err) <-               readCreateProcessWithExitCode@@ -270,6 +297,14 @@   lib "local_build_spec" libBzl   lib "'kind': 'library'" libBzl   lib "'name': 'lib-pkg'" libBzl+  -- extra-source-files reach the spec as they are (patterns), for+  -- cabal.bzl to glob.+  lib "'extra_source_files': [\n        'include/*.h',\n    ]" libBzl+  -- extra-lib-dirs, as configured (so with the directories of any+  -- pkgconfig-depends), go in the spec for the link.+  lib "'extra_lib_dirs': [\n                'libs',\n            ]" libBzl+  -- A module's boot file is found next to its source.+  lib "'boot_srcs': {\n                'MyLib': 'src/MyLib.hs-boot',\n            }" libBzl   noLib "haskell_library(" libBzl   -- Project-level options and test options are only recorded where they   -- apply.@@ -447,6 +482,25 @@   assertContains "user/BUCK.cabal.bzl" "'package': 're-lib'" userBzl   assertNotContains "user/BUCK.cabal.bzl" "base-lib" userBzl +-- | What Cabal's configure makes of @pkgconfig-depends@ and @extra-lib-dirs@ is+-- in the spec as it is, for the link: also for a component that has no C+-- sources, which buck2 doesn't run pkg-config for. The fixture has a+-- @foo.pc@ with its own library and include directories, a define and an+-- rpath.+pkgconfig :: Project -> IO ()+pkgconfig project = do+  _ <- buck2 project []+  bzl <- readIn project ("lib" </> "BUCK.cabal.bzl")+  let spec = assertContains "lib/BUCK.cabal.bzl"+  spec "'extra_libraries': [\n                'foo',\n            ]" bzl+  -- The directory of the package's own extra-lib-dirs and then that of pkg-config.+  spec "'extra_lib_dirs': [\n                'plain',\n                '/opt/foo/lib',\n            ]" bzl+  spec "'ld_options': [\n                '-Wl,-rpath,/opt/foo/lib',\n            ]" bzl+  spec "'include_dirs': [\n                '/opt/foo/include',\n            ]" bzl+  spec "'cc_options': [\n                '-DFOO_ENABLED',\n            ]" bzl+  -- and for buck2 to run pkg-config for the C sources there are.+  spec "'pkgconfig': [\n                'foo',\n            ]" bzl+ -- | The checkout of haskell-buck2 has to be for this release of cabal-buck2: -- if it is not, or doesn't say, the error says which branch is needed. buck2Version :: Project -> IO ()@@ -486,6 +540,33 @@   depBzl <- readIn project ("dist-newstyle" </> "src" </> "custom-dep-0.1" </> "BUCK.cabal.bzl")   assertNotContains "custom-dep BUCK.cabal.bzl" "'kind': 'library'" depBzl +  -- With --enable-custom-setup it is built as if it had build-type: Simple,+  -- and the module its Setup.hs would generate is left to the project.+  translated <- buck2 project ["--source-deps", "--enable-custom-setup"]+  assertContains "warning" "custom-dep-0.1 as if it had build-type: Simple" translated+  assertNotContains "output" "skipping" translated+  translatedBzl <- readIn project ("dist-newstyle" </> "src" </> "custom-dep-0.1" </> "BUCK.cabal.bzl")+  assertContains "custom-dep BUCK.cabal.bzl" "'kind': 'library'" translatedBzl+  assertContains "custom-dep BUCK.cabal.bzl" "'Custom.Generated': {\n                    'provided': True," translatedBzl+  appBzl <- readIn project ("app" </> "BUCK.cabal.bzl")+  assertContains "app BUCK.cabal.bzl" "'kind': 'executable'" appBzl++-- | A project's @cabal-buck2.bzl@, with its overrides of the generated+-- targets, is loaded by @packages.bzl@, and an empty set of overrides is+-- given there if there is none.+projectOverrides :: Project -> IO ()+projectOverrides project = do+  _ <- buck2 project []+  without <- readIn project ("cabal-buck2" </> "packages.bzl")+  assertContains "packages.bzl" "OVERRIDES = {}" without+  assertNotContains "packages.bzl" "cabal-buck2.bzl\"" without++  writeFile (projectDir project </> "cabal-buck2.bzl") "OVERRIDES = {}\n"+  _ <- buck2 project []+  with <- readIn project ("cabal-buck2" </> "packages.bzl")+  assertContains "packages.bzl" "load(\"//:cabal-buck2.bzl\", _OVERRIDES = \"OVERRIDES\")" with+  assertContains "packages.bzl" "OVERRIDES = _OVERRIDES" with+ -- | @--cache=ADDRESS@ adds the cache's settings to @.buckconfig@, which are -- kept by later runs without the flag, and @--no-cache@ removes. cacheConfig :: Project -> IO ()@@ -597,3 +678,23 @@   check "a library under GHC's libdir" (Just "ghc-9.6.7/x86_64-linux-ghc-9.6.7/base-4.18.3.0/libHSbase.a") (toRepoRelative paths' "/ghc/lib/x86_64-linux-ghc-9.6.7/base-4.18.3.0/libHSbase.a")   check "a library in the store" (Just "cabal-store/foo-1/lib/libHSfoo.a") (toRepoRelative paths' "/home/u/.cabal/store/ghc-9.6.7/foo-1/lib/libHSfoo.a")   check "something that isn't linked" Nothing (toRepoRelative paths' "/usr/include/stdio.h")++-- | The @-L@ flags for a prebuilt package's @extra-libraries@ come from its+-- @library-dirs@, as they do when GHC links against the package itself; a+-- package without any needs no @-L@ flags at all.+linkerFlagsTest :: IO ()+linkerFlagsTest = do+  let withLibs =+        emptyInstalledPackageInfo+          { libraryDirs = ["/nix/store/aaa-hmatrix-0.20.2/lib/x86_64-linux-ghc-9.6.7/hmatrix-0.20.2-X", "/nix/store/bbb-openblas-0.3.33/lib", "/nix/store/bbb-openblas-0.3.33/lib"]+          , extraLibraries = ["openblas"]+          }+      withoutLibs = emptyInstalledPackageInfo{libraryDirs = ["/nix/store/ccc-text-2.1.4/lib"]}+      check what expected actual =+        unless (expected == actual) $+          failure (what ++ ": expected " ++ show expected ++ ", got " ++ show actual)+  check+    "a package with extra-libraries"+    ["-L/nix/store/aaa-hmatrix-0.20.2/lib/x86_64-linux-ghc-9.6.7/hmatrix-0.20.2-X", "-L/nix/store/bbb-openblas-0.3.33/lib", "-lopenblas"]+    (prebuiltLinkerFlags withLibs)+  check "a package without" [] (prebuiltLinkerFlags withoutLibs)
+ test/fixtures/basic/lib-pkg/include/lib-pkg.h view
@@ -0,0 +1,1 @@+/* For the test of extra-source-files. */
test/fixtures/basic/lib-pkg/lib-pkg.cabal view
@@ -3,8 +3,13 @@ version:             0.1.0.0 build-type:          Simple +extra-source-files: include/*.h+ library   exposed-modules:   MyLib   hs-source-dirs:    src   build-depends:     base+  -- Where the linker looks for extra-libraries (none here); relative to the+  -- package, like include-dirs.+  extra-lib-dirs:    libs   default-language:  Haskell2010
+ test/fixtures/basic/lib-pkg/libs/.gitkeep view
+ test/fixtures/basic/lib-pkg/src/MyLib.hs-boot view
@@ -0,0 +1,3 @@+module MyLib (myLib) where++myLib :: String
test/fixtures/custom-setup/dep/custom-dep-0.1/custom-dep.cabal view
@@ -7,6 +7,8 @@   setup-depends: base, Cabal  library-  exposed-modules:  Custom.Dep+  exposed-modules:  Custom.Dep, Custom.Generated+  -- What a real Setup.hs would generate.+  autogen-modules:  Custom.Generated   build-depends:    base   default-language: Haskell2010
+ test/fixtures/pkgconfig/.buckconfig view
@@ -0,0 +1,4 @@+# Placeholder: this test only checks `cabal buck2`'s generated files, it+# never actually invokes a real buck2 binary, so this doesn't need to be+# a functional buck2 config - it only needs to exist so that+# `ensureBuckconfigAndPackage` sees it's already there and leaves it alone.
+ test/fixtures/pkgconfig/PACKAGE view
@@ -0,0 +1,1 @@+# Placeholder - see .buckconfig.
+ test/fixtures/pkgconfig/buck2/.gitkeep view
+ test/fixtures/pkgconfig/cabal.project view
@@ -0,0 +1,3 @@+packages: lib++active-repositories: :none
+ test/fixtures/pkgconfig/lib/L.hs view
@@ -0,0 +1,1 @@+module L where
+ test/fixtures/pkgconfig/lib/lib.cabal view
@@ -0,0 +1,12 @@+cabal-version:     3.0+name:              lib+version:           0.1+build-type:        Simple++-- No C sources, so only what Cabal made of these is in the spec.+library+  exposed-modules:   L+  build-depends:     base+  pkgconfig-depends: foo+  extra-lib-dirs:    plain+  default-language:  Haskell2010
+ test/fixtures/pkgconfig/lib/plain/.gitkeep view
+ test/fixtures/pkgconfig/pkgconfig/foo.pc view
@@ -0,0 +1,6 @@+prefix=/opt/foo+Name: foo+Description: A library that isn't there: only what pkg-config says about it matters+Version: 1.2.3+Cflags: -I/opt/foo/include -DFOO_ENABLED+Libs: -L/opt/foo/lib -lfoo -Wl,-rpath,/opt/foo/lib
+ test/fixtures/same-name/.buckconfig view
@@ -0,0 +1,4 @@+# Placeholder: this test only checks `cabal buck2`'s generated files, it+# never actually invokes a real buck2 binary, so this doesn't need to be+# a functional buck2 config - it only needs to exist so that+# `ensureBuckconfigAndPackage` sees it's already there and leaves it alone.
+ test/fixtures/same-name/PACKAGE view
@@ -0,0 +1,1 @@+# Placeholder - see .buckconfig.
+ test/fixtures/same-name/buck2/.gitkeep view
+ test/fixtures/same-name/cabal.project view
@@ -0,0 +1,3 @@+packages: tool user++active-repositories: :none
+ test/fixtures/same-name/tool/app/Main.hs view
@@ -0,0 +1,6 @@+module Main (main) where++import Tool (greeting)++main :: IO ()+main = putStrLn greeting
+ test/fixtures/same-name/tool/src/Tool.hs view
@@ -0,0 +1,4 @@+module Tool (greeting) where++greeting :: String+greeting = "hello"
+ test/fixtures/same-name/tool/tool.cabal view
@@ -0,0 +1,19 @@+cabal-version:      2.4+name:               tool+version:            0.1.0.0+build-type:         Simple++-- A library and an executable with the package's own name: a common layout+-- (the executable is a thin wrapper around the library), but a buck2 target+-- name has to be unique within its package.+library+  exposed-modules:   Tool+  hs-source-dirs:    src+  build-depends:     base+  default-language:  Haskell2010++executable tool+  main-is:           Main.hs+  hs-source-dirs:    app+  build-depends:     base, tool+  default-language:  Haskell2010
+ test/fixtures/same-name/user/src/User.hs view
@@ -0,0 +1,6 @@+module User (user) where++import Tool (greeting)++user :: String+user = greeting ++ " from user"
+ test/fixtures/same-name/user/user.cabal view
@@ -0,0 +1,13 @@+cabal-version:      2.4+name:               user+version:            0.1.0.0+build-type:         Simple++-- Needs the other package's executable on PATH when it builds, under the+-- name Cabal knows it by.+library+  exposed-modules:   User+  hs-source-dirs:    src+  build-depends:     base, tool+  build-tool-depends: tool:tool+  default-language:  Haskell2010