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.
|
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.
|
1. Create a ZIP archive containing all your `.clx` source files.
|
||||||
2. Append the ZIP archive to the compiled `clyx` binary:
|
2. Append the ZIP archive to the compiled `clyx` binary:
|
||||||
```sh
|
```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