• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TEN-framework / ten-framework / 22560854307

02 Mar 2026 04:02AM UTC coverage: 58.73%. First build
22560854307

Pull #2076

github

web-flow
Merge 15635a6ff into 1bc81a4e8
Pull Request #2076: feat: quick start demo on windows

0 of 128 new or added lines in 6 files covered. (0.0%)

53171 of 90534 relevant lines covered (58.73%)

761343.4 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/core/src/ten_manager/src/check_env/check_cpp.rs
1
//
2
// Copyright © 2025 Agora
3
// This file is part of TEN Framework, an open source project.
4
// Licensed under the Apache License, Version 2.0, with certain conditions.
5
// Refer to the "LICENSE" file in the root directory for more information.
6
//
7
use anyhow::Result;
8

9
use super::types::{CheckStatus, CppCheckResult, Suggestion, ToolInfo};
10

11
/// Check C++ development environment (tgn, gcc/g++/clang toolchain).
12
/// Returns structured result about C++ tools.
13
pub fn check() -> Result<CppCheckResult> {
×
14
    let mut compilers = Vec::new();
×
15
    let mut tgn_installed = false;
×
16
    let mut has_compiler = false;
×
17
    let mut suggestions = Vec::new();
×
18

19
    // Check tgn
20
    let tgn_check = std::process::Command::new("tgn").arg("--help").output();
×
21

22
    let tgn_info = match tgn_check {
×
23
        Ok(output) if output.status.success() => {
×
24
            // Find tgn path
NEW
25
            let path = if cfg!(windows) {
×
NEW
26
                std::process::Command::new("where.exe").arg("tgn").output().ok()
×
NEW
27
                    .and_then(|output| {
×
NEW
28
                        if output.status.success() {
×
NEW
29
                            Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
×
30
                        } else {
NEW
31
                            None
×
32
                        }
NEW
33
                    })
×
34
            } else {
NEW
35
                std::process::Command::new("which").arg("tgn").output().ok()
×
NEW
36
                    .and_then(|output| {
×
NEW
37
                        if output.status.success() {
×
NEW
38
                            Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
×
39
                        } else {
NEW
40
                            None
×
41
                        }
NEW
42
                    })
×
43
            };
44

45
            tgn_installed = true;
×
46
            Some(ToolInfo {
×
47
                name: "tgn".to_string(),
×
48
                version: None,
×
49
                path,
×
50
                status: CheckStatus::Ok,
×
51
                notes: vec![],
×
52
            })
×
53
        }
54
        _ => {
55
            suggestions.push(Suggestion {
×
56
                issue: "tgn not installed".to_string(),
×
57
                command: Some(
×
58
                    "curl -fsSL https://raw.githubusercontent.com/TEN-framework/ten-framework/main/tools/tgn/install_tgn.sh | bash".to_string(),
×
59
                ),
×
60
                help_text: Some("To develop C++ extensions, please install tgn".to_string()),
×
61
            });
×
62
            Some(ToolInfo {
×
63
                name: "tgn".to_string(),
×
64
                version: None,
×
65
                path: None,
×
66
                status: CheckStatus::Error,
×
67
                notes: vec!["Not installed".to_string()],
×
68
            })
×
69
        }
70
    };
71

72
    // Check C++ compiler based on OS
73
    let os = std::env::consts::OS;
×
74

75
    if os == "linux" {
×
76
        // Check gcc on Linux
77
        let gcc_check = std::process::Command::new("gcc").arg("--version").output();
×
78

79
        match gcc_check {
×
80
            Ok(output) if output.status.success() => {
×
81
                let version_str = String::from_utf8_lossy(&output.stdout);
×
82
                // Extract version (first line usually contains version info)
83
                if let Some(first_line) = version_str.lines().next() {
×
84
                    // Parse version number (e.g., "gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0")
85
                    let version = first_line.split_whitespace().last().map(|s| s.to_string());
×
86

87
                    let which_output = std::process::Command::new("which").arg("gcc").output().ok();
×
88
                    let path = if let Some(output) = which_output {
×
89
                        Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
×
90
                    } else {
91
                        None
×
92
                    };
93

94
                    compilers.push(ToolInfo {
×
95
                        name: "gcc".to_string(),
×
96
                        version,
×
97
                        path,
×
98
                        status: CheckStatus::Ok,
×
99
                        notes: vec![],
×
100
                    });
×
101
                    has_compiler = true;
×
102
                }
×
103
            }
104
            _ => {
×
105
                compilers.push(ToolInfo {
×
106
                    name: "gcc".to_string(),
×
107
                    version: None,
×
108
                    path: None,
×
109
                    status: CheckStatus::Error,
×
110
                    notes: vec!["Not found".to_string()],
×
111
                });
×
112
            }
×
113
        }
114

115
        // Check g++ on Linux
116
        let gpp_check = std::process::Command::new("g++").arg("--version").output();
×
117

118
        match gpp_check {
×
119
            Ok(output) if output.status.success() => {
×
120
                let version_str = String::from_utf8_lossy(&output.stdout);
×
121
                if let Some(first_line) = version_str.lines().next() {
×
122
                    let version = first_line.split_whitespace().last().map(|s| s.to_string());
×
123

124
                    let which_output = std::process::Command::new("which").arg("g++").output().ok();
×
125
                    let path = if let Some(output) = which_output {
×
126
                        Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
×
127
                    } else {
128
                        None
×
129
                    };
130

131
                    compilers.push(ToolInfo {
×
132
                        name: "g++".to_string(),
×
133
                        version,
×
134
                        path,
×
135
                        status: CheckStatus::Ok,
×
136
                        notes: vec![],
×
137
                    });
×
138
                    has_compiler = true;
×
139
                }
×
140
            }
141
            _ => {
×
142
                compilers.push(ToolInfo {
×
143
                    name: "g++".to_string(),
×
144
                    version: None,
×
145
                    path: None,
×
146
                    status: CheckStatus::Error,
×
147
                    notes: vec!["Not found".to_string()],
×
148
                });
×
149
            }
×
150
        }
151

152
        if !has_compiler {
×
153
            suggestions.push(Suggestion {
×
154
                issue: "gcc/g++ not found".to_string(),
×
155
                command: Some("sudo apt-get install gcc g++".to_string()),
×
156
                help_text: Some("To install gcc/g++".to_string()),
×
157
            });
×
158
        }
×
159
    } else if os == "macos" {
×
160
        // Check clang on macOS
161
        let clang_check = std::process::Command::new("clang").arg("--version").output();
×
162

163
        match clang_check {
×
164
            Ok(output) if output.status.success() => {
×
165
                let version_str = String::from_utf8_lossy(&output.stdout);
×
166
                // Extract version (format: "Apple clang version 14.0.0 ..." or "clang version
167
                // 15.0.0")
168
                if let Some(first_line) = version_str.lines().next() {
×
169
                    let version = if first_line.contains("Apple clang") {
×
170
                        first_line.split_whitespace().nth(3).map(|v| format!("{} (Apple clang)", v))
×
171
                    } else {
172
                        first_line.split_whitespace().nth(2).map(|s| s.to_string())
×
173
                    };
174

175
                    let which_output =
×
176
                        std::process::Command::new("which").arg("clang").output().ok();
×
177
                    let path = if let Some(output) = which_output {
×
178
                        Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
×
179
                    } else {
180
                        None
×
181
                    };
182

183
                    compilers.push(ToolInfo {
×
184
                        name: "clang".to_string(),
×
185
                        version,
×
186
                        path,
×
187
                        status: CheckStatus::Ok,
×
188
                        notes: vec![],
×
189
                    });
×
190
                    has_compiler = true;
×
191
                }
×
192
            }
193
            _ => {
×
194
                compilers.push(ToolInfo {
×
195
                    name: "clang".to_string(),
×
196
                    version: None,
×
197
                    path: None,
×
198
                    status: CheckStatus::Error,
×
199
                    notes: vec!["Not found".to_string()],
×
200
                });
×
201
            }
×
202
        }
203

204
        // Check clang++ on macOS
205
        let clangpp_check = std::process::Command::new("clang++").arg("--version").output();
×
206

207
        match clangpp_check {
×
208
            Ok(output) if output.status.success() => {
×
209
                let version_str = String::from_utf8_lossy(&output.stdout);
×
210
                if let Some(first_line) = version_str.lines().next() {
×
211
                    let version = if first_line.contains("Apple clang") {
×
212
                        first_line.split_whitespace().nth(3).map(|v| format!("{} (Apple clang)", v))
×
213
                    } else {
214
                        first_line.split_whitespace().nth(2).map(|s| s.to_string())
×
215
                    };
216

217
                    let which_output =
×
218
                        std::process::Command::new("which").arg("clang++").output().ok();
×
219
                    let path = if let Some(output) = which_output {
×
220
                        Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
×
221
                    } else {
222
                        None
×
223
                    };
224

225
                    compilers.push(ToolInfo {
×
226
                        name: "clang++".to_string(),
×
227
                        version,
×
228
                        path,
×
229
                        status: CheckStatus::Ok,
×
230
                        notes: vec![],
×
231
                    });
×
232
                    has_compiler = true;
×
233
                }
×
234
            }
235
            _ => {
×
236
                compilers.push(ToolInfo {
×
237
                    name: "clang++".to_string(),
×
238
                    version: None,
×
239
                    path: None,
×
240
                    status: CheckStatus::Error,
×
241
                    notes: vec!["Not found".to_string()],
×
242
                });
×
243
            }
×
244
        }
245

246
        if !has_compiler {
×
247
            suggestions.push(Suggestion {
×
248
                issue: "clang/clang++ not found".to_string(),
×
249
                command: Some("xcode-select --install".to_string()),
×
250
                help_text: Some("To install Xcode Command Line Tools".to_string()),
×
251
            });
×
252
        }
×
NEW
253
    } else if os == "windows" {
×
254
        // Check MSVC compiler on Windows
NEW
255
        let msvc_check = std::process::Command::new("cl.exe").arg("/?").output();
×
256

NEW
257
        match msvc_check {
×
NEW
258
            Ok(output) if output.status.success() => {
×
NEW
259
                let version_str = String::from_utf8_lossy(&output.stdout);
×
260
                // Extract version from MSVC output
NEW
261
                let version = version_str.lines().next().map(|s| s.to_string());
×
262

NEW
263
                let where_output = std::process::Command::new("where.exe").arg("cl.exe").output().ok();
×
NEW
264
                let path = if let Some(output) = where_output {
×
NEW
265
                    Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
×
266
                } else {
NEW
267
                    None
×
268
                };
269

NEW
270
                compilers.push(ToolInfo {
×
NEW
271
                    name: "cl.exe (MSVC)".to_string(),
×
NEW
272
                    version,
×
NEW
273
                    path,
×
NEW
274
                    status: CheckStatus::Ok,
×
NEW
275
                    notes: vec![],
×
NEW
276
                });
×
NEW
277
                has_compiler = true;
×
278
            }
NEW
279
            _ => {
×
NEW
280
                compilers.push(ToolInfo {
×
NEW
281
                    name: "cl.exe (MSVC)".to_string(),
×
NEW
282
                    version: None,
×
NEW
283
                    path: None,
×
NEW
284
                    status: CheckStatus::Error,
×
NEW
285
                    notes: vec!["Not found".to_string()],
×
NEW
286
                });
×
NEW
287
            }
×
288
        }
289

NEW
290
        if !has_compiler {
×
NEW
291
            suggestions.push(Suggestion {
×
NEW
292
                issue: "MSVC compiler not found".to_string(),
×
NEW
293
                command: Some("Install Visual Studio with C++ build tools".to_string()),
×
NEW
294
                help_text: Some("Please install Visual Studio with C++ development tools".to_string()),
×
NEW
295
            });
×
NEW
296
        }
×
297
    }
×
298

299
    // Determine overall status
300
    let status = if tgn_installed && has_compiler {
×
301
        CheckStatus::Ok
×
302
    } else if !tgn_installed && !has_compiler {
×
303
        CheckStatus::Error
×
304
    } else {
305
        CheckStatus::Warning
×
306
    };
307

308
    Ok(CppCheckResult {
×
309
        tgn: tgn_info,
×
310
        compilers,
×
311
        tgn_installed,
×
312
        has_compiler,
×
313
        status,
×
314
        suggestions,
×
315
    })
×
316
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc