add rust provider (#123)

This commit is contained in:
Jared Lunde
2025-03-27 11:00:06 -07:00
committed by GitHub
parent 2a7617a2b6
commit cdf87f31c9
56 changed files with 2099 additions and 1 deletions
@@ -0,0 +1,120 @@
{
"caches": {
"cargo_git": {
"directory": "/root/.cargo/git",
"type": "shared"
},
"cargo_registry": {
"directory": "/root/.cargo/registry",
"type": "shared"
}
},
"deploy": {
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-runtime:latest"
},
{
"include": [
"/app/bin"
],
"step": "build"
}
],
"startCommand": "./bin/binary",
"variables": {
"ROCKET_ADDRESS": "0.0.0.0"
}
},
"steps": [
{
"assets": {
"mise.toml": "[mise.toml]"
},
"commands": [
{
"path": "/mise/shims"
},
{
"customName": "create mise config",
"name": "mise.toml",
"path": "/etc/mise/config.toml"
},
{
"cmd": "sh -c 'mise trust -a \u0026\u0026 mise install'",
"customName": "install mise packages: rust"
}
],
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-builder:latest"
}
],
"name": "packages:mise",
"variables": {
"MISE_CACHE_DIR": "/mise/cache",
"MISE_CONFIG_DIR": "/mise",
"MISE_DATA_DIR": "/mise",
"MISE_INSTALLS_DIR": "/mise/installs",
"MISE_SHIMS_DIR": "/mise/shims"
}
},
{
"caches": [
"cargo_registry",
"cargo_git"
],
"commands": [
{
"dest": ".",
"src": "Cargo.toml*"
},
{
"dest": ".",
"src": "Cargo.lock*"
}
],
"inputs": [
{
"step": "packages:mise"
}
],
"name": "install",
"secrets": [
"*"
]
},
{
"commands": [
{
"dest": ".",
"src": "."
},
{
"cmd": "mkdir -p bin"
},
{
"cmd": "cargo build --release --package binary"
},
{
"cmd": "cp target/release/binary bin"
}
],
"inputs": [
{
"step": "packages:mise"
},
{
"exclude": [
"/app/"
],
"step": "install"
}
],
"name": "build",
"secrets": [
"*"
]
}
]
}
@@ -0,0 +1,120 @@
{
"caches": {
"cargo_git": {
"directory": "/root/.cargo/git",
"type": "shared"
},
"cargo_registry": {
"directory": "/root/.cargo/registry",
"type": "shared"
}
},
"deploy": {
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-runtime:latest"
},
{
"include": [
"/app/bin"
],
"step": "build"
}
],
"startCommand": "./bin/binary",
"variables": {
"ROCKET_ADDRESS": "0.0.0.0"
}
},
"steps": [
{
"assets": {
"mise.toml": "[mise.toml]"
},
"commands": [
{
"path": "/mise/shims"
},
{
"customName": "create mise config",
"name": "mise.toml",
"path": "/etc/mise/config.toml"
},
{
"cmd": "sh -c 'mise trust -a \u0026\u0026 mise install'",
"customName": "install mise packages: rust"
}
],
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-builder:latest"
}
],
"name": "packages:mise",
"variables": {
"MISE_CACHE_DIR": "/mise/cache",
"MISE_CONFIG_DIR": "/mise",
"MISE_DATA_DIR": "/mise",
"MISE_INSTALLS_DIR": "/mise/installs",
"MISE_SHIMS_DIR": "/mise/shims"
}
},
{
"caches": [
"cargo_registry",
"cargo_git"
],
"commands": [
{
"dest": ".",
"src": "Cargo.toml*"
},
{
"dest": ".",
"src": "Cargo.lock*"
}
],
"inputs": [
{
"step": "packages:mise"
}
],
"name": "install",
"secrets": [
"*"
]
},
{
"commands": [
{
"dest": ".",
"src": "."
},
{
"cmd": "mkdir -p bin"
},
{
"cmd": "cargo build --release --package binary"
},
{
"cmd": "cp target/release/binary bin"
}
],
"inputs": [
{
"step": "packages:mise"
},
{
"exclude": [
"/app/"
],
"step": "install"
}
],
"name": "build",
"secrets": [
"*"
]
}
]
}
@@ -0,0 +1,143 @@
{
"caches": {
"cargo_git": {
"directory": "/root/.cargo/git",
"type": "shared"
},
"cargo_registry": {
"directory": "/root/.cargo/registry",
"type": "shared"
},
"cargo_target": {
"directory": "target",
"type": "shared"
}
},
"deploy": {
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-runtime:latest"
},
{
"include": [
"/app/bin"
],
"step": "build"
}
],
"startCommand": "./bin/rust-custom-toolchain",
"variables": {
"ROCKET_ADDRESS": "0.0.0.0"
}
},
"steps": [
{
"assets": {
"mise.toml": "[mise.toml]"
},
"commands": [
{
"path": "/mise/shims"
},
{
"customName": "create mise config",
"name": "mise.toml",
"path": "/etc/mise/config.toml"
},
{
"cmd": "sh -c 'mise trust -a \u0026\u0026 mise install'",
"customName": "install mise packages: rust"
}
],
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-builder:latest"
}
],
"name": "packages:mise",
"variables": {
"MISE_CACHE_DIR": "/mise/cache",
"MISE_CONFIG_DIR": "/mise",
"MISE_DATA_DIR": "/mise",
"MISE_INSTALLS_DIR": "/mise/installs",
"MISE_SHIMS_DIR": "/mise/shims"
}
},
{
"caches": [
"cargo_registry",
"cargo_git"
],
"commands": [
{
"dest": ".",
"src": "Cargo.toml*"
},
{
"dest": ".",
"src": "Cargo.lock*"
},
{
"cmd": "mkdir -p src"
},
{
"cmd": "sh -c 'echo \"fn main() { }\" \u003e /app/src/main.rs \u0026\u0026 if grep -q \"\\[lib\\]\" Cargo.toml; then echo \"fn main() { }\" \u003e /app/src/lib.rs; fi'",
"customName": "compile dependencies"
},
{
"cmd": "cat /app/src/main.rs"
},
{
"cmd": "cargo build --release"
},
{
"cmd": "rm -rf src target/release/rust-custom-toolchain*"
}
],
"inputs": [
{
"step": "packages:mise"
}
],
"name": "install",
"secrets": [
"*"
]
},
{
"caches": [
"cargo_target"
],
"commands": [
{
"dest": ".",
"src": "."
},
{
"cmd": "mkdir -p bin"
},
{
"cmd": "cargo build --release"
},
{
"cmd": "cp target/release/rust-custom-toolchain bin"
}
],
"inputs": [
{
"step": "packages:mise"
},
{
"exclude": [
"/app/"
],
"step": "install"
}
],
"name": "build",
"secrets": [
"*"
]
}
]
}
@@ -0,0 +1,143 @@
{
"caches": {
"cargo_git": {
"directory": "/root/.cargo/git",
"type": "shared"
},
"cargo_registry": {
"directory": "/root/.cargo/registry",
"type": "shared"
},
"cargo_target": {
"directory": "target",
"type": "shared"
}
},
"deploy": {
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-runtime:latest"
},
{
"include": [
"/app/bin"
],
"step": "build"
}
],
"startCommand": "./bin/rust-custom-version",
"variables": {
"ROCKET_ADDRESS": "0.0.0.0"
}
},
"steps": [
{
"assets": {
"mise.toml": "[mise.toml]"
},
"commands": [
{
"path": "/mise/shims"
},
{
"customName": "create mise config",
"name": "mise.toml",
"path": "/etc/mise/config.toml"
},
{
"cmd": "sh -c 'mise trust -a \u0026\u0026 mise install'",
"customName": "install mise packages: rust"
}
],
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-builder:latest"
}
],
"name": "packages:mise",
"variables": {
"MISE_CACHE_DIR": "/mise/cache",
"MISE_CONFIG_DIR": "/mise",
"MISE_DATA_DIR": "/mise",
"MISE_INSTALLS_DIR": "/mise/installs",
"MISE_SHIMS_DIR": "/mise/shims"
}
},
{
"caches": [
"cargo_registry",
"cargo_git"
],
"commands": [
{
"dest": ".",
"src": "Cargo.toml*"
},
{
"dest": ".",
"src": "Cargo.lock*"
},
{
"cmd": "mkdir -p src"
},
{
"cmd": "sh -c 'echo \"fn main() { }\" \u003e /app/src/main.rs \u0026\u0026 if grep -q \"\\[lib\\]\" Cargo.toml; then echo \"fn main() { }\" \u003e /app/src/lib.rs; fi'",
"customName": "compile dependencies"
},
{
"cmd": "cat /app/src/main.rs"
},
{
"cmd": "cargo build --release"
},
{
"cmd": "rm -rf src target/release/rust-custom-version*"
}
],
"inputs": [
{
"step": "packages:mise"
}
],
"name": "install",
"secrets": [
"*"
]
},
{
"caches": [
"cargo_target"
],
"commands": [
{
"dest": ".",
"src": "."
},
{
"cmd": "mkdir -p bin"
},
{
"cmd": "cargo build --release"
},
{
"cmd": "cp target/release/rust-custom-version bin"
}
],
"inputs": [
{
"step": "packages:mise"
},
{
"exclude": [
"/app/"
],
"step": "install"
}
],
"name": "build",
"secrets": [
"*"
]
}
]
}
@@ -0,0 +1,149 @@
{
"caches": {
"cargo_git": {
"directory": "/root/.cargo/git",
"type": "shared"
},
"cargo_registry": {
"directory": "/root/.cargo/registry",
"type": "shared"
},
"cargo_target": {
"directory": "target",
"type": "shared"
}
},
"deploy": {
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-runtime:latest"
},
{
"include": [
"/app/bin"
],
"step": "build"
}
],
"startCommand": "./bin/bin1",
"variables": {
"ROCKET_ADDRESS": "0.0.0.0"
}
},
"steps": [
{
"assets": {
"mise.toml": "[mise.toml]"
},
"commands": [
{
"path": "/mise/shims"
},
{
"customName": "create mise config",
"name": "mise.toml",
"path": "/etc/mise/config.toml"
},
{
"cmd": "sh -c 'mise trust -a \u0026\u0026 mise install'",
"customName": "install mise packages: rust"
}
],
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-builder:latest"
}
],
"name": "packages:mise",
"variables": {
"MISE_CACHE_DIR": "/mise/cache",
"MISE_CONFIG_DIR": "/mise",
"MISE_DATA_DIR": "/mise",
"MISE_INSTALLS_DIR": "/mise/installs",
"MISE_SHIMS_DIR": "/mise/shims"
}
},
{
"caches": [
"cargo_registry",
"cargo_git"
],
"commands": [
{
"dest": ".",
"src": "Cargo.toml*"
},
{
"dest": ".",
"src": "Cargo.lock*"
},
{
"cmd": "mkdir -p src"
},
{
"cmd": "sh -c 'echo \"fn main() { }\" \u003e /app/src/main.rs \u0026\u0026 if grep -q \"\\[lib\\]\" Cargo.toml; then echo \"fn main() { }\" \u003e /app/src/lib.rs; fi'",
"customName": "compile dependencies"
},
{
"cmd": "cat /app/src/main.rs"
},
{
"cmd": "cargo build --release"
},
{
"cmd": "rm -rf src target/release/rust-multiple-bins*"
}
],
"inputs": [
{
"step": "packages:mise"
}
],
"name": "install",
"secrets": [
"*"
]
},
{
"caches": [
"cargo_target"
],
"commands": [
{
"dest": ".",
"src": "."
},
{
"cmd": "mkdir -p bin"
},
{
"cmd": "cargo build --release"
},
{
"cmd": "cp target/release/rust-multiple-bins bin"
},
{
"cmd": "cp target/release/bin1 bin"
},
{
"cmd": "cp target/release/bin2 bin"
}
],
"inputs": [
{
"step": "packages:mise"
},
{
"exclude": [
"/app/"
],
"step": "install"
}
],
"name": "build",
"secrets": [
"*"
]
}
]
}
@@ -0,0 +1,143 @@
{
"caches": {
"cargo_git": {
"directory": "/root/.cargo/git",
"type": "shared"
},
"cargo_registry": {
"directory": "/root/.cargo/registry",
"type": "shared"
},
"cargo_target": {
"directory": "target",
"type": "shared"
}
},
"deploy": {
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-runtime:latest"
},
{
"include": [
"/app/bin"
],
"step": "build"
}
],
"startCommand": "./bin/rust-open-ssl",
"variables": {
"ROCKET_ADDRESS": "0.0.0.0"
}
},
"steps": [
{
"assets": {
"mise.toml": "[mise.toml]"
},
"commands": [
{
"path": "/mise/shims"
},
{
"customName": "create mise config",
"name": "mise.toml",
"path": "/etc/mise/config.toml"
},
{
"cmd": "sh -c 'mise trust -a \u0026\u0026 mise install'",
"customName": "install mise packages: rust"
}
],
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-builder:latest"
}
],
"name": "packages:mise",
"variables": {
"MISE_CACHE_DIR": "/mise/cache",
"MISE_CONFIG_DIR": "/mise",
"MISE_DATA_DIR": "/mise",
"MISE_INSTALLS_DIR": "/mise/installs",
"MISE_SHIMS_DIR": "/mise/shims"
}
},
{
"caches": [
"cargo_registry",
"cargo_git"
],
"commands": [
{
"dest": ".",
"src": "Cargo.toml*"
},
{
"dest": ".",
"src": "Cargo.lock*"
},
{
"cmd": "mkdir -p src"
},
{
"cmd": "sh -c 'echo \"fn main() { }\" \u003e /app/src/main.rs \u0026\u0026 if grep -q \"\\[lib\\]\" Cargo.toml; then echo \"fn main() { }\" \u003e /app/src/lib.rs; fi'",
"customName": "compile dependencies"
},
{
"cmd": "cat /app/src/main.rs"
},
{
"cmd": "cargo build --release"
},
{
"cmd": "rm -rf src target/release/rust-open-ssl*"
}
],
"inputs": [
{
"step": "packages:mise"
}
],
"name": "install",
"secrets": [
"*"
]
},
{
"caches": [
"cargo_target"
],
"commands": [
{
"dest": ".",
"src": "."
},
{
"cmd": "mkdir -p bin"
},
{
"cmd": "cargo build --release"
},
{
"cmd": "cp target/release/rust-open-ssl bin"
}
],
"inputs": [
{
"step": "packages:mise"
},
{
"exclude": [
"/app/"
],
"step": "install"
}
],
"name": "build",
"secrets": [
"*"
]
}
]
}
@@ -0,0 +1,143 @@
{
"caches": {
"cargo_git": {
"directory": "/root/.cargo/git",
"type": "shared"
},
"cargo_registry": {
"directory": "/root/.cargo/registry",
"type": "shared"
},
"cargo_target": {
"directory": "target",
"type": "shared"
}
},
"deploy": {
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-runtime:latest"
},
{
"include": [
"/app/bin"
],
"step": "build"
}
],
"startCommand": "./bin/rust-ring",
"variables": {
"ROCKET_ADDRESS": "0.0.0.0"
}
},
"steps": [
{
"assets": {
"mise.toml": "[mise.toml]"
},
"commands": [
{
"path": "/mise/shims"
},
{
"customName": "create mise config",
"name": "mise.toml",
"path": "/etc/mise/config.toml"
},
{
"cmd": "sh -c 'mise trust -a \u0026\u0026 mise install'",
"customName": "install mise packages: rust"
}
],
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-builder:latest"
}
],
"name": "packages:mise",
"variables": {
"MISE_CACHE_DIR": "/mise/cache",
"MISE_CONFIG_DIR": "/mise",
"MISE_DATA_DIR": "/mise",
"MISE_INSTALLS_DIR": "/mise/installs",
"MISE_SHIMS_DIR": "/mise/shims"
}
},
{
"caches": [
"cargo_registry",
"cargo_git"
],
"commands": [
{
"dest": ".",
"src": "Cargo.toml*"
},
{
"dest": ".",
"src": "Cargo.lock*"
},
{
"cmd": "mkdir -p src"
},
{
"cmd": "sh -c 'echo \"fn main() { }\" \u003e /app/src/main.rs \u0026\u0026 if grep -q \"\\[lib\\]\" Cargo.toml; then echo \"fn main() { }\" \u003e /app/src/lib.rs; fi'",
"customName": "compile dependencies"
},
{
"cmd": "cat /app/src/main.rs"
},
{
"cmd": "cargo build --release"
},
{
"cmd": "rm -rf src target/release/rust-ring*"
}
],
"inputs": [
{
"step": "packages:mise"
}
],
"name": "install",
"secrets": [
"*"
]
},
{
"caches": [
"cargo_target"
],
"commands": [
{
"dest": ".",
"src": "."
},
{
"cmd": "mkdir -p bin"
},
{
"cmd": "cargo build --release"
},
{
"cmd": "cp target/release/rust-ring bin"
}
],
"inputs": [
{
"step": "packages:mise"
},
{
"exclude": [
"/app/"
],
"step": "install"
}
],
"name": "build",
"secrets": [
"*"
]
}
]
}
@@ -0,0 +1,143 @@
{
"caches": {
"cargo_git": {
"directory": "/root/.cargo/git",
"type": "shared"
},
"cargo_registry": {
"directory": "/root/.cargo/registry",
"type": "shared"
},
"cargo_target": {
"directory": "target",
"type": "shared"
}
},
"deploy": {
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-runtime:latest"
},
{
"include": [
"/app/bin"
],
"step": "build"
}
],
"startCommand": "./bin/rocket",
"variables": {
"ROCKET_ADDRESS": "0.0.0.0"
}
},
"steps": [
{
"assets": {
"mise.toml": "[mise.toml]"
},
"commands": [
{
"path": "/mise/shims"
},
{
"customName": "create mise config",
"name": "mise.toml",
"path": "/etc/mise/config.toml"
},
{
"cmd": "sh -c 'mise trust -a \u0026\u0026 mise install'",
"customName": "install mise packages: rust"
}
],
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-builder:latest"
}
],
"name": "packages:mise",
"variables": {
"MISE_CACHE_DIR": "/mise/cache",
"MISE_CONFIG_DIR": "/mise",
"MISE_DATA_DIR": "/mise",
"MISE_INSTALLS_DIR": "/mise/installs",
"MISE_SHIMS_DIR": "/mise/shims"
}
},
{
"caches": [
"cargo_registry",
"cargo_git"
],
"commands": [
{
"dest": ".",
"src": "Cargo.toml*"
},
{
"dest": ".",
"src": "Cargo.lock*"
},
{
"cmd": "mkdir -p src"
},
{
"cmd": "sh -c 'echo \"fn main() { }\" \u003e /app/src/main.rs \u0026\u0026 if grep -q \"\\[lib\\]\" Cargo.toml; then echo \"fn main() { }\" \u003e /app/src/lib.rs; fi'",
"customName": "compile dependencies"
},
{
"cmd": "cat /app/src/main.rs"
},
{
"cmd": "cargo build --release"
},
{
"cmd": "rm -rf src target/release/rocket*"
}
],
"inputs": [
{
"step": "packages:mise"
}
],
"name": "install",
"secrets": [
"*"
]
},
{
"caches": [
"cargo_target"
],
"commands": [
{
"dest": ".",
"src": "."
},
{
"cmd": "mkdir -p bin"
},
{
"cmd": "cargo build --release"
},
{
"cmd": "cp target/release/rocket bin"
}
],
"inputs": [
{
"step": "packages:mise"
},
{
"exclude": [
"/app/"
],
"step": "install"
}
],
"name": "build",
"secrets": [
"*"
]
}
]
}
-1
View File
@@ -38,7 +38,6 @@ func TestGenerateBuildPlanForExamples(t *testing.T) {
require.NoError(t, err)
env := app.NewEnvironment(nil)
buildResult := GenerateBuildPlan(userApp, env, &GenerateBuildPlanOptions{})
if !buildResult.Success {
+2
View File
@@ -9,6 +9,7 @@ import (
"github.com/railwayapp/railpack/core/providers/php"
"github.com/railwayapp/railpack/core/providers/python"
"github.com/railwayapp/railpack/core/providers/ruby"
"github.com/railwayapp/railpack/core/providers/rust"
"github.com/railwayapp/railpack/core/providers/shell"
"github.com/railwayapp/railpack/core/providers/staticfile"
)
@@ -28,6 +29,7 @@ func GetLanguageProviders() []Provider {
&golang.GoProvider{},
&java.JavaProvider{},
&python.PythonProvider{},
&rust.RustProvider{},
&ruby.RubyProvider{},
&deno.DenoProvider{},
&node.NodeProvider{},
+600
View File
@@ -0,0 +1,600 @@
package rust
import (
"fmt"
"maps"
"regexp"
"slices"
"strings"
"github.com/railwayapp/railpack/core/generate"
"github.com/railwayapp/railpack/core/plan"
"github.com/railwayapp/railpack/internal/utils"
)
const (
DEFAULT_RUST_VERSION = "1.85.1"
CARGO_REGISTRY_CACHE = "/root/.cargo/registry"
CARGO_GIT_CACHE = "/root/.cargo/git"
CARGO_TARGET_CACHE = "target"
)
type RustProvider struct {
}
func (p *RustProvider) Name() string {
return "rust"
}
func (p *RustProvider) Detect(ctx *generate.GenerateContext) (bool, error) {
hasCargoToml := ctx.App.HasMatch("Cargo.toml")
return hasCargoToml, nil
}
func (p *RustProvider) Initialize(ctx *generate.GenerateContext) error {
return nil
}
func (p *RustProvider) Plan(ctx *generate.GenerateContext) error {
miseStep := ctx.GetMiseStepBuilder()
p.InstallMisePackages(ctx, miseStep)
install := ctx.NewCommandStep("install")
install.AddInputs([]plan.Input{
plan.NewStepInput(miseStep.Name()),
})
p.Install(ctx, install)
build := ctx.NewCommandStep("build")
build.AddInputs([]plan.Input{
plan.NewStepInput(miseStep.Name()),
plan.NewStepInput(install.Name(), plan.InputOptions{
Exclude: []string{"/app/"},
}),
})
p.Build(ctx, build)
maps.Copy(ctx.Deploy.Variables, p.GetRustEnvVars(ctx))
ctx.Deploy.Inputs = []plan.Input{
ctx.DefaultRuntimeInput(),
plan.NewStepInput(build.Name(), plan.InputOptions{
Include: []string{"/app/bin"},
}),
}
ctx.Deploy.StartCmd = p.GetStartCommand(ctx)
return nil
}
func (p *RustProvider) StartCommandHelp() string {
return "To start your Rust application, Railpack will look for:\n\n" +
"1. A Cargo.toml file in your project root\n\n" +
"Your application will be compiled to a binary and started using `./bin/<binary>`"
}
func (p *RustProvider) GetStartCommand(ctx *generate.GenerateContext) string {
target := p.getTarget(ctx)
workspace := p.resolveCargoWorkspace(ctx)
if target != "" {
if workspace != "" {
return fmt.Sprintf("./bin/%s", workspace)
}
return p.getStartBin(ctx)
}
if workspace != "" {
return fmt.Sprintf("./bin/%s", workspace)
}
return p.getStartBin(ctx)
}
func (p *RustProvider) getStartBin(ctx *generate.GenerateContext) string {
bins, err := p.getBins(ctx)
if err != nil {
return ""
}
if len(bins) == 0 {
return ""
}
var bin string
if len(bins) == 1 {
bin = bins[0]
} else if envBinName, _ := ctx.Env.GetConfigVariable("RUST_BIN"); envBinName != "" {
for _, b := range bins {
if b == envBinName {
bin = b
break
}
}
if bin == "" {
ctx.Logger.LogWarn("RUST_BIN environment variable set to '%s', but no matching binary found in Cargo.toml", envBinName)
}
} else {
cargoToml, err := parseCargoTOML(ctx)
if err == nil && cargoToml.Package.DefaultRun != "" {
bin = cargoToml.Package.DefaultRun
}
}
if bin == "" {
return bin
}
binSuffix := p.getBinSuffix(ctx)
return fmt.Sprintf("./bin/%s%s", bin, binSuffix)
}
func (p *RustProvider) getTarget(ctx *generate.GenerateContext) string {
// Target may be defined in .config/cargo.toml
if p.shouldMakeWasm32Wasi(ctx) {
return "wasm32-wasi"
}
return ""
}
func (p *RustProvider) Install(ctx *generate.GenerateContext, install *generate.CommandStepBuilder) {
install.AddCache(ctx.Caches.AddCache("cargo_registry", CARGO_REGISTRY_CACHE))
install.AddCache(ctx.Caches.AddCache("cargo_git", CARGO_GIT_CACHE))
install.AddCommands([]plan.Command{
plan.NewCopyCommand("Cargo.toml*", "."),
plan.NewCopyCommand("Cargo.lock*", "."),
})
buildCmd := "cargo build --release"
dummyCmd := `echo "fn main() { }" > /app/src/main.rs && if grep -q "\[lib\]" Cargo.toml; then echo "fn main() { }" > /app/src/lib.rs; fi`
target := p.getTarget(ctx)
targetArg := ""
targetPath := ""
if target != "" {
targetArg = fmt.Sprintf(" --target %s", target)
targetPath = fmt.Sprintf("%s/", target)
install.AddCommands([]plan.Command{
plan.NewExecCommand(fmt.Sprintf("rustup target add %s", target)),
})
}
// Don't do anything if we're in a workspace for now
if workspace := p.resolveCargoWorkspace(ctx); workspace != "" {
return
}
install.AddCommands([]plan.Command{
plan.NewExecCommand(`mkdir -p src`),
plan.NewExecShellCommand(dummyCmd, plan.ExecOptions{CustomName: "compile dependencies"}),
plan.NewExecCommand(`cat /app/src/main.rs`),
plan.NewExecCommand(fmt.Sprintf("%s%s", buildCmd, targetArg)),
plan.NewExecCommand(fmt.Sprintf("rm -rf src target/%srelease/%s*", targetPath, p.getAppName(ctx))),
})
}
func (p *RustProvider) Build(ctx *generate.GenerateContext, build *generate.CommandStepBuilder) {
build.AddCommands([]plan.Command{
plan.NewCopyCommand("."),
plan.NewExecCommand("mkdir -p bin"),
})
buildCmd := "cargo build --release"
binSuffix := p.getBinSuffix(ctx)
target := p.getTarget(ctx)
targetArg := ""
targetPath := ""
if target != "" {
targetArg = fmt.Sprintf(" --target %s", target)
targetPath = fmt.Sprintf("%s/", target)
build.AddCommands([]plan.Command{
plan.NewExecCommand(fmt.Sprintf("rustup target add %s", target)),
})
}
workspace := p.resolveCargoWorkspace(ctx)
if workspace != "" {
buildCmd = fmt.Sprintf("%s --package %s%s", buildCmd, workspace, targetArg)
build.AddCommands([]plan.Command{
plan.NewExecCommand(buildCmd),
plan.NewExecCommand(fmt.Sprintf("cp target/%srelease/%s%s bin", targetPath, workspace, binSuffix)),
})
} else {
bins, err := p.getBins(ctx)
if err != nil {
return
}
if len(bins) > 0 {
build.AddCommand(plan.NewExecCommand(fmt.Sprintf("%s%s", buildCmd, targetArg)))
for _, bin := range bins {
build.AddCommand(plan.NewExecCommand(fmt.Sprintf("cp target/%srelease/%s%s bin", targetPath, bin, binSuffix)))
}
}
}
appName := p.getAppName(ctx)
if appName != "" {
build.AddCache(ctx.Caches.AddCache("cargo_target", CARGO_TARGET_CACHE))
}
}
func (p *RustProvider) getBinSuffix(ctx *generate.GenerateContext) string {
if p.shouldMakeWasm32Wasi(ctx) {
return ".wasm"
}
return ""
}
func (p *RustProvider) getBins(ctx *generate.GenerateContext) ([]string, error) {
var bins []string
name := p.getAppName(ctx)
if name != "" {
if ctx.App.HasMatch("src/main.rs") {
bins = append(bins, name)
}
}
if ctx.App.HasMatch("src/bin") {
findBins, err := ctx.App.FindFiles("src/bin/*")
if err != nil {
return nil, err
}
for _, binPath := range findBins {
if binPath == "" {
continue
}
binPathParts := strings.Split(binPath, "/")
if len(binPathParts) == 0 {
continue
}
filename := binPathParts[len(binPathParts)-1]
parts := strings.Split(filename, ".")
if len(parts) <= 1 {
continue
}
binName := strings.Join(parts[:len(parts)-1], ".")
bins = append(bins, binName)
}
}
if len(bins) == 0 {
return nil, nil
}
return bins, nil
}
func (p *RustProvider) getAppName(ctx *generate.GenerateContext) string {
tomlFile, err := parseCargoTOML(ctx)
if err != nil {
return ""
}
if tomlFile.Package.Name != "" {
return tomlFile.Package.Name
}
return ""
}
func (p *RustProvider) GetRustEnvVars(ctx *generate.GenerateContext) map[string]string {
return map[string]string{
"ROCKET_ADDRESS": "0.0.0.0", // Allows Rocket apps to accept non-local connections
}
}
func (p *RustProvider) InstallMisePackages(ctx *generate.GenerateContext, miseStep *generate.MiseStepBuilder) {
rust := miseStep.Default("rust", DEFAULT_RUST_VERSION)
cargoToml, _ := parseCargoTOML(ctx)
if cargoToml != nil {
// Fall back to the edition
switch cargoToml.Package.Edition {
case "2015":
// https://doc.rust-lang.org/edition-guide/rust-2015/index.html
// >= 1.0.0
miseStep.Version(rust, "1.30.0", "Cargo.toml")
case "2018":
// https://doc.rust-lang.org/edition-guide/rust-2021/index.html
// >= 1.31.0
miseStep.Version(rust, "1.55.0", "Cargo.toml")
case "2021":
// https://doc.rust-lang.org/edition-guide/rust-2021/index.html
// >= 1.56.0
miseStep.Version(rust, "1.84.0", "Cargo.toml")
case "2024":
// https://doc.rust-lang.org/edition-guide/rust-2024/index.html
// >= 1.85.0
miseStep.Version(rust, "1.85.1", "Cargo.toml")
}
}
if envVersion, varName := ctx.Env.GetConfigVariable("RUST_VERSION"); envVersion != "" {
miseStep.Version(rust, envVersion, varName)
}
for _, filename := range []string{"rust-version.txt", ".rust-version"} {
if content, err := ctx.App.ReadFile(filename); err == nil {
if version := strings.TrimSpace(utils.ExtractSemverVersion(content)); version != "" {
miseStep.Version(rust, version, filename)
}
}
}
if cargoToml != nil {
if cargoToml.Package.RustVersion != "" {
// Newer versions of Rust allow the `rust-version` field in Cargo.toml
if version := utils.ExtractSemverVersion(cargoToml.Package.RustVersion); version != "" {
miseStep.Version(rust, version, "Cargo.toml")
}
}
}
if toolchain, err := parseRustToolchain(ctx); err == nil {
if version := utils.ExtractSemverVersion(toolchain.Toolchain.Version); version != "" {
miseStep.Version(rust, version, "rust-toolchain.toml")
}
}
}
var wasmRegex = regexp.MustCompile(`target\s*=\s*"wasm32-wasi"`)
func (p *RustProvider) shouldMakeWasm32Wasi(ctx *generate.GenerateContext) bool {
matches := ctx.App.FindFilesWithContent(".cargo/config.toml", wasmRegex)
return len(matches) > 0
}
func (p *RustProvider) resolveCargoWorkspace(ctx *generate.GenerateContext) string {
// First check for environment variable override
if name, _ := ctx.Env.GetConfigVariable("CARGO_WORKSPACE"); name != "" {
return name
}
// Then check for workspace in Cargo.toml
cargoToml, err := parseCargoTOML(ctx)
if err == nil && cargoToml != nil && cargoToml.Workspace.Members != nil {
if binary, err := p.findBinaryInWorkspace(ctx, cargoToml.Workspace); err == nil && binary != "" {
return binary
}
}
return ""
}
func (p *RustProvider) findBinaryInWorkspace(ctx *generate.GenerateContext, workspace WorkspaceConfig) (string, error) {
findBinary := func(member string) (string, error) {
path := fmt.Sprintf("%s/Cargo.toml", member)
var manifest CargoTOML
if err := ctx.App.ReadTOML(path, &manifest); err != nil {
return "", err
}
if manifest.Package.Name == "" {
return "", nil
}
// Check for src/main.rs which definitely indicates a binary
hasMainRs := ctx.App.HasMatch(fmt.Sprintf("%s/src/main.rs", member))
if hasMainRs {
return manifest.Package.Name, nil
}
// Check for binaries in src/bin/
hasBinDir := ctx.App.HasMatch(fmt.Sprintf("%s/src/bin", member))
if hasBinDir {
return manifest.Package.Name, nil
}
// Check for bin entries in the manifest
if len(manifest.Bin) > 0 {
return manifest.Package.Name, nil
}
// If no lib.rs exists, it might be a binary
hasLibRs := ctx.App.HasMatch(fmt.Sprintf("%s/src/lib.rs", member))
if !hasLibRs {
return manifest.Package.Name, nil
}
return "", nil
}
// First check default members that aren't excluded
for _, defaultMember := range workspace.DefaultMembers {
if slices.Contains(workspace.ExcludeMembers, defaultMember) {
continue
}
if strings.Contains(defaultMember, "*") || strings.Contains(defaultMember, "?") {
dirs, err := ctx.App.FindDirectories(defaultMember)
if err != nil {
return "", err
}
for _, dir := range dirs {
binary, err := findBinary(dir)
if err == nil && binary != "" {
return binary, nil
}
}
} else {
binary, err := findBinary(defaultMember)
if err == nil && binary != "" {
return binary, nil
}
}
}
// Then check all members that aren't excluded
for _, member := range workspace.Members {
if slices.Contains(workspace.ExcludeMembers, member) {
continue
}
if strings.Contains(member, "*") || strings.Contains(member, "?") {
dirs, err := ctx.App.FindDirectories(member)
if err != nil {
return "", err
}
for _, dir := range dirs {
binary, err := findBinary(dir)
if err == nil && binary != "" {
return binary, nil
}
}
} else {
binary, err := findBinary(member)
if err == nil && binary != "" {
return binary, nil
}
}
}
return "", nil
}
// parseCargoTOML parses a Cargo.toml file
func parseCargoTOML(ctx *generate.GenerateContext) (*CargoTOML, error) {
var cargoToml *CargoTOML
if err := ctx.App.ReadTOML("Cargo.toml", &cargoToml); err != nil {
return nil, err
}
return cargoToml, nil
}
// See https://doc.rust-lang.org/cargo/reference/manifest.html
type CargoTOML struct {
Package PackageInfo `toml:"package"`
Dependencies map[string]any `toml:"dependencies,omitempty"`
DevDependencies map[string]any `toml:"dev-dependencies,omitempty"`
BuildDependencies map[string]any `toml:"build-dependencies,omitempty"`
Lib LibConfig `toml:"lib,omitempty"`
Bin []BinConfig `toml:"bin,omitempty"`
Workspace WorkspaceConfig `toml:"workspace,omitempty"`
}
type PackageInfo struct {
Name string `toml:"name"`
Version string `toml:"version"`
RustVersion string `toml:"rust-version,omitempty"`
Authors []string `toml:"authors,omitempty"`
Edition string `toml:"edition,omitempty"`
Description string `toml:"description,omitempty"`
License string `toml:"license,omitempty"`
Repository string `toml:"repository,omitempty"`
Homepage string `toml:"homepage,omitempty"`
Documentation string `toml:"documentation,omitempty"`
Keywords []string `toml:"keywords,omitempty"`
Categories []string `toml:"categories,omitempty"`
Readme string `toml:"readme,omitempty"`
Exclude []string `toml:"exclude,omitempty"`
Include []string `toml:"include,omitempty"`
Publish bool `toml:"publish,omitempty"`
DefaultRun string `toml:"default-run,omitempty"`
}
type Dependency struct {
Version string `toml:"version,omitempty"`
Path string `toml:"path,omitempty"`
Git string `toml:"git,omitempty"`
Branch string `toml:"branch,omitempty"`
Tag string `toml:"tag,omitempty"`
Rev string `toml:"rev,omitempty"`
Features []string `toml:"features,omitempty"`
Optional bool `toml:"optional,omitempty"`
DefaultFeatures bool `toml:"default-features,omitempty"`
Package string `toml:"package,omitempty"`
}
type LibConfig struct {
Name string `toml:"name,omitempty"`
Path string `toml:"path,omitempty"`
CrateType []string `toml:"crate-type,omitempty"`
ProcMacro bool `toml:"proc-macro,omitempty"`
Harness bool `toml:"harness,omitempty"`
Test bool `toml:"test,omitempty"`
DocTest bool `toml:"doctest,omitempty"`
Bench bool `toml:"bench,omitempty"`
Doc bool `toml:"doc,omitempty"`
Plugin bool `toml:"plugin,omitempty"`
}
type BinConfig struct {
Name string `toml:"name,omitempty"`
Path string `toml:"path,omitempty"`
Test bool `toml:"test,omitempty"`
Bench bool `toml:"bench,omitempty"`
Doc bool `toml:"doc,omitempty"`
Plugin bool `toml:"plugin,omitempty"`
Harness bool `toml:"harness,omitempty"`
Required bool `toml:"required,omitempty"`
}
type Profile struct {
Opt string `toml:"opt-level,omitempty"`
Debug bool `toml:"debug,omitempty"`
Rpath bool `toml:"rpath,omitempty"`
LtoFlags []string `toml:"lto,omitempty"`
Debug_assertions bool `toml:"debug-assertions,omitempty"`
Codegen map[string]string `toml:"codegen-units,omitempty"`
Panic string `toml:"panic,omitempty"`
Incremental bool `toml:"incremental,omitempty"`
Overflow_checks bool `toml:"overflow-checks,omitempty"`
}
type WorkspaceConfig struct {
Members []string `toml:"members,omitempty"`
ExcludeMembers []string `toml:"exclude,omitempty"`
DefaultMembers []string `toml:"default-members,omitempty"`
Resolver string `toml:"resolver,omitempty"`
}
type RustToolchain struct {
// The toolchain specification
Toolchain ToolchainSpec `toml:"toolchain"`
}
type ToolchainSpec struct {
Channel string `toml:"channel"`
Version string `toml:"version,omitempty"`
Components []string `toml:"components,omitempty"`
Targets []string `toml:"targets,omitempty"`
Profile string `toml:"profile,omitempty"`
}
// parseRustToolchain parses a rust-toolchain.toml file
func parseRustToolchain(ctx *generate.GenerateContext) (*RustToolchain, error) {
var toolchain RustToolchain
// Try to read rust-toolchain.toml first (newer format)
err := ctx.App.ReadTOML("rust-toolchain.toml", &toolchain)
if err == nil {
return &toolchain, nil
}
// Fall back to rust-toolchain file (older format)
content, err := ctx.App.ReadFile("rust-toolchain")
if err != nil {
return nil, fmt.Errorf("no rust-toolchain files found: %w", err)
}
// Old format just contains the channel/version as plain text
channel := strings.TrimSpace(string(content))
return &RustToolchain{
Toolchain: ToolchainSpec{
Channel: channel,
},
}, nil
}
+52
View File
@@ -0,0 +1,52 @@
package rust
import (
"testing"
testingUtils "github.com/railwayapp/railpack/core/testing"
"github.com/stretchr/testify/require"
)
func TestRust(t *testing.T) {
tests := []struct {
name string
path string
detected bool
rustVersion string
}{
{
name: "rust ring",
path: "../../../examples/rust-ring",
detected: true,
rustVersion: "1.84.0",
},
{
name: "node",
path: "../../../examples/node-npm",
detected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := testingUtils.CreateGenerateContext(t, tt.path)
provider := RustProvider{}
detected, err := provider.Detect(ctx)
require.NoError(t, err)
require.Equal(t, tt.detected, detected)
if detected {
err = provider.Initialize(ctx)
require.NoError(t, err)
err = provider.Plan(ctx)
require.NoError(t, err)
if tt.rustVersion != "" {
rustVersion := ctx.Resolver.Get("rust")
require.Equal(t, tt.rustVersion, rustVersion.Version)
}
}
})
}
}
+2
View File
@@ -78,6 +78,8 @@ export default defineConfig({
{ label: "Java", link: "/languages/java" },
{ label: "Python", link: "/languages/python" },
{ label: "Deno", link: "/languages/deno" },
{ label: "Ruby", link: "/languages/ruby" },
{ label: "Rust", link: "/languages/rust" },
{ label: "Node", link: "/languages/node" },
{ label: "Staticfile", link: "/languages/staticfile" },
{ label: "Shell Scripts", link: "/languages/shell" },
+51
View File
@@ -0,0 +1,51 @@
---
title: Rust
description: Building Rust applications with Railpack
---
Railpack builds and deploys Rust applications.
## Detection
Your project will be detected as a Rust application if any of these conditions are met:
- A `Cargo.toml` file is present
## Versions
The Rust version is determined in the following order:
- Set via the `package.edition` field in the `Cargo.toml` file
- Set via the `RAILPACK_RUST_VERSION` environment variable
- Read from the `.rust-version` or `rust-version.txt` file
- Read from the `package.rust-version` field in the `Cargo.toml` file
- Read from the `toolchain.version` field in the `rust-toolchain.toml` file
- Defaults to `1.85.1`
## Runtime Variables
These variables are available at runtime:
```sh
ROCKET_ADDRESS="0.0.0.0"
```
## Configuration
Railpack builds your Rust application based on your project structure. The build process:
- Installs Rust and required system dependencies
- Installs package dependencies
- Compiles the application to a binary
The start command is:
```sh
./bin/<project-name>
```
### Config Variables
| Variable | Description | Example |
| -------------------------- | --------------------------- | ------------ |
| `RAILPACK_RUST_VERSION` | Override the Rust version | `1.85.1` |
@@ -0,0 +1,13 @@
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust
### Rust ###
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# End of https://www.toptal.com/developers/gitignore/api/rust
@@ -0,0 +1,4 @@
[workspace]
members = [
"example/*"
]
@@ -0,0 +1,9 @@
[package]
name = "binary"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies.library]
path = "../library"
@@ -0,0 +1,3 @@
fn main() {
println!("{}", library::MESSAGE);
}
@@ -0,0 +1,8 @@
[package]
name = "library"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@@ -0,0 +1 @@
pub const MESSAGE: &str = "Hello from rust";
@@ -0,0 +1,5 @@
[
{
"expectedOutput": "Hello from rust"
}
]
+13
View File
@@ -0,0 +1,13 @@
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust
### Rust ###
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# End of https://www.toptal.com/developers/gitignore/api/rust
@@ -0,0 +1,5 @@
[workspace]
members = [
"binary",
"library"
]
@@ -0,0 +1,9 @@
[package]
name = "binary"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies.library]
path = "../library"
@@ -0,0 +1,3 @@
fn main() {
println!("{}", library::MESSAGE);
}
@@ -0,0 +1,8 @@
[package]
name = "library"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@@ -0,0 +1 @@
pub const MESSAGE: &str = "Hello from rust";
+5
View File
@@ -0,0 +1,5 @@
[
{
"expectedOutput": "Hello from rust"
}
]
+13
View File
@@ -0,0 +1,13 @@
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust
### Rust ###
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# End of https://www.toptal.com/developers/gitignore/api/rust
@@ -0,0 +1,8 @@
[package]
name = "rust-custom-toolchain"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@@ -0,0 +1,4 @@
[toolchain]
channel = "nightly-2024-08-12"
version = "1.59.0"
profile = "minimal"
@@ -0,0 +1,3 @@
fn main() {
println!("hello from custom toolchain");
}
+5
View File
@@ -0,0 +1,5 @@
[
{
"expectedOutput": "hello from custom toolchain"
}
]
+13
View File
@@ -0,0 +1,13 @@
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust
### Rust ###
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# End of https://www.toptal.com/developers/gitignore/api/rust
+9
View File
@@ -0,0 +1,9 @@
[package]
name = "rust-custom-version"
version = "0.1.0"
edition = "2021"
rust-version = "1.56.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+3
View File
@@ -0,0 +1,3 @@
fn main() {
println!("hello from custom version");
}
+5
View File
@@ -0,0 +1,5 @@
[
{
"expectedOutput": "hello from custom version"
}
]
+2
View File
@@ -0,0 +1,2 @@
/target
!src/bin/
+7
View File
@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "rust-multiple-bins"
version = "0.1.0"
+9
View File
@@ -0,0 +1,9 @@
[package]
name = "rust-multiple-bins"
version = "0.1.0"
edition = "2021"
default-run = "bin1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@@ -0,0 +1,3 @@
fn main() {
println!("This is Bin 1!");
}
@@ -0,0 +1,3 @@
fn main() {
println!("This is Bin 2!");
}
+3
View File
@@ -0,0 +1,3 @@
fn main() {
println!("This is the main Bin!");
}
+5
View File
@@ -0,0 +1,5 @@
[
{
"expectedOutput": "This is Bin 1!"
}
]
+13
View File
@@ -0,0 +1,13 @@
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust
### Rust ###
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# End of https://www.toptal.com/developers/gitignore/api/rust
+10
View File
@@ -0,0 +1,10 @@
[package]
name = "rust-open-ssl"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
openssl = "0.10.41"
openssl-sys = "0.9.75"
+5
View File
@@ -0,0 +1,5 @@
use openssl as _;
fn main() {
println!("hello from rust openssl")
}
+5
View File
@@ -0,0 +1,5 @@
[
{
"expectedOutput": "hello from rust openssl"
}
]
+14
View File
@@ -0,0 +1,14 @@
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust
### Rust ###
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# End of https://www.toptal.com/developers/gitignore/api/rust
+9
View File
@@ -0,0 +1,9 @@
[package]
name = "rust-ring"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ring = "0.16.20"
+5
View File
@@ -0,0 +1,5 @@
use ring as _;
fn main() {
println!("Hello from rust");
}
+5
View File
@@ -0,0 +1,5 @@
[
{
"expectedOutput": "Hello from rust"
}
]
+14
View File
@@ -0,0 +1,14 @@
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust
### Rust ###
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# End of https://www.toptal.com/developers/gitignore/api/rust
+9
View File
@@ -0,0 +1,9 @@
[package]
name = "rocket"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rocket = "0.5.0-rc.1"
+12
View File
@@ -0,0 +1,12 @@
#[macro_use]
extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"Hello, from Rocket!"
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![index])
}
+5
View File
@@ -0,0 +1,5 @@
[
{
"expectedOutput": "Rocket has launched"
}
]