diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,21 @@
 # Revision history for psx
 
+## 0.1.1.0 -- 2023-02-22
+
+* Support GHC 9.4.2 / `base ^>=4.17`.
+
+* Rely on `_POSIX_C_SOURCE >= 1` instead of `_GNU_SOURCE` as feature test macro
+  for `sigset_t` in `hs-psx.c`.
+
+* Use `capi` foreign imports instead of `ccall` using the `CApiFFI` language
+  extension.
+
+* Include a `Setup.hs` file.
+
+* Minor stylistic changes to Cabal package description file.
+
+* Add a Cabal flag, `werror`, to enable compiler `-Werror` and friends.
+
 ## 0.1.0.0 -- 2022-08-24
 
 * First version. Released on an unsuspecting world.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+import Distribution.Simple
+
+main = defaultMain
diff --git a/cbits/hs-psx.c b/cbits/hs-psx.c
--- a/cbits/hs-psx.c
+++ b/cbits/hs-psx.c
@@ -1,4 +1,4 @@
-#define _GNU_SOURCE
+#define _POSIX_C_SOURCE 1
 
 #include <signal.h>
 
diff --git a/psx.cabal b/psx.cabal
--- a/psx.cabal
+++ b/psx.cabal
@@ -1,11 +1,10 @@
-Cabal-Version:       2.2
-Build-Type:          Simple
-
-Name:                psx
-Version:             0.1.0.0
-Synopsis:            Integrate @libpsx@ with the GHC RTS
-Description:
-  This library embeds libpsx in a GHC Haskell-compiled application.
+cabal-version:      2.2
+build-type:         Simple
+name:               psx
+version:            0.1.1.0
+synopsis:           Integrate libpsx with the GHC RTS
+description:
+  This library embeds @libpsx@ in a GHC Haskell-compiled application.
   .
   Note @libpsx@ performs some trickery with signal handling in a process.
   Furthermore, when using this library, @sigfillset@ will be wrapped so
@@ -17,40 +16,66 @@
   by default. Disable the @bundled-libpsx@ flag to use a system-provided
   version of the library, which must be from @libcap@ version 2.46 or higher.
   The license of the bundled library can be found in @cbits\/psx\/License@.
-Homepage:            https://github.com/NicolasT/landlock-hs
-Bug-Reports:         https://github.com/NicolasT/landlock-hs/issues
-License:             BSD-3-Clause
-License-File:        LICENSE
-Author:              Nicolas Trangez
-Maintainer:          ikke@nicolast.be
-Copyright:           (c) 2022 Nicolas Trangez
-Category:            System
-Stability:           alpha
 
-Extra-Source-Files:
+homepage:           https://github.com/NicolasT/landlock-hs
+bug-reports:        https://github.com/NicolasT/landlock-hs/issues
+license:            BSD-3-Clause
+license-file:       LICENSE
+author:             Nicolas Trangez
+maintainer:         ikke@nicolast.be
+copyright:          (c) 2022 Nicolas Trangez
+category:           System
+stability:          alpha
+extra-doc-files:
+  cbits/psx/License
   CHANGELOG.md
   README.md
+
+extra-source-files:
   cbits/hs-psx.h
-  cbits/psx/License
   cbits/psx/psx_syscall.h
   test/detect-psx.h
 
-Tested-With:         GHC ==8.10.5
-                   , GHC ==9.0.2
-                   , GHC ==9.2.2
+tested-with:        GHC ==8.10.7 || ==9.0.2 || ==9.2.4 || ==9.4.2
 
-Source-Repository head
-  Type:                git
-  Location:            https://github.com/NicolasT/landlock-hs.git
-  Subdir:              psx
-  Branch:              main
+source-repository head
+  type:     git
+  location: https://github.com/NicolasT/landlock-hs.git
+  subdir:   psx
+  branch:   main
 
-Flag bundled-libpsx
-  Description:         Use the bundled libpsx instead of a (potentially broken) system-provided version. See @cbits\/psx\/License@.
-  Default:             True
-  Manual:              True
+flag bundled-libpsx
+  description:
+    Use the bundled libpsx instead of a (potentially broken) system-provided version. See @cbits\/psx\/License@.
 
-Library
+  default:     True
+  manual:      True
+
+flag werror
+  description: Turn compiler warnings into errors.
+  default:     False
+  manual:      True
+
+common common-settings
+  default-language: Haskell2010
+  ghc-options:
+    -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates
+    -Wpartial-fields -Wmissing-home-modules -Widentities
+    -Wredundant-constraints -Wcpp-undef -Wmissing-export-lists
+
+  cc-options:       -Wall -Wextra -pedantic
+
+  if flag(werror)
+    ghc-options: -Werror -optc=-Werror
+
+    -- Note: disable some warnings triggered by `hsc2hs` code
+    cc-options:
+      -Werror -Wno-error=overlength-strings -Wno-error=type-limits
+      -Wno-error=variadic-macros
+
+library
+  import:           common-settings
+
   -- Despite this library not containing any Haskell code, and
   -- hence not really having any dependency on `base`, it is
   -- only *tested* on particular GHC versions (which we can tie
@@ -58,62 +83,68 @@
   -- between this package functionality working as expected (cfr.
   -- the `sigfillset` wrapping) and the GHC RTS, it seems wise to
   -- restrict compatibility with said GHC version(s).
-  Exposed-Modules:     System.PSX
-  Hs-Source-Dirs:      src
-  Build-Depends:       base ^>=4.14.2.0 || ^>=4.15 || ^>=4.16
-  Include-Dirs:        cbits
-  Install-Includes:    hs-psx.h
-  C-Sources:           cbits/hs-psx.c
-  Cc-Options:          -Wall
-  Ld-Options:          -Wl,-wrap,sigfillset -Wl,-undefined,__wrap_sigfillset
-  Default-Language:    Haskell2010
-  Ghc-Options:         -Wall
+  exposed-modules:  System.PSX
+  hs-source-dirs:   src
+  build-depends:    base >=4.14.2.0 && <4.17 || ^>=4.17
+  include-dirs:     cbits
+  install-includes: hs-psx.h
+  c-sources:        cbits/hs-psx.c
+  ld-options:
+    "-Wl,-wrap,sigfillset" "-Wl,-undefined,__wrap_sigfillset"
+
   if flag(bundled-libpsx)
-    C-Sources:         cbits/psx/psx.c
-    Cc-Options:        -DBUNDLED_LIBPSX
-    Ld-Options:        -pthread -Wl,-wrap,pthread_create
+    c-sources:  cbits/psx/psx.c
+    cc-options: -DBUNDLED_LIBPSX
+    ld-options: -pthread "-Wl,-wrap,pthread_create"
+
   else
-    Pkgconfig-Depends: libpsx
+    pkgconfig-depends: libpsx
 
-Test-Suite psx-test-threaded
-  Type:                exitcode-stdio-1.0
-  Hs-Source-Dirs:      test
-  Main-Is:             psx-test-threaded.hs
-  Other-Modules:       TestCases
-  C-Sources:           test/detect-psx.c
-  Include-Dirs:        test
-  Build-Depends:       psx
-                     , base
-                     , async ^>=2.2.3
-                     , tasty ^>=1.4.1
-                     , tasty-hunit ^>=0.10.0.3
-  Default-Language:    Haskell2010
-  Ghc-Options:         -Wall -threaded -with-rtsopts -N2
+test-suite psx-test-threaded
+  import:           common-settings
+  type:             exitcode-stdio-1.0
+  hs-source-dirs:   test
+  main-is:          psx-test-threaded.hs
+  other-modules:    TestCases
+  c-sources:        test/detect-psx.c
+  include-dirs:     test
+  build-depends:
+    , async        ^>=2.2.3
+    , base         >=4.14.2.0  && <4.17 || ^>=4.17
+    , psx
+    , tasty        ^>=1.4.1
+    , tasty-hunit  ^>=0.10.0.3
 
-Test-Suite psx-test
-  Type:                exitcode-stdio-1.0
-  Hs-Source-Dirs:      test
-  Main-Is:             psx-test.hs
-  Other-Modules:       TestCases
-  C-Sources:           test/detect-psx.c
-  Include-Dirs:        test
-  Build-Depends:       psx
-                     , base
-                     , async ^>=2.2.3
-                     , tasty ^>=1.4.1
-                     , tasty-hunit ^>=0.10.0.3
-  Default-Language:    Haskell2010
-  Ghc-Options:         -Wall
+  ghc-options:      -threaded -with-rtsopts -N2
+  other-extensions: CApiFFI
 
-Test-Suite psx-test-no-psx
-  Type:                exitcode-stdio-1.0
-  Hs-Source-Dirs:      test
-  Main-Is:             psx-test-no-psx.hs
-  C-Sources:           test/detect-psx.c
-  Include-Dirs:        test
-                       cbits
-  Build-Depends:       base
-                     , tasty ^>=1.4.1
-                     , tasty-hunit ^>=0.10.0.3
-  Default-Language:    Haskell2010
-  Ghc-Options:         -Wall
+test-suite psx-test
+  import:           common-settings
+  type:             exitcode-stdio-1.0
+  hs-source-dirs:   test
+  main-is:          psx-test.hs
+  other-modules:    TestCases
+  c-sources:        test/detect-psx.c
+  include-dirs:     test
+  build-depends:
+    , async        ^>=2.2.3
+    , base         >=4.14.2.0  && <4.17 || ^>=4.17
+    , psx
+    , tasty        ^>=1.4.1
+    , tasty-hunit  ^>=0.10.0.3
+
+  other-extensions: CApiFFI
+
+test-suite psx-test-no-psx
+  import:           common-settings
+  type:             exitcode-stdio-1.0
+  hs-source-dirs:   test
+  main-is:          psx-test-no-psx.hs
+  c-sources:        test/detect-psx.c
+  include-dirs:     test cbits
+  build-depends:
+    , base         >=4.14.2.0  && <4.17 || ^>=4.17
+    , tasty        ^>=1.4.1
+    , tasty-hunit  ^>=0.10.0.3
+
+  other-extensions: CApiFFI
diff --git a/src/System/PSX.hs b/src/System/PSX.hs
--- a/src/System/PSX.hs
+++ b/src/System/PSX.hs
@@ -27,5 +27,4 @@
 -- 2.44) is broken. Hence, this library contains a bundled version of @libpsx@
 -- by default. Disable the @bundled-libpsx@ flag to use a system-provided
 -- version of the library, which must be from @libcap@ version 2.46 or higher.
-
 module System.PSX () where
diff --git a/test/TestCases.hsc b/test/TestCases.hsc
--- a/test/TestCases.hsc
+++ b/test/TestCases.hsc
@@ -1,3 +1,5 @@
+{-# LANGUAGE CApiFFI #-}
+
 module TestCases (
       psxSyscall3Works
     , psxSyscall6Works
@@ -25,14 +27,14 @@
 import Test.Tasty (TestTree)
 import Test.Tasty.HUnit ((@?=), assertBool, testCase, testCaseSteps)
 
-foreign import ccall unsafe "hs-psx.h hs_psx_syscall3"
+foreign import capi unsafe "hs-psx.h hs_psx_syscall3"
     psxSyscall3 :: #{type long}
                 -> #{type long}
                 -> #{type long}
                 -> #{type long}
                 -> IO #{type long}
 
-foreign import ccall unsafe "hs-psx.h hs_psx_syscall6"
+foreign import capi unsafe "hs-psx.h hs_psx_syscall6"
     psxSyscall6 :: #{type long}
                 -> #{type long}
                 -> #{type long}
@@ -42,13 +44,13 @@
                 -> #{type long}
                 -> IO #{type long}
 
-foreign import ccall unsafe "unistd.h getpid"
+foreign import capi unsafe "unistd.h getpid"
     c_getpid :: IO #{type pid_t}
 
 getpid :: IO #{type pid_t}
 getpid = throwErrnoIfMinus1 "getpid" c_getpid
 
-foreign import ccall unsafe "unistd.h gettid"
+foreign import capi unsafe "unistd.h gettid"
     c_gettid :: IO #{type pid_t}
 
 gettid :: IO #{type pid_t}
@@ -66,7 +68,7 @@
     void $ throwErrnoIfMinus1 "prctl" $ psxSyscall6 #{const __NR_prctl} #{const PR_GET_NO_NEW_PRIVS} 0 0 0 0 0
 
 
-foreign import ccall unsafe "sys/prctl.h prctl"
+foreign import capi unsafe "sys/prctl.h prctl"
     _prctl :: #{type int}
            -> #{type unsigned long}
            -> #{type unsigned long}
@@ -147,10 +149,10 @@
     peek _ = error "peek not implemented"
     poke _ _ = error "poke not implemented"
 
-foreign import ccall unsafe "signal.h sigfillset"
+foreign import capi unsafe "signal.h sigfillset"
     sigfillset :: Ptr SigsetT -> IO #{type int}
 
-foreign import ccall unsafe "signal.h sigismember"
+foreign import capi unsafe "signal.h sigismember"
     sigismember :: Ptr SigsetT -> #{type int} -> IO #{type int}
 
 sigfillsetWrapped :: TestTree
@@ -160,7 +162,7 @@
     isMember @?= 0
 
 
-foreign import ccall unsafe "detect-psx.h detect_psx"
+foreign import capi unsafe "detect-psx.h detect_psx"
     detectPsx :: IO #{type int}
 
 psxDetected :: TestTree
diff --git a/test/psx-test-no-psx.hsc b/test/psx-test-no-psx.hsc
--- a/test/psx-test-no-psx.hsc
+++ b/test/psx-test-no-psx.hsc
@@ -1,3 +1,5 @@
+{-# LANGUAGE CApiFFI #-}
+
 module Main (main) where
 
 #include "hs-psx.h"
@@ -25,10 +27,10 @@
     peek _ = error "peek not implemented"
     poke _ _ = error "poke not implemented"
 
-foreign import ccall unsafe "signal.h sigfillset"
+foreign import capi unsafe "signal.h sigfillset"
     sigfillset :: Ptr SigsetT -> IO #{type int}
 
-foreign import ccall unsafe "signal.h sigismember"
+foreign import capi unsafe "signal.h sigismember"
     sigismember :: Ptr SigsetT -> #{type int} -> IO #{type int}
 
 sigfillsetNotWrapped :: IO ()
@@ -38,7 +40,7 @@
     isMember @?= 1
 
 
-foreign import ccall unsafe "detect-psx.h detect_psx"
+foreign import capi unsafe "detect-psx.h detect_psx"
     detectPsx :: IO #{type int}
 
 psxNotDetected :: IO ()
diff --git a/test/psx-test-threaded.hs b/test/psx-test-threaded.hs
--- a/test/psx-test-threaded.hs
+++ b/test/psx-test-threaded.hs
@@ -1,14 +1,16 @@
 module Main (main) where
 
 import Test.Tasty (defaultMain, testGroup)
-
 import qualified TestCases as T
 
 main :: IO ()
-main = defaultMain $ testGroup "Tests" [
-      T.sigfillsetWrapped
-    , T.psxDetected
-    , T.psxSyscall3Works
-    , T.psxSyscall6Works
-    , T.psxWorking
-    ]
+main =
+  defaultMain $
+    testGroup
+      "Tests"
+      [ T.sigfillsetWrapped,
+        T.psxDetected,
+        T.psxSyscall3Works,
+        T.psxSyscall6Works,
+        T.psxWorking
+      ]
diff --git a/test/psx-test.hs b/test/psx-test.hs
--- a/test/psx-test.hs
+++ b/test/psx-test.hs
@@ -1,14 +1,15 @@
 module Main (main) where
 
 import Test.Tasty (defaultMain, testGroup)
-
 import qualified TestCases as T
 
 main :: IO ()
-main = defaultMain $ testGroup "Tests" [
-      T.sigfillsetWrapped
-    , T.psxDetected
-    , T.psxSyscall3Works
-    , T.psxSyscall6Works
-    ]
-
+main =
+  defaultMain $
+    testGroup
+      "Tests"
+      [ T.sigfillsetWrapped,
+        T.psxDetected,
+        T.psxSyscall3Works,
+        T.psxSyscall6Works
+      ]
