From d46619fd40c4b7574d6dec93320dfb1c71b53590 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Thu, 16 Oct 2025 05:30:52 -0500 Subject: [PATCH] Build: cross-platform building scripts and github workflow --- .github/workflows/build-app.yml | 40 +++++++++++ .../project-impl/compile-all-android.sh | 68 ++++++++---------- .../project-impl/compile-all-mcu.sh | 36 ++++------ helper-scripts/project-impl/compile-all.sh | 25 +------ .../project-impl/compile-desktop-linux.sh | 24 +++++++ .../project-impl/compile-electrostatic-app.sh | 20 ++++++ libs/linux/x86-64/libelectrostatic.so | Bin 47584 -> 0 bytes 7 files changed, 130 insertions(+), 83 deletions(-) create mode 100644 .github/workflows/build-app.yml create mode 100644 helper-scripts/project-impl/compile-desktop-linux.sh delete mode 100644 libs/linux/x86-64/libelectrostatic.so diff --git a/.github/workflows/build-app.yml b/.github/workflows/build-app.yml new file mode 100644 index 0000000..4268bfd --- /dev/null +++ b/.github/workflows/build-app.yml @@ -0,0 +1,40 @@ +# This is a basic workflow to help you get started with Actions + +name: Build Electrostatic-Application + +# Controls when the workflow will run +on: + # Triggers the workflow on push or pull request events but only for the "master" branch + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + build-electrostatic-app: + # runner images with architectures (variants) + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ 'ubuntu-latest' ] + name: Build Electrostatic App + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + - name: Checkout Job + uses: actions/checkout@v3 + + - name: Setup Electrostatic-Sandbox Workstation + run: chmod +rwx ./helper-scripts/setup-environment/setup-sandbox.sh && ./helper-scripts/setup-environment/setup-sandbox.sh + + - name: User's Permissions Granting + run: chmod +rwx ./helper-scripts/project-impl/*.sh + + - name: Building Electrostatic-application Executable Binaries + run: sudo ./helper-scripts/project-impl/compile-all.sh + + - name: Testing Electrostatic-app ELF + run: sudo ./build/linux/x86-64/electrostatic-app.elf \ No newline at end of file diff --git a/helper-scripts/project-impl/compile-all-android.sh b/helper-scripts/project-impl/compile-all-android.sh index b375f5f..aa656c6 100644 --- a/helper-scripts/project-impl/compile-all-android.sh +++ b/helper-scripts/project-impl/compile-all-android.sh @@ -1,40 +1,34 @@ #!/bin/bash + +# pre-compilation automata source "./helper-scripts/project-impl/variables.sh" -PRIMER_SUFFIX="${1}" - -## -# define source modules -# The suffix 'primer' swaps binaries with -# the original project for testing purposes! -## -electronetsoft="$(pwd)/electrostatic-sandbox-framework/${source_dir}/src/libs/electrostatic${PRIMER_SUFFIX}/electronetsoft" - -platform_module="${electronetsoft}/platform/linux/" -comm_module="${electronetsoft}/comm/" -algorithm_module="${electronetsoft}/algorithm/" -util_module="${electronetsoft}/util/" - -./helper-scripts/project-impl/compile-electrostatic.sh \ - "${COMMISSION_LIB}" "${CLANG_BIN}" "${CLANGPP_BIN}" "ON" "ON" "OFF" "-O3 -fPIC" \ - "--target=${ARM_64}" \ - "${electrostatic_core_headers}" "${platform_module} ${comm_module} \ - ${algorithm_module} ${util_module}" "${NULL}" "m;c;dl" "${source_dir}" "android" "${ARM_64}" "${POST_COMPILE_TRUE}" - -./helper-scripts/project-impl/compile-electrostatic.sh \ - "${COMMISSION_LIB}" "${CLANG_BIN}" "${CLANGPP_BIN}" "ON" "ON" "OFF" "-O3 -fPIC" \ - "--target=${ARM_32}" \ - "${electrostatic_core_headers}" "${platform_module} ${comm_module} \ - ${algorithm_module} ${util_module}" "${NULL}" "m;c;dl" "${source_dir}" "android" "${ARM_32}" "${POST_COMPILE_TRUE}" - -./helper-scripts/project-impl/compile-electrostatic.sh \ - "${COMMISSION_LIB}" "${CLANG_BIN}" "${CLANGPP_BIN}" "ON" "ON" "OFF" "-O3 -fPIC" \ - "--target=${ANDROID_x86}" \ - "${electrostatic_core_headers}" "${platform_module} ${comm_module} \ - ${algorithm_module} ${util_module}" "${NULL}" "m;c;dl" "${source_dir}" "android" "${ANDROID_x86}" "${POST_COMPILE_TRUE}" - -./helper-scripts/project-impl/compile-electrostatic.sh \ - "${COMMISSION_LIB}" "${CLANG_BIN}" "${CLANGPP_BIN}" "ON" "ON" "OFF" "-O3 -fPIC" \ - "--target=${ANDROID_x86_64}" \ - "${electrostatic_core_headers}" "${platform_module} ${comm_module} \ - ${algorithm_module} ${util_module}" "${NULL}" "m;c;dl" "${source_dir}" "android" "${ANDROID_x86_64}" "${POST_COMPILE_TRUE}" +source_module="${app_src}/" +electrostatic_sdk="${app_libs}" + +# compilation automata + +./helper-scripts/project-impl/compile-electrostatic-app.sh \ + "${COMMISSION_EXE}" "${CLANG_BIN}" "${CLANGPP_BIN}" "-O3 -fPIC" \ + "--target=${ARM_64}" "${NDK_TOOLCHAIN_INCLUDES};${app_headers}" "${source_module}" \ + "${electrostatic_sdk}/android/${ARM_64}" "m;c;dl" "." \ + "android" "${ARM_64}" "false" "true" + +./helper-scripts/project-impl/compile-electrostatic-app.sh \ + "${COMMISSION_EXE}" "${CLANG_BIN}" "${CLANGPP_BIN}" "-O3 -fPIC" \ + "--target=${ARM_32}" "${NDK_TOOLCHAIN_INCLUDES};${app_headers}" "${source_module}" \ + "${electrostatic_sdk}/android/${ARM_32}" "m;c;dl" "." \ + "android" "${ARM_32}" "false" "true" + +./helper-scripts/project-impl/compile-electrostatic-app.sh \ + "${COMMISSION_EXE}" "${CLANG_BIN}" "${CLANGPP_BIN}" "-O3 -fPIC" \ + "--target=${ANDROID_x86}" "${NDK_TOOLCHAIN_INCLUDES};${app_headers}" "${source_module}" \ + "${electrostatic_sdk}/android/${ANDROID_x86}" "m;c;dl" "." \ + "android" "${ANDROID_x86}" "false" "true" + + +./helper-scripts/project-impl/compile-electrostatic-app.sh \ + "${COMMISSION_EXE}" "${CLANG_BIN}" "${CLANGPP_BIN}" "-O3 -fPIC" \ + "--target=${ANDROID_x86_64}" "${NDK_TOOLCHAIN_INCLUDES};${app_headers}" "${source_module}" \ + "${electrostatic_sdk}/android/${ANDROID_x86_64}" "m;c;dl" "." \ + "android" "${ANDROID_x86_64}" "false" "true" \ No newline at end of file diff --git a/helper-scripts/project-impl/compile-all-mcu.sh b/helper-scripts/project-impl/compile-all-mcu.sh index ab42f38..a3e294d 100644 --- a/helper-scripts/project-impl/compile-all-mcu.sh +++ b/helper-scripts/project-impl/compile-all-mcu.sh @@ -2,28 +2,18 @@ source "./helper-scripts/project-impl/variables.sh" -PRIMER_SUFFIX="${1}" +source_module="${app_src}/" +electrostatic_sdk="${app_libs}" -## -# define source modules -# The suffix 'primer' swaps binaries with -# the original project for testing purposes! -## -electronetsoft="$(pwd)/electrostatic-sandbox-framework/${source_dir}/src/libs/electrostatic${PRIMER_SUFFIX}/electronetsoft" -electroio="$(pwd)/electrostatic-sandbox-framework/${source_dir}/src/libs/electrostatic${PRIMER_SUFFIX}/electroio" +# compilation automata +./helper-scripts/project-impl/compile-electrostatic-app.sh \ + "${COMMISSION_EXE}" "${AVR_GCC_BIN}" "${AVR_GPP_BIN}" "-O2" \ + "-mmcu=atmega32 -D_ELECTRO_MIO" "${AVR_TOOLCHAIN_INCLUDES};${app_headers}" "${source_module}" \ + "${electrostatic_sdk}/avr-mcu/atmega32/" "m" "." \ + "avr-mcu" "atmega32" "false" "true" -platform_module="${electronetsoft}/platform/linux/" -comm_module="${electronetsoft}/comm/" -algorithm_module="${electronetsoft}/algorithm/" -util_module="${electronetsoft}/util/" -electromio_module="${electroio}/electromio/" - -./helper-scripts/project-impl/compile-electrostatic.sh \ - "${COMMISSION_LIB}" "${AVR_GCC_BIN}" "${AVR_GPP_BIN}" "ON" "OFF" "OFF" "-O2" \ - "-mmcu=atmega32 -D_ELECTRO_MIO" "${AVR_TOOLCHAIN_INCLUDES};${electrostatic_core_headers}" "${platform_module} \ - ${comm_module} ${algorithm_module} ${util_module} ${electromio_module}" "${NULL}" "m" "${source_dir}" "avr-mcu" "atmega32" "${POST_COMPILE_TRUE}" - -./helper-scripts/project-impl/compile-electrostatic.sh \ - "${COMMISSION_LIB}" "${AVR_GCC_BIN}" "${AVR_GPP_BIN}" "ON" "OFF" "OFF" "-O2" \ - "-mmcu=atmega328p -D_ELECTRO_MIO" "${AVR_TOOLCHAIN_INCLUDES};${electrostatic_core_headers}" "${platform_module} \ - ${comm_module} ${algorithm_module} ${util_module} ${electromio_module}" "${NULL}" "m" "${source_dir}" "avr-mcu" "atmega328p" "${POST_COMPILE_TRUE}" +./helper-scripts/project-impl/compile-electrostatic-app.sh \ + "${COMMISSION_EXE}" "${AVR_GCC_BIN}" "${AVR_GPP_BIN}" "-O2" \ + "-mmcu=atmega328p -D_ELECTRO_MIO" "${AVR_TOOLCHAIN_INCLUDES};${app_headers}" "${source_module}" \ + "${electrostatic_sdk}/avr-mcu/atmega328p/" "m" "." \ + "avr-mcu" "atmega328p" "false" "true" \ No newline at end of file diff --git a/helper-scripts/project-impl/compile-all.sh b/helper-scripts/project-impl/compile-all.sh index abb610a..98a4feb 100644 --- a/helper-scripts/project-impl/compile-all.sh +++ b/helper-scripts/project-impl/compile-all.sh @@ -3,26 +3,5 @@ # pre-compilation automata source "./helper-scripts/project-impl/variables.sh" -source_module="${app_src}/" -electrostatic_sdk="${app_libs}" - -# compilation automata -./helper-scripts/project-impl/compile-electrostatic-app.sh \ - "${COMMISSION_EXE}" "${GCC_BIN_x86}" "${GPP_BIN_x86}" "-O3 -fPIC" \ - "${TARGET_x86_64}" "${TOOLCHAIN_INCLUDES_x86};${app_headers}" "${source_module}" \ - "${electrostatic_sdk}/linux/x86-64/" "m;pthread;dl" "." \ - "linux" "${x86_64}" - - -./helper-scripts/project-impl/compile-electrostatic-app.sh \ - "${COMMISSION_EXE}" "${GCC_BIN_x86}" "${GPP_BIN_x86}" "-O3 -fPIC" \ - "${TARGET_x86}" "${TOOLCHAIN_INCLUDES_x86};${app_headers}" "${source_module}" \ - "${electrostatic_sdk}/linux/x86/" "m;pthread;dl" "." \ - "linux" "${x86}" - -# post-compilation automata -mkdir --parents "$(pwd)/build/linux/x86" -mkdir --parents "$(pwd)/build/linux/x86-64" - -mv --update "$(pwd)/cmake-build/linux/x86/${COMMISSION_EXE}.elf" "$(pwd)/build/linux/x86" -mv --update "$(pwd)/cmake-build/linux/x86-64/${COMMISSION_EXE}.elf" "$(pwd)/build/linux/x86-64" +./helper-scripts/project-impl/compile-desktop-linux.sh +./helper-scripts/project-impl/compile-all-android.sh diff --git a/helper-scripts/project-impl/compile-desktop-linux.sh b/helper-scripts/project-impl/compile-desktop-linux.sh new file mode 100644 index 0000000..feefdc0 --- /dev/null +++ b/helper-scripts/project-impl/compile-desktop-linux.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# pre-compilation automata +source "./helper-scripts/project-impl/variables.sh" + +source_module="${app_src}/" +electrostatic_sdk="${app_libs}" + +# compilation automata +./helper-scripts/project-impl/compile-electrostatic-app.sh \ + "${COMMISSION_EXE}" "${GCC_BIN_x86}" "${GPP_BIN_x86}" "-O3 -fPIC" \ + "${TARGET_x86_64}" "${TOOLCHAIN_INCLUDES_x86};${app_headers}" "${source_module}" \ + "${electrostatic_sdk}/linux/x86-64/" "m;pthread;dl" "." \ + "linux" "${x86_64}" "false" "true" + + +./helper-scripts/project-impl/compile-electrostatic-app.sh \ + "${COMMISSION_EXE}" "${GCC_BIN_x86}" "${GPP_BIN_x86}" "-O3 -fPIC" \ + "${TARGET_x86}" "${TOOLCHAIN_INCLUDES_x86};${app_headers}" "${source_module}" \ + "${electrostatic_sdk}/linux/x86/" "m;pthread;dl" "." \ + "linux" "${x86}" "false" "true" + +# post-compilation automata +# true, See, the compile-electrostatic-app.sh diff --git a/helper-scripts/project-impl/compile-electrostatic-app.sh b/helper-scripts/project-impl/compile-electrostatic-app.sh index 62c2513..f9d1145 100644 --- a/helper-scripts/project-impl/compile-electrostatic-app.sh +++ b/helper-scripts/project-impl/compile-electrostatic-app.sh @@ -18,12 +18,20 @@ BUILTIN_LIBS="${9}" SOURCE_DIR="${10}" SYSTEM_DIR="${11}" BUILD_DIR="${12}" +DYNAMIC_LINKING="${13}" +POST_PROCESSING="${14}" # precompile scripts sources=$(find ${CODEBASE_MODULES[*]} -name *.c -o -name *.cpp -o -name *.cxx | tr '\n' ';') if [ "${DEPENDENCIES_MODULES[*]}" != "${NULL}" ]; then + if [ "${DYNAMIC_LINKING}" == "true" ]; then + echo -e "--------- Deferring Linking to runtime ---------" + dependencies=$(find ${DEPENDENCIES_MODULES[*]} -name *.so | tr '\n' ';') + else + echo -e "--------- Performing Static Linking ---------" dependencies=$(find ${DEPENDENCIES_MODULES[*]} -name *.a -o -name *.ar | tr '\n' ';') + fi fi # compile scripts @@ -32,3 +40,15 @@ compile "${COMMISSION_OUTPUT}" "${GCC_BIN}" "${GPP_BIN}" \ "${TARGET_MACHINE}" "${HEADERS}" \ "${SOURCE_DIR}" "${sources}" "${dependencies};${BUILTIN_LIBS}" \ "${SYSTEM_DIR}/${BUILD_DIR}" "." "${SOURCE_DIR}" + +# post-compilation automata +if [ "${POST_PROCESSING}" == "true" ]; then + mkdir --parents "$(pwd)/build/${SYSTEM_DIR}/${BUILD_DIR}" + mkdir --parents "$(pwd)/build/${SYSTEM_DIR}/${BUILD_DIR}" + + mv --update "$(pwd)/cmake-build/${SYSTEM_DIR}/${BUILD_DIR}/${COMMISSION_EXE}.elf" \ + "$(pwd)/build/${SYSTEM_DIR}/${BUILD_DIR}" + + mv --update "$(pwd)/cmake-build/${SYSTEM_DIR}/${BUILD_DIR}/${COMMISSION_EXE}.elf" \ + "$(pwd)/build/${SYSTEM_DIR}/${BUILD_DIR}" +fi \ No newline at end of file diff --git a/libs/linux/x86-64/libelectrostatic.so b/libs/linux/x86-64/libelectrostatic.so deleted file mode 100644 index bdbdcef2e2de347c9febe4bc88b5672802a0e16c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47584 zcmeHwdwf*Ywg1Tj7zpGH3L2HlfKh`ACWxA-$V?t^f&n80MNuaqnIWl@%ycpX!3RW> zP^LpPt=QUDZCbUZuUl?w6}=TF1bJyS;)`lqBUkN&pavh5w(9)8YwxvZ&J0Q0dvE{f z=kw#h%sTtK*Is+=wbx#IpMB2BtS_sWpPrVcsUt(XQcI*X&CVJ9zf>HA6>4MgJw-c1 z@Mb2mjysE-At6OIt4vcJqv+H|UpQ>yJ5C+NGOeh&oT$&o{3&$XX%bh|Ty8Y7j82(v zJeW*dxDl?i!RMJ^$H*o2M<|`bM(LHr8KJZmwwCBveM~ELgluTeP?SfqTA{d-B&D zM{2gb?6o_}uAEA`l;AT3AF|6>d@?6Z-#Io-vs+s4v)C-B-}QsOZ)}{PbQw1oOkWr`e1$ecOG~-{Qkz%Ry@6Z z^4{LV=NZp^(LQ%l=F4?oT${7ui8J-dWUt|lRygiS!(`;a!H2_lf_FIld zVdQ@dY~nEZGGN2WiKGvYV+;+;|G)_NBO~bfJp|$5>ZK`RIQ;Vw@Qowb(=q}-V9hp+ z9nwdTvvUMHY#u>>>j?GUGlKlTj$nU^5yR=(GJ>4>;Gd39>T%8p_Ma*AAFuWCz<-Df z&J_BO*ZMg?J1&(LUySBdiZk``W`S-^cBx{-DFpc>d)weGb>VSJ{E(Oq1D~ zlk2TcsdokQ4{>{EG5@z!KXQ9FG5#B_H^TZTyRGH++PFhTGym^dzL-RS>5RY5{CyNC za5z~1D;RHOyPYDlwJEGmHBBlw+|2(Lx2u~ShnHvCcNkZbR<10j(L6-{w)HFtDEt(z zcZeo59K1Zz-od%x&l9k=4SaN@EBo+-r~F|7+h;2qavJXJ znJmZ0_Niig9VoTS#_dx4pDI0BPJsCjuzf1IURuM@@dJEFj>dLY{l1OmRI(k^+T$6< z)nY{9-()@Q?1!Wu9rrPRgcdS5c-Uwy+>c$fD8cclBw9P$$H(IZV#U#;_^W05kCJG! zSiY6{X{|*^JwDW~{~H5V{szkz3pZewFkYLK94e9O$$XFKa@l}o!e_?|H)$fRMykS^NXADy`aKB*{_s; z{+i`mt0m)F=Kl%n8DTwDoY9=lRgK;zXLF#&A8OAal z9xqIXWb@ia(c`k)-F|PQa8YNS$K!<8tVY+s1GJjvW)}u*0Pg7wVx%>j5e>QuROD-Z zSEF~e%LF84Hy@YZthv4ZTb$4pwy1SA%QPYdRBiG)F)yifB zS&-Ay;C9unt%ZXMe?J~~iWd8PUNp|{^0;bXqXutnz@te_3|cY-My02DIMBJWA;7rb zRa2MBYsQjTWx#XR!5^SzlPg&`!AZ3VzLcs=Oro0Mc;NGappq@PBx2G) z@uD^GIK)?Bo?1^$gY*@NVo)?90wXe+m}IoUSY26DdrPzCX;|4ftJyp25<07mpTW?z zFequ#K&ZB$qP)1oIeXUZOB1KFE>4^m#ZNDqgBd0r`%9Vlq~Rmah|<4NA}Kn7u;A$pV`)cpI;TS-KU159G#%8ozi@d< zOa6>F|6_tbT`OXKwZEy>yLMg}RX#|i6W381dZvx*|mFyXv}5O}2tKRYf3dt@eDtw|}n+Jy7cPL!%Q;k?urxX*;&ED-tCV#13} zc&iCF@84`R;TM_syG%GQK}GKUCcM_f-)+L3CVYzt=cTX6-D<*l2`%t#Cj4TPoQMgZ zV#4>B@H!LTXToz#_yH5nmzE;8--MrT;@7%mVho5{;}c@(rf*Fn981yoVeOWugk$L% zKXSU|Dd8D$RMTuG+%VyJCj5F6o^Qgjbd4W{CYllYiB~1chk4z$3TxC)!p)x_-DsaTnCx(aVFen!qr-yvRh2}cmnun?UpAbe*$Af zHg?Md;pfOx@!i!e6NIa4Tte>erf;dgE>FdGcehLsKgBV1Z0VL~gwInT=+6Qt?3+1W!-qS4;gr6@@#dlw~Ob|}@C)9DETb>bKEl_;c9P& za&k<#x^^@bJ8^o#0w*kR!UF$e3m9#OEk<}$a6P89jz}Oq)@QWswDiX1#4g^4tk~Jl z<6EC<#~G#TDSx0phU4rVlun~`pGZGNX_~qRA|m}uO4F1*uvMggLTQ?M2f9W22b3N~ z=`NA}4y9>{IM6E6-=H*w&jFuEe~r>K6%SO4^j(yuDRrPyq;I7(O_>9Bk@i!XrpkeQ zk^VBJX^I@MiS$ZJPoT6_q;H@!O??BJNH3u@O?d-DUjR6JA*E@m8|WA5VoKAJaG+15 zFQYU~Z37XJo=s_*(gwDQ^m&w~scE2Fq^DDwrk;T=kv^T$H02Dmiu6g8rm1GYC(`36 zO-r(YYLQN-G)*A`l_LGubx6|^Y``wkA5og7l7W1YK169+0uI)cB5 z^lo6h5uW=6bc)uX)zLb9?HbhyzO&Z3gZbNu-}+DRf2@16@tJQeh=5#cGj=Z!%OZWEu1~zqrcYd8 z?RC3n=~LUOKCP?cXkdKX7iod1y|UdfR0xeSLX)2Y8TdJ>6nX$JkoZc%?~CIdvA{(J zq|7qHV<Ab2R|%`pka1x8%2a(cb9$Rl|T{-8IX6D z(Kb&Dj3T_NZM`Kea5}pCW!TUNjS{?K+FFhwxjg!jJ`qsx-9;Vm=F2rnMF`^4e%nr&nji`s`<0&~ z2|h$;Xc;^LIcN`RsLIX5cSWu(`i;NFVt}i1QEb)@{cH2k1A0dhzJY=PXhp8|De4#f zI}yEXM|(u?I2}p1p7&Q#Fb^!RC-S}kC-B>It-^`JrMWq7{la6rP<{hV5CxI4f>=eT zCwHE-~K6 z8{w+l91?e5#L>1JMW3~lx9zfg4CdZAAn;bVgoV^&j zqp^KZ5Q+BwMP>^}G;wf$Kq0QKj=DXrTEG6)u@F3PqX-G`S5!}oNh*jAfs$y#E)Cfi z?$I}V1qDQ11OJJz3yujP1MU?bExOk-@FYegq0K-AWF1%`@#9J(e5%p0 zKaj6KKH3yN^vB1c3pekWwy%A!zPX2TrtKNqw-H`*9RkY!;2%Xqh{uDZ@n1;8KU9@F zMGW|bndAmz%0pj>;dVJC#c(R1vyQ!bd!B%b5GX3(RqdyV0$(axt!YouHSl&C8}I;n zHo*vIMTd^XV&%2#a<)_8C=Y!Wjr}dH9ry zPzx4(CmG>MhXgsv2wBU+^DPwHCm3O|3LI4t`ZE@S=2lgN{sb3Ji~b%}J5Y5|bp0bj zcC9BjN3_Q1c^6fjx4TUE9cgwO!Wgy0ia4PrBodlyYVBs2DEd_hEpNLLqrVYFgn_`P zw>yz~imvWe&)iMi*9#S{&FR>$-#r%`i0nBSJTb>_@U_0+{n8L3(W20YWubT7UFGBu zhs%53$uz?G6>0B<*NyLp1>NCmVFa?O2NGdX*HJR{7_@(WxXxxND>{6~*~%&>8)3VZ z%rnji2Xd{#HX*cH$fx$uKBUsHlr($-(j4JybI4*vhxB{aKry2hYAyVp(ag-eh2hNp zaHZu=Oa!s@fd$gB3oAnXqUmYJ!oKkxM}rp@XH?CzTwZCp-nKKXwCL^i-y*x_P_%Uvy{K=Z^$VKawzDuPbR!<4=-`3G_)yLx7Vj8+x0k?n zuYV$9e_?9ur_P>%ma5MFuoTSuz+4a+yjP9}bTW^%-F7h$3L*nRv^ehnh=(hdVzp$Y zg(6ynxCrwU$~YS?5#0)l+ijGo8=<#oAeO){h%5TwM-**tvqm@L1T$B!RFM{U?bHV< zPMYJl-u^T)XxUUA`dqA>#7a(Y7o8XSRIHyifhByM1zp#%f1N*JpT*%h{fiL3D=@(d z-_uJ&2P;BHD?%T}`W)e97O>~jl+X2-hv)o}!aWw4WBr@5(+;j1 zM@}&K0Ilm*6hwFymh0jbqG1Y>vl8)Nyb&6oE9Rd& zDVWnVL(c}n)JE+GVxADwN3{0{B24WaIoruAFe#w_dudMjDe%%zE!HQP7K~7a5&qH^ zFU~0bg@iqUEIAq|7mhR+Z=T^2kU{&v#BQ07O-PMsNGHW~-#DQ#d#tgX_b zJ4kj>FlYVGNG5bF4KKHpb-bzHeKmq~DW+-!z6wm3MvUFhVlZ*2Cx0M$i#sp)9A&A=Xu~mTL$EY#OeyQw8}y*%Xbgq= zJ0TM`xOIq31uX=3UTL^Kr>yARJI?OP!D-1E$N7u$RDaZU- zTJ*vCueISKD-DC!QZ%G*qLnZrdrs2AUBw^DkTEf_s3$*>5_}dVBmg0UPrAF2i7h@p{o9ss{4=+LR*&i4k z+b<(}Vf2N=9L}Gmliela3YEfoJf5b;AKA7@z>$P9FrSd?&p*f)-gYxEUyP~ zS(|1Q_37>RQqJXbdV=p8mzPxPZC|H!QC~CG&80mSqjSzna$f=t7209!MlSMk5p0Bv zA*1M{;Crwk#*)ttZ_1}ZTR~P>ASTSYWP{-OM)+j1_eDndD#LB)O*@Rvz`kQf+dvwn zUNAy{bx#j=V{&LWrj@Fo=T%!Vt>Tmj_9azH&P!_dp#p2GLaMPCGZA&dWk&eM-24ix z5bc{R=y%{DIm;dMxUAGcXmxDmuq!P`Y4m zMUf^hxM0$>edR?x!NcWPWG)V8z6LSD7t4$G3tK!zwp^i??&wWYAkqIv_019L>&-ou zJ;6)J6a_~3YNLWC=e>cc==$*#H$}hq1oZOD=R~m25pNIKo1IG73+0QbJ#&N`VKs~% zoDLzn*?)FmG?DK}zeLZ-epAkwn6A4ZO1dRBjNp^B+f5!z%Nh$rlAspDxLsm+;PkZEyc(xvB^Quw$rkLwgB77wB)k>U62B?V&16CqjFi>(~&2} zIeheFxG5&R{Q*=VeHB;2M+3O>l8ZZIuw8WP;KT4~sFToP;C5J_!DmHvWJV|__QKg0 z60IdWQ+w&9i{$oxNUDaj#q#7;agH(C*<^uz_6Ke=!WY596NLRmKkW#tGK$9ULO+SI z`4cLEu{i_g*oCoK@fxM>e%X z$qZsGHo{BAn2pfJ32N-axIHAs?Ot?8eB2u0MVRmR>K$`nDA7NIKNN#@@O#pv_p_1W z`cm&djP?k3xO@#F&)vcvOARAD&nSAW`CK&e&lG@Om--AFe_k`iA9(Bn*|D_C0p*Jl z?W7=d8zi4>bY6|^&8vi0ord=8J0>C$eeF#IA)#za*fC8mqJN=(1Nv94=RXzedFu1? zfEnRgM#uYl`x~lOV;?h4n3T0`J8{h9-eMbOClSd*GVXLfS~^tlEQdQ-X1`)K=cP zIITSF`7O%6A894q7vmOqD+L1F4~XyWqx)dbCxl_)-v5CUdC}Z86Ji0F?mxm)8>l%zP_)H{l z2h(8Ku#%1)MZ$$~Wr`tMZG;U3AnZJeW(6=|i6+rPrwId9a$RQZE*6^&q7|flM==Qr zUcVX4O|+E%7K%Zzrv%6YEt^91rL}|-wgdX_szf;-z*e348{0v#; z;VHRB(Z_)XqvOrs*uj-pzZd->kgKeHv!e~$X=!Ut$F=oSX!!adcKw#akZ%TGUlHoV z6+tiVCzV&H=)d)1*bY zgKK_IoZkcsz8TCKoX!0f>NSdPvf$oZ=#RM4a>QO$MqAi+2TV3K_y@QuOce>fA{<`M z&vavi=jBlosWmnTSN-0CM|8JW7Qi8EG`dYwTlHOwaq$s zv9d?HQS^fUTyAtA&k=61w#CxcET(x3Cu|Q{EMXFIAWN$13oep|c&49K7r{)8m*3r# zVmCXpcM-c9n!Vyotzb><#mYKDqlDJiddE1phKP*xg05`(KC*^*jDwplH~eJt^>&)H zVFF`!I!=UT=3pPCXb9uyG8#X-=mJS@C)YS+3|dow`!Hz;M!|mN6t9a#nyFo(%i?YV z2Z0}qI&x!5JD1~uM)Hp>Z=szujs~9r+dg75523Nlb|=^d@0Vr(-w#sx-Y$^ht|xJ5 zO6%ZVJaQ7#O_#6@z5K-!iCptbLk*!2E=$N56kI6k$emZc{atY`wiAmA_KS;EwZ4B% zzqhA-Z{QMP30fLZ*Qpm_hE1B$bJehL^~0x=Et4$cAVkzh~`GU;~wZ8AE0_WJ@_jJtKR+zvUmcNt4lSH zzbVS_JTAsN&EvGMrMG{d@d@Ci@98UAOn8)StSimiSJ*+pG_d|*n82VkSsFm^} zPH(?KB*e6>w=bdu-B6NObbWNg#v+WQ=0iCJUz##eBe2Mc`b_ggJyA{6@%zK*k0idDwC?UH|^cQV7 zihep7C&LVs56F-zkn(+ku$)}vg|oO_27z;~v}%mbeGg?hkqJ zIn@5;sqLT1?SE5xVc?mB2a-R>hgT`_jar*pejAt1M|sie!M$KxLTonFtIYHyvyCM- zG41~#x(N5S5=(xP-*Hr2DTe+mw>j+k=3REnklt~ou;H6}`(!%l994pnMrdIR*5UVK z^<#vJD}grhk{rwPi_>U*jV1mb;FB?Uz`32S6LuFvGrBYH>7ndCWS@eSJ@9J6^@+ve z3Sd{kQOZ65J}mx6{kLQ>Bulzj#3QR0#qziqZZQGvOE4rgYt0A;uE@ z_3zm9*vgF0WpaOq_lq2`XQ?F;#1(5SFat|_)Or$@)4|CDTcDQm?}0NQ3G<7b7TjH; zKg}|i_n1(% z&D%qrrO(0mh5SX{uwr; z77cuX6SFwGrk^t5+vmYaZ|*^JFEYYtcL(fA2a$D4rGcb>;H}z)R-nw^B!V7x_o&X>3i@^9Mh1^~G zuD$(a>A3wVeaeJa5i_U{yWCXUXCLbq{Do`}EiXWl-TS3){~4Zo!H&>tIDyS};e&2n z*{iRhhyGe=L;iZ{XCC7$EMS|=7boAzhJ>#=}{1x|}Tf+mEXjXsFS z0EJP% zb2=x#4??~vT$`qe3s5=DEJkR7RVboQ924Je7xNpejUW#f!*@k)j$+a$UTsxZBZ&^{ z5~haDFC|mVHt-}6sXGJrghM45gtBq*=ZF&R7q_&iK2!VAUwEh{rTxhh2Ik)w*;DSX zkHQvhtl!ujAw$8Xg#Jfy{ST(8Mi`r~F>GpfPCnxtRD_MXo@k~~&}S6Qw+6;g$N~Sr zE$|4F38_e_l7BfypCRu%;DV_0;_tzD^jw_{^+6z>wZv3Oj}Xwqq?q3E8e zP1W^x<^6)h{LkfmSs0zx)@+9*2ChA{z*QhQ8q{xFZ_@&E$v9Y_Hs=|k-La)&J|+7v zmG?uTB%V3$!ZT}lVgaZP*BIj^Nb`tXC%wVbYof!cJ+SZ5B>VnX?#T8%|D|O6;&JTI zYb0eR42vG$PvYUebBJWpFCT zwes+!Ts$g*$24|Y--<1h!Gl|eaa0j@Vd)E2mWN=A zSipd}>I))Iju*23WQ5-P*!U^J-RB|#xgyit?S0n>8?`!ak%OZOV4{_?E2%o z@bH_ZVr;Zbf1I8<<F?JvL2&ovmgNQNquabNu$v!M&nZp>11Rjhvb?oZ~o2nE~jmB*y*8xbz`_*K> zy4Rko%@SaW}%1Ot7ZBlKxO zL|8Ezfka`xmhw_tW0K~L$(pMz47$Eb_QzCxca@>ZtaESlk9&m9Qlxrp*8~4*=9@6#Y5!6DaAvyIpTqbR=7l5 zmp?_9NL@~roMb;dL$E(p|Nk%J(*_lv{$uxW@yU)SssHEk>EJHW_ZhPAzbHPDrt$cs zDQ%PD(|5=NDVqL+_*5+QyG649%i>dqDLy$-#lLfWx(*8?VXA*ceEMjo>~AUa{}`Xh zicuS$ogE=Qxk{2W|KG-^E2Yk-N@+@Gb9_pyP~vmaUl3MkP7?QHaGfotr8`aCUJt3< z?LPJ0k0{#AGlyljhNI z^A(tCZidF#D#2`n`y=upBs>;-@ou{`;C_^&2~kWp?PR{V{T_=R>=C+rSMmz`eGmJ= zX<#zV_rkxR!kX}cLacqBrfgJqNi>YA!?zVi&qtF&&$dT`xE@U`89Ss@x_-tpOSt@z zTQ|Hs$90NYhrJcOLF%zo>4A0mAhrwnc{owwicnNu2HI)=LT~>TlrXOs<%~Qgywr~8 z4kxg?aC&NS;bKUKG`gkIC7UT3A~HAsz2T-OMD zy$E}$jkv-)*W2kvA>IS;oLhwp(r6KN0N(7O=f8XPCuS}Kh$nksGqTeBQWS@)H)8@;$l!f)~h4hsdi{8rl<2ZjD=bt3XXUYB!y@y=zTd;qFEuUCS zixzV^+~5;(&x~m?5_ygmJ=d(EyzXE>732Fh9xgW3G`#;jckRh&+RbF6ww*S91e`)Y zG(QDW&lDR+r-+*OfJ=X3)J-Tsb%SF(+LcXuyJ<~_#6(I&zh@FRLVwe6#WRZZ+EVA_ zsd(W+?ge59;E^tif#-g)bBIUnv8T~WGG#kZF+FgAq1sE}iQ|L?PFUcC1x{GtgauAm z;DiNESm1;OPFUcC1x{Gt-`)aM_(SiuO8%?+(=?G>>hd?#c&2F$&CNlVZKf?h-io1T zBQmrs9?d}K9_dCb#iTs7$II?+w^OBD2n;?Yxa!SQxTtKkP80`=l=@jGi>9?$TmvfQN?MyL-W|<+Bl4ukt4vsZcwdS0n{7RU zbfISwUtBu+zFBsjYR~X|f4A?ClRrYA3%=v}gnoMDANC0~SK4ue^2@{ksS|!i!^G4# z$9JHRhQH&@bg64qBYuj)R*IjB!Oxetnrdl`*4H%K+%*jzSKMQ(*7{tCHf~ou+JI@b zD}{@MwqnDPK6LaGo!5-tlJUCp=;tlO4_VC67U9YX2`|u|81kS9pj9)DB92G`|Zp2ec9opWF^g4_|i^{$won38)qCw&jmT z{o7-)&7j?&+d%t3p9j^RiN*RsZJ?ikTCok7I|h9QS_j$<+5&3BHsxl*LAQWLKz{?e z6PNw1L_|3qiX< zD?$4}>p?X}gr4Phn?V$aj_k&vTVENBLTS5CM zAM_o{2R#Ow|3)lk#kOrLXdZ3f;zfkzpmtCX;h?RceW05`EAc+ZPSCBOL!c4ROda{4 zIiS^lKzYzsP!H%3Xgesq*K!rq{^0sO5;Y))?l^?=$B#bS?u4uQS{ z>Kly3reM>)@-W5&Xg_ExC>>0+v|E>GX)V^YGscgxbYc5H7kN|g@%;$8(wl7A*7?~v z3-zoumR4=v>6f2(Q7*mGB+8e9-v49x4gq}RfZ~NRt@hSpt9~)v!Ibw-coNc`)y*NAP?u_DWTW4l*cHX8@j_mvmqaE3WZDUHaThlU1)5m2O zmSpEUvh%(x2YdvH~~jPxxlwg}@gR zBOleEKLhRqPVe^pLw$W2XJtYyG$BRZvaH5o)pcaqAl8b$ejahsjdN{2^;vrPIBMhk zY|Fx4_z>VZ;K@PEe4co&%C_E3cI(V2%eHOGL}eSuZf&E}?;Dq$S7Nf${48Y7Hvx{` zUC;ma1^GJz8zFNuWUeNe3$m@7(jD138!}3>ZEcx1jLXg`5vDH7`bu^Vw1U+apfFgg z@uA-;J%F;4{~5bfX55i6Y&Vu?l@4o{GGUiI_{iobVzE`IkL_Y7i&T<{U>owW3h?xU z=N#g}L0C1g&r+}eFnaEr{>U^P7vMwlTrRLd0+tH9{~C5TvgS+ct3Gh_Y8v@4J#YIC z_*W1={E+(qewown0gE0Cn%m}bjfgrwuRs#DB*g?V;W?MHY=nn^z&gOBE z{^j_E7dYY6pb)5myrpEs<&>__mGOkhv+N6QMxNT?bIdD_BQur8XcT^4ehX;HU}GqNk;&jZ)6He4d{{PabV{~h24@UtXty_xwx16~bW_$%e%AUTsTNw)yU(n82b z?+N?@;H|(ZhNy%1OPT*%1%eWOBk(TpXPfXjI1d2d2)vhYF&?nA*pz{;-H=&HBmB7Wr36zI}_&))@9C)g|X-!T1 z$c`Vxp9|aoj-^}tAp8p8cHl*ERLZXcUO$W+5Af z&?N^xLZJhlVMF#F@YaF1jCjSoO~bRCrfr%sG?I51JYC@V0r4c{(ZEJz-kE)YrGcJyC7>N`hX59M>{NAz;lK`B-R4# zF<|%u9pWH+ZUWX1>}o=mWLK`{etZOY4z6v?IQjl>fL8(!62E9OHN`H+crmTYqsWlj3lYkuqrp77Nl?QANuB!r6W+la8#8F=P=4^FC^BXWOHpi{sVK<`Hk5=Oif}fL)UM0 zz?DwKdjYU&6GlZy*HYlifl~;jBOjmTz^Z_)BS5U@Fvd5~oY$5ai0gM%Rz2%ScG`q8 z-6$h|({{MI3b8oDLh~e+mGN0%0WAzt=7nmG&T?(}4&-jbweUlvi?CZl7YgsjI3W(+ zi^eBZ(hRWMaNRfs*Ut`WT*BsJT}owNGna)b**3^#N$`eBOiY;@GB%|zM{y5i+3>p7 zqc|sBBjZb(NK-?b44nXz>l8v#j0gFgO(uL>`2~~pmh?sOfm)i?q^`l_n!OO^Hly4Rsa(pKLg3}bmuEG_&lhCL zH6`qaA}uJNiG7^4R9@7Z7?X+e#aXn(m4+EXSVGB~-_WPV{tmiG zKfo3Lh105?EbjkXvi!l}n|_H+;`5na%hb(uHPa1DzsdB6Odn^ui|K1j-(z}|>F8;i zI8I@D4%17R&S!cpQ#aGqOgAw7Cet4>eVpkormr!5kLgjSqo;HIOwVC@3DfyZuVw0H zYWuz{H`2HIJ?xS4{}JA*;>JH>93g)}Ny%llyi(W7hMFc@0e)D0R{qR_Ip^28Ru;?- z7R+F1gu;N+@X6GU;7(`qLGdUZ7h_#)2bD|Vg78QRPG%-t#XrS=DNfQb`Xg*ds*jEm zeA4g>z$#t|5MN)$hvdZLDQD0=e3~{z_%p!M z@Jqj~tf!s%pJ&{jg1-rTxOxXi!2brE^r_~}3KehZZ^sTNCuaow+!63gN5E+ha5(wb zjDRm60rvnW{UaBlAvn&FM8h8v5cp6EemCPbS|sB*RTAw-jN2I}d(rV6bz zdyIE6uIl}a@d)Ed}2(*+!kS(0dPje!4+@h;{Ud-o_a5fd@# zTy*l)+_JjS=$CH|fy+BJ-KJ0u|X&2d`Kcwe!^#U43MH!yBz zLyCQE;P*2=R3`bwJ~mG2{?KrCcxD8A*9iCvBjA4+0smkGd<@n(!|5}11f1?I4adK1 z1iWDc{I(JBZ;XKdcmzB$0=|C){7)m`$40=juy7i#z0*d(FB<``8Ugo?fPZZS{Gk!> zp8_X8Z{>l`!&Un=;}OQoq&sTc8MiKyzz-OI8TfGReM`w%EEzf6Xdf|dt4zi-5!i>5 zb24z!v+o+okEA#X81GNPD@TyClKJz+O&FT9kh?^Kl~!*$JF&uSl}mXsq0I6E(xz{Yqp@0AnA`-j#>|>++PWNa{PKi;d_Cn)75}Y zA(Flb{3O_Oi0#(N*>4FvnU_)@G5^*)nJ1oEz-ihTl5_lVlEBAnTXSWecqRj<=ZwIA z3G?^Ql>D@Aprev;EB6=F5C{FDHR)fuP^Qmi{0_!#tS5(c?Q4wtSRbASv~GcOVH0_p z`K|2#>YmW6z-=Zzb$SFiwwaDQGI3!>dirjZSz?b7r>8J(zgglNxa2g(`>spIFBdp7 znMeimSMvH{73W>g_z;h;0ORz_-=t6fRT4n>631G`xAH_v>qR;?G4A7jaZ6Zxka4jY z2kaEaf2#OvB%s>$l)#zEMD{X&*G&?9l=I$Vyqfh_{rEoP5nkXZ{xrBawX2)?=d+xX z7>{s!)jmKYF3^Yb+iA?Nald2xRUCx^=Y)w|H3EJU%dxS4s=B-*@ZZV&)p=4lhfD1q z#oWV^c%*zmqfzjP^+*T z;zqfEn0h4HS166j@|o-3vCSiM{V;=UA4zbo^Ph})ITx?ae*opFd2$Gj2bEMflq z3nia;rVXbzjlkc;{9RW`{%MkEcQPJf`zw2Xa|Ag*W`19V6rlX%zku6VrkT9T{MB6V zIh^?}aM9{|te1!bGlMejCqsDxNQ8+{f#aDlX#! zKHXGaowhRn5bLk>*(`9ym7tF@zl|N_O3td`ai^ukpC|;1`GxIp2J`<)$>DxMxR6J! zKhPWq;xCKUYIS%He-+-harvErMrW*UEG`gI1!N$h5C}K)E>2;1IRss0@-hj8( z>w#i;3nzd#O8j_T$mNkKynllic{E9!ftr;bm!>#4*^JjqYU}Y@fwQKm4pI{7#$XH5 zO;Br$vaNy!$GR`07ItC8MxX%6^r^`NI^0Frk~Lq3IS^ zUBa}@Fm02oC7_Hk3%(G5ZxZhFyH+<)N3fw(UXl#zg5xDS>u3B{WY~fHz$);7FvPm1tzL(M(vK$K&*PYY>=GmJ$fc%`S1~MOTOucd)6JUd0oP z6w2c7JE4qnR41C`Sy@wiOaAc?6=!LY{R}Dod#>=H>;zMhwhE3} z@07-MIq7XWC#C^^LkrA3hgNsQ0u^#?Ga)YQ@R6bLqJ z5)m$@GI?QuS7K|Nh&osq_=17vWI34nP%Y*{?^=!GY1|W=m8!y@C`t@t!bHy~83}7( zQpUXRZ=}~wVQaj`r}?~V615kx%BDs*SHd5Xv@r9Cb`S@L;<&0NO(|3)l1bxVYjibY zZb>MB-e~aF20TefJV2^Ah{1sIo5Yi7BUToyp>PE?VpVUf!E3)RF(LWA9?`fIXLq_< zT&AGR`l@K6kvwm0Qr)7Sq?sns+@zSEfNN+b(Q0bF&F&;obsqATID~OVZ|1_S#M+Il z+pM{dr!yWn|`6o3)YYd=1KUt;=(U5GE4$4m5ou#$rPC}X?dz8bsxpSc&(;+ zI04FOP=hw+@Ji*xTfj25)_I!OHky4RE;BwiC$%8nxo%;Qc*!Jn;tnmM+^{h&UX5H7 z2-kOt>C@Y^8nYH=%S205?Bq#0kwMmuuaPj5B#&KqxC)JMHP&31KQ*GzHB@a&4b6CB zIWj`C;)@P3i6t>5VgzPN*@4GTG2(4|++c*s;n1J~zohl*3_;X2YgJQl*2-Xmr*39L zohDLv>AGH8w?V)w2Td z8f_L`1cJ#cJbRXl{vrTf1lHFDfQ0J(jrm>+G)#H*(R3hc9#Ff)5T!D(K z9(5i2f24GsjID9pgOEodpD3#KXE+=8V3LnnNFK$rNUD4_pD5bO=?pHWuKSe~y3I^` zG^%_*SDbWU9Fp{mxtLMEGRnK>UMI5}Xq>|#9b9&ZFl~>PKDY}n2 zmHvuPQQD5AXSY;ZJ-?->kIR$(#G~|QSiBdj@(5GUiz%v}7gP1C@~Zt!C`09osW1-p z{8^lGK_Zj!NiE+3jBFC$7qKBhhfRFPpKFjQS(iE|+Ki96yv;@^irWOy#JkM$RD4_c zTv6JmG?({Hmkf&9m|qd4zoK77hPk|Yo=4Fi^78?zysB5FJ5$Q5`+|zH`ziM0{Qq7q zuliq89nSPj+($JZsr7$1rM$YIsHjJEJPV<|HXlDmg4(a@@1hRHp=e&pO)q6P$%Q}7 zfRk)|R5j}PBZCZsBb8sJ6{Y8jbbM5K^}JK%KUw}clqKI&<<))G8izx*Th*)V zco*`BMU^l79&zJ6lzSxIDoOlXl~?o?