diff --git a/.appveyor.yml b/.appveyor.yml index 1cab66176..76c4a7c0b 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -42,6 +42,11 @@ test_script: - build\nimbus.exe --help - mingw32-make -j2 ARCH_OVERRIDE=%PLATFORM% test - IF "%PLATFORM%" == "x64" mingw32-make -j2 test-reproducibility + # disable libnimbus builds until https://github.com/nim-lang/Nim/issues/12759 is fixed + # wrapper builds could then also get activated instead but need some rework for Windows + # the "go-checks" target fails in AppVeyor, for some reason; easier to disable than to debug + # - mingw32-make -j2 ARCH_OVERRIDE=%PLATFORM% DISABLE_GO_CHECKS=1 libnimbus.so + # - mingw32-make -j2 ARCH_OVERRIDE=%PLATFORM% DISABLE_GO_CHECKS=1 libnimbus.a deploy: off diff --git a/.travis.yml b/.travis.yml index 1e1827209..c30c218db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -language: c +language: go dist: bionic @@ -14,6 +14,9 @@ git: # disable LFS file downloading during regular cloning lfs_skip_smudge: true +go: + - "1.12.x" + matrix: include: - os: linux @@ -48,5 +51,9 @@ script: - make -j${NPROC} NIMFLAGS="--parallelBuild:${NPROC}" update # to allow a newer Nim version to be detected - make -j${NPROC} NIMFLAGS="--parallelBuild:${NPROC}" - build/nimbus --help - - make -j${NPROC} NIMFLAGS="--parallelBuild:${NPROC}" test test-reproducibility - + # -static option will not work for osx unless static system libraries are provided + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then + make -j${NPROC} NIMFLAGS="--parallelBuild:${NPROC}" test test-reproducibility wrappers; + else + make -j${NPROC} NIMFLAGS="--parallelBuild:${NPROC}" test test-reproducibility wrappers wrappers-static; + fi diff --git a/Makefile b/Makefile index 15ab6ddc1..506794b27 100644 --- a/Makefile +++ b/Makefile @@ -86,18 +86,21 @@ wrappers: | build deps libnimbus.so go-checks echo -e $(BUILD_MSG) "build/C_wrapper_example" && \ $(CC) wrappers/wrapper_example.c -Wl,-rpath,'$$ORIGIN' -Lbuild -lnimbus -lm -g -o build/C_wrapper_example echo -e $(BUILD_MSG) "build/go_wrapper_example" && \ - go build -linkshared -o build/go_wrapper_example wrappers/wrapper_example.go wrappers/cfuncs.go + go build -o build/go_wrapper_example wrappers/wrapper_example.go wrappers/cfuncs.go echo -e $(BUILD_MSG) "build/go_wrapper_whisper_example" && \ - go build -linkshared -o build/go_wrapper_whisper_example wrappers/wrapper_whisper_example.go wrappers/cfuncs.go + go build -o build/go_wrapper_whisper_example wrappers/wrapper_whisper_example.go wrappers/cfuncs.go libnimbus.a: | build deps echo -e $(BUILD_MSG) "build/$@" && \ rm -f build/$@ && \ - $(ENV_SCRIPT) nim c --app:staticlib --noMain --nimcache:nimcache/libnimbus $(NIM_PARAMS) -o:build/$@ wrappers/libnimbus.nim + $(ENV_SCRIPT) nim c --app:staticlib --noMain --nimcache:nimcache/libnimbus_static $(NIM_PARAMS) -o:build/$@ wrappers/libnimbus.nim && \ + [[ -e "$@" ]] && mv "$@" build/ # workaround for https://github.com/nim-lang/Nim/issues/12745 wrappers-static: | build deps libnimbus.a go-checks echo -e $(BUILD_MSG) "build/C_wrapper_example_static" && \ $(CC) wrappers/wrapper_example.c -static -pthread -Lbuild -lnimbus -lm -ldl -lpcre -g -o build/C_wrapper_example_static echo -e $(BUILD_MSG) "build/go_wrapper_example_static" && \ go build -ldflags "-linkmode external -extldflags '-static -ldl -lpcre'" -o build/go_wrapper_example_static wrappers/wrapper_example.go wrappers/cfuncs.go + echo -e $(BUILD_MSG) "build/go_wrapper_whisper_example_static" && \ + go build -ldflags "-linkmode external -extldflags '-static -ldl -lpcre'" -o build/go_wrapper_whisper_example_static wrappers/wrapper_example.go wrappers/cfuncs.go diff --git a/nix/nimbus-wrappers.nix b/nix/nimbus-wrappers.nix index 5020c82ab..834730b76 100644 --- a/nix/nimbus-wrappers.nix +++ b/nix/nimbus-wrappers.nix @@ -40,7 +40,7 @@ stdenv.mkDerivation rec { LD_LIBRARY_PATH = "${makeLibraryPath buildInputs}"; buildPhase = '' - mkdir -p $TMPDIR/.nimcache ./build + mkdir -p $TMPDIR/.nimcache $TMPDIR/.nimcache_static ./build BUILD_MSG="\\e[92mBuilding:\\e[39m" export CC="${clang}/bin/clang" @@ -50,13 +50,11 @@ stdenv.mkDerivation rec { vendorPathOpts="${concatMapStringsSep " " (dep: "--path:./vendor/${dep}") vendorDeps}" echo -e $BUILD_MSG "build/libnimbus.so" && \ ${nim}/bin/nim c --app:lib --noMain --nimcache:$TMPDIR/.nimcache -d:release ''${vendorPathOpts} -o:./build/libnimbus.so wrappers/libnimbus.nim - # For some reason nim doesn't output anything if we pass -o option when building the static lib - # so we just move it from the default location after it's built echo -e $BUILD_MSG "build/libnimbus.a" && \ - ${nim}/bin/nim c --app:staticlib --noMain --nimcache:$TMPDIR/.nimcache -d:release ''${vendorPathOpts} wrappers/libnimbus.nim && \ - mv libnimbus build/libnimbus.a + ${nim}/bin/nim c --app:staticlib --noMain --nimcache:$TMPDIR/.nimcache_static -d:release ''${vendorPathOpts} -o:build/libnimbus.a wrappers/libnimbus.nim && \ + [[ -e "libnimbus.a" ]] && mv "libnimbus.a" build/ # workaround for https://github.com/nim-lang/Nim/issues/12745 - rm -rf $TMPDIR/.nimcache + rm -rf $TMPDIR/.nimcache $TMPDIR/.nimcache_static '' + optionalString buildSamples '' mkdir -p $TMPDIR/.home/.cache @@ -65,9 +63,9 @@ stdenv.mkDerivation rec { echo -e $BUILD_MSG "build/C_wrapper_example" && \ $CC wrappers/wrapper_example.c -Wl,-rpath,'$$ORIGIN' -Lbuild -lnimbus -lm -g -o build/C_wrapper_example echo -e $BUILD_MSG "build/go_wrapper_example" && \ - ${go}/bin/go build -linkshared -o build/go_wrapper_example wrappers/wrapper_example.go wrappers/cfuncs.go + ${go}/bin/go build -o build/go_wrapper_example wrappers/wrapper_example.go wrappers/cfuncs.go echo -e $BUILD_MSG "build/go_wrapper_whisper_example" && \ - ${go}/bin/go build -linkshared -o build/go_wrapper_whisper_example wrappers/wrapper_whisper_example.go wrappers/cfuncs.go + ${go}/bin/go build -o build/go_wrapper_whisper_example wrappers/wrapper_whisper_example.go wrappers/cfuncs.go rm -rf $TMPDIR/.home/.cache ''; diff --git a/vendor/nimcrypto b/vendor/nimcrypto index 2bbf7c3c0..e50298c7a 160000 --- a/vendor/nimcrypto +++ b/vendor/nimcrypto @@ -1 +1 @@ -Subproject commit 2bbf7c3c0185448d933f2b66ae1a74deef1fd0c9 +Subproject commit e50298c7ac4d1bd6a087b38a9c27c2ae16271940 diff --git a/wrappers/README.md b/wrappers/README.md index 3dbac479a..68eab17f3 100644 --- a/wrappers/README.md +++ b/wrappers/README.md @@ -26,6 +26,13 @@ To build statically linked versions: make wrappers-static ``` +You can also build the wrappers with the Nix build file (Need to +[install](https://nixos.org/nix/download.html) Nix first): + +```bash +nix-build -A wrappers +``` + # Notes on usage Before any of the API calls are done, `NimMain()` needs to be run. diff --git a/wrappers/libnimbus.nim b/wrappers/libnimbus.nim index 86f2d38ae..e6ea970a9 100644 --- a/wrappers/libnimbus.nim +++ b/wrappers/libnimbus.nim @@ -98,7 +98,8 @@ proc connectToNodes(nodes: openArray[string]) = # Setting up the node proc nimbus_start(port: uint16, startListening: bool, enableDiscovery: bool, - minPow: float64, privateKey: ptr byte, staging: bool): bool {.exportc.} = + minPow: float64, privateKey: ptr byte, staging: bool): bool + {.exportc, dynlib.} = # TODO: any async calls can still create `Exception`, why? let address = Address( udpPort: port.Port, tcpPort: port.Port, ip: parseIpAddress("0.0.0.0")) @@ -134,10 +135,10 @@ proc nimbus_start(port: uint16, startListening: bool, enableDiscovery: bool, result = true -proc nimbus_poll() {.exportc.} = +proc nimbus_poll() {.exportc, dynlib.} = poll() -proc nimbus_add_peer(nodeId: cstring): bool {.exportc.} = +proc nimbus_add_peer(nodeId: cstring): bool {.exportc, dynlib.} = var whisperENode: ENode whisperNode: Node @@ -153,7 +154,8 @@ proc nimbus_add_peer(nodeId: cstring): bool {.exportc.} = # Whisper API (Similar to Whisper JSON-RPC API) -proc nimbus_channel_to_topic(channel: cstring): CTopic {.exportc, raises: [].} = +proc nimbus_channel_to_topic(channel: cstring): CTopic + {.exportc, dynlib, raises: [].} = # Only used for the example, to conveniently convert channel to topic. doAssert(not channel.isNil, "Channel cannot be nil.") @@ -163,7 +165,8 @@ proc nimbus_channel_to_topic(channel: cstring): CTopic {.exportc, raises: [].} = # Asymmetric Keys -proc nimbus_new_keypair(id: var Identifier): bool {.exportc, raises: [].} = +proc nimbus_new_keypair(id: var Identifier): bool + {.exportc, dynlib, raises: [].} = ## Caller needs to provide as id a pointer to 32 bytes allocation. doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.") @@ -177,7 +180,7 @@ proc nimbus_new_keypair(id: var Identifier): bool {.exportc, raises: [].} = discard proc nimbus_add_keypair(privateKey: ptr byte, id: var Identifier): - bool {.exportc, raises: [OSError, IOError, ValueError].} = + bool {.exportc, dynlib, raises: [OSError, IOError, ValueError].} = ## Caller needs to provide as id a pointer to 32 bytes allocation. doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.") doAssert(not privateKey.isNil, "Private key cannot be nil.") @@ -194,14 +197,15 @@ proc nimbus_add_keypair(privateKey: ptr byte, id: var Identifier): id = generateRandomID() whisperKeys.asymKeys.add(id.toHex(), keypair) -proc nimbus_delete_keypair(id: Identifier): bool {.exportc, raises: [].} = +proc nimbus_delete_keypair(id: Identifier): bool + {.exportc, dynlib, raises: [].} = doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.") var unneeded: KeyPair result = whisperKeys.asymKeys.take(id.toHex(), unneeded) proc nimbus_get_private_key(id: Identifier, privateKey: var PrivateKey): - bool {.exportc, raises: [OSError, IOError, ValueError].} = + bool {.exportc, dynlib, raises: [OSError, IOError, ValueError].} = doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.") doAssert(not (unsafeAddr privateKey).isNil, "Private key cannot be nil.") @@ -214,7 +218,7 @@ proc nimbus_get_private_key(id: Identifier, privateKey: var PrivateKey): # Symmetric Keys proc nimbus_add_symkey(symKey: ptr SymKey, id: var Identifier): bool - {.exportc, raises: [].} = + {.exportc, dynlib, raises: [].} = ## Caller needs to provide as id a pointer to 32 bytes allocation. doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.") doAssert(not symKey.isNil, "Symmetric key cannot be nil.") @@ -226,7 +230,7 @@ proc nimbus_add_symkey(symKey: ptr SymKey, id: var Identifier): bool whisperKeys.symKeys.add(id.toHex, symKey[]) proc nimbus_add_symkey_from_password(password: cstring, id: var Identifier): - bool {.exportc, raises: [].} = + bool {.exportc, dynlib, raises: [].} = ## Caller needs to provide as id a pointer to 32 bytes allocation. doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.") doAssert(not password.isNil, "Password cannot be nil.") @@ -241,14 +245,15 @@ proc nimbus_add_symkey_from_password(password: cstring, id: var Identifier): whisperKeys.symKeys.add(id.toHex(), symKey) -proc nimbus_delete_symkey(id: Identifier): bool {.exportc, raises: [].} = +proc nimbus_delete_symkey(id: Identifier): bool + {.exportc, dynlib, raises: [].} = doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.") var unneeded: SymKey result = whisperKeys.symKeys.take(id.toHex(), unneeded) proc nimbus_get_symkey(id: Identifier, symKey: var SymKey): - bool {.exportc, raises: [OSError, IOError, ValueError].} = + bool {.exportc, dynlib, raises: [OSError, IOError, ValueError].} = doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.") doAssert(not (unsafeAddr symKey).isNil, "Symmetric key cannot be nil.") @@ -260,7 +265,7 @@ proc nimbus_get_symkey(id: Identifier, symKey: var SymKey): # Whisper message posting and receiving -proc nimbus_post(message: ptr CPostMessage): bool {.exportc.} = +proc nimbus_post(message: ptr CPostMessage): bool {.exportc, dynlib.} = ## Encryption is mandatory. ## A symmetric key or an asymmetric key must be provided. Both is not allowed. ## Providing a payload is mandatory, it cannot be nil, but can be of length 0. @@ -323,7 +328,7 @@ proc nimbus_post(message: ptr CPostMessage): bool {.exportc.} = proc nimbus_subscribe_filter(options: ptr CFilterOptions, handler: proc (msg: ptr CReceivedMessage, udata: pointer) {.gcsafe, cdecl.}, - udata: pointer = nil, id: var Identifier): bool {.exportc.} = + udata: pointer = nil, id: var Identifier): bool {.exportc, dynlib.} = ## Encryption is mandatory. ## A symmetric key or an asymmetric key must be provided. Both is not allowed. ## The received message needs to be copied before the passed handler ends. @@ -402,15 +407,16 @@ proc nimbus_subscribe_filter(options: ptr CFilterOptions, traceAsyncErrors node.setBloomFilter(node.filtersToBloom()) result = true -proc nimbus_unsubscribe_filter(id: Identifier): bool {.exportc, raises: [].} = +proc nimbus_unsubscribe_filter(id: Identifier): bool + {.exportc, dynlib, raises: [].} = doAssert(not(unsafeAddr id).isNil, "Filter id cannot be nil.") result = node.unsubscribeFilter(id.toHex()) -proc nimbus_get_min_pow(): float64 {.exportc, raises: [].} = +proc nimbus_get_min_pow(): float64 {.exportc, dynlib, raises: [].} = result = node.protocolState(Whisper).config.powRequirement -proc nimbus_get_bloom_filter(bloom: var Bloom) {.exportc, raises: [].} = +proc nimbus_get_bloom_filter(bloom: var Bloom) {.exportc, dynlib, raises: [].} = doAssert(not (unsafeAddr bloom).isNil, "Bloom pointer cannot be nil.") bloom = node.protocolState(Whisper).config.bloom @@ -437,7 +443,7 @@ proc subscribeChannel( proc nimbus_join_public_chat(channel: cstring, handler: proc (msg: ptr CReceivedMessage) - {.gcsafe, cdecl.}) {.exportc.} = + {.gcsafe, cdecl.}) {.exportc, dynlib.} = if handler.isNil: subscribeChannel($channel, nil) else: @@ -458,7 +464,8 @@ proc nimbus_join_public_chat(channel: cstring, # TODO: Add signing key as parameter # TODO: How would we do key management? In nimbus (like in rpc) or in status go? -proc nimbus_post_public(channel: cstring, payload: cstring) {.exportc.} = +proc nimbus_post_public(channel: cstring, payload: cstring) + {.exportc, dynlib.} = let encPrivateKey = initPrivateKey("5dc5381cae54ba3174dc0d46040fe11614d0cc94d41185922585198b4fcef9d3") var ctx: HMAC[sha256]