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 +31/−0
- cabal-buck2.cabal +4/−1
- changelog.md +21/−0
- src/Distribution/Client/Buck2/Flags.hs +9/−1
- src/Distribution/Client/Buck2/Generate.hs +59/−17
- src/Distribution/Client/Buck2/LocalPackages.hs +47/−5
- src/Distribution/Client/Buck2/Prebuilt.hs +16/−1
- src/Distribution/Client/Buck2/Setup.hs +3/−3
- src/Distribution/Client/Buck2/Spec.hs +17/−2
- src/Distribution/Client/Buck2/Write.hs +25/−10
- src/Distribution/Client/CmdBuck2.hs +11/−3
- test/Main.hs +105/−4
- test/fixtures/basic/lib-pkg/include/lib-pkg.h +1/−0
- test/fixtures/basic/lib-pkg/lib-pkg.cabal +5/−0
- test/fixtures/basic/lib-pkg/libs/.gitkeep +0/−0
- test/fixtures/basic/lib-pkg/src/MyLib.hs-boot +3/−0
- test/fixtures/custom-setup/dep/custom-dep-0.1/custom-dep.cabal +3/−1
- test/fixtures/pkgconfig/.buckconfig +4/−0
- test/fixtures/pkgconfig/PACKAGE +1/−0
- test/fixtures/pkgconfig/buck2/.gitkeep +0/−0
- test/fixtures/pkgconfig/cabal.project +3/−0
- test/fixtures/pkgconfig/lib/L.hs +1/−0
- test/fixtures/pkgconfig/lib/lib.cabal +12/−0
- test/fixtures/pkgconfig/lib/plain/.gitkeep +0/−0
- test/fixtures/pkgconfig/pkgconfig/foo.pc +6/−0
- test/fixtures/same-name/.buckconfig +4/−0
- test/fixtures/same-name/PACKAGE +1/−0
- test/fixtures/same-name/buck2/.gitkeep +0/−0
- test/fixtures/same-name/cabal.project +3/−0
- test/fixtures/same-name/tool/app/Main.hs +6/−0
- test/fixtures/same-name/tool/src/Tool.hs +4/−0
- test/fixtures/same-name/tool/tool.cabal +19/−0
- test/fixtures/same-name/user/src/User.hs +6/−0
- test/fixtures/same-name/user/user.cabal +13/−0
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