Skip to content

Commit

Permalink
implements makefile generator and the --run option (#61)
Browse files Browse the repository at this point in the history
* implements makefile generator and the `--run` option

* install make for windows

* fixes syntax

* pass CC as parameters

* progress

* implements opt:speed and opt:size

* improve tests

* test cpp

* adds docs

* fixes

* improve

* cut extccomp to the bone

* remove extccomp

* simplifiy

* typo
  • Loading branch information
ringabout authored Sep 13, 2024
1 parent bc688ba commit 073191d
Show file tree
Hide file tree
Showing 11 changed files with 179 additions and 41 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ jobs:
echo '${{ github.workspace }}'"/external/mingw-${{ matrix.target.cpu }}/bin" >> $GITHUB_PATH
echo '${{ github.workspace }}'"/external/dlls-${{ matrix.target.cpu }}" >> $GITHUB_PATH
- name: Install winget
if: runner.os == 'Windows'
uses: Cyberboss/install-winget@v1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Install make dependencies (Windows)
if: runner.os == 'Windows'
run: winget install ezwinports.make --disable-interactivity --accept-source-agreements

# - name: Restore Nim from cache
# if: >
# steps.nim-compiler-cache.outputs.cache-hit != 'true' &&
Expand Down
5 changes: 1 addition & 4 deletions src/nifc/codegen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ from std / strutils import parseBiggestInt, parseBiggestUInt, parseInt
from std / os import changeFileExt, splitFile, extractFileName

import .. / lib / [bitabs, packedtrees]
import mangler, nifc_model, cprelude
import mangler, nifc_model, cprelude, noptions

type
Token = distinct uint32
Expand Down Expand Up @@ -81,9 +81,6 @@ type
generatedTypes: IntSet
requestedSyms: HashSet[string]

State* = object
selects*: seq[string]

proc initGeneratedCode*(m: sink Module): GeneratedCode =
result = GeneratedCode(m: m, code: @[], tokens: initBiTable[Token, string]())
fillTokenTable(result.tokens)
Expand Down
35 changes: 35 additions & 0 deletions src/nifc/makefile.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import std/[os, strformat]
import noptions

proc generateMakefile*(s: State, path: string; moduleNames: seq[string]; app: string; nifcache: string; compileOption: string) =
var h = open(path, fmWrite)
var makefileContent = "program:"
var programBody = ""
var objectBody = ""
let cc =
case s.config.backend
of backendC:
"$(CC)"
of backendCpp:
"$(CXX)"
else:
quit "unreachable"
let cflags =
case s.config.backend
of backendC:
"$(CFLAGS)"
of backendCpp:
"$(CXXFLAGS)"
else:
quit "unreachable"
for i in 0..<moduleNames.len:
makefileContent.add " " & moduleNames[i] & ".o"
programBody.add " " & nifcache / moduleNames[i] & ".o"
objectBody.add &"{moduleNames[i]}.o:\n {cc} {cflags} -c " &
nifcache / moduleNames[i] & ".c -o " &
nifcache / moduleNames[i] & ".o\n"

makefileContent.add &"\n {cc} -o " & app & programBody & "\n\n" & objectBody

h.write(makefileContent)
h.close()
99 changes: 90 additions & 9 deletions src/nifc/nifc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

## NIFC driver program.

import std / [parseopt, strutils, os]
import codegen
import std / [parseopt, strutils, os, osproc]
import codegen, makefile, noptions

const
Version = "0.2"
Expand All @@ -23,9 +23,12 @@ Command:
c|cpp file.nif [file2.nif] convert NIF files to C|C++
Options:
--bits:N (int M) has N bits; possible values: 64, 32, 16
--version show the version
--help show this help
-r, --run run the makefile and the compiled program
--cc:SYMBOL specify the C compiler
--opt:none|speed|size optimize not at all or for speed|size
--bits:N (int M) has N bits; possible values: 64, 32, 16
--version show the version
--help show this help
"""

proc writeHelp() = quit(Usage, QuitSuccess)
Expand All @@ -35,6 +38,14 @@ proc handleCmdLine() =
var action = ""
var args: seq[string] = @[]
var bits = sizeof(int)*8
var toRun = false


var s = State(config: ConfigRef())
when defined(macos): # TODO: switches to default config for platforms
s.config.cCompiler = ccCLang
else:
s.config.cCompiler = ccGcc
for kind, key, val in getopt():
case kind
of cmdArgument:
Expand All @@ -52,6 +63,28 @@ proc handleCmdLine() =
else: quit "invalid value for --bits"
of "help", "h": writeHelp()
of "version", "v": writeVersion()
of "run", "r": toRun = true
of "cc":
case val.normalize
of "gcc":
s.config.cCompiler = ccGcc
of "clang":
s.config.cCompiler = ccCLang
else:
quit "unknown C compiler: '$1'. Available options are: gcc, clang" % [val]
of "opt":
case val.normalize
of "speed":
incl(s.config.options, optOptimizeSpeed)
excl(s.config.options, optOptimizeSize)
of "size":
excl(s.config.options, optOptimizeSpeed)
incl(s.config.options, optOptimizeSize)
of "none":
excl(s.config.options, optOptimizeSpeed)
excl(s.config.options, optOptimizeSize)
else:
quit "'none', 'speed' or 'size' expected, but '$1' found" % val
else: writeHelp()
of cmdEnd: assert false, "cannot happen"

Expand All @@ -62,18 +95,66 @@ proc handleCmdLine() =
if args.len == 0:
quit "command takes a filename"
else:
s.config.backend = if action == "c": backendC else: backendCpp
let destExt = if action == "c": ".c" else: ".cpp"
var s = State()
createDir("nifcache")
var moduleNames = newSeq[string](args.len)
let nifcacheDir = "nifcache"
createDir(nifcacheDir)
for i in 0..<args.len:
let inp = args[i]
let outp = "nifcache" / splitFile(inp).name & destExt
moduleNames[i] = splitFile(inp).name
let outp = nifcacheDir / moduleNames[i] & destExt
generateCode s, inp, outp, bits
if s.selects.len > 0:
var h = open("nifcache/select_any.h", fmWrite)
var h = open(nifcacheDir / "select_any.h", fmWrite)
for x in s.selects:
write h, "#include \"" & extractFileName(x) & "\"\n"
h.close()
let appName = moduleNames[^1]
let makefilePath = nifcacheDir / "Makefile." & appName
generateMakefile(s, makefilePath, moduleNames, appName, nifcacheDir, action)
if toRun:
var cflags = ""
if optOptimizeSpeed in s.config.options:
cflags.add "-O3"
elif optOptimizeSize in s.config.options:
cflags.add "-Os"

let cCompiler: string =
case s.config.cCompiler
of ccGcc:
"gcc"
of ccCLang:
"clang"
else:
quit "unreachable"

let cppCompiler =
case s.config.cCompiler
of ccGcc:
"g++"
of ccCLang:
"clang++"
else:
quit "unreachable"

let makeCmd = case s.config.backend
of backendC:
"make " & "CC=" & cCompiler &
" " & "CFLAGS=" & "\"" & cflags & "\"" &
" -f " & makefilePath
of backendCpp:
"make " & "CXX=" & cppCompiler &
" " & "CXXFLAGS=" & "\"" & cflags & "\"" &
" -f " & makefilePath
else:
quit "unreachable"

let (output, exitCode) = execCmdEx(makeCmd)
if exitCode != 0:
quit "execution of an external program failed: " & output
if execCmd("./" & appName) != 0:
quit "execution of an external program failed: " & appName
else:
quit "Invalid action: " & action

Expand Down
20 changes: 20 additions & 0 deletions src/nifc/noptions.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
type
Backend* = enum
backendInvalid = "" # for parseEnum
backendC = "c"
backendCpp = "cpp"

Option* = enum
optOptimizeSpeed, optOptimizeSize

SystemCC* = enum
ccNone, ccGcc, ccCLang

ConfigRef* {.acyclic.} = ref object ## every global configuration
cCompiler*: SystemCC
backend*: Backend
options*: set[Option]

State* = object
selects*: seq[string] # names of modules with functions with selectany pragmas
config*: ConfigRef
6 changes: 3 additions & 3 deletions tests/nifc/hello.expected.idx.nif
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
(kv a3 +31)
(kv a4 +25)
(kv foo.c +36)
(kv foo2.c +85)
(kv foo2.c +88)
(kv x.c +32)
(kv MyObject.ptr.flexarray +105)
(kv MyObject.ptr.flexarray +111)
(kv a1 +47)
(kv a2 +27)
(kv a3 +31)
Expand Down Expand Up @@ -61,5 +61,5 @@
(kv cap +49)
(kv data +28)
(kv main.c +47)
(kv x.c +42))
(kv x.c +43))
)
14 changes: 7 additions & 7 deletions tests/nifc/hello.nif
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@
)

(proc :foo.c . (void) . (stmts
(call printf.c "foo %s" "abc")
(call printf.c "foo %s\0A" "abc")
))

(nodecl (proc :foo2.c . (void) . (stmts
(var :x.c . (i +32 .) +12)
(call printf.c "foo %s" "abc")
(call printf.c "foo %d" x.c)
(call printf.c "foo %s\0A" "abc")
(call printf.c "foo %d\0A" x.c)
)))

(type :MyObject.ptr.flexarray .
Expand Down Expand Up @@ -101,11 +101,11 @@
(fld :data . (flexarray (i +64 .)))
))

(proc :main.c . (i -1 atomic) . (stmts
(proc :main.c . (i +32 atomic) . (stmts
(var :x.c . (i +32 .) +12)
(call printf.c "hello %s" "abc")
(call printf.c "hello %d" (suf +12 "i64"))
(call printf.c "hello %d" x.c)
(call printf.c "hello %s\0A" "abc")
(call printf.c "hello %d\0A" (suf +12 "i64"))
(call printf.c "hello %d\0A" x.c)
(call foo.c)
(ret +0)
))
Expand Down
7 changes: 1 addition & 6 deletions tests/nifc/selectany/t1.nif
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,9 @@
)

(proc :genericProc2.c . (void) (pragmas (selectany)) (stmts
(call printf.c "hello %s" "file t1")
(call printf.c "hello %s\0A" "file t1")
)
)

(proc :main.c . (i -1 +90) . (stmts
(call printf.c "hello %s" "abc")
(call printf.c "hello %d" (suf +12 "i64"))
(ret +0)
))

)
7 changes: 1 addition & 6 deletions tests/nifc/selectany/t2.nif
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,9 @@
(stmts
(incl "<stdio.h>")
(proc :genericProc.c . (void) (pragmas (selectany)) (stmts
(call printf.c "hello %s" "file t2")
(call printf.c "hello %s\0A" "file t2")
)
)

(proc :main.c . (i -1 +90) . (stmts
(call printf.c "hello %s" "abc")
(call printf.c "hello %d" (suf +12 "i64"))
(ret +0)
))

)
8 changes: 4 additions & 4 deletions tests/nifc/selectany/t3.nif
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
(stmts
(incl "<stdio.h>")
(proc :genericProc.c . (void) (pragmas (selectany)) (stmts
(call printf.c "hello %s" "file t3")
(call printf.c "hello %s\0A" "file t3")
)
)

(proc :genericProc2.c . (void) (pragmas (selectany)) (stmts
(call printf.c "hello %s" "file t3")
(call printf.c "hello %s\0A" "file t3")
)
)

(proc :main.c . (i -1 +90) . (stmts
(call printf.c "hello %s" "abc")
(call printf.c "hello %d" (suf +12 "i64"))
(call printf.c "hello %s\0A" "abc")
(call printf.c "hello %d\0A" (suf +12 "i64"))
(ret +0)
))
)
9 changes: 7 additions & 2 deletions tests/tester.nim
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,13 @@ proc testNifc(overwrite: bool) =
let t1 = "tests/nifc/selectany/t1.nif"
let t2 = "tests/nifc/selectany/t2.nif"
let t3 = "tests/nifc/selectany/t3.nif"
exec ("src" / "nifc" / "nifc").addFileExt(ExeExt) & " c " & t1 & " " & t2 & " " & t3
exec ("src" / "nifc" / "nifc").addFileExt(ExeExt) & " c -r " & t1 & " " & t2 & " " & t3
let hello = "tests/nifc/hello.nif"
exec ("src" / "nifc" / "nifc").addFileExt(ExeExt) & " c " & hello
exec ("src" / "nifc" / "nifc").addFileExt(ExeExt) & " c -r " & hello
exec ("src" / "nifc" / "nifc").addFileExt(ExeExt) & " c -r --opt:speed " & hello
exec ("src" / "nifc" / "nifc").addFileExt(ExeExt) & " c -r --opt:size " & hello
# TEST CPP
exec ("src" / "nifc" / "nifc").addFileExt(ExeExt) & " cpp -r " & hello
exec ("src" / "nifc" / "nifc").addFileExt(ExeExt) & " cpp -r --opt:speed " & hello

testNifc(overwrite)

0 comments on commit 073191d

Please sign in to comment.