Skip to content

Commit 4758882

Browse files
committed
Fix cross-compilation compatibility and ob-run reliability
The cabal.project used a flat package list that included packages with build-type: Custom depending on obelisk-setup. When the WASM/GHCJS cross-compiler's cabal resolved the project, it could not find obelisk-setup (only available in the native ghc-pkg), causing cross-builds to fail. Move backend, frontend/js, frontend/wasm, and static/generated/custom behind an `if !(arch(javascript) || arch(wasm32))` conditional so the cross-compiler's cabal never attempts to resolve their setup-depends. Add obelisk-setup as a build-depends of obelisk-generated-static-custom so it appears in ghc-pkg for native cabal's setup-depends resolution. Guard frontendDataOverride and backendDataOverride with mkOptionalPackages so they are silently skipped in cross projects where those packages do not exist, fixing an infinite recursion during nix evaluation of projectCross. Fix ob-run's `cabal list-bin` returning the wrong path under -O0 by emitting cabal-level optimization flags (-O0) instead of --ghc-options=-O0, and passing only optimization flags (not the full extraFlags with --ghc-options) to list-bin/assembleAndLinkFrontend/ linkFrontendAssets. Fix ob-run EXIT trap to also kill inotifywait and read processes. Remove unused dependencies (directory from frontend, filepath from backend library).
1 parent 7b47a17 commit 4758882

File tree

14 files changed

+102
-61
lines changed

14 files changed

+102
-61
lines changed

lib/setup/src/Obelisk/Setup/Frontend/Js.hs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ main :: IO ()
2626
main = defaultMainWithHooks simpleUserHooks
2727
{ buildHook = \pd lbi hooks flags -> do
2828
envArgs <- crossCabalArgs
29-
let extraFlags = optLevelFlags (withOptimization lbi) <> envArgs
29+
let optFlags = optLevelFlags (withOptimization lbi)
30+
extraFlags = optFlags <> envArgs
3031
resultVar <- newEmptyMVar :: IO (MVar (Either SomeException ()))
3132
_ <- forkIO $ do
3233
result <- try (buildFrontendWithGhcjs extraFlags)
@@ -40,7 +41,7 @@ main = defaultMainWithHooks simpleUserHooks
4041
exitFailure
4142
Right () -> do
4243
hPutStrLn stderr "[Setup] GHCJS frontend build complete."
43-
linkFrontendAssets
44+
linkFrontendAssets optFlags
4445
}
4546

4647
findGhcjsCabal :: IO (String, [String] -> [String])
@@ -73,8 +74,8 @@ buildFrontendWithGhcjs extraFlags = do
7374
hPutStrLn stderr "[Setup] Building frontend with GHCJS..."
7475
callInRoot ghcjsCabal (mkArgs (["build", "exe:frontend", "--builddir=" <> distJs] <> extraFlags))
7576

76-
linkFrontendAssets :: IO ()
77-
linkFrontendAssets = do
77+
linkFrontendAssets :: [String] -> IO ()
78+
linkFrontendAssets extraFlags = do
7879
projectRoot <- findProjectRoot
7980
(ghcjsCabal, mkArgs) <- findGhcjsCabal
8081
let dataDir = projectRoot </> "frontend" </> "data"
@@ -84,7 +85,7 @@ linkFrontendAssets = do
8485

8586
let inRoot cmd args = (proc cmd args) { cwd = Just projectRoot }
8687

87-
binPathRaw <- readCreateProcess (inRoot ghcjsCabal (mkArgs ["list-bin", "frontend", "--builddir=" <> distJs])) ""
88+
binPathRaw <- readCreateProcess (inRoot ghcjsCabal (mkArgs (["list-bin", "frontend", "--builddir=" <> distJs] <> extraFlags))) ""
8889
let binPath = strip binPathRaw
8990
jsexeDir = binPath <> ".jsexe"
9091

lib/setup/src/Obelisk/Setup/Frontend/Wasm.hs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ main :: IO ()
3131
main = defaultMainWithHooks simpleUserHooks
3232
{ buildHook = \pd lbi hooks flags -> do
3333
envArgs <- crossCabalArgs
34-
let extraFlags = optLevelFlags (withOptimization lbi) <> envArgs
34+
let optFlags = optLevelFlags (withOptimization lbi)
35+
extraFlags = optFlags <> envArgs
3536
resultVar <- newEmptyMVar :: IO (MVar (Either SomeException ()))
3637
_ <- forkIO $ do
3738
result <- try (buildFrontendWithWasm extraFlags)
@@ -45,7 +46,7 @@ main = defaultMainWithHooks simpleUserHooks
4546
exitFailure
4647
Right () -> do
4748
hPutStrLn stderr "[Setup] WASM frontend build complete."
48-
assembleAndLinkFrontend
49+
assembleAndLinkFrontend optFlags
4950
}
5051

5152
-- | Find the wasm32 cross cabal: either the @wasm32-unknown-wasi@ wrapper
@@ -92,8 +93,8 @@ buildFrontendWithWasm extraFlags = do
9293
callInRoot wasmCabal (mkArgs (["build", "exe:frontend", "--builddir=" <> distWasm] <> extraFlags))
9394

9495
-- | Assemble the jsexe directory and symlink it into @frontend\/data\/@.
95-
assembleAndLinkFrontend :: IO ()
96-
assembleAndLinkFrontend = do
96+
assembleAndLinkFrontend :: [String] -> IO ()
97+
assembleAndLinkFrontend extraFlags = do
9798
projectRoot <- findProjectRoot
9899
(wasmCabal, mkArgs) <- findWasmCabal
99100
let distWasm = projectRoot </> "dist-wasm"
@@ -103,7 +104,7 @@ assembleAndLinkFrontend = do
103104

104105
-- Find the compiled .wasm binary
105106
binPathRaw <- readCreateProcess
106-
(inRoot wasmCabal (mkArgs ["list-bin", "frontend", "--builddir=" <> distWasm])) ""
107+
(inRoot wasmCabal (mkArgs (["list-bin", "frontend", "--builddir=" <> distWasm] <> extraFlags))) ""
107108
let wasmBin = strip binPathRaw
108109

109110
-- Create jsexe assembly directory

lib/setup/src/Obelisk/Setup/Utils.hs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,13 @@ symlink target linkName = do
5252
crossCabalArgs :: IO [String]
5353
crossCabalArgs = maybe [] words <$> lookupEnv "OBELISK_CROSS_CABAL_ARGS"
5454

55-
-- | Map a Cabal 'OptimisationLevel' to @--ghc-options@ flags for cross cabal.
55+
-- | Map a Cabal 'OptimisationLevel' to cabal-level optimization flags.
56+
-- Uses @-O@ rather than @--ghc-options=-O@ so that cabal's build directory
57+
-- layout (e.g. @noopt/@) matches the optimization level.
5658
optLevelFlags :: OptimisationLevel -> [String]
57-
optLevelFlags NoOptimisation = ["--ghc-options=-O0"]
58-
optLevelFlags NormalOptimisation = ["--ghc-options=-O1"]
59-
optLevelFlags MaximumOptimisation = ["--ghc-options=-O2"]
59+
optLevelFlags NoOptimisation = ["-O0"]
60+
optLevelFlags NormalOptimisation = ["-O1"]
61+
optLevelFlags MaximumOptimisation = ["-O2"]
6062

6163
-- | Strip leading and trailing whitespace.
6264
strip :: String -> String

nix/lib.nix

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -112,43 +112,53 @@ in rec {
112112
# at both build time (preBuild) and in the installed output (postInstall).
113113
frontendDataOverride = { static ? null, compressedStatic ? null }:
114114
({ config, lib, pkgs, ... }:
115-
let dataDir = config.packages.frontend.package.dataDir;
115+
let optional = mkOptionalPackages { inherit config lib; };
116+
dataDir = if config.packages ? frontend
117+
then config.packages.frontend.package.dataDir
118+
else "";
116119
in {
117-
packages.frontend.components.library.preBuild = lib.optionalString (dataDir != "") ''
118-
mkdir -p ${dataDir}
119-
${if static != null && static != {} then ''ln -sf ${static} ${dataDir}/static'' else ""}
120-
${if compressedStatic != null && compressedStatic != {} then ''ln -sf ${compressedStatic} ${dataDir}/static.assets'' else ""}
121-
'';
122-
packages.frontend.components.library.postInstall = ''
123-
for datadir in $data/share/*/*/frontend-*; do
124-
${if static != null && static != {} then ''ln -sf ${static} "$datadir/static"'' else ""}
125-
${if compressedStatic != null && compressedStatic != {} then ''ln -sf ${compressedStatic} "$datadir/static.assets"'' else ""}
126-
done
127-
'';
120+
packages = optional {
121+
frontend.components.library.preBuild = lib.optionalString (dataDir != "") ''
122+
mkdir -p ${dataDir}
123+
${if static != null && static != {} then ''ln -sf ${static} ${dataDir}/static'' else ""}
124+
${if compressedStatic != null && compressedStatic != {} then ''ln -sf ${compressedStatic} ${dataDir}/static.assets'' else ""}
125+
'';
126+
frontend.components.library.postInstall = ''
127+
for datadir in $data/share/*/*/frontend-*; do
128+
${if static != null && static != {} then ''ln -sf ${static} "$datadir/static"'' else ""}
129+
${if compressedStatic != null && compressedStatic != {} then ''ln -sf ${compressedStatic} "$datadir/static.assets"'' else ""}
130+
done
131+
'';
132+
};
128133
}
129134
);
130135

131136
# Symlink static assets and frontend jsexe into backend's dataDir
132137
# at both build time (preBuild) and in the installed output (postInstall).
133138
backendDataOverride = { static ? null, compressedStatic ? null, frontendJs ? null, compressedFrontendJs ? null }:
134139
({ config, lib, pkgs, ... }:
135-
let dataDir = config.packages.backend.package.dataDir;
140+
let optional = mkOptionalPackages { inherit config lib; };
141+
dataDir = if config.packages ? backend
142+
then config.packages.backend.package.dataDir
143+
else "";
136144
in {
137-
packages.backend.components.library.preBuild = lib.optionalString (dataDir != "") ''
138-
mkdir -p ${dataDir}
139-
${if static != null && static != {} then ''ln -sf ${static} ${dataDir}/static'' else ""}
140-
${if compressedStatic != null && compressedStatic != {} then ''ln -sf ${compressedStatic} ${dataDir}/static.assets'' else ""}
141-
${if frontendJs != null && frontendJs != {} then ''ln -sf ${frontendJs} ${dataDir}/frontend.jsexe'' else ""}
142-
${if compressedFrontendJs != null && compressedFrontendJs != {} then ''ln -sf ${compressedFrontendJs} ${dataDir}/frontend.jsexe.assets'' else ""}
143-
'';
144-
packages.backend.components.library.postInstall = ''
145-
for datadir in $data/share/*/*/backend-*; do
146-
${if static != null && static != {} then ''ln -sf ${static} "$datadir/static"'' else ""}
147-
${if compressedStatic != null && compressedStatic != {} then ''ln -sf ${compressedStatic} "$datadir/static.assets"'' else ""}
148-
${if frontendJs != null && frontendJs != {} then ''ln -sf ${frontendJs} "$datadir/frontend.jsexe"'' else ""}
149-
${if compressedFrontendJs != null && compressedFrontendJs != {} then ''ln -sf ${compressedFrontendJs} "$datadir/frontend.jsexe.assets"'' else ""}
150-
done
151-
'';
145+
packages = optional {
146+
backend.components.library.preBuild = lib.optionalString (dataDir != "") ''
147+
mkdir -p ${dataDir}
148+
${if static != null && static != {} then ''ln -sf ${static} ${dataDir}/static'' else ""}
149+
${if compressedStatic != null && compressedStatic != {} then ''ln -sf ${compressedStatic} ${dataDir}/static.assets'' else ""}
150+
${if frontendJs != null && frontendJs != {} then ''ln -sf ${frontendJs} ${dataDir}/frontend.jsexe'' else ""}
151+
${if compressedFrontendJs != null && compressedFrontendJs != {} then ''ln -sf ${compressedFrontendJs} ${dataDir}/frontend.jsexe.assets'' else ""}
152+
'';
153+
backend.components.library.postInstall = ''
154+
for datadir in $data/share/*/*/backend-*; do
155+
${if static != null && static != {} then ''ln -sf ${static} "$datadir/static"'' else ""}
156+
${if compressedStatic != null && compressedStatic != {} then ''ln -sf ${compressedStatic} "$datadir/static.assets"'' else ""}
157+
${if frontendJs != null && frontendJs != {} then ''ln -sf ${frontendJs} "$datadir/frontend.jsexe"'' else ""}
158+
${if compressedFrontendJs != null && compressedFrontendJs != {} then ''ln -sf ${compressedFrontendJs} "$datadir/frontend.jsexe.assets"'' else ""}
159+
done
160+
'';
161+
};
152162
}
153163
);
154164

scripts/ob-run

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@ if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
1717
exit 0
1818
fi
1919

20-
# Kill the backend process on exit.
21-
trap 'kill "$PID" 2>/dev/null' EXIT
20+
# Kill all child processes on exit.
21+
cleanup() {
22+
kill "$PID" 2>/dev/null || true
23+
kill "$INOTIFY_PID" 2>/dev/null || true
24+
kill "$READ_PID" 2>/dev/null || true
25+
}
26+
trap cleanup EXIT
2227

2328
restart() {
2429
kill "$PID" 2>/dev/null || true

skeleton/backend/backend.cabal

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ library
162162
--
163163
, directory
164164
, file-embed
165-
, filepath
166165
, obelisk-backend
167166

168167
-- Directories containing source files.

skeleton/cabal.project

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
packages:
2-
backend
32
common
43
frontend
54

65
optional-packages:
7-
frontend/js
8-
frontend/wasm
96
static/generated
10-
static/generated/custom
117

12-
optional-packages:
13-
deps/obelisk/lib/*
14-
deps/obelisk/lib/*/*
15-
16-
optional-packages:
17-
deps/obelisk/deps/reflex-dom/*
8+
if !(arch(javascript) || arch(wasm32))
9+
packages:
10+
backend
11+
12+
optional-packages:
13+
frontend/js
14+
frontend/wasm
15+
static/generated/custom
16+
17+
-- Uncomment to develop obelisk libraries and reflex-dom locally.
18+
-- Not needed for normal development; nix provides these via source-repository-packages.
19+
--optional-packages:
20+
-- deps/obelisk/lib/*
21+
-- deps/obelisk/lib/*/*
22+
--
23+
--optional-packages:
24+
-- deps/obelisk/deps/reflex-dom/*
1825

1926
multi-repl: True
2027

skeleton/frontend/frontend.cabal

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,7 @@ library
151151
if !(arch(javascript) || arch(wasm32))
152152
cpp-options: -DNOT_REPL
153153
other-modules: Paths_frontend
154-
build-depends: directory
155-
, file-embed
154+
build-depends: file-embed
156155

157156
-- Directories containing source files.
158157
hs-source-dirs: src

skeleton/frontend/js/frontend-js.cabal

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ custom-setup
4949
obelisk-setup
5050

5151
library
52-
build-depends: frontend
53-
, base
52+
build-depends: base
53+
--
54+
, frontend
5455

5556
reexported-modules: Frontend
5657

skeleton/frontend/wasm/frontend-wasm.cabal

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ custom-setup
4949
obelisk-setup
5050

5151
library
52-
build-depends: frontend
53-
, base
52+
build-depends: base
53+
--
54+
, frontend
5455

5556
reexported-modules: Frontend
5657

0 commit comments

Comments
 (0)