diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # chs-cabal
 
+## 1.0.0.0
+
+  * Complete rewrite to use `hookedPreProcessors`
+  * Adds `c2hsSuffixHandler`
+  * Removes `c2hsBuildHooks`, `c2hsHaddockHooks`, `c2hsReplHooks`
+
 ## 0.1.1.4
 
   * Update for Cabal 3.14 correctly
diff --git a/chs-cabal.cabal b/chs-cabal.cabal
--- a/chs-cabal.cabal
+++ b/chs-cabal.cabal
@@ -1,6 +1,6 @@
 cabal-version:   1.18
 name:            chs-cabal
-version:         0.1.1.4
+version:         1.0.0.0
 license:         BSD3
 license-file:    LICENSE
 copyright:       Copyright: (c) 2019, 2021 Vanessa McHale
diff --git a/src/Distribution/C2Hs.hs b/src/Distribution/C2Hs.hs
--- a/src/Distribution/C2Hs.hs
+++ b/src/Distribution/C2Hs.hs
@@ -1,133 +1,30 @@
 {-# LANGUAGE DataKinds #-}
 
--- | Everything in this module is slightly morally dubious in that it works by
--- considering *all* modules to be @exposed-modules@ in the preprocessor phase.
---
--- This works in practice, but the Cabal API provides no guarantees this will
--- continue to be the case in the future.
 module Distribution.C2Hs ( defaultMainC2Hs
                          -- * User hooks
                          , c2hsUserHooks
-                         -- * Specialized hooks
-                         , c2hsBuildHooks
-                         , c2hsHaddockHooks
-                         , c2hsReplHooks
+                         , c2hsSuffixHandler
                          ) where
 
-import           Control.Applicative                   (pure)
-import           Data.Traversable                      (traverse)
+import           Control.Applicative            (pure)
+import           Data.Traversable               (traverse)
 import           Distribution.C2Hs.TopSort
-import           Distribution.ModuleName               (ModuleName)
-import           Distribution.Simple                   (UserHooks (buildHook, haddockHook, replHook),
-                                                        defaultMainWithHooks,
-                                                        simpleUserHooks)
-import           Distribution.Simple.LocalBuildInfo    (LocalBuildInfo)
-import           Distribution.Simple.Setup             (BuildFlags, buildCommonFlags,
-                                                        HaddockFlags, haddockCommonFlags,
-                                                        ReplFlags, replCommonFlags,
-                                                        CommonSetupFlags (CommonSetupFlags, setupVerbosity),
-                                                        fromFlagOrDefault)
-import           Distribution.Types.Benchmark
-import           Distribution.Types.BuildInfo
-import           Distribution.Types.Executable
-import           Distribution.Types.ForeignLib
-import           Distribution.Types.Library
-import           Distribution.Types.PackageDescription
-import           Distribution.Types.TestSuite
-import           Distribution.Utils.Path               (Pkg, Source, FileOrDir (Dir),
-                                                        SymbolicPath)
-import           Distribution.Verbosity                (Verbosity, normal)
-
-type CabalFP = SymbolicPath Pkg (Dir Source)
+import           Distribution.Simple            (UserHooks (hookedPreProcessors),
+                                                 defaultMainWithHooks,
+                                                 simpleUserHooks)
+import           Distribution.Simple.PreProcess (PPSuffixHandler,
+                                                 PreProcessor (ppOrdering),
+                                                 Suffix (Suffix), ppC2hs)
 
 defaultMainC2Hs :: IO ()
 defaultMainC2Hs = defaultMainWithHooks c2hsUserHooks
 
 -- | @since 0.1.1.0
 c2hsUserHooks :: UserHooks
-c2hsUserHooks = simpleUserHooks { buildHook = c2hsBuildHooks
-                                , haddockHook = c2hsHaddockHooks
-                                , replHook = c2hsReplHooks
-                                }
-
--- | Custom build hooks to be used with @.chs@ files which @{\#import\#}@ one
--- another.
-c2hsBuildHooks :: PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()
-c2hsBuildHooks = \pd lbi hooks bf -> do
-    let v = getSetupVerbosity (buildCommonFlags bf)
-    pd' <- mapPackageDescription (reorderC2Hs v) pd
-    buildHook simpleUserHooks pd' lbi hooks bf
-
-c2hsHaddockHooks :: PackageDescription -> LocalBuildInfo -> UserHooks -> HaddockFlags -> IO ()
-c2hsHaddockHooks = \pd lbi hooks hf -> do
-    let v = getSetupVerbosity (haddockCommonFlags hf)
-    pd' <- mapPackageDescription (reorderC2Hs v) pd
-    haddockHook simpleUserHooks pd' lbi hooks hf
-
-c2hsReplHooks :: PackageDescription -> LocalBuildInfo -> UserHooks -> ReplFlags -> [String] -> IO ()
-c2hsReplHooks = \pd lbi hooks rf ss -> do
-    let v = getSetupVerbosity (replCommonFlags rf)
-    pd' <- mapPackageDescription (reorderC2Hs v) pd
-    replHook simpleUserHooks pd' lbi hooks rf ss
-
-getSetupVerbosity :: CommonSetupFlags -> Verbosity
-getSetupVerbosity CommonSetupFlags { setupVerbosity = v } = fromFlagOrDefault normal v
-
-mapPackageDescription :: ([CabalFP] -> [ModuleName] -> IO [ModuleName]) -> PackageDescription -> IO PackageDescription
-mapPackageDescription f p@PackageDescription { library = ml
-                                             , subLibraries = ls
-                                             , executables = es
-                                             , foreignLibs = fs
-                                             , testSuites = ts
-                                             , benchmarks = bs
-                                             } = do
-    ml' <- traverse (mapLibrary f) ml
-    ls' <- traverse (mapLibrary f) ls
-    es' <- traverse (mapExecutable f) es
-    fs' <- traverse (mapForeignLibrary f) fs
-    ts' <- traverse (mapTestSuite f) ts
-    bs' <- traverse (mapBenchmark f) bs
-    pure $ p { library = ml'
-             , subLibraries = ls'
-             , executables = es'
-             , foreignLibs = fs'
-             , testSuites = ts'
-             , benchmarks = bs'
-             }
-
-mapLibrary :: ([CabalFP] -> [ModuleName] -> IO [ModuleName]) -> Library -> IO Library
-mapLibrary f lib@Library { exposedModules = es, libBuildInfo = bi } = do
-    let dirs = hsSourceDirs bi
-        om = otherModules bi
-        isOther = (`notElem` es)
-    newMods <- f dirs (es ++ om)
-    let om' = filter isOther newMods
-        bi' = bi { otherModules = om' }
-        -- This is stupid, but I've tested it and it seems to not do anything
-        -- egregious
-    pure $ lib { exposedModules = newMods, libBuildInfo = bi' }
-
-mapBenchmark :: ([CabalFP] -> [ModuleName] -> IO [ModuleName]) -> Benchmark -> IO Benchmark
-mapBenchmark f b@Benchmark { benchmarkBuildInfo = bi } = do
-    bi' <- mapBuildInfo f bi
-    pure $ b { benchmarkBuildInfo = bi' }
-
-mapExecutable :: ([CabalFP] -> [ModuleName] -> IO [ModuleName]) -> Executable -> IO Executable
-mapExecutable f e@Executable { buildInfo = bi } = do
-    bi' <- mapBuildInfo f bi
-    pure $ e { buildInfo = bi' }
-
-mapForeignLibrary :: ([CabalFP] -> [ModuleName] -> IO [ModuleName]) -> ForeignLib -> IO ForeignLib
-mapForeignLibrary f fl@ForeignLib { foreignLibBuildInfo = bi } = do
-    bi' <- mapBuildInfo f bi
-    pure $ fl { foreignLibBuildInfo = bi' }
-
-mapTestSuite :: ([CabalFP] -> [ModuleName] -> IO [ModuleName]) -> TestSuite -> IO TestSuite
-mapTestSuite f t@TestSuite { testBuildInfo = bi } = do
-    bi' <- mapBuildInfo f bi
-    pure $ t { testBuildInfo = bi' }
+c2hsUserHooks = simpleUserHooks { hookedPreProcessors = [c2hsSuffixHandler] }
 
-mapBuildInfo :: ([CabalFP] -> [ModuleName] -> IO [ModuleName]) -> BuildInfo -> IO BuildInfo
-mapBuildInfo f bi@BuildInfo { otherModules = om, hsSourceDirs = dirs } = do
-    om' <- f dirs om
-    pure $ bi { otherModules = om' }
+-- | 'PPSuffixHandler' for @.chs@ files that reorders based on imports
+--
+-- @since 1.0.0.0
+c2hsSuffixHandler :: PPSuffixHandler
+c2hsSuffixHandler = (Suffix ".chs", \bi lbi cbi -> (ppC2hs bi lbi cbi) { ppOrdering = reorderC2Hs })
