├── .dir-locals.el ├── .gitattributes ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.org └── config.nims /.dir-locals.el: -------------------------------------------------------------------------------- 1 | (nil 2 | . ((nil . ((indent-tabs-mode . nil) 3 | (fill-column . 70))) 4 | (org-mode . ((mode . auto-fill))))) 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # -*- conf -*- 2 | # https://github.com/github/linguist#using-gitattributes 3 | # Syntax highlight the .nims files using Nim syntax highlighter. 4 | *.nims linguist-language=Nim 5 | # https://github.com/github/linguist#vendored-code 6 | # Do not count the "vendored" files in the repo's language statistics. 7 | .dir-locals.el linguist-vendored 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.o 3 | *.h 4 | *.tar.gz 5 | *.tar 6 | *.gz 7 | *.tar.bz2 8 | *.bz2 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | sudo: required 3 | 4 | cache: 5 | directories: 6 | - nim 7 | - upx 8 | - pcre 9 | - openssl 10 | - libressl 11 | 12 | env: 13 | global: 14 | - NIMFILE="hello.nim" 15 | - BINFILE="./hello" 16 | # 17 | - NIMREPO="https://github.com/nim-lang/Nim" 18 | - NIMVER="$(git ls-remote ${NIMREPO} devel | cut -f 1)" 19 | - NIMDIR="${TRAVIS_BUILD_DIR}/nim/${NIMVER}" 20 | - UPXVER="3.95" # Change this value when upgrading upx 21 | - PCREVER="8.42" # Change this value when upgrading pcre 22 | - LIBRESSLVER="2.8.1" # Change this value when upgrading libressl 23 | - OPENSSLVER="1.1.1" # Change this value when upgrading openssl 24 | 25 | addons: 26 | apt: 27 | packages: 28 | # For building MUSL static builds on Linux. 29 | - musl-tools 30 | 31 | install: 32 | - set -e # Quit on first error 33 | - echo "NIMDIR = ${NIMDIR}" 34 | - | 35 | if [[ ! -f "${NIMDIR}/bin/nim" ]] 36 | then 37 | rm -rf nim 38 | mkdir -p nim 39 | git clone --single-branch --branch devel --depth=1 "${NIMREPO}" "${NIMDIR}" 40 | cd "${NIMDIR}" || exit 41 | # Don't build 'koch tools'; remove that line from build_all.sh. 42 | sed -i '/koch tools/d' build_all.sh 43 | sh build_all.sh # https://github.com/nim-lang/Nim/issues/17907#issuecomment-831654235 44 | fi 45 | - export PATH="${NIMDIR}/bin:${PATH}" 46 | - nim -v 47 | 48 | - | 49 | if [[ ! -f "${TRAVIS_BUILD_DIR}/upx/${UPXVER}/upx" ]] 50 | then 51 | echo "Installing upx .." 52 | # Ensure that you are in repo/build root now. 53 | cd "${TRAVIS_BUILD_DIR}" 54 | curl -OL "https://github.com/upx/upx/releases/download/v${UPXVER}/upx-${UPXVER}-amd64_linux.tar.xz" 55 | tar xvf "upx-${UPXVER}-amd64_linux.tar.xz" 56 | mkdir -p upx 57 | mv "upx-${UPXVER}-amd64_linux" "upx/${UPXVER}" 58 | fi 59 | - export PATH="${TRAVIS_BUILD_DIR}/upx/${UPXVER}/:${PATH}" 60 | - upx --version | grep -E '^upx' 61 | 62 | script: 63 | # Ensure that you are in repo/build root now. 64 | - cd "${TRAVIS_BUILD_DIR}" 65 | - echo 'echo "Hello, World!"' > "${NIMFILE}" 66 | # Fri Aug 30 09:18:18 EDT 2019 - kmodi 67 | # Remove the lint check for config.nims; this broke in this range of commits on Nim devel: 68 | # https://github.com/nim-lang/Nim/compare/a25d43ca6b5b9a918a7e...170cb4f4cbe734d6fa30 69 | # As per Araq (https://gitter.im/nim-lang/Nim?at=5d69220e7b263a4c9c7f6042), this was expected. 70 | # # Lint check 71 | # - nim check --styleCheck:hint config.nims 72 | # strip, upx 73 | - nim c "${NIMFILE}" 74 | - nim strip "${BINFILE}" 75 | - nim upx "${BINFILE}" 76 | - "${BINFILE}" 77 | # checksums 78 | - nim checksums "${BINFILE}" 79 | # musl 80 | - nim musl "${NIMFILE}" 81 | - file "${BINFILE}" 82 | - "${BINFILE}" 83 | # musl -d:pcre 84 | - nim musl -d:pcre "${NIMFILE}" 85 | - file "${BINFILE}" 86 | - "${BINFILE}" 87 | # musl -d:libressl 88 | - nim musl -d:libressl "${NIMFILE}" 89 | - file "${BINFILE}" 90 | - "${BINFILE}" 91 | # musl -d:openssl 92 | - nim musl -d:openssl "${NIMFILE}" 93 | - file "${BINFILE}" 94 | - "${BINFILE}" 95 | 96 | notifications: 97 | email: 98 | on_success: never # default: change 99 | on_failure: always # default: always 100 | 101 | # References: 102 | # choosenim: https://github.com/mratsim/Arraymancer/blob/master/.travis.yml 103 | # musl: https://github.com/BurntSushi/ripgrep/blob/master/.travis.yml 104 | # nim build caching: https://github.com/status-im/nimbus/blob/master/.travis.yml 105 | # https://docs.travis-ci.com/user/deployment/releases/ 106 | # https://github.com/nim-lang/Nim/wiki/TravisCI 107 | # https://docs.travis-ci.com/user/environment-variables/#default-environment-variables 108 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Kaushal Modi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+title: Global Nim config 2 | #+author: Kaushal Modi 3 | 4 | This repo contains my global Nim configuration ~config.nims~ (which I 5 | place in the *$XDG_CONFIG_HOME/nim/* directory.) 6 | 7 | * Requirement 8 | Needs Nim built from its ~devel~ branch (<2018-10-16 Tue>). 9 | * List available tasks 10 | #+begin_example 11 | nim help 12 | #+end_example 13 | Note that there's no ~--~ before ~help~. 14 | 15 | That will print: 16 | #+begin_example 17 | installPcre Install PCRE using musl-gcc 18 | installLibreSsl Install LIBRESSL using musl-gcc 19 | installOpenSsl Install OPENSSL using musl-gcc 20 | strip Optimize the binary size using 'strip' utility 21 | upx Optimize the binary size using 'upx' utility 22 | checksums Generate checksums of the binary using 'sha1sum' and 'md5sum' 23 | sign Sign the binary using 'gpg' (armored, ascii) 24 | encrypt Encrypt the binary using 'gpg' (compressed, symmetric, ascii) 25 | musl Build an optimized static binary using musl 26 | glibc25 Build C, dynamically linked to GLibC 2.5 (x86_64) 27 | js2asm Build JS, print Assembly from that JS (performance debug) 28 | c2asm Build C, print Assembly from that C (performance debug) 29 | fmt Run nimpretty on all git-managed .nim files in the current repo 30 | rmfiles Recursively remove all files with the specific extension(s) from the current directory 31 | test Run tests via 'nim doc' (runnableExamples) and tests in tests/ dir 32 | docs Deploy doc html + search index to public/ directory 33 | runc Run equivalent of 'nim c -r ..' 34 | runcpp Run equivalent of 'nim cpp -r ..' 35 | #+end_example 36 | * How to use this 37 | ** Use in your local projects 38 | 1. Create *$XDG_CONFIG_HOME/nim/* directory if it doesn't already 39 | exist (or *~/.config/nim/* if you don't have ~XDG_CONFIG_HOME~ 40 | environment variable set). 41 | 2. Download the [[https://github.com/kaushalmodi/nim_config/blob/master/config.nims][config.nims]] and put it in that directory. 42 | ** Install using Curl: 43 | #+begin_src bash 44 | mkdir --verbose $XDG_CONFIG_HOME/nim/ 45 | curl -o $XDG_CONFIG_HOME/nim/config.nims https://raw.githubusercontent.com/kaushalmodi/nim_config/master/config.nims 46 | #+end_src 47 | ** Uninstall: 48 | #+begin_src bash 49 | rm --verbose $XDG_CONFIG_HOME/nim/config.nims 50 | #+end_src 51 | ** Use in Travis CI 52 | I use this same file during Nim project builds on Travis CI by 53 | including the below in the ~script:~ phase: 54 | #+begin_example 55 | git clone https://github.com/kaushalmodi/nim_config && cp nim_config/config.nims . 56 | #+end_example 57 | 58 | - Note :: This will overwrite your project-specific ~config.nims~ (if 59 | any) with the version in this repo. That overwrite happens 60 | only in that Travis workspace, but still understand what the 61 | above command is doing before using it. *** Using the ~test~ 62 | and ~docs~ tasks 63 | *** Example use of ~test~ and ~docs~ tasks 64 | #+begin_src yaml 65 | script: 66 | - nim -v 67 | - git clone https://github.com/kaushalmodi/nim_config && cp nim_config/config.nims . # Get my global config.nims 68 | - nim test # The 'test' task is defined in the above retrieved config.nims 69 | - nim docs # The 'docs' task is defined in the above retrieved config.nims 70 | #+end_src 71 | [[https://github.com/kaushalmodi/elnim/blob/8f795c691f80e9d6a4ffe1bafc7892830d4b78ba/.travis.yml#L43-L47][Source]] 72 | *** Example use of ~musl~ task 73 | #+begin_src yaml 74 | script: 75 | - cd "${TRAVIS_BUILD_DIR}" # Ensure that you are in repo/build root now. 76 | - nimble install --depsOnly --accept 77 | - git clone https://github.com/kaushalmodi/nim_config && cp nim_config/config.nims . # Get my global config.nims 78 | - nim musl "${NIMFILE}" # The ${NIMFILE} var is defined further up in that .travis.yml 79 | #+end_src 80 | [[https://github.com/OrgTangle/ntangle/blob/92fcd43569f48b512799ebf563ac4bbef6813795/.travis.yml#L59-L66][Source]] 81 | * References 82 | - [[https://nim-lang.github.io/Nim/nimscript.html][NimScript API]] 83 | - [[https://nim-lang.github.io/Nim/nims.html][*.nims* config]] 84 | - [[https://github.com/kaushalmodi/hello_musl][*musl* task]] 85 | -------------------------------------------------------------------------------- /config.nims: -------------------------------------------------------------------------------- 1 | from macros import error 2 | from strutils import `%`, endsWith, strip, replace 3 | from sequtils import filterIt, concat 4 | 5 | const 6 | nimVersion = (major: NimMajor, minor: NimMinor, patch: NimPatch) 7 | 8 | when nimVersion <= (0, 19, 9): 9 | from ospaths import `/`, splitPath, splitFile 10 | when not defined(projectDir): 11 | let projectDir = getCurrentDir 12 | echo "\nprojectDir() is not defined, fallback to getCurrentDir(), you must run it from the project directory (needs Nim devel).\n" 13 | else: 14 | when nimVersion < (1, 2, 0): 15 | from os import `/`, splitPath, splitFile 16 | import oswalkdir # This was deprecated in Nim 1.2.0; just use "import os" instead 17 | else: 18 | when nimVersion < (1, 3, 0): 19 | from os import `/`, splitPath, splitFile, walkDirRec, pcFile, pcDir 20 | else: 21 | # nim devel 22 | import std/[os] 23 | 24 | when nimVersion >= (1, 7, 3): 25 | import std/[assertions] # for doAssert 26 | 27 | # Switches 28 | hint("Processing", false) # Do not print the "Hint: .. [Processing]" messages when compiling 29 | 30 | # Use Dragonbox by default - https://github.com/nim-lang/Nim/commit/25efb5386293540b0542833625d3fb6e22f3cfbc 31 | switch("define", "nimFpRoundtrips") 32 | 33 | when nimVersion >= (0, 20, 0): 34 | when defined(strictMode): 35 | switch("styleCheck", "error") 36 | else: 37 | switch("styleCheck", "hint") 38 | 39 | ## Constants 40 | const 41 | doOptimize = true 42 | stripSwitches = @["--strip-all", "--remove-section=.comment", "--remove-section=.note.gnu.gold-version", "--remove-section=.note", "--remove-section=.note.gnu.build-id", "--remove-section=.note.ABI-tag"] 43 | # upxSwitches = @["--best"] # fast 44 | upxSwitches = @["--ultra-brute"] # slower 45 | checksumsSwitches = @["--tag"] 46 | gpgSignSwitches = @["--clear-sign", "--armor", "--detach-sign", "--digest-algo sha512"] 47 | gpgEncryptSwitches = @["--armor", "--symmetric", "--s2k-digest-algo sha512", "--cipher-algo AES256", "-z 9"] # 9=Max, 0=Disabled 48 | 49 | proc getGitRootMaybe(): string = 50 | ## Try to get the path to the current git root directory. 51 | ## Return ``projectDir()`` if a ``.git`` directory is not found. 52 | const 53 | maxAttempts = 10 # arbitrarily picked 54 | var 55 | path = projectDir() # projectDir() needs nim 0.20.0 (or nim devel as of Tue Oct 16 08:41:09 EDT 2018) 56 | attempt = 0 57 | while (attempt < maxAttempts) and (not dirExists(path / ".git")): 58 | path = path / "../" 59 | attempt += 1 60 | if dirExists(path / ".git"): 61 | result = path 62 | else: 63 | result = projectDir() 64 | 65 | ## Lets 66 | let 67 | root = getGitRootMaybe() 68 | (_, pkgName) = root.splitPath() 69 | srcFile = root / "src" / (pkgName & ".nim") 70 | # pcre 71 | pcreVersion = getEnv("PCREVER", "8.42") 72 | pcreSourceDir = "pcre-" & pcreVersion 73 | pcreArchiveFile = pcreSourceDir & ".tar.bz2" 74 | pcreDownloadLink = "https://downloads.sourceforge.net/pcre/" & pcreArchiveFile 75 | pcreInstallDir = (root / "pcre/") & pcreVersion 76 | # http://www.linuxfromscratch.org/blfs/view/8.1/general/pcre.html 77 | pcreConfigureCmd = ["./configure", "--prefix=" & pcreInstallDir, "--enable-pcre16", "--enable-pcre32", "--disable-shared"] 78 | pcreLibDir = pcreInstallDir / "lib" 79 | pcreLibFile = pcreLibDir / "libpcre.a" 80 | # libressl 81 | libreSslVersion = getEnv("LIBRESSLVER", "2.8.1") 82 | libreSslSourceDir = "libressl-" & libreSslVersion 83 | libreSslArchiveFile = libreSslSourceDir & ".tar.gz" 84 | libreSslDownloadLink = "https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/" & libreSslArchiveFile 85 | libreSslInstallDir = (root / "libressl/") & libreSslVersion 86 | libreSslConfigureCmd = ["./configure", "--disable-shared", "--prefix=" & libreSslInstallDir] 87 | libreSslLibDir = libreSslInstallDir / "lib" 88 | libreSslLibFile = libreSslLibDir / "libssl.a" 89 | libreCryptoLibFile = libreSslLibDir / "libcrypto.a" 90 | libreSslIncludeDir = libreSslInstallDir / "include/openssl" 91 | # openssl 92 | openSslSeedConfigOsCompiler = "linux-x86_64" 93 | openSslVersion = getEnv("OPENSSLVER", "1.1.1") 94 | openSslSourceDir = "openssl-" & openSslVersion 95 | openSslArchiveFile = openSslSourceDir & ".tar.gz" 96 | openSslDownloadLink = "https://www.openssl.org/source/" & openSslArchiveFile 97 | openSslInstallDir = (root / "openssl/") & openSslVersion 98 | # "no-async" is needed for openssl to compile using musl 99 | # - https://gitter.im/nim-lang/Nim?at=5bbf75c3ae7be940163cc198 100 | # - https://www.openwall.com/lists/musl/2016/02/04/5 101 | # -DOPENSSL_NO_SECURE_MEMORY is needed to make openssl compile using musl. 102 | # - https://github.com/openssl/openssl/issues/7207#issuecomment-420814524 103 | openSslConfigureCmd = ["./Configure", openSslSeedConfigOsCompiler, "no-shared", "no-zlib", "no-async", "-fPIC", "-DOPENSSL_NO_SECURE_MEMORY", "--prefix=" & openSslInstallDir] 104 | openSslLibDir = openSslInstallDir / "lib" 105 | openSslLibFile = openSslLibDir / "libssl.a" 106 | openCryptoLibFile = openSslLibDir / "libcrypto.a" 107 | openSslIncludeDir = openSslInstallDir / "include/openssl" 108 | # Custom Header file to force to link to GLibC 2.5, for old Linux (x86_64). 109 | glibc25DownloadLink = "https://raw.githubusercontent.com/wheybags/glibc_version_header/master/version_headers/x64/force_link_glibc_2.5.h" 110 | 111 | 112 | ## Helper Procs 113 | # https://github.com/kaushalmodi/elnim 114 | proc dollar[T](s: T): string = 115 | result = $s 116 | proc mapconcat[T](s: openArray[T]; sep = " "; op: proc(x: T): string = dollar): string = 117 | ## Concatenate elements of ``s`` after applying ``op`` to each element. 118 | ## Separate each element using ``sep``. 119 | for i, x in s: 120 | result.add(op(x)) 121 | if i < s.len-1: 122 | result.add(sep) 123 | 124 | proc parseArgs(): tuple[switches: seq[string], nonSwitches: seq[string]] = 125 | ## Parse the args and return its components as 126 | ## ``(switches, nonSwitches)``. 127 | let 128 | numParams = paramCount() # count starts at 0 129 | # So "nim musl foo.nim" will have a count of 2. 130 | # param 0 will always be "nim" 131 | doAssert numParams >= 1 132 | # param 1 will always be the task name like "musl". 133 | let 134 | subCmd = paramStr(1) 135 | 136 | if numParams < 2: 137 | error("The '$1' sub-command needs at least one non-switch argument" % [subCmd]) 138 | 139 | for i in 2 .. numParams: 140 | if paramStr(i)[0] == '-': # -d:foo or --define:foo 141 | result.switches.add(paramStr(i)) 142 | else: 143 | result.nonSwitches.add(paramStr(i)) 144 | 145 | proc runUtil(f, util: string; args: seq[string]) = 146 | ## Run ``util`` executable with ``args`` on ``f`` file. 147 | doAssert findExe(util) != "", 148 | "'$1' executable was not found" % [util] 149 | let 150 | cmd = concat(@[util], args, @[f]).mapconcat() 151 | echo "Running '$1' .." % [cmd] 152 | exec cmd 153 | 154 | template preBuild(targetPlusSwitches: string) = 155 | assert targetPlusSwitches.len > 0, "Build arguments must not be empty" 156 | when defined(libressl) and defined(openssl): 157 | error("Define only 'libressl' or 'openssl', not both.") 158 | let (switches, nimFiles) = parseArgs() 159 | assert nimFiles.len > 0, """ 160 | This nim sub-command accepts at least one Nim file name 161 | Examples: nim FILE.nim 162 | nim FILE1.nim FILE2.nim 163 | nim -d:pcre FILE.nim 164 | """ 165 | var allBuildCmds {.inject.} = newSeqOfCap[tuple[nimArgs, binFile: string]](nimFiles.len) 166 | for f in nimFiles: 167 | let 168 | extraSwitches = switches.mapconcat() 169 | (dirName, baseName, tmpVar) = splitFile(f) 170 | binFile = dirName / baseName # Save the binary in the same dir as the nim file 171 | nimArgsArray = when doOptimize: 172 | [targetPlusSwitches, "-d:musl", "-d:release", "--opt:size", "--passL:-s", "--listFullPaths:off", "--excessiveStackTrace:off", extraSwitches, " --out:" & binFile, f] 173 | else: 174 | [targetPlusSwitches, "-d:musl", extraSwitches, " --out:" & binFile, f] 175 | nimArgs = nimArgsArray.mapconcat() 176 | discard tmpVar # Avoid the "declared but not used" warning. Workaround for https://github.com/nim-lang/Nim/issues/12094 177 | allBuildCmds.add((nimArgs: nimArgs, binFile: binFile)) 178 | 179 | 180 | ## Tasks 181 | task installPcre, "Install PCRE using musl-gcc": 182 | if not fileExists(pcreLibFile): 183 | if not dirExists(pcreSourceDir): 184 | if not fileExists(pcreArchiveFile): 185 | exec("curl -LO " & pcreDownloadLink) 186 | exec("tar xf " & pcreArchiveFile) 187 | else: 188 | echo "PCRE lib source dir " & pcreSourceDir & " already exists" 189 | withDir pcreSourceDir: 190 | putEnv("CC", "musl-gcc -static") 191 | exec(pcreConfigureCmd.mapconcat()) 192 | exec("make -j8") 193 | exec("make install") 194 | else: 195 | echo pcreLibFile & " already exists" 196 | setCommand("nop") 197 | 198 | task installLibreSsl, "Install LIBRESSL using musl-gcc": 199 | if (not fileExists(libreSslLibFile)) or (not fileExists(libreCryptoLibFile)): 200 | if not dirExists(libreSslSourceDir): 201 | if not fileExists(libreSslArchiveFile): 202 | exec("curl -LO " & libreSslDownloadLink) 203 | exec("tar xf " & libreSslArchiveFile) 204 | else: 205 | echo "LibreSSL lib source dir " & libreSslSourceDir & " already exists" 206 | withDir libreSslSourceDir: 207 | # -idirafter /usr/include/ # Needed for linux/sysctl.h 208 | # -idirafter /usr/include/x86_64-linux-gnu/ # Needed for Travis/Ubuntu build to pass, for asm/types.h 209 | putEnv("CC", "musl-gcc -static -idirafter /usr/include/ -idirafter /usr/include/x86_64-linux-gnu/") 210 | putEnv("C_INCLUDE_PATH", libreSslIncludeDir) 211 | exec(libreSslConfigureCmd.mapconcat()) 212 | exec("make -j8 -C crypto") # build just the "crypto" component 213 | exec("make -j8 -C ssl") # build just the "ssl" component 214 | exec("make -C crypto install") 215 | exec("make -C ssl install") 216 | else: 217 | echo libreSslLibFile & " already exists" 218 | setCommand("nop") 219 | 220 | task installOpenSsl, "Install OPENSSL using musl-gcc": 221 | if (not fileExists(openSslLibFile)) or (not fileExists(openCryptoLibFile)): 222 | if not dirExists(openSslSourceDir): 223 | if not fileExists(openSslArchiveFile): 224 | exec("curl -LO " & openSslDownloadLink) 225 | exec("tar xf " & openSslArchiveFile) 226 | else: 227 | echo "OpenSSL lib source dir " & openSslSourceDir & " already exists" 228 | withDir openSslSourceDir: 229 | # https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html 230 | # -idirafter /usr/include/ # Needed for Travis/Ubuntu build to pass, for linux/version.h, etc. 231 | # -idirafter /usr/include/x86_64-linux-gnu/ # Needed for Travis/Ubuntu build to pass, for asm/types.h 232 | putEnv("CC", "musl-gcc -static -idirafter /usr/include/ -idirafter /usr/include/x86_64-linux-gnu/") 233 | putEnv("C_INCLUDE_PATH", openSslIncludeDir) 234 | exec(openSslConfigureCmd.mapconcat()) 235 | echo "The insecure switch -DOPENSSL_NO_SECURE_MEMORY is needed so that OpenSSL can be compiled using MUSL." 236 | exec("make -j8 depend") 237 | exec("make -j8") 238 | exec("make install_sw") 239 | else: 240 | echo openSslLibFile & " already exists" 241 | setCommand("nop") 242 | 243 | task strip, "Optimize the binary size using 'strip' utility": 244 | ## Usage: nim strip .. 245 | let 246 | (_, binFiles) = parseArgs() 247 | for f in binFiles: 248 | f.runUtil("strip", stripSwitches) 249 | setCommand("nop") 250 | 251 | task upx, "Optimize the binary size using 'upx' utility": 252 | ## Usage: nim upx .. 253 | let 254 | (_, binFiles) = parseArgs() 255 | for f in binFiles: 256 | f.runUtil("upx", upxSwitches) 257 | setCommand("nop") 258 | 259 | task checksums, "Generate checksums of the binary using 'sha1sum' and 'md5sum'": 260 | ## Usage: nim checksums .. 261 | let (_, binFiles) = parseArgs() 262 | for f in binFiles: 263 | f.runUtil("md5sum", checksumsSwitches) 264 | f.runUtil("sha1sum", checksumsSwitches) 265 | setCommand("nop") 266 | 267 | task sign, "Sign the binary using 'gpg' (armored, ascii)": 268 | ## Usage: nim sign .. 269 | let (_, binFiles) = parseArgs() 270 | for f in binFiles: 271 | f.runUtil("gpg", gpgSignSwitches) 272 | setCommand("nop") 273 | 274 | task encrypt, "Encrypt the binary using 'gpg' (compressed, symmetric, ascii)": 275 | ## Usage: nim encrypt .. 276 | # Decrypt is just double click or 'gpg --decrypt' (Asks Password). 277 | let (_, binFiles) = parseArgs() 278 | for f in binFiles: 279 | f.runUtil("gpg", gpgEncryptSwitches) 280 | setCommand("nop") 281 | 282 | task musl, "Build an optimized static binary using musl": 283 | ## Usage: nim musl [-d:pcre] [-d:libressl|-d:openssl] .. 284 | preBuild("c") 285 | for cmd in allBuildCmds: 286 | # Build binary 287 | echo "\nRunning 'nim " & cmd.nimArgs & "' .." 288 | selfExec cmd.nimArgs 289 | when doOptimize: 290 | cmd.binFile.runUtil("strip", stripSwitches) 291 | cmd.binFile.runUtil("upx", upxSwitches) 292 | echo "Built: " & cmd.binFile 293 | 294 | task glibc25, "Build C, dynamically linked to GLibC 2.5 (x86_64)": 295 | ## Usage: nim glibc25 file.nim 296 | # See https://github.com/wheybags/glibc_version_header/pull/21. 297 | let 298 | header = getCurrentDir() / "force_link_glibc_2.5.h" 299 | optns = ["-ffast-math", "-flto", "-include" & header] # Don't use -march here 300 | if not fileExists(header): 301 | exec("curl -LO " & glibc25DownloadLink) 302 | var passCSwitches: string 303 | for o in optns: 304 | passCSwitches.add(" --passC:" & o) 305 | preBuild("c -d:ssl" & passCSwitches) 306 | for cmd in allBuildCmds: 307 | echo "\nRunning 'nim " & cmd.nimArgs 308 | # preBuild auto-adds "-d:musl", so remove that. 309 | # FIXME: Make preBuild not always add that switch. -- Thu Jun 13 12:13:17 EDT 2019 - kmodi 310 | selfExec cmd.nimArgs.replace("-d:musl", "") 311 | when doOptimize: 312 | cmd.binFile.runUtil("strip", stripSwitches) 313 | # Version check -- Changes from GLIBC_2.15 to GLIBC_2.5 314 | cmd.binFile.runUtil("ldd", @["-v"]) 315 | 316 | task js2asm, "Build JS, print Assembly from that JS (performance debug)": 317 | ## Usage: nim js2asm .. 318 | # This debugs performance of JavaScript, the less ASM the better JS. 319 | # This ASM is NOT usable as proper ASM, just for Debug performance. 320 | preBuild("js") 321 | for cmd in allBuildCmds: 322 | echo "\nRunning 'nim " & cmd.nimArgs 323 | selfExec cmd.nimArgs 324 | cmd.binFile.runUtil("node", @["--print_code"]) 325 | 326 | task c2asm, "Build C, print Assembly from that C (performance debug)": 327 | ## Usage: nim c2asm .. 328 | # This debugs performance of Nim, the less ASM the better your Nim. 329 | const 330 | optns = [ # This cleans up the produced ASM as much as possible. 331 | "-ffast-math", "-march=native", "-fno-math-errno", "-fno-exceptions", 332 | "-fno-asynchronous-unwind-tables", "-fno-inline-functions", "-std=c11", 333 | "-fno-inline-functions-called-once", "-fno-inline-small-functions", 334 | "-xc", "-s", "-S", "-O3", "-masm=intel", "-o-"] 335 | var passCSwitches: string 336 | for o in optns: 337 | passCSwitches.add(" --passC:" & o) 338 | preBuild("compileToC --compileOnly:on -d:danger -d:noSignalHandler" & passCSwitches) 339 | for cmd in allBuildCmds: 340 | echo "\nRunning 'nim " & cmd.nimArgs 341 | selfExec cmd.nimArgs 342 | let cSource = nimcacheDir() / cmd.binFile & ".nim.c" 343 | cSource.runUtil("gcc", @optns) 344 | 345 | task fmt, "Run nimpretty on all git-managed .nim files in the current repo": 346 | ## Usage: nim fmt 347 | for file in walkDirRec(root, {pcFile, pcDir}): 348 | if file.splitFile().ext == ".nim": 349 | let 350 | # https://github.com/nim-lang/Nim/issues/6262#issuecomment-454983572 351 | # https://stackoverflow.com/a/2406813/1219634 352 | fileIsGitManaged = gorgeEx("cd $1 && git ls-files --error-unmatch $2" % [getCurrentDir(), file]).exitCode == 0 353 | # ^^^^^-- That "cd" is required. 354 | if fileIsGitManaged: 355 | let 356 | cmd = "nimpretty $1" % [file] 357 | echo "Running $1 .." % [cmd] 358 | exec(cmd) 359 | setCommand("nop") 360 | 361 | task rmfiles, "Recursively remove all files with the specific extension(s) from the current directory": 362 | ## Usage: nim rmfiles pyc c o 363 | for extToDelete in parseArgs().nonSwitches: # Invalid Patterns: "", " ", "\t" 364 | assert extToDelete.strip.len > 0, "Specified extension must not be whitespace or empty string" 365 | assert extToDelete[0] != '.', "Do not prefix the extensions with dot" 366 | for file in walkDirRec(getCurrentDir(), {pcFile, pcDir}): 367 | if file.splitFile().ext == "." & extToDelete: 368 | # echo "file to delete: ", file 369 | rmFile(file) 370 | setCommand("nop") 371 | 372 | task test, "Run tests via 'nim doc' (runnableExamples) and tests in tests/ dir": 373 | let 374 | testDir = root / "tests" 375 | selfExec("doc " & srcFile) 376 | if dirExists(testDir): 377 | let 378 | testFiles = listFiles(testDir).filterIt(it.len >= 5 and it.endsWith(".nim")) 379 | for t in testFiles: 380 | selfExec "c -r " & t 381 | 382 | when nimVersion >= (1, 3, 5): 383 | task docs, "Deploy doc html + search index to public/ directory": 384 | let 385 | deployDir = root / "public" 386 | selfExec("doc --project --outdir:$1 $2" % [deployDir, srcFile]) # generates search index and theindex.html too. 387 | withDir deployDir: 388 | # Move PKGNAME.html to index.html so that we can access the 389 | # documentation on a clean URL like https://foo.bar/ instead of 390 | # https://foo.bar/PKGNAME.html. 391 | mvFile(pkgName & ".html", "index.html") 392 | # As we renamed the file, we need to rename that in hyperlinks 393 | # and the search index too. 394 | for file in walkDirRec(".", {pcFile}): 395 | exec(r"sed -i -r 's|$1\.html|index.html|g' $2" % [pkgName, file]) 396 | else: 397 | task docs, "Deploy doc html + search index to public/ directory": 398 | let 399 | deployDir = root / "public" 400 | docOutBaseName = "index" 401 | deployHtmlFile = deployDir / (docOutBaseName & ".html") 402 | genDocCmd = "nim doc --out:$1 --index:on $2" % [deployHtmlFile, srcFile] 403 | genTheIndexCmd = "nim buildIndex -o:$1/theindex.html $1" % [deployDir] 404 | deployJsFile = deployDir / "dochack.js" 405 | docHackJsSource = "https://nim-lang.github.io/Nim/dochack.js" # devel docs dochack.js 406 | mkDir(deployDir) 407 | exec(genDocCmd) 408 | exec(genTheIndexCmd) 409 | if not fileExists(deployJsFile): 410 | withDir deployDir: 411 | exec("curl -LO " & docHackJsSource) 412 | 413 | # https://www.reddit.com/r/nim/comments/byzq7d/go_run_for_nim/ 414 | task runc, "Run equivalent of 'nim c -r ..'": 415 | switch("run") 416 | switch("verbosity", "0") 417 | hint("Processing", false) 418 | setCommand("c") 419 | 420 | task runcpp, "Run equivalent of 'nim cpp -r ..'": 421 | switch("run") 422 | switch("verbosity", "0") 423 | hint("Processing", false) 424 | setCommand("cpp") 425 | 426 | ## Define Switch Parsing 427 | # -d:musl 428 | when defined(musl): 429 | var 430 | muslGccPath: string 431 | echo " [-d:musl] Building a static binary using musl .." 432 | muslGccPath = findExe("musl-gcc") 433 | if muslGccPath == "": 434 | error("'musl-gcc' binary was not found in PATH.") 435 | switch("passL", "-static") 436 | switch("gcc.exe", muslGccPath) 437 | switch("gcc.linkerexe", muslGccPath) 438 | # -d:pcre 439 | when defined(pcre): 440 | let 441 | pcreIncludeDir = pcreInstallDir / "include" 442 | if not fileExists(pcreLibFile): 443 | selfExec "installPcre" # Install PCRE in current dir if pcreLibFile is not found 444 | switch("passC", "-I" & pcreIncludeDir) # So that pcre.h is found when running the musl task 445 | switch("define", "usePcreHeader") 446 | switch("passL", pcreLibFile) 447 | # -d:libressl or -d:openssl 448 | when defined(libressl) or defined(openssl): 449 | switch("define", "ssl") # Pass -d:ssl to nim 450 | when defined(libressl): 451 | let 452 | sslLibFile = libreSslLibFile 453 | cryptoLibFile = libreCryptoLibFile 454 | sslIncludeDir = libreSslIncludeDir 455 | sslLibDir = libreSslLibDir 456 | when defined(openssl): 457 | let 458 | sslLibFile = openSslLibFile 459 | cryptoLibFile = openCryptoLibFile 460 | sslIncludeDir = openSslIncludeDir 461 | sslLibDir = openSslLibDir 462 | 463 | if (not fileExists(sslLibFile)) or (not fileExists(cryptoLibFile)): 464 | # Install SSL in current dir if sslLibFile or cryptoLibFile is not found 465 | when defined(libressl): 466 | selfExec "installLibreSsl" 467 | when defined(openssl): 468 | selfExec "installOpenSsl" 469 | switch("passC", "-I" & sslIncludeDir) # So that ssl.h is found when running the musl task 470 | switch("passL", "-L" & sslLibDir) 471 | switch("passL", "-lssl") 472 | switch("passL", "-lcrypto") # This *has* to come *after* -lssl 473 | switch("dynlibOverride", "libssl") 474 | switch("dynlibOverride", "libcrypto") 475 | --------------------------------------------------------------------------------