diff --git a/package.yaml b/package.yaml index 7604585..2ebb514 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,7 @@ name: cabalize + ghc-options: -Wall + dependencies: - aeson >= 0.8 - base == 4.* @@ -9,10 +11,16 @@ dependencies: - interpolate - unordered-containers - yaml + +library: + exposed-modules: + - Cabalize + executables: cb: main: driver/Main.hs dependencies: cabalize + tests: spec: main: test/Spec.hs diff --git a/src/Cabalize.hs b/src/Cabalize.hs index 9d543e1..7dbf147 100644 --- a/src/Cabalize.hs +++ b/src/Cabalize.hs @@ -59,7 +59,7 @@ version: #{packageVersion} build-type: Simple cabal-version: >= 1.10 -#{renderLibrary packageLibrary} +#{maybe "" renderLibrary packageLibrary} #{renderExecutables packageExecutables} #{renderTests packageTests} |] @@ -70,6 +70,8 @@ library hs-source-dirs: src exposed-modules: #{intercalate "\n" . map (" " ++) $ libraryExposedModules} + other-modules: +#{intercalate "\n" . map (" " ++) $ libraryOtherModules} build-depends: #{intercalate "\n , " $ sort libraryDependencies} default-language: Haskell2010 diff --git a/src/Config.hs b/src/Config.hs index 31b3b81..a552fba 100644 --- a/src/Config.hs +++ b/src/Config.hs @@ -9,6 +9,7 @@ module Config ( import Prelude () import Prelude.Compat +import Data.List ((\\)) import Data.Maybe import Data.Yaml import GHC.Generics @@ -18,6 +19,15 @@ import System.Directory import Util +data LibrarySection = LibrarySection { + librarySectionExposedModules :: Maybe (List Dependency) +, librarySectionDependencies :: Maybe (List Dependency) +, librarySectionGhcOptions :: Maybe (List GhcOption) +} deriving (Eq, Show, Generic) + +instance FromJSON LibrarySection where + parseJSON = genericParseJSON_ "LibrarySection" + data ExecutableSection = ExecutableSection { executableSectionMain :: FilePath , executableSectionDependencies :: Maybe (List Dependency) @@ -32,6 +42,7 @@ data ConfigFile = ConfigFile { , configFileVersion :: Maybe String , configFileDependencies :: Maybe [Dependency] , configFileGhcOptions :: Maybe (List GhcOption) +, configFileLibrary :: Maybe LibrarySection , configFileExecutables :: Maybe (HashMap String ExecutableSection) , configFileTests :: Maybe (HashMap String ExecutableSection) } deriving (Eq, Show, Generic) @@ -52,14 +63,16 @@ type GhcOption = String data Package = Package { packageName :: String , packageVersion :: String -, packageLibrary :: Library +, packageLibrary :: Maybe Library , packageExecutables :: [Executable] , packageTests :: [Executable] } deriving (Eq, Show) data Library = Library { libraryExposedModules :: [String] +, libraryOtherModules :: [String] , libraryDependencies :: [Dependency] +, libraryGhcOptions :: [GhcOption] } deriving (Eq, Show) data Executable = Executable { @@ -73,18 +86,25 @@ mkPackage :: ConfigFile -> IO Package mkPackage ConfigFile{..} = do let dependencies = fromMaybe [] configFileDependencies let ghcOptions = fromMaybeList configFileGhcOptions - library <- mkLibrary dependencies + mLibrary <- mapM (mkLibrary dependencies ghcOptions) configFileLibrary let package = Package { packageName = configFileName , packageVersion = fromMaybe "0.0.0" configFileVersion - , packageLibrary = library + , packageLibrary = mLibrary , packageExecutables = toExecutables dependencies ghcOptions configFileExecutables , packageTests = toExecutables dependencies ghcOptions configFileTests } return package -mkLibrary :: [Dependency] -> IO Library -mkLibrary dependencies = Library <$> getModules "src" <*> pure dependencies +mkLibrary :: [Dependency] -> [GhcOption] -> LibrarySection -> IO Library +mkLibrary globalDependencies globalGhcOptions LibrarySection{..} = do + modules <- getModules "src" + let otherModules = modules \\ exposedModules + return (Library exposedModules otherModules dependencies ghcOptions) + where + exposedModules = fromMaybeList librarySectionExposedModules + dependencies = globalDependencies ++ fromMaybeList librarySectionDependencies + ghcOptions = globalGhcOptions ++ fromMaybeList librarySectionGhcOptions getModules :: FilePath -> IO [String] getModules src = do diff --git a/test/ConfigSpec.hs b/test/ConfigSpec.hs index bb7f4d7..b0945d0 100644 --- a/test/ConfigSpec.hs +++ b/test/ConfigSpec.hs @@ -11,11 +11,14 @@ main :: IO () main = hspec spec package :: String -> Package -package name = Package name "0.0.0" (Library [] []) [] [] +package name = Package name "0.0.0" Nothing [] [] executable :: String -> String -> Executable executable name path = Executable name path [] [] +library :: Library +library = Library [] [] [] [] + spec :: Spec spec = around_ inTempDirectory $ do describe "readConfig" $ do @@ -32,6 +35,17 @@ spec = around_ inTempDirectory $ do |] readConfig "package.yaml" `shouldReturn` Just (package "foo") {packageVersion = "0.1.0"} + context "when reading library section" $ do + it "allows to specify exposed modules" $ do + writeFile "package.yaml" [i| + name: foo + library: + exposed-modules: Foo + |] + touch "src/Foo.hs" + touch "src/Bar.hs" + readConfig "package.yaml" `shouldReturn` Just (package "foo") {packageLibrary = Just library {libraryExposedModules = ["Foo"], libraryOtherModules = ["Bar"]}} + context "when reading executable section" $ do it "reads executable section" $ do writeFile "package.yaml" [i| @@ -106,4 +120,4 @@ spec = around_ inTempDirectory $ do main: test/Spec.hs dependencies: hspec |] - readConfig "package.yaml" `shouldReturn` Just (package "foo") {packageTests = [(executable "spec" "test/Spec.hs") {executableDependencies = ["base", "hspec"]}], packageLibrary = Library [] ["base"]} + readConfig "package.yaml" `shouldReturn` Just (package "foo") {packageTests = [(executable "spec" "test/Spec.hs") {executableDependencies = ["base", "hspec"]}]} diff --git a/test/Helper.hs b/test/Helper.hs index 15d6d56..0d07257 100644 --- a/test/Helper.hs +++ b/test/Helper.hs @@ -2,6 +2,7 @@ module Helper where import Control.Exception import System.Directory +import System.FilePath import System.IO.Temp inTempDirectory :: IO a -> IO a @@ -9,3 +10,8 @@ inTempDirectory action = withSystemTempDirectory "hspec" $ \path -> do bracket getCurrentDirectory setCurrentDirectory $ \_ -> do setCurrentDirectory path action + +touch :: FilePath -> IO () +touch p = do + createDirectoryIfMissing True (takeDirectory p) + writeFile p ""