Fork of daniellemaywood.uk/gleam — Wasm codegen work
3.5 kB
107 lines
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2020 The Gleam contributors
3
4use crate::{
5 CompilePackage, config,
6 fs::{self, ConsoleWarningEmitter, ProjectIO},
7};
8use camino::Utf8Path;
9use ecow::EcoString;
10use gleam_core::{
11 Error, Result,
12 build::{
13 Mode, NullTelemetry, PackageCompiler, StaleTracker, Target, TargetCodegenConfiguration,
14 },
15 error::{FileIoAction, FileKind},
16 metadata,
17 paths::{self, ProjectPaths},
18 type_::ModuleInterface,
19 uid::UniqueIdGenerator,
20 warning::WarningEmitter,
21};
22use std::{collections::HashSet, rc::Rc};
23
24pub fn command(options: CompilePackage) -> Result<()> {
25 let ids = UniqueIdGenerator::new();
26 let mut type_manifests = load_libraries(&ids, &options.libraries_directory)?;
27 let mut defined_modules = im::HashMap::new();
28 let warnings = WarningEmitter::new(Rc::new(ConsoleWarningEmitter));
29 let paths = ProjectPaths::new(options.package_directory.clone());
30 let config = config::read(paths.root_config())?;
31
32 let io = ProjectIO::new();
33 // Initialise the BEAM compiler instance eagerly, so we don't have to wait
34 // for it to boot when we come to use it for the first time.
35 if options.target.is_erlang() && !options.skip_beam_compilation {
36 io.initialise_beam_compiler()?;
37 }
38
39 let target = match options.target {
40 Target::Erlang => TargetCodegenConfiguration::Erlang { app_file: None },
41 Target::JavaScript => TargetCodegenConfiguration::JavaScript {
42 emit_typescript_definitions: false,
43 emit_source_maps: false,
44 prelude_location: options
45 .javascript_prelude
46 .ok_or_else(|| Error::JavaScriptPreludeRequired)?,
47 },
48 };
49
50 tracing::info!("Compiling package");
51
52 let mut compiler = PackageCompiler::new(
53 &config,
54 Mode::Dev,
55 &options.package_directory,
56 &options.output_directory,
57 &options.libraries_directory,
58 &target,
59 ids,
60 io,
61 );
62 compiler.write_entrypoint = false;
63 compiler.write_metadata = true;
64 compiler.compile_beam_bytecode = !options.skip_beam_compilation;
65 compiler
66 .compile(
67 &warnings,
68 &mut type_manifests,
69 &mut defined_modules,
70 &mut StaleTracker::default(),
71 &mut HashSet::new(),
72 &NullTelemetry,
73 )
74 .into_result()
75 .map(|_| ())
76}
77
78fn load_libraries(
79 ids: &UniqueIdGenerator,
80 lib: &Utf8Path,
81) -> Result<im::HashMap<EcoString, ModuleInterface>> {
82 tracing::info!("Reading precompiled module metadata files");
83 let mut manifests = im::HashMap::new();
84 for lib in fs::read_dir(lib)?.filter_map(Result::ok) {
85 let path = lib.path().join(paths::ARTEFACT_DIRECTORY_NAME);
86 if !path.is_dir() {
87 continue;
88 }
89 for module in fs::module_caches_paths(path)? {
90 let bytes = fs::read_bytes(module.clone())?;
91 let module = match metadata::decode(&bytes, ids.clone()) {
92 Ok(module) => module,
93 Err(e) => {
94 return Err(Error::FileIo {
95 kind: FileKind::File,
96 action: FileIoAction::Parse,
97 path: module,
98 err: Some(e.to_string()),
99 });
100 }
101 };
102 let _ = manifests.insert(module.name.clone(), module);
103 }
104 }
105
106 Ok(manifests)
107}