| 99f1a2e | | | 1 | # syntax=docker/dockerfile:1 |
| 99f1a2e | | | 2 | # Grove: EdenFS Docker Build |
| 99f1a2e | | | 3 | # |
| 99f1a2e | | | 4 | # Build: cd /build/sapling && docker build -f /build/grove/docker/Dockerfile.edenfs -t grove/edenfs . |
| 99f1a2e | | | 5 | # (context must be the sapling/ directory) |
| 99f1a2e | | | 6 | # |
| 2d46ffc | | | 7 | # Requires grove/sapling-deps:latest to be built first (shared C++ deps). |
| 2d46ffc | | | 8 | # EdenFS is a C++/Rust hybrid (CMake build, not pure Cargo like Mononoke). |
| 818dc90 | | | 9 | |
| 99f1a2e | | | 10 | # ============================================================================= |
| 2d46ffc | | | 11 | # Stage 1: Build EdenFS (C++ deps from shared base image) |
| 99f1a2e | | | 12 | # ============================================================================= |
| 2d46ffc | | | 13 | FROM grove/sapling-deps:latest AS builder |
| 99f1a2e | | | 14 | |
| 4dfd09b | | | 15 | # Copy full source tree. |
| 99f1a2e | | | 16 | COPY . /build |
| 99f1a2e | | | 17 | |
| 2d46ffc | | | 18 | # Fix shipit mismatches: the Facebook->OSS export renames/strips some files |
| 818dc90 | | | 19 | # but doesn't update CMakeLists.txt references. |
| 4dfd09b | | | 20 | RUN ln -sf sl eden/fs/store/hg && \ |
| 4dfd09b | | | 21 | touch eden/fs/inodes/InodeNumber.cpp eden/fs/service/PrettyPrinters.cpp && \ |
| 4dfd09b | | | 22 | sed -i '/add_subdirectory(eden\/integration)/d; /add_subdirectory(eden\/test_support)/d' CMakeLists.txt && \ |
| 36387cc | | | 23 | sed -i '/add_subdirectory(cli_rs\/edenfsctl)/d' eden/fs/CMakeLists.txt && \ |
| 679ea08 | | | 24 | cp eden/scm/lib/backingstore/include/ffi.h eden/scm/lib/backingstore/ && \ |
| 5adbed7 | | | 25 | ln -sf include/SaplingBackingStoreError.h eden/scm/lib/backingstore/SaplingBackingStoreError.h && \ |
| 679ea08 | | | 26 | cp eden/scm/lib/edenfs_ffi/include/ffi.h eden/scm/lib/edenfs_ffi/ && \ |
| 4dfd09b | | | 27 | sed -i '/edencommon::edencommon_utils/a\ backingstore' eden/fs/utils/CMakeLists.txt && \ |
| 8dd15af | | | 28 | sed -i '/file(GLOB PRIVHELPER_SRCS/a file(GLOB PRIORITY_SRCS "priority/ProcessPriority.cpp" "priority/LinuxMemoryPriority.cpp")\nlist(APPEND PRIVHELPER_SRCS ${PRIORITY_SRCS})' eden/fs/privhelper/CMakeLists.txt && \ |
| 36387cc | | | 29 | sed -i '/edencommon::edencommon_os/a\ cpptoml' eden/scm/lib/backingstore/CMakeLists.txt && \ |
| 6e37760 | | | 30 | sed -i 's/^name = "sapling-backingstore"/name = "backingstore"/' eden/scm/lib/backingstore/Cargo.toml && \ |
| 6e37760 | | | 31 | sed -i 's/^name = "sapling-edenfs_ffi"/name = "edenfs_ffi"/' eden/scm/lib/edenfs_ffi/Cargo.toml && \ |
| 0950470 | | | 32 | sed -i 's/sapling-backingstore/backingstore/g' eden/scm/lib/backingstore/benches/Cargo.toml && \ |
| 0950470 | | | 33 | rm -f eden/scm/Cargo.lock && \ |
| 4dfd09b | | | 34 | sed -i 's/"specialization", //' eden/scm/lib/backingstore/Cargo.toml && \ |
| b0e115a | | | 35 | sed -i 's/^sapling-workingcopy = { version = "0.1.0", path = "..\/workingcopy", optional = true }/workingcopy = { package = "sapling-workingcopy", version = "0.1.0", path = "..\/workingcopy" }/' eden/scm/lib/repo/Cargo.toml && \ |
| 2b7f0d9 | | | 36 | sed -i 's/^wdir = .*/wdir = []/' eden/scm/lib/repo/Cargo.toml && \ |
| 2b7f0d9 | | | 37 | sed -i 's/sapling-repo = { version = "0.1.0", path = "..\/repo" }/sapling-repo = { version = "0.1.0", path = "..\/repo", features = ["wdir"] }/' eden/scm/lib/backingstore/Cargo.toml |
| 4dfd09b | | | 38 | |
| e9b6528 | | | 39 | # Remove Meta-only OBC dependencies from OSS EdenFS sources. |
| e9b6528 | | | 40 | RUN <<'PATCH_OBC' |
| e9b6528 | | | 41 | python3 - <<'PY' |
| e9b6528 | | | 42 | from pathlib import Path |
| e9b6528 | | | 43 | |
| e9b6528 | | | 44 | |
| e9b6528 | | | 45 | def replace_exact(path: str, old: str, new: str) -> None: |
| e9b6528 | | | 46 | p = Path(path) |
| e9b6528 | | | 47 | s = p.read_text() |
| e9b6528 | | | 48 | if old not in s: |
| e9b6528 | | | 49 | raise SystemExit(f"pattern not found in {path}: {old[:80]!r}") |
| e9b6528 | | | 50 | p.write_text(s.replace(old, new)) |
| e9b6528 | | | 51 | |
| e9b6528 | | | 52 | |
| e9b6528 | | | 53 | # eden/fs/service: remove OBCAvg header and concrete metric type |
| e9b6528 | | | 54 | replace_exact( |
| e9b6528 | | | 55 | "eden/fs/service/EdenServer.h", |
| e9b6528 | | | 56 | '#include "monitoring/obc/OBCAvg.h"\n', |
| e9b6528 | | | 57 | "", |
| e9b6528 | | | 58 | ) |
| e9b6528 | | | 59 | replace_exact( |
| e9b6528 | | | 60 | "eden/fs/service/EdenServer.h", |
| e9b6528 | | | 61 | "#include <chrono>\n", |
| e9b6528 | | | 62 | "#include <chrono>\n#include <cstdint>\n", |
| e9b6528 | | | 63 | ) |
| e9b6528 | | | 64 | replace_exact( |
| e9b6528 | | | 65 | "eden/fs/service/EdenServer.h", |
| e9b6528 | | | 66 | " monitoring::OBCAvg memory_vm_rss_bytes_;\n", |
| e9b6528 | | | 67 | " uint64_t memory_vm_rss_bytes_{0};\n", |
| e9b6528 | | | 68 | ) |
| e9b6528 | | | 69 | replace_exact( |
| e9b6528 | | | 70 | "eden/fs/service/EdenServer.cpp", |
| e9b6528 | | | 71 | """ if (config->enableOBCOnEden.getValue()) { |
| e9b6528 | | | 72 | // Get the hostname without the ".facebook.com" suffix |
| e9b6528 | | | 73 | auto hostname = facebook::network::getLocalHost(/*stripFbDomain=*/true); |
| e9b6528 | | | 74 | std::vector<std::string> entities; |
| e9b6528 | | | 75 | auto reWorkerID = std::getenv("REMOTE_EXECUTION_WORKER"); |
| e9b6528 | | | 76 | if (reWorkerID == nullptr) { |
| e9b6528 | | | 77 | entities = {hostname}; |
| e9b6528 | | | 78 | } else { |
| e9b6528 | | | 79 | entities = {hostname, fmt::format("{}:{}", hostname, reWorkerID)}; |
| e9b6528 | | | 80 | } |
| e9b6528 | | | 81 | memory_vm_rss_bytes_ = monitoring::OBCAvg( |
| e9b6528 | | | 82 | monitoring::OdsCategoryId::ODS_EDEN, |
| e9b6528 | | | 83 | fmt::format("eden.{}", kMemoryVmRssBytes), |
| e9b6528 | | | 84 | entities); |
| e9b6528 | | | 85 | // Report memory usage stats once every 60 seconds |
| e9b6528 | | | 86 | memoryStatsTask_.updateInterval(60s); |
| e9b6528 | | | 87 | } |
| e9b6528 | | | 88 | """, |
| e9b6528 | | | 89 | """ if (config->enableOBCOnEden.getValue()) { |
| e9b6528 | | | 90 | // OBC is Meta-internal; preserve memory stats reporting cadence in OSS. |
| e9b6528 | | | 91 | memoryStatsTask_.updateInterval(60s); |
| e9b6528 | | | 92 | } |
| e9b6528 | | | 93 | """, |
| e9b6528 | | | 94 | ) |
| e9b6528 | | | 95 | |
| e9b6528 | | | 96 | # eden/fs/store/sl: remove OBCPxx header and concrete metric types |
| e9b6528 | | | 97 | replace_exact( |
| e9b6528 | | | 98 | "eden/fs/store/sl/SaplingBackingStore.h", |
| e9b6528 | | | 99 | '#include "monitoring/obc/OBCPxx.h"\n', |
| e9b6528 | | | 100 | "", |
| e9b6528 | | | 101 | ) |
| e9b6528 | | | 102 | replace_exact( |
| e9b6528 | | | 103 | "eden/fs/store/sl/SaplingBackingStore.h", |
| e9b6528 | | | 104 | "#include <atomic>\n", |
| e9b6528 | | | 105 | "#include <atomic>\n#include <cstdint>\n", |
| e9b6528 | | | 106 | ) |
| e9b6528 | | | 107 | replace_exact( |
| e9b6528 | | | 108 | "eden/fs/store/sl/SaplingBackingStore.h", |
| e9b6528 | | | 109 | " monitoring::OBCP99P95P50 getBlobPerRepoLatencies_; // calculates p50, p95, p99\n", |
| e9b6528 | | | 110 | " uint64_t getBlobPerRepoLatencies_{0}; // OSS fallback counter\n", |
| e9b6528 | | | 111 | ) |
| e9b6528 | | | 112 | replace_exact( |
| e9b6528 | | | 113 | "eden/fs/store/sl/SaplingBackingStore.h", |
| e9b6528 | | | 114 | " monitoring::OBCP99P95P50 getTreePerRepoLatencies_; // calculates p50, p95, p99\n", |
| e9b6528 | | | 115 | " uint64_t getTreePerRepoLatencies_{0}; // OSS fallback counter\n", |
| e9b6528 | | | 116 | ) |
| e9b6528 | | | 117 | replace_exact( |
| e9b6528 | | | 118 | "eden/fs/store/sl/SaplingBackingStore.cpp", |
| e9b6528 | | | 119 | """void SaplingBackingStore::initializeOBCCounters() { |
| e9b6528 | | | 120 | // Get the hostname without the ".facebook.com" suffix |
| e9b6528 | | | 121 | auto hostname = facebook::network::getLocalHost(/*stripFbDomain=*/true); |
| e9b6528 | | | 122 | getBlobPerRepoLatencies_ = monitoring::OBCP99P95P50( |
| e9b6528 | | | 123 | monitoring::OdsCategoryId::ODS_EDEN, |
| e9b6528 | | | 124 | fmt::format("eden.store.sapling.fetch_blob_{}_us", repoName_), |
| e9b6528 | | | 125 | {hostname}); |
| e9b6528 | | | 126 | getTreePerRepoLatencies_ = monitoring::OBCP99P95P50( |
| e9b6528 | | | 127 | monitoring::OdsCategoryId::ODS_EDEN, |
| e9b6528 | | | 128 | fmt::format("eden.store.sapling.fetch_tree_{}_us", repoName_), |
| e9b6528 | | | 129 | {hostname}); |
| e9b6528 | | | 130 | isOBCEnabled_ = true; |
| e9b6528 | | | 131 | } |
| e9b6528 | | | 132 | """, |
| e9b6528 | | | 133 | """void SaplingBackingStore::initializeOBCCounters() { |
| e9b6528 | | | 134 | isOBCEnabled_ = true; |
| e9b6528 | | | 135 | } |
| e9b6528 | | | 136 | """, |
| e9b6528 | | | 137 | ) |
| e9b6528 | | | 138 | PY |
| e9b6528 | | | 139 | PATCH_OBC |
| e9b6528 | | | 140 | |
| 679ea08 | | | 141 | # Additional OSS-only source patching: |
| 679ea08 | | | 142 | # - Disable redirect_ffi CXX bridge usage (lib.rs.h is not generated in CMake build) |
| 679ea08 | | | 143 | # - Avoid duplicate class definitions from copied backingstore headers |
| 679ea08 | | | 144 | RUN <<'PATCH_OSS' |
| 679ea08 | | | 145 | python3 - <<'PY' |
| 679ea08 | | | 146 | from pathlib import Path |
| 679ea08 | | | 147 | |
| 679ea08 | | | 148 | |
| 679ea08 | | | 149 | def replace_exact(path: str, old: str, new: str) -> None: |
| 679ea08 | | | 150 | p = Path(path) |
| 679ea08 | | | 151 | s = p.read_text() |
| 679ea08 | | | 152 | if old not in s: |
| 679ea08 | | | 153 | raise SystemExit(f"pattern not found in {path}: {old[:80]!r}") |
| 679ea08 | | | 154 | p.write_text(s.replace(old, new)) |
| 679ea08 | | | 155 | |
| 679ea08 | | | 156 | |
| 679ea08 | | | 157 | replace_exact( |
| 679ea08 | | | 158 | "eden/fs/service/EdenServiceHandler.cpp", |
| 679ea08 | | | 159 | '#include "eden/fs/rust/redirect_ffi/include/ffi.h"\n', |
| 679ea08 | | | 160 | "", |
| 679ea08 | | | 161 | ) |
| 679ea08 | | | 162 | replace_exact( |
| 679ea08 | | | 163 | "eden/fs/service/EdenServiceHandler.cpp", |
| 679ea08 | | | 164 | '#include "eden/fs/rust/redirect_ffi/src/lib.rs.h"\n', |
| 679ea08 | | | 165 | "", |
| 679ea08 | | | 166 | ) |
| 679ea08 | | | 167 | replace_exact( |
| 679ea08 | | | 168 | "eden/fs/service/EdenServiceHandler.cpp", |
| 679ea08 | | | 169 | """void EdenServiceHandler::listRedirections( |
| 679ea08 | | | 170 | ListRedirectionsResponse& response, |
| 679ea08 | | | 171 | std::unique_ptr<ListRedirectionsRequest> request) { |
| 679ea08 | | | 172 | auto mountId = request->mount(); |
| 679ea08 | | | 173 | auto helper = INSTRUMENT_THRIFT_CALL(DBG3, *mountId); |
| 679ea08 | | | 174 | |
| 679ea08 | | | 175 | const auto& configDir = server_->getEdenDir(); |
| 679ea08 | | | 176 | const auto& edenEtcDir = |
| 679ea08 | | | 177 | server_->getServerState()->getEdenConfig()->getSystemConfigDir(); |
| 679ea08 | | | 178 | |
| 679ea08 | | | 179 | auto redirsFFI = list_redirections( |
| 679ea08 | | | 180 | absolutePathFromThrift(*mountId->mountPoint()).stringWithoutUNC(), |
| 679ea08 | | | 181 | configDir.stringWithoutUNC(), |
| 679ea08 | | | 182 | edenEtcDir.stringWithoutUNC()); |
| 679ea08 | | | 183 | |
| 679ea08 | | | 184 | std::vector<Redirection> redirs(redirsFFI.size()); |
| 679ea08 | | | 185 | std::transform( |
| 679ea08 | | | 186 | redirsFFI.begin(), redirsFFI.end(), redirs.begin(), [](auto&& redirFFI) { |
| 679ea08 | | | 187 | return redirectionFromFFI(std::move(redirFFI)); |
| 679ea08 | | | 188 | }); |
| 679ea08 | | | 189 | |
| 679ea08 | | | 190 | response.redirections() = std::move(redirs); |
| 679ea08 | | | 191 | } |
| 679ea08 | | | 192 | """, |
| 679ea08 | | | 193 | """void EdenServiceHandler::listRedirections( |
| 679ea08 | | | 194 | ListRedirectionsResponse& response, |
| 679ea08 | | | 195 | std::unique_ptr<ListRedirectionsRequest> request) { |
| 679ea08 | | | 196 | auto mountId = request->mount(); |
| 679ea08 | | | 197 | auto helper = INSTRUMENT_THRIFT_CALL(DBG3, *mountId); |
| 679ea08 | | | 198 | (void)request; |
| 679ea08 | | | 199 | response.redirections() = std::vector<Redirection>{}; |
| 679ea08 | | | 200 | } |
| 679ea08 | | | 201 | """, |
| 679ea08 | | | 202 | ) |
| 0315de8 | | | 203 | replace_exact( |
| 0315de8 | | | 204 | "eden/fs/store/ObjectStore.cpp", |
| 0315de8 | | | 205 | " co_return std::move(result.blob);\n", |
| 0315de8 | | | 206 | " std::shared_ptr<const Blob> blob = result.blob.get();\n" |
| 0315de8 | | | 207 | " co_return blob;\n", |
| 0315de8 | | | 208 | ) |
| 679ea08 | | | 209 | PY |
| 679ea08 | | | 210 | PATCH_OSS |
| 679ea08 | | | 211 | |
| e33d237 | | | 212 | # Fix ambiguous Cargo.toml deps (both path and git specified — shipit bug) |
| e33d237 | | | 213 | RUN <<'FIX_CARGO' |
| e33d237 | | | 214 | python3 -c " |
| e33d237 | | | 215 | import re, glob |
| e33d237 | | | 216 | for f in glob.glob('eden/fs/cli_rs/*/Cargo.toml'): |
| e33d237 | | | 217 | with open(f) as fh: c = fh.read() |
| e33d237 | | | 218 | c = re.sub(r', git = \"[^\"]+\", branch = \"[^\"]+\"', '', c) |
| e33d237 | | | 219 | with open(f, 'w') as fh: fh.write(c) |
| e33d237 | | | 220 | " |
| e33d237 | | | 221 | FIX_CARGO |
| e33d237 | | | 222 | |
| 4dfd09b | | | 223 | # Create minimal iobuf stub crate — wraps folly::IOBuf for the CXX bridge. |
| 4dfd09b | | | 224 | # The real iobuf crate is Meta-internal; this stub provides just enough for |
| 4dfd09b | | | 225 | # the backingstore FFI to compile. folly::IOBuf is available from the C++ deps. |
| 4dfd09b | | | 226 | RUN mkdir -p eden/scm/lib/iobuf/src |
| 4dfd09b | | | 227 | RUN <<'IOBUF_CARGO' |
| 4dfd09b | | | 228 | cat > eden/scm/lib/iobuf/Cargo.toml << 'INNER' |
| 4dfd09b | | | 229 | [package] |
| 4dfd09b | | | 230 | name = "iobuf" |
| 4dfd09b | | | 231 | version = "0.1.0" |
| 4dfd09b | | | 232 | edition = "2021" |
| 4dfd09b | | | 233 | |
| 4dfd09b | | | 234 | [dependencies] |
| 4dfd09b | | | 235 | cxx = "1.0.119" |
| 4dfd09b | | | 236 | INNER |
| 4dfd09b | | | 237 | IOBUF_CARGO |
| 4dfd09b | | | 238 | RUN <<'IOBUF_RS' |
| 4dfd09b | | | 239 | cat > eden/scm/lib/iobuf/src/lib.rs << 'INNER' |
| 0b1c50f | | | 240 | use std::fmt; |
| 0b1c50f | | | 241 | |
| e33d237 | | | 242 | #[cxx::bridge(namespace = "folly")] |
| e33d237 | | | 243 | mod ffi { |
| e33d237 | | | 244 | unsafe extern "C++" { |
| e33d237 | | | 245 | type IOBuf; |
| e33d237 | | | 246 | } |
| e33d237 | | | 247 | impl UniquePtr<IOBuf> {} |
| 0b1c50f | | | 248 | } |
| 0b1c50f | | | 249 | |
| e33d237 | | | 250 | pub use ffi::IOBuf; |
| 4dfd09b | | | 251 | |
| 0b1c50f | | | 252 | #[derive(Clone)] |
| 4dfd09b | | | 253 | pub struct IOBufShared { |
| 4dfd09b | | | 254 | data: Vec<u8>, |
| 4dfd09b | | | 255 | } |
| 4dfd09b | | | 256 | |
| 0b1c50f | | | 257 | impl fmt::Debug for IOBufShared { |
| 0b1c50f | | | 258 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 0b1c50f | | | 259 | f.debug_struct("IOBufShared").field("len", &self.data.len()).finish() |
| 0b1c50f | | | 260 | } |
| 0b1c50f | | | 261 | } |
| 0b1c50f | | | 262 | |
| 4dfd09b | | | 263 | impl IOBufShared { |
| 4dfd09b | | | 264 | pub unsafe fn from_owner<T: AsRef<[u8]>>(owner: T) -> Self { |
| 4dfd09b | | | 265 | Self { data: owner.as_ref().to_vec() } |
| 4dfd09b | | | 266 | } |
| 4dfd09b | | | 267 | pub fn append_to_end(&mut self, other: IOBufShared) { |
| 4dfd09b | | | 268 | self.data.extend_from_slice(&other.data); |
| 4dfd09b | | | 269 | } |
| 4dfd09b | | | 270 | pub fn len(&self) -> usize { self.data.len() } |
| 4dfd09b | | | 271 | pub fn is_empty(&self) -> bool { self.data.is_empty() } |
| 4dfd09b | | | 272 | } |
| 4dfd09b | | | 273 | |
| 4dfd09b | | | 274 | impl From<&str> for IOBufShared { |
| 4dfd09b | | | 275 | fn from(s: &str) -> Self { Self { data: s.as_bytes().to_vec() } } |
| 4dfd09b | | | 276 | } |
| 4dfd09b | | | 277 | |
| 4dfd09b | | | 278 | impl From<IOBufShared> for Vec<u8> { |
| 4dfd09b | | | 279 | fn from(buf: IOBufShared) -> Vec<u8> { buf.data } |
| 4dfd09b | | | 280 | } |
| 4dfd09b | | | 281 | |
| 4dfd09b | | | 282 | impl PartialEq for IOBufShared { |
| 4dfd09b | | | 283 | fn eq(&self, other: &Self) -> bool { self.data == other.data } |
| 4dfd09b | | | 284 | } |
| 4dfd09b | | | 285 | INNER |
| 4dfd09b | | | 286 | IOBUF_RS |
| 0b1c50f | | | 287 | # Add iobuf to workspace + deps, and patch source for OSS compatibility. |
| 0b1c50f | | | 288 | RUN <<'PATCH_SCRIPT' |
| 0b1c50f | | | 289 | #!/bin/bash |
| 0b1c50f | | | 290 | set -e |
| 0b1c50f | | | 291 | |
| 0b1c50f | | | 292 | # Add iobuf to workspace members |
| 0b1c50f | | | 293 | sed -i '/"lib\/identity",/a\ "lib/iobuf",' eden/scm/Cargo.toml |
| 0b1c50f | | | 294 | |
| 0b1c50f | | | 295 | # Add iobuf dep to backingstore |
| 0b1c50f | | | 296 | sed -i '/^cxx = /a iobuf = { version = "0.1.0", path = "../iobuf" }' eden/scm/lib/backingstore/Cargo.toml |
| 0b1c50f | | | 297 | |
| 0b1c50f | | | 298 | # Add iobuf dep to blob |
| 0b1c50f | | | 299 | sed -i '/^sha1 = /a iobuf = { version = "0.1.0", path = "../iobuf" }' eden/scm/lib/blob/Cargo.toml |
| 0b1c50f | | | 300 | |
| 0b1c50f | | | 301 | # Patch ffi.rs: add impl UniquePtr<IOBuf> {}, add make_iobuf_from_bytes fn, |
| 0b1c50f | | | 302 | # replace into_iobuf().into() calls |
| 0b1c50f | | | 303 | python3 -c " |
| 0b1c50f | | | 304 | import re |
| 0b1c50f | | | 305 | with open('eden/scm/lib/backingstore/src/ffi.rs', 'r') as f: |
| 0b1c50f | | | 306 | content = f.read() |
| 0b1c50f | | | 307 | |
| e33d237 | | | 308 | # Add make_iobuf_from_bytes fn to the extern C++ block containing IOBuf |
| 0b1c50f | | | 309 | content = content.replace( |
| 0b1c50f | | | 310 | 'type IOBuf = iobuf::IOBuf;', |
| e33d237 | | | 311 | 'type IOBuf = iobuf::IOBuf;\n fn make_iobuf_from_bytes(data: &[u8]) -> UniquePtr<IOBuf>;' |
| 0b1c50f | | | 312 | ) |
| 0b1c50f | | | 313 | |
| 0b1c50f | | | 314 | # Replace blob.into_iobuf().into() with our helper |
| 0b1c50f | | | 315 | content = content.replace( |
| 0b1c50f | | | 316 | 'blob.into_iobuf().into()', |
| 0b1c50f | | | 317 | 'ffi::make_iobuf_from_bytes(&blob.into_vec())' |
| 0b1c50f | | | 318 | ) |
| 0b1c50f | | | 319 | |
| 0b1c50f | | | 320 | with open('eden/scm/lib/backingstore/src/ffi.rs', 'w') as f: |
| 0b1c50f | | | 321 | f.write(content) |
| 0b1c50f | | | 322 | " |
| 0b1c50f | | | 323 | |
| 0b1c50f | | | 324 | # Add C++ helper to create IOBuf from bytes |
| 0b1c50f | | | 325 | cat >> eden/scm/lib/backingstore/include/ffi.h << 'CPP_EOF' |
| 0b1c50f | | | 326 | |
| 0b1c50f | | | 327 | #include <folly/io/IOBuf.h> |
| 0b1c50f | | | 328 | namespace sapling { |
| 0b1c50f | | | 329 | inline std::unique_ptr<folly::IOBuf> make_iobuf_from_bytes( |
| 0b1c50f | | | 330 | rust::Slice<const uint8_t> data) { |
| 0b1c50f | | | 331 | return folly::IOBuf::copyBuffer(data.data(), data.length()); |
| 0b1c50f | | | 332 | } |
| 0b1c50f | | | 333 | } // namespace sapling |
| 0b1c50f | | | 334 | CPP_EOF |
| 0b1c50f | | | 335 | PATCH_SCRIPT |
| 4dfd09b | | | 336 | |
| 4dfd09b | | | 337 | # Build EdenFS using getdeps. Unlike Mononoke (pure Cargo), EdenFS uses CMake |
| 2d46ffc | | | 338 | # which needs proper workspace resolution for the Rust FFI crates. |
| 99f1a2e | | | 339 | RUN --mount=type=cache,target=/root/.cargo/registry \ |
| 99f1a2e | | | 340 | python3 build/fbcode_builder/getdeps.py --allow-system-packages \ |
| 99f1a2e | | | 341 | build --no-deps --build-type MinSizeRel --no-tests --src-dir=. eden \ |
| 99f1a2e | | | 342 | --project-install-prefix eden:/ |
| 99f1a2e | | | 343 | |
| 99f1a2e | | | 344 | # Collect artifacts with dynamic library fixups |
| 99f1a2e | | | 345 | RUN python3 build/fbcode_builder/getdeps.py --allow-system-packages \ |
| 99f1a2e | | | 346 | fixup-dyn-deps --strip --src-dir=. eden \ |
| 99f1a2e | | | 347 | /artifacts --project-install-prefix eden:/ \ |
| 99f1a2e | | | 348 | --final-install-prefix /usr/local |
| 99f1a2e | | | 349 | |
| 99f1a2e | | | 350 | # ============================================================================= |
| 2d46ffc | | | 351 | # Stage 2: Minimal runtime image |
| 99f1a2e | | | 352 | # ============================================================================= |
| 99f1a2e | | | 353 | FROM ubuntu:22.04 AS runtime |
| 99f1a2e | | | 354 | |
| 99f1a2e | | | 355 | RUN apt-get update && apt-get install -y \ |
| 99f1a2e | | | 356 | ca-certificates \ |
| 99f1a2e | | | 357 | git \ |
| 99f1a2e | | | 358 | libssl3 \ |
| 99f1a2e | | | 359 | zlib1g \ |
| 99f1a2e | | | 360 | libzstd1 \ |
| 99f1a2e | | | 361 | liblz4-1 \ |
| 99f1a2e | | | 362 | libsnappy1v5 \ |
| 99f1a2e | | | 363 | libsodium23 \ |
| 99f1a2e | | | 364 | libevent-2.1-7 \ |
| 99f1a2e | | | 365 | libdouble-conversion3 \ |
| 99f1a2e | | | 366 | libgflags2.2 \ |
| 99f1a2e | | | 367 | libgoogle-glog0v5 \ |
| 99f1a2e | | | 368 | libunwind8 \ |
| 99f1a2e | | | 369 | libdwarf1 \ |
| 99f1a2e | | | 370 | libfuse2 \ |
| 99f1a2e | | | 371 | libre2-9 \ |
| 99f1a2e | | | 372 | libgit2-1.1 \ |
| 99f1a2e | | | 373 | liblmdb0 \ |
| 99f1a2e | | | 374 | libsqlite3-0 \ |
| 99f1a2e | | | 375 | libcurl4 \ |
| 99f1a2e | | | 376 | python3 \ |
| 99f1a2e | | | 377 | && rm -rf /var/lib/apt/lists/* |
| 99f1a2e | | | 378 | |
| 99f1a2e | | | 379 | # Copy built artifacts (fixup-dyn-deps puts binaries in /artifacts/bin/) |
| 99f1a2e | | | 380 | COPY --from=builder /artifacts/bin /usr/local/bin |
| 99f1a2e | | | 381 | |
| 99f1a2e | | | 382 | # Create data directories |
| 99f1a2e | | | 383 | RUN mkdir -p /data/eden /config /certs |
| 99f1a2e | | | 384 | |
| 99f1a2e | | | 385 | # EdenFS uses FUSE on Linux — needs /dev/fuse access at runtime |
| 99f1a2e | | | 386 | # (requires --privileged or --device /dev/fuse when running the container) |
| 99f1a2e | | | 387 | |
| 99f1a2e | | | 388 | # edenfs daemon port (thrift) |
| 99f1a2e | | | 389 | EXPOSE 8400 |
| 99f1a2e | | | 390 | |
| 99f1a2e | | | 391 | # Default entrypoint runs the edenfs daemon |
| 99f1a2e | | | 392 | ENTRYPOINT ["/usr/local/bin/edenfs"] |
| 99f1a2e | | | 393 | CMD ["--edenDir", "/data/eden", \ |
| 99f1a2e | | | 394 | "--etcEdenDir", "/config", \ |
| 99f1a2e | | | 395 | "--configPath", "/config/edenfs.toml", \ |
| 99f1a2e | | | 396 | "--foreground"] |