Fork of daniellemaywood.uk/gleam — Wasm codegen work
3.6 kB
108 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 Target::Wasm => TargetCodegenConfiguration::Wasm {},
49 };
50
51 tracing::info!("Compiling package");
52
53 let mut compiler = PackageCompiler::new(
54 &config,
55 Mode::Dev,
56 &options.package_directory,
57 &options.output_directory,
58 &options.libraries_directory,
59 &target,
60 ids,
61 io,
62 );
63 compiler.write_entrypoint = false;
64 compiler.write_metadata = true;
65 compiler.compile_beam_bytecode = !options.skip_beam_compilation;
66 compiler
67 .compile(
68 &warnings,
69 &mut type_manifests,
70 &mut defined_modules,
71 &mut StaleTracker::default(),
72 &mut HashSet::new(),
73 &NullTelemetry,
74 )
75 .into_result()
76 .map(|_| ())
77}
78
79fn load_libraries(
80 ids: &UniqueIdGenerator,
81 lib: &Utf8Path,
82) -> Result<im::HashMap<EcoString, ModuleInterface>> {
83 tracing::info!("Reading precompiled module metadata files");
84 let mut manifests = im::HashMap::new();
85 for lib in fs::read_dir(lib)?.filter_map(Result::ok) {
86 let path = lib.path().join(paths::ARTEFACT_DIRECTORY_NAME);
87 if !path.is_dir() {
88 continue;
89 }
90 for module in fs::module_caches_paths(path)? {
91 let bytes = fs::read_bytes(module.clone())?;
92 let module = match metadata::decode(&bytes, ids.clone()) {
93 Ok(module) => module,
94 Err(e) => {
95 return Err(Error::FileIo {
96 kind: FileKind::File,
97 action: FileIoAction::Parse,
98 path: module,
99 err: Some(e.to_string()),
100 });
101 }
102 };
103 let _ = manifests.insert(module.name.clone(), module);
104 }
105 }
106
107 Ok(manifests)
108}