From 3dfb01d45b971ffdfeea50ce58653eff592807d9 Mon Sep 17 00:00:00 2001 From: Thad House Date: Fri, 28 Jun 2019 14:09:10 -0700 Subject: [PATCH] Update to new Native Utils (#1696) Also update to azure 2019 windows image --- azure-pipelines.yml | 13 +- build.gradle | 18 +- buildSrc/build.gradle | 9 + buildSrc/src/main/groovy/MultiBuilds.groovy | 10 - .../src/main/groovy/SingleNativeBuild.groovy | 8 +- cameraserver/build.gradle | 31 +- cscore/build.gradle | 59 ++-- gradle/wrapper/gradle-wrapper.jar | Bin 55741 -> 55616 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 18 +- gradlew.bat | 18 +- hal/build.gradle | 54 ++-- hal/simjni.gradle | 2 +- myRobot/build.gradle | 6 +- ntcore/build.gradle | 56 ++-- shared/config.gradle | 283 ++---------------- shared/googletest.gradle | 13 +- shared/java/javacommon.gradle | 2 +- shared/java/javastyle.gradle | 17 +- shared/javacpp/setupBuild.gradle | 4 +- shared/jni/publish.gradle | 4 +- shared/jni/setupBuild.gradle | 12 +- shared/nilibraries.gradle | 39 +-- shared/opencv.gradle | 23 +- shared/plugins/publish.gradle | 2 +- shared/plugins/setupBuild.gradle | 8 +- simulation/gz_msgs/build.gradle | 190 ++++++------ .../build.gradle | 37 +-- simulation/halsim_ds_socket/build.gradle | 2 +- simulation/lowfi_simulation/build.gradle | 35 +-- wpilibc/build.gradle | 27 +- wpilibcExamples/build.gradle | 4 +- wpilibcIntegrationTests/build.gradle | 7 +- wpilibj/build.gradle | 2 +- wpilibjExamples/build.gradle | 15 +- wpiutil/build.gradle | 37 ++- 36 files changed, 408 insertions(+), 659 deletions(-) create mode 100644 buildSrc/build.gradle diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 97ef121a50..cb0626903d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -31,7 +31,7 @@ stages: publishJUnitResults: false testResultsFiles: '**/TEST-*.xml' tasks: 'build' - options: '-PonlyAthena' + options: '-Ponlylinuxathena' # checkStyleRunAnalysis: true # pmdRunAnalysis: true @@ -55,7 +55,7 @@ stages: publishJUnitResults: true testResultsFiles: '**/TEST-*.xml' tasks: 'build' - options: '-PonlyRaspbian' + options: '-Ponlylinuxraspbian' # checkStyleRunAnalysis: true # pmdRunAnalysis: true @@ -79,7 +79,7 @@ stages: publishJUnitResults: true testResultsFiles: '**/TEST-*.xml' tasks: 'build' - options: '-PskipAthena' + options: '-Pskiplinuxathena -Pskiplinuxraspbian' # checkStyleRunAnalysis: true # pmdRunAnalysis: true @@ -130,7 +130,7 @@ stages: - job: Windows_64_Bit pool: - vmImage: 'vs2017-win2016' + vmImage: 'windows-2019' steps: - powershell: | mkdir build @@ -151,6 +151,7 @@ stages: publishJUnitResults: true testResultsFiles: '**/TEST-*.xml' tasks: 'build' + options: '-PskipPMD' # checkStyleRunAnalysis: true # pmdRunAnalysis: true @@ -161,7 +162,7 @@ stages: - job: Windows_32_Bit pool: - vmImage: 'vs2017-win2016' + vmImage: 'windows-2019' steps: - powershell: | mkdir build @@ -182,6 +183,7 @@ stages: publishJUnitResults: true testResultsFiles: '**/TEST-*.xml' tasks: 'build' + options: '-PskipPMD' # checkStyleRunAnalysis: true # pmdRunAnalysis: true - task: PublishPipelineArtifact@0 @@ -212,6 +214,7 @@ stages: publishJUnitResults: true testResultsFiles: '**/TEST-*.xml' tasks: 'build' + #options: '' # checkStyleRunAnalysis: true # pmdRunAnalysis: true diff --git a/build.gradle b/build.gradle index aac1e12af2..acb8310039 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,14 @@ +import edu.wpi.first.toolchain.* + plugins { id 'base' id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '2.3' - id 'edu.wpi.first.NativeUtils' version '2.1.2' - id 'edu.wpi.first.GradleJni' version '0.3.1' - id 'edu.wpi.first.GradleVsCode' version '0.7.1' + id 'edu.wpi.first.NativeUtils' apply false + id 'edu.wpi.first.GradleJni' version '0.4.1' + id 'edu.wpi.first.GradleVsCode' version '0.8.0' id 'idea' id 'visual-studio' - id 'com.gradle.build-scan' version '2.0.2' + id 'com.gradle.build-scan' version '2.3' id 'net.ltgt.errorprone' version '0.6' apply false id 'com.github.johnrengelman.shadow' version '4.0.3' apply false } @@ -99,6 +101,10 @@ subprojects { } } -wrapper { - gradleVersion = '5.0' +ext.getCurrentArch = { + return NativePlatforms.desktop +} + +wrapper { + gradleVersion = '5.4.1' } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle new file mode 100644 index 0000000000..7bab0117e9 --- /dev/null +++ b/buildSrc/build.gradle @@ -0,0 +1,9 @@ +repositories { + maven { + url "https://plugins.gradle.org/m2/" + mavenLocal() + } +} +dependencies { + compile "edu.wpi.first:native-utils:2019.5.12" +} diff --git a/buildSrc/src/main/groovy/MultiBuilds.groovy b/buildSrc/src/main/groovy/MultiBuilds.groovy index aa1a225e16..8df7fc6d4c 100644 --- a/buildSrc/src/main/groovy/MultiBuilds.groovy +++ b/buildSrc/src/main/groovy/MultiBuilds.groovy @@ -47,16 +47,6 @@ class MultiBuilds implements Plugin { @CompileStatic static class Rules extends RuleSource { - @Mutate - void setupBuildTypes(BuildTypeContainer buildTypes, ProjectLayout projectLayout) { - def project = (Project) projectLayout.projectIdentifier - if (project.hasProperty('releaseBuild')) { - buildTypes.create('debug') - } else { - buildTypes.create('release') - } - } - @CompileDynamic private static void setBuildableFalseDynamically(NativeBinarySpec binary) { binary.buildable = false diff --git a/buildSrc/src/main/groovy/SingleNativeBuild.groovy b/buildSrc/src/main/groovy/SingleNativeBuild.groovy index 20d415da07..2b7e087b24 100644 --- a/buildSrc/src/main/groovy/SingleNativeBuild.groovy +++ b/buildSrc/src/main/groovy/SingleNativeBuild.groovy @@ -40,6 +40,7 @@ import org.gradle.platform.base.ComponentType; import org.gradle.platform.base.TypeBuilder; import org.gradle.nativeplatform.tasks.ObjectFilesToBinary; import groovy.transform.CompileStatic; +import edu.wpi.first.nativeutils.tasks.ExportsGenerationTask @CompileStatic class SingleNativeBuild implements Plugin { @@ -94,8 +95,7 @@ class SingleNativeBuild implements Plugin { return } def tmpBaseBin = (NativeBinarySpec) oTmpBaseBin - if (tmpBaseBin.targetPlatform.operatingSystem.name == binary.targetPlatform.operatingSystem.name && - tmpBaseBin.targetPlatform.architecture.name == binary.targetPlatform.architecture.name && + if (tmpBaseBin.targetPlatform.name == binary.targetPlatform.name && tmpBaseBin.buildType == binary.buildType) { baseBin = tmpBaseBin } @@ -105,6 +105,10 @@ class SingleNativeBuild implements Plugin { if (binary instanceof SharedLibraryBinarySpec) { def sBinary = (SharedLibraryBinarySpec) binary ObjectFilesToBinary link = (ObjectFilesToBinary) sBinary.tasks.link + ExportsGenerationTask exportsTask = binary.tasks.withType(ExportsGenerationTask)[0] + if (exportsTask != null) { + exportsTask.dependsOn compileTask + } link.dependsOn compileTask link.inputs.dir compileTask.objectFileDir def tree = project.fileTree(compileTask.objectFileDir) diff --git a/cameraserver/build.gradle b/cameraserver/build.gradle index 2b19454a27..d59d74983d 100644 --- a/cameraserver/build.gradle +++ b/cameraserver/build.gradle @@ -30,23 +30,20 @@ ext { apply from: "${rootDir}/shared/opencv.gradle" -model { - // Exports config is a utility to enable exporting all symbols in a C++ library on windows to a DLL. - // This removes the need for DllExport on a library. However, the gradle C++ builder has a bug - // where some extra symbols are added that cannot be resolved at link time. This configuration - // lets you specify specific symbols to exlude from exporting. - exportsConfigs { - cameraserver(ExportsConfig) { - x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', - '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] - x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', - '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] - } +nativeUtils.exportsConfigs { + cameraserver { + x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] + x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] } +} + +model { components {} binaries { all { @@ -66,7 +63,7 @@ model { if (it in NativeExecutableSpec && it.name == "${nativeName}Dev") { it.binaries.each { if (!found) { - def arch = it.targetPlatform.architecture.name + def arch = it.targetPlatform.name if (arch == systemArch) { def filePath = it.tasks.install.installDirectory.get().toString() + File.separatorChar + 'lib' diff --git a/cscore/build.gradle b/cscore/build.gradle index 40cb97dafa..53a762beec 100644 --- a/cscore/build.gradle +++ b/cscore/build.gradle @@ -20,7 +20,7 @@ ext { useJava = true useCpp = true splitSetup = { - if (it.targetPlatform.operatingSystem.name == 'osx') { + if (it.targetPlatform.operatingSystem.isMacOsX()) { it.sources { macObjCpp(ObjectiveCppSourceSet) { source { @@ -43,7 +43,7 @@ ext { } } } - } else if (it.targetPlatform.operatingSystem.name == 'linux') { + } else if (it.targetPlatform.operatingSystem.isLinux()) { it.sources { cscoreLinuxCpp(CppSourceSet) { source { @@ -56,7 +56,7 @@ ext { } } } - } else if (it.targetPlatform.operatingSystem.name == 'windows') { + } else if (it.targetPlatform.operatingSystem.isWindows()) { it.sources { cscoreWindowsCpp(CppSourceSet) { source { @@ -88,43 +88,28 @@ examplesTree.list(new FilenameFilter() { apply from: "${rootDir}/shared/opencv.gradle" -model { - // Exports config is a utility to enable exporting all symbols in a C++ library on windows to a DLL. - // This removes the need for DllExport on a library. However, the gradle C++ builder has a bug - // where some extra symbols are added that cannot be resolved at link time. This configuration - // lets you specify specific symbols to exlude from exporting. - exportsConfigs { - cscore(ExportsConfig) { - x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVbad_cast', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure'] - x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVbad_cast', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure'] +nativeUtils.exportsConfigs { + cscore { + x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] + x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] + } + cscoreJNI { + x86SymbolFilter = { symbols -> + symbols.removeIf({ !it.startsWith('CS_') }) } - cscoreJNI(ExportsConfig) { - x86SymbolFilter = { symbols -> - def retList = [] - symbols.each { symbol -> - if (symbol.startsWith('CS_')) { - retList << symbol - } - } - return retList - } - x64SymbolFilter = { symbols -> - def retList = [] - symbols.each { symbol -> - if (symbol.startsWith('CS_')) { - retList << symbol - } - } - return retList - } + x64SymbolFilter = { symbols -> + symbols.removeIf({ !it.startsWith('CS_') }) } } +} + +model { components { examplesMap.each { key, value -> "${key}"(NativeExecutableSpec) { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 457aad0d98108420a977756b7145c93c8910b076..5c2d1cf016b3885f6930543d57b744ea8c220a1a 100644 GIT binary patch delta 19567 zcmYhiV{o8du(li9wr$(CZEIrtnV1th6WcZ>6Wg{mv7Pgtz3V&Y`?qSXTK%i5`>w0+ z?r8$=YXpZ>kq3u>OZGOh~=hd!cQmjp<%-CTWeE-^AiME;XgwO3=>%hlLUvROgMUVhTAE(G|m z(f%sRg_ag=iwu6~(OvuT*2?I|*@s*qCCpf4Y+Hq-VcuLEDttX|c*TY5jWiXms}33x zAYc9?o9CFVk0ORk%P{K-T>Y@%mo!4ycb7u=MO1@&RA!`8b;jmY<`biQ|=ATNSH5}lvH3WTcfE+$N?pyqGFtH1)m5?BafI$go6oYHP9es3` z!4)*xb@w6ZaJS2hkitpj_3`^HBKv zI1%Vu@8lI20iLQYPG8%YenP!U*#(z=Q}U@AKXEwy*5ODp-7TI z>d2j;Ysg!KKx0lI-}_626Tlcm`e+DZ#(7C5Njp#uf!Ui0_9imcSTI(b%FBL*jSFG}_;b6`2}2>gtygSxGI zX|wy_|00jHzRjchl2`rGzkJ}7e9a1~qYwC!=KQY8`c|Lf*0>M1>#fLgqRny45^H*s zRH$GnnMW~3dB4?F|M-ym$zWEVE6XjbiDHPxQNkDb!z@$HT&9L>DO1g9oDEzV2MuoA zRo8S}uH_${xE6lna7sPx4**fudi;$f+#-Y)U$H~-62E||aV$k&v12M_s??tK$Wy&F zYd)WA)k>y_R1vI-KGAt|x;;mZmsYfVM$ssjH{ppYClnjMrKgy_9RGrMd%>^rWOKIQ z%SPJ?d98D11N*YIJtxB^#@CU7wLw{BAyc7PfPW8h?Y7xmt|`B@4*2sd^Ic%`U~r=9 zNS075cl1NlV`O)4AmVLCvP+4$5&};KZZH`g9qFj%pHe5f1A46>me)E{$J0aeL953< z*=SattA;XyxAY#;5yhb-Skces?BC8g8kPKMcfUi|%Stwdpp(nR2S^^sheJhy+MM)l84WSFkxp*#{pneorG$)kOmoEvI!;3u94?fAP zZ@_>Wo%+yWQdR)>aj!1>ay%9KK|@sYKL!QF%cpUuAr17$i#d4ei?iRH$2v;YyJ_JU zy|5!c@Gq{%WuquJkVf|7(o9y(&E+^tjxS3$7U=@kecGQR!>mI_0eNax8i%8&eV&v@%fPCi>o zX8qX~4EMatnF{ozlPBhfWWe?mlJ;wR^m;8V>cqMXPm!D^ol2&HU$7>moA1K5`+Cs= zpr#_ZzfYk>JVUU z=e1g~dfM;pNRMATBvsxADGhHPZou0@&zeh78oNqs{ah;^rD_P;#+@=&?FynMyyv|p zc?CO?tuUYdBj&}xT0qIxVU71rKhA3U9&fEcA5OW4960Haku;pUy6`|=a}+3T*TQna zM5CQ)FNw1JJYLu^!l@!d1+sI|txf!fE0#~zZeKHUu&*Gg@WTrIK zL#JC)vaT|b6kj6@j^;X~7{<`kwua`_G2jx`%!f>>VECy;sXjCaenpckfTLKtr7E3@ z8Yt+YvSGl3D&8@PW5oG8m+U--#bN?UkL$cFfT-Dd6BfRFd~RAP-)q z+_k;mcZ+bfh$r>ZZPZ?8T%-2Vca6VjyJ6}c=vO|lX6VqqA{ROOS1gX*z^-MW$S`0w zNt3JgPOPFBL7C$^+aGab3eRjB$D|V7W|ODy3dkVoyGq2}8R+$c$afxQP>z&rB%r4~ z$kb5=$Zb#`QJABtJMWd230hAk1j-k(k?0te-)xJ0!S=s0lBZv26x*0qsijS5d?M?y zQIsM0#83{nt|zg(YJtdKrGv^7shHMBqt7I{Wi%a%F0IPVpf2HSPT}BR{nHsW(c0CX z1LSqtn9zgi%a9(P-5&{}5K1#_5{tmW15khAC917PQZVy54l1c^q_B?{k+H=ipfcl* zk-LS)kV!X#lbZ`fZm!Dc-8M_T?IW>@Gs+L?s3y9Lnlz{CmJd>Htq$-e==Ib?@y$21 z*UpM)2_EIh!VAa8>!7J?<)*`@4Tim{0Cmf)YWCeN;sYs^u%;DICx0VE{^U4v$wMw5=BtR$t>M}LNZN9bp)*mmgjryF;6BQU{|Mf-L<-f47u zP^97f5VY}YK_be&LO^v7YzidOYoIN&nR&nODD5_+0$3_W zOES1SBzDa!WXR4W)y~e&C_Hdt61c=aA_?&M3hp1#5*hT_YC4isTZX{PQ&!Ul1Totu z(k9F47DbkQS)qSuIi`eEbzV5z<(g5b*XUv(HfoEta@N;uB-w2wMRVB8UM_q)(4Xtw z)eDF*(5mklLc@DyBFdAlB555z0sdP@H{p?nSFvTUNAXK$3NjcC*w}7fvcU)non!KA z@++PD(ecw10`IP><=Sb2opSe1;a=i$RaUep@wPeKMKkr3Q_I>xK7Lr;gu%2U{HL)S zXFTYD;hc+3f7x@ns+mLjVD-QA`-rWNFlH7HQ-uE5hcU19Dg@LZZ+1qv+Ek4)-P(i572%~xBTU}Xk zq`0-H(11rdVLrRypcMaA2872W!DxoHXPyk z|1#a-e8JDIBkhAVH@cF-L$oh#X575?Tr{KC$`6WL4M$uQJ8PuxG8aw%1!>4-$4>7) zv(QN36n=`hWNbYnU3JBL@;~+_UL*x8db9@< zFE*avh_A;8Pxi*A(7a!d!&hyF{`^|23r8;U1Qt9Nt?R1=St4d{2-1+%Z=!XpFJPhB zbe67u*u%YBHDoavFF1w<6gaPrnmDYc|LyerZiMm&#_hS6YzD4OmU7Q41vyQD)k%|s zo2$y`6IKtxHVYIVIC|l5#R7fyb_b;F2yuNYm-mS(J1s54hUdlV%H^GN%_aJJkIHkw znSzR2^l}7;iTv9XDn7qTS=dbxnSd-UsJiOPSBfk!8`$hr`YJY?z`f(H$E-92y@4-$ zmVqw-VO`HLKQZN!dAIec^X@)83wfpIqfn`H=D?%#!oyz^Xd(?@UVvMjcnvsgkGR^I zf#^tIe4mX4UyVYVc5f7nWFn9vj+@<+W*wZviEDU^W6$Z#+!jQTXU-)VS>TC6E+i(V zJQ-pAsqGTosC)p=6T-a5&>IVVgZaA%tLzr=nBVTxMHL_k{GCjNi+y|+dF1fio4A8lIvVj7~%`iFnoE~^M0gA1$5ZL2tjfMJN>ze@#Q8#t%%MU1<; zSuAMz%t%L|{@I>bHGl9>NLQ!mw#vGh@mI;z4f@;j_FC!d@^~j#chjRqr46)aR}2-& zzJF%EoM##$NFU2Ncbz|WU&!0JbJ)4F;BtUs!Ue=#Gxt-U2hTsW# zW`BD&0GGgq0>kSjTa>!WjVQixHKUkl!F@^G-2$#E$_=$}TX3+)=l8a8U*abu!CE{v zjtL*E*WL*SSFfSD=Ma9mRjd|9?5YA)?{$+3tqUBY^RY|kfeBQE5=R7*wKE0a-h8)k zI=-u;>~`9Y=k?A*REv-knY4QK19ke@Vs_&S`Mp0-=?OubE9{MpM>c$0dlpEghh7~2 zJD+NrmvZ3vJY{Ob<1Pofs&7;pO%=0C5wfl;;63ap$`vm{Q#S2OWJH>wIeRUe@c3jf3cKuP7<1)Co*5G+n0QL zgGD1YS2le*fHW4a{T!!UVt5!04NrscOD0fqVyNy=DkC3ts=96tiyd0)|vU3~)+#Wc*e zi97S~JR^u^*K^g^!-*_5uHe_s50HPAE0b{OIh}*Be+SH&5(|HwvMf;W5x_KAhl0jdcQ28_2B{iiruAz?=I<`Wxm zB9(t^h(Y|EvDxSkeM^5tB<-j34HFc8Ui)Qi$}BRi-EwF=6xu7LX=3ngtcZU8EvZEI z;_yGTBzbNeH@O368T?mH~VO05m>e zFANulEY~2m_<0kc9Yu@`$up04N^;^Y}JXYYc62s=UCds|(OF~lQ5YjWn zaATUk_kk(9m24QAVdO3zc98AW|2bB~eUwqH-eJ@Au)@w($#>!SH)E<`o5?zRsda^0 z4$dPsgWXtM*S5dsHhWC#B$JO-2Sd-rO=_@VjZXSeq~*k4F;Oi#^iuO_`S`fush=b) z8L$WSo7KSnKV)UioyI1}637Js$J4^tbD7}*C^J1x4x zB!jj{i^O}vAQxPU4Pg;jq9s#lI=1<#tctMd*qX#R-@oF8!KTKI%8QE{0_N{dGph{j zo)yYY)B0b;TO*e3bJpCYJ@mFVI2ZKEaNv*+6&(SFG1m^&w214=$G!*mZ`RaM+8qW4 zrHmsHg@F}LfAIlsPJek3>sO1lwn*xJoAE3!g+J%2&x3vLjz3W20t(r}k=)%%(C_E- zsN|>_Hneo?#@(Bu2`Sxtl#tdOC4~%Iik;X~$N0H|V^B~A?d1zxFxs8)iKN(%w0gvP zmfwM^xJe;O`+Q_=M1nz5@E#rtlWOFtKKPf`KJe_WYl)@Cn0fXavRYhk*d5fHZ>$y#B(CqpafJLR545g87?F~f+BF>ef3p{~V%&;G0V8Y=gY=83)Aa+j~x?xiEB z%|&m38Q}v>TX&XUv@WJKfE^6-X%pS`*LzosI(gRyQY@m80<-s(T6vOA4lJra-zeab zQT?Rwd~92oc$A{Me>AP|>>0veJG+Mwl{vZmuLjMdzT)EuT`*J6t(A9I#yI< z{ah}*Rhj0kkAhCBhk4a6B;;vLgRb+5h0;GH&flJKs(DJ&Ed-vNgq|SUH@}E@238LH(zTVL!K}wt=?bjOYp))ksZwW`f8D+Y692M9B zGl-G7hQuWEP4D0wJ=ie9Sdo$)o-SMQSOk4Y0+aDrB!tm>3oi;UB`6uFf0Y2-XyJ zC(o;cuU#l^q%AQ$lCmMRl)+ zsWxDn?}JHaV;Cpl23;%C#OPs)MDkrG~`@fo7ra2dP z87v40A{Gb;-TyQ-@W6!%;v&&0IN6`T`qj>`eK+ZfLKn8ZJpiNhK zqZ(a|$bWcO1p8?$$_?uoB*ZYQ-@0~-{iWBObRVlzyS3Y-H@!|C_;GlnhxvTq0cUhQ zg8$)N1Q*0j>)jL`<{c9a>0K4vR-wZHdNl$LNAz%TN!RZk5$&~ac=vD1)jOVG``?J9 zFjGbO;QQgnC!G-R6S;EKL}v(wNbQzI3e#WauO;R`7s(;R_Vba5qwx5bTUAKn!)W$dZ- zX*;b}#!nxqjA^3L+F0AqDUPr1r(R=)nK=V)6E}QH82%Idi{8|Kd_QV1X}H#XKg0C# zd}KddV?Or$_OlZ+`JQ3U8hKa^OrETibC$#8?9-*_EVcw05m!q+f?aTT+Vi}D;@2JJ z3q1?FfB7O{A>HYSh*CFgt}8M{=Cr~XWS35E#pMt)gjlPEtV@M`nUR=;0XoE{*u^Nd z9Zk9=hx?(EQD@CT^uvx59aeCS`PbIv4N5ti9hEY=jH8ZzcfpClI2T%%Tj3pu-bgE| zIBUcO&cO-keBwf0Tl~d>nq<9u;t%8XxS{Ofvw0-|`v-CAB?o$Q6PY6tf{f*fuO#U{ zgR8M(+I--0WT`{)M@;t%GKQ;cTU*{Qyjotk-s#=b&(9%8ly+JJoP_?&*qU=W*Hj~w z!EF_S>Gf){SGLkH`PB~>tCB^=bX3^^$Mv?hm>1%i^ z>J?nT!3!6A&V^GO!^l^KU@MVehdQyVtI=O>2(2*cIJ>AyeX5o-DN+r;$!1K>&4*lF z*Iq4|AO&#bNUnPYHplZ%yr)9x0rbRW6Y`Qhn$wk8i88SP?pwyUKQAh55matBxNwb1 zZfj{}uFLA-wb}vM|%DL)bM`iN>>j0L{CqTfDDBOq4`2i!Wb%Tx=zh5?4 zcq_hGQ3i!8fhasMgZUvgz@Q40k7w6k?i^yKKBo?A+ILZG{`T#M+xnM?HqgIK%Qt_V*=UP!>omi^gOPsooq6Vy@iCa~! zLY8OwPJSY6I15JViDTp!93gj&$}&Jry8JrpGNBM!XfHeRkb+ui{JYXvH6dbaLUyBY*0t2DYBrAzK4vKU02 zA5F>RD?`))+nqtt5x>&%l=r4U6SEK7*ubjbGBH*dKGi}B-6X>)-^{WPcqDLTP>~%O zLCaQNrdJ*0-Y>I`UXeDC`g!MVPvXGJi=DpMu4Zn*Oyk9OXHj!&pXsyld%sUi&}8-X z((Fm6i^ic)u5|?7K1V`xTHF+JZB~T?JL8H{YMX!FGo~6R$e9%)px$}^N*>>v1PQ}S ztPQ1_*0vzo?j#Hf`!QqQ#2eUIu#2%w_IwHNGlKM}ruV7EN>P^nX~v^9`yg&)dqCS? zvzGhAh;k*-E#^eCbQSU!QNoZzWil>Cx^@#^>G7af>HMIpnqHeX!B&R$@v%Z@!vj+{ zCB4O3$pn9z6|T68;WlGW)C-1S^g< z&rGH!BcQe-!+JpHtd}X`AJMCk%eAEcc}jj<9h%eA%2`P?3TFT741O|<uWf?^f3NNC@Owd@d)u4)Y;M3KuBVveR{N%{+XY9R ziI?G>M~i0=<;iW)0E(aw{Y5`Yh=2l{JI1eE1JhPpS_Mm&4{S#X>8MLeb&eaMWDWbl za#tATA=OyQ(pWdYvTO!>)|V|KOZ1VaLn^6E_AW?u(bYP?LqLb=c^NX`7p{U+EzaLq zE6VZ&J=W+f*xIzJ^>Qq=i{14Rcy6Q`}>7-enU=zJ{dj?$kJ) zsgo%^oOVR(1|nr~_N!s3-`25ACh)cSODKG1&A- zcO1+Aq`W%;`3eyQs-&=CV2S}$96JG2j?hn0niLP{y0{43k^9Ac2qm;ju*Vqkzs?kd zykJy+UY|y#c;%{T=h^sNG4^_gMFv>#r0Y|JCX>>R6Nd@a6o-B~l#4^B&HCFeDqzE5 zrT)D4SY!p{Qki?J`&!nTE6qOAI=-2(C|BaT4=ev;A7ZP#k!cJ&4AOfDY4=W&`Ly+H zA^H&wl{mHh$c|b_admSHn?>$9i(TCLR`q-#oVe9fyRC%CCUzDW|K8J(4xXwo<_K03 z{tmyh=%ayW`=>W_)KxcFL+FRQjA-(eACcN)w&MU}l}lW)PccZYh{@K3Tyy$_2ta1h z1{xIfN2TdFM7b%U@|-|!KFdHy)Vhbtj1rXY`SxhvlJk!3@4f0c{+WG(mg{0o>syMz zDf7yXD&=EiMt?udYCnWjxGOjhT8zqZY3t=(A!_8GkiUW|5n8um&KwVU&qnjrD+Pm@ z&V~gVyH%dmtAltaTU@-DoLy%z^`KZI%w7toqIL5y)diz3CF%;wO)qHTrpE-@&l!H3 z(8<@9eIx&`%1dB6`_I(j%UlTkf4M|7${7Gg3=k0aWM*ywj0i&5$WRIy4p#-*L2v6Zqe8cVc_^^fyVCq1DPn3noDH+OV(%Z>e&K74QtE1;Ss z>zF&KzUdCGoH|@}BkPDav0(8v2B+-h(wj}Riwig74lF=0IWG_~rR0*?Mq@I$END!7 zxY4F}R3uFtxutP5m1MHVBHbB;opgBj_QP8Yi*ZjKsuu%^G4zKWI;)0c=4G9<@#&o} z96n4F$8ttj$8@!x2Q^ZAn2vgpJuIG`9P}j>m~hrGVeEzm)Pj$2+%(3PDpz1mt!UNIsNMorfmx16FGM2y(ve#Lq@nC zj*eD&9D&?5$wXULpSjbnxZo8?|b^>G7Csz#&uL^ zVyur3v%F;-%-gHC4=9S(rk1KxdD3IlAf4;&Am=b?P7wI%AkkU7^TpYJ5{{%?v5l^|tYrK16%E$tzph zfPZs$d~PW8hF>z$JUDY73hHc%)ip}76HJ#`b6T)i;!~mp0*nj6OJ{ENHo@Cx@WbXo z4sX#SDs>O94?5LG@IR=WjxuQ$2|PeYdD9{KLCt9wIv|b7R?_8N?OWkj*w?Da0&{FF z3`wfF2gRp+-D|={8$<@nAXk3O{q(2i11_cXLDI5QT&x=uSzxZVddq8ZeLYC5SQy7? z{zCnO4QYkYJ5Zg1k?4fnI_EOu7B#XoW?*GY;%N{VImZ(WsLdRJNQzgL*Hn_%eQ76Hi$o<5g)BjOLh}Q1IONC!R2}pH>P<}BZ=Se2 z)od@g6>$&0isCw^?qq5#^!kHMSj#15iyMj2SEv z+8TUg>1i^2#_il8aDilO7v*!ZDu0l#x;Y|Q!m&a8Atg|WymY&ZDQ*#7V&18`0Lz10 zSi0oPfe|?b(eGUNcacOXt?!3_<&Id`m2uIJKzh7k1c1V^n8e1hhYStTHr!OH9vZbr zq^t)wkw?+8st7fzYT_U$ACQdN$Q(w zMHK;OTyW!s*^5THjct1^2QQ^y35gq`VfDmtD(c3CZqS-QnW3~Zwu3(N zREg)o!ectgs+Gg-4QR_^)VEYh9;;!a>ecW_rr?l0%Hvbt~&qOj_(mPt(HU&T7~Q?#;^3rdrVO z&B|3hBlOiSG4j zNgfg3Pu*NT%yCFVLXM8N-PF+S47XMJLw`feQM#?=-{jEk40%;`$6Twv8hur8JXdsQ z*J-|5KR~&P0^j4DxAmwnXB8P!%}4I)NKU?jyE&P}*=LW^4;kD9tlc!ih>R#tc6&?; zF=Pc&6j`Z0KhV~een@mP!WUNa9tcZ>GdJKCdum@Q4htyY%gY657g z-{7yOD*vCzbemOo17M#l z|1E@&GATcC%_J^Jm&N7fO-mRVjif#N$&B_ZfPI6a;-hzD{i2%+(8>^`cYO4-3W`g$ z3~L0&0hFOg^7kJg1!_l`b>3bYA=?lz*JrNM(4o(ZrZ*tvO-;MVwRVR50y}i`(Tl_Gf>h8w}2-@v=e(ey1k`XU( z5&iFPt8=wT3~UP$qkZJU5UaFFnscm2%Z(Q$8a;ebwEC+@p!nWS#fRTl$T)B)Y+5}) z_o5M)yrcFy^T7o-9ZMM}cYV)K_lF+l1^%1UHjC6FWBgjS_&s~qeBR_=4W3H=FJ_&ml`z zT+TzM(_r5^c*)-I-=URL(l0iVZ(B~{22iGH` zO;0;-GYbqK#SpIE!}oGAF;_!+-Fp79l93HVf_GH{`nfM4!(2bvd`%EI>qsJS6H`CA zSvw$Ga2pN=QOlQX*jX9r>2sD3-K+_hR|A+Rcoc%f=?Kg^5_$HAoN~N+< zc}XT3>$ZE(9;~)!#tP4Z zdtEL7c~*++&Ck)O7_%f@=&PuL{1*!3tG<5QmO=;`pZsVFZqX9hD&rN`ukkZf7LE-! z08cHO;M=YJXXEYh5{x>RR0OW7UzTjckBOETBH#`h5R$<(sEuVP!RsnE;ulA-GDVHF zevDq`C@^Ajb@V{ktiAisOr`#Sx2HU!F~)anD}~*jLvTado zcmwqf&Hg;3f}ANC+Tv&=nko-3jIe<)lG0ukd~zJGa2_>R2t)rI5S%u`+t4_4@g<-f zDiKWCP&^V}58)rG;05$S;FPMepY13zg}5YpD`DtQ46Ji*pj}$qu^{9s8?oIidn%xv95emprSxA%8f3v>fii&z=mAmhc`tCzti6 zQ*mHE&kjOufW4opKGawBC;ph}Or=WoCD`Jy4H8@ll;5GIB#L0f7E{_@dUllMR;>7$ zqMq$Ls$T%CVzs*(5}g$A+br9h-}AT`x-oAmQ)^oIHFnu%eRAO)t4d9smnL(2W1MC6 znnuKUJ@)LXcG4Oznz1i621^xfLA1`4BsSyDu7aW4ainJ1QoZKW2y=@oMqk}QW0z*b$e`jPNN-)Og>TbPDwyKavM-Dp2!1CiLbkoiguPX{>4#5OR;)lWgg zp6bQ?qDuWmi*5^NHH5_2F)BY|!;$O9LLOAW%>RI~idu`KD(uv1ht}@d4ir8L+>-?(|Ozc zapEXWSuin+nraJBF~icTEp|K)a(yb&=ES5Hgq|h08!fFS=P)b?QHP3Ll}DzQ@Q3BY zpt6(8E3GU{BBHCSPmkW2>`XicQ)}WroKyuAWTWx3FHSQyRu5?$>|K2?$aKTZnWxYt zrrWN|ApO+pY1tb5VYxO%2TT?lB58;QQ*du~I=pkic66csRD|al*!m`;2ha(ERS@Vj zL?Z1e7T3wj8jHtg&B<>MCO1yDjVQ!-?Zi5LIH4${-@Evdk)Bj}M}uoW&5QAj(xL&Z zSeL~e-WnV!M0zG|jLwJsLsukDwzcL;VG9Qrr9=F(jJG_K-c7|jzUm6W z{Ghw|rajr^AO=(YPcb)vcp|yYCZGnVN(=W50diU6p^SzZ%vh6hy0hoJKZz3U$kyIw zi+}p76j0;JWqi;=1dbyZ|LNOVc!&isOPj*Yi|ikWp)Qmp5!M&veH4dy<^4{ZeH~9r zEET7v%Nxhinh2n#DuQ`Um(GWYDjW8X;RY3P9v*U<3)8i@9@QL@{qyF;t)EnKBr<$y z>I=kB5o_!!odp$rh$yXF!o1?E8nUO?e|l2{Stt%LWmzN|#%N0%e>V4KbIAZBYluG$ zNX?q&NIRJ#p-CA z)e3wI$vGec0+P}fs8JcU%Wo0FmJyjD)>h7bNkBObqSwhpW4r*FNI zb3LeeFS;DM)QNtZH@;Ko0MWysW(S}ws>3`nVqyrXQnS|zbr@-ep$U9OJflf@U}#-e z5o843OblFtl?d@^z8mvnl%tB&n3<;xnF7!^7o=T>E%;-m8$AP5+u;>W@48u5$8d8W zruH8K!Q=4tLov>c=?OqYZW-@vZaok3#*z6l@tHD;8AN~OAuj&%WIp#9qx#PmPH>vh^eNaS z$yZ;fKj{-`9i{U6IDuwDOKou%+VPrF$fs-@3E2u=dk^61{2iw6Lacm!Iq$aG;A_X` z8~OH2UBmBNYAEJVKCes!wvblw(ELiUlyD@uRhn98cId1P=>Fqq%dlzOZ7H3#hQ-2o`wnHrV4**fpz{iT zL1l5|bq08I*(OMDdDv~2vP=?(_nFI?2h2`f7>E6p7;0r87|L{iS{gY(QdrB;l~H1z zS~M`C6TV-e7n@s4i%nG(5W>bVmE%UhY~;qKR5wng79N68Ryn(f&S>rJo0Z|7EpSZ3 zb+Ki!)8BI$J5FcMPr_C^b9J%PhOjRPMYGYwMBtA3YpGVq#f^%gw0>>%C7($TeuMrG zRcr#}tHAzS5(B1ins6*+$y@z|JNir6qx$g|KFmS|9{hDmj9U~_h^#>_?j5s zhDr6L42-j2i1S!6jC<@g(Hd&?X;4vjl%h0`MNFpI453@?YbpEMpMe+22MPf|im=QyjjG zlN~pXztxnA91QUwEz^TzL3eSU*D(Jn*c5L%<0tiE6U{DRo0hGhfMo{orr>BU*@oSm z+RT)!3(MG3z83x)`@Z-P1q-Iw zath24|Iy8}-6qm~V%h9e`3hO{4Tty6tZ8+W$n%o-RBnJ7s&2GiOi!gadX_Rer1nnt zgnJrUGZxWtnaG(|jP8=_Ce)C@ON%NEA=+2AN2NqF`ZLVFUp$9c)9c?M(7i|umAxno zowS$i!~0k4)B6K8`}qF!vpPPWK49Z`wE0)mH>`?|gJR>YTrpmL%rwWRt;aeHMawiq zfkFt{YaQd{3 z3xwlU41%J+QaSG$Z`WFLE|T_cdYd&45*;cP|5>Slt+wDW2XM6|F%GwdnrXt`Qdr(v ze?^?CSrU2b?D}KAuv7Nk!`vAo?sgOeMw??>bK0CJk7@_sAuyW81sByl6AfN76=ydt zb3&mOYQO^^5Bcflgm1IT7$HN(H)yaQtua|gem4q_$9tcsy}eysH*+fdJ@A&9nV;;R z;697D*sI}u`>ArXegJ+BdzVVO*PO^h!SR3(2b-ii(G>Wz^I;%BB<(dz#=>47q7}s7 zu27{8t!7=Ln=|A*sj^x!3u`LyT>T@QE*7FzKL-X{G0U}F0|r?g|}Ju1x& zrTaoM-D!?8fFml{M$Ro9Uz9SkHv&sAEX&bh@5y@3@wr7oGFa}|J?WCsgsO&4$}5la zQ*nl|(KkC2=;QqmTdc!zjrx74Jx<$9NUR(A{rhyUCICLHI*>CI{MG;Pln6*XwFODXpP}l?hF9MDU1XWI41E_PYi{1XnBE~P;mUnBGXu*W zkGlYU-Tk`f-TH9h$!D9tIGKm$Q}o(5_xb(eM6l=X8rvAE9`ZZsHZoRP+*?5ubDQqK z0WO%QOr(F~_0R?P8fGttZM$R_VY?HwJu40qUHmLP=hNrptBu4ZOCyQ0W0KDewt&O4)N4ja-*;yq|-gl9^z z6wvR`oph*zDR4ZL)|tFpjfjHGrWHVu?_Vyq%cy94en^q z_Q0s<5OVUGTNa~?7*DpV*32ys{pvy=G4U3< zGTS+<&v>WipYeUt}^W)zc3L(>ITsA4=5=C;-h{(8oFO}vE1rdxC?ToJE0)cF?U=cGUy zi3z-YTSQgEBPY;G7fCxYF$ottGPNoUr!Sjkah;VN`Es_(H`#BYxxm>h^XTfIkcXtO z5XitPwxQFQj+G;SF^>0ZW5Oj2c+UQ&$UaGY-!xHisE*mL-h>hk&};+D%HBAn*7n@4 zl@jOQGPFiFPYw95Va_6%HAd%&8B_|&Drn+lU~(;FaJ6acXc`nJt~l>}%ox|IC?v7? zTiS~Y$+#L}V5h#jJV)W28ss9iZumF2yt*0|uQU+$vnkf=Iy0XbiNZDf@plS_4I6#( z6Iy=B_UPE5=^5sbQQiQfIJD@xf4Ke#C2`qib6!RUW>s2~rz*l$0V({c(bxNa43~JE zdHmHxm~{jHGzt2CXc9=Y!Ts_O3@)OpJ$R>}xTIY|Vyvrr0X0%h9FfHowve?XfSt-! zxg|e-VMYJfGk6#(#jM)MQn62sG;E70Y{~UVN}gU!a~c<#$NHFjU``5#zm^PTK?EKa zK%Pu(!3m5*9;L-0?jBXeUBrFQR|ZVbd&jhh6n`+v!fo-H9TK?6ZFjlQ zAhpZ8a5ZeS?U)sZVcWq{WoFI3LT1cd!vyeKIFx~73FFG`I6q206(?uYc8ZuHte2LD z45boVeb~5CCZ($GAcG&nl(JE6EPDU@e=4~acqp?rJ{aRt?w7pfGM817nJg7bC1P1d z*e*g!X!u;h=t3B?nDV3sPs7)me-8Z!wqG4t-2I;aYTeN9wZS`#z-#IUa*?zz8 z`+di6yzl&<=lP%KJm2c5c8Skw9*$}d@z;BN&=zH=zFf5U!>YPRuX-FhuHWIW z&$GQ46O?^9JnvAdW80rzTXj-*@po@6J$c+nY^xT%U3*nyZNgtR%4~IQQTZn0H+7jW zPDsK+vWW$!*czL4#q}mu%7t#mb+YcMuA+^cf1Ca*yYbs!Erm1A7FyQ0lnOpp+t{pT zR0Q1)bg|c^M5SIDY zJ5fD5%lpJYlP!7m@19<#9oN*&Urp4L+Zw-J9K_@@}{(n04-lj74)@2A*7I z66=a1I;ZuYEtfuBd8X3OhU^u#chw3ut&RCKL`I_~2M=s=tZ}r>uOn7?rns#XQ69g) z?a9s=E-AkfK3p+Z?V|QYu~3$EWaa%;Ynz*$%{l6q&G*x=%fg)C(qKV|mO)&Arv`1x zcM(1&PR^d&i~@S8*{ZqPIr^nbu7{|+z0@;3S5QeXimlXgT4DTSuD+X94x`m`);gZb z&Xq68^>E)_PZ{}P{;lfo>Q3n&Jh4vrENYrz{c_AFi=VRQ7$re#z7}^t7NdT_x5jz* zy}%>-sX^A3iS}V!TSFiJZQFCw5`VOD%FBD zX%Br^N<|Txr`Ed%HXYhPPb{UU+AoV1UMyKoyXx@Val!dMLf7Yl3!!}nnireLTMyoS zI!NuKe?QVUqKrS?$P+$DBlD(Mz=R=Y@IxbjIFTiwN1LkmD~~4+F`73Uidacu5wVf< zZAoDX36V+kgs`NrxX5I977veX_}0p12q#BJvgJufj6h^G1{aQ;=v=szma)i2R}kuP}_+CV(~1nK}O;)Ib4qvhD(Q#NxBT< ze>}Djoj!o4eidY7mRPk`A0lO482{;|KVc>O?i(~D_}JKi+!PD$Dw#}d6Z+J>wA={B z#Q=UR2*9O>0>h@E*KcjzHm60%te+G=JIjgqg~vw!kJu?G8>*meE$;A9bFAnRUM@qY zO!t+`=w7}abN#$=EqNcxlfpnH_;e~SJTCa@wwW@{2OiwkG(b#;p%`U{86zpWiIGPQ zkg#D)INIG4Iz~FEp`!)q4Z;WDX{1p%fQ1qU3R={OJg%7%D4J^o&bC;KCVo-l8`7I@@webvTnDK`H!f{98-^OV4WOHnYo zs(~9_Yc)VlNLrB-S4?nBXkz{ak-~;A1)@{fC=o_h8><}@-9c=%WS}RU0VH>@nJN=Q zLgD3l1)?oLS7?Wv*~7rVIw6Ww1RZi41C9`Pa-R^<`Z6H))fW!RU*?)aAdnS!U(bgI zrohjEBzKVGjlqp;qlL!}`4(?MY?~gcozsSDQD@?qMY|SgYD0qq^y9eUiZR?|)}%%$ z{LV8@439i+{AyhP=QUg_srazB?UZth-3>LOR6e%Y8`W zPOk5#Oq@iwgFHE~b=K8EOnBA3f>)i#c6*L3d$iFj}0_u1vT9} zgM$2jyGcR+=g1oR|BT7tp!lF@jU=FQ5TIzuj*$BZ|M#NhnGV5Z!{3g8XxX{ne#k|U z0)2#LT`Djfb7))PxtTt*e_l4*GYxusf506HZ(Jm<^~B zNh@hHFezBTb72RhZc;TnBFu>lqxo5l?FU5Oh){&EU}=tP7P?nb*t#^?m1X@zqiZ~( z;700=N}6SnMW1&rH70)D5@so!6Hns|TgxpvHo0C09pSaMlcE4X0K=Wbe#Rt7GTpkS zn^gy*Y+^VE0W;e74GVSy<%m4Fxj4sk!Wl9t!AkJ7y-c)T7&I#;IdnxQ+@!x5NRb-W zip*OhaTujYz>nl~PFx~1{Um(ta>~9b$=ONkBwRZ&dCR2vz#{4T5N|gQ=CMp4OE7ph z2scF20vuC|Gsp#i){f5fRA3v{e~3Ke?GfbGF?E@&VeDzVj>_7(olvstAt@Z|VTA7k zsluVn5#(etGDm{VFyB;Q{*6`Y5>fIbt^_(`MAhJ(x<-8m6Ze|d2mJJdrSl@=dfxu= zmbGnx)=ufdOE)ao1~N_R3-o{DJAXK3k3GB!-QEW-*QXDT2ES20o z7ky23NR!n88AV*~kbKTI7Y8j~(yE*GCa}hb(=M67Dm%~KyHqZlOR4wed9JoeDHqK9 zA?~O9=X?8SD81)pjS*y(LORl%`wN9`KjC3QgZ@ zBX2^P0^{T1yL%Lx{0RA#G&|%vy^cM9#B|HXOLv%ma-QNCrEx_ z!dtu zrS4kJW#;2GQmL|o918_`ZheV5{Y_#fuIolhyr?;!b$%NUva5fZ5>qcI70e9bZM=t` zXCc`rZ1UdM87C!+-H}Z-t>0hVBrY6UtxTojlZ0U zu57;t39yxln1K^g*xaP@>k1|JT{sgjEFjN0gzgkeBmhoM4A18h-%*)0DVX%TBp3Os zqn0q)^*i_2KW|K>2MT855^6)Lxu-?E6;ne2#in&-*G*|V7bPQ~PVWs!CR_I6%tmvB zMCfO*=I(8@eR?VGX4pCu;uF~FMaluzoCmOJm`i_h?kHLLW3N|Hb!(*^KN|L}6|CLo z6U;@l;Q&_bCDRG+BHUCC>jZ9)-64iscsdSQHVQaoMq@RHa@ihhXG6ET0Q<_*+Ba#c z(a^AHlMY?%W=i&R6n^NF|me#K0AKh|ramyL!sy z-05l+=4tA5(6H?Jp6tSNZhsNEef4F6b93{NGS2ao6oL25Q@LE*B^Q28P^lcc0#rpi zF(rFZKsy8H*x>&DTIs&-oZN|G^RisJ{Plep_F-X0_FWi$s&UMfuwiSJ3ti6ehT20t z1OPJ`gCNL)xCVz18}_DekZq^!MxjN4rd}}#w_!MG`!fl`k+zfKXZuCp@pC%=T`nGL`Nvjtt1%94(jeBjnrwu`g`qXq_tt?3eD_aJtg4XEYTRMKb z@$v;{*%5lFF{_}M^$q!!@n;5j6+l`J@-|AL)-Cbe?6`{z1zBo*=|VSd6c3K`uFJn^ z=#&!`7@@GXG}#G}rn}wwZaWXneW{L^+IlxB2wfD>rOUVH2h{OrmB@dRANCuqUlmf} z1+o_x8|FRb00#Le=UEM@2D+?+(He*n#e{VJDiJJ+HUkwgB8$+FL=B>ZX_;%|V+l4=NG-uk*@-wJ1G^U=j*T(dX z?!@35x?}CU%Sbh}TQ{oR_kdLGsNWSR_Y0!e^ssTo2YEgW8jdv#)6c7_6Ror9ZC+Z# zHdVaOKuydf9sI=rP1)&BYCiydc>}{Q^QX)QQK(XUKr5@YMN&-A61j#Eb}oOh{@-Rk z`D57?&9+nX=OCnoG=u~bethBpl_f5bv(R3V+ zv{2C==V{N0tWYPfy@YJ?@ORM;i{~I}dhQSOBs6j@WuvT5_Dx5PQZR+J&kugJQ#p3o z#G{(h?9Nd;Mxbpr4#0gPs#Gsadzib_>J4=JPfD%h$8GGs#e!)fj!FkZrb;$GSAl8m zpA&Ll$O55_=g0C)>mIc~0y(aWm8L}s#)AiO1K7b|U-s*>Pw&tHZ+SJkW(^)>2UKwC zQq3!kqZF>loNqv5vv1kiABXG(V#)0F@kcz3BN>xaIXj0+alouWW2O01G-mFCN^um+ z8L%DwK2CQiyM@f^>vLGUgU2QX=(W|AUFD3E>X{XO69yONlQ^e`Ucu0%x*Qk)RTYe$8 z`i+N9qgfdQ1Ms4$9>sYS+9irmliX$dumDjd9={VE=L)U&rmiPckB9h@JL&ahxy2>9 z(#kRM$txE6N7UzF=Mvr2A}5l!I4Wy3K+~d>Vfv%~oaGYoO57#)(^9L>in66rUFoX8 zT(wNMoo8`JrSb3PWtm-}xU&5SrZRh@mS_$ST31NU1#p25-flQ`ulGCnO75^F@Wf8^ zm;H$HW)M_XJw|pDosJ77hMAT|idn9Dqx1{GLPL385>1~Lf5yEs{<1Qd%;2%wKYfWo z_K$yvDJH1#g#$NaxY1RsfZeP6fN&H{JUD=o~3D~L16&9+0 zH(%#(w`bK>?NK9i7#@&y#CW}7+Tu*sR{rR0ZcH_O&VSyf z^8lIIvjQLZx<%8v1Kjs)moo+C>Hwa$ZK_Yw z0?!M(A50-%SbJ082uytlEC~qn#D1^PVGHESe8HrzUU0i!%DuwpD@dd1PIv~x(7y1L zcW#>s)cda(C)<6{dnSU`j=h@o%^y1wQUIJ=7Js}Oph)X3bXT~LO~L_07bYe)4I)eD z&Zur3d8eb3uu(awQ=0Ie(FW296*fN@mL6cXa zO0iH^dx_YLS0sMf$?`sbh-Oyaw(UNgU)k`y_Pa@e@mQV%eG>3+SWSW8V-{iU?Es`y z%gUPqo3JFv6I7Hu^K!X0n15YZp3Y(8%Ulknx8dNn=H&{*E;30Ys=Y&F7NTgT zsvt?vfeRD06brob5y|vlo@l;s?LnW$Rm^RJFRw>ar-C|mU&UCTUwETcgMe`3oJ+VS z=#`HKu1zgeXi@97Rm?hj=obs85b$t=kv_9)-b#0bw3`_45)?O!U7WD}JrkI&?Ryk4 zwoGt|(|@3`XMek5v#hWcO_D)-l4zPyDQ`@r@r{(>nPNvWB@tO835?#Ue6}QDtI39E zcP+exc^q={O&I$!Q)SJM`TEVFQV6L={Pg=XZKiB zl(gC))L2aoYD|(VZo6R4R^e`v1)ZW$z0-8``%*t4+#*Sjrl$9}7|TWW4s1WP>kc4` zHqU*#ZoSu*Rx^hqTXeg0&0V)V+Oe1?pXlGP@Lz={zKMbJ;m}U$(f|@O7p3=U?li4h z#r^7@X?n16S7zmNq8+iSG>?F2jXPugnYx5Xn5pEw4Iol%KvbW>*i$te%i z(yz>E?1UC(x6tPOi?Y?odGj4tv(PCk^bsbn)z2|v61s~Wq0k`tiydP1xcMtfLMd90 z5YN`0GaOw*`UxqFHZ#33%zDCVMyl9V^C9my!%iXJnEzAjCf|-@C$C~H|34f`ad7x% zEhGqtZ*o7j0sux*-nMivi6k3ov{~gXsqOESh#u-<^tp4$O9xQv~(RJAwpPjesotqE$ualqeXAh9L zJqvFBkduvq1Bm7+D^Dc}wEP7}Aql+Ms=>0Q>!Ps#z}{2JPEIUGLq>_7yjc=HUFUB> zOEhT9BVGptJ2mu zDmR-fG*(itN(P!RNXEyFOa~A#r9dClZ|3ad0-zMwcN$#8R;ZVG6}bKFSDWn2oQOJ! z&l?{!Oy@Nw4x6KnYM6$YJ4`!=$pgEIi$%JJ#TK1P^x)x`qR3OJ+UI#F%o{OjSQ@3- ze}BgdfYnUsmzPwv`;FY6W>)E*KgyOJrVYM|v`{YFe=xGipwU?CtL%GooF z1Efo}(kKb9pLVCF`k+%otaj)a}ctlO&h9>HP&=9(+690QfHUw&NgJt?t5Z) zNx;FGH`HwjAPCk1!{=o?+3Qxzp8|iA0vZjVaZg9xeuX;?2@=LZVd09f-m>(N+^#NP z^QbjmCOyLWqI1Ie!q-7PcGuMs9lu}gCk1Mx2KoDL^>N;21v*q7>3GKWwL3iMPAk=P z>yrf*586*Nl;W=_VDeeLv*(~dEDy#+8KO-=M8tk(dWE{^e0NlfVPlb@6J&V{7HBql0%G&Zb;GRpwAzNmaS{m z<+lB9x`E6)q<$vtvf9O{wR!y;*veG8M+xa4bwPLfRlq5_(T*Mn_CWyCe*6`@UXi(l z|9gaj(Hw)%6mGi>ZbC^mfj7soAC{hviEwP{PAG z=H1n~_N2ZHdrJhEcI-oIr2Ha~(8*lN!)d0MHKkB(Eu&>rXF8Jd)SWpn2xve(@@;CR z@cZg6^jb(WSF>kf>sEd;%ZzlB9aWnly^L~Sfu~h-Ae5J(iJUvv+Xf|FHiKTN`!H=KKMkm?g-U+OD3Ql z;7S#SctELbE+k_qASwUnJs+iUqapakvBFf%0Ht>aPT_z5BEkHI{sj?Y0zM$Md`wbh z+;B_otR`90V9(en4B*r%=5)+yygqpSbN>nfc`E}~BwwKhH-8SbJ!thAOc?ibxU$#F z6vr+b0W|{?ySUy5)%}M)i7J8*3-yDU0pX5+@}oEdrrtSltYVj;h8I3I?V>4_GS<^_ zKfDuE8@>M;l}qRouVh9cX*nq7w1hJ_W^QQbbdkEKBBa+43ov_o;1;q!(s4*du8_X-##@4Ec#$_D&CfU~@@eC&ACO>LkndeiEDkhjR$` z^EzSuxbSxu!LmCzxYMcpv+9W=>i6S=5KBx#8FE|gwh{bWw6A!O{wL|W&&~cXFb7iZ zJA`p1mX<|Z8QKDdNX@y9PsYH<=&ts@9$%~AcZ3mv!Lo^vu(1+xE&Uus-mEXe|HZQU z3GBvMqDnBd|I6b?HSUl#p&xH{CDx;y*X? zN$d!>b-lYD-a8-9-aC`Yv;3b}0qn-XQS@9jMR;{-lQxI<+7NXrN;LhYp4~y5RDiaP zXrC_6V(>1h;p{sM#_jXr4YV#jv1ZZg5uU@nZkp{#4{FcWC@+LpesrE&g7Ihn_AU*E z8fKf#P3e163#5p2OjE z@_vo3*UF%}@qB~yaE0+f2T2A6uRFQ%QyqO@oqmrJ;h1e;5ZWq=36+3oMz zJbO@s(+GcEhsg84iD~?_1d*|}C>dM!BPeMEjgU{43rJ9Ci5{-ct!|;*JPp3q3sfJF z9o!#{bHiS9Bt;F=iJC*}B#O#AOjNs8oZ-|pG-#37TjPI4#Jdax(AZ0o%r)Z?&hH{N z%K`~(*piSm(OC{i=}DdZxB%8oIT05J2jX33W!+mhm(Qn(Sh4ppceG5s--3U~TU`10 zh5gwXM!~GJ9#Xw^3l{n#GU$0ol!D7r51f+2)rTY{BLYx3<*G=9HyfPz@|a#tv}*JA zEK5qa@NgGR1{YSlIS{Z@!>3oBSdzdmV4>gT$>~gN9n@73f}i2Ay#Q3lZRkdyx}xjO zVJ@c;`ngnwGMIm!$!jE=%y1a4Ts`3x*Yu9DuIQq(NJ*8~qBo0>8W5#4Qo~&H*aoB~ z$-ZGYKfm5I7p`(C2gOHnaQr;m=6-`=uAE4a0w{k~aU0{s+Q81?!kGM_tdXmYIe#Z% zb4a14MxO+VOx0^cdILH=DX1)@24{_$9fK! z^Kz256mZA$K*>iccD5xlCEwN0rxC>!#zRj{R&Jo-c%0LYgkFR4I0Y*TA1aDrx_~`&8Za!*#T|pgHZO%j;Qwk9Kkso zZ!db4oNEj987o)ifyHe!F zYFMq2`j7^c>S0m@jS~IYG1Wj>Bo4C%@&g;Q0iEKIFhK5gm_$ssBy!joy4xwwxRkW) zp_CK5k;Fv&S@FJZX=qp(cGifdE;2xqroL1!epr^4$#!mxIgAr2?mTjc>kFOBcI1~; zKDcK-IKt@kU%?EG9b!Hs@N;#F^Q;Hwrjt2jQd=wIOihO2nzX{v5Oc#~SieuhM zjYw|DYQP5EDpeqxG|?hexiAZdEVauPPB+E5STIFUk&@vruaXTpBJ-DQLE}v*2?U9l zJwY;egzxDr%~+eYzk2JiHZ@zaNmM(0*x@Ci>@qUhXhQPz`zY!eZK}vNY=1FYsf}}G z-?GmFU0RT(y7`mU&+5(pjXOknNk7MrOry@YDgg#*m=)lL;zl&l_%dlN#ry_kYwuWC z?as|=2S>a#A5E{rA08X>*dC&k_~tPPrQ)!eFN7=2-X@?A98Jlv%VKGxz1{vY--FRN zTV!NvA8?xZPRmZt5>kMrdpj$q_b)sCpfKQ z90HX7on+w6P}Ew!{T}$!f2Ma41sQ`a$NiRut{XM1??GsEf;K^M+3~>Q-buo;5^!Oq zKiUdG6=nw^C$O7FSWA+lGxjufl~#X5=YjtSqle^bq~&>WZCojObf`Lr*L5qZl_TVS zeeSfJi~4YXsjr_Kwp25zq!NvLprj|yat8oMRHQ)jGgT!sa-5PY`xXBxHLONn~?vv z=Cxt9RVepX!#k8_n&~dX*q5^SGN5Z=#?x_yk6qStTW%zv7h@vDC;fYRa@gZ~T@C=R zff~rp4`g*r@AUi$fQ{8TJZ_&`7c;SlVLu-#Yqbn;a4hB-RlIRBZwY;>JyF&kcCF(Z z#(Ze^I-xbdiOXuZ`8}KO|HjYI)fR=rHrN+U>k`?{9kIQ0S$P=hX;Ig%#yWV&6IUzs zV}Q__>1MGV%xRh>k$mvz`LzTetOLCS=pCBP|Iv=y$Mk1lt$FJtA6R!PShuXtzcHbH&?l#WR9KjUL)3h^iyHypx)O zVV5s5MZ{EiL6Z)rP+UI0^HElO{@^Q(AK+2lSNRCz?TP9^YeF+u2&N@(lLiF6C=_O; zxM<6Kl_o8pynw5eThV6^ZK@B~A!&1jdWmM{4+NoMynF3CJiT|zC2Nv#Vm7DMi1-Ii4ynGhWskprPvlS ztrSfVEZ3P+RpCwr;knPU@LQA~@YUM_rTf0!hB%~C84sKKp3Xii4T&^(erC{2wKU|@ z)K>jLwKh}C=F>)W3~6(OQGc@h=zC<8+g!nHVAih2jarE&XPnD?HNccte}1 zt7VM*U~t`c!q*C^Z2@@JIekYK)J03J)S=TahK1nowYR)c^djW_JyN#0eJzbvdg~PR zUorHRF#NjWl=w{-;(O~7t3-uguInHejZhbvoEr7Kr9q(k>UTF7y!o9tBi9g~#DD0; zRdAk3zNf{d>VhWo#M^^(e!;QlkHz5|V-M;`r+^x?*YSnMZ2|fznKqW27nK};H~LtV zCu(0?Kf0AV9_1}z$84dPxN*h{%UNifC5C?HHFjP#+PeqkHJa*A`fiJZZq#pm2f>#| zUvG`5`Qz*8Wa8{HGS)1tk{+{;T4$C{W}XRkbZ3IDj)hp7i976h;P&cGozZ5_E+7g? z!z7)%zgu9mHv#s@Ju9vT#k*p>7$UTUcDi`462(39MtmVWc!Nt}+^KH)DSt_Wcp$;( z-{G|jekWDr_vN0oA+8+>jtJ#v4QzL^LiA1dpn01SQO;8~R*+F1&_hy0iqTb^RaZ94 z%qx|F8zT>Ew$aj?n`p}(p}miHClygJDQ1*#9@baMHo~KNmc~9+{`{}bA=!%l>_7dB z3PaIv%>VmiM%UA(C;M+{OA7)*^uL-1hTqB59Jqkr0~DZ%NI{~>0U^VZ$odqF<72in zUBuAM*7WK&%{4mo+AEcorD}>OL{TC(&pMA)S>LlhtjSU=P-F3% zFWY)Ee3L(PFEfn>1iYf6=%0z%Ef0=X;*zY&SxO5rGvdjl(^zkK7eL_|HP4*b*Hnqk z!(#w1HZEiA=rpQl5nJ*mZ)REB8FwB{ti~SdCR*46rB!Ir=xkY0R?a?P8Ez*OI~0o*NB#(x_3oVs07 z{4;4l;k{{l>qB}N8+&{6d^UP}ZA!k5>@2R8;hKBfWZ=N`)uqSXABJrj+usd;#sI{~ z443;6ytC+eMKGhA|0rPWOiZx+rkt!=s5ke3AS=>~)To_k+qJixTduWJvA13gyE-H{ zZ}#sYj0v-_hgZVP(-1I#Y^fUf&__!*!RX;ftYizX>8MIKHycjIIy>D?p!-@!b8{6A zM_sLUXA*VUHJ)9zI>DT<-BGOgKLDY%&JbG{H(nIB_LycJ#C}IKqp>sOfSsLpij}b* z*Sh*P#*#Lex0i%!wCJOySMHyP)Y>#h2`Z#z?F^u4mS!g}Gef5+TX8oG9c1<|VJ~eU zMAhPn;XHWvB4)(s=f)%YcYyxU!`WZWZj1%l?Fm+;@<01v2`&uJ;h!TYKtLmGk8o{W z+Tp1!X01hoM!1eEFwyNhVH*jN<6^!U2XYw9C?7+!PVDPG_p}N3%3sr7c_eq3BM_v` zE49OdbOW5;EWgc>*%?))*3{4#;ks*sSnm zuEzIjYc?#A<)eql$hH7ST@858IXfmU0>wa_+I!{Vu^SrHV)C-r0mU3>k+=m_HbOBh z|8{NTT3cZLHF7Wnx3YWmzh@OPo0+IY{{r5Lv}v2yqKI(fWI5P$V=y}bZ--$38ihUq zO&nY0FwNB~#ox=duH?1Q;h?oz!Qg~6FG#XSrMQ0W1P@|g$dhT$7yvZqxCV7YUPb*A zPIM;w0!CM{r0-pP0Gr2M-&Pu(@+%76j``pG+o^N+tyXpl_iPQOl)YjY@G`Zaw9o>B zX^WxefXJXrO)i3`Gm7Q#vs~mYi&OgJ2wKB__ysRkkx~QgP)3Lfae$5_>%Nj-dEDc5YnjuT>n7j3xnnnkjCDzY%DgIF^>|5OAVE! zQwJpxoMn`OdI>7ZI2XxAic(f#>&8as2XQ&9<->X^;C4s76dizpf0I&@f2q^*Yw}S|^5E^l; z7D^soqxTjBr0-%+7tqP78auIS1(^A^`(7o`SN`fT;V^&n4$v-a&BVK#a~BxO&zd(| znBJQc5pSY3Lsr?))Q-zgB_%~EF^p4%L;8_K(Mnxrbdr~RBVRiyMXrJ#4)&%|+>mX# zr0+0=HS=M)J%ZobI#k@7MEmX;NGBco7)Y#bG8|F`s3$N>nwifA5wKaX_M5>*U~FYo zY@IclPa9WGW^^V+Ubl%TsQ+(vo9|t+U88ZylC@7|zALTFCM$#?ZhC!%F4Yi_(sqfH zzn}^%$zRqjRP*L-nmIS%Rlvx1f{Tvlj4*ebIomPoxokLXo6f!FkWz+?)6v%2v>dUA z1-x4u>u1WUoJo00mwKG>rFx$UrEV7pls{7O0T;v`@lzQ}9I9Le_zD(EeIYpbYn4?n zz648e7RYI?h)lN#D?dqll#i-jtwZY)<89QwnGMSB6<)bZ4oG3y{aTPVD(;_re~C(_ zBiV1YHB_Q4MNJ4C;qGmm6IdI2JchmQA)5S8t0x z+1LPMRiPbB^id%=X_o58HBzP;b;!>xBnduG@?`sh=^pOZ`Wo2Mk>6h$?D@g=fKl2rv7voOd!nAAj1mZ1!YG)z3J!chl?<`#3wqq41 zDq;9yN0;U*;^93uGD{yQb z9_Ay?K0rjVCkqD&fH8SUV-90FOxntb~V$>etzR1|}*L(vF&Qb@NY2_zVckMkX;In)pethGg z9=n@D(w*}|1bP(pl{fIxw}iz4NL0u(an{FzjmlugEdZl=(dNQKNW!*|BMXR_UM>=12ZWU%R!*WdK!S!>#}{3Sj^)H1y& zE8XQ^+{Vo4w)FSFCf(pyv-{M5SuJd?_P(!L>RpLx5yUw5?a<#zsyav)un^F62KAQk zfI*@HYN4^;&=wY4H<$!R_rnO6%}_lY47Ak{9(R(_=8{sO00da)nY0jxRals#ceBSn zENgus1l9rC4+mpsSZh|}(MVFo?0I`*?PrwSaZq<-p{KdGiplIGQkhh%j!7uWH^tAt zS%yP>T8nGe$FL80Y$2;7g;~>M{`M5&hjFaOI}C9!I&g`6X4GZ=4Ew&eNU4YJ&cdw- z$7u)Z?4tvL$#sHw0OZ8F09~=OT>r&_w7@$v@ip7_QDnL-OzKb(<4q=jtyjbAFIa6@ zTaW$uy0Q9Usxj4?&;jCEiEQ-p$qoe<$X4x_jy!)X_;yGdg><(*y_Lk<^IM34 zB65k}MJ@7_bM7=`B)`2*dEYUZbK~piIs%*zL*icW{?ukG;5AKC%5Qnb^>50Y`B*Xz zu7nmCj=Fd&A(~-6C3R9;tXg_^g#Ytn>nisoq!uIp0E}s=cEpQcGJCx8uR|Y-^1#z} zv!%&{BQ9FO939v}>cu6JL{sPq2@tXDgivzqgjCTz$h|fczJx!LK0xtQhoQzt-zpBK&1}h}T5N zy!f^Pv=%KfUc^W?j-vxWoYU$j;DlH<-gM&M;*K~ zBCYe)^Z!nqjysNXdh_MWr=Cqc7TG@N*`|tPvX0(FmKL%wu@a=ddi2* zE6pHc#XF&G^W{jbSPT9_Q2eu`VPBNJ7gC~kMQIko_vcQXDP(U#X9atOS!hQCGCb-D z0+dujYmgMxcVNiP7OmLg?ThmhWkTdDo{T&2rGsn?m+)OFQ&^K)<{3I*KMxgSu18>a zEWuAtToM0ufOlSxWTVcKKf=C~Pq{LlrX&?3F6O}4X;3K?exR)n!d#JO-IK?TL<_6D zxnvb8E?Kbo2FP8P{YJt1V2^<2#*H$B0Z53PfoAnHUA*dNt)-|K0wQ3tZOLOlpb?Zl znZ#v~z&EnR1i}d3A-yRxX%6r5GaXonEA;sqH}YZ1w?c|8VV0#7K#`Z0UxC*8EDQ50r%2A z6|d9P7gh*F>^>s$p~lk6o2#Z0qd6lK5>_V3izb-kH26MNwM5Q&ege}w$w6|7kw?+> zdk8p?#c^VycSOLcfS;NE2eQ{0<=1KF*YP7D=b!nq1(Ae_Ky=tMq;1jntdvLg$Nxa? zP>z>+(${C`vCU`tb>s)K-}Mh6pmY?)xhJTM%TbMyJ|H-U4B2E)J}X$lOysQa&3(gH zf0%${A)Se7-bV0!~pSPOAun$8l%M^ z;zb4Iz61hxSGYAhFaAnpL6zM0Y{2)gq54FS`Yh;UgevOzaySLVVK59IU`BD^P=WXs z)%^7x{X4IutePp89S_&6_=m~RgT;6*Pk+LOW=3m4r0k!I2qV3nGry>sTuY7_lchZS z6m%7X!(|~3t$nTFW{8l&mK3eGm6;0T636(96`!j&;*wNIMK~BP4f_0CB~W@LIpsvj zSzX8Tr46U^ECxP80!4Bez;;=tRr089O>3?5Qm|y6crLEQRT=oRbbckK`|-KD|ip%HfZ+ z%oL6-qi(YIBp&Mlh}TiFc=GfN*-#wXt|_eRTVGQc=sC&DaGq(kCJ**(wD27D|DouN z4}PMw#3SM$06{g2X`~_>QnUj9+J2NaS`&k+I0y}Pw9$*e7|0p_A9z{Bm-y;WkZlQ%4 zbZyEYb1k(e^Gf0a5O2;q#W}7L54#Rhd!VIMET7sx<(Kv%ZPK$1Uj zGQCs82GQ^;j<|aNp72SR4=a&5^HY2WY2p_>|K_3ci?Dq}w)BhP`i7?Ri>W*z1SYKr z5-y&}zO#NoWUYq;?fSjb((%E(UH*E_*E-zoT%0+7Q~w;Cxtm+3$=oUCCvZaVVhYz^{>bML-TFQ6!ELiFqxCK zO`JlCH9W|FtP>4uL-qq({G4}B(SaW>rE1JN-f$>DCNDKlTxzenAq8oGCAQW902`fO z0mWYemMyliF9Ja5`>BUdDp9iu62pn^E$M-a&K(6bVLkl$+s1-io@2h3>eY-MkwaaP zlcrjbJlrDddf6GD9G8m^&0ZJgPKMV}V2(#%>%*elFu|@7l?0no9W)HVrvnikoogPV zu*gMwIbk_dJ+t z096C+M=zDj2vyqf0ev?+;~-v6F1R+?M5P>JNGZ5 z-^E;}yv3yq-b7Q+i$a6^)s4L{5wSL*^L6{l=S=&__e?kE$4f8Z6Jl4)7gG?i2!;Zz zT!byasjJYC1tgzs1WfT3nA1hxObxLJfZ2yJ2eTCZ7q9iFhkiH*EfPd^O6HX(R23%Ae5(;y15q>W;pki!@*E66Nxc}UrqpWDyQ-QGNngd4e2_~2iq zy9%rY8!NgzSBnvl1WYcSj`hS6*jQk8-y!(rHOQ9Z1gcOD5bE<8*Dh@KnqYbYc>3FE zwVpH|#V{mmNzpeJtcB&I$LLeq9fF4e>3GoP*Vd)Q5$iUzIjT1HhQw#)SIq6AQAg)o zlCz{*r%~3GJ5;XFPZ7{3*{g3u66Z<3hOM@lS@x{xC%Jl!oN+r^D3GfAMy71HsXL%h z>8iUg)5UiG<0mj^S_jG}5-B}})7J<%wL36*sHV$W){3JAT^TU|j8&jWGZo6I zr*O6zx5zM!efikfkRAIw{am}wlkT=_47*=^W3jgk=7YGoSSy5gaf{s=--XrI<+$cL zj2~Yo{8jsm_K0eAf69Pz;;=*mk&YNbTu@h3wx)&?tQ9)$tES=Z+J8MN_1a5prQ66T zg}cnCStp%g%va@MjaO~JFz2iKuHn<#5p=m_NkB(>AAZ(m#9NbHP5Sk-z2elo-Sl5g z@opvVPhYIs2A3rXaej;>yg<^<+HOuI65sKd)a1ID%|@w9N6R0n^BoHsHxlJgM!mVR zy{|YmwmZqt=U}5GVh`9Y0y=yCZJe&( zh;OHZP_Tsk)E;pAbmH@4S7Xzo^Wt7;{&*s+9rODQYm?=uk1vS5ol%0t(Vg}}{ODxmk3C7|XtJx0Qm7iYi(rt(%D+d&0sNDBgG zdxkQ8(o+KJCgqL+qU_EdqS;dz&<~cAdPe{e?bMRSwKF;R;pr)0@Ckyb!17dq#6R}1 z=zCAB@5dEl;mJQb*huUfauUz-X43WU36;P5mdxu*6LRAD&4!qtc(;bcKMIp$@jOf0 z25Vr5-aA&scy~TY>>IiS$ivo8U>w-RigmN3E^O3KPCkMw5F)rV(P+g zi$cP_w#NGduj2~)ufKZ|3j^~KhXesdHinLx!fhvQ?#ec^mTPyq3 z$l7%IZ7wWecYmdn9-Zoc7+GAS@j}Qn!n4YxpO45!AL6a3Jo^t8%{KwbZKKnIcVPb7 zNGqV9;sio)PqSIIw2h9P`-P4xZQ=YA*IIFm&s<;$XPeyZ_8D^rbUKfhm4w4)lry;+ zEi5ZjdN=3z)S1^MvS0d;+m_EQ?6~0~N+q0XcT-Y#0G0pq1q$}%F^%2Pw_5Dq=ainX z$?P~BQvVf)g<~Lm!*WphTtDlYy0V8Jn03 zjj1R_&1-_f){-^_=w;Kb3yFJJxIk?D*(N=}WzkQ%V`&HIwsxN<+Pf-actYQu{v?w( zFz^Zj@nQ+O|F(T5bhNLsU>j(MTdkMmr(G%H$vu#Ni zgqRiczj9K;8mLhTB5Vk`B-!cuH#V<;%AG3A5e`X~z31lZt)5uQcXqzvI3DB2fx^oi6i>z# zQkHIRQ7L@@Qj-!{)4`6C0f%zy<3qAU2HA!&j4fneA}J)2u@uP?xk$LSVRAzsqp}sL zoV3`oe6&fJ8w!^~WHRV-RC==dCvR(e*gdPod0{y`<^+TdH=)| zWf5bajUUN!7yhgCDmCu1)<@9dMP|<&0&l%YtByu*0es$i^gmBTY`t2Fh zr!4=h8M1dD?4}uB8~#>%f5bhz@vo50A7ipp52$rIZPla{ywo7l`W=nTvLg31?e^Fm z9%(#o#ogH>8JXQnPZz0aa+R_FRwN%EETt8eYM?MZY9P$@sL&vD=;la>7V|#uZ4O{< z^XeaV)v?2Ie@K;A^s*&i<|_=T`dju0^I?aud#)yDkVD@+W-DGNM)!`;!`7?QiEK0u z2LcHCwdONp=fC!*3DWrKp}-#+D({Kv51i4G;|Wss+P@-%&id3>I;*>?faZsR;x z-KYB>?Wi8?E?JZ5U)RO(F#W>c6(cgWdCQm0esxb6Aw|&_eCzlQ4 zUW{m4lXlIqD=x)ZW(}$m*$l@{7hte&Dr@vv*62>s$#$<(blT7)u|yW2!`7T!Z3*oD8aIWz=!N4mQ z-^sL&3eRU(Nmpy07>y7<^6Fb{T&dUu6~90C)A~5xRlj?rni;6N8Jg)Qu$6i3u<~jm z*ekf*B|3g5pZS%(CMQMZ(zn}8VxdFKOaHNM*Ekn*8t*2J$7ZCU+6R$ln`naJ48Hy!QDUP6CIYv(=oP^9tH_X1_VZ`nS3hzp)ug zk>7cn+mHl&1<2fq`dwaadP-$89yQRZs%z1z;JLfueQ2&;JQc5{rfn{WaL)WusLoJrHh`EgX>)vw(w>T>~E1B)* zndzdS|k) z=4iRsbi8cZx|DTePx#K;lXRYMoY<>n*RVZP*#3UYec@pt3w}J)J-)A^#q((Xs{HL& z@EU`$wZTORUZKh+O|JfCo#1F*extye{Nvipono(XWXH{xH)Aa673-7qW#7LMzImNv z{9N*9;?%MHRHY-={3<5-bva7%i^!V2Q6l#SF7;3Bl1z5c?y@Z82v$@TNI2&Ih7W&M z!xpUeEfvB$Xm8mz*K8CMsQiX$-&fewAMex~S05ADnE6^&Ce7OP;|=aM1F2$#5*_mp z#jDjHZYuUPzT>%T6R2rWA5O0=bo%r%^mJn8$-BCD?pj79Kc#=FTbc6WMSQmh2_{e> zg15dFT&ouor-*`sz7%aBiM^OLV=hsi3!;S6-w^u#2MT`4<^;xl zqKx3Q667kCjz?nm`Unh*i!V@{Dj8o8p_u&+RU)|#sPfO>gv{y(2#lIS6CsFvt>oi| z)tY)aNHEkJdXX=C6O(P(H#q$F1}FHl7n~57cwpeQ5IM{%^CPhgBv?fp9(jfP2Odxh z^YQlaryf$LhJ{dl!VdZS&^A!iR65(cW;b-$SgDok_3Pl^CFJ6M`(96S9dr|fpIsC- zc3~V!L}L!WF#c3*%=eh8?XN{B4K5=fexsfO9iwvOR*z8LRt$aY6N!?enP^0 z7d2o@K)q#+1fpsdDBm#81A#uvEby2oGQr9O+OosVKGszLTF7uKFTn=R%83A5HVGC% zfFw;s{ zk49l(axA@MfWxUQlfmI^<)FPPOT@bki6pCI>e+3=aM%C?!@@N%jINIVS2tJuAZvxX zxc-6@*H7W^Zb$7zQ84PQ0I*TmgB1fAx;2+0rHED zfT<7yQ0wM~SE_;vdJ>61hAPG)Y2D}&T8Cl8q#vF|v|>at4I_Aa1W{9@9%TF>5@K@v zD{mNZ2;)Yh5C?3dmhQMwjEIZD2nD7X657f{LWhrH*sEAcR;yPrf*FqyGfWj^OzcI* z$CH3*?{;*ah@C$_joEbd${_4LhCNFIrWwlc0Sxb0VIY-G;9a`7;~=)r7{T}YklbGv zF;jfMD8knFBWyMUVtTB;Bw^rmHUu@mqka)&IE!JAbFsGVas@$bFE)c529SVu0fuJ| z$RXQ$3=1rRnCwr}{c9y0l0h^i52^sUUKZ>dg9%AaOeyBGrk7FK;4{k%Y zDnrP&tqIr-nJk}ttYrblF1-{#Jj!VXlMl#li%+Y?m16m$9<3BhWxDzQuN%84tKloR PFlPAY0appj7IgMMQM_1| diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 75b8c7c8c6..f4d7b2bf61 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index af6708ff22..b0d6d0ab5d 100755 --- a/gradlew +++ b/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m"' +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" diff --git a/gradlew.bat b/gradlew.bat index 0f8d5937c4..15e1ee37a7 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome diff --git a/hal/build.gradle b/hal/build.gradle index 2f49ee5c99..08eadb202d 100644 --- a/hal/build.gradle +++ b/hal/build.gradle @@ -67,7 +67,7 @@ ext { it.tasks.withType(AbstractNativeSourceCompileTask) { it.dependsOn generateUsageReporting } - if (it.targetPlatform.architecture.name == 'athena') { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.sources { athenaJniCpp(CppSourceSet) { source { @@ -99,7 +99,7 @@ ext { it.tasks.withType(AbstractNativeSourceCompileTask) { it.dependsOn generateUsageReporting } - if (it.targetPlatform.architecture.name == 'athena') { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.sources { athenaCpp(CppSourceSet) { source { @@ -163,41 +163,23 @@ cppHeadersZip { } } -model { - // Exports config is a utility to enable exporting all symbols in a C++ library on windows to a DLL. - // This removes the need for DllExport on a library. However, the gradle C++ builder has a bug - // where some extra symbols are added that cannot be resolved at link time. This configuration - // lets you specify specific symbols to exlude from exporting. - exportsConfigs { - hal(ExportsConfig) { - x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVbad_cast', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure'] - x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVbad_cast', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure'] +nativeUtils.exportsConfigs { + hal { + x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] + x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] + } + halJNI { + x86SymbolFilter = { symbols -> + symbols.removeIf({ !it.startsWith('HAL_') && !it.startsWith('HALSIM_') }) } - halJNI(ExportsConfig) { - x86SymbolFilter = { symbols -> - def retList = [] - symbols.each { symbol -> - if (symbol.startsWith('HAL_') || symbol.startsWith('HALSIM_')) { - retList << symbol - } - } - return retList - } - x64SymbolFilter = { symbols -> - def retList = [] - symbols.each { symbol -> - if (symbol.startsWith('HAL_') || symbol.startsWith('HALSIM_')) { - retList << symbol - } - } - return retList - } + x64SymbolFilter = { symbols -> + symbols.removeIf({ !it.startsWith('HAL_') && !it.startsWith('HALSIM_') }) } } } diff --git a/hal/simjni.gradle b/hal/simjni.gradle index 599f0949b7..c1aef73dc4 100644 --- a/hal/simjni.gradle +++ b/hal/simjni.gradle @@ -12,7 +12,7 @@ task generateAthenaSimFiles() { it.all { component -> if (component in getJniSpecClass()) { component.binaries.all { binary -> - if (binary.targetPlatform.architecture.name == 'athena') { + if (binary.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { binary.tasks.withType(CppCompile) { it.dependsOn createdTask } diff --git a/myRobot/build.gradle b/myRobot/build.gradle index 0c047e84d7..8f296cec22 100644 --- a/myRobot/build.gradle +++ b/myRobot/build.gradle @@ -110,7 +110,7 @@ model { if (it in NativeExecutableSpec && it.name == "myRobotCpp") { it.binaries.each { if (!found) { - def arch = it.targetPlatform.architecture.name + def arch = it.targetPlatform.name if (arch == systemArch) { dependsOn it.tasks.install commandLine it.tasks.install.runScriptFile.get().asFile.toString() @@ -129,14 +129,14 @@ model { } installAthena(Task) { $.binaries.each { - if (it in NativeExecutableBinarySpec && it.targetPlatform.architecture.name == 'athena' && it.component.name == 'myRobotCpp') { + if (it in NativeExecutableBinarySpec && it.targetPlatform.name == nativeUtils.wpi.platforms.roborio && it.component.name == 'myRobotCpp') { dependsOn it.tasks.install } } } installAthenaStatic(Task) { $.binaries.each { - if (it in NativeExecutableBinarySpec && it.targetPlatform.architecture.name == 'athena' && it.component.name == 'myRobotCppStatic') { + if (it in NativeExecutableBinarySpec && it.targetPlatform.name == nativeUtils.wpi.platforms.roborio && it.component.name == 'myRobotCppStatic') { dependsOn it.tasks.install } } diff --git a/ntcore/build.gradle b/ntcore/build.gradle index 659b0f9214..5739b71113 100644 --- a/ntcore/build.gradle +++ b/ntcore/build.gradle @@ -5,45 +5,29 @@ ext { apply from: "${rootDir}/shared/jni/setupBuild.gradle" -model { - // Exports config is a utility to enable exporting all symbols in a C++ library on windows to a DLL. - // This removes the need for DllExport on a library. However, the gradle C++ builder has a bug - // where some extra symbols are added that cannot be resolved at link time. This configuration - // lets you specify specific symbols to exlude from exporting. - exportsConfigs { - ntcore(ExportsConfig) { - x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVbad_cast', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure'] - x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVbad_cast', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure'] +nativeUtils.exportsConfigs { + ntcore { + x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] + x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] + } + ntcoreJNI { + x86SymbolFilter = { symbols -> + symbols.removeIf({ !it.startsWith('NT_') }) } - ntcoreJNI(ExportsConfig) { - x86SymbolFilter = { symbols -> - def retList = [] - symbols.each { symbol -> - if (symbol.startsWith('NT_')) { - retList << symbol - } - } - return retList - } - x64SymbolFilter = { symbols -> - def retList = [] - symbols.each { symbol -> - if (symbol.startsWith('NT_')) { - retList << symbol - } - } - return retList - } + x64SymbolFilter = { symbols -> + symbols.removeIf({ !it.startsWith('NT_') }) } } } -pmdMain { - pmdMain.enabled = false +if (!project.hasProperty('skipPMD')) { + pmdMain { + pmdMain.enabled = false + } } diff --git a/shared/config.gradle b/shared/config.gradle index d5ac9b17da..2a66371269 100644 --- a/shared/config.gradle +++ b/shared/config.gradle @@ -1,251 +1,40 @@ -import edu.wpi.first.nativeutils.* import org.gradle.internal.os.OperatingSystem -def windowsCompilerArgs = ['/EHsc', '/D_CRT_SECURE_NO_WARNINGS', '/Zi', '/FS', '/Zc:inline', '/W3', '/wd4244', '/wd4267', '/wd4146', '/wd4996', '/std:c++17', '/Zc:throwingNew', '/permissive-', '/WX'] -def windowsCCompilerArgs = ['/Zi', '/FS', '/Zc:inline', '/W3', '/WX'] -def windowsReleaseCompilerArgs = ['/O2', '/MD'] -def windowsDebugCompilerArgs = ['/Od', '/MDd'] -def windowsLinkerArgs = ['/DEBUG:FULL'] -def windowsReleaseLinkerArgs = ['/OPT:REF', '/OPT:ICF'] - -def linuxCrossCompilerArgs = ['-std=c++17', '-Wformat=2', '-Wall', '-Wextra', '-Werror', '-pedantic', '-Wno-psabi', '-g', - '-Wno-unused-parameter', '-Wno-error=deprecated-declarations', '-fPIC', '-rdynamic', - '-pthread'] -def linuxCrossCCompilerArgs = ['-Wformat=2', '-Wall', '-Wextra', '-Werror', '-pedantic', '-Wno-psabi', '-g', - '-Wno-unused-parameter', '-fPIC', '-rdynamic', '-pthread'] -def linuxCrossLinkerArgs = ['-rdynamic', '-pthread', '-ldl'] -def linuxCrossReleaseCompilerArgs = ['-O2'] -def linuxCrossDebugCompilerArgs = ['-Og'] - -def linuxCompilerArgs = ['-std=c++17', '-Wformat=2', '-Wall', '-Wextra', '-Werror', '-pedantic', '-Wno-psabi', '-g', - '-Wno-unused-parameter', '-Wno-error=deprecated-declarations', '-fPIC', '-rdynamic', - '-pthread'] -def linuxCCompilerArgs = ['-Wformat=2', '-Wall', '-Wextra', '-Werror', '-pedantic', '-Wno-psabi', '-g', - '-Wno-unused-parameter', '-fPIC', '-rdynamic', '-pthread'] -def linuxLinkerArgs = ['-rdynamic', '-pthread', '-ldl'] -def linuxReleaseCompilerArgs = ['-O2'] -def linuxDebugCompilerArgs = ['-O0'] -def linux32BitArg = '-m32' - -def macCompilerArgs = ['-std=c++17', '-Wall', '-Wextra', '-Werror', '-pedantic-errors', '-fPIC', '-g', - '-Wno-unused-parameter', '-Wno-error=deprecated-declarations', '-Wno-missing-field-initializers', - '-Wno-unused-private-field', '-Wno-unused-const-variable', '-pthread'] -def macCCompilerArgs = ['-Wall', '-Wextra', '-Werror', '-pedantic-errors', '-fPIC', '-g', - '-Wno-unused-parameter', '-Wno-missing-field-initializers', '-Wno-unused-private-field'] -def macObjCLinkerArgs = ['-std=c++17', '-stdlib=libc++','-fobjc-arc', '-g', '-fPIC', '-Wall', '-Wextra', '-Werror'] -def macReleaseCompilerArgs = ['-O2'] -def macDebugCompilerArgs = ['-O0'] -def macLinkerArgs = ['-framework', 'CoreFoundation', '-framework', 'AVFoundation', '-framework', 'Foundation', '-framework', 'CoreMedia', '-framework', 'CoreVideo'] -def mac32BitArg = '-m32' - -def buildAll = project.hasProperty('buildAll') - -def windows64PlatformDetect = { - def arch = System.getProperty("os.arch") - def isWin = OperatingSystem.current().isWindows() - if (buildAll) { - return isWin - } else { - return isWin && arch == 'amd64' +nativeUtils.addWpiNativeUtils() +nativeUtils.withRaspbian() +nativeUtils { + wpi { + configureDependencies { + wpiVersion = "-1" + niLibVersion = "2019.12.1" + opencvVersion = "3.4.4-5" + googleTestVersion = "1.8.1-1-f71fb4f" } + } } -def windows32PlatformDetect = { - def arch = System.getProperty("os.arch") - def isWin = OperatingSystem.current().isWindows() - if (buildAll) { - return isWin - } else { - return isWin && arch == 'x86' - } +nativeUtils.wpi.addWarnings() +nativeUtils.wpi.addWarningsAsErrors() + +nativeUtils.setSinglePrintPerPlatform() + +toolchainsPlugin.crossCompilers.named(nativeUtils.wpi.platforms.roborio) { + optional.set(true) } -def linux32IntelPlatformDetect = { - def arch = System.getProperty("os.arch") - def isLinux = OperatingSystem.current().isLinux() - def isIntel = (arch == 'amd64' || arch == 'i386') - if (buildAll) { - return isLinux && isIntel - } else { - return isLinux && arch == 'i386' - } -} - -def linux64IntelPlatformDetect = { - def arch = System.getProperty("os.arch") - def isLinux = OperatingSystem.current().isLinux() - def isIntel = (arch == 'amd64' || arch == 'i386') - if (buildAll) { - return isLinux && isIntel - } else { - return isLinux && arch == 'amd64' - } -} - -def linuxArmPlatformDetect = { - def arch = System.getProperty("os.arch") - def isIntel = (arch == 'amd64' || arch == 'i386') - return OperatingSystem.current().isLinux() && !isIntel -} - -def mac64PlatformDetect = { - def arch = System.getProperty("os.arch") - def isMac = OperatingSystem.current().isMacOsX() - if (buildAll) { - return isMac - } else { - return isMac && arch == 'x86_64' - } -} - -def mac32PlatformDetect = { - def arch = System.getProperty("os.arch") - def isMac = OperatingSystem.current().isMacOsX() - if (buildAll) { - return isMac - } else { - return isMac && arch == 'x86' - } -} - -if (!project.hasProperty('skipAthena') && !project.hasProperty('onlyRaspbian')) { - model { - buildConfigs { - roboRio(CrossBuildConfig) { - architecture = 'athena' - operatingSystem = 'linux' - toolChainPrefix = 'arm-frc2019-linux-gnueabi-' - compilerArgs = linuxCrossCompilerArgs - CCompilerArgs = linuxCrossCCompilerArgs - linkerArgs = linuxCrossLinkerArgs - debugCompilerArgs = linuxCrossDebugCompilerArgs - releaseCompilerArgs = linuxCrossReleaseCompilerArgs - stripBuildTypes = ['debug', 'release'] - compilerFamily = 'Gcc' - } +model { + components { + all { + nativeUtils.useAllPlatforms(it) } } -} - -if (!project.hasProperty('skipRaspbian') && !project.hasProperty('onlyAthena')) { - model { - buildConfigs { - raspbian(CrossBuildConfig) { - architecture = 'raspbian' - operatingSystem = 'linux' - toolChainPrefix = 'arm-raspbian9-linux-gnueabihf-' - compilerArgs = linuxCrossCompilerArgs - CCompilerArgs = linuxCrossCCompilerArgs - linkerArgs = linuxCrossLinkerArgs - debugCompilerArgs = linuxCrossDebugCompilerArgs - releaseCompilerArgs = linuxCrossReleaseCompilerArgs - stripBuildTypes = ['debug', 'release'] - compilerFamily = 'Gcc' - } + binaries { + withType(NativeBinarySpec).all { + nativeUtils.usePlatformArguments(it) } } } -if (!project.hasProperty('onlyAthena') && !hasProperty('onlyRaspbian')) { - model { - buildConfigs { - winX86(BuildConfig) { - architecture = 'x86' - operatingSystem = 'windows' - compilerArgs = windowsCompilerArgs - CCompilerArgs = windowsCCompilerArgs - linkerArgs = windowsLinkerArgs - releaseCompilerArgs = windowsReleaseCompilerArgs - releaseLinkerArgs = windowsReleaseLinkerArgs - debugCompilerArgs = windowsDebugCompilerArgs - compilerFamily = 'VisualCpp' - detectPlatform = windows32PlatformDetect - } - winX64(BuildConfig) { - architecture = 'x86-64' - operatingSystem = 'windows' - compilerArgs = windowsCompilerArgs - CCompilerArgs = windowsCCompilerArgs - linkerArgs = windowsLinkerArgs - releaseCompilerArgs = windowsReleaseCompilerArgs - releaseLinkerArgs = windowsReleaseLinkerArgs - debugCompilerArgs = windowsDebugCompilerArgs - compilerFamily = 'VisualCpp' - detectPlatform = windows64PlatformDetect - } - linuxX64(BuildConfig) { - architecture = 'x86-64' - operatingSystem = 'linux' - compilerArgs = linuxCompilerArgs - CCompilerArgs = linuxCCompilerArgs - linkerArgs = linuxLinkerArgs - debugCompilerArgs = linuxDebugCompilerArgs - releaseCompilerArgs = linuxReleaseCompilerArgs - stripBuildTypes = ['debug', 'release'] - compilerFamily = 'Gcc' - detectPlatform = linux64IntelPlatformDetect - } - macX64(BuildConfig) { - architecture = 'x86-64' - operatingSystem = 'osx' - compilerArgs = macCompilerArgs - CCompilerArgs = macCCompilerArgs - debugCompilerArgs = macDebugCompilerArgs - releaseCompilerArgs = macReleaseCompilerArgs - objCppCompilerArgs = macObjCLinkerArgs - linkerArgs = macLinkerArgs - compilerFamily = 'Clang' - detectPlatform = mac64PlatformDetect - } - } - } -} - -if (project.hasProperty('linuxCross')) { - model { - buildConfigs { - linuxArm(CrossBuildConfig) { - architecture = 'nativearm' - operatingSystem = 'linux' - toolChainPrefix = 'PLEASE_PROVIDE_A_COMPILER_NAME' - compilerArgs = linuxCompilerArgs - CCompilerArgs = linuxCCompilerArgs - linkerArgs = linuxLinkerArgs - debugCompilerArgs = linuxDebugCompilerArgs - releaseCompilerArgs = linuxReleaseCompilerArgs - stripBuildTypes = ['debug', 'release'] - skipByDefault = true - compilerFamily = 'Gcc' - } - } - } -} else { - model { - buildConfigs { - linuxArm(BuildConfig) { - architecture = 'nativearm' - operatingSystem = 'linux' - compilerArgs = linuxCompilerArgs - CCompilerArgs = linuxCCompilerArgs - linkerArgs = linuxLinkerArgs - debugCompilerArgs = linuxDebugCompilerArgs - releaseCompilerArgs = linuxReleaseCompilerArgs - stripBuildTypes = ['debug', 'release'] - compilerFamily = 'Gcc' - detectPlatform = linuxArmPlatformDetect - } - } - } -} - -ext.getPublishClassifier = { binary -> - return NativeUtils.getPublishClassifier(binary) -} - -ext.getPlatformPath = { binary -> - return NativeUtils.getPlatformPath(binary) -} - ext.appendDebugPathToBinaries = { binaries-> binaries.withType(StaticLibraryBinarySpec) { if (it.buildType.name.contains('debug')) { @@ -287,7 +76,7 @@ ext.createComponentZipTasks = { components, names, base, type, project, func -> if (it in NativeLibrarySpec && stringNames.contains(it.name)) { it.binaries.each { if (!it.buildable) return - def target = getPublishClassifier(it) + def target = nativeUtils.getPublishClassifier(it) if (configMap.containsKey(target)) { configMap.get(target).add(it) } else { @@ -358,38 +147,26 @@ ext.includeStandardZipFormat = { task, value -> if (binary instanceof SharedLibraryBinarySpec) { task.dependsOn binary.tasks.link task.from(new File(binary.sharedLibraryFile.absolutePath + ".debug")) { - into getPlatformPath(binary) + '/shared' + into nativeUtils.getPlatformPath(binary) + '/shared' } def sharedPath = binary.sharedLibraryFile.absolutePath sharedPath = sharedPath.substring(0, sharedPath.length() - 4) task.from(new File(sharedPath + '.pdb')) { - into getPlatformPath(binary) + '/shared' + into nativeUtils.getPlatformPath(binary) + '/shared' } task.from(binary.sharedLibraryFile) { - into getPlatformPath(binary) + '/shared' + into nativeUtils.getPlatformPath(binary) + '/shared' } task.from(binary.sharedLibraryLinkFile) { - into getPlatformPath(binary) + '/shared' + into nativeUtils.getPlatformPath(binary) + '/shared' } } else if (binary instanceof StaticLibraryBinarySpec) { task.dependsOn binary.tasks.createStaticLib task.from(binary.staticLibraryFile) { - into getPlatformPath(binary) + '/static' + into nativeUtils.getPlatformPath(binary) + '/static' } } } } } - -ext.getCurrentArch = { - def arch = System.getProperty('os.arch'); - - if (arch.equals("x86") || arch.equals("i386")) { - return 'x86' - } else if (arch.equals("amd64") || arch.equals("x86_64")) { - return 'x86-64' - } else { - return arch - } -} diff --git a/shared/googletest.gradle b/shared/googletest.gradle index 893c17c73b..4ca8eca770 100644 --- a/shared/googletest.gradle +++ b/shared/googletest.gradle @@ -1,13 +1,8 @@ model { - dependencyConfigs { - googletest(DependencyConfig) { - groupId = 'edu.wpi.first.thirdparty.frc2019' - artifactId = 'googletest' - headerClassifier = 'headers' - ext = 'zip' - version = '1.8.1-1-f71fb4f' - sharedConfigs = [:] - staticConfigs = project.staticGtestConfigs + binaries { + withType(GoogleTestTestSuiteBinarySpec).all { + if (it.targetPlatform.name != nativeUtils.wpi.platforms.raspbian) + nativeUtils.useRequiredLibrary(it, 'googletest_static') } } } diff --git a/shared/java/javacommon.gradle b/shared/java/javacommon.gradle index 969b4876a8..cd011455d3 100644 --- a/shared/java/javacommon.gradle +++ b/shared/java/javacommon.gradle @@ -87,7 +87,7 @@ test { } } -if (project.hasProperty('onlyAthena') || project.hasProperty('onlyRaspbian')) { +if (project.hasProperty('onlylinuxathena') || project.hasProperty('onlylinuxraspbian')) { test.enabled = false } diff --git a/shared/java/javastyle.gradle b/shared/java/javastyle.gradle index e0919883a5..6e4e2611ad 100644 --- a/shared/java/javastyle.gradle +++ b/shared/java/javastyle.gradle @@ -1,6 +1,5 @@ apply plugin: 'checkstyle' -apply plugin: 'pmd' checkstyle { toolVersion = "8.12" @@ -8,10 +7,14 @@ checkstyle { config = resources.text.fromFile(new File(configDir, "checkstyle.xml")) } -pmd { - toolVersion = '6.7.0' - consoleOutput = true - reportsDir = file("$project.buildDir/reports/pmd") - ruleSetFiles = files(new File(rootDir, "styleguide/pmd-ruleset.xml")) - ruleSets = [] +if (!project.hasProperty('skipPMD')) { + apply plugin: 'pmd' + + pmd { + toolVersion = '6.7.0' + consoleOutput = true + reportsDir = file("$project.buildDir/reports/pmd") + ruleSetFiles = files(new File(rootDir, "styleguide/pmd-ruleset.xml")) + ruleSets = [] + } } diff --git a/shared/javacpp/setupBuild.gradle b/shared/javacpp/setupBuild.gradle index d2cdd1d866..078af7df36 100644 --- a/shared/javacpp/setupBuild.gradle +++ b/shared/javacpp/setupBuild.gradle @@ -103,7 +103,7 @@ model { } binaries { withType(GoogleTestTestSuiteBinarySpec) { - if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian')) { lib library: nativeName, linkage: 'shared' } else { it.buildable = false @@ -121,7 +121,7 @@ model { if (it in NativeExecutableSpec && it.name == "${nativeName}Dev") { it.binaries.each { if (!found) { - def arch = it.targetPlatform.architecture.name + def arch = it.targetPlatform.name if (arch == systemArch) { dependsOn it.tasks.install commandLine it.tasks.install.runScriptFile.get().asFile.toString() diff --git a/shared/jni/publish.gradle b/shared/jni/publish.gradle index a6a1abe11b..7908304525 100644 --- a/shared/jni/publish.gradle +++ b/shared/jni/publish.gradle @@ -82,13 +82,13 @@ model { task.outputs.file(hashFile) task.inputs.file(binary.sharedLibraryFile) task.from(hashFile) { - into getPlatformPath(binary) + into nativeUtils.getPlatformPath(binary) } task.doFirst { hashFile.text = MessageDigest.getInstance("MD5").digest(binary.sharedLibraryFile.bytes).encodeHex().toString() } task.from(binary.sharedLibraryFile) { - into getPlatformPath(binary) + into nativeUtils.getPlatformPath(binary) } } } diff --git a/shared/jni/setupBuild.gradle b/shared/jni/setupBuild.gradle index a22a67d185..d73476d3f0 100644 --- a/shared/jni/setupBuild.gradle +++ b/shared/jni/setupBuild.gradle @@ -106,8 +106,8 @@ model { } enableCheckTask true javaCompileTasks << compileJava - jniCrossCompileOptions << JniCrossCompileOptions('athena') - jniCrossCompileOptions << JniCrossCompileOptions('raspbian') + jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.roborio) + jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.raspbian) sources { cpp { source { @@ -144,8 +144,8 @@ model { } enableCheckTask true javaCompileTasks << compileJava - jniCrossCompileOptions << JniCrossCompileOptions('athena') - jniCrossCompileOptions << JniCrossCompileOptions('raspbian') + jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.roborio) + jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.raspbian) sources { cpp { source { @@ -224,7 +224,7 @@ model { } binaries { withType(GoogleTestTestSuiteBinarySpec) { - if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian')) { lib library: nativeName, linkage: 'shared' lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared' } else { @@ -243,7 +243,7 @@ model { if (it in NativeExecutableSpec && it.name == "${nativeName}Dev") { it.binaries.each { if (!found) { - def arch = it.targetPlatform.architecture.name + def arch = it.targetPlatform.name if (arch == systemArch) { dependsOn it.tasks.install commandLine it.tasks.install.runScriptFile.get().asFile.toString() diff --git a/shared/nilibraries.gradle b/shared/nilibraries.gradle index 937abbf7a0..49e99b0d51 100644 --- a/shared/nilibraries.gradle +++ b/shared/nilibraries.gradle @@ -1,37 +1,10 @@ -def netCommLibConfigs = [:]; -def chipObjectConfigs = [:]; - -project.chipObjectComponents.each { String s-> - chipObjectConfigs[s] = ['linux:athena'] -} - -project.netCommComponents.each { String s-> - netCommLibConfigs[s] = ['linux:athena'] -} - -def niLibrariesVersion = '2019.12.1' - model { - dependencyConfigs { - chipobject(DependencyConfig) { - groupId = 'edu.wpi.first.ni-libraries' - artifactId = 'chipobject' - headerClassifier = 'headers' - ext = 'zip' - version = niLibrariesVersion - sharedConfigs = chipObjectConfigs - staticConfigs = [:] - compileOnlyShared = true - } - netcomm(DependencyConfig) { - groupId = 'edu.wpi.first.ni-libraries' - artifactId = 'netcomm' - headerClassifier = 'headers' - ext = 'zip' - version = niLibrariesVersion - sharedConfigs = netCommLibConfigs - staticConfigs = [:] - compileOnlyShared = true + binaries { + all { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { + nativeUtils.useRequiredLibrary(it, 'netcomm_shared', 'chipobject_shared') + } + } } } diff --git a/shared/opencv.gradle b/shared/opencv.gradle index 09fa8be465..21540fe8a4 100644 --- a/shared/opencv.gradle +++ b/shared/opencv.gradle @@ -2,16 +2,19 @@ def opencvVersion = '3.4.4-5' if (project.hasProperty('useCpp') && project.useCpp) { model { - dependencyConfigs { - opencv(DependencyConfig) { - groupId = 'edu.wpi.first.thirdparty.frc2019.opencv' - artifactId = 'opencv-cpp' - headerClassifier = 'headers' - ext = 'zip' - version = opencvVersion - sharedConfigs = project.sharedCvConfigs - staticConfigs = project.staticCvConfigs - linkExcludes = ['**/*java*'] + binaries { + withType(NativeBinarySpec).all { + def binary = it + project.sharedCvConfigs.each { + if (binary.component.name == it.key) { + nativeUtils.useRequiredLibrary(binary, 'opencv_shared') + } + } + project.staticCvConfigs.each { + if (binary.component.name == it.key) { + nativeUtils.useRequiredLibrary(binary, 'opencv_static') + } + } } } } diff --git a/shared/plugins/publish.gradle b/shared/plugins/publish.gradle index a9ba5384fd..5379b44a53 100644 --- a/shared/plugins/publish.gradle +++ b/shared/plugins/publish.gradle @@ -56,7 +56,7 @@ model { if (binary instanceof SharedLibraryBinarySpec) { task.dependsOn binary.buildTask task.from(binary.sharedLibraryFile) { - into getPlatformPath(binary) + '/shared' + into nativeUtils.getPlatformPath(binary) + '/shared' } } } diff --git a/shared/plugins/setupBuild.gradle b/shared/plugins/setupBuild.gradle index ba4c6f0b65..8591f079d2 100644 --- a/shared/plugins/setupBuild.gradle +++ b/shared/plugins/setupBuild.gradle @@ -10,7 +10,7 @@ ext { apply from: "${rootDir}/shared/nilibraries.gradle" -if (!project.hasProperty('onlyAthena')) { +if (!project.hasProperty('onlylinuxathena')) { ext.skipAthena = true apply from: "${rootDir}/shared/config.gradle" @@ -57,7 +57,7 @@ if (!project.hasProperty('onlyAthena')) { } } binaries.all { - if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian')) { project(':hal').addHalDependency(it, 'shared') lib library: pluginName if (project.hasProperty('includeNtCore')) { @@ -78,7 +78,7 @@ if (!project.hasProperty('onlyAthena')) { model { tasks { def c = $.components - if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian')) { project.tasks.create('runCpp', Exec) { group = 'WPILib' description = "Run the ${pluginName}Dev executable" @@ -88,7 +88,7 @@ model { if (it in NativeExecutableSpec && it.name == "${pluginName}Dev") { it.binaries.each { if (!found) { - def arch = it.targetPlatform.architecture.name + def arch = it.targetPlatform.name if (arch == systemArch) { dependsOn it.tasks.install commandLine it.tasks.install.runScriptFile.get().asFile.toString() diff --git a/simulation/gz_msgs/build.gradle b/simulation/gz_msgs/build.gradle index 8264ceb2b8..aa0982595c 100644 --- a/simulation/gz_msgs/build.gradle +++ b/simulation/gz_msgs/build.gradle @@ -1,95 +1,95 @@ -plugins { - id 'cpp' - id 'java' - id 'com.google.protobuf' version '0.8.6' - id 'edu.wpi.first.NativeUtils' -} - -description = "A C++ and Java library to pass FRC Simulation Messages in and out of Gazebo." - -/* The simulation does not run on real hardware; so we always skip Athena */ -ext.skipAthena = true -ext.skipRaspbian = true -apply from: "${rootDir}/shared/config.gradle" - -/* Use a sort of poor man's autoconf to find the protobuf development - files; on Debian, those are supplied by libprotobuf-dev. - - This should get skipped on Windows. - - TODO: Add Windows support for the simulation code */ - -def protobuf_version = "" -try { - protobuf_version = "pkg-config --modversion protobuf".execute().text.trim() - println "Protobuf version is [${protobuf_version}]" -} catch(Exception ex) { -} - -if (!protobuf_version?.trim()) { - println "Protobuf is not available. (pkg-config --modversion protobuf failed)" - protobuf_version = "+" - if (project.hasProperty("makeSim")) { - /* Force the build even though we did not find protobuf. */ - println "makeSim set. Forcing build - failure likely." - } - else { - ext.skip_gz_msgs = true - println "Skipping gz_msgs." - } -} - -tasks.whenTaskAdded { task -> - task.onlyIf { !project.hasProperty('skip_gz_msgs') } -} - -dependencies { - compile "com.google.protobuf:protobuf-java:${protobuf_version}" - compile "com.google.protobuf:protoc:${protobuf_version}" -} - -/* There is a nice gradle plugin for protobuf, and the protoc tool - is included; using it simplifies our build process. - The trick is that we have to use the same version as the system - copy of libprotobuf-dev */ -protobuf { - protoc { - artifact = "com.google.protobuf:protoc:${protobuf_version}" - } - - generatedFilesBaseDir = "$buildDir/generated" - generateProtoTasks { - all().each { task -> - task.builtins { - cpp { - outputSubDir = 'simulation/gz_msgs' - } - } - } - } -} - -model { - components { - gz_msgs(NativeLibrarySpec) { - sources { - cpp { - source { - srcDir "$buildDir/generated/main/simulation/gz_msgs" - builtBy tasks.generateProto - } - exportedHeaders { - srcDir "src/include" - srcDir "$buildDir/generated/main" - } - } - } - /* We must compile with -fPIC to link the static library into an so */ - binaries { - all { - cppCompiler.args "-fPIC" - } - } - } - } -} +plugins { + id 'cpp' + id 'java' + id 'com.google.protobuf' version '0.8.8' + id 'edu.wpi.first.NativeUtils' +} + +description = "A C++ and Java library to pass FRC Simulation Messages in and out of Gazebo." + +/* The simulation does not run on real hardware; so we always skip Athena */ +ext.skipAthena = true +ext.skipRaspbian = true +apply from: "${rootDir}/shared/config.gradle" + +/* Use a sort of poor man's autoconf to find the protobuf development + files; on Debian, those are supplied by libprotobuf-dev. + + This should get skipped on Windows. + + TODO: Add Windows support for the simulation code */ + +def protobuf_version = "" +try { + protobuf_version = "pkg-config --modversion protobuf".execute().text.trim() + println "Protobuf version is [${protobuf_version}]" +} catch(Exception ex) { +} + +if (!protobuf_version?.trim()) { + println "Protobuf is not available. (pkg-config --modversion protobuf failed)" + protobuf_version = "+" + if (project.hasProperty("makeSim")) { + /* Force the build even though we did not find protobuf. */ + println "makeSim set. Forcing build - failure likely." + } + else { + ext.skip_gz_msgs = true + println "Skipping gz_msgs." + } +} + +tasks.whenTaskAdded { task -> + task.onlyIf { !project.hasProperty('skip_gz_msgs') } +} + +dependencies { + compile "com.google.protobuf:protobuf-java:${protobuf_version}" + compile "com.google.protobuf:protoc:${protobuf_version}" +} + +/* There is a nice gradle plugin for protobuf, and the protoc tool + is included; using it simplifies our build process. + The trick is that we have to use the same version as the system + copy of libprotobuf-dev */ +protobuf { + protoc { + artifact = "com.google.protobuf:protoc:${protobuf_version}" + } + + generatedFilesBaseDir = "$buildDir/generated" + generateProtoTasks { + all().each { task -> + task.builtins { + cpp { + outputSubDir = 'simulation/gz_msgs' + } + } + } + } +} + +model { + components { + gz_msgs(NativeLibrarySpec) { + sources { + cpp { + source { + srcDir "$buildDir/generated/main/simulation/gz_msgs" + builtBy tasks.generateProto + } + exportedHeaders { + srcDir "src/include" + srcDir "$buildDir/generated/main" + } + } + } + /* We must compile with -fPIC to link the static library into an so */ + binaries { + all { + cppCompiler.args "-fPIC" + } + } + } + } +} diff --git a/simulation/halsim_adx_gyro_accelerometer/build.gradle b/simulation/halsim_adx_gyro_accelerometer/build.gradle index c9f754dde6..f73804d9a0 100644 --- a/simulation/halsim_adx_gyro_accelerometer/build.gradle +++ b/simulation/halsim_adx_gyro_accelerometer/build.gradle @@ -11,7 +11,7 @@ ext { apply from: "${rootDir}/shared/config.gradle" -if (!project.hasProperty('onlyAthena')) { +if (!project.hasProperty('onlylinuxathena')) { ext { sharedCvConfigs = [halsim_adx_gyro_accelerometerTest: []] @@ -37,19 +37,20 @@ if (!project.hasProperty('onlyAthena')) { apply from: "${rootDir}/shared/nilibraries.gradle" - model { - exportsConfigs { - halsim_adx_gyro_accelerometer(ExportsConfig) { - x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVbad_cast', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure'] - x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVbad_cast', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure'] - } + nativeUtils.exportsConfigs { + halsim_adx_gyro_accelerometer { + x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] + x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] } + } + + model { components { "${nativeName}Base"(NativeLibrarySpec) { sources { @@ -68,7 +69,7 @@ if (!project.hasProperty('onlyAthena')) { it.buildable = false return } - if (it.targetPlatform.architecture.name == 'athena') { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -89,7 +90,7 @@ if (!project.hasProperty('onlyAthena')) { } } binaries.all { - if (it.targetPlatform.architecture.name == 'athena') { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -114,7 +115,7 @@ if (!project.hasProperty('onlyAthena')) { } } binaries.all { - if (it.targetPlatform.architecture.name == 'athena') { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -126,7 +127,7 @@ if (!project.hasProperty('onlyAthena')) { } binaries { withType(GoogleTestTestSuiteBinarySpec) { - if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian')) { lib project: ':ntcore', library: 'ntcore', linkage: 'shared' lib project: ':cscore', library: 'cscore', linkage: 'shared' project(':hal').addHalDependency(it, 'shared') @@ -147,7 +148,7 @@ if (!project.hasProperty('onlyAthena')) { model { testSuites { - if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian')) { "${nativeName}Test"(GoogleTestTestSuiteSpec) { for(NativeComponentSpec c : $.components) { if (c.name == nativeName) { diff --git a/simulation/halsim_ds_socket/build.gradle b/simulation/halsim_ds_socket/build.gradle index 0200980c99..98c5fe7ccb 100644 --- a/simulation/halsim_ds_socket/build.gradle +++ b/simulation/halsim_ds_socket/build.gradle @@ -21,7 +21,7 @@ apply from: "${rootDir}/shared/plugins/setupBuild.gradle" model { testSuites { def comps = $.components - if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian')) { "${pluginName}Test"(GoogleTestTestSuiteSpec) { for(NativeComponentSpec c : comps) { if (c.name == pluginName) { diff --git a/simulation/lowfi_simulation/build.gradle b/simulation/lowfi_simulation/build.gradle index 2b97416e54..e42ea3bfa6 100644 --- a/simulation/lowfi_simulation/build.gradle +++ b/simulation/lowfi_simulation/build.gradle @@ -12,7 +12,7 @@ ext { apply from: "${rootDir}/shared/config.gradle" -if (!project.hasProperty('onlyAthena')) { +if (!project.hasProperty('onlylinuxathena')) { ext { sharedCvConfigs = [lowfi_simTest: []] @@ -40,19 +40,20 @@ if (!project.hasProperty('onlyAthena')) { apply from: "${rootDir}/shared/nilibraries.gradle" - model { - exportsConfigs { - lowfi_sim(ExportsConfig) { - x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVbad_cast', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure'] - x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVbad_cast', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure'] - } + nativeUtils.exportsConfigs { + lowfi_sim { + x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] + x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] } + } + + model { components { "${nativeName}Base"(NativeLibrarySpec) { sources { @@ -71,7 +72,7 @@ if (!project.hasProperty('onlyAthena')) { it.buildable = false return } - if (it.targetPlatform.architecture.name == 'athena') { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -93,7 +94,7 @@ if (!project.hasProperty('onlyAthena')) { } } binaries.all { - if (it.targetPlatform.architecture.name == 'athena') { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -119,7 +120,7 @@ if (!project.hasProperty('onlyAthena')) { } } binaries.all { - if (it.targetPlatform.architecture.name == 'athena') { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -150,7 +151,7 @@ if (!project.hasProperty('onlyAthena')) { model { testSuites { - if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian')) { "${nativeName}Test"(GoogleTestTestSuiteSpec) { for(NativeComponentSpec c : $.components) { if (c.name == nativeName) { diff --git a/wpilibc/build.gradle b/wpilibc/build.gradle index 3b5b3e12a0..61154d3c23 100644 --- a/wpilibc/build.gradle +++ b/wpilibc/build.gradle @@ -81,19 +81,20 @@ ext { apply from: "${rootDir}/shared/nilibraries.gradle" -model { - exportsConfigs { - wpilibc(ExportsConfig) { - x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVbad_cast', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure'] - x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVbad_cast', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure'] - } +nativeUtils.exportsConfigs { + wpilibc { + x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] + x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] } +} + +model { components { "${nativeName}Base"(NativeLibrarySpec) { sources { @@ -202,7 +203,7 @@ model { } } withType(GoogleTestTestSuiteBinarySpec) { - if (!project.hasProperty('onlyAthena') && !project.hasProperty('onlyRaspbian')) { + if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian')) { lib project: ':ntcore', library: 'ntcore', linkage: 'shared' lib project: ':cscore', library: 'cscore', linkage: 'shared' project(':hal').addHalDependency(it, 'shared') diff --git a/wpilibcExamples/build.gradle b/wpilibcExamples/build.gradle index af1b25af9c..ec790c0df1 100644 --- a/wpilibcExamples/build.gradle +++ b/wpilibcExamples/build.gradle @@ -94,7 +94,7 @@ model { project(':hal').addHalDependency(binary, 'shared') lib project: ':cameraserver', library: 'cameraserver', linkage: 'shared' lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared' - if (binary.targetPlatform.architecture.name != 'athena') { + if (binary.targetPlatform.name != nativeUtils.wpi.platforms.roborio) { lib project: ':simulation:halsim_lowfi', library: 'halsim_lowfi', linkage: 'shared' lib project: ':simulation:halsim_adx_gyro_accelerometer', library: 'halsim_adx_gyro_accelerometer', linkage: 'shared' lib project: ':simulation:halsim_print', library: 'halsim_print', linkage: 'shared' @@ -144,7 +144,7 @@ model { cppCompiler.args "/wd4996" } } - if (binary.targetPlatform.architecture.name != 'athena') { + if (binary.targetPlatform.name != nativeUtils.wpi.platforms.roborio) { lib project: ':simulation:halsim_lowfi', library: 'halsim_lowfi', linkage: 'shared' lib project: ':simulation:halsim_adx_gyro_accelerometer', library: 'halsim_adx_gyro_accelerometer', linkage: 'shared' lib project: ':simulation:halsim_print', library: 'halsim_print', linkage: 'shared' diff --git a/wpilibcIntegrationTests/build.gradle b/wpilibcIntegrationTests/build.gradle index 0dea400675..8a3797b7f5 100644 --- a/wpilibcIntegrationTests/build.gradle +++ b/wpilibcIntegrationTests/build.gradle @@ -32,8 +32,9 @@ model { wpilibcIntegrationTests(NativeExecutableSpec) { targetBuildTypes 'debug' baseName = 'FRCUserProgram' + nativeUtils.useRequiredLibrary(it, 'googletest_static') binaries.all { binary -> - if (binary.targetPlatform.architecture.name == 'athena') { + if (binary.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { binary.sources { athenaCpp(CppSourceSet) { source { @@ -82,7 +83,7 @@ model { copyWpilibCTestLibrariesToOutput(Copy) { def task = it $.binaries.each { - if (it in NativeExecutableBinarySpec && it.targetPlatform.architecture.name == 'athena') { + if (it in NativeExecutableBinarySpec && it.targetPlatform.name == nativeUtils.wpi.platforms.roborio && it.buildable) { def installTask = it.tasks.install task.dependsOn installTask task.from(installTask.executableFile) { @@ -99,7 +100,7 @@ model { } // This is in a separate if statement because of what I would assume is a bug in grade. // Will file an issue on their side. - if (!project.hasProperty('skipAthena')) { + if (!project.hasProperty('skiponlyathena')) { build.dependsOn copyWpilibCTestLibrariesToOutput } } diff --git a/wpilibj/build.gradle b/wpilibj/build.gradle index 82e94bb4f2..8e19140432 100644 --- a/wpilibj/build.gradle +++ b/wpilibj/build.gradle @@ -133,7 +133,7 @@ model { if (it in NativeExecutableSpec && it.name == "wpilibjDev") { it.binaries.each { if (!found) { - def arch = it.targetPlatform.architecture.name + def arch = it.targetPlatform.name if (arch == systemArch) { dependsOn it.tasks.install commandLine it.tasks.install.runScriptFile.get().asFile.toString() diff --git a/wpilibjExamples/build.gradle b/wpilibjExamples/build.gradle index 55087ba754..d57e143928 100644 --- a/wpilibjExamples/build.gradle +++ b/wpilibjExamples/build.gradle @@ -1,5 +1,4 @@ apply plugin: 'java' -apply plugin: 'pmd' ext { useJava = true @@ -21,11 +20,15 @@ dependencies { compile project(':cameraserver') } -pmd { - consoleOutput = true - reportsDir = file("$project.buildDir/reports/pmd") - ruleSetFiles = files(new File(rootDir, "styleguide/pmd-ruleset.xml")) - ruleSets = [] +if (!project.hasProperty('skipPMD')) { + apply plugin: 'pmd' + + pmd { + consoleOutput = true + reportsDir = file("$project.buildDir/reports/pmd") + ruleSetFiles = files(new File(rootDir, "styleguide/pmd-ruleset.xml")) + ruleSets = [] + } } gradle.projectsEvaluated { diff --git a/wpiutil/build.gradle b/wpiutil/build.gradle index 6b77b39608..c3634f6176 100644 --- a/wpiutil/build.gradle +++ b/wpiutil/build.gradle @@ -29,7 +29,7 @@ ext { } } } - if (it.targetPlatform.operatingSystem.name != 'windows') { + if (!it.targetPlatform.operatingSystem.isWindows()) { it.cppCompiler.define '_GNU_SOURCE' it.sources { libuvUnixCpp(CppSourceSet) { @@ -62,7 +62,7 @@ ext { } } } - if (it.targetPlatform.operatingSystem.name == 'windows') { + if (it.targetPlatform.operatingSystem.isWindows()) { if (it in SharedLibraryBinarySpec) { it.cppCompiler.define 'BUILDING_UV_SHARED' } @@ -77,7 +77,7 @@ ext { } } } - } else if (it.targetPlatform.operatingSystem.name == 'osx') { + } else if (it.targetPlatform.operatingSystem.isMacOsX()) { it.sources { libuvMacCpp(CppSourceSet) { source { @@ -132,6 +132,19 @@ file("$projectDir/examples").list(new FilenameFilter() { apply from: "${rootDir}/shared/javacpp/setupBuild.gradle" +nativeUtils.exportsConfigs { + wpiutil { + x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] + x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', + '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', + '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', + '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] + } +} + cppHeadersZip { from('src/main/native/libuv/include') { into '/' @@ -148,23 +161,9 @@ model { } } } +} - // Exports config is a utility to enable exporting all symbols in a C++ library on windows to a DLL. - // This removes the need for DllExport on a library. However, the gradle C++ builder has a bug - // where some extra symbols are added that cannot be resolved at link time. This configuration - // lets you specify specific symbols to exlude from exporting. - exportsConfigs { - wpiutil(ExportsConfig) { - x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', - '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] - x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure', - '_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure', - '_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range', - '_TI3?AVout_of_range', '_CT??_R0?AVbad_cast'] - } - } +model { components { examplesMap.each { key, value -> "${key}"(NativeExecutableSpec) {