Initial version
This commit is contained in:
parent
cb6e2d5139
commit
7471d94751
4 changed files with 361 additions and 0 deletions
19
.gitignore
vendored
19
.gitignore
vendored
|
|
@ -1 +1,20 @@
|
||||||
nimcache/
|
nimcache/
|
||||||
|
# Swap
|
||||||
|
[._]*.s[a-v][a-z]
|
||||||
|
[._]*.sw[a-p]
|
||||||
|
[._]s[a-rt-v][a-z]
|
||||||
|
[._]ss[a-gi-z]
|
||||||
|
[._]sw[a-p]
|
||||||
|
|
||||||
|
# Session
|
||||||
|
Session.vim
|
||||||
|
|
||||||
|
# Temporary
|
||||||
|
.netrwhist
|
||||||
|
*~
|
||||||
|
# Auto-generated tag files
|
||||||
|
tags
|
||||||
|
# Persistent undo
|
||||||
|
[._]*.un~
|
||||||
|
|
||||||
|
switch_build
|
||||||
|
|
|
||||||
35
README.md
35
README.md
|
|
@ -1,2 +1,37 @@
|
||||||
# switch-build
|
# switch-build
|
||||||
Build switch homebrew apps the easy way
|
Build switch homebrew apps the easy way
|
||||||
|
|
||||||
|
# Options
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ switch_build --help
|
||||||
|
|
||||||
|
switch-build [options] project-file.nim
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-d, --devkitProPath:PATH devkitpro installation path for switch-build.
|
||||||
|
Required if DEVKITPRO environment var is unset
|
||||||
|
-c, --devkitCompilerPath:PATH
|
||||||
|
the path where the binaries for the devkitpro
|
||||||
|
compiler lives. (defaults to "$DKP/devkitA64/bin/")
|
||||||
|
-t, --tools:PATH the devkitpro tools (defaults to "$DKP/tools/bin")
|
||||||
|
-o, --output:PATH output files in a specified directory (defaults to "build")
|
||||||
|
-b, --build:TYPE the type of output file you want (defaults to "all")
|
||||||
|
and can be specified multiple times.
|
||||||
|
TYPE is one of: "all", "nro", "nso", "pfs0", "nacp",
|
||||||
|
or "lst"
|
||||||
|
-l, --libs:STR additional linker args to pass to the compiler.
|
||||||
|
Ex: --libs="-lsdl -Lpath/to/lib"
|
||||||
|
|
||||||
|
-i, --includes:STR additional includes to pass to the compiler
|
||||||
|
Ex: --includes="-Ipath/to/include -Ipath/to/another/include"
|
||||||
|
-n, --name:STR the output file name to use. (defaults to input file name)
|
||||||
|
-a, --author:STR sets the author name for the generate NRO and NACP file
|
||||||
|
-v, --version:STR sets the version information for the generated NRO and NACP
|
||||||
|
file
|
||||||
|
-p, --icon:PATH sets the icon to use for the generated NRO and NACP
|
||||||
|
(defaults to "$DKP/libnx/default_icon.jpg)
|
||||||
|
-h, --help show this help
|
||||||
|
|
||||||
|
Note, single letter options that take an argument require a colon. E.g. -p:PATH.
|
||||||
|
```
|
||||||
|
|
|
||||||
291
src/switch_build.nim
Normal file
291
src/switch_build.nim
Normal file
|
|
@ -0,0 +1,291 @@
|
||||||
|
import os, ospaths, osproc, parseopt, sequtils, streams, strutils
|
||||||
|
|
||||||
|
type
|
||||||
|
BuildInfo = object
|
||||||
|
filename: string
|
||||||
|
name: string
|
||||||
|
author: string
|
||||||
|
version: string
|
||||||
|
icon: string
|
||||||
|
|
||||||
|
dkpPath: string
|
||||||
|
|
||||||
|
compilerPath: string
|
||||||
|
toolsPath: string
|
||||||
|
|
||||||
|
outDir: string
|
||||||
|
libs: string
|
||||||
|
includes: string
|
||||||
|
|
||||||
|
elfLocation: string
|
||||||
|
|
||||||
|
proc execProc(cmd: string): string {.discardable.}=
|
||||||
|
result = ""
|
||||||
|
var
|
||||||
|
p = startProcess(cmd, options = {poStdErrToStdOut, poUsePath, poEvalCommand})
|
||||||
|
|
||||||
|
outp = outputStream(p)
|
||||||
|
line = newStringOfCap(120).TaintedString
|
||||||
|
|
||||||
|
while true:
|
||||||
|
if outp.readLine(line):
|
||||||
|
result.add(line)
|
||||||
|
result.add("\n")
|
||||||
|
elif not running(p): break
|
||||||
|
|
||||||
|
var x = p.peekExitCode()
|
||||||
|
if x != 0:
|
||||||
|
raise newException(
|
||||||
|
Exception,
|
||||||
|
"Command failed: " & $x &
|
||||||
|
"\nCMD: " & $cmd &
|
||||||
|
"\nRESULT: " & $result
|
||||||
|
)
|
||||||
|
|
||||||
|
proc writeVersion() =
|
||||||
|
echo "Switch build version $version." % ["version", "0.1.0"]
|
||||||
|
|
||||||
|
proc writeHelp() =
|
||||||
|
writeVersion()
|
||||||
|
echo """
|
||||||
|
::
|
||||||
|
switch-build [options] project-file.nim
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-d, --devkitProPath:PATH devkitpro installation path for switch-build.
|
||||||
|
Required if DEVKITPRO environment var is unset
|
||||||
|
-c, --devkitCompilerPath:PATH
|
||||||
|
the path where the binaries for the devkitpro
|
||||||
|
compiler lives. (defaults to "$DKP/devkitA64/bin/")
|
||||||
|
-t, --tools:PATH the devkitpro tools (defaults to "$DKP/tools/bin")
|
||||||
|
-o, --output:PATH output files in a specified directory (defaults to "build")
|
||||||
|
-b, --build:TYPE the type of output file you want (defaults to "all")
|
||||||
|
and can be specified multiple times.
|
||||||
|
TYPE is one of: "all", "nro", "nso", "pfs0", "nacp",
|
||||||
|
or "lst"
|
||||||
|
-l, --libs:STR additional linker args to pass to the compiler.
|
||||||
|
Ex: --libs="-lsdl -Lpath/to/lib"
|
||||||
|
|
||||||
|
-i, --includes:STR additional includes to pass to the compiler
|
||||||
|
Ex: --includes="-Ipath/to/include -Ipath/to/another/include"
|
||||||
|
-n, --name:STR the output file name to use. (defaults to input file name)
|
||||||
|
-a, --author:STR sets the author name for the generate NRO and NACP file
|
||||||
|
-v, --version:STR sets the version information for the generated NRO and NACP
|
||||||
|
file
|
||||||
|
-p, --icon:PATH sets the icon to use for the generated NRO and NACP
|
||||||
|
(defaults to "$DKP/libnx/default_icon.jpg)
|
||||||
|
-h, --help show this help
|
||||||
|
|
||||||
|
Note, single letter options that take an argument require a colon. E.g. -p:PATH.
|
||||||
|
"""
|
||||||
|
|
||||||
|
proc buildElf(buildInfo: BuildInfo): string =
|
||||||
|
echo "Building elf file..."
|
||||||
|
let cmd = "nim c " &
|
||||||
|
"--os:nintendoswitch " & buildInfo.filename
|
||||||
|
execProc cmd
|
||||||
|
|
||||||
|
result = buildInfo.filename.splitFile().dir / buildInfo.name & ".elf"
|
||||||
|
|
||||||
|
proc buildNso(buildInfo: BuildInfo): string =
|
||||||
|
let name = buildInfo.name
|
||||||
|
|
||||||
|
result = buildInfo.outDir / name & ".nso"
|
||||||
|
|
||||||
|
var cmd = buildInfo.toolsPath / "elf2nso "
|
||||||
|
cmd &= buildInfo.elfLocation & " " & result
|
||||||
|
|
||||||
|
execProc cmd
|
||||||
|
|
||||||
|
|
||||||
|
proc buildPfs0(buildInfo: BuildInfo): string =
|
||||||
|
let nsoPath = buildNso(buildInfo)
|
||||||
|
|
||||||
|
let
|
||||||
|
name = buildInfo.name
|
||||||
|
outDir = buildInfo.outDir
|
||||||
|
toolsPath = buildInfo.toolsPath
|
||||||
|
|
||||||
|
result = outDir / name & ".pfs0"
|
||||||
|
|
||||||
|
createDir outDir & "/exefs"
|
||||||
|
copyFile nsoPath, outDir / "exefs/main"
|
||||||
|
execProc toolsPath / "build_pfs0 " & outDir / "exefs " & result
|
||||||
|
|
||||||
|
proc buildLst(buildInfo: BuildInfo): string =
|
||||||
|
let
|
||||||
|
name = buildInfo.name
|
||||||
|
outDir = buildInfo.outDir
|
||||||
|
compDir = buildInfo.compilerPath
|
||||||
|
|
||||||
|
result = outDir / name & ".lst"
|
||||||
|
var cmd = compDir / "aarch64-none-elf-gcc-nm " & buildInfo.elfLocation
|
||||||
|
cmd &= " > " & result
|
||||||
|
|
||||||
|
execProc cmd
|
||||||
|
|
||||||
|
proc buildNacp(buildInfo: BuildInfo): string =
|
||||||
|
let
|
||||||
|
name = buildInfo.name
|
||||||
|
outDir = buildInfo.outDir
|
||||||
|
toolsPath = buildInfo.toolsPath
|
||||||
|
author = buildInfo.author
|
||||||
|
version = buildInfo.version
|
||||||
|
|
||||||
|
result = outDir / name & ".nacp"
|
||||||
|
|
||||||
|
var cmd = toolsPath / "nacptool --create " & name
|
||||||
|
cmd &= " '" & author & "' '" & version & "' "
|
||||||
|
cmd &= result
|
||||||
|
|
||||||
|
execProc cmd
|
||||||
|
|
||||||
|
proc buildNro(buildInfo: BuildInfo): string =
|
||||||
|
let nacpPath = buildNacp(buildInfo)
|
||||||
|
let
|
||||||
|
name = buildInfo.name
|
||||||
|
outDir = buildInfo.outDir
|
||||||
|
toolsPath = buildInfo.toolsPath
|
||||||
|
icon = buildInfo.icon
|
||||||
|
elfLocation = buildInfo.elfLocation
|
||||||
|
|
||||||
|
result = outDir / name & ".nro"
|
||||||
|
|
||||||
|
var cmd = toolsPath / "elf2nro " & elfLocation & " " & result
|
||||||
|
cmd &= " --icon=" & icon & " --nacp=" & nacpPath
|
||||||
|
|
||||||
|
execProc cmd
|
||||||
|
|
||||||
|
proc buildAll(buildInfo: BuildInfo): seq[string] =
|
||||||
|
result = @[]
|
||||||
|
result.add buildNso(buildInfo)
|
||||||
|
result.add buildPfs0(buildInfo)
|
||||||
|
result.add buildLst(buildInfo)
|
||||||
|
result.add buildNacp(buildInfo)
|
||||||
|
result.add buildNro(buildInfo)
|
||||||
|
|
||||||
|
|
||||||
|
proc build(buildType: string, buildInfo: BuildInfo): string =
|
||||||
|
echo "Building $#..." % buildType
|
||||||
|
case buildType:
|
||||||
|
of "all":
|
||||||
|
result = buildAll(buildInfo).join("\n")
|
||||||
|
of "nro":
|
||||||
|
result = buildNro(buildInfo)
|
||||||
|
of "nso":
|
||||||
|
result = buildNso(buildInfo)
|
||||||
|
of "pfs0":
|
||||||
|
result = buildPfs0(buildInfo)
|
||||||
|
of "nacp":
|
||||||
|
result = buildNacp(buildInfo)
|
||||||
|
of "lst":
|
||||||
|
result = buildLst(buildInfo)
|
||||||
|
|
||||||
|
proc processArgs() =
|
||||||
|
|
||||||
|
let dkpEnv = "DEVKITPRO"
|
||||||
|
|
||||||
|
var buildInfo = BuildInfo(
|
||||||
|
filename: "",
|
||||||
|
name: "",
|
||||||
|
author: "",
|
||||||
|
version: "",
|
||||||
|
icon: "",
|
||||||
|
|
||||||
|
dkpPath: getEnv(dkpEnv),
|
||||||
|
|
||||||
|
compilerPath: "",
|
||||||
|
toolsPath: "",
|
||||||
|
|
||||||
|
outDir: "",
|
||||||
|
libs: "",
|
||||||
|
includes: ""
|
||||||
|
)
|
||||||
|
|
||||||
|
var buildTypes: seq[string] = @[]
|
||||||
|
|
||||||
|
|
||||||
|
for kind, key, val in getopt():
|
||||||
|
case kind
|
||||||
|
of cmdArgument:
|
||||||
|
buildInfo.filename = key
|
||||||
|
of cmdLongOption, cmdShortOption:
|
||||||
|
case key
|
||||||
|
of "devkitProPath", "d":
|
||||||
|
buildInfo.dkpPath = val
|
||||||
|
putEnv(dkpEnv, val)
|
||||||
|
of "devkitCompilerPath", "c":
|
||||||
|
buildInfo.compilerPath = val
|
||||||
|
of "output", "o":
|
||||||
|
buildInfo.outDir = val
|
||||||
|
of "tools", "t":
|
||||||
|
buildInfo.toolsPath = val
|
||||||
|
of "build", "b":
|
||||||
|
buildTypes.add(val)
|
||||||
|
of "libs", "l":
|
||||||
|
buildInfo.libs = val
|
||||||
|
of "includes", "i":
|
||||||
|
buildInfo.includes = val
|
||||||
|
of "name", "n":
|
||||||
|
buildInfo.name = val
|
||||||
|
of "icon", "p":
|
||||||
|
buildInfo.icon = val
|
||||||
|
of "version", "v":
|
||||||
|
buildInfo.version = val
|
||||||
|
of "help", "h":
|
||||||
|
writeHelp()
|
||||||
|
quit(0)
|
||||||
|
of cmdEnd: assert(false) # cannot happen
|
||||||
|
|
||||||
|
if buildInfo.filename == "":
|
||||||
|
# no filename has been given, so we show the help:
|
||||||
|
writeHelp()
|
||||||
|
quit(1)
|
||||||
|
|
||||||
|
if buildTypes.len == 0:
|
||||||
|
buildTypes.add("all")
|
||||||
|
|
||||||
|
if buildInfo.name == "":
|
||||||
|
buildInfo.name = buildInfo.filename.splitFile().name
|
||||||
|
|
||||||
|
if buildInfo.outDir == "":
|
||||||
|
buildInfo.outDir = "build"
|
||||||
|
|
||||||
|
if dirExists buildInfo.outDir:
|
||||||
|
removeDir buildInfo.outDir
|
||||||
|
|
||||||
|
createDir buildInfo.outDir
|
||||||
|
|
||||||
|
if buildInfo.dkpPath == "":
|
||||||
|
buildInfo.dkpPath = getEnv(dkpEnv, "")
|
||||||
|
if buildInfo.dkpPath == "" and not dkpEnv.existsEnv():
|
||||||
|
writeHelp()
|
||||||
|
raise newException(Exception, dkpEnv & " path must be set!")
|
||||||
|
|
||||||
|
if buildInfo.icon == "":
|
||||||
|
buildInfo.icon = buildInfo.dkpPath / "libnx/default_icon.jpg"
|
||||||
|
|
||||||
|
if buildInfo.compilerPath == "":
|
||||||
|
buildInfo.compilerPath = buildInfo.dkpPath / "devkitA64/bin"
|
||||||
|
|
||||||
|
if buildInfo.toolsPath == "":
|
||||||
|
buildInfo.toolsPath = buildInfo.dkpPath / "tools/bin"
|
||||||
|
|
||||||
|
|
||||||
|
putEnv("SWITCHLIBS", getEnv("SWITCHLIBS") & " " & buildInfo.libs)
|
||||||
|
putEnv("SWITCHINCLUDES", getEnv("SWITCHINCLUDES") & " " & buildInfo.includes)
|
||||||
|
|
||||||
|
buildInfo.elfLocation = buildElf(buildInfo)
|
||||||
|
|
||||||
|
# Build the files
|
||||||
|
for buildType in buildTypes:
|
||||||
|
let path = build(buildType, buildInfo)
|
||||||
|
echo "\nBuilt:"
|
||||||
|
echo path
|
||||||
|
|
||||||
|
|
||||||
|
proc main() =
|
||||||
|
processArgs()
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
main()
|
||||||
16
switch_build.nimble
Normal file
16
switch_build.nimble
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Package
|
||||||
|
|
||||||
|
version = "0.1.0"
|
||||||
|
author = "Joey Payne"
|
||||||
|
description = "Nintendo Switch library libnx for Nim."
|
||||||
|
license = "The Unlicense"
|
||||||
|
|
||||||
|
srcDir = "src"
|
||||||
|
|
||||||
|
bin = @["switch_build"]
|
||||||
|
|
||||||
|
# Deps
|
||||||
|
requires "nim >= 0.18.0", "libnx >= 0.1.0"
|
||||||
|
|
||||||
|
task test, "Run tests":
|
||||||
|
exec "nim c -r tests/test.nim"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue