diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..ca429902 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,74 @@ +version: 2 + +jobs: + build: + working_directory: ~/work + docker: + - image: circleci/python:latest + + steps: + - checkout + - run: .circleci/launch-job aarch64 + - run: .circleci/launch-job arm + - run: .circleci/launch-job i686 + - run: .circleci/launch-job x86_64 + + # aarch64-linux-android-4.9 + aarch64: + working_directory: ~/work + docker: + - image: toktoknet/ghc-android:latest.aarch64 + + steps: + - checkout + - restore_cache: + key: v1-cabal-cache-aarch64 + - run: android/build.sh + - save_cache: + key: v1-cabal-cache-aarch64 + paths: [~/.ghc/android-21/aarch64-linux-android-4.9] + + # arm-linux-androideabi-4.9 + arm: + working_directory: ~/work + docker: + - image: toktoknet/ghc-android:latest.arm + + steps: + - checkout + - restore_cache: + key: v1-cabal-cache-arm + - run: android/build.sh + - save_cache: + key: v1-cabal-cache-arm + paths: [~/.ghc/android-9/arm-linux-androideabi-4.9] + + # x86-4.9 + i686: + working_directory: ~/work + docker: + - image: toktoknet/ghc-android:latest.i686 + + steps: + - checkout + - restore_cache: + key: v1-cabal-cache-i686 + - run: android/build.sh + - save_cache: + key: v1-cabal-cache-i686 + paths: [~/.ghc/android-9/x86-4.9] + + # x86_64-4.9 + x86_64: + working_directory: ~/work + docker: + - image: toktoknet/ghc-android:latest.x86_64 + + steps: + - checkout + - restore_cache: + key: v1-cabal-cache-x86_64 + - run: android/build.sh + - save_cache: + key: v1-cabal-cache-x86_64 + paths: [~/.ghc/android-21/x86_64-4.9] diff --git a/.circleci/launch-job b/.circleci/launch-job new file mode 100755 index 00000000..eafbdbf1 --- /dev/null +++ b/.circleci/launch-job @@ -0,0 +1,6 @@ +#!/bin/sh + +curl --user ${CIRCLE_API_TOKEN}: \ + --data build_parameters[CIRCLE_JOB]=$1 \ + --data revision=$CIRCLE_SHA1 \ + https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/tree/$CIRCLE_BRANCH diff --git a/.travis/android-install b/.travis/android-install deleted file mode 100755 index 0de7ed6a..00000000 --- a/.travis/android-install +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -docker pull $DOCKER_IMAGE -docker run --rm $DOCKER_IMAGE cat /root/dockrun > dockrun -chmod +x dockrun diff --git a/.travis/android-script b/.travis/android-script deleted file mode 100755 index 0e980d01..00000000 --- a/.travis/android-script +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -./dockrun target-cabal configure -flibrary-only -./dockrun target-cabal build diff --git a/android/build.sh b/android/build.sh new file mode 100755 index 00000000..9bf7b063 --- /dev/null +++ b/android/build.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +set -exu + +export SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +$NDK_TARGET-cabal update + +$SCRIPT_DIR/user-scripts/cabal-install-clock.sh +$SCRIPT_DIR/user-scripts/cabal-install-network.sh +$SCRIPT_DIR/user-scripts/cabal-install-setup.sh distributive 0.5.0.2 +$SCRIPT_DIR/user-scripts/cabal-install-setup.sh comonad 5 +$SCRIPT_DIR/user-scripts/cabal-install-setup.sh entropy 0.3.7 +$SCRIPT_DIR/user-scripts/cabal-install-zlib.sh +$SCRIPT_DIR/user-scripts/install-happy.sh +$SCRIPT_DIR/user-scripts/install-hspec.sh +$SCRIPT_DIR/user-scripts/install-libsodium.sh + +$NDK_TARGET-cabal install --enable-tests --enable-benchmarks --only-dependencies +$NDK_TARGET-cabal install -flibrary-only diff --git a/android/patches/hs-clock-ffi.patch b/android/patches/hs-clock-ffi.patch new file mode 100644 index 00000000..b74e5127 --- /dev/null +++ b/android/patches/hs-clock-ffi.patch @@ -0,0 +1,21 @@ +diff -u -r a/System/Clock.hsc b/System/Clock.hsc +--- a/System/Clock.hsc 2016-04-20 02:14:45.000000000 +0100 ++++ b/System/Clock.hsc 2017-06-09 12:15:31.229226983 +0100 +@@ -41,8 +41,6 @@ + # endif + #endif + +-#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__) +- + -- | Clock types. A clock may be system-wide (that is, visible to all processes) + -- or per-process (measuring time that is meaningful only within a process). + -- All implementations shall support CLOCK_REALTIME. (The only suspend-aware +@@ -216,7 +214,7 @@ + #else + instance Storable TimeSpec where + sizeOf _ = #{size struct timespec} +- alignment _ = #{alignment struct timespec} ++ alignment _ = #{const __alignof__(struct timespec)} + poke ptr ts = do + let xs :: #{type time_t} = fromIntegral $ sec ts + xn :: #{type long} = fromIntegral $ nsec ts diff --git a/android/patches/hs-network-ffi.patch b/android/patches/hs-network-ffi.patch new file mode 100644 index 00000000..d9ac4cc9 --- /dev/null +++ b/android/patches/hs-network-ffi.patch @@ -0,0 +1,12 @@ +diff -u -r a/Network/Socket/Types.hsc b/Network/Socket/Types.hsc +--- a/Network/Socket/Types.hsc 2017-05-30 20:10:33.000000000 +0000 ++++ b/Network/Socket/Types.hsc 2017-06-10 16:34:51.782365107 +0000 +@@ -1085,7 +1085,7 @@ + + instance Storable In6Addr where + sizeOf _ = #const sizeof(struct in6_addr) +- alignment _ = #alignment struct in6_addr ++ alignment _ = #const __alignof__(struct in6_addr) + + peek p = do + a <- peek32 p 0 diff --git a/android/patches/hs-zlib-ffi.patch b/android/patches/hs-zlib-ffi.patch new file mode 100644 index 00000000..4b4ad19f --- /dev/null +++ b/android/patches/hs-zlib-ffi.patch @@ -0,0 +1,67 @@ +diff -ru a/Codec/Compression/Zlib/Stream.hsc b/Codec/Compression/Zlib/Stream.hsc +--- a/Codec/Compression/Zlib/Stream.hsc 2015-05-16 15:12:10.000000000 +0200 ++++ b/Codec/Compression/Zlib/Stream.hsc 2016-07-04 22:25:40.933314724 +0200 +@@ -2,6 +2,9 @@ + #if __GLASGOW_HASKELL__ >= 702 + {-# LANGUAGE DeriveGeneric #-} + #endif ++#if __GLASGOW_HASKELL__ >= 706 ++{-# LANGUAGE CApiFFI #-} ++#endif + ----------------------------------------------------------------------------- + -- | + -- Copyright : (c) 2006-2015 Duncan Coutts +@@ -1007,7 +1010,19 @@ + -- + -- So we define c_inflateInit2 and c_deflateInit2 here as wrappers around + -- their _ counterparts and pass the extra args. +- ++-- ++-- As of GHC 7.6, we can import macros directly using the CApiFFI extension. ++-- This avoids the need for the hsc2hs #{const_str} construct, which means ++-- hsc2hs can run in cross-compilation mode. ++ ++#if __GLASGOW_HASKELL__ >= 706 ++foreign import capi unsafe "zlib.h inflateInit2" ++ c_inflateInit2 :: StreamState -> CInt -> IO CInt ++ ++foreign import capi unsafe "zlib.h deflateInit2" ++ c_deflateInit2 :: StreamState ++ -> CInt -> CInt -> CInt -> CInt -> CInt -> IO CInt ++#else + foreign import ccall unsafe "zlib.h inflateInit2_" + c_inflateInit2_ :: StreamState -> CInt -> Ptr CChar -> CInt -> IO CInt + +@@ -1016,15 +1031,6 @@ + withCAString #{const_str ZLIB_VERSION} $ \versionStr -> + c_inflateInit2_ z n versionStr (#{const sizeof(z_stream)} :: CInt) + +-foreign import ccall unsafe "zlib.h inflate" +- c_inflate :: StreamState -> CInt -> IO CInt +- +-foreign import ccall unsafe "zlib.h &inflateEnd" +- c_inflateEnd :: FinalizerPtr StreamState +- +-foreign import ccall unsafe "zlib.h inflateReset" +- c_inflateReset :: StreamState -> IO CInt +- + foreign import ccall unsafe "zlib.h deflateInit2_" + c_deflateInit2_ :: StreamState + -> CInt -> CInt -> CInt -> CInt -> CInt +@@ -1036,6 +1042,16 @@ + c_deflateInit2 z a b c d e = + withCAString #{const_str ZLIB_VERSION} $ \versionStr -> + c_deflateInit2_ z a b c d e versionStr (#{const sizeof(z_stream)} :: CInt) ++#endif ++ ++foreign import ccall unsafe "zlib.h inflate" ++ c_inflate :: StreamState -> CInt -> IO CInt ++ ++foreign import ccall unsafe "zlib.h &inflateEnd" ++ c_inflateEnd :: FinalizerPtr StreamState ++ ++foreign import ccall unsafe "zlib.h inflateReset" ++ c_inflateReset :: StreamState -> IO CInt + + foreign import ccall unsafe "zlib.h deflateSetDictionary" + c_deflateSetDictionary :: StreamState diff --git a/android/user-scripts/cabal-install-clock.sh b/android/user-scripts/cabal-install-clock.sh new file mode 100755 index 00000000..cf0b87b6 --- /dev/null +++ b/android/user-scripts/cabal-install-clock.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +export THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source $HOME/ghc-build/set-env.sh +set -x +#################################################################################################### + +CLOCK_PACKAGE=$NDK/cabal/packages/hackage.haskell.org/clock/0.7.2/clock-0.7.2.tar.gz + +if [ -f "$CLOCK_PACKAGE" ]; then + exit 0 +fi + +$NDK_TARGET-cabal fetch clock-0.7.2 +tar zxf $CLOCK_PACKAGE +pushd clock-0.7.2 +patch -p1 < $SCRIPT_DIR/patches/hs-clock-ffi.patch +$NDK_TARGET-cabal install +popd + +rm -rf clock* diff --git a/android/user-scripts/cabal-install-network.sh b/android/user-scripts/cabal-install-network.sh new file mode 100755 index 00000000..f544e52c --- /dev/null +++ b/android/user-scripts/cabal-install-network.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +export THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source $HOME/ghc-build/set-env.sh +set -x +#################################################################################################### + +NETWORK_PACKAGE=$NDK/cabal/packages/hackage.haskell.org/network/2.6.3.2/network-2.6.3.2.tar.gz + +if [ -f "$NETWORK_PACKAGE" ]; then + exit 0 +fi + +$NDK_TARGET-cabal fetch network-2.6.3.2 +tar zxf $NETWORK_PACKAGE +pushd network-2.6.3.2 +patch -p1 < $SCRIPT_DIR/patches/hs-network-ffi.patch +$NDK_TARGET-cabal install +popd + +rm -rf network* diff --git a/android/user-scripts/cabal-install-setup.sh b/android/user-scripts/cabal-install-setup.sh new file mode 100755 index 00000000..34fc7b2a --- /dev/null +++ b/android/user-scripts/cabal-install-setup.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +export THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source $HOME/ghc-build/set-env.sh +set -x +#################################################################################################### + +PACKAGE=$NDK/cabal/packages/hackage.haskell.org/$1/$2/$1-$2.tar.gz + +if [ -f "$PACKAGE" ]; then + exit 0 +fi + +$NDK_TARGET-cabal fetch $1-$2 +tar zxf $PACKAGE + +pushd $1-$2 +$HOME/.ghc/android-host/bin/cabal configure || true +$NDK_TARGET-cabal install +popd + +rm -rf $1* diff --git a/android/user-scripts/cabal-install-zlib.sh b/android/user-scripts/cabal-install-zlib.sh new file mode 100755 index 00000000..4a504907 --- /dev/null +++ b/android/user-scripts/cabal-install-zlib.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +export THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source $HOME/ghc-build/set-env.sh +set -x +#################################################################################################### + +ZLIB_PACKAGE=$NDK/cabal/packages/hackage.haskell.org/zlib/0.6.1.1/zlib-0.6.1.1.tar.gz + +if [ -f "$ZLIB_PACKAGE" ]; then + exit 0 +fi + +$NDK_TARGET-cabal fetch zlib-0.6.1.1 +tar zxf $ZLIB_PACKAGE +pushd zlib-0.6.1.1 +patch -p1 < $SCRIPT_DIR/patches/hs-zlib-ffi.patch +$NDK_TARGET-cabal install +popd + +rm -rf zlib* diff --git a/android/user-scripts/install-happy.sh b/android/user-scripts/install-happy.sh new file mode 100755 index 00000000..cdbb113f --- /dev/null +++ b/android/user-scripts/install-happy.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +export THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source $HOME/ghc-build/set-env.sh +set -x +#################################################################################################### + +if [ -f "$PLATFORM_PREFIX/.cabal/bin/happy" ]; then + exit 0 +fi + +# +# Terminology: +# build platform: The system platform we're building on. Build platform +# executables can be executed during build. +# host platform: The system platform we're building *for*. Host executables +# can run on the device we're building for, but can't run during build. +# +# We first install happy for the build platform, then for the host platform, and +# then we overwrite the host platform's happy with the build platform's happy. +# +# We do this because otherwise packages depending on happy will try to build a +# host happy and run it during build. +# +# We also use cabal-install-setup.sh to build happy for the host platform, +# because it uses a non-simple setup, so we need to first build the setup +# program for the build platform. +# + +cabal install happy +$THIS_DIR/cabal-install-setup.sh happy 1.19.5 +cp $HOME/.cabal/bin/happy $PLATFORM_PREFIX/.cabal/bin/ diff --git a/android/user-scripts/install-hspec.sh b/android/user-scripts/install-hspec.sh new file mode 100755 index 00000000..1e6ce4e4 --- /dev/null +++ b/android/user-scripts/install-hspec.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +export THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source $HOME/ghc-build/set-env.sh +set -x +#################################################################################################### + +if [ -f "$PLATFORM_PREFIX/.cabal/bin/hspec-discover" ]; then + exit 0 +fi + +# See install-happy.sh for explanation for why we do this. + +cabal install hspec-discover +$THIS_DIR/cabal-install-setup.sh hspec-discover 2.4.3 +cp $HOME/.cabal/bin/hspec-discover $PLATFORM_PREFIX/.cabal/bin/ diff --git a/android/user-scripts/install-libsodium.sh b/android/user-scripts/install-libsodium.sh new file mode 100755 index 00000000..99c8fa09 --- /dev/null +++ b/android/user-scripts/install-libsodium.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +source $HOME/ghc-build/set-env.sh +#################################################################################################### + +if [ -f "$NDK_ADDON_PREFIX/lib/libsodium.a" ]; then + exit 0 +fi + +cd $NDK_ADDON_SRC +apt-get source libsodium + +pushd libsodium* +autoreconf -i +./configure --prefix="$NDK_ADDON_PREFIX" --host=$NDK_TARGET --build=$BUILD_ARCH --with-build-cc=$BUILD_GCC --enable-static --disable-shared +make $MAKEFLAGS +make install +popd + +rm -rf libsodium* diff --git a/hstox.cabal b/hstox.cabal index 35e4e79b..7aaba7f0 100644 --- a/hstox.cabal +++ b/hstox.cabal @@ -43,9 +43,7 @@ library , lens-family , MonadRandom , mtl - -- network-2.6.2.1 is the last version that can be cross-compiled, so we install - -- it explicitly here. - , network <= 2.6.2.1 + , network , network-msgpack-rpc >= 0.0.3 , saltine , random diff --git a/src/tox/Network/Tox/TimedT.hs b/src/tox/Network/Tox/TimedT.hs index 6d2c6c95..ffa5501c 100644 --- a/src/tox/Network/Tox/TimedT.hs +++ b/src/tox/Network/Tox/TimedT.hs @@ -23,7 +23,7 @@ newtype TimedT m a = TimedT (ReaderT Timestamp m a) deriving (Monad, Applicative, Functor, MonadState s, MonadWriter w , MonadRandomBytes, MonadTrans, MonadIO, Networked, Keyed) -runTimedT :: Monad m => TimedT m a -> Timestamp -> m a +runTimedT :: TimedT m a -> Timestamp -> m a runTimedT (TimedT m) = runReaderT m instance Monad m => Timed (TimedT m) where