⭐️ A friendly language for building type-safe, scalable systems!
at main 5.5 kB view raw
1use camino::Utf8PathBuf; 2use gleam_core::{ 3 Result, 4 analyse::TargetSupport, 5 build::{Codegen, Compile, Mode, Options, Target}, 6 paths::ProjectPaths, 7}; 8 9static ENTRYPOINT_FILENAME_POWERSHELL: &str = "entrypoint.ps1"; 10static ENTRYPOINT_FILENAME_POSIX_SHELL: &str = "entrypoint.sh"; 11 12static ENTRYPOINT_TEMPLATE_POWERSHELL: &str = 13 include_str!("../templates/erlang-shipment-entrypoint.ps1"); 14static ENTRYPOINT_TEMPLATE_POSIX_SHELL: &str = 15 include_str!("../templates/erlang-shipment-entrypoint.sh"); 16 17// TODO: start in embedded mode 18// TODO: test 19 20/// Generate a directory of precompiled Erlang along with a start script. 21/// Suitable for deployment to a server. 22/// 23/// For each Erlang application (aka package) directory these directories are 24/// copied across: 25/// - ebin 26/// - include 27/// - priv 28pub(crate) fn erlang_shipment(paths: &ProjectPaths) -> Result<()> { 29 let target = Target::Erlang; 30 let mode = Mode::Prod; 31 let build = paths.build_directory_for_target(mode, target); 32 let out = paths.erlang_shipment_directory(); 33 34 crate::fs::mkdir(&out)?; 35 36 // Reset the directories to ensure we have a clean slate and no old code 37 crate::fs::delete_directory(&build)?; 38 crate::fs::delete_directory(&out)?; 39 40 // Build project in production mode 41 let built = crate::build::main( 42 paths, 43 Options { 44 root_target_support: TargetSupport::Enforced, 45 warnings_as_errors: false, 46 codegen: Codegen::All, 47 compile: Compile::All, 48 mode, 49 target: Some(target), 50 no_print_progress: false, 51 }, 52 crate::build::download_dependencies(paths, crate::cli::Reporter::new())?, 53 )?; 54 55 for entry in crate::fs::read_dir(&build)?.filter_map(Result::ok) { 56 let path = entry.path(); 57 58 // We are only interested in package directories 59 if !path.is_dir() { 60 continue; 61 } 62 63 let name = path.file_name().expect("Directory name"); 64 let build = build.join(name); 65 let out = out.join(name); 66 crate::fs::mkdir(&out)?; 67 68 // Copy desired package subdirectories 69 for subdirectory in ["ebin", "priv", "include"] { 70 let source = build.join(subdirectory); 71 if source.is_dir() { 72 let source = crate::fs::canonicalise(&source)?; 73 let out = out.join(subdirectory); 74 crate::fs::copy_dir(source, &out)?; 75 } 76 } 77 } 78 79 // PowerShell entry point script. 80 write_entrypoint_script( 81 &out.join(ENTRYPOINT_FILENAME_POWERSHELL), 82 ENTRYPOINT_TEMPLATE_POWERSHELL, 83 &built.root_package.config.name, 84 )?; 85 86 // POSIX Shell entry point script. 87 write_entrypoint_script( 88 &out.join(ENTRYPOINT_FILENAME_POSIX_SHELL), 89 ENTRYPOINT_TEMPLATE_POSIX_SHELL, 90 &built.root_package.config.name, 91 )?; 92 93 crate::cli::print_exported(&built.root_package.config.name); 94 95 println!( 96 " 97Your Erlang shipment has been generated to {out}. 98 99It can be copied to a compatible server with Erlang installed and run with 100one of the following scripts: 101 - {ENTRYPOINT_FILENAME_POWERSHELL} (PowerShell script) 102 - {ENTRYPOINT_FILENAME_POSIX_SHELL} (POSIX Shell script) 103", 104 ); 105 106 Ok(()) 107} 108 109fn write_entrypoint_script( 110 entrypoint_output_path: &Utf8PathBuf, 111 entrypoint_template_path: &str, 112 package_name: &str, 113) -> Result<(), gleam_core::Error> { 114 let text = entrypoint_template_path.replace("$PACKAGE_NAME_FROM_GLEAM", package_name); 115 crate::fs::write(entrypoint_output_path, &text)?; 116 crate::fs::make_executable(entrypoint_output_path)?; 117 Ok(()) 118} 119 120pub fn hex_tarball(paths: &ProjectPaths) -> Result<()> { 121 let mut config = crate::config::root_config(paths)?; 122 let data: Vec<u8> = crate::publish::build_hex_tarball(paths, &mut config)?; 123 124 let path = paths.build_export_hex_tarball(&config.name, &config.version.to_string()); 125 crate::fs::write_bytes(&path, &data)?; 126 println!( 127 " 128Your hex tarball has been generated in {}. 129", 130 &path 131 ); 132 Ok(()) 133} 134 135pub fn javascript_prelude() -> Result<()> { 136 print!("{}", gleam_core::javascript::PRELUDE); 137 Ok(()) 138} 139 140pub fn typescript_prelude() -> Result<()> { 141 print!("{}", gleam_core::javascript::PRELUDE_TS_DEF); 142 Ok(()) 143} 144 145pub fn package_interface(paths: &ProjectPaths, out: Utf8PathBuf) -> Result<()> { 146 // Build the project 147 let mut built = crate::build::main( 148 paths, 149 Options { 150 mode: Mode::Prod, 151 target: None, 152 codegen: Codegen::All, 153 compile: Compile::All, 154 warnings_as_errors: false, 155 root_target_support: TargetSupport::Enforced, 156 no_print_progress: false, 157 }, 158 crate::build::download_dependencies(paths, crate::cli::Reporter::new())?, 159 )?; 160 built.root_package.attach_doc_and_module_comments(); 161 162 let out = gleam_core::docs::generate_json_package_interface( 163 out, 164 &built.root_package, 165 &built.module_interfaces, 166 ); 167 crate::fs::write_outputs_under(&[out], paths.root())?; 168 Ok(()) 169} 170 171pub fn package_information(paths: &ProjectPaths, out: Utf8PathBuf) -> Result<()> { 172 let config = crate::config::root_config(paths)?; 173 let out = gleam_core::docs::generate_json_package_information(out, config); 174 crate::fs::write_outputs_under(&[out], paths.root())?; 175 Ok(()) 176}