Skip to content

Commit

Permalink
Merge pull request #14 from Kerosene-Labs/add-deps-during-compilation
Browse files Browse the repository at this point in the history
Add deps during compilation
  • Loading branch information
hlafaille authored Oct 17, 2024
2 parents 25816e9 + 980edcc commit 8096bf8
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 34 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"makefile.configureOnOpen": false
}
13 changes: 7 additions & 6 deletions core/dependency/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,31 @@ package dependency
import (
"os"

"kerosenelabs.com/espresso/core/registry"
"kerosenelabs.com/espresso/core/util"
)

// CacheResolvedDependency fetches the resolved dependency from the internet
func CacheResolvedDependency(resolvedDependency ResolvedDependency) error {
// get our package signature
packageSignature := registry.CalculatePackageSignature(resolvedDependency.Package, resolvedDependency.PackageVersion)

// get where we should store this package
espressoPath, err := util.GetEspressoDirectoryPath()
if err != nil {
return err
}
pkgPath := espressoPath + "/cachedPackages/" + packageSignature + ".jar"

// ensure the package path exists
err = os.MkdirAll(espressoPath+"/cachedPackages", 0755)
if err != nil {
return err
}

// get our package cache path
pkgPath, err := resolvedDependency.GetCachePath()
if err != nil {
return err
}

// download the file
err = util.DownloadFile(pkgPath, resolvedDependency.PackageVersion.ArtifactUrl)
err = util.DownloadFile(pkgPath.Absolute, resolvedDependency.PackageVersion.ArtifactUrl)
if err != nil {
return err
}
Expand Down
31 changes: 25 additions & 6 deletions core/dependency/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,30 @@ import (

"kerosenelabs.com/espresso/core/context/project"
"kerosenelabs.com/espresso/core/registry"
"kerosenelabs.com/espresso/core/util"
)

// ResolvedDependency represents a match between a project dependency and a registry package.
type ResolvedDependency struct {
Dependency project.Dependency
Package registry.Package
PackageVersion registry.PackageVersionDeclaration
Dependency project.Dependency
Package registry.Package
PackageVersion registry.PackageVersionDeclaration
Registry project.Registry
PackageSignature string
}

// GetCachePath returns the absolute filesystem path to where the cached package should be located. Please note,
// this function will always return the path of the .jar even if it does not exist.
//
// You should use PackageCachePath.DoesExist() to ensure this path exists if you're depennding on the package.
func (resolvedDependency ResolvedDependency) GetCachePath() (util.Path, error) {
packageSignature := registry.CalculatePackageSignature(resolvedDependency.Registry, resolvedDependency.Package, resolvedDependency.PackageVersion)
espressoPath, err := util.GetEspressoDirectoryPath()
if err != nil {
return util.Path{}, err
}
pkgPath := espressoPath + "/cachedPackages/" + packageSignature + ".jar"
return util.Path{Absolute: pkgPath}, nil
}

// ResolveDependency resolves the given dependency. This function will iterate over the given registries,
Expand All @@ -39,9 +56,11 @@ func ResolveDependency(dependency project.Dependency, registries []project.Regis
for _, version := range pkg.Versions {
if version.Number == depVersionStr {
return ResolvedDependency{
Dependency: dependency,
Package: pkg,
PackageVersion: version,
Dependency: dependency,
Package: pkg,
PackageVersion: version,
Registry: reg,
PackageSignature: registry.CalculatePackageSignature(reg, pkg, version),
}, nil
}
}
Expand Down
6 changes: 3 additions & 3 deletions core/registry/implementation.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ func GetRegistryPackages(reg project.Registry) ([]Package, error) {
return pkgs, nil
}

// GenerateSignature generates a unique signature of a package and version. This can be used to uniquely
// CalculatePackageSignature generates a unique signature of a package and version. This can be used to uniquely
// reference a local copy of a packages across registries.
func CalculatePackageSignature(dep Package, version PackageVersionDeclaration) string {
return fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("%s:%s:%s", dep.Group, dep.Name, version.Number))))
func CalculatePackageSignature(registry project.Registry, pkg Package, version PackageVersionDeclaration) string {
return fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("%s:%s:%s:%s", registry.Name, pkg.Group, pkg.Name, version.Number))))
}
27 changes: 13 additions & 14 deletions core/service/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/fatih/color"
"kerosenelabs.com/espresso/core/context/project"
"kerosenelabs.com/espresso/core/dependency"
"kerosenelabs.com/espresso/core/registry"
"kerosenelabs.com/espresso/core/source"
"kerosenelabs.com/espresso/core/toolchain"
"kerosenelabs.com/espresso/core/util"
Expand All @@ -26,7 +25,8 @@ func BuildProject() {
util.ErrorQuit("An error occurred while getting the project context: %s", err)
}

color.Cyan("-- [%s] Beginning build, please ensure you are compliant with all dependency licenses\n", projectContext.Config.Name)
color.Cyan("- Beginning build of '%s'", projectContext.Config.Name)
color.Cyan("-- Note: please ensure you are compliant with all dependency licenses")

// discover source files
files, err := source.DiscoverSourceFiles(projectContext.Config)
Expand All @@ -45,7 +45,7 @@ func BuildProject() {
if err != nil {
util.ErrorQuit("An error occurred while compiling a source file: %s\n", err)
}
color.Blue("Compiled: " + f.Path)
color.Black("--- Compiled: " + f.Path)
}(&value)
}
wg.Wait()
Expand All @@ -56,7 +56,7 @@ func BuildProject() {
if err != nil {
util.ErrorQuit(fmt.Sprintf("An error occurred while packaging the classes: %s\n", err))
}
color.Blue("Finished packaging distributable")
color.Blue("-- Finished packaging distributable")

// iterate over each dependency, resolve it and copy it
distPath, err := toolchain.GetDistPath(projectContext.Config)
Expand All @@ -70,26 +70,25 @@ func BuildProject() {
depCopyWg.Add(1)
go func() {
defer depCopyWg.Done()
color.Cyan("-- Beginning copy of '%s:%s' to distributable", dep.Group, dep.Name)
resolved, err := dependency.ResolveDependency(dep, projectContext.Config.Registries)
if err != nil {
util.ErrorQuit(fmt.Sprintf("Unable to resolve dependency: %s", err))
}

// calculate the should-be location of this jar locally
espressoPath, err := util.GetEspressoDirectoryPath()
// get the cache path for this package
cachePath, err := resolved.GetCachePath()
if err != nil {
util.ErrorQuit(fmt.Sprintf("Unable to get the espresso home: %s", espressoPath))
util.ErrorQuit("Unable to find cache path for dependency: %s", err)
}
signature := registry.CalculatePackageSignature(resolved.Package, resolved.PackageVersion)
cachedPackageHome := espressoPath + "/cachedPackages" + signature + ".jar"

// copy the file
util.CopyFile(cachedPackageHome, *distPath+"/libs")

color.Blue("Copied '%s:%s' to distributable", dep.Group, dep.Name)
err = util.CopyFile(cachePath.Absolute, fmt.Sprintf(*distPath+"/libs/%s.jar", dep.Name))
if err != nil {
util.ErrorQuit(fmt.Sprintf("Unable to copy file: %s", err))
}
color.Black("--- Copied '%s:%s' to distributable", dep.Group, dep.Name)
}()
}
depCopyWg.Wait()
color.Green("Done!")
color.Green("- Done!")
}
21 changes: 20 additions & 1 deletion core/toolchain/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,39 @@ import (
"os/exec"

"kerosenelabs.com/espresso/core/context/project"
"kerosenelabs.com/espresso/core/dependency"
"kerosenelabs.com/espresso/core/source"
"kerosenelabs.com/espresso/core/util"
)

// CompileSourceFile compiles the sourcefile with the given project toolchain
func CompileSourceFile(cfg project.ProjectConfig, srcFile source.SourceFile) error {
// build our classpath value
// initialize our classpath value
cpVal := ""
if util.IsDebugMode() {
cpVal = "ESPRESSO_DEBUG/src/java"
} else {
cpVal = "src/java"
}

// iterate over dependencies, resolve each one and add it to the classpath argument value
for _, dep := range cfg.Dependencies {
// resolve our dependency
resolvedDependency, err := dependency.ResolveDependency(dep, cfg.Registries)
if err != nil {
return err
}

// get our cache path for the jar
depCachePath, err := resolvedDependency.GetCachePath()
if err != nil {
return err
}

// append it to the classpath value
cpVal += ":" + depCachePath.Absolute
}

// run the compiler
command := cfg.Toolchain.Path + "/bin/javac"
args := []string{}
Expand Down
53 changes: 49 additions & 4 deletions core/toolchain/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,59 @@ import (
"errors"
"os"
"os/exec"
"unicode/utf8"

"kerosenelabs.com/espresso/core/context/project"
"kerosenelabs.com/espresso/core/dependency"
"kerosenelabs.com/espresso/core/util"
)

func capLinesAt72Bytes(input string) []string {
var lines []string
var currentLine string
var currentLineBytes int

for len(input) > 0 {
r, size := utf8.DecodeRuneInString(input) // Get next rune and its byte size
if currentLineBytes+size > 72 {
lines = append(lines, currentLine) // Add current line to lines
currentLine = "" // Reset current line
currentLineBytes = 0 // Reset byte counter
}
currentLine += string(r) // Add the rune to the current line
currentLineBytes += size // Track the byte size
input = input[size:] // Move to the next part of the string
}

if currentLineBytes > 0 {
lines = append(lines, currentLine) // Add the last line if not empty
}

return lines
}

// GenerateManifest generates a JVM manifest
func GenerateManifest(cfg project.ProjectConfig) string {
func GenerateManifest(cfg project.ProjectConfig) (string, error) {
base := "Manifest-Version: 1.0\n"
base += "Main-Class: " + cfg.BasePackage + ".Main\n"
base += "Created-By: Espresso"
return base
base += "Created-By: Espresso\n"

// iterate over dependencies, resolve them and add them to the manifest base
classPath := "Class-Path: "
for _, dep := range cfg.Dependencies {
resolvedDependency, err := dependency.ResolveDependency(dep, cfg.Registries)
if err != nil {
return "", err
}
classPath += "libs/" + resolvedDependency.Package.Name + ".jar "
}

splitLines := capLinesAt72Bytes(classPath)
for _, line := range splitLines {
base += line + "\n"
}

return base, nil
}

// Write the Manifest to the build directory
Expand All @@ -38,7 +80,10 @@ func WriteManifest(cfg project.ProjectConfig) error {
defer file.Close()

// write the file
content := GenerateManifest(cfg)
content, err := GenerateManifest(cfg)
if err != nil {
return err
}
_, err = file.WriteString(content)
if err != nil {
return err
Expand Down
13 changes: 13 additions & 0 deletions core/util/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ package util

import "os/user"

type Path struct {
Absolute string
}

// DoesExist returns if the path does or does not exist.
func (p Path) DoesExist() (bool, error) {
exists, err := DoesPathExist(p.Absolute)
if err != nil {
return false, err
}
return exists, nil
}

// GetEspressoDirectoryPath gets the path to the user's .espresso directory.
func GetEspressoDirectoryPath() (string, error) {
user, err := user.Current()
Expand Down

0 comments on commit 8096bf8

Please sign in to comment.