An example Rust build

Change-Id: I7387a1f792fd79b7b1fd761395f6d7020a14cd0b
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/4886
Commit-Queue: Julie Hockett <juliehockett@google.com>
Reviewed-by: Brett Wilson <brettw@google.com>
diff --git a/tools/gn/rust_example/.gn b/tools/gn/rust_example/.gn
new file mode 100644
index 0000000..9fe0b42
--- /dev/null
+++ b/tools/gn/rust_example/.gn
@@ -0,0 +1 @@
+buildconfig = "//BUILDCONFIG.gn"
diff --git a/tools/gn/rust_example/BUILD.gn b/tools/gn/rust_example/BUILD.gn
new file mode 100644
index 0000000..e28f023
--- /dev/null
+++ b/tools/gn/rust_example/BUILD.gn
@@ -0,0 +1,5 @@
+group("default") {
+  deps = [
+    "//hello_world/src:hello_world",
+  ]
+}
diff --git a/tools/gn/rust_example/BUILDCONFIG.gn b/tools/gn/rust_example/BUILDCONFIG.gn
new file mode 100644
index 0000000..62b5bb6
--- /dev/null
+++ b/tools/gn/rust_example/BUILDCONFIG.gn
@@ -0,0 +1,23 @@
+if (target_os == "") {
+  target_os = host_os
+}
+if (target_cpu == "") {
+  target_cpu = host_cpu
+}
+if (current_cpu == "") {
+  current_cpu = target_cpu
+}
+if (current_os == "") {
+  current_os = target_os
+}
+
+_configs = [ "//build:rust_defaults" ]
+
+set_defaults("executable") {
+  configs = _configs
+}
+set_defaults("rust_library") {
+  configs = _configs
+}
+
+set_default_toolchain("//build:rust")
diff --git a/tools/gn/rust_example/README.txt b/tools/gn/rust_example/README.txt
new file mode 100644
index 0000000..8bfbdd0
--- /dev/null
+++ b/tools/gn/rust_example/README.txt
@@ -0,0 +1,4 @@
+This is an example directory structure that compiles some simple targets using
+gcc. It is intended to show how to set up a simple Rust GN build.
+
+Don't miss the ".gn" file in this directory!
diff --git a/tools/gn/rust_example/build/BUILD.gn b/tools/gn/rust_example/build/BUILD.gn
new file mode 100644
index 0000000..e4aecfd
--- /dev/null
+++ b/tools/gn/rust_example/build/BUILD.gn
@@ -0,0 +1,27 @@
+toolchain("rust") {
+  outfile = "{{target_out_dir}}/{{rustc_output_prefix}}{{crate_name}}{{rustc_output_extension}}"
+  tool("rustc") {
+    depfile = "{{target_out_dir}}/{{crate_name}}.d"
+    command = "rustc --edition={{edition}} --crate-name {{crate_name}} {{source}} --crate-type {{crate_type}} --emit=dep-info=$depfile,link {{rustflags}} -o $outfile {{rustdeps}} {{externs}}"
+    description = "RUST $outfile"
+    cdylib_output_extension = ".so"
+    proc_macro_output_extension = ".so"
+    outputs = [
+      outfile,
+    ]
+  }
+
+  tool("stamp") {
+    command = "touch {{output}}"
+    description = "STAMP {{output}}"
+  }
+
+  tool("copy") {
+    command = "cp -af {{source}} {{output}}"
+    description = "COPY {{source}} {{output}}"
+  }
+}
+
+config("rust_defaults") {
+  rustflags = [ "-Cdebuginfo=2" ]
+}
diff --git a/tools/gn/rust_example/hello_world/bar/src/BUILD.gn b/tools/gn/rust_example/hello_world/bar/src/BUILD.gn
new file mode 100644
index 0000000..49c6eee
--- /dev/null
+++ b/tools/gn/rust_example/hello_world/bar/src/BUILD.gn
@@ -0,0 +1,4 @@
+rust_library("bar") {
+  crate_root = "lib.rs"
+  edition = "2018"
+}
diff --git a/tools/gn/rust_example/hello_world/bar/src/lib.rs b/tools/gn/rust_example/hello_world/bar/src/lib.rs
new file mode 100644
index 0000000..43defe9
--- /dev/null
+++ b/tools/gn/rust_example/hello_world/bar/src/lib.rs
@@ -0,0 +1,23 @@
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn it_works() {
+        assert_eq!(2 + 2, 4);
+    }
+}
+
+#[derive(Debug)]
+pub struct Foo {
+    s: &'static str,
+    i: &'static str
+}
+
+impl Foo {
+    pub fn new(s: &'static str) -> Foo {
+        Foo{s: s, i: "bar"}
+    }
+}
+
+pub fn answer() -> i32 {
+  42
+}
\ No newline at end of file
diff --git a/tools/gn/rust_example/hello_world/foo/src/BUILD.gn b/tools/gn/rust_example/hello_world/foo/src/BUILD.gn
new file mode 100644
index 0000000..61ee1f3
--- /dev/null
+++ b/tools/gn/rust_example/hello_world/foo/src/BUILD.gn
@@ -0,0 +1,9 @@
+rust_library("foo") {
+  sources = [
+    "lib.rs",
+  ]
+  edition = "2018"
+  deps = [
+    "//hello_world/bar/src:bar",
+  ]
+}
diff --git a/tools/gn/rust_example/hello_world/foo/src/lib.rs b/tools/gn/rust_example/hello_world/foo/src/lib.rs
new file mode 100644
index 0000000..73c615c
--- /dev/null
+++ b/tools/gn/rust_example/hello_world/foo/src/lib.rs
@@ -0,0 +1,11 @@
+#[derive(Debug)]
+pub struct Foo {
+    s: &'static str,
+    i: &'static str
+}
+
+impl Foo {
+    pub fn new(s: &'static str) -> Foo {
+        Foo{s: s, i: "foo"}
+    }
+}
\ No newline at end of file
diff --git a/tools/gn/rust_example/hello_world/src/BUILD.gn b/tools/gn/rust_example/hello_world/src/BUILD.gn
new file mode 100644
index 0000000..d6a0a66
--- /dev/null
+++ b/tools/gn/rust_example/hello_world/src/BUILD.gn
@@ -0,0 +1,12 @@
+executable("hello_world") {
+  sources = [
+    "main.rs",
+  ]
+  deps = [
+    "//hello_world/foo/src:foo",
+  ]
+  edition = "2018"
+  aliased_deps = {
+    baz = "//hello_world/foo/src:foo"
+  }
+}
diff --git a/tools/gn/rust_example/hello_world/src/main.rs b/tools/gn/rust_example/hello_world/src/main.rs
new file mode 100644
index 0000000..ad70a12
--- /dev/null
+++ b/tools/gn/rust_example/hello_world/src/main.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let f = baz::Foo::new("hello");
+    println!("Hello world!");
+    println!("I'm from a dependency: {:?}!", f);
+}
\ No newline at end of file