From dc3395af1564265deb2398c4b4e0468a60348ee2 Mon Sep 17 00:00:00 2001 From: Gold856 <117957790+Gold856@users.noreply.github.com> Date: Sun, 22 Dec 2024 12:17:01 -0500 Subject: [PATCH 1/4] Clean up build completely Use CMake to build universal Mac binaries, remove triplet code, remove unnecessary publishing code, and execute CMake from Gradle --- .github/workflows/main.yml | 69 ++------- .gitignore | 5 +- CMakeLists.txt | 10 +- build.gradle | 6 +- copy-headers.sh | 3 - merge.gradle | 166 ---------------------- publish.gradle | 279 ++++++++++++------------------------- 7 files changed, 108 insertions(+), 430 deletions(-) delete mode 100755 copy-headers.sh delete mode 100644 merge.gradle diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8c1832a..ef84e8c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -45,7 +45,7 @@ jobs: include: - container: wpilib/ubuntu-base:22.04 artifact-name: Linux - build-options: -Pplatform=x64-linux + build-options: -Pplatform=linux-x86_64 -Psccache name: "Build - ${{ matrix.artifact-name }}" runs-on: ubuntu-latest @@ -62,8 +62,8 @@ jobs: sudo apt-get install -y ninja-build build-essential - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.5 - - run: ./gradlew publish ${{ matrix.build-options }} - name: Build with Gradle + - name: Build with Gradle + run: ./gradlew publish ${{ matrix.build-options }} env: SCCACHE_GHA_ENABLED: "true" - uses: actions/upload-artifact@v4 @@ -78,10 +78,10 @@ jobs: include: - artifact-name: WinArm64 tool-arch: amd64_arm64 - build-options: -Pplatform=arm64-windows + build-options: -Pplatform=windows-arm64 -Psccache - artifact-name: Win64 tool-arch: amd64 - build-options: -Pplatform=x64-windows + build-options: -Pplatform=windows-x86_64 -Psccache name: "Build - ${{ matrix.artifact-name }}" runs-on: windows-2019 @@ -98,8 +98,8 @@ jobs: arch: ${{ matrix.tool-arch }} - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.5 - - run: ./gradlew publish ${{ matrix.build-options }} - name: Build with Gradle + - name: Build with Gradle + run: ./gradlew publish ${{ matrix.build-options }} env: SCCACHE_GHA_ENABLED: "true" - uses: actions/upload-artifact@v4 @@ -122,8 +122,8 @@ jobs: name: install ninja - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.5 - - run: ./gradlew publish -Pplatform=x64-osx - name: Build with Gradle + - name: Build with Gradle + run: ./gradlew publish -Pplatform=osx-universal -Psccache env: SCCACHE_GHA_ENABLED: "true" - uses: actions/upload-artifact@v4 @@ -131,58 +131,9 @@ jobs: name: macOS path: gradleDir/outputs/ - build-mac-arm: - name: "Build - macOS (Arm)" - runs-on: macOS-14 - steps: - - uses: actions/checkout@v4 - with: - submodules: 'true' - - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: 'temurin' - - run: brew install cmake ninja - name: install ninja - - name: Install sccache - uses: mozilla-actions/sccache-action@v0.0.5 - - run: ./gradlew publish -Pplatform=arm64-osx - name: Build with Gradle - env: - SCCACHE_GHA_ENABLED: "true" - - uses: actions/upload-artifact@v4 - with: - name: macOSArm - path: gradleDir/outputs/ - - make_universal: - name: Make Universal - needs: [build-mac, build-mac-arm] - runs-on: macos-14 - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: macOS - path: build/downloads - - uses: actions/download-artifact@v4 - with: - name: macOSArm - path: build/downloads - - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: 'zulu' - - run: ./gradlew copyToUpload -Prunmerge - name: Build with Gradle - - uses: actions/upload-artifact@v4 - with: - name: macOSUniversal - path: build/toUpload/ - combine: name: Combine - needs: [build-docker, build-windows, make_universal] # , build-roborio] + needs: [build-docker, build-windows, build-mac] # , build-roborio] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index d256601..2ac8abc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ -/vcpkg_installed -/build -/buildDebug +/build* +/install* /.gradle /gradleDir diff --git a/CMakeLists.txt b/CMakeLists.txt index 756fa3e..183a11b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,10 +2,13 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE) endif() -cmake_minimum_required(VERSION 3.16) - +cmake_minimum_required(VERSION 3.25) +set(CMAKE_OSX_ARCHITECTURES arm64 x86_64) +set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded) project(thirdparty-gtsam) +set(GTSAM_COMPILE_OPTIONS_PRIVATE_DEBUG CACHE INTERNAL FORCE) +set(GTSAM_COMPILE_OPTIONS_PRIVATE_RELWITHDEBINFO CACHE INTERNAL FORCE) set(GTSAM_ENABLE_BOOST_SERIALIZATION OFF) set(GTSAM_USE_BOOST_FEATURES OFF) set(GTSAM_BUILD_PYTHON OFF) @@ -21,5 +24,4 @@ fetchcontent_declare( GIT_REPOSITORY https://github.com/borglab/gtsam GIT_TAG 6f7365e1f393d219dad5e65752529c7c0369fefc ) -fetchcontent_makeavailable(gtsam) -add_library(gtsam_static STATIC IMPORTED) +fetchcontent_makeavailable(gtsam) \ No newline at end of file diff --git a/build.gradle b/build.gradle index be6030d..dd09e41 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1 @@ -if (project.hasProperty('runmerge')) { - apply from: 'merge.gradle' -} else { - apply from: 'publish.gradle' -} +apply from: 'publish.gradle' diff --git a/copy-headers.sh b/copy-headers.sh deleted file mode 100755 index b7ead05..0000000 --- a/copy-headers.sh +++ /dev/null @@ -1,3 +0,0 @@ -rm gradleDir/ -rf -mkdir -p gradleDir/include/ -find buildDebug/_deps/gtsam-src/ \( -name "*.h" -or -name "*.hpp" \) -exec cp {} gradleDir/include \; diff --git a/merge.gradle b/merge.gradle deleted file mode 100644 index 51bd224..0000000 --- a/merge.gradle +++ /dev/null @@ -1,166 +0,0 @@ -import java.security.MessageDigest - -def downloadsFolder = project.file("build/downloads") -def toUpload = project.file("build/toUpload") -def extractFolder = project.file('build/extract') -def archivesFolder = project.file('build/archive') - -def files = project.files(downloadsFolder) - -def constantNames = [ - 'version.txt', - 'gtsam-cpp_CLS-headers.zip' -] - -def constantFiles = [] -def mergeFiles = [] - -downloadsFolder.eachFile { - def found = false - for (element in constantNames) { - System.out.println(it) - if (it.name.endsWith(element)) { - constantFiles << it - found = true - break - } - } - if (!found) { - mergeFiles << it - } -} - -def mergePairs = [:] - -// Match all to extract -mergeFiles.removeAll { - it.name.contains('osxarm64') -} - -mergeFiles.each { - mergePairs.put(it.name, it.name.replace('osxx86-64', 'osxarm64')) -} - -def mergeTasks = [] - -mergePairs.each { - - def intelArchive = it.key - def armArchive = it.value - - def extractIntelTask = project.tasks.create("extract_$intelArchive", Copy) { - def withoutExt = intelArchive.substring(0, intelArchive.length() - 4); - def folder = "$extractFolder/$withoutExt" - def f = "$downloadsFolder/$intelArchive" - inputs.file f - - from zipTree(f) - into folder - } - - def extractArmTask = project.tasks.create("extract_$armArchive", Copy) { - def withoutExt = armArchive.substring(0, armArchive.length() - 4); - def folder = "$extractFolder/$withoutExt" - def f = "$downloadsFolder/$armArchive" - inputs.file f - - from zipTree(f) - into folder - } - - def copyAndMerge = project.tasks.create("merge_$intelArchive", Copy) { - def withoutExt = intelArchive.substring(0, intelArchive.length() - 4); - def replaced = withoutExt.replace('osxx86-64', 'osxuniversal') - def replacedFolder = "$extractFolder/$replaced" - - dependsOn extractIntelTask - dependsOn extractArmTask - - from (extractIntelTask) { - exclude '**/*.dylib' - exclude '**/*.a' - exclude '**/*.hash' - includeEmptyDirs = false - } - into replacedFolder - - doLast { - def doHash = null - extractIntelTask.destinationDir.eachFileRecurse { - if (it.name.endsWith('.hash')) { - doHash = it - } - if (it.name.endsWith('.dylib') || it.name.endsWith('.a')) { - def intelFile = it.toString() - def armFile = it.toString().replace('x86-64', 'arm64') - def universalFile = it.toString().replace('x86-64', 'universal') - project.file(universalFile).parentFile.mkdirs() - exec { - executable 'lipo' - args = [ - '-create', - intelFile, - armFile, - '-output', - universalFile - ] - } - } - if (it.name.endsWith('.dylib') && project.hasProperty("developerID")) { - def universalFile = it.toString().replace('x86-64', 'universal') - // Get path to binary. - exec { - workingDir rootDir - def args = [ - "sh", - "-c", - "codesign --force --strict --deep " + - "--timestamp --options=runtime " + - "--verbose -s ${project.findProperty("developerID")} " + - "$universalFile" - ] - commandLine args - } - } - } - if (doHash != null) { - // Find dylib file - def dylibName = 'lib' + doHash.name.replace('.hash', '.dylib') - def dylibPath = project.file(doHash.parentFile.absolutePath.replace('x86-64', 'universal') + "/$dylibName") - def hashFile = project.file(doHash.absolutePath.replace('x86-64', 'universal')) - hashFile.text = MessageDigest.getInstance("MD5").digest(dylibPath.bytes).encodeHex().toString() - } - } - } - - def cls = intelArchive.endsWith('.jar') ? Jar.class : Zip.class - - def archive = project.tasks.create("archive_$intelArchive", cls) { - dependsOn copyAndMerge - - def withoutExt = intelArchive.substring(0, intelArchive.length() - 4); - def replaced = withoutExt.replace('osxx86-64', 'osxuniversal') - - archiveBaseName = replaced - - destinationDirectory = archivesFolder - - from copyAndMerge - } - - mergeTasks << archive -} - -project.tasks.register('copyToUpload', Copy) { - - mergeTasks.each { - dependsOn it - from it - } - - constantFiles.each { - from it - } - - into toUpload -} diff --git a/publish.gradle b/publish.gradle index 124c23e..8051ba3 100644 --- a/publish.gradle +++ b/publish.gradle @@ -1,4 +1,3 @@ -import java.security.MessageDigest import org.gradle.internal.os.OperatingSystem import java.nio.file.Files @@ -21,35 +20,59 @@ publishing { } } -def getPlatformPath(triplet) { - if (triplet == "arm32-linux") { +def getPlatform() { + def platform + def os_name = System.getProperty("os.name") + def os_arch = System.getProperty("os.arch") + + if (os_arch == 'amd64') { + os_arch = 'x86_64' + } else if (os_arch == 'aarch64' || os_arch == 'arm64') { + os_arch = 'arm64' + } + + if (OperatingSystem.current().isWindows()) { + platform = "windows-${os_arch}" + } else if (OperatingSystem.current().isLinux()) { + platform = "linux-${os_arch}" + } else if (OperatingSystem.current().isMacOsX()) { + platform = "osx-${os_arch}" + } else { + platform = "${os_name}-${os_arch}" + } + return platform +} + +def getPlatformPath(platform) { + if (platform == "linux-athena") { + return "linux/athena" + } else if (platform == "linux-arm32") { return "linux/arm32" - } else if (triplet == "arm64-linux") { + } else if (platform == "linux-arm64") { return "linux/arm64" - } else if (triplet == "x64-linux") { + } else if (platform == "linux-x86_64") { return "linux/x86-64" - } else if (triplet == "x64-osx") { - return "osx/x86-64" - } else if (triplet == "arm64-osx") { - return "osx/arm64" - } else if (triplet == "x64-windows") { + } else if (platform == "osx-universal") { + return "osx/universal" + } else if (platform == "windows-x86_64") { return "windows/x86-64" - } else if (triplet == "arm64-windows") { + } else if (platform == "windows-arm64") { return "windows/arm64" } else { return "" } } -ext.triplet = platform -ext.platformPath = getPlatformPath(ext.triplet) +if (!project.hasProperty('platform')) { + println "No 'platform' property specified; using the build system's platform" + ext.platform = getPlatform() +} +ext.platformPath = getPlatformPath(project.platform) ext.platformClassifier = ext.platformPath.replaceFirst('/', '') ext.repo = "thirdparty-gtsam" -def triplet = platform - -def pubVersion = "2.2-1" +def pubVersion = "4.3-1" def outputsFolder = file("$project.buildDir/outputs") @@ -61,9 +84,7 @@ def versionFile = file("$outputsFolder/version.txt") def licenseFile = file("LICENSE.md") def outputClassifierStatic = project.ext.platformClassifier + 'static' -def outputClassifierDebugStatic = project.ext.platformClassifier + 'debug/static' -System.out.println(triplet) - +println platformPath task copyAllOutputs(type: Copy) { destinationDir = outputsFolder @@ -90,141 +111,53 @@ task outputVersions() { } } -task cmakeRelease() { - doFirst { - exec { - workingDir rootDir - def args - if (platform.contains("windows")) { - args = [ - "cmake", - "-B build", - "-G Ninja", - "-DCMAKE_BUILD_TYPE=Release", - ] - } else { - args = [ - "cmake", - "-B build", - "-G Ninja", - "-DCMAKE_C_COMPILER_LAUNCHER=sccache", - "-DCMAKE_CXX_COMPILER_LAUNCHER=sccache ", - "-DCMAKE_BUILD_TYPE=Release", - ] - } - commandLine args - } - exec { - workingDir rootDir - def args = [ - "cmake", - "--build", - "build", - "--parallel", - "6" - ] - commandLine args - } - } -} -task cppLibsZipStatic(type: Zip) { - dependsOn cmakeRelease - - destinationDirectory = outputsFolder - archiveClassifier = outputClassifierStatic - archiveBaseName = zipBaseName - duplicatesStrategy = 'exclude' +["Debug", "RelWithDebInfo"].each { buildType -> + def buildDir = "build$buildType" + def installDir = "install$buildType" - from(licenseFile) { - into '/' - } - def resolvedDir = Paths.get(projectDir.canonicalPath).resolve("build/_deps/gtsam-build") - from(resolvedDir.toFile()) { - into project.platformPath + '/static' - exclude '**/pkgconfig' - include '**/*.a' - include '**/*.lib' - include '**/*.pdb' - } -} + task "cmakeConfigure$buildType"(type: Exec) { + def baseArgs = ["-B", buildDir, "-G", "Ninja", "-DCMAKE_BUILD_TYPE=$buildType", "-DCMAKE_INSTALL_PREFIX=$installDir"] -task cmakeDebug() { - doFirst { - exec { - workingDir rootDir - def args - if (platform.contains("windows")) { - args = [ - "cmake", - "-B buildDebug", - "-G Ninja", - "-DCMAKE_BUILD_TYPE=Debug", - ] - } else { - args = [ - "cmake", - "-B buildDebug", - "-G Ninja", - "-DCMAKE_C_COMPILER_LAUNCHER=sccache", - "-DCMAKE_CXX_COMPILER_LAUNCHER=sccache ", - "-DCMAKE_BUILD_TYPE=Debug", - ] - } - commandLine args - } - exec { - workingDir rootDir - def args = [ - "cmake", - "--build", - "buildDebug", - "--parallel", - "6" - ] - commandLine args + if (project.hasProperty('sccache')) { + baseArgs = baseArgs + "-DCMAKE_C_COMPILER_LAUNCHER=sccache" + "-DCMAKE_CXX_COMPILER_LAUNCHER=sccache" } + outputs.dir buildDir + executable "cmake" + args baseArgs } -} - -task cppLibsZipStaticDebug(type: Zip) { - dependsOn cmakeDebug - - destinationDirectory = outputsFolder - archiveClassifier = outputClassifierStatic + 'debug' - archiveBaseName = zipBaseName + 'debug' - duplicatesStrategy = 'exclude' - from(licenseFile) { - into '/' - } - def resolvedDir = Paths.get(projectDir.canonicalPath).resolve("buildDebug/_deps/gtsam-build") - from(resolvedDir.toFile()) { - into project.platformPath + '/static' - exclude '**/pkgconfig' - include '**/*.a' - include '**/*.lib' - include '**/*.pdb' + task "cmakeBuild$buildType"(type: Exec) { + dependsOn "cmakeConfigure$buildType" + def processors = Runtime.runtime.availableProcessors() + def baseArgs = ["--build", buildDir, "--parallel", "$processors", "--target", "install"] + outputs.dirs buildDir, installDir + executable "cmake" + args baseArgs } -} -task copyHeaders() { - dependsOn cmakeDebug - doFirst { - exec { - workingDir rootDir - def args = [ - "sh", - "-c", - "./copy-headers.sh" - ] - commandLine args + task "cppLibsZipStatic$buildType"(type: Zip) { + dependsOn "cmakeBuild$buildType" + destinationDirectory = outputsFolder + archiveClassifier = outputClassifierStatic + (buildType == "Debug" ? "debug" : "") + archiveBaseName = zipBaseName + (buildType == "Debug" ? "debug" : "") + duplicatesStrategy = 'exclude' + + from(licenseFile) { + into '/' + } + def resolvedDir = Paths.get(projectDir.canonicalPath).resolve(installDir).resolve("lib") + from(resolvedDir.toFile()) { + into project.platformPath + '/static' + include '**/*.a' + include '**/*.lib' + include '**/*.pdb' } } } - +// Choice of using Debug is arbitrary, just wanted a build task to depend on task cppHeadersZip(type: Zip) { + dependsOn "cmakeBuildDebug" dependsOn outputVersions - dependsOn copyHeaders destinationDirectory = outputsFolder archiveBaseName = zipBaseName archiveClassifier = "headers" @@ -232,9 +165,9 @@ task cppHeadersZip(type: Zip) { from(licenseFile) { into '/' } - def resolvedDir = Paths.get(projectDir.canonicalPath).resolve("gradleDir/include") + def resolvedDir = Paths.get(projectDir.canonicalPath).resolve("installDebug").resolve("include") from(resolvedDir.toFile()) { - into '/include' + into '/' include '**/*.hpp', '**/*.h' } @@ -242,60 +175,26 @@ task cppHeadersZip(type: Zip) { } if (!project.hasProperty('skipRelease')) { - addTaskToCopyAllOutputs(cppLibsZipStatic) + addTaskToCopyAllOutputs(cppLibsZipStaticRelWithDebInfo) } if (!project.hasProperty('skipDebug')) { addTaskToCopyAllOutputs(cppLibsZipStaticDebug) } -def isDev = true - -if (project.hasProperty('release')) { - isDev = false -} - -def photonMavenURL = 'https://maven.photonvision.org/' + (isDev ? 'snapshots' : 'releases'); - -if (project.hasProperty("thirdparty")) { - model { - publishing { - publications { - cpp(MavenPublication) { - artifact cppHeadersZip - artifact cppLibsZipStatic - artifact cppLibsZipStaticDebug - - artifactId = "${baseArtifactId}-cpp" - groupId artifactGroupId - version pubVersion - } - } - repositories { - maven { - url(photonMavenURL) - credentials { - username 'ghactions' - password System.getenv("ARTIFACTORY_API_KEY") - } - } +model { + publishing { + publications { + cpp(MavenPublication) { + artifact cppHeadersZip + artifact cppLibsZipStaticRelWithDebInfo + artifact cppLibsZipStaticDebug + artifactId = "${baseArtifactId}-cpp" + groupId artifactGroupId + version pubVersion } } - } -} else { - model { - publishing { - publications { - cpp(MavenPublication) { - artifact cppHeadersZip - artifact cppLibsZipStatic - artifact cppLibsZipStaticDebug - - artifactId = "${baseArtifactId}-cpp" - groupId artifactGroupId - version pubVersion - } - } + if (project.hasProperty("repo")) { repositories { maven { url "${System.getProperty('user.home')}/releases/maven/${project.repo}" From 8bf5e391b971d436f3907570cc0cc8d8662aad64 Mon Sep 17 00:00:00 2001 From: Gold856 <117957790+Gold856@users.noreply.github.com> Date: Mon, 23 Dec 2024 23:09:04 -0500 Subject: [PATCH 2/4] Add Linux ARM builds --- .github/workflows/main.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ef84e8c..4c35379 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -43,6 +43,15 @@ jobs: fail-fast: false matrix: include: + - container: wpilib/roborio-cross-ubuntu:2025-22.04 + artifact-name: Athena + build-options: -Pplatform=linuxathena -Psccache + - container: wpilib/raspbian-cross-ubuntu:bookworm-22.04 + artifact-name: Arm32 + build-options: -Pplatform=linuxarm32 -Psccache + - container: wpilib/aarch64-cross-ubuntu:bookworm-22.04 + artifact-name: Arm64 + build-options: -Pplatform=linuxarm64 -Psccache - container: wpilib/ubuntu-base:22.04 artifact-name: Linux build-options: -Pplatform=linux-x86_64 -Psccache From d977e509d694d7cf14f2e4df8ed234df31bdf5ed Mon Sep 17 00:00:00 2001 From: Gold856 <117957790+Gold856@users.noreply.github.com> Date: Tue, 24 Dec 2024 01:22:55 -0500 Subject: [PATCH 3/4] Add sources zip and properly add gtsam's license --- publish.gradle | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/publish.gradle b/publish.gradle index 8051ba3..cf6cf47 100644 --- a/publish.gradle +++ b/publish.gradle @@ -142,8 +142,10 @@ task outputVersions() { archiveBaseName = zipBaseName + (buildType == "Debug" ? "debug" : "") duplicatesStrategy = 'exclude' - from(licenseFile) { + def license = Paths.get(projectDir.canonicalPath).resolve(buildDir).resolve("_deps").resolve("gtsam-src") + from(license.toFile()) { into '/' + include 'LICENSE*' } def resolvedDir = Paths.get(projectDir.canonicalPath).resolve(installDir).resolve("lib") from(resolvedDir.toFile()) { @@ -162,8 +164,31 @@ task cppHeadersZip(type: Zip) { archiveBaseName = zipBaseName archiveClassifier = "headers" - from(licenseFile) { + def license = Paths.get(projectDir.canonicalPath).resolve("buildDebug").resolve("_deps").resolve("gtsam-src") + from(license.toFile()) { into '/' + include 'LICENSE*' + } + def resolvedDir = Paths.get(projectDir.canonicalPath).resolve("installDebug").resolve("include") + from(resolvedDir.toFile()) { + into '/' + include '**/*.hpp', '**/*.h' + } + + includeEmptyDirs = false +} + +task cppSourcesZip(type: Zip) { + dependsOn "cmakeBuildDebug" + dependsOn outputVersions + destinationDirectory = outputsFolder + archiveBaseName = zipBaseName + archiveClassifier = "sources" + + def license = Paths.get(projectDir.canonicalPath).resolve("buildDebug").resolve("_deps").resolve("gtsam-src") + from(license.toFile()) { + into '/' + include 'LICENSE*' } def resolvedDir = Paths.get(projectDir.canonicalPath).resolve("installDebug").resolve("include") from(resolvedDir.toFile()) { From ea6ff0b6ef4744d9d2b67ed9046664d15ae50127 Mon Sep 17 00:00:00 2001 From: Gold856 <117957790+Gold856@users.noreply.github.com> Date: Tue, 24 Dec 2024 02:11:37 -0500 Subject: [PATCH 4/4] Don't include empty directories --- publish.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/publish.gradle b/publish.gradle index cf6cf47..c869c79 100644 --- a/publish.gradle +++ b/publish.gradle @@ -154,6 +154,7 @@ task outputVersions() { include '**/*.lib' include '**/*.pdb' } + includeEmptyDirs = false } } // Choice of using Debug is arbitrary, just wanted a build task to depend on @@ -214,6 +215,7 @@ model { artifact cppHeadersZip artifact cppLibsZipStaticRelWithDebInfo artifact cppLibsZipStaticDebug + artifact cppSourcesZip artifactId = "${baseArtifactId}-cpp" groupId artifactGroupId version pubVersion