101 lines
2.7 KiB
Markdown
101 lines
2.7 KiB
Markdown
|
---
|
||
|
title: Nim and Tup
|
||
|
date: 2015-06-10
|
||
|
---
|
||
|
|
||
|
Nim and Tup
|
||
|
===========
|
||
|
|
||
|
I have been recently playing with and using a new lanugage for
|
||
|
my personal development, [Nim](http://nim-lang.org). It looks like
|
||
|
Python, runs like C and integrates well into other things. Its
|
||
|
compiler targets C, and as a result of this binding things to C
|
||
|
libraries is a lot more trivial in Nim; even moreso than with go.
|
||
|
|
||
|
For example, here is a program that links to the posix `crypt(3)`
|
||
|
function:
|
||
|
|
||
|
```
|
||
|
# crypt.nim
|
||
|
import posix
|
||
|
|
||
|
{.passL: "-lcrypt".}
|
||
|
|
||
|
echo "What would you like to encrypt? "
|
||
|
var password: string = readLine stdin
|
||
|
echo "What is the salt? "
|
||
|
var salt: string = readLine stdin
|
||
|
|
||
|
echo "result: " & $crypt(password, salt)
|
||
|
```
|
||
|
|
||
|
And an example usage:
|
||
|
|
||
|
```
|
||
|
xena@fluttershy (linux) ~/code/nim/crypt
|
||
|
➜ ./crypt
|
||
|
What would you like to encrypt?
|
||
|
foo
|
||
|
What is the salt?
|
||
|
rs
|
||
|
result: rsHt73tkfd0Rg
|
||
|
```
|
||
|
|
||
|
And that's it. No having to worry about deferring to free the C
|
||
|
string, no extra wrappers (like with Python or Lua), you just
|
||
|
write the code and it just works.
|
||
|
|
||
|
At the idea of another coworker, I've also started to use
|
||
|
[tup](http://gittup.org/tup/) for building things. Nim didn't
|
||
|
initially work very well with tup (temporary cache needed, etc),
|
||
|
but a very simple set of tup rules were able to fix that:
|
||
|
|
||
|
```
|
||
|
NIMFLAGS += --nimcache:".nimcache"
|
||
|
NIMFLAGS += --deadcodeElim:on
|
||
|
NIMFLAGS += -d:release
|
||
|
NIMFLAGS += -d:ssl
|
||
|
NIMFLAGS += -d:threads
|
||
|
NIMFLAGS += --verbosity:0
|
||
|
|
||
|
!nim = |> nim c $(NIMFLAGS) -o:%o %f && rm -rf .nimcache |>
|
||
|
```
|
||
|
|
||
|
This creates a tup !-macro called `!nim` that will Do The Right
|
||
|
Thing implicitly. Usage of this is simple:
|
||
|
|
||
|
```
|
||
|
.gitignore
|
||
|
include_rules
|
||
|
|
||
|
: crypt.nim |> !nim |> ../bin/crypt
|
||
|
```
|
||
|
|
||
|
```
|
||
|
xena@fluttershy (linux) ~/code/nim/crypt
|
||
|
➜ tup
|
||
|
[ tup ] [0.000s] Scanning filesystem...
|
||
|
[ tup ] [0.130s] Reading in new environment variables...
|
||
|
[ tup ] [0.130s] No Tupfiles to parse.
|
||
|
[ tup ] [0.130s] No files to delete.
|
||
|
[ tup ] [0.130s] Executing Commands...
|
||
|
1) [0.581s] nim c --nimcache:".nimcache" --deadcodeElim:on --verbosity:0 crypt.nim && rm -rf .nimcache
|
||
|
[ ] 100%
|
||
|
[ tup ] [0.848s] Updated.
|
||
|
```
|
||
|
|
||
|
Not only will this build the program if needed, it will also
|
||
|
generate a gitignore for all generated files. This is an amazing
|
||
|
thing. tup has a lot more features (including lua support for
|
||
|
scripting complicated build logic), but there is one powerful
|
||
|
feature of tup that makes it very difficult for me to work into
|
||
|
my deployment pipelines.
|
||
|
|
||
|
tup requires fuse to ensure that no extra things are being
|
||
|
depended on for builds. Docker doesn't let you use fuse mounts
|
||
|
in the build process.
|
||
|
|
||
|
I have a few ideas on how to work around this, and am thinking
|
||
|
about tackling them when I get nim programs built inside Rocket
|
||
|
images.
|