Skip to content

Commit

Permalink
set nwn_script_comp as default compiler
Browse files Browse the repository at this point in the history
This commit sets `nwn_script_comp` as the default compiler and reuses the configuration options `nssCompiler` and `nssFlags`.  `nwn_script_comp` output is read through peg and modified to appear nasher-organic.
  • Loading branch information
tinygiant98 committed Dec 19, 2023
1 parent 278aec5 commit 8210dbb
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 74 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# nasher changelog

## 0.22.0: <data>

- neverwinter.nim's `nwn_script_comp` is now the default script compiler.
Users who want to continue using nwnsc must set the `nssCompiler` and
`nssFlags` configuration values as noted in the [readme](readme.md).

## 0.21.0: September 2, 2023

- The `compile` command now returns a non-zero exit code on failure. When
Expand Down
67 changes: 34 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,19 @@ of nasher for your OS and place a pointer to the location of the executable
file in your [`PATH` environment variable](https://superuser.com/a/284351).

In addition, you will need the following tools:
* [neverwinter.nim](https://github.com/niv/neverwinter.nim/releases) >= 1.6.4
* [neverwinter.nim](https://github.com/niv/neverwinter.nim/releases) >= 1.7.0
* [nwnt](https://github.com/WilliamDraco/NWNT) >= 1.3.3
* [nwnsc](https://github.com/nwneetools/nwnsc/releases) >= 1.1.3
* [git](https://git-scm.com/downloads)

Starting with 0.22.0, nasher's default script compiler is neverwinter.nim's
`nwn_script_comp`. If you'd like to use the legacy script compiler nwnsc,
you'll need:
* [nwnsc](https://github.com/nwneetools/nwnsc/releases) >= 1.1.3

#### Tips
* Keep the binaries for nasher, neverwinter.nim, and nwnsc in the same
location.
* Do not keep binaries in your nasher project folder
* Do not keep binaries in your nasher project folder.
* Do not publish binaries with your source control repository. If you are
collaborating, each team member should download and install the binaries
individually.
Expand All @@ -84,9 +88,11 @@ In addition, you will need the following tools:
First, install the following:
* [nim](https://nim-lang.org) and it package manager `nimble`. The easy way to
install is to use [choosenim](https://github.com/dom96/choosenim).
* [nwnsc](https://github.com/nwneetools/nwnsc) >= 1.1.3
* [git](https://git-scm.com/downloads)

Optionally, install nwnsc if you'd like to use the legacy script compiler:
* [nwnsc](https://github.com/nwneetools/nwnsc) >= 1.1.3

*Note: when building nasher, nimble will download and install neverwinter.nim
automatically. You do not need to install it yourself.*

Expand Down Expand Up @@ -130,31 +136,37 @@ alias nasher='docker run --rm -it -v ${pwd}:/nasher nwntools/nasher:latest '
```

#### Tips
Create batch/script files to run your most common nasher commands since the
* Create batch/script files to run your most common nasher commands since the
docker commands can be rather verbose. An excellent example of this is in [The
Frozen North](https://github.com/b5635/the-frozen-north) GitHub repository.

## Getting Started

### First-Time Setup
nasher will detect nwnsc and the neverwinter.nim tools if they are in your
`PATH`. You can also use nasher's `config` command to set the proper locations:
nasher will detect neverwinter.nim tools and your chosen script compiler if
they are in your `PATH` enviromental variable. You can also use nasher's
`config` command to set the proper locations if the tools are not on your
`PATH` variable:
```console
$ # Set the path to nwnsc
$ nasher config nssCompiler "%USERPROFILE%/bin/nwnsc.exe" # Windows
$ nasher config nssCompiler "~/.local/bin/nwnsc" # Posix
$ # Set the path to the script compiler
$ # neverwinter.nim script compiler
$ nasher config nssCompiler "%USERPROFILE%/bin/nwn_script_comp.exe" # Windows
$ nasher config nssCompiler "~/.local/bin/nwn_script_comp" # Posix
$ # or nwnsc (this must be set if you want to use nwnsc with nasher >=0.22.0)
$ nasher config nssCompiler "%USERPROFILE%/bin/nwnsc.exe" # Windows
$ nasher config nssCompiler "~/.local/bin/nwnsc" # Posix

$ # Set the path to nwn_erf
$ nasher config erfUtil "%USERPROFILE%/bin/nwn_erf.exe" # Windows
$ nasher config erfUtil "~/.local/bin/nwn_erf" # Posix
$ nasher config erfUtil "%USERPROFILE%/bin/nwn_erf.exe" # Windows
$ nasher config erfUtil "~/.local/bin/nwn_erf" # Posix

$ # Set the path to nwn_gff
$ nasher config gffUtil "%USERPROFILE%/bin/nwn_gff.exe" # Windows
$ nasher config gffUtil "~/.local/bin/nwn_gff" # Posix
$ nasher config gffUtil "%USERPROFILE%/bin/nwn_gff.exe" # Windows
$ nasher config gffUtil "~/.local/bin/nwn_gff" # Posix

$ # Set the path to nwn_tlk
$ nasher config tlkUtil "%USERPROFILE%/bin/nwn_tlk.exe" # Windows
$ nasher config tlkUtil "~/.local/bin/nwn_tlk" # Posix
$ nasher config tlkUtil "%USERPROFILE%/bin/nwn_tlk.exe" # Windows
$ nasher config tlkUtil "~/.local/bin/nwn_tlk" # Posix
```
nasher will also detect NWN if it was installed by Steam, Beamdog, or GOG. If
you are having issues getting nasher to recognize your NWN install, you can set
Expand Down Expand Up @@ -205,7 +217,7 @@ $ nasher install
You can get help for nasher or one of its commands using the `--help` flag:
```console
$ nasher --help # General help
$ nasher init --help # Command-specific help
$ nasher <command> --help # Command-specific help
```

If you're still stuck, you can get assistance in several locations:
Expand Down Expand Up @@ -324,7 +336,7 @@ file = "myPWtlk.tlk"
include = "src/tlk/*.json"
```

While you can write your own package file, the [`init`](#init) command will
While you can write your own configuration file, the [`init`](#init) command will
create one for you. It will show prompts for each section and provide useful
defaults. If you don't want to answer the prompts and just want to quickly
initialize the package, you can pass the `--default` flag when running `init`.
Expand All @@ -350,7 +362,7 @@ Some fields, while optional, are inherited from the package by
| --- | --- | --- |
| `file` | no | filename including extension be created; can optionally include path info |
| `group` | yes | a group a target may belong to; used to build multiple targets at once |
| `flags` | yes | command line arguments to send to nwnsc at compile-time |
| `flags` | yes | command line arguments to send to the script compiler at compile-time |
| `branch` | no | the git branch to use for source files |
| `modName` | no | the name to give a module target file |
| `modMinGameVersion` | no | the minimum game version to run a module target file |
Expand Down Expand Up @@ -381,7 +393,7 @@ must be specified before the child target.
| `parent` | no | no | a target to inherit missing values from (if missing, will inherit from `[package]`) |
| `file` | no | yes | filename including extension be created; can optionally include path info |
| `group` | yes | yes | a group this target belongs to; used to build multiple targets at once |
| `flags` | yes | yes | command line arguments to send to nwnsc at compile-time |
| `flags` | yes | yes | command line arguments to send to the script compiler at compile-time |
| `branch` | no | yes | the git branch to use for source files |
| `modName` | no | yes | the name to give a module target file |
| `modMinGameVersion` | no | yes | the minimum game version to run a module target file |
Expand Down Expand Up @@ -642,8 +654,8 @@ by passing the key/value pair as an option to the command.
- default (Posix): `nwnsc`
- default (Windows): `nwnsc.exe`
- `nssFlags`: the default flags to use on packages
- default: `-lowqey`
- note: since nwnsc can read the `NWN_ROOT` environment variable to find
- default: `` for `nwn_script_comp``, `-lowqey` for `nwnsc`
- note: since compilers can read the `NWN_ROOT` environment variable to find
your NWN install, it is preferable to use that rather than passing the
location through `nssFlags`. If `NWN_ROOT` is set (or if nasher can find
your NWN install without it), nwnsc should work fine using the default
Expand Down Expand Up @@ -704,17 +716,6 @@ by passing the key/value pair as an option to the command.
float value changes.
- default: `4`
- supported: `1` - `32`
- `modName`: the name for any module file to be generated by the target. This
is independent of the filename. Only relevant when `convert` will be called.
- default: ""
- `modMinGameVersion`: the minimum game version that can run any module file
generated by the target. Only relevant when `convert` will be called.
- default: ""
- note: if blank, the version in the `module.ifo` file will be unchanged.
- `modDescription`: the description for a module file generated by a target.
Only relevant when `convert` will be called.
- default: ""
- note: If blank, the description in the `module.ifo` file will be unchanged.
- `onMultipleSources`: an action to perform when multiple source files of the
same name are found for a target.
- default: `choose`
Expand Down
2 changes: 1 addition & 1 deletion nasher.nimble
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Package

version = "0.21.0"
version = "0.22.0"
author = "Michael A. Sinclair"
description = "A build tool for Neverwinter Nights projects"
license = "MIT"
Expand Down
40 changes: 30 additions & 10 deletions src/nasher/compile.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ Usage:
Description:
Compiles all nss sources for <target>. If <target> is not supplied, the first
target supplied by the config files will be compiled. The input and output
files are placed in .nasher/cache/<target>.
target supplied by the config files will be compiled. The input files are
placed in .nasher/cache/<target>. The output files are placed in the same
folder unless the compiler flags `-b` (for nwnsc`) or `-o`/`-d` (for
nwn_script_comp) are specified.
Compilation of scripts is handled automatically by 'nasher pack', so you only
need to use this if you want to compile the scripts without converting gff
Expand Down Expand Up @@ -117,10 +119,27 @@ proc getUpdated(updatedNSS: var seq[string], files: seq[string]): seq[string] =

updatedNss = result

proc getFlags(compiler: Compiler, opts: Options, target: Target): seq[string] =
let nssFlags = opts.get("nssFlags", compilerFlags[compiler.ord]).parseCmdLine
var flags = nssFlags & target.flags

case compiler:
of Organic:
let
installDir = opts.get("installDir", getEnv("NWN_HOME")).expandPath
rootDir = getNwnRootDir().expandPath

if installDir.len > 0: flags = flags & "--userdirectory" & installDir
if rootDir.len > 0: flags = flags & "--root" & rootDir

result = flags & "-c"
of Legacy:
result = flags

proc compile*(opts: Options, target: Target, updatedNss: var seq[string], exitCode: var int): bool =
let
cmd = opts["command"]
cacheDir = ".nasher" / "cache" / target.name
cacheDir = (".nasher" / "cache" / target.name)
abortOnCompileError =
if opts.hasKey("abortOnCompileError"):
if opts.get("abortOnCompileError", false): Answer.No
Expand All @@ -134,8 +153,8 @@ proc compile*(opts: Options, target: Target, updatedNss: var seq[string], exitCo
return cmd != "compile"

let
compiler = opts.findBin("nssCompiler", "nwnsc", "script compiler")
userFlags = opts.get("nssFlags", "-lowqey").parseCmdLine
bin = opts.findBin("nssCompiler", $Compiler.low, "script compiler")
compiler = parseEnum[Compiler](bin.splitPath.tail.splitFile.name, Compiler.low)

withDir(cacheDir):
# If we are only compiling one file...
Expand Down Expand Up @@ -186,8 +205,9 @@ proc compile*(opts: Options, target: Target, updatedNss: var seq[string], exitCo
for chunk, scripts in distribute(scripts, chunks):
if chunks > 1:
info("Compiling", "$1 scripts (chunk $2/$3)" % [$scripts.len, $(chunk + 1), $chunks])
let args = userFlags & target.flags & scripts
if runCompiler(compiler, args) != 0:

let args = compiler.getFlags(opts, target) & scripts
if runCompiler(bin, args) != 0:
warning("Errors encountered during compilation (see above)")
if chunk + 1 < chunks:
let forced = getForceAnswer()
Expand All @@ -204,8 +224,8 @@ proc compile*(opts: Options, target: Target, updatedNss: var seq[string], exitCo
let unmatchedNcs = executables.filterIt(not fileExists(it.changeFileExt("ncs")))
if unmatchedNcs.len > 0:
warning("""
Compiled only $1 of $2 scripts. The following executable scripts do not
have matching .ncs files due to an nwnsc error: $3""".dedent %
Compiled $1 of $2 scripts. The following executable scripts do not
have a matching compiled (.ncs) script file: $3""".dedent %
[$(scripts.len - unmatchedNcs.len), $scripts.len, unmatchedNcs.join(", ")])
if cmd in ["pack", "install", "serve", "test", "play"]:
let forced = getForceAnswer()
Expand All @@ -219,7 +239,7 @@ proc compile*(opts: Options, target: Target, updatedNss: var seq[string], exitCo
else:
exitCode = QuitFailure
else:
success("All executable scripts have a matching compiled (.ncs) script", LowPriority);
success("All executable scripts have a matching compiled (.ncs) script file", LowPriority);
if scripts.len > 0:
success("Compiled $1 scripts" % $scripts.len)

Expand Down
2 changes: 1 addition & 1 deletion src/nasher/utils/cli.nim
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type
None, No, Yes, Default

const
colWidth = len("Initializing")
colWidth = len("Compile Error:")
foregrounds: array[Error .. Prompt, ForegroundColor] =
[fgRed, fgYellow, fgCyan, fgGreen, fgYellow]
styles: array[DebugPriority .. HighPriority, set[Style]] =
Expand Down
83 changes: 56 additions & 27 deletions src/nasher/utils/compiler.nim
Original file line number Diff line number Diff line change
@@ -1,39 +1,68 @@
import osproc, parseutils, sequtils, streams, strutils
import os, osproc, parseutils, pegs, sequtils, streams, strutils

import cli

type Compiler* = enum
Organic = "nwn_script_comp" #default
Legacy = "nwnsc"

proc parseCompilerOutput(line: var string): bool =
## Intercepts nwnsc's output and converts it into nasher's cli format. Returns
## whether any errors were detected. We have to do this here because nwnsc
## does not return consistent exit codes.
var
token: string
parsed = line.parseUntil(token, ':') + 2

case token
of "Compiling":
info("Compiling", line[parsed..^1])
of "Error":
error(line[parsed..^1])
else:
if token == line:
debug("Compiler:", line)
else:
var lines = line.split(':').mapIt(it.strip)
if lines.contains("Error"):
error(lines.filterIt(it != "Error").join("\n"))
result = true
elif lines.contains("Warning"):
warning(lines.filterIt(it != "Warning").join("\n"))
const compilerFlags* =
# Default compiler flags; ordered referenced to `Compiler` enum above
["-y", "-lowqey"]

proc parseCompilerOutput(line: var string, compiler: Compiler): bool =
## Intercepts the compiler's output and converts it into nasher's cli format.
case compiler:
of Organic:
if line =~ peg"""
output <- error / result
error <- type data* path file errorData data
result <- type data* results
type <- {[EI]} \s*
data <- \[ @ \] \s*
path <- (([A-Z][:]) / '~' / \/)? (![:] . )* [:] \s*
file <- {(![:] .)*}[:] \s*
errorData <- "ERROR:" \s* {(!\[.)*} &\[
results <- {.*}
""":
case matches[0]:
of "I":
display("Results:", matches[1])
of "E":
error("Compile Error:", "$1 :: $2" % [matches[1], matches[2].strip])
result = true
else:
#Catchall to find other errors I didn't expect
display("Unknown Compiler Output", line)
of Legacy:
var
token: string
parsed = line.parseUntil(token, ':') + 2

case token
of "Compiling":
info("Compiling", line[parsed..^1])
of "Error":
error(line[parsed..^1])
else:
display(lines.join("\n"))
if token == line:
debug("Compiler:", line)
else:
var lines = line.split(':').mapIt(it.strip)
if lines.contains("Error"):
error(lines.filterIt(it != "Error").join("\n"))
result = true
elif lines.contains("Warning"):
warning(lines.filterIt(it != "Warning").join("\n"))
else:
display(lines.join("\n"))

proc runCompiler*(cmd: string, args: openArray[string] = []): int =
## Runs the nwnsc compiler and returns its error code
## Runs the compiler and returns its error code
let
params = args.filterIt(it.len > 0)
options = {poUsePath, poStdErrToStdOut}
compiler = parseEnum[Compiler](cmd.splitPath.tail.splitFile.name, Compiler.low)

debug("Executing", "$1 $2" % [cmd, params.join(" ")])
var
Expand All @@ -43,7 +72,7 @@ proc runCompiler*(cmd: string, args: openArray[string] = []): int =

while p.running:
if s.readLine(line):
if line.parseCompilerOutput:
if line.parseCompilerOutput(compiler):
result = 1

p.close
4 changes: 2 additions & 2 deletions src/nasher/utils/shared.nim
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ Utility Options:
const CompilerOpts = """
Compiler Options:
--abortOnCompileError Quit if an error was encountered during compilation
--nssCompiler:<bin> Binary for compiling nss scripts [default: nwnsc]
--nssFlags:<flags> Flags to pass to the compiler [default: -lowqey]
--nssCompiler:<bin> Binary for compiling nss scripts [default: nwn_script_comp]
--nssFlags:<flags> Flags to pass to the compiler [default: <none>]
--nssChunks:<n> Max scripts to compile per compiler exec [default: 500]
"""

Expand Down

0 comments on commit 8210dbb

Please sign in to comment.