diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,10 @@
+# 0.4.11 (2024-02-18)
+- ProvReqs: new module for rpmspec dependency functions
+- ProvReqs: generate pkgconfig and cmake provides from %files (#4)
+- Graph depsGraph: include package set in potential deps
+- Order: add dependencyLayersRpmOpts
+- more tests
+
 # 0.4.10 (2022-10-28)
 - Graph: add depsGraphDeps which takes a list of possible deps
 - Graph: add topsortGraph (factored out of sortGraph)
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -11,13 +11,16 @@
 
 ## Usage
 
+`$ rpmbuild-order --version`
 ```
-$ rpmbuild-order --version
-0.4.10
-$ rpmbuild-order --help
+0.4.11
+```
+`$ rpmbuild-order --help`
+```
 Order packages by build dependencies
 
 Usage: rpmbuild-order [--version] COMMAND
+
   Sort package sources (spec files) in build dependency order
 
 Available options:
@@ -33,7 +36,9 @@
   leaves                   List of the top leaves of package graph
   roots                    List lowest root packages
   render                   Show graph with graphviz
+```
 
+```
 $ rpmbuild-order sort mycore mylib myapp
 mylib mycore myapp
 ```
@@ -48,7 +53,9 @@
 dependencies and reverse dependencies of a package can be obtained
 within the current set of checked out package sources.
 ie If you have a directory with packages:
-`pkg1/ pkg2/ lib1/ lib2/ lib3/ misc1/`
+```
+pkg1/ pkg2/ lib1/ lib2/ lib3/ misc1/
+```
 then the output of `rpmbuild-order deps pkg1` might be `lib1 lib3 pkg1`
 for example.
 
@@ -68,6 +75,8 @@
 Please see their documentation for more details.
 
 ## Notes and known problems
+0. Handles pkgconfig() provides by grepping .spec for .pc files
+
 1. Given packages A, B, C, where C depends on B, and B depends on A,
 and you call
 
diff --git a/rpmbuild-order.1 b/rpmbuild-order.1
--- a/rpmbuild-order.1
+++ b/rpmbuild-order.1
@@ -1,7 +1,7 @@
-.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.49.2.
-.TH RPMBUILD-ORDER "1" "August 2022" "rpmbuild-order 0.4.9" "User Commands"
+.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.49.3.
+.TH RPMBUILD-ORDER "1" "February 2024" "rpmbuild-order 0.4.11" "User Commands"
 .SH NAME
-rpmbuild-order \- manual page for rpmbuild-order 0.4.9
+rpmbuild-order \- manual page for rpmbuild-order 0.4.11
 .SH SYNOPSIS
 .B rpmbuild-order
 [\fI\,--version\/\fR] \fI\,COMMAND\/\fR
diff --git a/rpmbuild-order.cabal b/rpmbuild-order.cabal
--- a/rpmbuild-order.cabal
+++ b/rpmbuild-order.cabal
@@ -1,12 +1,12 @@
 Name:             rpmbuild-order
-Version:          0.4.10
+Version:          0.4.11
 License:          BSD3
 License-File:     LICENSE
 Author:           Jens Petersen <petersen@redhat.com>,
                   Henning Thielemann <haskell@henning-thielemann.de>
 Maintainer:       Jens Petersen <petersen@redhat.com>
 Copyright:        2010-2018  Henning Thielemann,
-                  2018-2022 Jens Petersen <petersen@redhat.com>
+                  2018-2024 Jens Petersen <petersen@redhat.com>
 Category:         Distribution
 Homepage:         https://github.com/juhp/rpmbuild-order
 Bug-reports:      https://github.com/juhp/rpmbuild-order/issues
@@ -24,9 +24,9 @@
   which can affect dependencies. It can also output dependency graphs.
 
   Since version 0.4, a library API is provided.
-Tested-with:       GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2,
-                   GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.4,
-                   GHC == 8.10.7, GHC == 9.0.2
+Tested-with:       GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5,
+                   GHC == 8.8.4, GHC == 8.10.7, GHC == 9.0.2, GHC == 9.2.8,
+                   GHC == 9.4.8, GHC == 9.6.4, GHC == 9.8.1
 Cabal-Version:     1.18
 Build-Type:        Simple
 Extra-doc-files:    README.md TODO ChangeLog.md
@@ -35,7 +35,11 @@
                     test/pkgs/B/B.spec
                     test/pkgs/C/C.spec
                     test/pkgs/D1.0/D1.0.spec
+                    test/pkgs/cmake/A/A.spec
+                    test/pkgs/cmake/B/B.spec
                     test/pkgs/dynbr/A/A.spec
+                    test/pkgs/pkgconf/A/A.spec
+                    test/pkgs/pkgconf/C/C.spec
 
 source-repository head
   type:     git
@@ -45,7 +49,6 @@
   Build-Depends: base < 5,
                  extra,
                  fgl,
-                 optparse-applicative,
                  rpmbuild-order,
                  simple-cmd-args
   Main-Is:          src/Main.hs
@@ -69,6 +72,7 @@
 Library
   Exposed-Modules:  Distribution.RPM.Build.Graph
                     Distribution.RPM.Build.Order
+                    Distribution.RPM.Build.ProvReqs
   Build-Depends: base < 5,
                  case-insensitive,
                  directory >= 1.2.5,
@@ -76,6 +80,7 @@
                  filepath,
                  fgl >= 5.5.4,
                  graphviz,
+                 regex-tdfa,
                  simple-cmd >= 0.2.3
   HS-Source-Dirs:      src
   default-language:    Haskell2010
diff --git a/src/Distribution/RPM/Build/Graph.hs b/src/Distribution/RPM/Build/Graph.hs
--- a/src/Distribution/RPM/Build/Graph.hs
+++ b/src/Distribution/RPM/Build/Graph.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE CPP #-}
-{-# LANGUAGE OverloadedStrings #-}
 
 {-|
 This module provides simple dependency graph making for rpm packages:
@@ -38,7 +37,6 @@
    topsortGraph,
   ) where
 
-import qualified Data.CaseInsensitive as CI
 import Data.Graph.Inductive.Query.DFS (components, scc, topsort', xdfsWith)
 import Data.Graph.Inductive.Query.SP (sp)
 import Data.Graph.Inductive.PatriciaTree (Gr)
@@ -53,13 +51,11 @@
 import Data.GraphViz
 import SimpleCmd
 import System.Directory (doesDirectoryExist, doesFileExist,
-                         getCurrentDirectory, withCurrentDirectory,
-                         listDirectory
-                        )
-import System.Exit (exitFailure)
+                         withCurrentDirectory, listDirectory)
 import System.FilePath
-import System.IO.Extra (withTempDir)
 
+import Distribution.RPM.Build.ProvReqs (rpmspecProvidesBuildRequires)
+
 data SourcePackage =
   SourcePackage {
     packagePath :: FilePath,
@@ -220,31 +216,7 @@
         Just (dir,spec) -> do
           when verbose $ warning spec
           withCurrentDirectory dir $ do
-            dynbr <- egrep_ "^\\(%generate_buildrequires\\|%gometa\\)" spec
-            mprovbrs <-
-              if dynbr
-              then do
-                brs <- rpmspecDynBuildRequires spec
-                provs <- do
-                  dynprovs <-
-                    if "golang-" `isPrefixOf` takeBaseName spec
-                    then do
-                      macro <- grep "%global goipath" spec
-                      return $
-                        case macro of
-                          [def] -> ["golang(" ++ last (words def) ++ ")"]
-                          _ -> error' $ "failed to find %goipath in " ++ spec
-                    else return []
-                  prs <- rpmspecProvides spec
-                  return $ dynprovs ++ prs
-                return $ Just (provs,brs)
-              else do
-                mcontent <- rpmspecParse spec
-                return $ case mcontent of
-                           Nothing -> Nothing
-                           Just content ->
-                             let pkg = takeBaseName spec
-                             in Just $ extractMetadata pkg ([],[]) $ lines content
+            mprovbrs <- rpmspecProvidesBuildRequires lenient rpmopts spec
             case mprovbrs of
               Nothing -> return Nothing
               Just (provs,brs) -> do
@@ -252,10 +224,10 @@
                 let provs' = filter (not . ("(x86-64)" `isSuffixOf`)) provs
                 when verbose $ do
                   warning $ show $ sort provs'
-                  warning $ show $ mapMaybe simplifyDep $ sort brs
+                  warning $ show $ sort brs
                 return $ Just (path,
                                nub provs',
-                               nub (mapMaybe simplifyDep brs) \\ ignoredBRs)
+                               nub brs \\ ignoredBRs)
       where
         -- (dir,specfile)
         findSpec :: IO (Maybe (FilePath,FilePath))
@@ -295,27 +267,6 @@
                             then Nothing
                             else error' $ f ++ " not found"
 
-        extractMetadata :: FilePath -> ([String],[String]) -> [String] -> ([String],[String])
-        extractMetadata _ acc [] = acc
-        extractMetadata pkg acc@(provs,brs) (l:ls) =
-          let ws = words l in
-            if length ws < 2 then extractMetadata pkg acc ls
-            else case CI.mk (head ws) of
-              "BuildRequires:" ->
-                let br = (head . tail) ws
-                    brs' = if br `elem` ignoredBRs then brs else br:brs
-                in extractMetadata pkg (provs, brs') ls
-              "Name:" -> extractMetadata pkg ((head . tail) ws : provs, brs) ls
-              "Provides:" -> extractMetadata pkg ((head . tail) ws : provs, brs) ls
-              "%package" ->
-                let subpkg =
-                      let sub = last ws in
-                        if length ws == 2
-                        then pkg ++ '-' : sub
-                        else sub
-                in extractMetadata pkg (subpkg : provs, brs) ls
-              _ -> extractMetadata pkg acc ls
-
     getBuildGraph :: [SourcePackage] -> PackageGraph
     getBuildGraph srcPkgs =
        let nodes = zip [0..] srcPkgs
@@ -375,50 +326,6 @@
        map (fromMaybe (error "node not found in graph") .
             G.lab graph)
 
-    rpmspecParse :: FilePath -> IO (Maybe String)
-    rpmspecParse spec = do
-      (ok, out, err) <- cmdFull "rpmspec" (["-P", "--define", "ghc_version any"] ++ rpmopts ++ [spec]) ""
-      unless (null err) $ warning $ spec +-+ err
-      if ok
-        then return $ Just out
-        else if lenient then return Nothing else exitFailure
-
-    rpmspecProvides :: FilePath -> IO [String]
-    rpmspecProvides spec = do
-      (ok, out, err) <- cmdFull "rpmspec" (["--define", "ghc_version any", "-q", "--provides"] ++ rpmopts ++ [spec]) ""
-      unless (null err) $ warning err
-      if ok
-        then return $ map (head . words) $ lines out
-        else if lenient then return [] else exitFailure
-
-    rpmspecDynBuildRequires :: FilePath -> IO [String]
-    rpmspecDynBuildRequires spec = do
-      cwd <- getCurrentDirectory
-      withTempDir $ \tmpdir -> do
-        (out,err) <- cmdStdErr "rpmbuild" ["-br", "--nodeps", "--define", "_srcrpmdir " ++ tmpdir, cwd </> spec]
-        unless (null err) $ when verbose $ warning err
-        -- Wrote: /current/dir/SRPMS/name-version-release.buildreqs.nosrc.rpm
-        case words out of
-          [] -> error' $ spec +-+ "could not generate source rpm for dynamic buildrequires"
-          ws -> cmdLines "rpm" ["-qp", "--requires", last ws]
-
-    simplifyDep br =
-      case (head . words) br of
-        '(':dep -> simplifyDep dep
-        dep -> case splitOn "(" (dropSuffix ")" dep) of
-          ("rpmlib":_) -> Nothing
-          ("crate":[crate]) -> Just $ "rust-" ++ replace "/" "+" crate ++ "-devel"
-          ("rubygem":[gem]) -> Just $ "rubygem-" ++ gem
-          _ -> Just dep
-
-    -- rpmspecBuildRequires :: FilePath -> IO [String]
-    -- rpmspecBuildRequires spec = do
-    --   (ok, out, err) <- cmdFull "rpmspec" (["--define", "ghc_version any", "-q", "--buildrequires"] ++ rpmopts ++ [spec]) ""
-    --   unless (null err) $ warning err
-    --   if ok
-    --     then return $ lines out
-    --     else if lenient then return [] else exitFailure
-
 -- | Alias for createGraph4
 --
 -- @since 0.4.4 (deprecated)
@@ -504,7 +411,8 @@
           -> IO PackageGraph -- ^ dependency graph of the packages
 depsGraph rev rpmopts verbose excludedPkgs ignoredBRs lenient mdir pkgs =
   listDirectory "." >>=
-  depsGraphDeps rev rpmopts verbose excludedPkgs ignoredBRs lenient mdir pkgs
+  depsGraphDeps rev rpmopts verbose excludedPkgs ignoredBRs lenient mdir pkgs .
+  (`union` pkgs)
 
 -- | Given a list of one or more packages and a list of potential dependencies,
 -- return a package dependency graph
@@ -524,7 +432,7 @@
   unlessM (and <$> mapM doesDirectoryExist pkgs) $
     errorWithoutStackTrace "Please use package directory paths"
   -- filter out dotfiles
-  createGraph3 ignoredBRs rpmopts verbose lenient (not rev) mdir (filter ((/= '.') . head) (filter (`notElem` excludedPkgs) deps)) >>=
+  createGraph3 ignoredBRs rpmopts verbose lenient (not rev) mdir (filter (\d -> d `notElem` excludedPkgs && head d /= '.') deps) >>=
     createGraph2 rpmopts verbose lenient True mdir . dependencyNodes pkgs
 
 -- | Used to control the output from sortGraph
diff --git a/src/Distribution/RPM/Build/Order.hs b/src/Distribution/RPM/Build/Order.hs
--- a/src/Distribution/RPM/Build/Order.hs
+++ b/src/Distribution/RPM/Build/Order.hs
@@ -20,6 +20,7 @@
    dependencySortRpmOpts,
    dependencySortParallel,
    dependencyLayers,
+   dependencyLayersRpmOpts,
    leafPackages,
    independentPackages,
    Components (..),
@@ -58,6 +59,14 @@
   graph <- createGraph pkgs
   return $ packageLayers graph
 
+-- | like dependencyLayers but with rpm options
+--
+-- @since 0.4.11
+dependencyLayersRpmOpts :: [String] -> [FilePath] -> IO [[FilePath]]
+dependencyLayersRpmOpts rpmopts pkgs = do
+  graph <- createGraphRpmOpts rpmopts pkgs
+  return $ packageLayers graph
+
 -- | returns the leaves of a set of packages
 leafPackages :: [FilePath] -> IO [FilePath]
 leafPackages pkgs = do
@@ -75,9 +84,9 @@
 sortGraph opt graph =
   mapM_ (putStrLn . unwords) $
   case opt of
-    Parallel -> intersperse ["\n"]
+    Parallel -> intersperse [""]
     Combine -> id
-    Connected -> intersperse ["\n"]
+    Connected -> intersperse [""]
     Separate -> id
   $ topsortGraph opt graph
 
diff --git a/src/Distribution/RPM/Build/ProvReqs.hs b/src/Distribution/RPM/Build/ProvReqs.hs
new file mode 100644
--- /dev/null
+++ b/src/Distribution/RPM/Build/ProvReqs.hs
@@ -0,0 +1,140 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+{-|
+This module has commands for reading the Requires and Provides
+from an RPM package spec file.
+-}
+
+module Distribution.RPM.Build.ProvReqs
+  (rpmspecProvidesBuildRequires)
+where
+
+import Control.Monad (unless)
+import qualified Data.CaseInsensitive as CI
+import Data.List.Extra
+import Data.Maybe (mapMaybe)
+import SimpleCmd (cmdFull, cmdLines, cmdStdErr, egrep_, error',
+                  grep, warning, (+-+))
+import System.Directory (doesFileExist)
+import System.Exit (exitFailure)
+import System.FilePath
+import System.IO.Extra (withTempDir)
+import Text.Regex.TDFA ((=~))
+
+generateBuildRequires :: FilePath -> IO Bool
+generateBuildRequires =
+  egrep_ "^\\(%generate_buildrequires\\|%gometa\\)"
+
+-- | Get RPM Provides and BuildRequires based on spec file.
+rpmspecProvidesBuildRequires :: Bool -- ^ lenient (allow failure)
+                             -> [String] -- ^ RPM opts
+                             -> FilePath -- ^ spec file
+                             -> IO (Maybe ([String], -- ^ Provides
+                                           [String]  -- ^ BuildRequires
+                                          ))
+rpmspecProvidesBuildRequires lenient rpmopts spec = do
+  dynbr <- generateBuildRequires spec
+  if dynbr
+    then do
+    brs <- rpmspecDynBuildRequires spec
+    provs <- do
+      dynprovs <- dynProvides
+      prs <- rpmspecProvides lenient rpmopts spec
+      return $ dynprovs ++ prs
+    return $ Just (provs, brs)
+    else do
+    mcontent <- rpmspecParse
+    case mcontent of
+      Nothing -> return Nothing
+      Just content ->
+        let pkg = takeBaseName spec
+        in fmap Just <$> extractMetadata pkg ([],[]) $ lines content
+  where
+    extractMetadata :: FilePath -> ([String],[String]) -> [String]
+                    -> IO ([String],[String])
+    extractMetadata _ (provs,brs) [] =
+      return (provs, mapMaybe simplifyDep brs)
+    extractMetadata pkg acc@(provs,brs) (l:ls) =
+      case words l of
+        [] -> extractMetadata pkg acc ls
+        [w]
+          | w =~ ("^/usr/(lib(64)?|share)/pkgconfig/.*\\.pc" :: String) ->
+              let pc = metaName "pkgconfig" $ takeBaseName w
+              in extractMetadata pkg (pc : provs, brs) ls
+          | w =~ ("^/usr/(lib(64)?|share)/cmake/[^/]*$" :: String) ->
+              let p = takeFileName w
+                  cm = map (metaName "cmake") $
+                       if lower p == p then [p] else [p, lower p]
+              in extractMetadata pkg (provs ++ cm, brs) ls
+          | otherwise -> extractMetadata pkg acc ls
+        (w:w':ws) ->
+            case CI.mk w of
+              "BuildRequires:" ->
+                -- FIXME could be more than one package: parse ws
+                extractMetadata pkg (provs, w':brs) ls
+              "Name:" -> extractMetadata pkg (w' : provs, brs) ls
+              "Provides:" -> extractMetadata pkg (w' : provs, brs) ls
+              "%package" ->
+                let subpkg =
+                      if null ws
+                      then pkg ++ '-' : w'
+                      else last ws
+                in extractMetadata pkg (subpkg : provs, brs) ls
+              _ -> extractMetadata pkg acc ls
+
+    rpmspecParse :: IO (Maybe String)
+    rpmspecParse = do
+      (ok, out, err) <- cmdFull "rpmspec" (["-P"] ++ rpmopts ++ [spec]) ""
+      unless (null err) $ warning $ spec +-+ err
+      if ok
+        then return $ Just out
+        else if lenient then return Nothing else exitFailure
+
+    dynProvides :: IO [String]
+    dynProvides =
+      if "golang-" `isPrefixOf` takeBaseName spec
+      then do
+        macro <- grep "%global goipath" spec
+        return $
+          case macro of
+            [def] -> ["golang(" ++ last (words def) ++ ")"]
+            _ -> error' $ "failed to find %goipath in" +-+ spec
+      else return []
+
+    simplifyDep br =
+      case (head . words) br of
+        '(':dep -> simplifyDep dep
+        dep -> case splitOn "(" (dropSuffix ")" dep) of
+          ("rpmlib":_) -> Nothing
+          ("crate":[crate]) -> Just $ "rust-" ++ replace "/" "+" crate ++ "-devel"
+          ("rubygem":[gem]) -> Just $ "rubygem-" ++ gem
+          _ -> Just dep
+
+rpmspecDynBuildRequires :: FilePath -> IO [String]
+rpmspecDynBuildRequires spec = do
+  withTempDir $ \tmpdir -> do
+    (out,err) <- cmdStdErr "rpmbuild" ["-br", "--nodeps", "--define", "_srcrpmdir" +-+ tmpdir, spec]
+    -- Wrote: /current/dir/SRPMS/name-version-release.buildreqs.nosrc.rpm
+    let errmsg =
+          "failed to generate srpm for dynamic buildrequires for" +-+ spec ++
+          "\n\n" ++ err
+    case words out of
+      [] -> error' errmsg
+      ws -> do
+        let srpm = last ws
+        exists <- doesFileExist srpm
+        if exists
+          then cmdLines "rpm" ["-qp", "--requires", last ws]
+          else error' errmsg
+
+rpmspecProvides :: Bool -> [String] -> FilePath -> IO [String]
+rpmspecProvides lenient rpmopts spec = do
+  (ok, out, err) <- cmdFull "rpmspec" (["-q", "--provides"] ++ rpmopts ++ [spec]) ""
+  unless (null err) $ warning err
+  if ok
+    then return $ map (head . words) $ lines out
+    else if lenient then return [] else exitFailure
+
+metaName :: String -> String -> String
+metaName meta name =
+  meta ++ '(' : name ++ ")"
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -59,11 +59,13 @@
     ignoredBRopts = many (strOptionWith 'I' "ignore-BR" "PKG" "BuildRequires to exclude from graph")
     excludeOpts = many (dropSuffix "/" <$> strOptionWith 'x' "exclude" "PKG" "Package dirs to exclude from graph")
 
-sortPackages :: [String] -> Bool -> Bool -> Components -> Maybe FilePath -> [FilePath] -> IO ()
+sortPackages :: [String] -> Bool -> Bool -> Components -> Maybe FilePath
+             -> [FilePath] -> IO ()
 sortPackages rpmopts verbose lenient opts mdir pkgs = do
   createGraph2 rpmopts verbose lenient True mdir pkgs >>= sortGraph opts
 
-layerPackages :: [String] -> Bool -> Bool -> Bool -> Maybe FilePath -> [FilePath] -> IO ()
+layerPackages :: [String] -> Bool -> Bool -> Bool -> Maybe FilePath
+              -> [FilePath] -> IO ()
 layerPackages rpmopts verbose lenient combine mdir pkgs = do
   graph <- createGraph2 rpmopts verbose lenient True mdir pkgs
   if combine
@@ -72,7 +74,8 @@
   where
     printLayers =  putStrLn . unlines . map unwords . packageLayers
 
-chainPackages :: [String] -> Bool -> Bool -> Bool -> Maybe FilePath -> [FilePath] -> IO ()
+chainPackages :: [String] -> Bool -> Bool -> Bool -> Maybe FilePath
+              -> [FilePath] -> IO ()
 chainPackages rpmopts verbose lenient combine mdir pkgs = do
   graph <- createGraph2 rpmopts verbose lenient True mdir pkgs
   if combine then doChain graph
@@ -82,12 +85,14 @@
       let chain = intercalate [":"] $ packageLayers graph
       in putStrLn $ unwords chain
 
-leavesPackages :: [String] -> Bool -> Bool -> Maybe FilePath -> [FilePath] -> IO ()
+leavesPackages :: [String] -> Bool -> Bool -> Maybe FilePath -> [FilePath]
+               -> IO ()
 leavesPackages rpmopts verbose lenient mdir pkgs = do
   graph <- createGraph2 rpmopts verbose lenient True mdir pkgs
   mapM_ putStrLn $ packageLeaves graph
 
-rootPackages :: [String] -> Bool -> Bool -> Maybe FilePath -> [FilePath] -> IO ()
+rootPackages :: [String] -> Bool -> Bool -> Maybe FilePath -> [FilePath]
+             -> IO ()
 rootPackages rpmopts verbose lenient mdir pkgs = do
   graph <- createGraph2 rpmopts verbose lenient True mdir pkgs
   mapM_ putStrLn $ lowestLayer graph
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -17,53 +17,70 @@
 pkg :: FilePath -> FilePath
 pkg = ("test/pkgs/" ++)
 
+-- FIXME refactor to test both subdir and withCurrentDirectory
 spec :: Version -> Spec
 spec rpmver = do
   describe "sort" $ do
     it "A B" $
-      dependencySort [pkg "A", pkg "B"] >>=
+      both dependencySort [pkg "A", pkg "B"] >>=
       (`shouldBe` [pkg "B", pkg "A"])
 
     it "1 2" $
-      dependencySort [pkg "1", pkg "2"] >>=
+      both dependencySort [pkg "1", pkg "2"] >>=
       (`shouldBe` [pkg "2", pkg "1"])
 
     it "A/ B/" $
-      dependencySort [pkg "A/", pkg "B/"] >>=
+      both dependencySort [pkg "A/", pkg "B/"] >>=
       (`shouldBe` [pkg "B/", pkg "A/"])
 
     it "1/ 2/" $
-      dependencySort [pkg "1/", pkg "2/"] >>=
+      both dependencySort [pkg "1/", pkg "2/"] >>=
       (`shouldBe` [pkg "2/", pkg "1/"])
 
     it "A.spec B.spec" $
-      dependencySort [pkg "A/A.spec", pkg "B/B.spec"] >>=
+      both dependencySort [pkg "A/A.spec", pkg "B/B.spec"] >>=
       (`shouldBe` [pkg "B/B.spec", pkg "A/A.spec"])
 
     it "1.spec 2.spec" $
-      dependencySort [pkg "1/A.spec", pkg "2/B.spec"] >>=
+      both dependencySort [pkg "1/A.spec", pkg "2/B.spec"] >>=
       (`shouldBe` [pkg "2/B.spec", pkg "1/A.spec"])
 
     it "A/ B.spec" $
-      dependencySort [pkg "A/", pkg "B/B.spec"] >>=
+      both dependencySort [pkg "A/", pkg "B/B.spec"] >>=
       (`shouldBe` [pkg "B/B.spec", pkg "A/"])
 
     it "circular A B C" $
-      dependencySort [pkg "A", pkg "B", pkg "C"]
+      both dependencySort [pkg "A", pkg "B", pkg "C"]
       `shouldThrow` anyException
 
     it "A B D1.0" $
       dependencySort [pkg "A", pkg "B/", pkg "D1.0"] >>=
       (`shouldBe` [pkg "B/", pkg "D1.0", pkg "A"])
 
+    it "A D" $
+      indy dependencySort [pkg "A", pkg "D1.0"] >>=
+      (`shouldBe` [pkg "A", pkg "D1.0"])
+
+    it "C D" $
+      indy dependencySort [pkg "C", pkg "D1.0"] >>=
+      (`shouldBe` [pkg "C", pkg "D1.0"])
+
+    it "pkgconf" $
+      both dependencySort [pkg "pkgconf/C", pkg "pkgconf/A"] >>=
+      (`shouldBe` [pkg "pkgconf/C", pkg "pkgconf/A"])
+
+    it "cmake" $
+      both dependencySort [pkg "cmake/A", pkg "cmake/B"] >>=
+      (`shouldBe` [pkg "cmake/B", pkg "cmake/A"])
+
     when (rpmver > makeVersion [4,15,0]) $
       it "dynbr A B" $
-      dependencySort [pkg "dynbr/A", pkg "B"] >>=
+      both dependencySort [pkg "dynbr/A", pkg "B"] >>=
       (`shouldBe` [pkg "B", pkg "dynbr/A"])
 
     when (rpmver > makeVersion [4,15,1]) $
       it "circular A B C boot" $
-      dependencySortRpmOpts ["--with=boot"] [pkg "A", pkg "B", pkg "C"] >>=
+      both (dependencySortRpmOpts ["--with=boot"]) [pkg "A", pkg "B", pkg "C"] >>=
       (`shouldBe` [pkg "C", pkg "B", pkg "A"])
 
   describe "layers" $
@@ -76,17 +93,44 @@
       leafPackages [pkg "A", pkg "B", pkg "D1.0"] >>=
       (`shouldBe` [pkg "A", pkg "D1.0"])
 
+  let rpmbuildOrder f c = fmap f . cmd "rpmbuild-order" . (c:)
+
   describe "rpmbuild-order" $ do
     it "sort A B" $
-      cmd "rpmbuild-order" ["sort", pkg "A", pkg "B"] >>=
-      (`shouldBe` unwords [pkg "B", pkg "A"])
+      both (rpmbuildOrder words "sort") [pkg "A", pkg "B"] >>=
+      (`shouldBe` [pkg "B", pkg "A"])
 
+    it "sort A D" $
+      indy (rpmbuildOrder lines "sort") [pkg "A", pkg "D1.0"] >>=
+      (`shouldBe` [pkg "D1.0", "", pkg "A"])
+
+    it "sort pkgconf" $
+      both (rpmbuildOrder words "sort") [pkg "pkgconf/A", pkg "pkgconf/C"] >>=
+      (`shouldBe` [pkg "pkgconf/C", pkg "pkgconf/A"])
+
+    it "sort cmake" $
+      both (rpmbuildOrder words "sort") [pkg "cmake/A", pkg "cmake/B"] >>=
+      (`shouldBe` [pkg "cmake/B", pkg "cmake/A"])
+
     it "deps A" $
       withCurrentDirectory "test/pkgs" $
       cmd "rpmbuild-order"
-      ["deps", "-x", "dynbr", "-x", "1", "-x", "2", "-x", "C", "A"] >>=
+      ["deps", "-x", "dynbr", "-x", "pkgconf", "-x", "1", "-x", "2", "-x", "C","-x", "cmake", "A"] >>=
       (`shouldBe` unwords ["B", "A"])
+  where
+    both :: ([FilePath] -> IO [FilePath]) -> [FilePath] -> IO [FilePath]
+    both io fs = do
+      r <- io fs
+      r' <- io $ reverse fs
+      r `shouldBe` r'
+      return r
 
+    indy :: ([FilePath] -> IO [FilePath]) -> [FilePath] -> IO [FilePath]
+    indy io fs = do
+      r <- io fs
+      r' <- io $ reverse fs
+      r `shouldBe` reverse r'
+      return r'
 
 setupSymlinks :: IO ()
 setupSymlinks =
diff --git a/test/pkgs/cmake/A/A.spec b/test/pkgs/cmake/A/A.spec
new file mode 100644
--- /dev/null
+++ b/test/pkgs/cmake/A/A.spec
@@ -0,0 +1,13 @@
+Name:           A
+Version:        1
+Release:        1%{?dist}
+Summary:        package A
+License:        GPL
+BuildRequires:  cmake(libB)
+
+%description
+Test package A pkgconfig
+
+%changelog
+* Wed Jul 29 13:38:27 +08 2020 Jens Petersen <petersen@redhat.com>
+-
diff --git a/test/pkgs/cmake/B/B.spec b/test/pkgs/cmake/B/B.spec
new file mode 100644
--- /dev/null
+++ b/test/pkgs/cmake/B/B.spec
@@ -0,0 +1,22 @@
+Name:           B
+Version:        1
+Release:        1%{?dist}
+Summary:        package B
+License:        GPL
+
+%description
+Test package B
+
+%prep
+
+%build
+
+%install
+
+%files
+%{_libdir}/cmake/libB
+%{_libdir}/cmake/libB/B.cmake
+
+%changelog
+* Wed Jul 29 13:38:27 +08 2020 Jens Petersen <petersen@redhat.com>
+-
diff --git a/test/pkgs/pkgconf/A/A.spec b/test/pkgs/pkgconf/A/A.spec
new file mode 100644
--- /dev/null
+++ b/test/pkgs/pkgconf/A/A.spec
@@ -0,0 +1,13 @@
+Name:           A
+Version:        1
+Release:        1%{?dist}
+Summary:        package A
+License:        GPL
+BuildRequires:  pkgconfig(libC)
+
+%description
+Test package A pkgconfig
+
+%changelog
+* Wed Jul 29 13:38:27 +08 2020 Jens Petersen <petersen@redhat.com>
+-
diff --git a/test/pkgs/pkgconf/C/C.spec b/test/pkgs/pkgconf/C/C.spec
new file mode 100644
--- /dev/null
+++ b/test/pkgs/pkgconf/C/C.spec
@@ -0,0 +1,14 @@
+Name:           C
+Version:        1
+Release:        1%{?dist}
+Summary:        package C
+License:        GPL
+
+%description
+
+%files
+%{_libdir}/pkgconfig/libC.pc
+
+%changelog
+* Wed Jul 29 13:38:27 +08 2020 Jens Petersen <petersen@redhat.com>
+-
