Add env var support for defines

This commit is contained in:
Ganesh Viswanathan 2019-09-25 21:15:14 -05:00
commit fad9fd78f3
6 changed files with 99 additions and 20 deletions

View file

@ -12,12 +12,14 @@ language: c
env:
- BRANCH=0.19.6
- BRANCH=0.20.2
- BRANCH=1.0.0
- BRANCH=devel
cache:
directories:
- "$HOME/.choosenim/toolchains/nim-0.19.6"
- "$HOME/.choosenim/toolchains/nim-0.20.2"
- "$HOME/.choosenim/toolchains/nim-1.0.0"
install:
- export CHOOSENIM_CHOOSE_VERSION=$BRANCH

View file

@ -11,6 +11,7 @@ environment:
matrix:
- NIM_VERSION: 0.19.6
- NIM_VERSION: 0.20.2
- NIM_VERSION: 1.0.0
for:
-

View file

@ -1,4 +1,4 @@
import macros, osproc, regex, strformat, strutils
import macros, osproc, regex, strformat, strutils, tables
import os except findExe
@ -650,6 +650,48 @@ proc getDynlibExt(): string =
elif defined(macosx):
result = ".dylib[0-9.]*"
var
gDefines {.compileTime.} = initTable[string, string]()
macro setDefines*(defs: static openArray[string]): untyped =
## Specify `-d:xxx` values in code instead of having to rely on the command
## line or `cfg` or `nims` files.
##
## At this time, Nim does not allow creation of `-d:xxx` defines in code. In
## addition, Nim only loads config files for the module being compiled but not
## for imported packages. This becomes a challenge when wanting to ship a wrapper
## library that wants to control `getHeader()` for an underlying package.
##
## E.g. nimarchive wanting to set `-d:lzmaStatic`
##
## The consumer of nimarchive would need to set such defines as part of their
## project, making it inconvenient.
##
## By calling this proc with the defines preferred before importing such a module,
## the caller can set the behavior in code instead.
##
## .. code-block:: nim
##
## setDefines(@["lzmaStatic", "lzmaDL", "lzmaSetVer=5.2.4"])
##
## import lzma
for def in defs:
let
nv = def.strip().split("=", maxsplit = 1)
if nv.len != 0:
let
n = nv[0]
v =
if nv.len == 2:
nv[1]
else:
""
gDefines[n] = v
macro clearDefines*(): untyped =
## Clear all defines set using `setDefines()`.
gDefines.clear()
macro getHeader*(header: static[string], giturl: static[string] = "", dlurl: static[string] = "", outdir: static[string] = "",
conFlags: static[string] = "", cmakeFlags: static[string] = "", makeFlags: static[string] = "",
altNames: static[string] = ""): untyped =
@ -670,6 +712,8 @@ macro getHeader*(header: static[string], giturl: static[string] = "", dlurl: sta
## `-d:xxxSetVer=x.y.z` can be used to specify which version to use. It is used as a tag
## name for Git whereas for DL, it replaces `$1` in the URL defined.
##
## All defines can also be set in code using `setDefines()`.
##
## The library is then configured (with `cmake` or `autotools` if possible) and built
## using `make`, unless using `-d:xxxStd` which presumes that the system package
## manager was used to install prebuilt headers and binaries.
@ -700,20 +744,37 @@ macro getHeader*(header: static[string], giturl: static[string] = "", dlurl: sta
var
name = header.extractFilename().split(".")[0]
nameStd = newIdentNode(name & "Std")
nameGit = newIdentNode(name & "Git")
nameDL = newIdentNode(name & "DL")
stdStr = name & "Std"
gitStr = name & "Git"
dlStr = name & "DL"
nameStatic = newIdentNode(name & "Static")
staticStr = name & "Static"
verStr = name & "SetVer"
nameStd = newIdentNode(stdStr)
nameGit = newIdentNode(gitStr)
nameDL = newIdentNode(dlStr)
nameStatic = newIdentNode(staticStr)
path = newIdentNode(name & "Path")
lpath = newIdentNode(name & "LPath")
version = newIdentNode(name & "SetVer")
version = newIdentNode(verStr)
lname = newIdentNode(name & "LName")
preBuild = newIdentNode(name & "PreBuild")
lre = "(lib)?$1[_]?(static)?[0-9.\\-]*\\"
stdVal = gDefines.hasKey(stdStr)
gitVal = gDefines.hasKey(gitStr)
dlVal = gDefines.hasKey(dlStr)
staticVal = gDefines.hasKey(staticStr)
verVal =
if gDefines.hasKey(verStr):
gDefines[verStr]
else:
""
if altNames.len != 0:
let
names = "(" & name & "|" & altNames.replace(",", "|") & ")"
@ -724,23 +785,28 @@ macro getHeader*(header: static[string], giturl: static[string] = "", dlurl: sta
result = newNimNode(nnkStmtList)
result.add(quote do:
const
`version`* {.strdefine.} = ""
`nameStd`* = when defined(`nameStd`): true else: `stdVal` == 1
`nameGit`* = when defined(`nameGit`): true else: `gitVal` == 1
`nameDL`* = when defined(`nameDL`): true else: `dlVal` == 1
`nameStatic`* = when defined(`nameStatic`): true else: `staticVal` == 1
`version`* {.strdefine.} = `verVal`
`lname` =
when defined(`nameStatic`):
when `nameStatic`:
`lre` & ".a"
else:
`lre` & getDynlibExt()
when defined(`nameStd`):
when `nameStd`:
const
`path`* = getStdPath(`header`)
`lpath`* = getStdLibPath(`lname`)
else:
const
`path`* =
when defined(`nameGit`):
when `nameGit`:
getGitPath(`header`, `giturl`, `outdir`, `version`)
elif defined(`nameDL`):
elif `nameDL`:
getDlPath(`header`, `dlurl`, `outdir`, `version`)
else:
getLocalPath(`header`, `outdir`)
@ -757,6 +823,6 @@ macro getHeader*(header: static[string], giturl: static[string] = "", dlurl: sta
doAssert `lpath`.len != 0, "\nLibrary " & `lname` & " not found"
echo "# Including library " & `lpath`
when defined(`nameStatic`):
when `nameStatic`:
{.passL: `lpath`.}
)

View file

@ -27,8 +27,8 @@ testCall(cmd & lrcmd, "No build files found", 1)
when defined(posix):
# stdlib
testCall(cmd & " -d:lzmaStd" & lrcmd, lexp, 0)
testCall(cmd & " -d:lzmaStd -d:lzmaStatic" & lrcmd, lexp, 0)
testCall(cmd & " -d:envTest" & lrcmd, lexp, 0)
testCall(cmd & " -d:envTestStatic" & lrcmd, lexp, 0)
when not defined(osx):
testCall(cmd & " -d:zlibStd" & zrcmd, zexp, 0)
@ -44,8 +44,8 @@ when defined(posix):
testCall("cd build/liblzma && git branch", "v5.2.0", 0, delete = false)
# git
testCall(cmd & " -d:zlibGit" & zrcmd, zexp, 0)
testCall(cmd & " -d:zlibGit -d:zlibStatic" & zrcmd, zexp, 0, delete = false)
testCall(cmd & " -d:envTest" & zrcmd, zexp, 0)
testCall(cmd & " -d:envTestStatic" & zrcmd, zexp, 0, delete = false)
# git tag
testCall(cmd & " -d:zlibGit -d:zlibSetVer=v1.2.10" & zrcmd, zexp & "1.2.10", 0)

View file

@ -8,6 +8,11 @@ const
static:
cDebug()
when defined(envTest):
setDefines(@["lzmaStd"])
elif defined(envTestStatic):
setDefines(@["lzmaStd", "lzmaStatic"])
getHeader(
"lzma.h",
giturl = "https://github.com/xz-mirror/xz",
@ -33,9 +38,9 @@ cOverride:
lzma_block = object
lzma_index_iter = object
when not defined(lzmaStatic):
when not lzmaStatic:
cImport(lzmaPath, recurse = true, dynlib = "lzmaLPath")
else:
cImport(lzmaPath, recurse = true)
echo "liblzma version = " & $lzma_version_string()
echo "liblzma version = " & $lzma_version_string()

View file

@ -19,6 +19,11 @@ proc zlibPreBuild(outdir, path: string) =
# Fix static lib name on Windows
setCmakeLibName(outdir, "zlibstatic", prefix = "lib", oname = "zlib", suffix = ".a")
when defined(envTest):
setDefines(@["zlibGit"])
elif defined(envTestStatic):
setDefines(@["zlibGit", "zlibStatic"])
getHeader(
"zlib.h",
giturl = "https://github.com/madler/zlib",
@ -56,11 +61,11 @@ when defined(posix):
static:
cSkipSymbol(@["u_int8_t", "u_int16_t", "u_int32_t", "u_int64_t"])
when defined(zlibGit) or defined(zlibDL):
when zlibGit or zlibDL:
when dirExists(baseDir / "buildcache"):
cIncludeDir(baseDir / "buildcache")
when not defined(zlibStatic):
when not zlibStatic:
cImport(zlibPath, recurse = true, dynlib = "zlibLPath")
else:
cImport(zlibPath, recurse = true)