diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..1ed925a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,27 @@ +os: + - linux + - osx + +language: c + +env: + - BRANCH=devel + +addons: + apt: + packages: + - libssh2-1-dev + +before_install: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then HOMEBREW_NO_AUTO_UPDATE=1 brew install libssh2; fi + +install: + - export CHOOSENIM_CHOOSE_VERSION=$BRANCH + - | + curl https://nim-lang.org/choosenim/init.sh -sSf > init.sh + sh init.sh -y + - export PATH=$HOME/.nimble/bin:$PATH + +script: + - nimble install -y + - nimble test diff --git a/README.md b/README.md index 5a1945d..818b8cd 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +[![Chat on Gitter](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/nimgen/Lobby) +[![Build status](https://ci.appveyor.com/api/projects/status/05t5ja88lmv1rt3r/branch/master?svg=true)](https://ci.appveyor.com/project/genotrance/nimgen/branch/master) +[![Build Status](https://travis-ci.org/genotrance/nimgen.svg?branch=master)](https://travis-ci.org/genotrance/nimgen) + Nimgen is a helper for [c2nim](https://github.com/nim-lang/c2nim/) to simplify and automate the wrapping of C libraries. Nimgen can be used to automate the process of manipulating C files so that c2nim can be run on them without issues. This includes adding/removing code snippets, removal of complex preprocessor definitions that c2nim doesn't yet comprehend and recursively running on #include files. @@ -39,7 +43,7 @@ To see examples of nimgen in action check out the following wrappers:- * [nim-clblast](https://github.com/numforge/nim-clblast) - OpenCL BLAS wrapper * static -* Compile C code into binary +* Compile C/C++ code into binary * [nim7z](https://github.com/genotrance/nim7z) - 7z decoder wrapper: [docs](http://nimgen.genotrance.com/nim7z) * git sparse checkout * [nimarchive](https://github.com/genotrance/nimarchive) - libarchive wrapper: [docs](http://nimgen.genotrance.com/nimarchive) @@ -48,18 +52,26 @@ To see examples of nimgen in action check out the following wrappers:- * git checkout * [nimclipboard](https://github.com/genotrance/nimclipboard) - libclipboard wrapper: [docs](http://nimgen.genotrance.com/nimclipboard) * git checkout - * [nimfuzz](https://github.com/genotrance/nimfuzz) - fts_fuzzy_match wrapper: [docs](http://nimgen.genotrance.com/nimfuzz) + * [nimfastText](https://github.com/genotrance/nimfastText) - fastText wrapper: [docs](http://nimgen.genotrance.com/nimfastText) + * git sparse checkout + * [nimfuzzy](https://github.com/genotrance/nimfuzzy) - fts_fuzzy_match wrapper: [docs](http://nimgen.genotrance.com/nimfuzzy) * download header file * [nimkerberos](https://github.com/genotrance/nimkerberos) - WinKerberos wrapper: [docs](http://nimgen.genotrance.com/nimkerberos) * git sparse checkout + * [nimmonocypher](https://github.com/genotrance/nimmonocypher) - monocypher wrapper: [docs](http://nimgen.genotrance.com/nimmonocypher) + * git sparse checkout + * [nimnuklear](https://github.com/genotrance/nimnuklear) - nuklear wrapper: [docs](https://nimgen.genotrance.com/nimnuklear) + * git sparse checkout * [nimpcre](https://github.com/genotrance/nimpcre) - PCRE wrapper: [docs](http://nimgen.genotrance.com/nimpcre) * git checkout * [nimrax](https://github.com/genotrance/nimrax) - Radix tree wrapper: [docs](http://nimgen.genotrance.com/nimrax) * git checkout * [nimssl](https://github.com/genotrance/nimssl) - OpenSSL wrapper: [docs](http://nimgen.genotrance.com/nimssl) * git sparse checkout - * [libsvm](https://github.com/genotrance/libsvm) - libsvm wrapper: [docs](http://nimgen.genotrance.com/libsvm) - * git sparse checkout + * [nimtess2](https://github.com/genotrance/nimtess2) - libtess2 wrapper: [docs](http://nimgen.genotrance.com/nimtess2) + * git checkout + * [duktape-nim](https://github.com/manguluka/duktape-nim) - Duktape wrapper + * static * Compile in as static binary * [nimssh2](https://github.com/genotrance/nimssh2) - libssh2 wrapper: [docs](http://nimgen.genotrance.com/nimssh2) @@ -80,6 +92,8 @@ In all sections below, environment variables are supported via Nim's string inte "${output}/library/include" "${MY_INCLUDE_PATH}/include" +Append -win, -lin and -mac/osx for OS specific sections and tasks. E.g. n.global-win, n.post-lin, download-win, execute-lin-mac.unique1. -unix can be used as a shortcut for -lin-mac. + _[n.global]_ ```output``` = name of the Nimble project once installed, also location to place generated .nim files @@ -106,17 +120,21 @@ List of all directories or files to exclude from all parsing. If an entry here m _[n.prepare]_ -The following keys can be used to prepare dependencies such as downloading ZIP files, cloning Git repositories, etc. Multiple entries are possible by appending any .string to the key. E.g. download.file1. -win, -lin and -mac/osx can be used for OS specific tasks. E.g. download-win, execute-lin,mac.unique1 +The following keys can be used to prepare dependencies such as downloading ZIP files, cloning Git repositories, etc. Multiple entries are possible by appending any .string to the key. E.g. download.file1. ```download``` = url to download to the output directory. ZIP files are automatically extracted. Files are not redownloaded if already present but re-extracted ```extract``` = ZIP file to extract in case they are local and don't need to be downloaded. Path is relative to output directory. -```git``` = url of Git repository to clone. Full repo is pulled so gitremote + gitsparse is preferable. Resets to HEAD if already present +```gitcheckout``` = branch, commit or tag of repository to checkout in following Git command, resets after each use. Use "-b name" for branches + +```gitoutput``` = directory for all following Git commands relative to `n.global:output` [default: `n.global:output` directory] + +```git``` = url of Git repository to clone. Full repo is pulled so gitremote + gitsparse is preferable. Resets if already present ```gitremote``` = url of Git repository to partially checkout. Use with gitsparse to pull only files and dirs of interest -```gitsparse``` = list of files and/or dirs to include in partial checkout, one per line. Resets to HEAD if already present +```gitsparse``` = list of files and/or dirs to include in partial checkout, one per line. Resets if already present ```execute``` = command to run during preparation @@ -126,7 +144,9 @@ _[n.post]_ This section is the same as the prepare section, but for performing actions after the project has been processed. -```reset``` = whether or not to perform a git reset on all files after processing [default: false] +```gitoutput``` = output directory for Git reset [default: `n.global:output` directory] + +```reset``` = perform a Git reset on all files after processing [default: false] ```execute``` = command to run after processing @@ -142,7 +162,7 @@ This section allows selection of multiple sourcefiles without requiring a detail _[sourcefile]_ -The following keys apply to library source code and help with generating the .nim files. -win, -lin and -osx can be used for OS specific tasks. E.g. dynlib-win, pragma-win +The following keys apply to library source code and help with generating the .nim files. -win, -lin and -osx can be used for OS specific tasks. E.g. dynlib-win, pragma-win. ```recurse``` = find #include files and process them [default: false] @@ -160,11 +180,13 @@ The following keys apply to library source code and help with generating the .ni ```noprocess``` = do not process this source file with c2nim [default: false] - this is useful if a file only needs to be manipulated +```nowildcard``` = ignore any wildcard definitions for this sourcefile + ```reset``` = reset the file back to original state after all processing [default: false] Multiple entries for the all following keys are possible by appending any .string to the key. E.g. dynlib.win, compile.dir -```compile``` = file or dir of files of source code to {.compile.} into generated .nim +```compile``` = file or dir of files of source code to {.compile.} into generated .nim. If directory, picks *.c if C mode and *.cxx, *.cpp, *.cc, *.c++ and *.C for cpp mode. Dir can also include wildcards. e.g. compile = """dir/A*.cxx""" ```pragma``` = pragmas to define in generated .nim file. E.g. pragma = "passL: \"-lssl\"" => {.passL: "-lssl".} @@ -174,15 +196,19 @@ The following keys apply to library source code (before processing) and generate ```create``` = create a file at exact location with contents specified. File needs to be in the _[n.exclude]_ list in order to be created. +```pipe``` = execute a command on a file and store the output of the command as the new file contents. E.g. pipe = "cat $file | grep 'static inline'" + ```search``` = search string providing context for following prepend/append/replace directives -```pipe``` = execute a command on a file and store the output of the command as the new file contents. Ex: pipe = "cat $file | grep 'static inline'" +```regex``` = regex search string providing context for the following replace directive. Specify using """ to avoid regex parsing issues ```prepend``` = string value to prepend into file at beginning or before search ```append``` = string value to append into file at the end or after search -```replace``` = string value to replace search string in file +```replace``` = string value to replace search string in file. Regex captures can be referred to using $1, $2, etc. + +```move``` = search string providing context for location to move the results of a preceding search or regex match ```comment``` = number of lines to comment from search location @@ -196,6 +222,41 @@ The following key only applies before processing and allows renaming the generat `$replace(srch1=repl1, srch2=reply2)` = rename specific portions in `$nimout` +__Command Line__ + +A subset of capabilities are available through the command line to enable quick tests using nimgen. Command line flags only apply to source files specified on the command line and do not influence any ```cfg``` files which are expected to be self-sufficient. + +``` +Usage: + nimgen [options] file.cfg|file.h ... + +Params: + -C add compile entry * + -E add n.exclude entry * + -F set c2nim flags * + -I add n.include dir * + -O set output directory + -P set preprocessor flags * + +Options: + -c set ctags = true + -d set defines = true + -i set inline = true + -n set noprocess = true + -p set preprocess = true + -r set recurse = true + +Editing: + -a append string * + -e prepend string * + -l replace string * + -o#lines comment X lines * + -s search string * + -x regex search string * + +* supports multiple instances +``` + __Feedback__ Nimgen is a work in progress and any feedback or suggestions are welcome. It is hosted on [GitHub](https://github.com/genotrance/nimgen) with an MIT license so issues, forks and PRs are most appreciated. Also join us at https://gitter.im/nimgen/Lobby to chat about nimgen and the future of Nim wrappers. diff --git a/appveyor.yml b/appveyor.yml index 6b5f682..7d8dabf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,6 +7,11 @@ image: matrix: fast_finish: true +environment: + matrix: + - NIM_VERSION: 0.20.0 + - NIM_VERSION: 0.19.6 + for: - matrix: @@ -14,93 +19,80 @@ for: - image: Visual Studio 2017 environment: - MINGW_DIR: mingw32 - MINGW_URL: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/8.1.0/threads-posix/dwarf/i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z/download + ARCH: 32 + MINGW_URL: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/8.1.0/threads-posix/dwarf MINGW_ARCHIVE: i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z - NIM_URL: https://nim-lang.org/download/nim-0.18.0_x32.zip - NIM_ARCHIVE: nim-0.18.0_x32.zip - NIM_VERSION: nim-0.18.0 - LIBSSH2_ARCHIVE: mingw-w64-i686-libssh2-1.8.0-1-any.pkg.tar.xz - LIBSSH2_ARCHIVE2: mingw-w64-i686-libssh2-1.8.0-1-any.pkg.tar - LIBSSH2_URL: https://sourceforge.net/projects/msys2/files/REPOS/MINGW/i686/mingw-w64-i686-libssh2-1.8.0-1-any.pkg.tar.xz/download - LIBCRYPTO_ARCHIVE: mingw-w64-i686-openssl-1.0.2.o-1-any.pkg.tar.xz - LIBCRYPTO_ARCHIVE2: mingw-w64-i686-openssl-1.0.2.o-1-any.pkg.tar - LIBCRYPTO_URL: https://sourceforge.net/projects/msys2/files/REPOS/MINGW/i686/mingw-w64-i686-openssl-1.0.2.o-1-any.pkg.tar.xz/download - DLLS_URL: http://nim-lang.org/download/dlls.zip - DLLS_ARCHIVE: dlls.zip - BASE_DIR: c:\projects + SFNET_URL: https://sourceforge.net/projects/msys2/files/REPOS/MINGW/i686 + LIBSSH2_ARCHIVE: mingw-w64-i686-libssh2-1.8.0-1-any.pkg + LIBCRYPTO_ARCHIVE: mingw-w64-i686-openssl-1.0.2.o-1-any.pkg install: - - CD %BASE_DIR% - - IF not exist "%MINGW_ARCHIVE%" appveyor DownloadFile "%MINGW_URL%" -FileName "%MINGW_ARCHIVE%" - - 7z x -y "%MINGW_ARCHIVE%"> nul - - IF not exist "%LIBSSH2_ARCHIVE%" appveyor DownloadFile "%LIBSSH2_URL%" -FileName "%LIBSSH2_ARCHIVE%" - - 7z x -y "%LIBSSH2_ARCHIVE%"> nul - - 7z x -y "%LIBSSH2_ARCHIVE2%"> nul - - IF not exist "%LIBCRYPTO_ARCHIVE%" appveyor DownloadFile "%LIBCRYPTO_URL%" -FileName "%LIBCRYPTO_ARCHIVE%" - - 7z x -y "%LIBCRYPTO_ARCHIVE%"> nul - - 7z x -y "%LIBCRYPTO_ARCHIVE2%"> nul - - IF not exist "%NIM_ARCHIVE%" appveyor DownloadFile "%NIM_URL%" -FileName "%NIM_ARCHIVE%" - - 7z x -y "%NIM_ARCHIVE%"> nul - - SET PATH=%BASE_DIR%\%MINGW_DIR%\bin;%BASE_DIR%\%NIM_VERSION%\bin;%USERPROFILE%\.nimble\bin;%PATH% - - CD %BASE_DIR%\nimgen - # - git clone --depth 1 https://github.com/nim-lang/nim - # - cd nim - # - git clone --depth 1 https://github.com/nim-lang/csources - # - cd csources - # - IF "%PLATFORM%" == "x64" ( build64.bat ) else ( build.bat ) - # - cd .. - # - IF not exist "%DLLS_ARCHIVE%" appveyor DownloadFile "%DLLS_URL%" -FileName "%DLLS_ARCHIVE%" - # - 7z x -y "%DLLS_ARCHIVE%" -o"%CD%\bin"> nul - # - bin\nim c -d:release koch - # - koch boot -d:release - # - koch nimble -d:release - # - SET PATH=%CD%\bin;%PATH% - # - cd .. + - CD c:\ + - IF not exist "binaries" ( + echo %NIM_VERSION% && + MKDIR binaries && + CD binaries && + appveyor DownloadFile "%MINGW_URL%/%MINGW_ARCHIVE%/download" -FileName "%MINGW_ARCHIVE%" && + 7z x -y "%MINGW_ARCHIVE%"> nul && + del "%MINGW_ARCHIVE%" && + appveyor DownloadFile "%SFNET_URL%/%LIBSSH2_ARCHIVE%.tar.xz/download" -FileName "%LIBSSH2_ARCHIVE%.tar.xz" && + 7z x -y "%LIBSSH2_ARCHIVE%.tar.xz"> nul && + del "%LIBSSH2_ARCHIVE%.tar.xz" && + 7z x -y "%LIBSSH2_ARCHIVE%.tar"> nul && + del "%LIBSSH2_ARCHIVE%.tar" && + appveyor DownloadFile "%SFNET_URL%/%LIBCRYPTO_ARCHIVE%.tar.xz/download" -FileName "%LIBCRYPTO_ARCHIVE%.tar.xz" && + 7z x -y "%LIBCRYPTO_ARCHIVE%.tar.xz"> nul && + del "%LIBCRYPTO_ARCHIVE%.tar.xz" && + 7z x -y "%LIBCRYPTO_ARCHIVE%.tar"> nul && + del "%LIBCRYPTO_ARCHIVE%.tar" && + appveyor DownloadFile "https://nim-lang.org/download/nim-%NIM_VERSION%_x%ARCH%.zip" -FileName "nim-%NIM_VERSION%_x%ARCH%.zip" && + 7z x -y "nim-%NIM_VERSION%_x%ARCH%.zip"> nul && + del "nim-%NIM_VERSION%_x%ARCH%.zip") + - SET PATH=c:\binaries\mingw%ARCH%\bin;c:\binaries\nim-%NIM_VERSION%\bin;%USERPROFILE%\.nimble\bin;%PATH% + - CD c:\projects\nimgen on_finish: - - 7z a -r buildlogs-win.zip %USERPROFILE%\.nimble\pkgs - - appveyor PushArtifact buildlogs-win.zip - - 7z a -r nimgen-docs.zip %BASE_DIR%\nimgen\web + - 7z a -r buildlogs-win-pkgs.zip %USERPROFILE%\.nimble\pkgs + - appveyor PushArtifact buildlogs-win-pkgs.zip + - 7z a -r buildlogs-win-projects.zip c:\projects\* + - appveyor PushArtifact buildlogs-win-projects.zip + - 7z a -r nimgen-docs.zip c:\projects\nimgen\web - appveyor PushArtifact nimgen-docs.zip cache: - - c:\projects\i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z - - c:\projects\mingw-w64-i686-libssh2-1.8.0-1-any.pkg.tar.xz - - c:\projects\mingw-w64-i686-openssl-1.0.2.o-1-any.pkg.tar.xz - - c:\projects\nim-0.18.0_x32.zip + - c:\binaries - matrix: only: - image: Ubuntu - environment: - NIM_URL: https://nim-lang.org/download/nim-0.18.0.tar.xz - NIM_ARCHIVE: nim-0.18.0.tar.xz - NIM_VERSION: nim-0.18.0 - BASE_DIR: /home/appveyor/projects - install: - sudo apt -qq update - - sudo apt -qq install --yes python-pygments libssh2-1-dev libgcrypt20-dev libgpg-error-dev - - cd $BASE_DIR - - if [ ! -e $NIM_ARCHIVE ]; then curl -s -o $NIM_ARCHIVE $NIM_URL; fi - - tar xJf $NIM_ARCHIVE - - cd $NIM_VERSION - - sh build.sh - - bin/nim c -d:release koch - - ./koch boot -d:release - - ./koch nimble -d:release - - export PATH=$BASE_DIR/$NIM_VERSION/bin:~/.nimble/bin:$PATH - - cd $BASE_DIR/nimgen + - sudo apt -qq install --yes libssh2-1-dev libgcrypt20-dev libgpg-error-dev + - if [ ! -e /home/appveyor/binaries ]; then + echo $NIM_VERSION && + mkdir /home/appveyor/binaries && + cd /home/appveyor/binaries && + curl -s -o nim-$NIM_VERSION.tar.xz https://nim-lang.org/download/nim-$NIM_VERSION.tar.xz && + tar xJf nim-$NIM_VERSION.tar.xz && + cd nim-$NIM_VERSION && + sh build.sh && + bin/nim c -d:release koch && + ./koch boot -d:release && + ./koch nimble -d:release; + fi + - export PATH=/home/appveyor/binaries/nim-$NIM_VERSION/bin:~/.nimble/bin:$PATH + - cd /home/appveyor/projects/nimgen on_finish: - - zip -r -q buildlogs-lin.zip ~/.nimble/pkgs - - appveyor PushArtifact buildlogs-lin.zip + - zip -r -q buildlogs-lin-pkgs.zip ~/.nimble/pkgs + - appveyor PushArtifact buildlogs-lin-pkgs.zip + - zip -r -q buildlogs-lin-projects.zip /home/appveyor/projects + - appveyor PushArtifact buildlogs-lin-projects.zip cache: - - /home/appveyor/projects/nim-0.18.0.tar.xz + - /home/appveyor/binaries build_script: - nimble install -y diff --git a/nimgen.nimble b/nimgen.nimble index 3e65545..fc7409e 100644 --- a/nimgen.nimble +++ b/nimgen.nimble @@ -1,17 +1,17 @@ # Package -version = "0.3.0" +version = "0.5.1" author = "genotrance" description = "c2nim helper to simplify and automate the wrapping of C libraries" license = "MIT" bin = @["nimgen"] srcDir = "src" -skipDirs = @["nimgen", "tests"] +skipDirs = @["nimgen", "tests", "web"] # Dependencies -requires "nim >= 0.17.0", "c2nim >= 0.9.13", "regex >= 0.7.1" +requires "nim >= 0.19.0", "c2nim >= 0.9.14", "regex >= 0.10.0" task test, "Test nimgen": exec "nim c -r tests/rununittests.nim" diff --git a/src/nimgen.nim b/src/nimgen.nim index 5777398..dc98ae4 100644 --- a/src/nimgen.nim +++ b/src/nimgen.nim @@ -2,6 +2,4 @@ import os import nimgen/runcfg -for i in commandLineParams(): - if i != "-f": - runCfg(i) +runCli() diff --git a/src/nimgen/c2nim.nim b/src/nimgen/c2nim.nim index f171e8d..c9ccff7 100644 --- a/src/nimgen/c2nim.nim +++ b/src/nimgen/c2nim.nim @@ -1,40 +1,47 @@ -import os, ospaths, regex, strutils +import os, regex, strutils + +when (NimMajor, NimMinor, NimPatch) < (0, 19, 9): + import ospaths import external, file, fileops, gencore, globals -template relativePath(path: untyped): untyped = - path.multiReplace([(gOutput, ""), ("\\", "/"), ("//", "/")]) +proc relativePath(path: string): string = + if gOutput.len() == 0: + result = path + else: + # multiReplace() bug - #9557 + result = path.replace(gOutput, "") + return result.multiReplace([("\\", "/"), ("//", "/")]) proc c2nim*(fl, outfile: string, c2nimConfig: c2nimConfigObj) = var file = search(fl) if file.len() == 0: return - echo " Generating " & outfile - - # Remove static inline function bodies - removeStatic(file) - - fixFuncProtos(file) + echo "Generating " & outfile var cfile = file if c2nimConfig.preprocess: cfile = "temp-$#.c" % [outfile.extractFilename()] - writeFile(cfile, runPreprocess(file, c2nimConfig.ppflags, c2nimConfig.flags, c2nimConfig.inline)) + writeFileFlush(cfile, runPreprocess(file, c2nimConfig.ppflags, c2nimConfig.flags, c2nimConfig.inline)) elif c2nimConfig.ctags: cfile = "temp-$#.c" % [outfile.extractFilename()] - writeFile(cfile, runCtags(file)) + writeFileFlush(cfile, runCtags(file)) + + if c2nimConfig.removeBodies: + removeBodies(cfile) if c2nimConfig.defines and (c2nimConfig.preprocess or c2nimConfig.ctags): prepend(cfile, getDefines(file, c2nimConfig.inline)) + removeStatic(cfile) var extflags = "" passC = "" outlib = "" outpragma = "" - passC = "import ospaths, strutils\n" + passC = "import strutils\n" passC &= """const sourcePath = currentSourcePath().split({'\\', '/'})[0..^2].join("/")""" & "\n" @@ -98,18 +105,18 @@ proc c2nim*(fl, outfile: string, c2nimConfig: c2nimConfigObj) = removeFile(cfile) except: discard + else: + if c2nimConfig.removeBodies: + reAddBodies(cfile) + reAddStatic(cfile) # Nim doesn't like {.cdecl.} for type proc() - freplace(outfile, re"(?m)(.*? = proc.*?)\{.cdecl.\}", "$#") + freplace(outfile, re"(?m)(.*? = proc.*?)\{.cdecl.\}", "$1") freplace(outfile, " {.cdecl.})", ")") # Include {.compile.} directives for cpl in c2nimConfig.compile: - let fcpl = search(cpl) - if getFileInfo(fcpl).kind == pcFile: - prepend(outfile, compile(file=fcpl)) - else: - prepend(outfile, compile(dir=fcpl)) + prepend(outfile, compile(cpl, c2nimConfig.flags)) # Add any pragmas if outpragma != "": @@ -122,6 +129,3 @@ proc c2nim*(fl, outfile: string, c2nimConfig: c2nimConfigObj) = # Add dynamic library if outlib != "": prepend(outfile, outlib) - - # Add back static functions for compilation - reAddStatic(file) diff --git a/src/nimgen/external.nim b/src/nimgen/external.nim index 350c841..a887e20 100644 --- a/src/nimgen/external.nim +++ b/src/nimgen/external.nim @@ -1,4 +1,4 @@ -import os, osproc, regex, ropes, streams, strutils +import os, osproc, regex, streams, strutils import globals @@ -6,26 +6,25 @@ proc sanitizePath*(path: string): string = path.multiReplace([("\\", "/"), ("//", "/")]) proc execProc*(cmd: string): string = - result = "" - var - p = startProcess(cmd, options = {poStdErrToStdOut, poUsePath, poEvalCommand}) + var ret: int - 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: - echo "Command failed: " & $x + (result, ret) = execCmdEx(cmd) + if ret != 0: + echo "Command failed: " & $ret echo cmd echo result quit(1) +proc execAction*(cmd: string): string = + var ccmd = "" + when defined(Windows): + ccmd = "cmd /c " & cmd.replace("/", "\\") + when defined(Linux) or defined(MacOSX): + ccmd = "bash -c '" & cmd & "'" + + echo "Running '" & ccmd[0.. add compile entry * + -E add n.exclude entry * + -F set c2nim flags * + -I add n.include dir * + -O set output directory + -P set preprocessor flags * + +Options: + -c set ctags = true + -d set defines = true + -i set inline = true + -n set noprocess = true + -p set preprocess = true + -r set recurse = true + +Editing: + -a append string * + -e prepend string * + -l replace string * + -o#lines comment X lines * + -s search string * + -x regex search string * + +* supports multiple instances +""" + +proc runCli*() = + var + cfg = newOrderedTable[string, string]() + files: seq[string] + uniq = 1 + + gProjectDir = getCurrentDir().sanitizePath + for param in commandLineParams(): + let flag = if param.len() <= 2: param else: param[0..<2] + + if fileExists(param): + if param.splitFile().ext.toLowerAscii() == ".cfg": + runCfg(param) + else: + files.add(param) + + elif flag == "-C": + cfg["compile." & $uniq] = param[2..^1] + elif flag == "-E": + gExcludes.add(param[2..^1].addEnv().sanitizePath) + elif flag == "-F": + if cfg.hasKey("flags"): + cfg["flags"] = cfg["flags"] & " " & param[2..^1] + else: + cfg["flags"] = param[2..^1] + elif flag == "-I": + gIncludes.add(param[2..^1].addEnv().sanitizePath) + elif flag == "-O": + setOutputDir(param[2..^1]) + elif flag == "-P": + if cfg.hasKey("ppflags"): + cfg["ppflags"] = cfg["ppflags"] & " " & param[2..^1] + else: + cfg["ppflags"] = param[2..^1] + + elif flag == "-c": + cfg["ctags"] = "true" + elif flag == "-d": + cfg["defines"] = "true" + elif flag == "-i": + cfg["inline"] = "true" + elif flag == "-n": + cfg["noprocess"] = "true" + elif flag == "-p": + cfg["preprocess"] = "true" + elif flag == "-r": + cfg["recurse"] = "true" + + elif flag == "-a": + cfg["append." & $uniq] = param[2..^1] + elif flag == "-e": + cfg["prepend." & $uniq] = param[2..^1] + elif flag == "-l": + cfg["replace." & $uniq] = param[2..^1] + elif flag == "-o": + cfg["comment." & $uniq] = param[2..^1] + elif flag == "-s": + cfg["search." & $uniq] = param[2..^1] + elif flag == "-x": + cfg["regex." & $uniq] = param[2..^1] + + elif param == "-h" or param == "-?" or param == "--help": + echo gHelp + quit(0) + + uniq += 1 + + for file in files: + runFile(file, cfg) diff --git a/tests/nimgentest.nims b/tests/nimgentest.nims index 9c3e2d7..0de436a 100644 --- a/tests/nimgentest.nims +++ b/tests/nimgentest.nims @@ -1,52 +1,78 @@ import distros, ospaths, strutils var - full = true - comps = @["libsvm", "nim7z", "nimarchive", "nimbass", "nimbigwig", "nimclipboard", - "nimfuzz", "nimpcre", "nimrax", "nimssl", "nimssh2"] + pygonly = false + comps = @["nim7z", #"nimarchive", + "nimbass", "nimbigwig", + "nimclipboard", "nimfuzzy", "nimmonocypher", + #"nimnuklear", + "nimpcre", "nimrax", "nimssl", "nimssh2", + "nimtess2" + ] + +let + gccver = staticExec("gcc --version").split("\n")[0].split(" ")[^1] + nimver = staticExec("nim -v").split("\n")[0].split(" ")[3] + +if nimver >= "0.19.0" and (gccver >= "5.0.0" or detectOs(MacOSX)): + comps.add("nimfastText") if detectOs(Windows): comps.add("nimkerberos") +if not detectOs(MacOSX): + comps.add("nimzbar") + +echo "Nim version: " & nimver +echo "GCC version: " & gccver + +echo "Testing comps:" +for comp in comps: + echo " " & comp + if paramCount() > 2: for i in 3 .. paramCount(): - if paramStr(i) == "--full": - full = true + if paramStr(i) == "--pygonly": + pygonly = true elif paramStr(i).len() > 10 and "--comps=" in paramStr(i)[0 ..< 8]: comps = paramStr(i)[8 .. ^1].split(",") for comp in comps: - if not dirExists(".."/comp): - withDir(".."): - exec "git clone --depth=1 https://github.com/genotrance/" & comp + if not pygonly: + if not dirExists(".."/comp): + withDir(".."): + exec "git clone --depth=1 https://github.com/genotrance/" & comp - exec "nimble uninstall -y " & comp, "", "" - withDir(".."/comp): - exec "git pull" + exec "nimble uninstall -y " & comp, "", "" + withDir(".."/comp): + exec "git pull" - if full: rmDir(comp) exec "nimble install -y" exec "nimble test" - exec "nimble install -y" - exec "nimble test" + exec "nimble install -y" + exec "nimble test" - if dirExists("web"/comp): - rmDir("web"/comp) + when defined(windows): + if not pygonly: + if dirExists("web"/comp): + rmDir("web"/comp) - mkDir("web"/comp) - for file in listFiles(".."/comp/comp) & listFiles(".."/comp): - if file.splitFile().ext == ".nim": - cpFile(file, "web"/comp/extractFilename(file)) + mkDir("web"/comp) + for file in listFiles(".."/comp/comp) & listFiles(".."/comp): + if file.splitFile().ext == ".nim": + cpFile(file, "web"/comp/extractFilename(file)) - cpFile("web"/"nimdoc.cfg", "web"/comp/"nimdoc.cfg") - withDir("web"/comp): - for file in listFiles("."): - if file.splitFile().ext == ".nim": - exec "nim doc --git.url:. --index:on -o:" & file.changeFileExt("html") & " " & file - exec "pygmentize -f html -O full,linenos=1,anchorlinenos=True,lineanchors=L,style=vs -o " & file & ".html " & file + cpFile("web"/"nimdoc.cfg", "web"/comp/"nimdoc.cfg") + withDir("web"/comp): + for file in listFiles("."): + if file.splitFile().ext == ".nim": + if not pygonly: + exec "nim doc --git.url:. --index:on -o:" & file.changeFileExt("html") & " " & file + exec "pygmentize -f html -O full,linenos=1,anchorlinenos=True,lineanchors=L,style=vs -o " & file & ".html " & file - exec "nim buildIndex -o:index.html ." - rmFile("web"/comp/"nimdoc.cfg") + if not pygonly: + exec "nim buildIndex -o:index.html ." + rmFile("web"/comp/"nimdoc.cfg") diff --git a/tests/rununittests.nim b/tests/rununittests.nim index a92ff0a..865f77d 100644 --- a/tests/rununittests.nim +++ b/tests/rununittests.nim @@ -1,8 +1,10 @@ import os, osproc, strutils proc main() = + var failures = 0 for file in walkFiles(currentSourcePath().splitPath().head / "unittests/*.nim"): let (path, fname, ext) = file.splitFile() if fname.startswith("test"): - discard execCmd "nim c -r " & file + failures += execCmd "nim c -r " & file + quit(failures) main() diff --git a/tests/unittests/testfileops.nim b/tests/unittests/testfileops.nim index 2fff387..2d24d4e 100644 --- a/tests/unittests/testfileops.nim +++ b/tests/unittests/testfileops.nim @@ -97,8 +97,6 @@ suite "test file ops": dataDir.createDir() setup: - if testfilename.existsFile(): - removeFile(testfilename) writeFile(testfilename, testFileContent) ################### Prepend ####################### @@ -120,7 +118,7 @@ suite "test file ops": test "pipe command into file": when defined(windows): - pipe(testfilename, "(ECHO foo)>>$file") + pipe(testfilename, "ECHO foo") testfilename.checkFile("foo") else: pipe(testfilename, "cat $file | grep 'this is text'") diff --git a/web/CNAME b/web/CNAME new file mode 100644 index 0000000..2c6879b --- /dev/null +++ b/web/CNAME @@ -0,0 +1 @@ +nimgen.genotrance.com \ No newline at end of file diff --git a/web/nimdoc.cfg b/web/nimdoc.cfg new file mode 100644 index 0000000..55c2827 --- /dev/null +++ b/web/nimdoc.cfg @@ -0,0 +1,1401 @@ +# This is the config file for the documentation generator. +# (c) 2016 Andreas Rumpf +# Feel free to edit the templates as you need. If you modify this file, it +# might be worth updating the hardcoded values in packages/docutils/rstgen.nim + +split.item.toc = "20" +# too long entries in the table of contents wrap around +# after this number of characters + +doc.section = """ +
+

$sectionTitle

+
+$content +
+""" + +doc.section.toc = """ +
  • + $sectionTitle +
      + $content +
    +
  • +""" + +# Chunk of HTML emitted for each entry in the HTML table of contents. +# Available variables are: +# * $desc: the actual docstring of the item. +# * $header: the full version of name, including types, pragmas, tags, etc. +# * $header_plain: like header but without HTML, for attribute embedding. +# * $itemID: numerical unique entry of the item in the HTML. +# * $itemSym: short symbolic name of the item for easier hyperlinking. +# * $itemSymEnc: quoted version for URLs or attributes. +# * $itemSymOrID: the symbolic name or the ID if that is not unique. +# * $itemSymOrIDEnc: quoted version for URLs or attributes. +# * $name: reduced name of the item. +# * $seeSrc: generated HTML from doc.item.seesrc (if some switches are used). + +doc.item = """ +
    $header
    +
    +$desc +$seeSrc +
    +""" + +# Chunk of HTML emitted for each entry in the HTML table of contents. +# See doc.item for available substitution variables. +doc.item.toc = """ +
  • $name
  • +""" + +# HTML rendered for doc.item's seeSrc variable. Note that this will render to +# the empty string if you don't pass anything through --docSeeSrcURL. Available +# substitutaion variables here are: +# * $path: relative path to the file being processed. +# * $line: line of the item in the original source file. +# * $url: whatever you did pass through the --docSeeSrcUrl switch (which also +# gets variables path/line replaced!) +doc.item.seesrc = """  Source +""" + +doc.toc = """ +
      +$content +
    +""" + +doc.body_toc = """ +
    +
    +
    + Search: +
    + $tableofcontents +
    +
    +
    +

    $moduledesc

    + $content +
    +
    +""" + +@if boot: +# This is enabled with the "boot" directive to generate +# the compiler documentation. +# As a user, tweak the block below instead. +# You can add your own global-links entries +doc.body_toc_group = """ +
    +
    + +
    + Search: +
    +
    + Group by: + +
    + $tableofcontents +
    +
    +
    +

    $moduledesc

    + $content +
    +
    +""" + +@else + +doc.body_toc_group = """ +
    +
    + +
    + Search: +
    +
    + Group by: + +
    + $tableofcontents +
    +
    +
    +

    $moduledesc

    + $content +
    +
    +""" +@end + +doc.body_no_toc = """ +$moduledesc +$content +""" + +doc.listing_start = "
    "
    +doc.listing_end = "
    " + +# * $analytics: Google analytics location, includes + + + + + +
    +
    +

    $title

    + $content +
    + +
    +
    +
    +$analytics + + +"""