mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 16:21:11 +00:00
Rebuild hosts automatically (for now)
This commit is contained in:
parent
856c01f706
commit
7e1166b3a2
3 changed files with 81 additions and 65 deletions
|
@ -10,6 +10,10 @@ pub fn link(
|
||||||
host_input_path: &Path,
|
host_input_path: &Path,
|
||||||
dest_filename: &Path,
|
dest_filename: &Path,
|
||||||
) -> io::Result<Child> {
|
) -> io::Result<Child> {
|
||||||
|
// TODO we should no longer need to do this once we have platforms on
|
||||||
|
// a package repository, as we can then get precompiled hosts from there.
|
||||||
|
rebuild_host(host_input_path);
|
||||||
|
|
||||||
match target {
|
match target {
|
||||||
Triple {
|
Triple {
|
||||||
architecture: Architecture::X86_64,
|
architecture: Architecture::X86_64,
|
||||||
|
@ -25,6 +29,68 @@ pub fn link(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rebuild_host(host_input_path: &Path) {
|
||||||
|
let c_host_src = host_input_path.with_file_name("host.c");
|
||||||
|
let c_host_dest = host_input_path.with_file_name("c_host.o");
|
||||||
|
let rust_host_src = host_input_path.with_file_name("host.rs");
|
||||||
|
let rust_host_dest = host_input_path.with_file_name("rust_host.o");
|
||||||
|
let host_dest = host_input_path.with_file_name("host.o");
|
||||||
|
|
||||||
|
// Compile host.c
|
||||||
|
Command::new("clang")
|
||||||
|
.env_clear()
|
||||||
|
.args(&[
|
||||||
|
"-c",
|
||||||
|
c_host_src.to_str().unwrap(),
|
||||||
|
"-o",
|
||||||
|
c_host_dest.to_str().unwrap(),
|
||||||
|
])
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if rust_host_src.exists() {
|
||||||
|
// Compile and link host.rs, if it exists
|
||||||
|
Command::new("rustc")
|
||||||
|
.args(&[
|
||||||
|
rust_host_src.to_str().unwrap(),
|
||||||
|
"-o",
|
||||||
|
rust_host_dest.to_str().unwrap(),
|
||||||
|
])
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Command::new("ld")
|
||||||
|
.env_clear()
|
||||||
|
.args(&[
|
||||||
|
"-r",
|
||||||
|
c_host_dest.to_str().unwrap(),
|
||||||
|
rust_host_dest.to_str().unwrap(),
|
||||||
|
"-o",
|
||||||
|
host_dest.to_str().unwrap(),
|
||||||
|
])
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Clean up rust_host.o
|
||||||
|
Command::new("rm")
|
||||||
|
.env_clear()
|
||||||
|
.args(&[
|
||||||
|
"-f",
|
||||||
|
rust_host_dest.to_str().unwrap(),
|
||||||
|
c_host_dest.to_str().unwrap(),
|
||||||
|
])
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
// Clean up rust_host.o
|
||||||
|
Command::new("mv")
|
||||||
|
.env_clear()
|
||||||
|
.args(&[c_host_dest, host_dest])
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn link_linux(
|
fn link_linux(
|
||||||
target: &Triple,
|
target: &Triple,
|
||||||
binary_path: &Path,
|
binary_path: &Path,
|
||||||
|
@ -34,6 +100,8 @@ fn link_linux(
|
||||||
// NOTE: order of arguments to `ld` matters here!
|
// NOTE: order of arguments to `ld` matters here!
|
||||||
// The `-l` flags should go after the `.o` arguments
|
// The `-l` flags should go after the `.o` arguments
|
||||||
Command::new("ld")
|
Command::new("ld")
|
||||||
|
// Don't allow LD_ env vars to affect this
|
||||||
|
.env_clear()
|
||||||
.args(&[
|
.args(&[
|
||||||
"-arch",
|
"-arch",
|
||||||
arch_str(target),
|
arch_str(target),
|
||||||
|
@ -73,6 +141,8 @@ fn link_macos(
|
||||||
// NOTE: order of arguments to `ld` matters here!
|
// NOTE: order of arguments to `ld` matters here!
|
||||||
// The `-l` flags should go after the `.o` arguments
|
// The `-l` flags should go after the `.o` arguments
|
||||||
Command::new("ld")
|
Command::new("ld")
|
||||||
|
// Don't allow LD_ env vars to affect this
|
||||||
|
.env_clear()
|
||||||
.args(&[
|
.args(&[
|
||||||
"-arch",
|
"-arch",
|
||||||
target.architecture.to_string().as_str(),
|
target.architecture.to_string().as_str(),
|
||||||
|
|
|
@ -1,21 +1,8 @@
|
||||||
## Recompiling the platform from source
|
# Rebuilding the host from source
|
||||||
|
|
||||||
This example platform for "Hello, World!" includes the same host implemented
|
Run `build.sh` to manually rebuild this platform's host.
|
||||||
in two different languages—C and Rust—to demonstrate how it's done in both.
|
|
||||||
Ordinarily you'd only implement your host once, in your preferred language.
|
|
||||||
|
|
||||||
|
Note that the compiler currently has its own logic for rebuilding these hosts
|
||||||
### Recompiling the C implementation
|
(in `link.rs`). It's hardcoded for now, but the long-term goal is that
|
||||||
|
hosts will be precompiled by platform authors and distributed in packages,
|
||||||
```shell
|
at which point only package authors will need to think about rebuilding hosts.
|
||||||
$ clang -c host.c -o host.o
|
|
||||||
```
|
|
||||||
|
|
||||||
Then `mv` the compiled `host.o` into the apropriate subdirectory under
|
|
||||||
`host/` based on the operating system you've compiled it for.
|
|
||||||
|
|
||||||
### Recompiling the Rust implementation
|
|
||||||
|
|
||||||
```shell
|
|
||||||
$ rustc
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,49 +1,8 @@
|
||||||
# Rebuilding the host from source
|
# Rebuilding the host from source
|
||||||
|
|
||||||
Here are the current steps to rebuild this host. These
|
Run `build.sh` to manually rebuild this platform's host.
|
||||||
steps can likely be moved into a `build.rs` script after
|
|
||||||
turning `host.rs` into a `cargo` project, but that hasn't
|
|
||||||
been attempted yet.
|
|
||||||
|
|
||||||
## Compile the Rust and C sources
|
Note that the compiler currently has its own logic for rebuilding these hosts
|
||||||
|
(in `link.rs`). It's hardcoded for now, but the long-term goal is that
|
||||||
Currently this host has both a `host.rs` and a `host.c`.
|
hosts will be precompiled by platform authors and distributed in packages,
|
||||||
This is only because we haven't figured out a way to convince
|
at which point only package authors will need to think about rebuilding hosts.
|
||||||
Rust to emit a `.o` file that doesn't define a `main` entrypoint,
|
|
||||||
but which is capable of being linked into one later.
|
|
||||||
|
|
||||||
As a workaround, we have `host.rs` expose a function called
|
|
||||||
`rust_main` instead of `main`, and all `host.c` does is provide
|
|
||||||
an actual `main` which imports and then calls `rust_main` from
|
|
||||||
the compiled `host.rs`. It's not the most elegant workaround,
|
|
||||||
but [asking on `users.rust-lang.org`](https://users.rust-lang.org/t/error-when-compiling-linking-with-o-files/49635/4)
|
|
||||||
didn't turn up any nicer approaches. Maybe they're out there though!
|
|
||||||
|
|
||||||
To make this workaround happen, we need to compile both `host.rs`
|
|
||||||
and `host.c`. First, `cd` into `platform/host/src/` and then run:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ clang -c host.c -o c_host.o
|
|
||||||
$ rustc host.rs -o rust_host.o
|
|
||||||
```
|
|
||||||
|
|
||||||
Now we should have `c_host.o` and `rust_host.o` in the curent directory.
|
|
||||||
|
|
||||||
## Link together the `.o` files
|
|
||||||
|
|
||||||
Next, combine `c_host.o` and `rust_host.o` into `host.o` using `ld -r` like so:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ld -r c_host.o rust_host.o -o host.o
|
|
||||||
```
|
|
||||||
|
|
||||||
Move `host.o` into the appropriate `platform/` subdirectory
|
|
||||||
based on your architecture and operating system. For example,
|
|
||||||
on macOS, you'd move `host.o` into the `platform/host/x86_64-unknown-darwin10/` directory.
|
|
||||||
|
|
||||||
## All done!
|
|
||||||
|
|
||||||
Congratulations! You now have an updated host.
|
|
||||||
|
|
||||||
It's now fine to delete `c_host.o` and `rust_host.o`,
|
|
||||||
since they were only needed to produce `host.o`.
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue