Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove platform rebuilding and generate_stub_lib #6696

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
186c7b2
remove generate_stub_lib
lukewilliamboswell Apr 30, 2024
3f1db90
WIP refactor
lukewilliamboswell May 1, 2024
7061a54
update preprocess-host
lukewilliamboswell May 1, 2024
1c4c0b8
pipe --verbose through for preprocess subcommand
lukewilliamboswell May 1, 2024
b7a23f8
remove host rebuilding
lukewilliamboswell May 1, 2024
d45960b
WIP get a test platform working
lukewilliamboswell May 1, 2024
dd3f147
first test passing using build script
lukewilliamboswell May 2, 2024
5c0e255
update quicksort host
lukewilliamboswell May 2, 2024
9daa94a
refactor breakout and benchmarks
lukewilliamboswell May 2, 2024
64a0964
refactor cli/tests/expects platform
lukewilliamboswell May 2, 2024
00dc081
refactor cli/tests/fixtures platforms
lukewilliamboswell May 2, 2024
2c9d38c
refactor cli tests
lukewilliamboswell May 2, 2024
e7ee450
refactor false-interpreter cli test
lukewilliamboswell May 2, 2024
19eeb1a
move known_type_error
lukewilliamboswell May 2, 2024
faba303
move more cli tests
lukewilliamboswell May 2, 2024
b2cad48
refactor cli/tui test
lukewilliamboswell May 2, 2024
77dc8b9
WIP refactor platform-switching examples
lukewilliamboswell May 2, 2024
5a5cfb1
refactor Swift
lukewilliamboswell May 3, 2024
d7780a0
refactor zig example
lukewilliamboswell May 3, 2024
d4313e7
WIP WASM
lukewilliamboswell May 3, 2024
2286625
fix zig example after rebase
lukewilliamboswell May 3, 2024
ed2b0e6
fix ingested_file_bytes example after rebase
lukewilliamboswell May 3, 2024
c20bd22
refactor static site gen example
lukewilliamboswell May 3, 2024
0ff9239
refactor gui example
lukewilliamboswell May 3, 2024
193dc29
ignore swift and ruby cli example tests
lukewilliamboswell May 3, 2024
01db1e6
fix cli_run for check_output_with_stdin
lukewilliamboswell May 3, 2024
bd1c3ec
ignore inspect_gui test
lukewilliamboswell May 4, 2024
64b80c9
refactor valgrind host building
lukewilliamboswell May 5, 2024
c3332ad
fix cli test ingested bytes
lukewilliamboswell May 12, 2024
6fdb559
remove accidentally added file
lukewilliamboswell May 12, 2024
aa009b7
clippy fixes
lukewilliamboswell May 12, 2024
5754ce9
cleanup files after rebase
lukewilliamboswell May 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 20 additions & 40 deletions crates/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ pub const FLAG_TARGET: &str = "target";
pub const FLAG_TIME: &str = "time";
pub const FLAG_VERBOSE: &str = "verbose";
pub const FLAG_LINKER: &str = "linker";
pub const FLAG_PREBUILT: &str = "prebuilt-platform";
pub const FLAG_CHECK: &str = "check";
pub const FLAG_STDIN: &str = "stdin";
pub const FLAG_STDOUT: &str = "stdout";
Expand All @@ -78,6 +77,9 @@ pub const GLUE_DIR: &str = "GLUE_DIR";
pub const GLUE_SPEC: &str = "GLUE_SPEC";
pub const DIRECTORY_OR_FILES: &str = "DIRECTORY_OR_FILES";
pub const ARGS_FOR_APP: &str = "ARGS_FOR_APP";
pub const FLAG_PP_HOST: &str = "host";
pub const FLAG_PP_PLATFORM: &str = "platform";
pub const FLAG_PP_DYLIB: &str = "lib";

const VERSION: &str = include_str!("../../../version.txt");
const DEFAULT_GENERATED_DOCS_DIR: &str = "generated-docs";
Expand Down Expand Up @@ -131,12 +133,6 @@ pub fn build_app() -> Command {
.value_parser(["surgical", "legacy"])
.required(false);

let flag_prebuilt = Arg::new(FLAG_PREBUILT)
.long(FLAG_PREBUILT)
.help("Assume the platform has been prebuilt and skip rebuilding the platform\n(This is enabled implicitly when using `roc build` with a --target other than `--target <current machine>`, unless the target is wasm.)")
.action(ArgAction::SetTrue)
.required(false);

let flag_wasm_stack_size_kb = Arg::new(FLAG_WASM_STACK_SIZE_KB)
.long(FLAG_WASM_STACK_SIZE_KB)
.help("Stack size in kilobytes for wasm32 target\n(This only applies when --dev also provided.)")
Expand Down Expand Up @@ -184,7 +180,6 @@ pub fn build_app() -> Command {
.arg(flag_profiling.clone())
.arg(flag_time.clone())
.arg(flag_linker.clone())
.arg(flag_prebuilt.clone())
.arg(flag_fuzz.clone())
.arg(flag_wasm_stack_size_kb)
.arg(
Expand Down Expand Up @@ -235,7 +230,6 @@ pub fn build_app() -> Command {
.arg(flag_profiling.clone())
.arg(flag_time.clone())
.arg(flag_linker.clone())
.arg(flag_prebuilt.clone())
.arg(flag_fuzz.clone())
.arg(
Arg::new(FLAG_VERBOSE)
Expand Down Expand Up @@ -266,7 +260,6 @@ pub fn build_app() -> Command {
.arg(flag_profiling.clone())
.arg(flag_time.clone())
.arg(flag_linker.clone())
.arg(flag_prebuilt.clone())
.arg(flag_fuzz.clone())
.arg(roc_file_to_run.clone())
.arg(args_for_app.clone().last(true))
Expand All @@ -281,7 +274,6 @@ pub fn build_app() -> Command {
.arg(flag_profiling.clone())
.arg(flag_time.clone())
.arg(flag_linker.clone())
.arg(flag_prebuilt.clone())
.arg(flag_fuzz.clone())
.arg(roc_file_to_run.clone())
.arg(args_for_app.clone().last(true))
Expand Down Expand Up @@ -371,28 +363,23 @@ pub fn build_app() -> Command {
.default_value(DEFAULT_ROC_FILENAME)
)
)
.subcommand(Command::new(CMD_GEN_STUB_LIB)
.about("Generate a stubbed shared library that can be used for linking a platform binary.\nThe stubbed library has prototypes, but no function bodies.\n\nNote: This command will be removed in favor of just using `roc build` once all platforms support the surgical linker")
.subcommand(Command::new(CMD_PREPROCESS_HOST)
.about("Runs the surgical linker pre-processor to generate `.rh` and `.rm` files.")
.arg(
Arg::new(ROC_FILE)
.help("The .roc file for an app using the platform")
Arg::new(FLAG_PP_HOST)
.help("Path to the host executable where the app was linked dynamically")
.value_parser(value_parser!(PathBuf))
.required(true)
)
.arg(
Arg::new(FLAG_TARGET)
.long(FLAG_TARGET)
.help("Choose a different target")
.default_value(Into::<&'static str>::into(Target::default()))
.value_parser(build_target_values_parser.clone())
.required(false),
Arg::new(FLAG_PP_PLATFORM)
.help("Path to the platform/main.roc file")
.value_parser(value_parser!(PathBuf))
.required(true)
)
)
.subcommand(Command::new(CMD_PREPROCESS_HOST)
.about("Runs the surgical linker preprocessor to generate `.rh` and `.rm` files.")
.arg(
Arg::new(ROC_FILE)
.help("The .roc file for an app using the platform")
Arg::new(FLAG_PP_DYLIB)
.help("Path to a stubbed app dynamic library (e.g. roc build --lib app.roc)")
.value_parser(value_parser!(PathBuf))
.required(true)
)
Expand All @@ -404,6 +391,13 @@ pub fn build_app() -> Command {
.value_parser(build_target_values_parser)
.required(false),
)
.arg(
Arg::new(FLAG_VERBOSE)
.long(FLAG_VERBOSE)
.help("Print detailed information while pre-processing host")
.action(ArgAction::SetTrue)
.required(false)
)
)
.arg(flag_optimize)
.arg(flag_max_threads)
Expand All @@ -413,7 +407,6 @@ pub fn build_app() -> Command {
.arg(flag_profiling)
.arg(flag_time)
.arg(flag_linker)
.arg(flag_prebuilt)
.arg(flag_fuzz)
.arg(roc_file_to_run)
.arg(args_for_app.trailing_var_arg(true))
Expand Down Expand Up @@ -822,18 +815,6 @@ pub fn build(
LinkingStrategy::Surgical
};

let prebuilt = {
let cross_compile = target != Target::default();
let targeting_wasm = matches!(target.architecture(), Architecture::Wasm32);

matches.get_flag(FLAG_PREBUILT) ||
// When compiling for a different target, assume a prebuilt platform.
// Otherwise compilation would most likely fail because many toolchains
// assume you're compiling for the current machine. We make an exception
// for Wasm, because cross-compiling is the norm in that case.
(cross_compile && !targeting_wasm)
};

let fuzz = matches.get_flag(FLAG_FUZZ);
if fuzz && !matches!(code_gen_backend, CodeGenBackend::Llvm(_)) {
user_error!("Cannot instrument binary for fuzzing while using a dev backend.");
Expand Down Expand Up @@ -868,7 +849,6 @@ pub fn build(
emit_timings,
link_type,
linking_strategy,
prebuilt,
wasm_dev_stack_bytes,
roc_cache_dir,
load_config,
Expand Down
85 changes: 48 additions & 37 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ use roc_build::link::LinkType;
use roc_build::program::{check_file, CodeGenBackend};
use roc_cli::{
build_app, format_files, format_src, test, BuildConfig, FormatMode, CMD_BUILD, CMD_CHECK,
CMD_DEV, CMD_DOCS, CMD_FORMAT, CMD_GEN_STUB_LIB, CMD_GLUE, CMD_PREPROCESS_HOST, CMD_REPL,
CMD_RUN, CMD_TEST, CMD_VERSION, DIRECTORY_OR_FILES, FLAG_CHECK, FLAG_DEV, FLAG_LIB,
FLAG_NO_LINK, FLAG_OUTPUT, FLAG_STDIN, FLAG_STDOUT, FLAG_TARGET, FLAG_TIME, GLUE_DIR,
GLUE_SPEC, ROC_FILE,
CMD_DEV, CMD_DOCS, CMD_FORMAT, CMD_GLUE, CMD_PREPROCESS_HOST, CMD_REPL, CMD_RUN, CMD_TEST,
CMD_VERSION, DIRECTORY_OR_FILES, FLAG_CHECK, FLAG_DEV, FLAG_LIB, FLAG_NO_LINK, FLAG_OUTPUT,
FLAG_PP_DYLIB, FLAG_PP_HOST, FLAG_PP_PLATFORM, FLAG_STDIN, FLAG_STDOUT, FLAG_TARGET, FLAG_TIME,
FLAG_VERBOSE, GLUE_DIR, GLUE_SPEC, ROC_FILE,
};
use roc_docs::generate_docs_html;
use roc_error_macros::user_error;

#[allow(unused_imports)]
use roc_error_macros::{internal_error, user_error};

use roc_gen_dev::AssemblyBackendMode;
use roc_gen_llvm::llvm::build::LlvmBackendMode;
use roc_load::{FunctionKind, LoadingProblem, Threading};
use roc_load::{LoadingProblem, Threading};
use roc_packaging::cache::{self, RocCacheDir};
use roc_target::Target;
use std::fs::{self, FileType};
Expand Down Expand Up @@ -120,47 +123,55 @@ fn main() -> io::Result<()> {
Ok(1)
}
}
Some((CMD_GEN_STUB_LIB, matches)) => {
let input_path = matches.get_one::<PathBuf>(ROC_FILE).unwrap();
let target = matches
.get_one::<String>(FLAG_TARGET)
.and_then(|s| Target::from_str(s).ok())
.unwrap_or_default();
let function_kind = FunctionKind::LambdaSet;
roc_linker::generate_stub_lib(
input_path,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
target,
function_kind,
);
Ok(0)
}
Some((CMD_PREPROCESS_HOST, matches)) => {
let input_path = matches.get_one::<PathBuf>(ROC_FILE).unwrap();
let preprocess_host_err =
{ |msg: String| user_error!("\n\n ERROR PRE-PROCESSING HOST: {}\n\n", msg) };

let host_path = matches.get_one::<PathBuf>(FLAG_PP_HOST).unwrap();
if !host_path.is_file() {
preprocess_host_err(format!(
"Expected to find the host executable file at {}",
&host_path.display()
));
}

let platform_path = matches.get_one::<PathBuf>(FLAG_PP_PLATFORM).unwrap();
if !platform_path.is_file() {
preprocess_host_err(format!(
"Expected to find the platform/main.roc file at {}",
&platform_path.display()
));
}

let dylib_path = matches.get_one::<PathBuf>(FLAG_PP_DYLIB).unwrap();
if !dylib_path.is_file() {
preprocess_host_err(format!(
"Expected to find the app stub dynamic library file at {}",
dylib_path.display()
));
}

let target = matches
.get_one::<String>(FLAG_TARGET)
.and_then(|s| Target::from_str(s).ok())
.unwrap_or_default();

let function_kind = FunctionKind::LambdaSet;
let (platform_path, stub_lib, stub_dll_symbols) = roc_linker::generate_stub_lib(
input_path,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
target,
function_kind,
);
let verbose_and_time = matches.get_one::<bool>(FLAG_VERBOSE).unwrap();

#[cfg(target_os = "windows")]
{
internal_error!("TODO populate stub_dll_symbols for Windows");
}

// TODO: pipeline the executable location through here.
// Currently it is essentally hardcoded as platform_path/dynhost.
roc_linker::preprocess_host(
target,
&platform_path.with_file_name("main.roc"),
// The target triple string must be derived from the triple to convert from the generic
// `system` target to the exact specific target.
&platform_path.with_file_name(format!("{}.rh", target)),
&stub_lib,
&stub_dll_symbols,
host_path,
platform_path,
dylib_path,
*verbose_and_time,
*verbose_and_time,
);

Ok(0)
}
Some((CMD_BUILD, matches)) => {
Expand Down
7 changes: 7 additions & 0 deletions crates/cli/tests/algorithms/fibonacci/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
zig-cache/
zig-out/
glue/

build

*.a
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
app "fibonacci"
packages { pf: "fibonacci-platform/main.roc" }
app ""
packages { pf: "platform.roc" }
imports []
provides [main] to pf

Expand Down
57 changes: 57 additions & 0 deletions crates/cli/tests/algorithms/fibonacci/build.roc
lukewilliamboswell marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
app ""
packages {
cli: "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br",
build: "../../../../../examples/build-helpers/main.roc",
}
imports [cli.Task.{ Task }, cli.Path, cli.Env, cli.Cmd, build.Help]
provides [main] to cli

main =

# use ENV VARs for easier automation from within test runner
roc = Env.var "ROC" |> Task.mapErr! \_ -> EnvionmentVariableNotSet "ROC"
glue = Env.var "ZIG_GLUE" |> Task.mapErr! \_ -> EnvionmentVariableNotSet "ZIG_GLUE"

# get the current OS and ARCH
target = getTarget!

# the prebuilt binary `macos-arm64.a` changes based on target
prebuiltBinaryPath = Help.prebuiltBinaryName target

when Path.isFile (Path.fromStr prebuiltBinaryPath) |> Task.result! is
Ok _ ->
Task.ok {} # the prebuilt binary already exists... no need to rebuild
Err _ ->
# generate glue for the host
Cmd.exec roc ["glue", glue, "glue/", "platform.roc"]
|> Task.mapErr! ErrGeneratingGlue

# build the host
Cmd.exec "zig" ["build"]
|> Task.mapErr! ErrBuildingHost

# copy pre-built binary into platform
Cmd.exec "cp" ["-f", "zig-out/lib/libfibonacci.a", prebuiltBinaryPath]
|> Task.mapErr! ErrCopyPrebuiltBinary

getTarget : Task Help.RocTarget _
getTarget =

arch =
Cmd.new "uname"
|> Cmd.arg "-m"
|> Cmd.output
|> Task.map .stdout
|> Task.map Help.archFromStr
|> Task.mapErr! \err -> ErrGettingNativeArch (Inspect.toStr err)

os =
Cmd.new "uname"
|> Cmd.arg "-s"
|> Cmd.output
|> Task.map .stdout
|> Task.map Help.osFromStr
|> Task.mapErr! \err -> ErrGettingNativeOS (Inspect.toStr err)
lukewilliamboswell marked this conversation as resolved.
Show resolved Hide resolved

Help.rocTarget { os, arch } |> Task.fromResult!

15 changes: 15 additions & 0 deletions crates/cli/tests/algorithms/fibonacci/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const std = @import("std");

pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

const lib = b.addStaticLibrary(.{
.name = "fibonacci",
.root_source_file = .{ .path = "host.zig" },
.target = target,
.optimize = optimize,
});

b.installArtifact(lib);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
const str = @import("glue").str;
const str = @import("glue/str.zig");
const RocStr = str.RocStr;
const testing = std.testing;
const expectEqual = testing.expectEqual;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
platform "fibonacci"
platform ""
requires {} { main : I64 -> I64 }
exposes []
packages {}
Expand Down
7 changes: 7 additions & 0 deletions crates/cli/tests/algorithms/quicksort/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
zig-cache/
zig-out/
glue/

build

*.a
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
app "quicksort"
packages { pf: "quicksort-platform/main.roc" }
packages { pf: "platform.roc" }
imports []
provides [quicksort] to pf

Expand Down
Loading
Loading