Skip to content

Commit b0bf15a

Browse files
cakeljaewookilee
andauthored
fix: cargo install --git 빌드 실패 해결 (web/dist 없을 때) (#104)
* fix: web/dist 없을 때 cargo install --git 빌드 실패 해결 web-ui 기능이 release 빌드 시 web/dist/ (gitignore된 pnpm build 산출물) 를 rust-embed 로 요구해, cargo install --git 사용자가 RustEmbed 'folder does not exist' 로 항상 컴파일 실패하던 문제. crates/secall-core/build.rs 추가: - dist 없으면 안내용 placeholder index.html 생성 → 컴파일 유지 (CLI/MCP/REST 정상, 웹 UI 자리에 빌드 안내 페이지) - dist 있으면 그대로 사용 (early-return, 덮어쓰지 않음) - web/dist/index.html 에 rerun-if-changed → dist staleness 회귀 해소 Node 불필요. 웹 UI 불필요 시 --no-default-features 로 설치 가능. * fix: build.rs 에서 CARGO_MANIFEST_DIR 를 var_os 로 읽기 비-UTF-8 경로에서도 OsStr 그대로 Path 생성하도록 견고화 (Gemini 리뷰 반영). --------- Co-authored-by: jaewooki.lee <jaewooki.lee@lge.com>
1 parent 01ec87f commit b0bf15a

2 files changed

Lines changed: 91 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
> NOTE: v0.3.x ~ v0.4.x 의 상세 변경 이력은 `README.md` 의 "버전 히스토리" 표 참고. CHANGELOG.md 는 v0.2.x 시점에서 README 로 SSOT 이전됨.
44
5+
## Unreleased
6+
7+
### 🐛 Fixes
8+
9+
- **`cargo install --git` 빌드 실패 해결** (web-ui default): `web-ui` 기능이 release 빌드 시점에 `web/dist/` (gitignore 된 `pnpm build` 산출물) 를 `rust-embed` 로 요구하는데, `cargo install --git ...` 사용자는 `pnpm build` 를 거치지 않아 `RustEmbed` derive 가 `folder ... does not exist` 로 항상 컴파일 실패하던 문제. `crates/secall-core/build.rs` 추가 — dist 가 없으면 안내용 placeholder `index.html` 을 생성해 컴파일을 살리고(웹 UI 자리에 빌드 안내 페이지 표시, CLI·MCP·REST API 는 정상), dist 가 있으면 그대로 사용한다. 더불어 `web/dist/index.html``cargo:rerun-if-changed` 를 걸어 dist 갱신 후 옛 번들이 embed 되던 staleness 회귀도 함께 해소. Node 불필요. (웹 UI 가 필요 없으면 종전처럼 `--no-default-features` 로 설치 가능)
10+
11+
---
12+
513
## v0.6.2 (2026-06-01)
614

715
검색 품질 개선 + 내부 의존 방향 정리.

crates/secall-core/build.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//! 빌드 스크립트 — `web-ui` 기능의 정적 자산 임베드를 견고하게 만든다.
2+
//!
3+
//! `src/web/embed.rs` 의 `#[derive(RustEmbed)] #[folder = "../../web/dist/"]` 는
4+
//! release 빌드 시점에 `web/dist/` 폴더가 **반드시 존재**해야 컴파일된다.
5+
//! `web/dist/` 는 `pnpm build` 산출물이라 `.gitignore` 대상이고 git 에 포함되지
6+
//! 않으므로, 외부 사용자가 `cargo install --git ...` 로 받으면 폴더가 없어
7+
//! `RustEmbed` derive 가 컴파일 에러를 낸다.
8+
//!
9+
//! 이 스크립트는 두 가지를 보장한다:
10+
//! 1. `web/dist/index.html` 변경 시 cargo 가 rebuild 하도록 추적한다.
11+
//! (dist 갱신 후 `cargo install` 만 돌리면 옛 번들이 embed 되던 회귀 방지)
12+
//! 2. `web/dist/` 가 없으면 안내용 placeholder 를 만들어 컴파일이 깨지지 않게
13+
//! 한다. CLI · MCP · REST API 는 그대로 동작하고, 웹 UI 자리에는 빌드 방법을
14+
//! 안내하는 페이지가 표시된다.
15+
16+
use std::path::Path;
17+
18+
fn main() {
19+
// `web-ui` 기능이 꺼져 있으면 embed 자체가 컴파일되지 않으므로 할 일이 없다.
20+
// cargo 는 활성 기능마다 `CARGO_FEATURE_<NAME>` (대문자, `-`→`_`) 을 설정한다.
21+
if std::env::var_os("CARGO_FEATURE_WEB_UI").is_none() {
22+
return;
23+
}
24+
25+
let manifest_dir = std::env::var_os("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
26+
// embed.rs 의 `#[folder = "../../web/dist/"]` 와 동일한 위치.
27+
let dist_dir = Path::new(&manifest_dir).join("../../web/dist");
28+
let index_html = dist_dir.join("index.html");
29+
30+
// dist 가 바뀌면 (특히 index.html) cargo 가 재컴파일하도록 추적한다.
31+
println!("cargo:rerun-if-changed={}", index_html.display());
32+
33+
if index_html.exists() {
34+
// 정상 경로: CI / `just build` / `pnpm build` 로 만들어진 실제 번들이 있다.
35+
return;
36+
}
37+
38+
// dist 가 없다 — placeholder 를 만들어 컴파일을 살린다.
39+
if let Err(e) = std::fs::create_dir_all(&dist_dir) {
40+
// 디렉터리조차 못 만들면 RustEmbed 가 명확히 에러를 내도록 그냥 둔다.
41+
println!("cargo:warning=secall: web/dist 생성 실패 ({e}). 웹 UI 없이 빌드하려면 --no-default-features 를 사용하세요.");
42+
return;
43+
}
44+
45+
if let Err(e) = std::fs::write(&index_html, PLACEHOLDER_INDEX_HTML) {
46+
println!("cargo:warning=secall: placeholder index.html 작성 실패 ({e}).");
47+
return;
48+
}
49+
50+
println!(
51+
"cargo:warning=secall: web/dist 가 없어 placeholder 웹 UI 로 빌드합니다. \
52+
실제 웹 UI 를 쓰려면 `cd web && pnpm install && pnpm build` 후 다시 빌드하거나, \
53+
웹 UI 가 필요 없으면 `--no-default-features` 로 설치하세요."
54+
);
55+
}
56+
57+
/// dist 가 없을 때 임베드되는 안내 페이지.
58+
const PLACEHOLDER_INDEX_HTML: &str = r#"<!doctype html>
59+
<html lang="ko">
60+
<head>
61+
<meta charset="utf-8">
62+
<meta name="viewport" content="width=device-width, initial-scale=1">
63+
<title>seCall — web UI not built</title>
64+
<style>
65+
body { font-family: system-ui, sans-serif; max-width: 42rem; margin: 4rem auto; padding: 0 1.5rem; line-height: 1.6; color: #1a1a1a; }
66+
code { background: #f0f0f0; padding: .15em .4em; border-radius: 4px; }
67+
pre { background: #f6f8fa; padding: 1rem; border-radius: 8px; overflow-x: auto; }
68+
h1 { font-size: 1.4rem; }
69+
.muted { color: #666; }
70+
</style>
71+
</head>
72+
<body>
73+
<h1>seCall web UI is not built</h1>
74+
<p>This binary was compiled without a pre-built <code>web/dist/</code> bundle, so the web UI is a placeholder. The REST API, MCP server, and CLI all work normally.</p>
75+
<p>To get the full web UI, build the frontend and reinstall:</p>
76+
<pre>cd web
77+
pnpm install
78+
pnpm build
79+
# then rebuild/reinstall secall</pre>
80+
<p class="muted">If you don't need the web UI, install with <code>--no-default-features</code> to skip it entirely.</p>
81+
</body>
82+
</html>
83+
"#;

0 commit comments

Comments
 (0)