From c01aa27777de121b618c0f8749946a5d6836168a Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Wed, 8 Nov 2023 20:17:49 -0500 Subject: [PATCH 1/2] Use github actions for testing PRs --- .github/workflows/build.yml | 90 ++++++++++++++++++ .travis.yml | 88 ----------------- CMakeLists.txt | 5 +- pom.xml | 27 ++++++ .../natives/osx_arm64/libjssc.dylib | Bin 52848 -> 36224 bytes .../java/jssc/SerialNativeInterfaceTest.java | 3 + toolchain/Riscv32.cmake | 10 ++ toolchain/Riscv64.cmake | 10 ++ 8 files changed, 144 insertions(+), 89 deletions(-) create mode 100644 .github/workflows/build.yml delete mode 100644 .travis.yml create mode 100644 toolchain/Riscv32.cmake create mode 100644 toolchain/Riscv64.cmake diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..ea85d122e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,90 @@ +name: build + +on: [push, pull_request] + +env: + MAVEN_OPTS: -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn + +jobs: + ubuntu: + runs-on: [ubuntu-latest] + strategy: + fail-fast: false + matrix: + include: + - profile: x86 + packages: g++-multilib + + - profile: x86_64 + packages: g++- + + - profile: armhf + packages: g++-arm-linux-gnueabihf + + - profile: aarch64 + packages: g++-aarch64-linux-gnu + + - profile: riscv64 + packages: g++-riscv64-linux-gnu + + - profile: ppc64 + packages: g++-powerpc64le-linux-gnu + + - profile: mingw32 + packages: g++-mingw-w64-i686 + + - profile: mingw64 + packages: g++-mingw-w64-x86-64 + + - profile: mingwaarch64 + packages: clang + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Java + uses: actions/setup-java@v3 + with: + java-version: 11 + distribution: temurin + + - run: sudo apt-get install socat ${{ matrix.packages }} + - run: mvn -P "${{ matrix.profile }}" --batch-mode + + macos: + runs-on: [macos-latest] + strategy: + fail-fast: false + matrix: + include: + - profile: aarch64 + - profile: x86_64 + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + java-version: 11 + distribution: temurin + + - run: brew install socat + - run: mvn -P "${{ matrix.profile }}" --batch-mode + + windows: + runs-on: [windows-latest] + strategy: + fail-fast: false + matrix: + include: + - profile: aarch64 + + - profile: x86_64 + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + java-version: 11 + distribution: temurin + + - run: mvn -P "${{ matrix.profile }}" --batch-mode \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b62c60ee9..000000000 --- a/.travis.yml +++ /dev/null @@ -1,88 +0,0 @@ -language: java - -jdk: - - openjdk11 - -cache: - directories: - - $HOME/.m2 - - $HOME/.jabba/jdk - -before_cache: - - rm -rf $HOME/.m2/repository/com/github/java-native - -matrix: - include: - - os: linux - addons: - apt: - packages: - - g++ - - os: linux - env: PROFILE=x86 - addons: - apt: - packages: - - g++-multilib - - os: linux - env: PROFILE=mingw32 - addons: - apt: - packages: - - g++-mingw-w64-i686 - - os: linux - env: PROFILE=mingw64 - addons: - apt: - packages: - - g++-mingw-w64-x86-64 - - os: linux - env: PROFILE=mingwaarch64 - addons: - apt: - packages: - - clang - - os: linux - env: PROFILE=armhf - addons: - apt: - packages: - - g++-arm-linux-gnueabihf - - os: linux - env: PROFILE=aarch64 - addons: - apt: - packages: - - g++-aarch64-linux-gnu - - os: linux - env: PROFILE=ppc64 - addons: - apt: - packages: - - g++-powerpc64le-linux-gnu - - os: osx - - os: osx - osx_image: xcode12.5 # xcode 12+ needed for cross-compile - env: PROFILE=aarch64 - -addons: - homebrew: - packages: - - maven - - ant - - cmake - apt: - packages: - - maven - - ant - - cmake - -install: - - mvn dependency:resolve - -script: if [ -z "$PROFILE" ]; then mvn --batch-mode; else mvn -P "$PROFILE" --batch-mode; fi - -after_success: - - bash <(curl -s https://codecov.io/bash) - - diff --git a/CMakeLists.txt b/CMakeLists.txt index ce202316f..528e37651 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,9 +191,12 @@ if(CMAKE_STRIP AND NOT CMAKE_BUILD_TYPE MATCHES "Deb") add_custom_command(TARGET jssc POST_BUILD COMMAND "${CMAKE_STRIP}" ${STRIP_ARGS} $) endif() -# Copy native library back to source tree + add_custom_command(TARGET jssc POST_BUILD + # Copy native library back to source tree COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/natives/ ${CMAKE_CURRENT_SOURCE_DIR}/src/main/resources-precompiled/natives/ + # Copy native library back to target/classes tree + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/natives/ ${CMAKE_CURRENT_BINARY_DIR}/../classes/natives/ ) # Handle compiler warnings diff --git a/pom.xml b/pom.xml index 5229404b5..728a27139 100644 --- a/pom.xml +++ b/pom.xml @@ -279,6 +279,7 @@ maven-surefire-plugin ${plugin.surfire.version} + false @@ -495,6 +496,32 @@ + + + riscv64 + + Riscv64 + + linux + riscv64 + 64 + + + + + + riscv32 + + Riscv32 + + linux + riscv32 + 32 + + + + + x86_64 diff --git a/src/main/resources-precompiled/natives/osx_arm64/libjssc.dylib b/src/main/resources-precompiled/natives/osx_arm64/libjssc.dylib index 188832e1ec09d02471599b12b017b7c489d496a6..d96d06a4860bae41bd5372c9b86f1e2ff24c63ad 100755 GIT binary patch delta 3833 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 +PQV`$d7Z$ z@GV<{VL&$;S8x~<{Xk)DT%QSs2)$&{j~vybkorug7dwErCwmCrc5PoF)}qi z^bIUgk@^k$@{O5CSkhDj`4f|;Mxs|8tDCxzG_g}tvxA)I#UoU(u(Ty)F{@0|5fdZn zI(8r}jpVQ%y1oZq$p1c z#_k*PCHeP!FX2g|STP?nC`D9sN4LbWyXnT?mE&L?fg7;5<;%Yl*mVmBy91%7A`pr? z(UydRG7`?mX@8k@=0YHZ4bY4UcPKQ)-&%j>E*7E19q2*MkD`P}1(S4Xu-{-!(;k(N zV?_9MFs-2C5ASG6%!Go9?02pX4o0gZqWB2Y`{<(p2%p$s?sFJ*xYzHNOJkncdu;sH z4Q@WgD9>rsYuB{~H&g8sEfi`(Sg0YF>}2x{&xY+p+tDsV6E2BwgLbeU!xCaP9&eQrc9kR4!v7xzoGolW>Z1P z%Z`Ti`}SymDLd2h=aDs$M_b~&>y+?)CT)CBL4)ZEX>~+B9TX3eV(J5R3;60q>R~?~ zl&)Zm#kc4?w5d1tXwQu2cbEvYIe?AL$|u*EoRzQlra-Zl7zex~VL%JG-Lb}jz2l)! zhbNbB9qY`}v#VKpa-4-`M@M#GxT9|vn!NeYq&^!WJ%?Flc6{)jaq1mAJ%KIDKE%dM zPfC85pB(kJyM!m`8(dBv@~uEv1~(* z$;}O^(NZx;y7L^5^25DR_w}d!@IgP^=!dKQaG@Vg^~0n5aBrmKzL)rPQd}fqM|YB=FaWUpEW#6_U3FzKHk(fzKiS zT;MLmJpzA*_@=-o5eM*BAXdiPuc{av4uL`J^5ez$*jbR99m>C_ojZb(b5C}dWC5;y7njnxK4hGT}3<2wg1DP2D8dnIwnh>DPBLLb)0Ks=; zc2c{dxfbQti%+S?gv=0frjUg~{$9v(AzeZ$LT(dsw~%c@9u)FDAv=XUtIGCOnrXa} ziBaybar))_H6CU(n-`bLg{xqJ16upVnhcUgpWcT02bEQF<$vl{|GO?6N1L54xun8e zQeI(RSt~nAp#~a_rFFJaG}KnEFt4yymExCZBNoBi|D_I$>(GZA*%3wWZUo18UtJc5 z!_Ma4a{O1a87q_W>r6>yc!?zC`wA(FC^Dwl73F%ql2 zL?z3SRLNC#x6@{^RCC{Q)Yz*nRUB6%c35Ozjx~s#7MrES#Vra!>MAL-)jG>LZ&3M4 zi%WLlhb?LvRSniTq}k0is~uJsuSsph3;`g`l~*xM!`L}6$-HsV>=DRxrd)O`2_x*85rUS(dL%i@I3CY% znpay^W^p)uPWkrQDi@rkvu*a(`SvQ8!)}{rFSWqebfLvzm2Eume7O>%-KI}kt1Qli zIEh*(+@<&qU4ozVyO!X0^fX@Oi&7d2KPMY_X$Gp?bE;gpm$lU{r!SqY&=w-xqZS zKcTYKrN)OJaj@5lKJ^uRNF`p{?0iTyUhdZ5+|wg$kh?y#~X;D4WyH#YTEEArM5q60H!0%nYw2FbO;7 z{nLCDEJIw_cM0ywQ0<*OKOgWgkBY4yJLf}xq>~YIK1SFrg74!0F4&$Iyj&zWBzQf4 zg<$(u@Vg@6DE$B7@my)D-JKy6y&}L$!P^X~!yds~Q&oOka1a6hDR_UTYLCNDcAmg1 z?6U>`P}r9UemTYG9}f*h)%==z<*A4lri>TXN*Yd3G4v+4HpS3?s#?9R63EN;7AUz%}o zQMdDSe#rH=Wt#EYvdPo0hd;KB7HSUMFkZ}Gww604ZcFL<^tI{3pG*AW=Gre`J$wA^ YW5tFm2X6L#`$@8O(JvcM@reNZ3!S9b+W-In diff --git a/src/test/java/jssc/SerialNativeInterfaceTest.java b/src/test/java/jssc/SerialNativeInterfaceTest.java index 6890aab04..ccbd0f3cd 100644 --- a/src/test/java/jssc/SerialNativeInterfaceTest.java +++ b/src/test/java/jssc/SerialNativeInterfaceTest.java @@ -1,5 +1,6 @@ package jssc; +import org.junit.Assume; import org.junit.Test; import static org.hamcrest.CoreMatchers.is; @@ -41,6 +42,8 @@ public void testPrintVersion() { @Test(expected = java.io.IOException.class) public void reportsWriteErrorsAsIOException() throws Exception { + Assume.assumeFalse(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_WINDOWS); + long fd = -1; /*bad file by intent*/ byte[] buf = new byte[]{ 0x6A, 0x73, 0x73, 0x63, 0x0A }; SerialNativeInterface testTarget = new SerialNativeInterface(); diff --git a/toolchain/Riscv32.cmake b/toolchain/Riscv32.cmake new file mode 100644 index 000000000..2b4a5df01 --- /dev/null +++ b/toolchain/Riscv32.cmake @@ -0,0 +1,10 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(TOOLCHAIN_PREFIX riscv32-linux-gnu) +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++) +set(CMAKE_STRIP ${TOOLCHAIN_PREFIX}-strip CACHE FILEPATH "" FORCE) +set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}/) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) + diff --git a/toolchain/Riscv64.cmake b/toolchain/Riscv64.cmake new file mode 100644 index 000000000..abfa3e9a2 --- /dev/null +++ b/toolchain/Riscv64.cmake @@ -0,0 +1,10 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(TOOLCHAIN_PREFIX riscv64-linux-gnu) +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++) +set(CMAKE_STRIP ${TOOLCHAIN_PREFIX}-strip CACHE FILEPATH "" FORCE) +set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}/) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) + From 6eb6600160f163bc3e194bd720e234a0367539e3 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Fri, 10 Nov 2023 12:16:32 -0500 Subject: [PATCH 2/2] Remove binary --- .../natives/osx_arm64/libjssc.dylib | Bin 36224 -> 52848 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/main/resources-precompiled/natives/osx_arm64/libjssc.dylib b/src/main/resources-precompiled/natives/osx_arm64/libjssc.dylib index d96d06a4860bae41bd5372c9b86f1e2ff24c63ad..188832e1ec09d02471599b12b017b7c489d496a6 100755 GIT binary patch delta 4415 zcmcIneN>cH8h`G42OJPokZ*Knup-ewRB-r^7(rdMG#oh|R#(SY7-S9u12cn)YtEaY z;b-7=PnPV0#VMWKj%TT@w2o+{RC+S}tj@Mzb{b1pOiVC~eeS#$oppEr+v$<$iaS@wAMmNpSk-#ST(J&?1=K;G% zs#0lsF*htGM?pL4tN5Z&X&-NTNza1GZz8*e zrCeAz*RUE*JS!&pu!3Aw9VDy;Y%|G?EE3u_q2*lijp--VWE8VX@$Lv=*NCPFY5eb;qMCPH8(%Y)H)~cOa67OkX*Crbh zHjgk4Ts@-fOd=s$wj`4Miqw(Ar_fUd%`hfmzQSfrc_?wS1OqKApl +PQV`$d7Z$ z@GV<{VL&$;S8x~<{Xk)DT%QSs2)$&{j~vybkorug7dwErCwmCrc5PoF)}qi z^bIUgk@^k$@{O5CSkhDj`4f|;Mxs|8tDCxzG_g}tvxA)I#UoU(u(Ty)F{@0|5fdZn zI(8r}jpVQ%y1oZq$p1c z#_k*PCHeP!FX2g|STP?nC`D9sN4LbWyXnT?mE&L?fg7;5<;%Yl*mVmBy91%7A`pr? z(UydRG7`?mX@8k@=0YHZ4bY4UcPKQ)-&%j>E*7E19q2*MkD`P}1(S4Xu-{-!(;k(N zV?_9MFs-2C5ASG6%!Go9?02pX4o0gZqWB2Y`{<(p2%p$s?sFJ*xYzHNOJkncdu;sH z4Q@WgD9>rsYuB{~H&g8sEfi`(Sg0YF>}2x{&xY+p+tDsV6E2BwgLbeU!xCaP9&eQrc9kR4!v7xzoGolW>Z1P z%Z`Ti`}SymDLd2h=aDs$M_b~&>y+?)CT)CBL4)ZEX>~+B9TX3eV(J5R3;60q>R~?~ zl&)Zm#kc4?w5d1tXwQu2cbEvYIe?AL$|u*EoRzQlra-Zl7zex~VL%JG-Lb}jz2l)! zhbNbB9qY`}v#VKpa-4-`M@M#GxT9|vn!NeYq&^!WJ%?Flc6{)jaq1mAJ%KIDKE%dM zPfC85pB(kJyM!m`8(dBv@~uEv1~(* z$;}O^(NZx;y7L^5^25DR_w}d!@IgP^=!dKQaG@Vg^~0n5aBrmKzL)rPQd}fqM|YB=FaWUpEW#6_U3FzKHk(fzKiS zT;MLmJpzA*_@=-o5eM*BAXdiPuc{av4uL`J^5ez$*jbR99m>C_ojZb(b5C}dWC5;y7njnxK4hGT}3<2wg1DP2D8dnIwnh>DPBLLb)0Ks=; zc2c{dxfbQti%+S?gv=0frjUg~{$9v(AzeZ$LT(dsw~%c@9u)FDAv=XUtIGCOnrXa} ziBaybar))_H6CU(n-`bLg{xqJ16upVnhcUgpWcT02bEQF<$vl{|GO?6N1L54xun8e zQeI(RSt~nAp#~a_rFFJaG}KnEFt4yymExCZBNoBi|D_I$>(GZA*%3wWZUo18UtJc5 z!_Ma4a{O1a87q_W>r6>yc!?zC`wA(FC^Dwl73F%ql2 zL?z3SRLNC#x6@{^RCC{Q)Yz*nRUB6%c35Ozjx~s#7MrES#Vra!>MAL-)jG>LZ&3M4 zi%WLlhb?LvRSniTq}k0is~uJsuSsph3;`g`l~*xM!`L}6$-HsV>=DRxrd)O`2_x*85rUS(dL%i@I3CY% znpay^W^p)uPWkrQDi@rkvu*a(`SvQ8!)}{rFSWqebfLvzm2Eume7O>%-KI}kt1Qli zIEh*(+@<&qU4ozVyO!X0^fX@Oi&7d2KPMY_X$Gp?bE;gpm$lU{r!SqY&=w-xqZS zKcTYKrN)OJaj@5lKJ^uRNF`p{?0iTyUhdZ5+|wg$kh?y#~X;D4WyH#YTEEArM5q60H!0%nYw2FbO;7 z{nLCDEJIw_cM0ywQ0<*OKOgWgkBY4yJLf}xq>~YIK1SFrg74!0F4&$Iyj&zWBzQf4 zg<$(u@Vg@6DE$B7@my)D-JKy6y&}L$!P^X~!yds~Q&oOka1a6hDR_UTYLCNDcAmg1 z?6U>`P}r9UemTYG9}f*h)%==z<*A4lri>TXN*Yd3G4v+4HpS3?s#?9R63EN;7AUz%}o zQMdDSe#rH=Wt#EYvdPo0hd;KB7HSUMFkZ}Gww604ZcFL<^tI{3pG*AW=Gre`J$wA^ YW5tFm2X6L#`$@8O(JvcM@reNZ3!S9b+W-In delta 3833 zcmZ8kdstIP7C&=uf{B2D5Cnovd?7wSz(63NL{QiIKsRKqtLr056bb?f@zE`k>}P9z zeF_eK+f~0M`uPXkWz~xA`sh}0twIZ3s;yPm?m}N5uC^bxNJ(AIp1Jp`+0K`9=lsr` zIp@rob7yY)kMN$uTy0d`5(U7U5CN>kBHbbYt5;j+EVI%&5?MD(N0fE8i4o07q6Q>} zOMP?QA95o;nIVDyN*#PscW(?`PF~V<&y*y^@&LmM+NRXfMxu|%%$3BW<i62-N+nCUXE{T-@v z;tyhwJ+~czEh_UZ055%0k*(ah17HeUb*2{OOefnG+%;aGopm;1petB2R^hjtH zTPOe@D)KyoeHS1PncVwBYBV zelvIuL<2Q5wHUaoZpThh@YI0Erw3cNHlZCpYV2fj;d;k97cabS=C z()aU8@NQu^_;iurC>{pZ`+Usg&b4%DT0(3iiW5oo=|-H=!$%4P*Zl>C`j{R}n@(=h zjx=rPKRBrOa6`t%d~;RLI==J|SYFFD*ZAh|am zp?oKY@;~Qcd{LOfNP)=*QGU6`Oj#wdlv~gnt5FZu(7!n-9URpV7m1PSP#%r-CEAEJ z``Q-55|%J#i`l_?nS;d>Eo7kL7tfq!nPq3AM5Sn4o@jvNKM#T>iAOmz!sgS;baR#) zH?r8vGlj+R3v6{VyWre1AHTTQI|Qw%ve4^olYbyob$z;cEQohiF?+% zSvI1DUPnRSw_P{Z;mUC_k-{IT-ME5O&^Duv z)YD#LX+*VbVE}W;H1g=m%qe7ssIitdW#$qcy@!(fRFkE1Pe$!le#lsSVV7lI$T8>6 zn#RMLC+lzYReMG@)~K`%$HE+a(|5+HNK~+T-cHLs;&n!EQ)_|qSa_VvcAn)%qlYG} zzU#3lW4kj5&rXj>Vb=bA76QkeVK~O>4&=JSQoC?cS#O&(}1D{w+ zY`@1#`^~n=GXl=g*(SZh6N*fcNuP9s`3Q#dEFXR2psr8MiALx`dD{t;<-d@%(|1hT z;r|>hogvln^rq>8qK8LIwb_$a*0IWvN)wOC^kP=B=UK_J6Cp}q)$%274husZ3()rh zq@N9fx=YFMux-$9WiM0|CZaFQ?9*YXcErh=&2-S%C^FS)i8t z;c_1=_vjN_I99CGkC1ze0b98Ak%7JR?G)}ADa-Nf6UU?EUL*G4kvjHl`A~V5-Sr1Y zx%CL=A$gJT`VL$gNGm~CC})j*kpQL)%#4v5Tm2JU`V;j2WGqq&e&OKP7FUB*i*yF* z4$=V92m)L@5}q4eCQ<o7S(lJFCRu{EAKGE_iv)W_!7-YLTs~6wZ^mWffcUE6QEYis-UM z6-9PC}&$OFh~LddWU-vkQC2fxFxn< zIBgrN;38+S7D6kotdTkPR^sD|4Ik$i9CD!(TZv0D2Jdsu5|>@d%2znW`zj7oN4q`| zf>$q3g|~T}j8k|6W;S5OWkC51mh9`)e>rB=V^phMg;Vovn~E$pX0c$?#uDh_XWLx1 zyb>2?Rutd|8=PXn47e~6QQe%EkGiW|n4?m;T>a!Lu9m0jwz6**1Qrln`38qy8y56tuS z)4xJm(fc73Uh<; z!B)#}vi`KK{=+kyKi@)9whWuFyQAs&D^v5ooV?_#Z)2QyPTp|%-dJ@d=iwI zj?DaiT=&zo3ES6xKn`8*jZMGKXT`5SnX698Ev56j)+D5Lo3y(Mmt{oQ_fGs_|Ek-< Wq7BCcVe#v=`^W?G(FA