Compare commits
87 commits
fix_cross_
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
638c9b4a5a | ||
|
|
942ae8e803 | ||
|
|
2be81614a9 | ||
|
|
39f5f320a6 | ||
|
|
fabd615379 | ||
|
|
b54feea3fc | ||
|
|
4ab5ff93b8 | ||
|
|
97141f523f | ||
|
|
d6f8d140cc | ||
|
|
69b9ee9083 | ||
|
|
293476c0a9 | ||
|
|
cf132951bd | ||
|
|
31b63a6ea6 | ||
|
|
5199b86b74 |
||
|
|
46cce39e64 | ||
|
|
2f1a62a030 | ||
|
|
24c62dbc18 | ||
|
|
86df7b19f1 | ||
|
|
d6241b1da4 | ||
|
|
02459f3d82 | ||
|
|
b78f6d38fd | ||
|
|
44fc30a9cb | ||
|
|
ae6d4aff28 | ||
|
|
47ca2cffd6 | ||
|
|
c60a8cd415 | ||
|
|
5be86fcd99 | ||
|
|
a8b836656e | ||
|
|
81fa6d15ba | ||
|
|
d6c827bb28 | ||
|
|
03c38a2448 | ||
|
|
d080be55a5 | ||
|
|
d27d28f0d9 | ||
|
|
c7c419e6fa | ||
|
|
5549505f61 | ||
|
|
34efd6619f | ||
|
|
715b502274 | ||
|
|
c40919b87c | ||
|
|
713703caae | ||
|
|
ee7a55f2ec | ||
|
|
f1a8d17891 | ||
|
|
8188c75118 | ||
|
|
ad49917733 | ||
|
|
ebd362d934 | ||
|
|
e8faaf8d0c | ||
|
|
9ec27678ea | ||
|
|
1f3ae34dc0 | ||
|
|
1c057f2520 | ||
|
|
caba6fcc50 | ||
|
|
da865618be | ||
|
|
b5030a8bd5 | ||
|
|
c4d45b318b | ||
|
|
35765f046b | ||
|
|
db26f9580d | ||
|
|
83465b25de | ||
|
|
efc04c38cc | ||
|
|
e04b40d6a8 | ||
|
|
4df59320fd | ||
|
|
6b16a83572 | ||
|
|
0a32e7fa2c | ||
|
|
2f27ad0d05 | ||
|
|
6c8bf5e842 | ||
|
|
598214c1d2 | ||
|
|
8eaa765601 | ||
|
|
23bb86803d | ||
|
|
7082f89781 | ||
|
|
a2a2c41704 | ||
|
|
864506afbc | ||
|
|
02de68b36d | ||
|
|
1711052eae | ||
|
|
7e21b2799e | ||
|
|
1e26d3e6eb | ||
|
|
1a29b9f0f8 | ||
|
|
1fb8674d07 | ||
|
|
bb2c9474fa | ||
|
|
667d6caf84 | ||
|
|
0406d83384 | ||
|
|
db0363505e |
||
|
|
32debc5534 | ||
|
|
1dbff5cbd1 | ||
|
|
c6148571c1 | ||
|
|
87e08bfb66 | ||
|
|
2c3cc71540 | ||
|
|
dc9943a22c |
||
|
|
f3c01e53f9 | ||
|
|
6343567a91 | ||
|
|
5e3c0999e0 | ||
|
|
aad005e0b1 |
17 changed files with 2099 additions and 369 deletions
27
.travis.yml
Normal file
27
.travis.yml
Normal file
|
|
@ -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
|
||||||
85
README.md
85
README.md
|
|
@ -1,3 +1,7 @@
|
||||||
|
[](https://gitter.im/nimgen/Lobby)
|
||||||
|
[](https://ci.appveyor.com/project/genotrance/nimgen/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 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.
|
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
|
* [nim-clblast](https://github.com/numforge/nim-clblast) - OpenCL BLAS wrapper
|
||||||
* static
|
* 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)
|
* [nim7z](https://github.com/genotrance/nim7z) - 7z decoder wrapper: [docs](http://nimgen.genotrance.com/nim7z)
|
||||||
* git sparse checkout
|
* git sparse checkout
|
||||||
* [nimarchive](https://github.com/genotrance/nimarchive) - libarchive wrapper: [docs](http://nimgen.genotrance.com/nimarchive)
|
* [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
|
* git checkout
|
||||||
* [nimclipboard](https://github.com/genotrance/nimclipboard) - libclipboard wrapper: [docs](http://nimgen.genotrance.com/nimclipboard)
|
* [nimclipboard](https://github.com/genotrance/nimclipboard) - libclipboard wrapper: [docs](http://nimgen.genotrance.com/nimclipboard)
|
||||||
* git checkout
|
* 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
|
* download header file
|
||||||
* [nimkerberos](https://github.com/genotrance/nimkerberos) - WinKerberos wrapper: [docs](http://nimgen.genotrance.com/nimkerberos)
|
* [nimkerberos](https://github.com/genotrance/nimkerberos) - WinKerberos wrapper: [docs](http://nimgen.genotrance.com/nimkerberos)
|
||||||
* git sparse checkout
|
* 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)
|
* [nimpcre](https://github.com/genotrance/nimpcre) - PCRE wrapper: [docs](http://nimgen.genotrance.com/nimpcre)
|
||||||
* git checkout
|
* git checkout
|
||||||
* [nimrax](https://github.com/genotrance/nimrax) - Radix tree wrapper: [docs](http://nimgen.genotrance.com/nimrax)
|
* [nimrax](https://github.com/genotrance/nimrax) - Radix tree wrapper: [docs](http://nimgen.genotrance.com/nimrax)
|
||||||
* git checkout
|
* git checkout
|
||||||
* [nimssl](https://github.com/genotrance/nimssl) - OpenSSL wrapper: [docs](http://nimgen.genotrance.com/nimssl)
|
* [nimssl](https://github.com/genotrance/nimssl) - OpenSSL wrapper: [docs](http://nimgen.genotrance.com/nimssl)
|
||||||
* git sparse checkout
|
* git sparse checkout
|
||||||
* [libsvm](https://github.com/genotrance/libsvm) - libsvm wrapper: [docs](http://nimgen.genotrance.com/libsvm)
|
* [nimtess2](https://github.com/genotrance/nimtess2) - libtess2 wrapper: [docs](http://nimgen.genotrance.com/nimtess2)
|
||||||
* git sparse checkout
|
* git checkout
|
||||||
|
* [duktape-nim](https://github.com/manguluka/duktape-nim) - Duktape wrapper
|
||||||
|
* static
|
||||||
|
|
||||||
* Compile in as static binary
|
* Compile in as static binary
|
||||||
* [nimssh2](https://github.com/genotrance/nimssh2) - libssh2 wrapper: [docs](http://nimgen.genotrance.com/nimssh2)
|
* [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"
|
"${output}/library/include"
|
||||||
"${MY_INCLUDE_PATH}/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]_
|
_[n.global]_
|
||||||
|
|
||||||
```output``` = name of the Nimble project once installed, also location to place generated .nim files
|
```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]_
|
_[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
|
```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.
|
```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
|
```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
|
```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.
|
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
|
```execute``` = command to run after processing
|
||||||
|
|
||||||
|
|
@ -142,7 +162,7 @@ This section allows selection of multiple sourcefiles without requiring a detail
|
||||||
|
|
||||||
_[sourcefile]_
|
_[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]
|
```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
|
```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]
|
```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
|
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".}
|
```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.
|
```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
|
```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
|
```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
|
```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
|
```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`
|
`$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<compile> add compile entry *
|
||||||
|
-E<exclude> add n.exclude entry *
|
||||||
|
-F<flags> set c2nim flags *
|
||||||
|
-I<include> add n.include dir *
|
||||||
|
-O<outdir> set output directory
|
||||||
|
-P<ppflags> 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> append string *
|
||||||
|
-e<prepend> prepend string *
|
||||||
|
-l<replace> replace string *
|
||||||
|
-o#lines comment X lines *
|
||||||
|
-s<search> search string *
|
||||||
|
-x<regex> regex search string *
|
||||||
|
|
||||||
|
* supports multiple instances
|
||||||
|
```
|
||||||
|
|
||||||
__Feedback__
|
__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.
|
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.
|
||||||
|
|
|
||||||
126
appveyor.yml
126
appveyor.yml
|
|
@ -7,6 +7,11 @@ image:
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
|
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- NIM_VERSION: 0.20.0
|
||||||
|
- NIM_VERSION: 0.19.6
|
||||||
|
|
||||||
for:
|
for:
|
||||||
-
|
-
|
||||||
matrix:
|
matrix:
|
||||||
|
|
@ -14,93 +19,80 @@ for:
|
||||||
- image: Visual Studio 2017
|
- image: Visual Studio 2017
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
MINGW_DIR: mingw32
|
ARCH: 32
|
||||||
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
|
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
|
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
|
SFNET_URL: https://sourceforge.net/projects/msys2/files/REPOS/MINGW/i686
|
||||||
NIM_ARCHIVE: nim-0.18.0_x32.zip
|
LIBSSH2_ARCHIVE: mingw-w64-i686-libssh2-1.8.0-1-any.pkg
|
||||||
NIM_VERSION: nim-0.18.0
|
LIBCRYPTO_ARCHIVE: mingw-w64-i686-openssl-1.0.2.o-1-any.pkg
|
||||||
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
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- CD %BASE_DIR%
|
- CD c:\
|
||||||
- IF not exist "%MINGW_ARCHIVE%" appveyor DownloadFile "%MINGW_URL%" -FileName "%MINGW_ARCHIVE%"
|
- IF not exist "binaries" (
|
||||||
- 7z x -y "%MINGW_ARCHIVE%"> nul
|
echo %NIM_VERSION% &&
|
||||||
- IF not exist "%LIBSSH2_ARCHIVE%" appveyor DownloadFile "%LIBSSH2_URL%" -FileName "%LIBSSH2_ARCHIVE%"
|
MKDIR binaries &&
|
||||||
- 7z x -y "%LIBSSH2_ARCHIVE%"> nul
|
CD binaries &&
|
||||||
- 7z x -y "%LIBSSH2_ARCHIVE2%"> nul
|
appveyor DownloadFile "%MINGW_URL%/%MINGW_ARCHIVE%/download" -FileName "%MINGW_ARCHIVE%" &&
|
||||||
- IF not exist "%LIBCRYPTO_ARCHIVE%" appveyor DownloadFile "%LIBCRYPTO_URL%" -FileName "%LIBCRYPTO_ARCHIVE%"
|
7z x -y "%MINGW_ARCHIVE%"> nul &&
|
||||||
- 7z x -y "%LIBCRYPTO_ARCHIVE%"> nul
|
del "%MINGW_ARCHIVE%" &&
|
||||||
- 7z x -y "%LIBCRYPTO_ARCHIVE2%"> nul
|
appveyor DownloadFile "%SFNET_URL%/%LIBSSH2_ARCHIVE%.tar.xz/download" -FileName "%LIBSSH2_ARCHIVE%.tar.xz" &&
|
||||||
- IF not exist "%NIM_ARCHIVE%" appveyor DownloadFile "%NIM_URL%" -FileName "%NIM_ARCHIVE%"
|
7z x -y "%LIBSSH2_ARCHIVE%.tar.xz"> nul &&
|
||||||
- 7z x -y "%NIM_ARCHIVE%"> nul
|
del "%LIBSSH2_ARCHIVE%.tar.xz" &&
|
||||||
- SET PATH=%BASE_DIR%\%MINGW_DIR%\bin;%BASE_DIR%\%NIM_VERSION%\bin;%USERPROFILE%\.nimble\bin;%PATH%
|
7z x -y "%LIBSSH2_ARCHIVE%.tar"> nul &&
|
||||||
- CD %BASE_DIR%\nimgen
|
del "%LIBSSH2_ARCHIVE%.tar" &&
|
||||||
# - git clone --depth 1 https://github.com/nim-lang/nim
|
appveyor DownloadFile "%SFNET_URL%/%LIBCRYPTO_ARCHIVE%.tar.xz/download" -FileName "%LIBCRYPTO_ARCHIVE%.tar.xz" &&
|
||||||
# - cd nim
|
7z x -y "%LIBCRYPTO_ARCHIVE%.tar.xz"> nul &&
|
||||||
# - git clone --depth 1 https://github.com/nim-lang/csources
|
del "%LIBCRYPTO_ARCHIVE%.tar.xz" &&
|
||||||
# - cd csources
|
7z x -y "%LIBCRYPTO_ARCHIVE%.tar"> nul &&
|
||||||
# - IF "%PLATFORM%" == "x64" ( build64.bat ) else ( build.bat )
|
del "%LIBCRYPTO_ARCHIVE%.tar" &&
|
||||||
# - cd ..
|
appveyor DownloadFile "https://nim-lang.org/download/nim-%NIM_VERSION%_x%ARCH%.zip" -FileName "nim-%NIM_VERSION%_x%ARCH%.zip" &&
|
||||||
# - IF not exist "%DLLS_ARCHIVE%" appveyor DownloadFile "%DLLS_URL%" -FileName "%DLLS_ARCHIVE%"
|
7z x -y "nim-%NIM_VERSION%_x%ARCH%.zip"> nul &&
|
||||||
# - 7z x -y "%DLLS_ARCHIVE%" -o"%CD%\bin"> nul
|
del "nim-%NIM_VERSION%_x%ARCH%.zip")
|
||||||
# - bin\nim c -d:release koch
|
- SET PATH=c:\binaries\mingw%ARCH%\bin;c:\binaries\nim-%NIM_VERSION%\bin;%USERPROFILE%\.nimble\bin;%PATH%
|
||||||
# - koch boot -d:release
|
- CD c:\projects\nimgen
|
||||||
# - koch nimble -d:release
|
|
||||||
# - SET PATH=%CD%\bin;%PATH%
|
|
||||||
# - cd ..
|
|
||||||
|
|
||||||
on_finish:
|
on_finish:
|
||||||
- 7z a -r buildlogs-win.zip %USERPROFILE%\.nimble\pkgs
|
- 7z a -r buildlogs-win-pkgs.zip %USERPROFILE%\.nimble\pkgs
|
||||||
- appveyor PushArtifact buildlogs-win.zip
|
- appveyor PushArtifact buildlogs-win-pkgs.zip
|
||||||
- 7z a -r nimgen-docs.zip %BASE_DIR%\nimgen\web
|
- 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
|
- appveyor PushArtifact nimgen-docs.zip
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
- c:\projects\i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z
|
- c:\binaries
|
||||||
- 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
|
|
||||||
|
|
||||||
-
|
-
|
||||||
matrix:
|
matrix:
|
||||||
only:
|
only:
|
||||||
- image: Ubuntu
|
- 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:
|
install:
|
||||||
- sudo apt -qq update
|
- sudo apt -qq update
|
||||||
- sudo apt -qq install --yes python-pygments libssh2-1-dev libgcrypt20-dev libgpg-error-dev
|
- sudo apt -qq install --yes libssh2-1-dev libgcrypt20-dev libgpg-error-dev
|
||||||
- cd $BASE_DIR
|
- if [ ! -e /home/appveyor/binaries ]; then
|
||||||
- if [ ! -e $NIM_ARCHIVE ]; then curl -s -o $NIM_ARCHIVE $NIM_URL; fi
|
echo $NIM_VERSION &&
|
||||||
- tar xJf $NIM_ARCHIVE
|
mkdir /home/appveyor/binaries &&
|
||||||
- cd $NIM_VERSION
|
cd /home/appveyor/binaries &&
|
||||||
- sh build.sh
|
curl -s -o nim-$NIM_VERSION.tar.xz https://nim-lang.org/download/nim-$NIM_VERSION.tar.xz &&
|
||||||
- bin/nim c -d:release koch
|
tar xJf nim-$NIM_VERSION.tar.xz &&
|
||||||
- ./koch boot -d:release
|
cd nim-$NIM_VERSION &&
|
||||||
- ./koch nimble -d:release
|
sh build.sh &&
|
||||||
- export PATH=$BASE_DIR/$NIM_VERSION/bin:~/.nimble/bin:$PATH
|
bin/nim c -d:release koch &&
|
||||||
- cd $BASE_DIR/nimgen
|
./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:
|
on_finish:
|
||||||
- zip -r -q buildlogs-lin.zip ~/.nimble/pkgs
|
- zip -r -q buildlogs-lin-pkgs.zip ~/.nimble/pkgs
|
||||||
- appveyor PushArtifact buildlogs-lin.zip
|
- appveyor PushArtifact buildlogs-lin-pkgs.zip
|
||||||
|
- zip -r -q buildlogs-lin-projects.zip /home/appveyor/projects
|
||||||
|
- appveyor PushArtifact buildlogs-lin-projects.zip
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
- /home/appveyor/projects/nim-0.18.0.tar.xz
|
- /home/appveyor/binaries
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- nimble install -y
|
- nimble install -y
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "0.3.0"
|
version = "0.5.1"
|
||||||
author = "genotrance"
|
author = "genotrance"
|
||||||
description = "c2nim helper to simplify and automate the wrapping of C libraries"
|
description = "c2nim helper to simplify and automate the wrapping of C libraries"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
bin = @["nimgen"]
|
bin = @["nimgen"]
|
||||||
srcDir = "src"
|
srcDir = "src"
|
||||||
skipDirs = @["nimgen", "tests"]
|
skipDirs = @["nimgen", "tests", "web"]
|
||||||
|
|
||||||
# Dependencies
|
# 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":
|
task test, "Test nimgen":
|
||||||
exec "nim c -r tests/rununittests.nim"
|
exec "nim c -r tests/rununittests.nim"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,4 @@ import os
|
||||||
|
|
||||||
import nimgen/runcfg
|
import nimgen/runcfg
|
||||||
|
|
||||||
for i in commandLineParams():
|
runCli()
|
||||||
if i != "-f":
|
|
||||||
runCfg(i)
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
import external, file, fileops, gencore, globals
|
||||||
|
|
||||||
template relativePath(path: untyped): untyped =
|
proc relativePath(path: string): string =
|
||||||
path.multiReplace([(gOutput, ""), ("\\", "/"), ("//", "/")])
|
if gOutput.len() == 0:
|
||||||
|
result = path
|
||||||
|
else:
|
||||||
|
# multiReplace() bug - #9557
|
||||||
|
result = path.replace(gOutput, "")
|
||||||
|
return result.multiReplace([("\\", "/"), ("//", "/")])
|
||||||
|
|
||||||
proc c2nim*(fl, outfile: string, c2nimConfig: c2nimConfigObj) =
|
proc c2nim*(fl, outfile: string, c2nimConfig: c2nimConfigObj) =
|
||||||
var file = search(fl)
|
var file = search(fl)
|
||||||
if file.len() == 0:
|
if file.len() == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
echo " Generating " & outfile
|
echo "Generating " & outfile
|
||||||
|
|
||||||
# Remove static inline function bodies
|
|
||||||
removeStatic(file)
|
|
||||||
|
|
||||||
fixFuncProtos(file)
|
|
||||||
|
|
||||||
var cfile = file
|
var cfile = file
|
||||||
if c2nimConfig.preprocess:
|
if c2nimConfig.preprocess:
|
||||||
cfile = "temp-$#.c" % [outfile.extractFilename()]
|
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:
|
elif c2nimConfig.ctags:
|
||||||
cfile = "temp-$#.c" % [outfile.extractFilename()]
|
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):
|
if c2nimConfig.defines and (c2nimConfig.preprocess or c2nimConfig.ctags):
|
||||||
prepend(cfile, getDefines(file, c2nimConfig.inline))
|
prepend(cfile, getDefines(file, c2nimConfig.inline))
|
||||||
|
|
||||||
|
removeStatic(cfile)
|
||||||
var
|
var
|
||||||
extflags = ""
|
extflags = ""
|
||||||
passC = ""
|
passC = ""
|
||||||
outlib = ""
|
outlib = ""
|
||||||
outpragma = ""
|
outpragma = ""
|
||||||
|
|
||||||
passC = "import ospaths, strutils\n"
|
passC = "import strutils\n"
|
||||||
|
|
||||||
passC &= """const sourcePath = currentSourcePath().split({'\\', '/'})[0..^2].join("/")""" & "\n"
|
passC &= """const sourcePath = currentSourcePath().split({'\\', '/'})[0..^2].join("/")""" & "\n"
|
||||||
|
|
||||||
|
|
@ -98,18 +105,18 @@ proc c2nim*(fl, outfile: string, c2nimConfig: c2nimConfigObj) =
|
||||||
removeFile(cfile)
|
removeFile(cfile)
|
||||||
except:
|
except:
|
||||||
discard
|
discard
|
||||||
|
else:
|
||||||
|
if c2nimConfig.removeBodies:
|
||||||
|
reAddBodies(cfile)
|
||||||
|
reAddStatic(cfile)
|
||||||
|
|
||||||
# Nim doesn't like {.cdecl.} for type proc()
|
# Nim doesn't like {.cdecl.} for type proc()
|
||||||
freplace(outfile, re"(?m)(.*? = proc.*?)\{.cdecl.\}", "$#")
|
freplace(outfile, re"(?m)(.*? = proc.*?)\{.cdecl.\}", "$1")
|
||||||
freplace(outfile, " {.cdecl.})", ")")
|
freplace(outfile, " {.cdecl.})", ")")
|
||||||
|
|
||||||
# Include {.compile.} directives
|
# Include {.compile.} directives
|
||||||
for cpl in c2nimConfig.compile:
|
for cpl in c2nimConfig.compile:
|
||||||
let fcpl = search(cpl)
|
prepend(outfile, compile(cpl, c2nimConfig.flags))
|
||||||
if getFileInfo(fcpl).kind == pcFile:
|
|
||||||
prepend(outfile, compile(file=fcpl))
|
|
||||||
else:
|
|
||||||
prepend(outfile, compile(dir=fcpl))
|
|
||||||
|
|
||||||
# Add any pragmas
|
# Add any pragmas
|
||||||
if outpragma != "":
|
if outpragma != "":
|
||||||
|
|
@ -122,6 +129,3 @@ proc c2nim*(fl, outfile: string, c2nimConfig: c2nimConfigObj) =
|
||||||
# Add dynamic library
|
# Add dynamic library
|
||||||
if outlib != "":
|
if outlib != "":
|
||||||
prepend(outfile, outlib)
|
prepend(outfile, outlib)
|
||||||
|
|
||||||
# Add back static functions for compilation
|
|
||||||
reAddStatic(file)
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import os, osproc, regex, ropes, streams, strutils
|
import os, osproc, regex, streams, strutils
|
||||||
|
|
||||||
import globals
|
import globals
|
||||||
|
|
||||||
|
|
@ -6,26 +6,25 @@ proc sanitizePath*(path: string): string =
|
||||||
path.multiReplace([("\\", "/"), ("//", "/")])
|
path.multiReplace([("\\", "/"), ("//", "/")])
|
||||||
|
|
||||||
proc execProc*(cmd: string): string =
|
proc execProc*(cmd: string): string =
|
||||||
result = ""
|
var ret: int
|
||||||
var
|
|
||||||
p = startProcess(cmd, options = {poStdErrToStdOut, poUsePath, poEvalCommand})
|
|
||||||
|
|
||||||
outp = outputStream(p)
|
(result, ret) = execCmdEx(cmd)
|
||||||
line = newStringOfCap(120).TaintedString
|
if ret != 0:
|
||||||
|
echo "Command failed: " & $ret
|
||||||
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
|
|
||||||
echo cmd
|
echo cmd
|
||||||
echo result
|
echo result
|
||||||
quit(1)
|
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..<min(64, len(ccmd))] & "'"
|
||||||
|
return execProc(ccmd)
|
||||||
|
|
||||||
proc extractZip*(zipfile: string) =
|
proc extractZip*(zipfile: string) =
|
||||||
var cmd = "unzip -o $#"
|
var cmd = "unzip -o $#"
|
||||||
if defined(Windows):
|
if defined(Windows):
|
||||||
|
|
@ -44,9 +43,10 @@ proc downloadUrl*(url: string) =
|
||||||
file = url.extractFilename()
|
file = url.extractFilename()
|
||||||
ext = file.splitFile().ext.toLowerAscii()
|
ext = file.splitFile().ext.toLowerAscii()
|
||||||
|
|
||||||
var cmd = "curl $# -o $#"
|
var cmd = if defined(Windows):
|
||||||
if defined(Windows):
|
"powershell [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; wget $# -OutFile $#"
|
||||||
cmd = "powershell wget $# -OutFile $#"
|
else:
|
||||||
|
"curl -L $# -o $#"
|
||||||
|
|
||||||
if not (ext == ".zip" and fileExists(gOutput/file)):
|
if not (ext == ".zip" and fileExists(gOutput/file)):
|
||||||
echo "Downloading " & file
|
echo "Downloading " & file
|
||||||
|
|
@ -55,53 +55,67 @@ proc downloadUrl*(url: string) =
|
||||||
if ext == ".zip":
|
if ext == ".zip":
|
||||||
extractZip(file)
|
extractZip(file)
|
||||||
|
|
||||||
proc gitReset*() =
|
template setGitDir() =
|
||||||
echo "Resetting Git repo"
|
setCurrentDir(gGitOutput)
|
||||||
|
|
||||||
setCurrentDir(gOutput)
|
|
||||||
defer: setCurrentDir(gProjectDir)
|
defer: setCurrentDir(gProjectDir)
|
||||||
|
|
||||||
discard execProc("git reset --hard HEAD")
|
proc gitReset*() =
|
||||||
|
echo "Resetting " & gGitOutput
|
||||||
|
|
||||||
|
setGitDir()
|
||||||
|
|
||||||
|
let cmd = "git reset --hard"
|
||||||
|
while execCmdEx(cmd)[0].contains("Permission denied"):
|
||||||
|
sleep(1000)
|
||||||
|
echo " Retrying ..."
|
||||||
|
|
||||||
proc gitCheckout*(file: string) =
|
proc gitCheckout*(file: string) =
|
||||||
echo " Resetting " & file
|
echo "Resetting " & file
|
||||||
|
|
||||||
setCurrentDir(gOutput)
|
setGitDir()
|
||||||
defer: setCurrentDir(gProjectDir)
|
|
||||||
|
|
||||||
discard execProc("git checkout $#" % file.replace(gOutput & "/", ""))
|
let cmd = "git checkout $#" % file.replace(gGitOutput & "/", "")
|
||||||
|
while execCmdEx(cmd)[0].contains("Permission denied"):
|
||||||
|
sleep(500)
|
||||||
|
echo " Retrying ..."
|
||||||
|
|
||||||
|
proc gitPull() =
|
||||||
|
if gGitCheckout.len() != 0:
|
||||||
|
echo "Checking out " & gGitCheckout
|
||||||
|
discard execProc("git pull --tags origin master")
|
||||||
|
discard execProc("git checkout " & gGitCheckout)
|
||||||
|
gGitCheckout = ""
|
||||||
|
else:
|
||||||
|
echo "Pulling repository"
|
||||||
|
discard execProc("git pull --depth=1 origin master")
|
||||||
|
|
||||||
proc gitRemotePull*(url: string, pull=true) =
|
proc gitRemotePull*(url: string, pull=true) =
|
||||||
if dirExists(gOutput/".git"):
|
if dirExists(gGitOutput/".git"):
|
||||||
if pull:
|
if pull:
|
||||||
gitReset()
|
gitReset()
|
||||||
return
|
return
|
||||||
|
|
||||||
setCurrentDir(gOutput)
|
setGitDir()
|
||||||
defer: setCurrentDir(gProjectDir)
|
|
||||||
|
|
||||||
echo "Setting up Git repo"
|
echo "Setting up Git repo: " & url
|
||||||
discard execProc("git init .")
|
discard execProc("git init .")
|
||||||
discard execProc("git remote add origin " & url)
|
discard execProc("git remote add origin " & url)
|
||||||
|
|
||||||
if pull:
|
if pull:
|
||||||
echo "Checking out artifacts"
|
gitPull()
|
||||||
discard execProc("git pull --depth=1 origin master")
|
|
||||||
|
|
||||||
proc gitSparseCheckout*(plist: string) =
|
proc gitSparseCheckout*(plist: string) =
|
||||||
let sparsefile = ".git/info/sparse-checkout"
|
let sparsefile = ".git/info/sparse-checkout"
|
||||||
if fileExists(gOutput/sparsefile):
|
if fileExists(gGitOutput/sparsefile):
|
||||||
gitReset()
|
gitReset()
|
||||||
return
|
return
|
||||||
|
|
||||||
setCurrentDir(gOutput)
|
setGitDir()
|
||||||
defer: setCurrentDir(gProjectDir)
|
|
||||||
|
|
||||||
discard execProc("git config core.sparsecheckout true")
|
discard execProc("git config core.sparsecheckout true")
|
||||||
writeFile(sparsefile, plist)
|
writeFile(sparsefile, plist)
|
||||||
|
|
||||||
echo "Checking out artifacts"
|
gitPull()
|
||||||
discard execProc("git pull --depth=1 origin master")
|
|
||||||
|
|
||||||
proc runPreprocess*(file, ppflags, flags: string, inline: bool): string =
|
proc runPreprocess*(file, ppflags, flags: string, inline: bool): string =
|
||||||
var
|
var
|
||||||
|
|
@ -116,9 +130,9 @@ proc runPreprocess*(file, ppflags, flags: string, inline: bool): string =
|
||||||
|
|
||||||
# Include content only from file
|
# Include content only from file
|
||||||
var
|
var
|
||||||
rdata: Rope
|
rdata: seq[string] = @[]
|
||||||
start = false
|
start = false
|
||||||
sfile = file.replace("\\", "/")
|
sfile = file.sanitizePath
|
||||||
|
|
||||||
if inline:
|
if inline:
|
||||||
sfile = sfile.parentDir()
|
sfile = sfile.parentDir()
|
||||||
|
|
@ -136,9 +150,9 @@ proc runPreprocess*(file, ppflags, flags: string, inline: bool): string =
|
||||||
line.multiReplace([("_Noreturn", ""), ("(())", ""), ("WINAPI", ""),
|
line.multiReplace([("_Noreturn", ""), ("(())", ""), ("WINAPI", ""),
|
||||||
("__attribute__", ""), ("extern \"C\"", "")])
|
("__attribute__", ""), ("extern \"C\"", "")])
|
||||||
.replace(re"\(\([_a-z]+?\)\)", "")
|
.replace(re"\(\([_a-z]+?\)\)", "")
|
||||||
.replace(re"\(\(__format__[\s]*\(__[gnu_]*printf__, [\d]+, [\d]+\)\)\);", ";") & "\n"
|
.replace(re"\(\(__format__[\s]*\(__[gnu_]*printf__, [\d]+, [\d]+\)\)\);", ";")
|
||||||
)
|
)
|
||||||
return $rdata
|
return rdata.join("\n")
|
||||||
|
|
||||||
proc runCtags*(file: string): string =
|
proc runCtags*(file: string): string =
|
||||||
var
|
var
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
import os, ospaths, pegs, regex, strutils, tables
|
import os, pegs, regex, strutils, tables
|
||||||
|
|
||||||
import globals
|
when (NimMajor, NimMinor, NimPatch) < (0, 19, 9):
|
||||||
|
import ospaths
|
||||||
|
|
||||||
|
import globals, external
|
||||||
|
|
||||||
# ###
|
# ###
|
||||||
# File loction
|
# File loction
|
||||||
|
|
@ -16,8 +19,7 @@ proc getNimout*(file: string, rename=true): string =
|
||||||
if gRenames.hasKey(file):
|
if gRenames.hasKey(file):
|
||||||
result = gRenames[file]
|
result = gRenames[file]
|
||||||
|
|
||||||
if not dirExists(parentDir(result)):
|
createDir(parentDir(result))
|
||||||
createDir(parentDir(result))
|
|
||||||
|
|
||||||
proc exclude*(file: string): bool =
|
proc exclude*(file: string): bool =
|
||||||
for excl in gExcludes:
|
for excl in gExcludes:
|
||||||
|
|
@ -44,7 +46,7 @@ proc search*(file: string): string =
|
||||||
quit(1)
|
quit(1)
|
||||||
|
|
||||||
# Only keep relative directory
|
# Only keep relative directory
|
||||||
return result.multiReplace([("\\", $DirSep), ("//", $DirSep), (gProjectDir & $DirSep, "")])
|
return result.sanitizePath.replace(gProjectDir & "/", "")
|
||||||
|
|
||||||
proc rename*(file: string, renfile: string) =
|
proc rename*(file: string, renfile: string) =
|
||||||
if file.splitFile().ext == ".nim":
|
if file.splitFile().ext == ".nim":
|
||||||
|
|
@ -82,6 +84,12 @@ proc openRetry*(file: string, mode: FileMode = fmRead): File =
|
||||||
except IOError:
|
except IOError:
|
||||||
sleep(100)
|
sleep(100)
|
||||||
|
|
||||||
|
template writeFileFlush*(file, content: string): untyped =
|
||||||
|
let f = openRetry(file, fmWrite)
|
||||||
|
f.write(content)
|
||||||
|
f.flushFile()
|
||||||
|
f.close()
|
||||||
|
|
||||||
template withFile*(file: string, body: untyped): untyped =
|
template withFile*(file: string, body: untyped): untyped =
|
||||||
if fileExists(file):
|
if fileExists(file):
|
||||||
var f = openRetry(file)
|
var f = openRetry(file)
|
||||||
|
|
@ -93,9 +101,7 @@ template withFile*(file: string, body: untyped): untyped =
|
||||||
body
|
body
|
||||||
|
|
||||||
if content != contentOrig:
|
if content != contentOrig:
|
||||||
f = openRetry(file, fmWrite)
|
writeFileFlush(file, content)
|
||||||
write(f, content)
|
|
||||||
f.close()
|
|
||||||
else:
|
else:
|
||||||
echo "Missing file " & file
|
echo "Missing file " & file
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,20 +31,25 @@ proc append*(file: string, data: string, search="") =
|
||||||
if idx != -1:
|
if idx != -1:
|
||||||
content = content[0..<idy] & data & content[idy..<content.len()]
|
content = content[0..<idy] & data & content[idy..<content.len()]
|
||||||
|
|
||||||
proc freplace*(file: string, pattern: string, repl="") =
|
proc freplace*(file: string, pattern: string|Regex, repl="") =
|
||||||
withFile(file):
|
withFile(file):
|
||||||
if pattern in content:
|
content = content.replace(pattern, repl)
|
||||||
content = content.replace(pattern, repl)
|
|
||||||
|
|
||||||
proc freplace*(file: string, pattern: Regex, repl="") =
|
proc move*(file: string, pattern: string|Regex, move: string) =
|
||||||
|
var tomove: seq[string] = @[]
|
||||||
withFile(file):
|
withFile(file):
|
||||||
var m: RegexMatch
|
when pattern is string:
|
||||||
if content.find(pattern, m):
|
tomove.add(pattern)
|
||||||
if "$#" in repl:
|
|
||||||
content = content.replace(pattern,
|
when pattern is Regex:
|
||||||
proc (m: RegexMatch, s: string): string = repl % s[m.group(0)[0]])
|
var ms = content.findAll(pattern)
|
||||||
else:
|
for i, m in ms:
|
||||||
content = content.replace(pattern, repl)
|
tomove.add(content[m.group(0)[0]])
|
||||||
|
|
||||||
|
content = content.replace(pattern, "")
|
||||||
|
|
||||||
|
for i in tomove:
|
||||||
|
append(file, i, move)
|
||||||
|
|
||||||
proc comment*(file: string, pattern: string, numlines: string) =
|
proc comment*(file: string, pattern: string, numlines: string) =
|
||||||
let
|
let
|
||||||
|
|
@ -86,6 +91,36 @@ proc removeStatic*(filename: string) =
|
||||||
result.add(body.replace(re"(?m)^(.*\n?)", "//$1"))
|
result.add(body.replace(re"(?m)^(.*\n?)", "//$1"))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
proc removeBodies*(filename: string) =
|
||||||
|
## Replace function bodies with a semicolon and commented
|
||||||
|
## out body
|
||||||
|
withFile(filename):
|
||||||
|
content = content.replace(
|
||||||
|
re"(?m)(.*?\))(\s*\{(\s*?.*?$)*?[\n\r]\})",
|
||||||
|
proc (m: RegexMatch, s: string): string =
|
||||||
|
let funcDecl = s[m.group(0)[0]]
|
||||||
|
let body = s[m.group(1)[0]].strip()
|
||||||
|
result = ""
|
||||||
|
|
||||||
|
result.add("$#;" % [funcDecl])
|
||||||
|
result.add(body.replace(re"(?m)^(.*\n?)", "//$1"))
|
||||||
|
)
|
||||||
|
|
||||||
|
proc reAddBodies*(filename: string) =
|
||||||
|
## Uncomment out the body and remove the semicolon. Undoes
|
||||||
|
## removeBodies
|
||||||
|
withFile(filename):
|
||||||
|
content = content.replace(
|
||||||
|
re"(?m)(.*?\))(\s*\{(\s*?.*?$)*?[\n\r]\})",
|
||||||
|
proc (m: RegexMatch, s: string): string =
|
||||||
|
let funcDecl = s[m.group(0)[0]]
|
||||||
|
let body = s[m.group(1)[0]].strip()
|
||||||
|
result = ""
|
||||||
|
|
||||||
|
result.add("$# " % [funcDecl])
|
||||||
|
result.add(body.replace(re"(?m)^\/\/(.*\n?)", "$1"))
|
||||||
|
)
|
||||||
|
|
||||||
proc reAddStatic*(filename: string) =
|
proc reAddStatic*(filename: string) =
|
||||||
## Uncomment out the body and remove the semicolon. Undoes
|
## Uncomment out the body and remove the semicolon. Undoes
|
||||||
## removeStatic
|
## removeStatic
|
||||||
|
|
|
||||||
|
|
@ -4,38 +4,53 @@ import file, globals
|
||||||
|
|
||||||
proc addEnv*(str: string): string =
|
proc addEnv*(str: string): string =
|
||||||
var newStr = str
|
var newStr = str
|
||||||
for pair in envPairs():
|
|
||||||
try:
|
|
||||||
newStr = newStr % [pair.key, pair.value.string]
|
|
||||||
except ValueError:
|
|
||||||
# Ignore if there are no values to replace. We
|
|
||||||
# want to continue anyway
|
|
||||||
discard
|
|
||||||
|
|
||||||
try:
|
if "$output" in newStr or "${output}" in newStr:
|
||||||
newStr = newStr % ["output", gOutput]
|
newStr = newStr % ["output", gOutput]
|
||||||
except ValueError:
|
|
||||||
# Ignore if there are no values to replace. We
|
|
||||||
# want to continue anyway
|
|
||||||
discard
|
|
||||||
|
|
||||||
# if there are still format args, print a warning
|
for pair in envPairs():
|
||||||
if newStr.contains("$") and not newStr.contains("$replace("):
|
if pair.key.len() == 0:
|
||||||
echo "WARNING: \"", newStr, "\" still contains an uninterpolated value!"
|
continue
|
||||||
|
|
||||||
|
if ("$" & pair.key) in newStr or ("${" & pair.key & "}") in newStr:
|
||||||
|
newStr = newStr % [pair.key, pair.value.string]
|
||||||
|
|
||||||
return newStr
|
return newStr
|
||||||
|
|
||||||
proc compile*(dir="", file=""): string =
|
proc compile*(cpl, flags: string): string =
|
||||||
proc fcompile(file: string): string =
|
|
||||||
return "{.compile: \"$#\".}" % file.replace("\\", "/")
|
|
||||||
|
|
||||||
var data = ""
|
var data = ""
|
||||||
if dir != "" and dirExists(dir):
|
|
||||||
for f in walkFiles(dir / "*.c"):
|
proc fcompile(file: string): string =
|
||||||
|
let fn = file.splitFile().name
|
||||||
|
var
|
||||||
|
ufn = fn
|
||||||
|
uniq = 1
|
||||||
|
while ufn in gCompile:
|
||||||
|
ufn = fn & $uniq
|
||||||
|
uniq += 1
|
||||||
|
|
||||||
|
gCompile.add(ufn)
|
||||||
|
if fn == ufn:
|
||||||
|
return "{.compile: \"$#\".}" % file.replace("\\", "/")
|
||||||
|
else:
|
||||||
|
return "{.compile: (\"../$#\", \"$#.o\").}" % [file.replace("\\", "/"), ufn]
|
||||||
|
|
||||||
|
proc dcompile(dir: string) =
|
||||||
|
for f in walkFiles(dir):
|
||||||
data &= fcompile(f) & "\n"
|
data &= fcompile(f) & "\n"
|
||||||
|
|
||||||
if file != "" and fileExists(file):
|
if cpl.contains("*") or cpl.contains("?"):
|
||||||
data &= fcompile(file) & "\n"
|
dcompile(cpl)
|
||||||
|
else:
|
||||||
|
let fcpl = search(cpl)
|
||||||
|
if getFileInfo(fcpl).kind == pcFile:
|
||||||
|
data &= fcompile(fcpl) & "\n"
|
||||||
|
elif getFileInfo(fcpl).kind == pcDir:
|
||||||
|
if flags.contains("cpp"):
|
||||||
|
for i in @["*.C", "*.cpp", "*.c++", "*.cc", "*.cxx"]:
|
||||||
|
dcompile(fcpl / i)
|
||||||
|
else:
|
||||||
|
dcompile(fcpl / "*.c")
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
@ -87,7 +102,6 @@ proc getDefines*(file: string, inline=false): string =
|
||||||
for incl in incls:
|
for incl in incls:
|
||||||
let sincl = search(incl)
|
let sincl = search(incl)
|
||||||
if sincl != "":
|
if sincl != "":
|
||||||
echo "Inlining " & sincl
|
|
||||||
result &= getDefines(sincl)
|
result &= getDefines(sincl)
|
||||||
withFile(file):
|
withFile(file):
|
||||||
for def in content.findAll(re"(?m)^(\s*#\s*define\s+[\w\d_]+\s+[\d\-.xf]+)(?:\r|//|/*).*?$"):
|
for def in content.findAll(re"(?m)^(\s*#\s*define\s+[\w\d_]+\s+[\d\-.xf]+)(?:\r|//|/*).*?$"):
|
||||||
|
|
|
||||||
|
|
@ -7,25 +7,32 @@ const
|
||||||
defaultCppCompiler* = "g++"
|
defaultCppCompiler* = "g++"
|
||||||
|
|
||||||
var
|
var
|
||||||
gDoneRecursive*: seq[string] = @[]
|
# Config
|
||||||
gDoneInline*: seq[string] = @[]
|
|
||||||
|
|
||||||
gProjectDir* = ""
|
|
||||||
gConfig*: Config
|
gConfig*: Config
|
||||||
gFilter* = ""
|
|
||||||
gQuotes* = true
|
|
||||||
gCppCompiler* = getEnv(cppCompilerEnv, defaultCCompiler)
|
|
||||||
gCCompiler* = getEnv(cCompilerEnv, defaultCppCompiler)
|
|
||||||
gOutput* = ""
|
|
||||||
gIncludes*: seq[string] = @[]
|
|
||||||
gExcludes*: seq[string] = @[]
|
gExcludes*: seq[string] = @[]
|
||||||
|
gIncludes*: seq[string] = @[]
|
||||||
gRenames* = initTable[string, string]()
|
gRenames* = initTable[string, string]()
|
||||||
gWildcards* = newConfig()
|
gWildcards* = newConfig()
|
||||||
|
|
||||||
|
# n.global
|
||||||
|
gOutput* = "."
|
||||||
|
gQuotes* = true
|
||||||
|
gFilter* = ""
|
||||||
|
gCppCompiler* = getEnv(cppCompilerEnv, defaultCCompiler)
|
||||||
|
gCCompiler* = getEnv(cCompilerEnv, defaultCppCompiler)
|
||||||
|
|
||||||
|
# State tracking
|
||||||
|
gGitCheckout* = ""
|
||||||
|
gGitOutput* = ""
|
||||||
|
gProjectDir* = ""
|
||||||
|
gCompile*: seq[string] = @[]
|
||||||
|
gDoneInline*: seq[string] = @[]
|
||||||
|
gDoneRecursive*: seq[string] = @[]
|
||||||
|
|
||||||
type
|
type
|
||||||
c2nimConfigObj* = object
|
c2nimConfigObj* = object
|
||||||
flags*, ppflags*: string
|
flags*, ppflags*: string
|
||||||
recurse*, inline*, preprocess*, ctags*, defines*: bool
|
recurse*, inline*, preprocess*, removeBodies*, ctags*, defines*: bool
|
||||||
dynlib*, compile*, pragma*: seq[string]
|
dynlib*, compile*, pragma*: seq[string]
|
||||||
|
|
||||||
const gDoc* = """
|
const gDoc* = """
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,19 @@ proc `[]`*(table: OrderedTableRef[string, string], key: string): string =
|
||||||
## Gets table values with env vars inserted
|
## Gets table values with env vars inserted
|
||||||
tables.`[]`(table, key).addEnv
|
tables.`[]`(table, key).addEnv
|
||||||
|
|
||||||
proc getKey(ukey: string): tuple[key: string, val: bool] =
|
proc getKey(ukey: string, section = false): tuple[key: string, val: bool] =
|
||||||
var kv = ukey.replace(re"\..*", "").split("-", 1)
|
var kv = if not section: ukey.replace(re"\..*", "").split("-", 1) else: ukey.split("-", 1)
|
||||||
if kv.len() == 1:
|
if kv.len() == 1:
|
||||||
kv.add("")
|
kv.add("")
|
||||||
|
|
||||||
if kv[1] == "":
|
if kv[1] == "":
|
||||||
return (kv[0], true)
|
return (kv[0], true)
|
||||||
|
|
||||||
for ostyp in kv[1].split(","):
|
for ostyp in kv[1].split("-"):
|
||||||
if (ostyp == "win" and defined(Windows)) or
|
if (ostyp == "win" and defined(Windows)) or
|
||||||
(ostyp == "lin" and defined(Linux)) or
|
(ostyp == "lin" and defined(Linux)) or
|
||||||
((ostyp == "osx" or ostyp == "mac") and defined(MacOSX)):
|
((ostyp == "osx" or ostyp == "mac") and defined(MacOSX)) or
|
||||||
|
(ostyp == "unix" and (defined(Linux) or defined(MacOSX))):
|
||||||
return (kv[0], true)
|
return (kv[0], true)
|
||||||
|
|
||||||
return (kv[0], false)
|
return (kv[0], false)
|
||||||
|
|
@ -25,7 +26,8 @@ proc getKey(ukey: string): tuple[key: string, val: bool] =
|
||||||
proc runFile*(file: string, cfgin: OrderedTableRef = newOrderedTable[string, string]()) =
|
proc runFile*(file: string, cfgin: OrderedTableRef = newOrderedTable[string, string]()) =
|
||||||
var
|
var
|
||||||
cfg = cfgin
|
cfg = cfgin
|
||||||
sfile = search(file).sanitizePath
|
sfile = search(file)
|
||||||
|
nowildcard = false
|
||||||
|
|
||||||
if sfile in gDoneRecursive:
|
if sfile in gDoneRecursive:
|
||||||
return
|
return
|
||||||
|
|
@ -34,16 +36,24 @@ proc runFile*(file: string, cfgin: OrderedTableRef = newOrderedTable[string, str
|
||||||
echo "Processing " & sfile
|
echo "Processing " & sfile
|
||||||
gDoneRecursive.add(sfile)
|
gDoneRecursive.add(sfile)
|
||||||
|
|
||||||
for pattern in gWildcards.keys():
|
for act in cfg.keys():
|
||||||
var m: RegexMatch
|
let (action, val) = getKey(act)
|
||||||
let pat = pattern.replace(".", "\\.").replace("*", ".*").replace("?", ".?")
|
if val == true and action == "nowildcard" and cfg[act] == "true":
|
||||||
if file.find(toPattern(pat), m):
|
nowildcard = true
|
||||||
echo " Appending keys for wildcard " & pattern
|
break
|
||||||
for key in gWildcards[pattern].keys():
|
|
||||||
cfg[key & "." & pattern] = gWildcards[pattern][key]
|
if not nowildcard:
|
||||||
|
for pattern in gWildcards.keys():
|
||||||
|
var m: RegexMatch
|
||||||
|
let pat = pattern.replace(".", "\\.").replace("*", ".*").replace("?", ".?")
|
||||||
|
if file.find(toPattern(pat), m):
|
||||||
|
echo " Appending keys for wildcard " & pattern
|
||||||
|
for key in gWildcards[pattern].keys():
|
||||||
|
cfg[key & "." & pattern] = gWildcards[pattern][key]
|
||||||
|
|
||||||
var
|
var
|
||||||
srch = ""
|
srch = ""
|
||||||
|
rgx = ""
|
||||||
|
|
||||||
c2nimConfig = c2nimConfigObj(
|
c2nimConfig = c2nimConfigObj(
|
||||||
flags: "--stdcall", ppflags: "",
|
flags: "--stdcall", ppflags: "",
|
||||||
|
|
@ -57,14 +67,14 @@ proc runFile*(file: string, cfgin: OrderedTableRef = newOrderedTable[string, str
|
||||||
if action == "create":
|
if action == "create":
|
||||||
echo "Creating " & file
|
echo "Creating " & file
|
||||||
createDir(file.splitPath().head)
|
createDir(file.splitPath().head)
|
||||||
writeFile(file, cfg[act])
|
writeFileFlush(file, cfg[act])
|
||||||
if file in gExcludes:
|
if file in gExcludes:
|
||||||
gExcludes.delete(gExcludes.find(file))
|
gExcludes.delete(gExcludes.find(file))
|
||||||
sfile = search(file)
|
sfile = file
|
||||||
gDoneRecursive.add(sfile)
|
gDoneRecursive.add(sfile)
|
||||||
elif action in @["prepend", "append", "replace", "comment",
|
elif action in @["prepend", "append", "replace", "move", "comment",
|
||||||
"rename", "compile", "dynlib", "pragma",
|
"rename", "compile", "dynlib", "pragma", "pipe"] and
|
||||||
"pipe"] and sfile != "":
|
sfile != "":
|
||||||
if action == "prepend":
|
if action == "prepend":
|
||||||
if srch != "":
|
if srch != "":
|
||||||
prepend(sfile, cfg[act], cfg[srch])
|
prepend(sfile, cfg[act], cfg[srch])
|
||||||
|
|
@ -78,6 +88,13 @@ proc runFile*(file: string, cfgin: OrderedTableRef = newOrderedTable[string, str
|
||||||
elif action == "replace":
|
elif action == "replace":
|
||||||
if srch != "":
|
if srch != "":
|
||||||
freplace(sfile, cfg[srch], cfg[act])
|
freplace(sfile, cfg[srch], cfg[act])
|
||||||
|
elif rgx != "":
|
||||||
|
freplace(sfile, toPattern(cfg[rgx]), cfg[act])
|
||||||
|
elif action == "move":
|
||||||
|
if srch != "":
|
||||||
|
move(sfile, cfg[srch], cfg[act])
|
||||||
|
elif rgx != "":
|
||||||
|
move(sfile, toPattern(cfg[rgx]), cfg[act])
|
||||||
elif action == "comment":
|
elif action == "comment":
|
||||||
if srch != "":
|
if srch != "":
|
||||||
comment(sfile, cfg[srch], cfg[act])
|
comment(sfile, cfg[srch], cfg[act])
|
||||||
|
|
@ -92,8 +109,11 @@ proc runFile*(file: string, cfgin: OrderedTableRef = newOrderedTable[string, str
|
||||||
elif action == "pipe":
|
elif action == "pipe":
|
||||||
pipe(sfile, cfg[act])
|
pipe(sfile, cfg[act])
|
||||||
srch = ""
|
srch = ""
|
||||||
|
rgx = ""
|
||||||
elif action == "search":
|
elif action == "search":
|
||||||
srch = act
|
srch = act
|
||||||
|
elif action == "regex":
|
||||||
|
rgx = act
|
||||||
|
|
||||||
if file.splitFile().ext != ".nim":
|
if file.splitFile().ext != ".nim":
|
||||||
var
|
var
|
||||||
|
|
@ -110,6 +130,8 @@ proc runFile*(file: string, cfgin: OrderedTableRef = newOrderedTable[string, str
|
||||||
c2nimConfig.inline = true
|
c2nimConfig.inline = true
|
||||||
elif action == "preprocess":
|
elif action == "preprocess":
|
||||||
c2nimConfig.preprocess = true
|
c2nimConfig.preprocess = true
|
||||||
|
elif action == "removeBodies":
|
||||||
|
c2nimConfig.removeBodies = true
|
||||||
elif action == "ctags":
|
elif action == "ctags":
|
||||||
c2nimConfig.ctags = true
|
c2nimConfig.ctags = true
|
||||||
elif action == "defines":
|
elif action == "defines":
|
||||||
|
|
@ -127,141 +149,263 @@ proc runFile*(file: string, cfgin: OrderedTableRef = newOrderedTable[string, str
|
||||||
echo "Cannot use recurse and inline simultaneously"
|
echo "Cannot use recurse and inline simultaneously"
|
||||||
quit(1)
|
quit(1)
|
||||||
|
|
||||||
if not noprocess:
|
removeStatic(sfile)
|
||||||
let outfile = getNimout(sfile)
|
fixFuncProtos(sfile)
|
||||||
c2nim(file, outfile, c2nimConfig)
|
|
||||||
|
|
||||||
if c2nimConfig.recurse:
|
let outfile = getNimout(sfile)
|
||||||
var
|
var incout = ""
|
||||||
cfg = newOrderedTable[string, string]()
|
if c2nimConfig.recurse or c2nimConfig.inline:
|
||||||
incls = getIncls(sfile)
|
var
|
||||||
incout = ""
|
cfg = newOrderedTable[string, string]()
|
||||||
|
incls = getIncls(sfile)
|
||||||
|
|
||||||
for name, value in c2nimConfig.fieldPairs:
|
for name, value in c2nimConfig.fieldPairs:
|
||||||
when value is string:
|
when value is string:
|
||||||
cfg[name] = value
|
cfg[name] = value
|
||||||
when value is bool:
|
when value is bool:
|
||||||
cfg[name] = $value
|
cfg[name] = $value
|
||||||
|
|
||||||
for i in c2nimConfig.dynlib:
|
for i in c2nimConfig.dynlib:
|
||||||
cfg["dynlib." & i] = i
|
cfg["dynlib." & i] = i
|
||||||
|
|
||||||
for inc in incls:
|
if c2nimConfig.inline:
|
||||||
runFile(inc, cfg)
|
cfg["noprocess"] = "true"
|
||||||
|
|
||||||
|
for inc in incls:
|
||||||
|
runFile(inc, cfg)
|
||||||
|
if c2nimConfig.recurse:
|
||||||
incout &= "import $#\n" % inc.search().getNimout()[0 .. ^5]
|
incout &= "import $#\n" % inc.search().getNimout()[0 .. ^5]
|
||||||
|
|
||||||
if incout.len() != 0:
|
if not noprocess:
|
||||||
prepend(outfile, incout)
|
c2nim(file, outfile, c2nimConfig)
|
||||||
|
|
||||||
|
if c2nimConfig.recurse and incout.len() != 0:
|
||||||
|
prepend(outfile, incout)
|
||||||
|
|
||||||
if reset:
|
if reset:
|
||||||
gitCheckout(sfile)
|
gitCheckout(sfile)
|
||||||
|
|
||||||
|
proc setOutputDir(dir: string) =
|
||||||
|
gOutput = dir.sanitizePath
|
||||||
|
if dirExists(gOutput):
|
||||||
|
if "-f" in commandLineParams():
|
||||||
|
try:
|
||||||
|
removeDir(gOutput)
|
||||||
|
except OSError:
|
||||||
|
echo "Directory in use: " & gOutput
|
||||||
|
quit(1)
|
||||||
|
else:
|
||||||
|
for f in walkFiles(gOutput/"*.nim"):
|
||||||
|
try:
|
||||||
|
removeFile(f)
|
||||||
|
except OSError:
|
||||||
|
echo "Unable to delete: " & f
|
||||||
|
quit(1)
|
||||||
|
createDir(gOutput)
|
||||||
|
|
||||||
|
gGitOutput = gOutput
|
||||||
|
|
||||||
proc runCfg*(cfg: string) =
|
proc runCfg*(cfg: string) =
|
||||||
if not fileExists(cfg):
|
if not fileExists(cfg):
|
||||||
echo "Config doesn't exist: " & cfg
|
echo "Config doesn't exist: " & cfg
|
||||||
quit(1)
|
quit(1)
|
||||||
|
|
||||||
gProjectDir = parentDir(cfg.expandFilename())
|
gProjectDir = parentDir(cfg.expandFilename()).sanitizePath
|
||||||
|
|
||||||
gConfig = loadConfig(cfg)
|
gConfig = loadConfig(cfg)
|
||||||
|
gCppCompiler = getEnv(cppCompilerEnv, defaultCppCompiler).quoteShell
|
||||||
|
gCCompiler = getEnv(cCompilerEnv, defaultCCompiler).quoteShell
|
||||||
|
gGitOutput = gOutput
|
||||||
|
|
||||||
if gConfig.hasKey("n.global"):
|
for section in gConfig.keys():
|
||||||
if gConfig["n.global"].hasKey("output"):
|
let (sname, sval) = getKey(section, true)
|
||||||
gOutput = gConfig["n.global"]["output"]
|
if not sval:
|
||||||
if dirExists(gOutput):
|
|
||||||
if "-f" in commandLineParams():
|
|
||||||
try:
|
|
||||||
removeDir(gOutput)
|
|
||||||
except OSError:
|
|
||||||
echo "Directory in use: " & gOutput
|
|
||||||
quit(1)
|
|
||||||
else:
|
|
||||||
for f in walkFiles(gOutput/"*.nim"):
|
|
||||||
try:
|
|
||||||
removeFile(f)
|
|
||||||
except OSError:
|
|
||||||
echo "Unable to delete: " & f
|
|
||||||
quit(1)
|
|
||||||
createDir(gOutput)
|
|
||||||
|
|
||||||
if gConfig["n.global"].hasKey("cpp_compiler"):
|
|
||||||
gCppCompiler = gConfig["n.global"]["cpp_compiler"]
|
|
||||||
else:
|
|
||||||
# Reset on a per project basis
|
|
||||||
gCppCompiler = getEnv(cppCompilerEnv, defaultCppCompiler)
|
|
||||||
|
|
||||||
if gConfig["n.global"].hasKey("c_compiler"):
|
|
||||||
gCCompiler = gConfig["n.global"]["c_compiler"]
|
|
||||||
else:
|
|
||||||
# Reset on a per project basis
|
|
||||||
gCCompiler = getEnv(cCompilerEnv, defaultCCompiler)
|
|
||||||
|
|
||||||
gCppCompiler = gCppCompiler.quoteShell
|
|
||||||
gCCompiler = gCCompiler.quoteShell
|
|
||||||
|
|
||||||
if gConfig["n.global"].hasKey("filter"):
|
|
||||||
gFilter = gConfig["n.global"]["filter"]
|
|
||||||
if gConfig["n.global"].hasKey("quotes"):
|
|
||||||
if gConfig["n.global"]["quotes"] == "false":
|
|
||||||
gQuotes = false
|
|
||||||
|
|
||||||
if gConfig.hasKey("n.include"):
|
|
||||||
for inc in gConfig["n.include"].keys():
|
|
||||||
gIncludes.add(inc.addEnv())
|
|
||||||
|
|
||||||
if gConfig.hasKey("n.exclude"):
|
|
||||||
for excl in gConfig["n.exclude"].keys():
|
|
||||||
gExcludes.add(excl.addEnv())
|
|
||||||
|
|
||||||
if gConfig.hasKey("n.prepare"):
|
|
||||||
for prep in gConfig["n.prepare"].keys():
|
|
||||||
let (key, val) = getKey(prep)
|
|
||||||
if val == true:
|
|
||||||
let prepVal = gConfig["n.prepare"][prep]
|
|
||||||
if key == "download":
|
|
||||||
downloadUrl(prepVal)
|
|
||||||
elif key == "extract":
|
|
||||||
extractZip(prepVal)
|
|
||||||
elif key == "git":
|
|
||||||
gitRemotePull(prepVal)
|
|
||||||
elif key == "gitremote":
|
|
||||||
gitRemotePull(prepVal, false)
|
|
||||||
elif key == "gitsparse":
|
|
||||||
gitSparseCheckout(prepVal)
|
|
||||||
elif key == "execute":
|
|
||||||
discard execProc(prepVal)
|
|
||||||
elif key == "copy":
|
|
||||||
doCopy(prepVal)
|
|
||||||
|
|
||||||
if gConfig.hasKey("n.wildcard"):
|
|
||||||
var wildcard = ""
|
|
||||||
for wild in gConfig["n.wildcard"].keys():
|
|
||||||
let (key, val) = getKey(wild)
|
|
||||||
if val == true:
|
|
||||||
if key == "wildcard":
|
|
||||||
wildcard = gConfig["n.wildcard"][wild]
|
|
||||||
else:
|
|
||||||
gWildcards.setSectionKey(wildcard, wild,
|
|
||||||
gConfig["n.wildcard"][wild])
|
|
||||||
|
|
||||||
for file in gConfig.keys():
|
|
||||||
if file in @["n.global", "n.include", "n.exclude",
|
|
||||||
"n.prepare", "n.wildcard", "n.post"]:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if file == "n.sourcefile":
|
case sname:
|
||||||
for pattern in gConfig["n.sourcefile"].keys():
|
of "n.global":
|
||||||
for file in walkFiles(pattern.addEnv):
|
for glob in gConfig[section].keys():
|
||||||
runFile(file)
|
let (key, val) = getKey(glob)
|
||||||
else:
|
if val == true:
|
||||||
runFile(file, gConfig[file])
|
let globVal = gConfig[section][glob]
|
||||||
|
case key:
|
||||||
|
of "output":
|
||||||
|
setOutputDir(globVal)
|
||||||
|
of "cpp_compiler":
|
||||||
|
gCppCompiler = globVal.quoteShell
|
||||||
|
of "c_compiler":
|
||||||
|
gCCompiler = globVal.quoteShell
|
||||||
|
of "filter":
|
||||||
|
gFilter = globVal
|
||||||
|
of "quotes":
|
||||||
|
if globVal == "false":
|
||||||
|
gQuotes = false
|
||||||
|
|
||||||
if gConfig.hasKey("n.post"):
|
of "n.include":
|
||||||
for post in gConfig["n.post"].keys():
|
for inc in gConfig[section].keys():
|
||||||
let (key, val) = getKey(post)
|
gIncludes.add(inc.addEnv().sanitizePath)
|
||||||
if val == true:
|
|
||||||
let postVal = gConfig["n.post"][post]
|
of "n.exclude":
|
||||||
if key == "reset":
|
for excl in gConfig[section].keys():
|
||||||
gitReset()
|
gExcludes.add(excl.addEnv().sanitizePath)
|
||||||
elif key == "execute":
|
|
||||||
discard execProc(postVal)
|
of "n.prepare":
|
||||||
|
for prep in gConfig[section].keys():
|
||||||
|
let (key, val) = getKey(prep)
|
||||||
|
if val == true:
|
||||||
|
let prepVal = gConfig[section][prep]
|
||||||
|
case key:
|
||||||
|
of "download":
|
||||||
|
downloadUrl(prepVal)
|
||||||
|
of "extract":
|
||||||
|
extractZip(prepVal)
|
||||||
|
of "gitcheckout":
|
||||||
|
gGitCheckout = prepVal
|
||||||
|
of "gitoutput":
|
||||||
|
gGitOutput = gOutput/prepVal
|
||||||
|
createDir(gGitOutput)
|
||||||
|
of "git":
|
||||||
|
gitRemotePull(prepVal)
|
||||||
|
of "gitremote":
|
||||||
|
gitRemotePull(prepVal, false)
|
||||||
|
of "gitsparse":
|
||||||
|
gitSparseCheckout(prepVal)
|
||||||
|
of "execute":
|
||||||
|
discard execAction(prepVal)
|
||||||
|
of "copy":
|
||||||
|
doCopy(prepVal)
|
||||||
|
|
||||||
|
of "n.wildcard":
|
||||||
|
var wildcard = ""
|
||||||
|
for wild in gConfig[section].keys():
|
||||||
|
let (key, val) = getKey(wild)
|
||||||
|
if val == true:
|
||||||
|
if key == "wildcard":
|
||||||
|
wildcard = gConfig[section][wild]
|
||||||
|
else:
|
||||||
|
gWildcards.setSectionKey(wildcard, wild,
|
||||||
|
gConfig[section][wild])
|
||||||
|
|
||||||
|
of "n.sourcefile":
|
||||||
|
for pattern in gConfig[section].keys():
|
||||||
|
for file in walkFiles(pattern.addEnv):
|
||||||
|
runFile(file)
|
||||||
|
|
||||||
|
of "n.post":
|
||||||
|
for post in gConfig[section].keys():
|
||||||
|
let (key, val) = getKey(post)
|
||||||
|
if val == true:
|
||||||
|
let postVal = gConfig[section][post]
|
||||||
|
case key:
|
||||||
|
of "gitoutput":
|
||||||
|
gGitOutput = gOutput/postVal
|
||||||
|
of "reset":
|
||||||
|
gitReset()
|
||||||
|
of "execute":
|
||||||
|
discard execAction(postVal)
|
||||||
|
|
||||||
|
else:
|
||||||
|
runFile(section, gConfig[section])
|
||||||
|
|
||||||
|
let gHelp = """
|
||||||
|
Nimgen is a helper for c2nim to simplify and automate the wrapping of C libraries
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
nimgen [options] file.cfg|file.h ...
|
||||||
|
|
||||||
|
Params:
|
||||||
|
-C<compile> add compile entry *
|
||||||
|
-E<exclude> add n.exclude entry *
|
||||||
|
-F<flags> set c2nim flags *
|
||||||
|
-I<include> add n.include dir *
|
||||||
|
-O<outdir> set output directory
|
||||||
|
-P<ppflags> 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> append string *
|
||||||
|
-e<prepend> prepend string *
|
||||||
|
-l<replace> replace string *
|
||||||
|
-o#lines comment X lines *
|
||||||
|
-s<search> search string *
|
||||||
|
-x<regex> 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)
|
||||||
|
|
|
||||||
|
|
@ -1,52 +1,78 @@
|
||||||
import distros, ospaths, strutils
|
import distros, ospaths, strutils
|
||||||
|
|
||||||
var
|
var
|
||||||
full = true
|
pygonly = false
|
||||||
comps = @["libsvm", "nim7z", "nimarchive", "nimbass", "nimbigwig", "nimclipboard",
|
comps = @["nim7z", #"nimarchive",
|
||||||
"nimfuzz", "nimpcre", "nimrax", "nimssl", "nimssh2"]
|
"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):
|
if detectOs(Windows):
|
||||||
comps.add("nimkerberos")
|
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:
|
if paramCount() > 2:
|
||||||
for i in 3 .. paramCount():
|
for i in 3 .. paramCount():
|
||||||
if paramStr(i) == "--full":
|
if paramStr(i) == "--pygonly":
|
||||||
full = true
|
pygonly = true
|
||||||
elif paramStr(i).len() > 10 and "--comps=" in paramStr(i)[0 ..< 8]:
|
elif paramStr(i).len() > 10 and "--comps=" in paramStr(i)[0 ..< 8]:
|
||||||
comps = paramStr(i)[8 .. ^1].split(",")
|
comps = paramStr(i)[8 .. ^1].split(",")
|
||||||
|
|
||||||
for comp in comps:
|
for comp in comps:
|
||||||
if not dirExists(".."/comp):
|
if not pygonly:
|
||||||
withDir(".."):
|
if not dirExists(".."/comp):
|
||||||
exec "git clone --depth=1 https://github.com/genotrance/" & comp
|
withDir(".."):
|
||||||
|
exec "git clone --depth=1 https://github.com/genotrance/" & comp
|
||||||
|
|
||||||
exec "nimble uninstall -y " & comp, "", ""
|
exec "nimble uninstall -y " & comp, "", ""
|
||||||
withDir(".."/comp):
|
withDir(".."/comp):
|
||||||
exec "git pull"
|
exec "git pull"
|
||||||
|
|
||||||
if full:
|
|
||||||
rmDir(comp)
|
rmDir(comp)
|
||||||
|
|
||||||
exec "nimble install -y"
|
exec "nimble install -y"
|
||||||
exec "nimble test"
|
exec "nimble test"
|
||||||
|
|
||||||
exec "nimble install -y"
|
exec "nimble install -y"
|
||||||
exec "nimble test"
|
exec "nimble test"
|
||||||
|
|
||||||
if dirExists("web"/comp):
|
when defined(windows):
|
||||||
rmDir("web"/comp)
|
if not pygonly:
|
||||||
|
if dirExists("web"/comp):
|
||||||
|
rmDir("web"/comp)
|
||||||
|
|
||||||
mkDir("web"/comp)
|
mkDir("web"/comp)
|
||||||
for file in listFiles(".."/comp/comp) & listFiles(".."/comp):
|
for file in listFiles(".."/comp/comp) & listFiles(".."/comp):
|
||||||
if file.splitFile().ext == ".nim":
|
if file.splitFile().ext == ".nim":
|
||||||
cpFile(file, "web"/comp/extractFilename(file))
|
cpFile(file, "web"/comp/extractFilename(file))
|
||||||
|
|
||||||
cpFile("web"/"nimdoc.cfg", "web"/comp/"nimdoc.cfg")
|
cpFile("web"/"nimdoc.cfg", "web"/comp/"nimdoc.cfg")
|
||||||
withDir("web"/comp):
|
withDir("web"/comp):
|
||||||
for file in listFiles("."):
|
for file in listFiles("."):
|
||||||
if file.splitFile().ext == ".nim":
|
if file.splitFile().ext == ".nim":
|
||||||
exec "nim doc --git.url:. --index:on -o:" & file.changeFileExt("html") & " " & file
|
if not pygonly:
|
||||||
exec "pygmentize -f html -O full,linenos=1,anchorlinenos=True,lineanchors=L,style=vs -o " & file & ".html " & file
|
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 ."
|
if not pygonly:
|
||||||
rmFile("web"/comp/"nimdoc.cfg")
|
exec "nim buildIndex -o:index.html ."
|
||||||
|
rmFile("web"/comp/"nimdoc.cfg")
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import os, osproc, strutils
|
import os, osproc, strutils
|
||||||
|
|
||||||
proc main() =
|
proc main() =
|
||||||
|
var failures = 0
|
||||||
for file in walkFiles(currentSourcePath().splitPath().head / "unittests/*.nim"):
|
for file in walkFiles(currentSourcePath().splitPath().head / "unittests/*.nim"):
|
||||||
let (path, fname, ext) = file.splitFile()
|
let (path, fname, ext) = file.splitFile()
|
||||||
if fname.startswith("test"):
|
if fname.startswith("test"):
|
||||||
discard execCmd "nim c -r " & file
|
failures += execCmd "nim c -r " & file
|
||||||
|
quit(failures)
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -97,8 +97,6 @@ suite "test file ops":
|
||||||
dataDir.createDir()
|
dataDir.createDir()
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
if testfilename.existsFile():
|
|
||||||
removeFile(testfilename)
|
|
||||||
writeFile(testfilename, testFileContent)
|
writeFile(testfilename, testFileContent)
|
||||||
|
|
||||||
################### Prepend #######################
|
################### Prepend #######################
|
||||||
|
|
@ -120,7 +118,7 @@ suite "test file ops":
|
||||||
|
|
||||||
test "pipe command into file":
|
test "pipe command into file":
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
pipe(testfilename, "(ECHO foo)>>$file")
|
pipe(testfilename, "ECHO foo")
|
||||||
testfilename.checkFile("foo")
|
testfilename.checkFile("foo")
|
||||||
else:
|
else:
|
||||||
pipe(testfilename, "cat $file | grep 'this is text'")
|
pipe(testfilename, "cat $file | grep 'this is text'")
|
||||||
|
|
|
||||||
1
web/CNAME
Normal file
1
web/CNAME
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
nimgen.genotrance.com
|
||||||
1401
web/nimdoc.cfg
Normal file
1401
web/nimdoc.cfg
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue