added clyxc compiler
This commit is contained in:
@@ -123,8 +123,27 @@ To run programs directly, pass the path to the `.clx` files as arguments:
|
||||
|
||||
The Go implementation supports reading an optional ZIP archive appended directly to the end of the `clyx` binary. This allows you to package your Clyx source code into a single executable file.
|
||||
|
||||
To package your program, use the bundled `clyxc` utility, or:
|
||||
To package your program, you can use the `clyxc` utility.
|
||||
|
||||
#### Installing `clyxc`
|
||||
Install the utility directly from Git:
|
||||
```sh
|
||||
go install codeberg.org/luxferre/clyx/clyxc@latest
|
||||
```
|
||||
Alternatively, if compiling locally from the repository root:
|
||||
```sh
|
||||
go install ./clyxc
|
||||
```
|
||||
|
||||
#### Using `clyxc`
|
||||
Run the compiler by passing the output binary path followed by the list of source files or directories:
|
||||
```sh
|
||||
clyxc out-bin-path src1 src2...
|
||||
```
|
||||
*(Note: `clyxc` requires the main `clyx` interpreter binary to be installed in your `$GOPATH/bin` directory).*
|
||||
|
||||
#### Manual Packaging Alternative
|
||||
If you prefer not to use `clyxc`, you can package the application manually:
|
||||
1. Create a ZIP archive containing all your `.clx` source files.
|
||||
2. Append the ZIP archive to the compiled `clyx` binary:
|
||||
```sh
|
||||
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getGopath() string {
|
||||
gopath := os.Getenv("GOPATH")
|
||||
if gopath != "" {
|
||||
return gopath
|
||||
}
|
||||
out, err := exec.Command("go", "env", "GOPATH").Output()
|
||||
if err == nil {
|
||||
return strings.TrimSpace(string(out))
|
||||
}
|
||||
home, err := os.UserHomeDir()
|
||||
if err == nil {
|
||||
return filepath.Join(home, "go")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func addPathToZip(zw *zip.Writer, path string) error {
|
||||
return filepath.Walk(path, func(walkPath string, walkInfo os.FileInfo, walkErr error) error {
|
||||
if walkErr != nil {
|
||||
return walkErr
|
||||
}
|
||||
if walkInfo.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
file, err := os.Open(walkPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
header, err := zip.FileInfoHeader(walkInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Convert path to use forward slashes for ZIP compatibility
|
||||
relPath := filepath.ToSlash(walkPath)
|
||||
header.Name = relPath
|
||||
header.Method = zip.Deflate
|
||||
|
||||
writer, err := zw.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = io.Copy(writer, file)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 3 {
|
||||
fmt.Println("Clyx compiler/bundler")
|
||||
fmt.Println("Usage: clyxc out-bin-path src1 src2...")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
outfile := os.Args[1]
|
||||
srcs := os.Args[2:]
|
||||
|
||||
// Check if output file exists
|
||||
if _, err := os.Stat(outfile); err == nil {
|
||||
fmt.Fprintf(os.Stderr, "File %s exists, won't overwrite!\n", outfile)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println(strings.Join(srcs, " "))
|
||||
|
||||
// Locate the Clyx interpreter binary
|
||||
gopath := getGopath()
|
||||
if gopath == "" {
|
||||
fmt.Fprintln(os.Stderr, "Error: GOPATH could not be determined")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
clyxName := "clyx"
|
||||
if runtime.GOOS == "windows" {
|
||||
clyxName = "clyx.exe"
|
||||
}
|
||||
clyxPath := filepath.Join(gopath, "bin", clyxName)
|
||||
|
||||
clyxBin, err := os.ReadFile(clyxPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: Clyx interpreter binary not found at %s. Please install it first using: go install codeberg.org/luxferre/clyx@latest\n", clyxPath)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Create ZIP archive in memory
|
||||
var zipBuf bytes.Buffer
|
||||
zw := zip.NewWriter(&zipBuf)
|
||||
|
||||
for _, src := range srcs {
|
||||
if err := addPathToZip(zw, src); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error adding %s to ZIP: %v\n", src, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if err := zw.Close(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error closing ZIP writer: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Write bundled executable
|
||||
out, err := os.OpenFile(outfile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error creating output file: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
if _, err := out.Write(clyxBin); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error writing Clyx binary: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if _, err := out.Write(zipBuf.Bytes()); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error writing ZIP archive: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("Executable bundled into %s\n", outfile)
|
||||
}
|
||||
Reference in New Issue
Block a user