Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
5c0477c
ensure obelisk-asset-th-generate makes name based on source static dir
augyg Feb 25, 2025
5554cdd
make static.out a String constant
augyg Feb 25, 2025
589f62d
findProjectAssets returns Map of isDrv by path
augyg Feb 26, 2025
a4d20eb
add way to recover packageName arg of processAssets
augyg Feb 27, 2025
e58a489
make staticFilesImpure and processedStatic attr sets of each static dir
augyg Feb 27, 2025
63efb3a
use path attr instead of src
augyg Feb 28, 2025
0f32877
findProjectAssets returns StaticInfos
augyg Feb 28, 2025
bbe9bcc
watch multiple static dirs for file changes
augyg Feb 28, 2025
080b7db
update obelisk-asset-th-generate to differentiate filepaths by static…
augyg Mar 3, 2025
e00a236
staticFiles.<attr> -> processAssets staticName arg
augyg Mar 3, 2025
f1daba5
creation of symlinks for multiple statics at static.out/<name>
augyg Mar 3, 2025
4cdf89e
update command to deal with multiple static directories + static.out …
augyg Mar 3, 2025
87aefe5
update symlinking on serverExe for multiple statics
augyg Mar 3, 2025
31c82d1
fix nix eval typo
augyg Mar 4, 2025
dcfac93
update skeleton/default.nix for explicit static
augyg Mar 4, 2025
ed485a4
dont use static pkg name in \!OBELISK_ASSET_PASSTHRU
augyg Mar 4, 2025
d235e52
temporarily set attr of android for testing
augyg Mar 12, 2025
81ff52f
temp fix to use staticAssets name, statically
augyg Mar 12, 2025
f062eaf
Allow 3rd party cookies on android
augyg Mar 18, 2025
6edfa9f
Show route encoder error
augyg Sep 23, 2025
ba1c889
render route on encoder error + start at Login
augyg Sep 27, 2025
9540968
Update reflex-platform: use buildIcons
augyg Sep 28, 2025
9be402f
update NA
augyg Oct 1, 2025
47a5481
SQUASH: add plan for strip llvm
augyg Oct 1, 2025
947c928
SQUASH: add plan for strip llvm
augyg Oct 1, 2025
29fb272
Update reflex-platform : optimized android builds
augyg Oct 2, 2025
d30188b
filter out non-hashed staticAssets to massively reduce .aab size
augyg Oct 2, 2025
3dba9f2
+ injectMany for use with android inject configs
augyg Oct 4, 2025
88a471e
undo reflex-platform optimizations
augyg Oct 5, 2025
90a4ff1
use injectMany on ios
augyg Oct 5, 2025
b78c6a1
use injectMany on ios
augyg Oct 5, 2025
dab138d
use injectMany on ios
augyg Oct 5, 2025
75bb39e
correct attribute of ios options
augyg Oct 5, 2025
6740124
add page size arg (const set to 16384) to sed of ghc-options in impl.…
augyg Oct 13, 2025
bb1f18c
add alexfmpe's libffi override to reflex-platform/default.nix
augyg Oct 22, 2025
507c61d
use PackageImports to disambiguate TemplateHaskell
augyg Dec 23, 2025
b02db43
use PackageImports to disambiguate TemplateHaskell
augyg Dec 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 73 additions & 30 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,24 @@ in rec {
'';
nullIfAbsent = p: if lib.pathExists p then p else null;
#TODO: Avoid copying files within the nix store. Right now, obelisk-asset-manifest-generate copies files into a big blob so that the android/ios static assets can be imported from there; instead, we should get everything lined up right before turning it into an APK, so that copies, if necessary, only exist temporarily.
processAssets = { src, packageName ? "obelisk-generated-static", moduleName ? "Obelisk.Generated.Static", exe ? "obelisk-asset-th-generate" }: pkgs.runCommand "asset-manifest" {
inherit src;
outputs = [ "out" "haskellManifest" "symlinked" ];
nativeBuildInputs = [ ghcObelisk.obelisk-asset-manifest ];
} ''
set -euo pipefail
touch "$out"
mkdir -p "$symlinked"
${exe} "$src" "$haskellManifest" ${packageName} ${moduleName} "$symlinked"
'';
processAssets =
{ src
, packageName ? "obelisk-generated-static"
, moduleName ? "Obelisk.Generated.Static"
#, staticFunctionName ? packageName
, staticPath ? "static"
, staticName ? "static"
, exe ? "obelisk-asset-th-generate"
}: pkgs.runCommand "asset-manifest" {
inherit src;
outputs = [ "out" "haskellManifest" "symlinked" ];
nativeBuildInputs = [ ghcObelisk.obelisk-asset-manifest ];
} ''
set -euo pipefail
touch "$out"
mkdir -p "$symlinked"
${exe} "$src" "$haskellManifest" ${packageName} ${moduleName} "$symlinked" ${staticName}
'' // {inherit packageName;};

compressedJs = frontend: optimizationLevel: externs: pkgs.runCommand "compressedJs" {} ''
set -euo pipefail
Expand Down Expand Up @@ -213,12 +221,16 @@ in rec {
exeBackend = if profiling then backend else haskellLib.justStaticExecutables backend;
exeFrontend = compressedJs frontend optimizationLevel externjs;
exeFrontendAssets = mkAssets exeFrontend;
exeAssets = mkAssets assets;
exeAssets = lib.mapAttrs (n: args: mkAssets (if args.isDrv then (import args.path args.drvArgs) else args.path)) assets;
in pkgs.runCommand "serverExe" {} ''
mkdir $out
set -eux
ln -s '${exeBackend}'/bin/* $out/
ln -s '${exeAssets}' $out/static.assets
mkdir $out/static.assets
${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: assets: ''
ln -s '${assets}' $out/static.assets/${name}
'') exeAssets)}

for d in '${exeFrontendAssets}'/*/; do
ln -s "$d" "$out"/"$(basename "$d").assets"
done
Expand Down Expand Up @@ -270,19 +282,48 @@ in rec {
inherit args;
userSettings = {
inherit android ios packages overrides tools shellToolOverrides withHoogle externjs __closureCompilerOptimizationLevel __withGhcide __deprecated;
staticFiles = if staticFiles == null then self.base + /static else staticFiles;
staticFiles =
if staticFiles == null
then { static = { path = self.base + /static; isDrv = false; drvArgs = null; moduleName = "Obelisk.Generated.Static"; }; }
else staticFiles;
};
frontendName = "frontend";
backendName = "backend";
commonName = "common";
staticName = "obelisk-generated-static";
staticFilesImpure = let fs = self.userSettings.staticFiles; in if lib.isDerivation fs then fs else toString fs;
processedStatic = processAssets {
src = self.userSettings.staticFiles;
exe = if lib.attrByPath ["userSettings" "__deprecated" "useObeliskAssetManifestGenerate"] false self
then builtins.trace "obelisk-asset-manifest-generate is deprecated. Use obelisk-asset-th-generate instead." "obelisk-asset-manifest-generate"
else "obelisk-asset-th-generate";
};
#staticName = "obelisk-generated-static";
staticFilesImpure =
let fs = self.userSettings.staticFiles;
in lib.mapAttrs (_: staticArgs:
# path attr just allows us to watch for file changes
if staticArgs.isDrv
then { path = staticArgs.path; src = import staticArgs.path staticArgs.drvArgs; }
else { path = staticArgs.path; src = toString staticArgs.path; }
) fs;
processedStatic =
let processAssets' =
{ path
, drvArgs
, isDrv
, staticName
, packageName
, moduleName ? "Obelisk.Generated.Static"
, mobile ? true
}@staticDrvArgs: processAssets {
src = if isDrv then (import path drvArgs) else path;
staticName = staticName;
packageName = packageName;
moduleName = moduleName;
exe = if lib.attrByPath ["userSettings" "__deprecated" "useObeliskAssetManifestGenerate"] false self
then builtins.trace "obelisk-asset-manifest-generate is deprecated. Use obelisk-asset-th-generate instead." "obelisk-asset-manifest-generate"
else "obelisk-asset-th-generate";
} // { inherit mobile; };
in
lib.mapAttrs
(name: staticArgs: processAssets'
(staticArgs
// { packageName = name; staticName = name; }
))
self.userSettings.staticFiles;
# The packages whose names and roles are defined by this package
predefinedPackages = lib.filterAttrs (_: x: x != null) {
${self.frontendName} = nullIfAbsent (self.base + "/frontend");
Expand All @@ -291,10 +332,12 @@ in rec {
};
shellPackages = {};
combinedPackages = self.predefinedPackages // self.userSettings.packages // self.shellPackages;
projectOverrides = self': super': {
${self.staticName} = haskellLib.dontHaddock (self'.callCabal2nix self.staticName self.processedStatic.haskellManifest {});
projectOverrides = self': super': ({
${self.backendName} = haskellLib.addBuildDepend super'.${self.backendName} self'.obelisk-run;
};
} // (
# unique name | <<- unique packageName <<- unique module name, in order to depend on all of them together in one pkgset
lib.mapAttrs (pkgName: assets: self'.callCabal2nix pkgName assets.haskellManifest {}) self.processedStatic
));
totalOverrides = lib.composeExtensions self.projectOverrides self.userSettings.overrides;
privateConfigDirs = ["config/backend"];
injectableConfig = builtins.filterSource (path: _:
Expand All @@ -303,19 +346,19 @@ in rec {
__androidWithConfig = configPath: {
${if self.userSettings.android == null then null else self.frontendName} = {
executableName = "frontend";
${if builtins.pathExists self.userSettings.staticFiles then "assets" else null} =
nixpkgs.obeliskExecutableConfig.platforms.android.inject
"assets" = #${if builtins.pathExists self.userSettings.staticFiles.staticAssets then "assets" else null} =
nixpkgs.obeliskExecutableConfig.platforms.android.injectMany
(self.injectableConfig configPath)
self.processedStatic.symlinked;
(lib.filterAttrs (name: static: static.mobile) self.processedStatic); #.staticAssets.symlinked;
} // self.userSettings.android;
};
__iosWithConfig = configPath: {
${if self.userSettings.ios == null then null else self.frontendName} = {
executableName = "frontend";
${if builtins.pathExists self.userSettings.staticFiles then "staticSrc" else null} =
nixpkgs.obeliskExecutableConfig.platforms.ios.inject
"staticSrc" =
nixpkgs.obeliskExecutableConfig.platforms.ios.injectMany
(self.injectableConfig configPath)
self.processedStatic.symlinked;
(lib.filterAttrs (name: static: static.mobile) self.processedStatic);
} // self.userSettings.ios;
};

Expand Down
8 changes: 4 additions & 4 deletions dep/reflex-platform/github.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"owner": "reflex-frp",
"owner": "Ace-Interview-Prep",
"repo": "reflex-platform",
"branch": "release/1.2.0.0",
"branch": "gs/optimize-android-builds",
"private": false,
"rev": "f231e2425ac92339b8491cdd970930d63d9ad1ad",
"sha256": "0b042x423p04shhidni08f47ydgpfj0rpqhb0m6gj2lg8b3s9l8k"
"rev": "ec391db332f6533dae6fa9c209891c5880ad7743",
"sha256": "1rim6qvnlwq4k34lbk3w73zfghfdlzh7jwh5lylsk4rr16yz2af2"
}
13 changes: 7 additions & 6 deletions lib/asset/manifest/src-bin/static-th.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import System.FilePath
main :: IO ()
main = do
--TODO: Usage
[root, haskellTarget, packageName, moduleName, fileTarget] <- getArgs
[root, haskellTarget, packageName, moduleName, fileTarget, staticAttrName] <- getArgs
paths <- gatherHashedPaths root
writeCabalProject haskellTarget $ SimplePkg
{ _simplePkg_name = T.pack packageName
Expand All @@ -20,6 +20,7 @@ main = do
]
, _simplePkg_moduleContents = T.pack $ unlines
[ "{-# Language CPP #-}"
, "{-# Language PackageImports #-}"
, "{-|"
, " Description:"
, " Automatically generated module that provides the 'static' TH function"
Expand All @@ -28,15 +29,15 @@ main = do
, "module " <> moduleName <> " ( static, staticFilePath ) where"
, ""
, "import Obelisk.Asset.TH"
, "import Language.Haskell.TH"
, "import \"template-haskell\" Language.Haskell.TH"
, ""
, "static, staticFilePath :: FilePath -> Q Exp"
, "#ifdef OBELISK_ASSET_PASSTHRU"
, "static = staticAssetRaw"
, "staticFilePath = staticAssetFilePathRaw \"static.out\""
, "static = staticAssetRaw" <> " " <> show staticAttrName
, "staticFilePath = staticAssetFilePathRaw \"static.out\"" <> " " <> show staticAttrName
, "#else"
, "static = staticAssetHashed " <> show root
, "staticFilePath = staticAssetFilePath " <> show root
, "static = staticAssetHashed " <> show root <> " " <> show staticAttrName
, "staticFilePath = staticAssetFilePath " <> show root
, "#endif"
]
}
Expand Down
30 changes: 19 additions & 11 deletions lib/asset/manifest/src/Obelisk/Asset/TH.hs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ staticOutPath = "static.out"
--
-- If the filepath can not be found in the static output directory,
-- this will throw a compile-time error.
staticAssetRaw :: FilePath -> Q Exp
staticAssetRaw = staticAssetWorker staticPrefix staticOutPath
staticAssetRaw :: FilePath -> FilePath -> Q Exp
staticAssetRaw staticName fp = staticAssetWorker staticPrefix staticOutPath staticName fp

staticAssetHashed :: FilePath -> FilePath -> Q Exp
staticAssetHashed root fp = do
LitE . StringL . (staticPrefix </>) <$> hashedAssetFilePath root fp
-- | Generate URL to reference handler which will serve this asset path
-- | where "/static" route maps to the base directory static.assets
staticAssetHashed :: FilePath -> FilePath -> FilePath -> Q Exp
staticAssetHashed root staticPkgName fp = do
LitE . StringL . (\p -> staticPrefix </> staticPkgName </> p) <$> hashedAssetFilePath root fp

-- | Embed a filepath via template haskell. Differently to 'staticAssetRaw'
-- this points to a local filepath instead of an URL during deployment.
Expand All @@ -57,10 +59,13 @@ staticAssetFilePathRaw
:: FilePath
-- ^ Add this prefix directory to the embedded filepath @fp@.
-> FilePath
-- ^ Static Project specific prefix to avoid collisions
-> FilePath
-- ^ Filepath you want to embed.
-> Q Exp
staticAssetFilePathRaw root = staticAssetWorker root staticOutPath
staticAssetFilePathRaw root staticName = staticAssetWorker root staticOutPath staticName

-- | Return the real location of 'relativePath'
staticAssetFilePath :: FilePath -> FilePath -> Q Exp
staticAssetFilePath root relativePath = do
let fullPath = root </> relativePath
Expand All @@ -77,13 +82,16 @@ staticAssetWorker
:: FilePath
-- ^ Add this prefix directory to the embedded filepath @fp@.
-> FilePath
-- ^ Directory to which the filepath must have been copied.
-- ^ Base Directory to which the filepath must have been copied.
-- If @fp@ does not exist within this directory, this function will fail.
-> FilePath
-- ^ Static Project Directory to which the filepath must have been copied.
-- If @fp@ does not exist within this directory, this function will fail.
-> FilePath
-- ^ Filepath you want to embed.
-> Q Exp
staticAssetWorker root staticOut fp = do
exists <- runIO $ doesFileExist $ staticOut </> fp
staticAssetWorker root staticOut staticName fp = do
exists <- runIO $ doesFileExist $ staticOut </> staticName </> fp
when (not exists) $
fail $ "The file " <> fp <> " was not found in " <> staticOut
return $ LitE $ StringL $ root </> fp
fail $ "The file " <> fp <> " was not found in " <> staticOut </> staticName
return $ LitE $ StringL $ root </> staticName </> fp
Loading