You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
568tools/tools/rusty-book/devtools/build-tools.html

345 lines
22 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE HTML>
<html lang="zh-CN" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>构建时工具 - Rusty Book(锈书)</title>
<!-- Custom HTML head -->
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="../favicon.svg">
<link rel="shortcut icon" href="../favicon.png">
<link rel="stylesheet" href="../css/variables.css">
<link rel="stylesheet" href="../css/general.css">
<link rel="stylesheet" href="../css/chrome.css">
<link rel="stylesheet" href="../css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="../fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="../highlight.css">
<link rel="stylesheet" href="../tomorrow-night.css">
<link rel="stylesheet" href="../ayu-highlight.css">
<!-- Custom theme stylesheets -->
<link rel="stylesheet" href="../theme/style1.css">
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "../";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded affix "><a href="../about.html">Rusty Book</a></li><li class="chapter-item expanded affix "><li class="part-title">Awesome</li><li class="spacer"></li><li class="chapter-item expanded "><a href="../daily-dev.html">日常开发常用库</a></li><li class="chapter-item expanded "><a href="../superstar.html">Rust 明星项目</a></li><li class="chapter-item expanded "><a href="../empowering-js.html">使用 Rust 增强 JS</a></li><li class="chapter-item expanded "><a href="../games.html">Rust开发的游戏</a></li><li class="chapter-item expanded "><a href="../gamedev.html">游戏引擎</a></li><li class="chapter-item expanded affix "><li class="part-title">Awesome + Cookbook</li><li class="spacer"></li><li class="chapter-item expanded "><a href="../algos/awesome.html">实用算法</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../algos/randomness.html">生成随机值</a></li><li class="chapter-item expanded "><a href="../algos/sorting.html">Vec 排序</a></li><li class="chapter-item expanded "><div>压缩算法</div><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="../algos/compression/tar.html">使用.tar包</a></li></ol></li><li class="chapter-item expanded "><div>密码学</div><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="../algos/cryptography/hashing.html">哈希</a></li><li class="chapter-item "><a href="../algos/cryptography/encryption.html">加密</a></li></ol></li><li class="chapter-item expanded "><div>数学计算</div><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="../algos/math/linear-algebra.html">线性代数</a></li><li class="chapter-item "><a href="../algos/math/trigonometry.html">三角函数</a></li><li class="chapter-item "><a href="../algos/math/complex.html">复数</a></li><li class="chapter-item "><a href="../algos/math/statistics.html">统计学</a></li><li class="chapter-item "><a href="../algos/math/misc.html">杂项</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../datastructures/awesome.html">数据结构</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../datastructures/bitfield.html">位字段</a></li></ol></li><li class="chapter-item expanded "><a href="../cmd/awesome.html">命令行</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../cmd/parsing.html">参数解析</a></li><li class="chapter-item expanded "><a href="../cmd/ansi.html">终端输出格式化</a></li></ol></li><li class="chapter-item expanded "><a href="../os/awesome.html">操作系统</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../os/processor.html">处理器</a></li><li class="chapter-item expanded "><a href="../os/command.html">调用系统命令</a></li></ol></li><li class="chapter-item expanded "><div>并发</div><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../cocurrency/threads.html">线程</a></li><li class="chapter-item expanded "><a href="../cocurrency/parallel.html">使用rayon并行处理数据</a></li></ol></li><li class="chapter-item expanded "><div>数据库</div><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../database/sqlite.html">SQLite</a></li><li class="chapter-item expanded "><a href="../database/postgres.html">Postgres</a></li></ol></li><li class="chapter-item expanded "><div>日期和时间</div><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../datetime/duration.html">时间计算和转换</a></li><li class="chapter-item expanded "><a href="../datetime/parsing.html">解析和显示</a></li></ol></li><li class="chapter-item expanded "><div>开发者工具</div><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../devtools/log.html">日志</a></li><li class="chapter-item expanded "><a href="../devtools/config-log.html">配置日志</a></li><li class="chapter-item expanded "><a href="../devtools/version.html">版本号</a></li><li class="chapter-item expanded "><a href="../devtools/build-tools.html" class="active">构建时工具</a></li></ol></li><li class="chapter-item expanded "><div>编解码</div><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../encoding/strings.html">字符编码</a></li><li class="chapter-item expanded "><a href="../encoding/csv.html">CSV</a></li><li class="chapter-item expanded "><a href="../encoding/structured.html">结构化数据</a></li></ol></li><li class="chapter-item expanded "><div>错误处理</div></li><li class="chapter-item expanded "><div>文件操作</div><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../files/read-write.html">文件读写</a></li><li class="chapter-item expanded "><a href="../files/dir.html">目录访问</a></li></ol></li><li class="chapter-item expanded "><div>内存管理</div><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../memory/global-vars.html">全局变量</a></li></ol></li><li class="chapter-item expanded "><div>网络协议</div><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../protocols/tcpip.html">TCP/IP</a></li></ol></li><li class="chapter-item expanded "><div>文本处理</div><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../text/regex.html">正则表达式</a></li><li class="chapter-item expanded "><a href="../text/string.html">字符串解析</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Rusty Book(锈书)</h1>
<div class="right-buttons">
<a href="../print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
<a href="https://github.com/studyrs/rusty-book" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
<a href="https://github.com/studyrs/rusty-book/edit/main/src/devtools/build-tools.md" title="Suggest an edit" aria-label="Suggest an edit">
<i id="git-edit-button" class="fa fa-edit"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<!-- Page table of contents -->
<div class="sidetoc"><nav class="pagetoc"></nav></div>
<main>
<h1 id="构建时工具"><a class="header" href="#构建时工具">构建时工具</a></h1>
<p>本章节的内容是关于构建工具的,如果大家没有听说过 <code>build.rs</code> 文件,强烈建议先看看<a href="https://course.rs/cargo/reference/build-script/intro.html">这里</a>了解下何为构建工具。</p>
<h3 id="编译并静态链接一个-c-库"><a class="header" href="#编译并静态链接一个-c-库">编译并静态链接一个 C 库</a></h3>
<p><a href="https://docs.rs/cc/latest/cc/">cc</a> 包能帮助我们更好地跟 C/C++/汇编进行交互:它提供了简单的 API 可以将外部的库编译成静态库( .a ),然后通过 <code>rustc</code> 进行静态链接。</p>
<p>下面的例子中,我们将在 Rust 代码中使用 C 的代码: <em>src/hello.c</em>。在开始编译 Rust 的项目代码前,<code>build.rs</code> 构建脚本将先被执行。通过 cc 包,一个静态的库可以被生成( <em>libhello.a</em> ),然后该库将被 Rust的代码所使用通过 <code>extern</code> 声明外部函数签名的方式来使用。</p>
<p>由于例子中的 C 代码很简单,因此只需要将一个文件传递给 <a href="https://docs.rs/cc/*/cc/struct.Build.html">cc::Build</a>。如果大家需要更复杂的构建,<code>cc::Build</code> 还提供了通过 <a href="https://docs.rs/cc/*/cc/struct.Build.html#method.include">include</a> 来包含路径的方式,以及额外的编译标志( <a href="https://docs.rs/cc/1.0.73/cc/struct.Build.html#method.flag">flags</a> )。</p>
<p><em>Cargo.toml</em></p>
<pre><code class="language-toml">[package]
...
build = &quot;build.rs&quot;
[build-dependencies]
cc = &quot;1&quot;
[dependencies]
error-chain = &quot;0.11&quot;
</code></pre>
<p><em>build.rs</em></p>
<pre><pre class="playground"><code class="language-rust edition2021">fn main() {
cc::Build::new()
.file(&quot;src/hello.c&quot;)
.compile(&quot;hello&quot;); // outputs `libhello.a`
}
</code></pre></pre>
<p><em>src/hello.c</em></p>
<pre><code class="language-C">#include &lt;stdio.h&gt;
void hello() {
printf(&quot;Hello from C!\n&quot;);
}
void greet(const char* name) {
printf(&quot;Hello, %s!\n&quot;, name);
}
</code></pre>
<p><em>src/main.rs</em></p>
<pre><pre class="playground"><code class="language-rust edition2021">use error_chain::error_chain;
use std::ffi::CString;
use std::os::raw::c_char;
error_chain! {
foreign_links {
NulError(::std::ffi::NulError);
Io(::std::io::Error);
}
}
fn prompt(s: &amp;str) -&gt; Result&lt;String&gt; {
use std::io::Write;
print!(&quot;{}&quot;, s);
std::io::stdout().flush()?;
let mut input = String::new();
std::io::stdin().read_line(&amp;mut input)?;
Ok(input.trim().to_string())
}
extern {
fn hello();
fn greet(name: *const c_char);
}
fn main() -&gt; Result&lt;()&gt; {
unsafe { hello() }
let name = prompt(&quot;What's your name? &quot;)?;
let c_name = CString::new(name)?;
unsafe { greet(c_name.as_ptr()) }
Ok(())
}
</code></pre></pre>
<h3 id="编译并静态链接一个-c-库-1"><a class="header" href="#编译并静态链接一个-c-库-1">编译并静态链接一个 C++ 库</a></h3>
<p>链接到 C++ 库跟之前的方式非常相似。主要的区别在于链接到 C++ 库时,你需要通过构建方法 <a href="https://docs.rs/cc/*/cc/struct.Build.html#method.cpp">cpp(true)</a> 来指定一个 C++ 编译器,然后在 C++ 的代码顶部添加 <code>extern &quot;C&quot;</code> 来阻止 C++ 编译器对库名进行名称重整( name mangling )。</p>
<p><em>Cargo.toml</em></p>
<pre><code class="language-toml">[package]
...
build = &quot;build.rs&quot;
[build-dependencies]
cc = &quot;1&quot;
</code></pre>
<p><em>build.rs</em></p>
<pre><pre class="playground"><code class="language-rust edition2021">fn main() {
cc::Build::new()
.cpp(true)
.file(&quot;src/foo.cpp&quot;)
.compile(&quot;foo&quot;);
}
</code></pre></pre>
<p><em>src/foo.cpp</em></p>
<pre><code class="language-c++">extern &quot;C&quot; {
int multiply(int x, int y);
}
int multiply(int x, int y) {
return x*y;
}
</code></pre>
<p><em>src/main.rs</em></p>
<pre><pre class="playground"><code class="language-rust edition2021">extern {
fn multiply(x : i32, y : i32) -&gt; i32;
}
fn main(){
unsafe {
println!(&quot;{}&quot;, multiply(5,7));
}
}
</code></pre></pre>
<h3 id="为-c-库创建自定义的-define"><a class="header" href="#为-c-库创建自定义的-define">为 C 库创建自定义的 define</a></h3>
<p><a href="https://docs.rs/cc/*/cc/struct.Build.html#method.define">cc::Build::define</a> 可以让我们使用自定义的 define 来构建 C 库。</p>
<p>以下示例在构建脚本 <code>build.rs</code> 中动态定义了一个 define然后在运行时打印出 <strong>Welcome to foo - version 1.0.2</strong>。Cargo 会设置一些<a href="https://doc.rust-lang.org/cargo/reference/environment-variables.html">环境变量</a>,它们对于自定义的 define 会有所帮助。</p>
<p><em>Cargo.toml</em></p>
<pre><code class="language-toml">[package]
...
version = &quot;1.0.2&quot;
build = &quot;build.rs&quot;
[build-dependencies]
cc = &quot;1&quot;
</code></pre>
<p><em>build.rs</em></p>
<pre><pre class="playground"><code class="language-rust edition2021">fn main() {
cc::Build::new()
.define(&quot;APP_NAME&quot;, &quot;\&quot;foo\&quot;&quot;)
.define(&quot;VERSION&quot;, format!(&quot;\&quot;{}\&quot;&quot;, env!(&quot;CARGO_PKG_VERSION&quot;)).as_str())
.define(&quot;WELCOME&quot;, None)
.file(&quot;src/foo.c&quot;)
.compile(&quot;foo&quot;);
}
</code></pre></pre>
<p><em>src/foo.c</em></p>
<pre><code class="language-C">#include &lt;stdio.h&gt;
void print_app_info() {
#ifdef WELCOME
printf(&quot;Welcome to &quot;);
#endif
printf(&quot;%s - version %s\n&quot;, APP_NAME, VERSION);
}
</code></pre>
<p><em>src/main.rs</em></p>
<pre><pre class="playground"><code class="language-rust edition2021">extern {
fn print_app_info();
}
fn main(){
unsafe {
print_app_info();
}
}
</code></pre></pre>
<div id="giscus-container"></div>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../devtools/version.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="../encoding/strings.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../devtools/version.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="../encoding/strings.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script type="text/javascript">
window.playground_copyable = true;
</script>
<script src="../ace.js" type="text/javascript" charset="utf-8"></script>
<script src="../editor.js" type="text/javascript" charset="utf-8"></script>
<script src="../mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="../theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="../theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="../book.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
var pagePath = "devtools/build-tools.md"
</script>
<!-- Custom JS scripts -->
<script type="text/javascript" src="../assets/custom1.js"></script>
<script type="text/javascript" src="../assets/bigPicture.js"></script>
</body>
</html>