diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5a7b55d..a1f6098 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,21 +7,35 @@ concurrency: cancel-in-progress: true jobs: + validation: + name: "Validation" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: gradle/actions/wrapper-validation@v4 + build-docker: strategy: fail-fast: false matrix: include: + - container: wpilib/raspbian-cross-ubuntu:bookworm-22.04 + artifact-name: Arm32 + build-options: -Pplatform=linux-arm32 + - container: wpilib/aarch64-cross-ubuntu:bookworm-22.04 + artifact-name: Arm64 + build-options: -Pplatform=linux-arm64 - container: wpilib/ubuntu-base:22.04 artifact-name: Linux - build-options: -Pplatform=x64-linux + build-options: name: "Build - ${{ matrix.artifact-name }}" runs-on: ubuntu-latest + needs: [validation] container: ${{ matrix.container }} steps: - - run: sudo apt-get update && sudo apt-get install -y gfortran - name: install gfortran + - run: sudo apt-get update && sudo apt-get install -y gfortran ninja-build + name: Install dependencies - uses: actions/checkout@v4 with: submodules: 'true' @@ -29,13 +43,10 @@ jobs: with: java-version: 17 distribution: 'temurin' - - uses: lukka/run-vcpkg@v11.5 - with: - vcpkgGitCommitId: '29b2ea2d4b6197e66ef346e62ccbba35b55b7de5' - run: ./gradlew publish ${{ matrix.build-options }} name: Build with Gradle - - run: ls vcpkg_installed/*/lib/* - name: List dependent shared libraries + - run: ls build*/install/lib/* + name: List libraries - uses: actions/upload-artifact@v4 with: name: ${{ matrix.artifact-name }} @@ -48,13 +59,14 @@ jobs: include: - artifact-name: WinArm64 tool-arch: amd64_arm64 - build-options: -Pplatform=arm64-windows-static-md + build-options: -Pplatform=windows-arm64 - artifact-name: Win64 tool-arch: amd64 build-options: name: "Build - ${{ matrix.artifact-name }}" - runs-on: windows-2019 + runs-on: windows-2022 + needs: [validation] steps: - uses: actions/checkout@v4 with: @@ -63,33 +75,22 @@ jobs: with: java-version: 17 distribution: 'temurin' - - uses: lukka/run-vcpkg@v11.5 - with: - vcpkgGitCommitId: '29b2ea2d4b6197e66ef346e62ccbba35b55b7de5' - uses: ilammy/msvc-dev-cmd@v1.13.0 with: arch: ${{ matrix.tool-arch }} - run: ./gradlew publish ${{ matrix.build-options }} name: Build with Gradle - - run: ls vcpkg_installed/*/bin/* - name: List dependent DLLs + - run: ls build*/install/lib/* + name: List libraries - uses: actions/upload-artifact@v4 with: name: ${{ matrix.artifact-name }} path: gradleDir/outputs/ build-mac: - strategy: - fail-fast: false - matrix: - include: - - artifact-name: macOSArm - build-options: -Pplatform=arm64-osx - - artifact-name: macOS - build-options: -Pplatform=x64-osx - - name: "Build - ${{ matrix.artifact-name }}" + name: "Build - Mac" runs-on: macOS-14 + needs: [validation] steps: - uses: actions/checkout@v4 with: @@ -100,46 +101,18 @@ jobs: distribution: 'temurin' - run: brew install cmake ninja name: install ninja - - uses: lukka/run-vcpkg@v11.5 - with: - vcpkgGitCommitId: '29b2ea2d4b6197e66ef346e62ccbba35b55b7de5' - - run: ./gradlew publish ${{ matrix.build-options }} + - run: ./gradlew publish name: Build with Gradle - - run: ls vcpkg_installed/*/lib/* - name: List dependent shared libraries + - run: ls build*/install/lib/* + name: List libraries - uses: actions/upload-artifact@v4 with: - name: ${{ matrix.artifact-name }} + name: Mac path: gradleDir/outputs/ - make_universal: - name: Make Universal - needs: [build-mac] - 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] + needs: [build-docker, build-windows, build-mac] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index 364e99d..5b22c41 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -/vcpkg_installed -/build +/build* /.gradle /gradleDir \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index a0a57f3..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "vcpkg"] - path = vcpkg - url = https://github.com/microsoft/vcpkg.git diff --git a/0003-Make-assignment-constexpr.patch b/0003-Make-assignment-constexpr.patch new file mode 100644 index 0000000..a5c7dc8 --- /dev/null +++ b/0003-Make-assignment-constexpr.patch @@ -0,0 +1,305 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tyler Veness +Date: Sun, 12 Jan 2025 21:04:07 -0800 +Subject: [PATCH 3/3] Make assignment constexpr + +--- + Eigen/src/Core/AssignEvaluator.h | 165 +++++++++++-------- + Eigen/src/Core/EigenBase.h | 2 +- + Eigen/src/Core/functors/AssignmentFunctors.h | 2 +- + 3 files changed, 102 insertions(+), 67 deletions(-) + +diff --git a/Eigen/src/Core/AssignEvaluator.h b/Eigen/src/Core/AssignEvaluator.h +index f7f0b238b8ca70bbc9100262479cc1dbebab9979..9c2436afa7fe98692a036e6ef255ed104a5bf388 100644 +--- a/Eigen/src/Core/AssignEvaluator.h ++++ b/Eigen/src/Core/AssignEvaluator.h +@@ -263,7 +263,7 @@ struct copy_using_evaluator_innervec_CompleteUnrolling { + DstAlignment = Kernel::AssignmentTraits::DstAlignment + }; + +- EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel) { ++ EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { + kernel.template assignPacketByOuterInner(outer, inner); + enum { NextIndex = Index + unpacket_traits::size }; + copy_using_evaluator_innervec_CompleteUnrolling::run(kernel); +@@ -431,17 +431,25 @@ struct dense_assignment_loop { + template + struct dense_assignment_loop { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel& kernel) { +- typedef typename Kernel::DstEvaluatorType::XprType DstXprType; +- typedef typename Kernel::PacketType PacketType; +- +- enum { +- size = DstXprType::SizeAtCompileTime, +- packetSize = unpacket_traits::size, +- alignedSize = (int(size) / packetSize) * packetSize +- }; +- +- copy_using_evaluator_linearvec_CompleteUnrolling::run(kernel); +- copy_using_evaluator_LinearTraversal_CompleteUnrolling::run(kernel); ++ if (internal::is_constant_evaluated()) { ++ for (Index outer = 0; outer < kernel.outerSize(); ++outer) { ++ for (Index inner = 0; inner < kernel.innerSize(); ++inner) { ++ kernel.assignCoeffByOuterInner(outer, inner); ++ } ++ } ++ } else { ++ typedef typename Kernel::DstEvaluatorType::XprType DstXprType; ++ typedef typename Kernel::PacketType PacketType; ++ ++ enum { ++ size = DstXprType::SizeAtCompileTime, ++ packetSize = unpacket_traits::size, ++ alignedSize = (int(size) / packetSize) * packetSize ++ }; ++ ++ copy_using_evaluator_linearvec_CompleteUnrolling::run(kernel); ++ copy_using_evaluator_LinearTraversal_CompleteUnrolling::run(kernel); ++ } + } + }; + +@@ -465,9 +473,17 @@ struct dense_assignment_loop { + + template + struct dense_assignment_loop { +- EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel) { +- typedef typename Kernel::DstEvaluatorType::XprType DstXprType; +- copy_using_evaluator_innervec_CompleteUnrolling::run(kernel); ++ EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { ++ if (internal::is_constant_evaluated()) { ++ for (Index outer = 0; outer < kernel.outerSize(); ++outer) { ++ for (Index inner = 0; inner < kernel.innerSize(); ++inner) { ++ kernel.assignCoeffByOuterInner(outer, inner); ++ } ++ } ++ } else { ++ typedef typename Kernel::DstEvaluatorType::XprType DstXprType; ++ copy_using_evaluator_innervec_CompleteUnrolling::run(kernel); ++ } + } + }; + +@@ -498,8 +514,16 @@ struct dense_assignment_loop { + template + struct dense_assignment_loop { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel& kernel) { +- typedef typename Kernel::DstEvaluatorType::XprType DstXprType; +- copy_using_evaluator_LinearTraversal_CompleteUnrolling::run(kernel); ++ if (internal::is_constant_evaluated()) { ++ for (Index outer = 0; outer < kernel.outerSize(); ++outer) { ++ for (Index inner = 0; inner < kernel.innerSize(); ++inner) { ++ kernel.assignCoeffByOuterInner(outer, inner); ++ } ++ } ++ } else { ++ typedef typename Kernel::DstEvaluatorType::XprType DstXprType; ++ copy_using_evaluator_LinearTraversal_CompleteUnrolling::run(kernel); ++ } + } + }; + +@@ -510,41 +534,49 @@ struct dense_assignment_loop { + template + struct dense_assignment_loop { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel& kernel) { +- typedef typename Kernel::Scalar Scalar; +- typedef typename Kernel::PacketType PacketType; +- enum { +- packetSize = unpacket_traits::size, +- requestedAlignment = int(Kernel::AssignmentTraits::InnerRequiredAlignment), +- alignable = +- packet_traits::AlignedOnScalar || int(Kernel::AssignmentTraits::DstAlignment) >= sizeof(Scalar), +- dstIsAligned = int(Kernel::AssignmentTraits::DstAlignment) >= int(requestedAlignment), +- dstAlignment = alignable ? int(requestedAlignment) : int(Kernel::AssignmentTraits::DstAlignment) +- }; +- const Scalar* dst_ptr = kernel.dstDataPtr(); +- if ((!bool(dstIsAligned)) && (std::uintptr_t(dst_ptr) % sizeof(Scalar)) > 0) { +- // the pointer is not aligned-on scalar, so alignment is not possible +- return dense_assignment_loop::run(kernel); +- } +- const Index packetAlignedMask = packetSize - 1; +- const Index innerSize = kernel.innerSize(); +- const Index outerSize = kernel.outerSize(); +- const Index alignedStep = alignable ? (packetSize - kernel.outerStride() % packetSize) & packetAlignedMask : 0; +- Index alignedStart = +- ((!alignable) || bool(dstIsAligned)) ? 0 : internal::first_aligned(dst_ptr, innerSize); +- +- for (Index outer = 0; outer < outerSize; ++outer) { +- const Index alignedEnd = alignedStart + ((innerSize - alignedStart) & ~packetAlignedMask); +- // do the non-vectorizable part of the assignment +- for (Index inner = 0; inner < alignedStart; ++inner) kernel.assignCoeffByOuterInner(outer, inner); +- +- // do the vectorizable part of the assignment +- for (Index inner = alignedStart; inner < alignedEnd; inner += packetSize) +- kernel.template assignPacketByOuterInner(outer, inner); +- +- // do the non-vectorizable part of the assignment +- for (Index inner = alignedEnd; inner < innerSize; ++inner) kernel.assignCoeffByOuterInner(outer, inner); +- +- alignedStart = numext::mini((alignedStart + alignedStep) % packetSize, innerSize); ++ if (internal::is_constant_evaluated()) { ++ for (Index outer = 0; outer < kernel.outerSize(); ++outer) { ++ for (Index inner = 0; inner < kernel.innerSize(); ++inner) { ++ kernel.assignCoeffByOuterInner(outer, inner); ++ } ++ } ++ } else { ++ typedef typename Kernel::Scalar Scalar; ++ typedef typename Kernel::PacketType PacketType; ++ enum { ++ packetSize = unpacket_traits::size, ++ requestedAlignment = int(Kernel::AssignmentTraits::InnerRequiredAlignment), ++ alignable = ++ packet_traits::AlignedOnScalar || int(Kernel::AssignmentTraits::DstAlignment) >= sizeof(Scalar), ++ dstIsAligned = int(Kernel::AssignmentTraits::DstAlignment) >= int(requestedAlignment), ++ dstAlignment = alignable ? int(requestedAlignment) : int(Kernel::AssignmentTraits::DstAlignment) ++ }; ++ const Scalar* dst_ptr = kernel.dstDataPtr(); ++ if ((!bool(dstIsAligned)) && (std::uintptr_t(dst_ptr) % sizeof(Scalar)) > 0) { ++ // the pointer is not aligned-on scalar, so alignment is not possible ++ return dense_assignment_loop::run(kernel); ++ } ++ const Index packetAlignedMask = packetSize - 1; ++ const Index innerSize = kernel.innerSize(); ++ const Index outerSize = kernel.outerSize(); ++ const Index alignedStep = alignable ? (packetSize - kernel.outerStride() % packetSize) & packetAlignedMask : 0; ++ Index alignedStart = ++ ((!alignable) || bool(dstIsAligned)) ? 0 : internal::first_aligned(dst_ptr, innerSize); ++ ++ for (Index outer = 0; outer < outerSize; ++outer) { ++ const Index alignedEnd = alignedStart + ((innerSize - alignedStart) & ~packetAlignedMask); ++ // do the non-vectorizable part of the assignment ++ for (Index inner = 0; inner < alignedStart; ++inner) kernel.assignCoeffByOuterInner(outer, inner); ++ ++ // do the vectorizable part of the assignment ++ for (Index inner = alignedStart; inner < alignedEnd; inner += packetSize) ++ kernel.template assignPacketByOuterInner(outer, inner); ++ ++ // do the non-vectorizable part of the assignment ++ for (Index inner = alignedEnd; inner < innerSize; ++inner) kernel.assignCoeffByOuterInner(outer, inner); ++ ++ alignedStart = numext::mini((alignedStart + alignedStep) % packetSize, innerSize); ++ } + } + } + }; +@@ -594,9 +626,9 @@ class generic_dense_assignment_kernel { + typedef copy_using_evaluator_traits AssignmentTraits; + typedef typename AssignmentTraits::PacketType PacketType; + +- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE generic_dense_assignment_kernel(DstEvaluatorType& dst, +- const SrcEvaluatorType& src, +- const Functor& func, DstXprType& dstExpr) ++ EIGEN_DEVICE_FUNC ++ EIGEN_STRONG_INLINE constexpr generic_dense_assignment_kernel(DstEvaluatorType& dst, const SrcEvaluatorType& src, ++ const Functor& func, DstXprType& dstExpr) + : m_dst(dst), m_src(src), m_functor(func), m_dstExpr(dstExpr) { + #ifdef EIGEN_DEBUG_ASSIGN + AssignmentTraits::debug(); +@@ -614,7 +646,7 @@ class generic_dense_assignment_kernel { + EIGEN_DEVICE_FUNC const SrcEvaluatorType& srcEvaluator() const EIGEN_NOEXCEPT { return m_src; } + + /// Assign src(row,col) to dst(row,col) through the assignment functor. +- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Index row, Index col) { ++ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void assignCoeff(Index row, Index col) { + m_functor.assignCoeff(m_dst.coeffRef(row, col), m_src.coeff(row, col)); + } + +@@ -624,7 +656,7 @@ class generic_dense_assignment_kernel { + } + + /// \sa assignCoeff(Index,Index) +- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeffByOuterInner(Index outer, Index inner) { ++ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void assignCoeffByOuterInner(Index outer, Index inner) { + Index row = rowIndexByOuterInner(outer, inner); + Index col = colIndexByOuterInner(outer, inner); + assignCoeff(row, col); +@@ -648,7 +680,7 @@ class generic_dense_assignment_kernel { + assignPacket(row, col); + } + +- EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner) { ++ EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr Index rowIndexByOuterInner(Index outer, Index inner) { + typedef typename DstEvaluatorType::ExpressionTraits Traits; + return int(Traits::RowsAtCompileTime) == 1 ? 0 + : int(Traits::ColsAtCompileTime) == 1 ? inner +@@ -656,7 +688,7 @@ class generic_dense_assignment_kernel { + : inner; + } + +- EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Index colIndexByOuterInner(Index outer, Index inner) { ++ EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr Index colIndexByOuterInner(Index outer, Index inner) { + typedef typename DstEvaluatorType::ExpressionTraits Traits; + return int(Traits::ColsAtCompileTime) == 1 ? 0 + : int(Traits::RowsAtCompileTime) == 1 ? inner +@@ -708,8 +740,8 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize_if_allowed(DstXprType& dst, co + } + + template +-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize_if_allowed(DstXprType& dst, const SrcXprType& src, +- const internal::assign_op& /*func*/) { ++EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize_if_allowed(DstXprType& dst, const SrcXprType& src, ++ const internal::assign_op& /*func*/) { + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if (((dst.rows() != dstRows) || (dst.cols() != dstCols))) dst.resize(dstRows, dstCols); +@@ -790,7 +822,7 @@ struct Assignment; + // not has to bother about these annoying details. + + template +-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_assignment(Dst& dst, const Src& src) { ++EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_assignment(Dst& dst, const Src& src) { + call_assignment(dst, src, internal::assign_op()); + } + template +@@ -807,7 +839,7 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void call_assignment( + } + + template +-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_assignment( ++EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_assignment( + Dst& dst, const Src& src, const Func& func, std::enable_if_t::value, void*> = 0) { + call_assignment_no_alias(dst, src, func); + } +@@ -891,9 +923,12 @@ EIGEN_DEVICE_FUNC void check_for_aliasing(const Dst& dst, const Src& src); + // both partial specialization+SFINAE without ambiguous specialization + template + struct Assignment { +- EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, const Functor& func) { ++ EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(DstXprType& dst, const SrcXprType& src, ++ const Functor& func) { + #ifndef EIGEN_NO_DEBUG +- internal::check_for_aliasing(dst, src); ++ if (!internal::is_constant_evaluated()) { ++ internal::check_for_aliasing(dst, src); ++ } + #endif + + call_dense_assignment_loop(dst, src, func); +diff --git a/Eigen/src/Core/EigenBase.h b/Eigen/src/Core/EigenBase.h +index 6d167006a094181fa3693b19f6b9daeb6f2afb79..894bfc13b15eb994abd90f100da15de5bd8b22b7 100644 +--- a/Eigen/src/Core/EigenBase.h ++++ b/Eigen/src/Core/EigenBase.h +@@ -50,7 +50,7 @@ struct EigenBase { + /** \returns a const reference to the derived object */ + EIGEN_DEVICE_FUNC constexpr const Derived& derived() const { return *static_cast(this); } + +- EIGEN_DEVICE_FUNC inline Derived& const_cast_derived() const { ++ EIGEN_DEVICE_FUNC inline constexpr Derived& const_cast_derived() const { + return *static_cast(const_cast(this)); + } + EIGEN_DEVICE_FUNC inline const Derived& const_derived() const { return *static_cast(this); } +diff --git a/Eigen/src/Core/functors/AssignmentFunctors.h b/Eigen/src/Core/functors/AssignmentFunctors.h +index 09d1da8ca2bcb41384520f46e2b793ba8b28a798..3687bb20db4dfe1a2f6cf1342b4fcbd8f91f1f68 100644 +--- a/Eigen/src/Core/functors/AssignmentFunctors.h ++++ b/Eigen/src/Core/functors/AssignmentFunctors.h +@@ -23,7 +23,7 @@ namespace internal { + */ + template + struct assign_op { +- EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(DstScalar& a, const SrcScalar& b) const { a = b; } ++ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void assignCoeff(DstScalar& a, const SrcScalar& b) const { a = b; } + + template + EIGEN_STRONG_INLINE void assignPacket(DstScalar* a, const Packet& b) const { diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..4d44e5d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,76 @@ +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE) +endif() + +cmake_minimum_required(VERSION 3.25) +set(CMAKE_OSX_ARCHITECTURES arm64 x86_64) +set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded) +project(thirdparty-ceres C CXX) + +set(BUILD_SHARED_LIBS OFF) +set(BUILD_TESTING OFF) +set(BUILD_EXAMPLES OFF) + +set(NO_CBLAS ON) +set(C_LAPACK ON) +set(USE_LOCKING ON) +set(USE_THREAD OFF) +if(MSVC) + set(NOFORTRAN ON) +endif() + +set(SUITESPARSE_ENABLE_PROJECTS cholmod) +set(SUITESPARSE_USE_CUDA OFF) +set(SUITESPARSE_USE_PYTHON OFF) +set(CHOLMOD_GPL OFF) +if(NOT APPLE) + set(BLA_VENDOR OpenBLAS) +endif() +if(MSVC) + set(SUITESPARSE_USE_FORTRAN OFF) +endif() + +set(EIGEN_BUILD_CMAKE_PACKAGE ON) + +set(WITH_GFLAGS OFF) +set(WITH_GTEST OFF) + +set(BUILD_BENCHMARKS OFF) +set(MINIGLOG ON) +set(PROVIDE_UNINSTALL_TARGET OFF) +set(SUITESPARSE OFF) +include(FetchContent) +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) +if(NOT APPLE) + fetchcontent_declare( + BLAS + GIT_REPOSITORY https://github.com/OpenMathLib/OpenBLAS.git + GIT_TAG v0.3.29 + OVERRIDE_FIND_PACKAGE + ) +endif() + +fetchcontent_declare( + SuiteSparse + GIT_REPOSITORY https://github.com/DrTimothyAldenDavis/SuiteSparse.git + GIT_TAG v7.8.3 + OVERRIDE_FIND_PACKAGE +) + +fetchcontent_declare( + Eigen3 + GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git + GIT_TAG 0fb2ed140d4fc0108553ecfb25f2d7fc1a9319a1 + OVERRIDE_FIND_PACKAGE + PATCH_COMMAND git apply ${CMAKE_CURRENT_SOURCE_DIR}/0003-Make-assignment-constexpr.patch +) + +fetchcontent_declare( + Ceres + GIT_REPOSITORY https://github.com/ceres-solver/ceres-solver.git + GIT_TAG 2.2.0 +) +if(NOT APPLE) + fetchcontent_makeavailable(BLAS) +endif() +fetchcontent_makeavailable(SuiteSparse Eigen3 Ceres) diff --git a/build.gradle b/build.gradle index 1284aa1..ce4bcc2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,306 @@ -if (project.hasProperty('runmerge')) { - apply from: 'merge.gradle' +import org.gradle.internal.os.OperatingSystem + +import java.nio.file.Files +import java.nio.file.Paths + +apply plugin: 'maven-publish' + + +ext.version = "2.2" +ext.libVersion = "${ext.version.replace(".", "")}" + +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-universal" + } 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 (platform == "linux-arm64") { + return "linux/arm64" + } else if (platform == "linux-x86_64") { + return "linux/x86-64" + } else if (platform == "osx-universal") { + return "osx/universal" + } else if (platform == "windows-x86_64") { + return "windows/x86-64" + } else if (platform == "windows-arm64") { + return "windows/arm64" + } else { + return "" + } +} + +def platform +if (!project.hasProperty('platform')) { + println "No 'platform' property specified; using the build system's platform" + platform = getPlatform() } else { - apply from: 'publish.gradle' -} \ No newline at end of file + platform = project.platform +} + +ext.platformPath = getPlatformPath(platform) +ext.platformClassifier = ext.platformPath.replaceFirst('/', '') + + +// Determine what repo to publish to. Default is development. Valid options are development and release +if (!project.hasProperty('repo')) { + ext.repo = 'development' +} +def pubVersion = "$ext.version-1" + +def outputsFolder = file("$project.buildDir/outputs") + +def baseArtifactId = 'ceres' +def artifactGroupId = 'edu.wpi.first.thirdparty.frc2025.ceres' +def zipBaseName = '_GROUP_edu_wpi_first_thirdparty_frc2025_ceres_ID_ceres-cpp_CLS' + +def versionFile = file("$outputsFolder/version.txt") +def licenseFile = files("LICENSE.md", "CERES_LICENSE") + +def outputClassifierStatic = project.ext.platformClassifier + 'static' +println platformPath + +task copyAllOutputs(type: Copy) { + destinationDir = outputsFolder +} + +ext.addTaskToCopyAllOutputs = { task -> + copyAllOutputs.dependsOn task + copyAllOutputs.inputs.file task.archiveFile + copyAllOutputs.from task.archiveFile +} + +['Debug', 'RelWithDebInfo'].each { buildtype -> + task "configure$buildtype" (type: Exec) { + def baseArgs = ["-B", "build$buildtype", "-DCMAKE_BUILD_TYPE=$buildtype", "-G", "Ninja"] + if (platform == "windows-arm64") { + // Need to set CMAKE_CROSSCOMPILING because getarch can't be crosscompiled and executed on the host. + // Also, TARGET must be generic. You need to set it if crosscompiling, but setting it to ARMV8, it will try to use assembly, which fails on Windows + baseArgs += ["-DCMAKE_CROSSCOMPILING=1", "-DCMAKE_SYSTEM_NAME=Windows", "-DCMAKE_SYSTEM_PROCESSOR=ARM64", "-DTARGET=GENERIC", "-DARCH=ARM64"] + } + outputs.dir "build$buildtype" + executable "cmake" + args baseArgs + } + task "build$buildtype" (type: Exec) { + dependsOn "configure$buildtype" + def baseArgs = ["--build", "build$buildtype"] + outputs.dir "build$buildtype" + executable "cmake" + args baseArgs + } + task "install$buildtype" (type: Exec) { + dependsOn "build$buildtype" + def baseArgs = ["--install", "build$buildtype", '--prefix', "build$buildtype/install"] + outputs.dir "build$buildtype/install" + executable "cmake" + args baseArgs + } + task "merge${buildtype}StaticLibs"(type: Exec) { + dependsOn("install$buildtype") + def buildDirectory = Paths.get(projectDir.canonicalPath).resolve("build$buildtype").resolve("install") + + if (project.platformPath.startsWith('windows')) { + workingDir buildDirectory.resolve("lib").toString() + executable 'lib' + def inputFiles + if (buildtype == "Debug") { + inputFiles = ['ceres-debug'] + } else { + inputFiles = ['ceres'] + } + inputFiles += ['amd_static', 'camd_static', 'ccolamd_static', 'colamd_static', 'cholmod_static', 'suitesparseconfig_static', "openblas"] + inputFiles.each { + args "${buildDirectory.resolve("lib")}/$it" + ".lib" + } + args "/OUT:ceres-$buildtype${project.libVersion}.lib" + } else if (project.platformPath.startsWith('osx')) { + executable 'libtool' + workingDir buildDirectory.resolve("lib").toString() + + def outputLibName = "libceres-$buildtype${project.libVersion}.a" + def inputFiles + if (buildtype == "Debug") { + inputFiles = ['libceres-debug'] + } else { + inputFiles = ['libceres'] + } + inputFiles += ['libamd', 'libcamd', 'libccolamd', 'libcolamd', 'libcholmod', 'libsuitesparseconfig'] + inputFiles.each { + args "${buildDirectory.resolve("lib")}/$it" + ".a" + } + + args '-static', '-o', outputLibName + + outputs.file buildDirectory.resolve("lib/${outputLibName}") + } else { + workingDir buildDirectory.resolve("lib").toString() + executable 'ar' + args = ['-M'] + + def inputString = "create libceres-$buildtype${project.libVersion}.a\n" + def inputFiles + if (buildtype == "Debug") { + inputFiles = ['libceres-debug'] + } else { + inputFiles = ['libceres'] + } + inputFiles += ['libamd', 'libcamd', 'libccolamd', 'libcolamd', 'libcholmod', 'libsuitesparseconfig', 'libopenblas'] + inputFiles.each { + def inFile = 'addlib ' + it + ".a\n" + inputString += inFile + } + inputString += "save\nend\n" + standardInput = new ByteArrayInputStream(inputString.getBytes()) + } + } +} + +task outputVersions() { + description = 'Prints the versions of this to a file for use by the downstream packaging project' + group = 'Build' + outputs.files(versionFile) + + doFirst { + buildDir.mkdir() + outputsFolder.mkdir() + } + + doLast { + versionFile.write pubVersion + } +} + +task cppHeadersZip(type: Zip) { + dependsOn outputVersions + destinationDirectory = outputsFolder + archiveBaseName = zipBaseName + archiveClassifier = "headers" + + from(licenseFile) { + into '/' + } + + from("buildDebug/install/include/ceres") { + exclude "**/miniglog/**" + into '/ceres' + } + from("buildDebug/install/include/ceres/internal/miniglog") { + into '/' + } + from("buildDebug/install/include/openblas") { + into '/openblas' + } + from("buildDebug/install/include/suitesparse") { + into '/suitesparse' + } + + includeEmptyDirs = false + // Just need to depend on any install task + dependsOn installDebug +} + +task cppSourcesZip(type: Zip) { + // Just need to depend on any build task + dependsOn buildDebug + destinationDirectory = outputsFolder + archiveClassifier = 'sources' + archiveBaseName = zipBaseName + duplicatesStrategy = 'exclude' + + from('buildDebug/_deps/') { + into '/' + include "*-src/**/*" + } + includeEmptyDirs = false +} + +task cppLibsZipStatic(type: Zip) { + dependsOn mergeRelWithDebInfoStaticLibs + destinationDirectory = outputsFolder + archiveClassifier = outputClassifierStatic + archiveBaseName = zipBaseName + duplicatesStrategy = 'exclude' + + from(licenseFile) { + into '/' + } + from("buildRelWithDebInfo/install/lib") { + into project.platformPath + '/static' + include "**/libceres-RelWithDebInfo${project.libVersion}.a" + include "**/ceres-RelWithDebInfo${project.libVersion}.lib" + include '**/*.pdb' + } + includeEmptyDirs = false +} + +task cppLibsZipStaticDebug(type: Zip) { + dependsOn mergeDebugStaticLibs + destinationDirectory = outputsFolder + archiveClassifier = outputClassifierStatic + 'debug' + archiveBaseName = zipBaseName + duplicatesStrategy = 'exclude' + + from(licenseFile) { + into '/' + } + from("buildDebug/install/lib") { + into project.platformPath + '/static' + include "**/libceres-Debug${project.libVersion}.a" + include "**/ceres-Debug${project.libVersion}.lib" + include '**/*.pdb' + } + includeEmptyDirs = false +} + +if (!project.hasProperty('skipRelease')) { + addTaskToCopyAllOutputs(cppLibsZipStatic) +} + +if (!project.hasProperty('skipDebug')) { + addTaskToCopyAllOutputs(cppLibsZipStaticDebug) +} + +model { + publishing { + publications { + cpp(MavenPublication) { + artifact cppHeadersZip + artifact cppSourcesZip + artifact cppLibsZipStatic + artifact cppLibsZipStaticDebug + + artifactId = "${baseArtifactId}-cpp" + groupId artifactGroupId + version pubVersion + } + } + repositories { + maven { + url "${System.getProperty('user.home')}/releases/maven/${project.repo}" + } + } + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a7..a4b76b9 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0c85a1f..94113f2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index aeb74cb..f5feea6 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +134,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +205,11 @@ fi # 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" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 93e3f59..9d21a21 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/merge.gradle b/merge.gradle deleted file mode 100644 index 9f8f514..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', - 'ceres-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 -} \ No newline at end of file diff --git a/publish.gradle b/publish.gradle deleted file mode 100644 index 5a82b6f..0000000 --- a/publish.gradle +++ /dev/null @@ -1,315 +0,0 @@ -import org.gradle.internal.os.OperatingSystem - -import java.nio.file.Files -import java.nio.file.Paths - -apply plugin: 'maven-publish' - -configurations { - archives -} - -publishing { - repositories { - maven { - url "${System.getProperty('user.home')}/releases/maven/development" - } - maven { - url "${System.getProperty('user.home')}/releases/maven/release" - } - } -} - -ext.version = "2.2" -ext.libVersion = "${ext.version.replace(".", "")}" - -def getTriplet() { - def triplet - def os_name = System.getProperty("os.name") - def os_arch = System.getProperty("os.arch") - - if (os_arch == 'amd64') { - os_arch = 'x64' - } else if (os_arch == 'i386') { - os_arch = 'x86' - } else if (os_arch == 'aarch64' || os_arch == 'arm64') { - os_arch = 'arm64' - } - - if (OperatingSystem.current().isWindows()) { - triplet = "${os_arch}-windows-static-md" - } else if (OperatingSystem.current().isLinux()) { - triplet = "${os_arch}-linux" - } else if (OperatingSystem.current().isMacOsX()) { - triplet = "${os_arch}-osx" - } else { - triplet = "${os_arch}-${os_name}" - } - return triplet -} - -def getPlatformPath(triplet) { - if (triplet == "arm32-linux") { - return "linux/arm32" - } else if (triplet == "arm64-linux") { - return "linux/arm64" - } else if (triplet == "x64-linux") { - 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-static-md") { - return "windows/x86-64" - } else if (triplet == "arm64-windows-static-md") { - return "windows/arm64" - } else { - return "" - } -} -def triplet -if (!project.hasProperty('platform')) { - println "No 'platform' property specified; using the build system's platform" - triplet = getTriplet() -} else { - triplet = project.platform -} - -if (project.hasProperty('forcealternatemacbuild')) { - if (project.platform == 'arm64-osx') { - triplet = 'x64-osx' - } else if (ext.platform == 'x64-osx') { - triplet = 'arm64-osx' - } -} - -ext.platformPath = getPlatformPath(triplet) -ext.platformClassifier = ext.platformPath.replaceFirst('/', '') - -ext.repo = "thirdparty-ceres" -def pubVersion = "$ext.version-3" - -def outputsFolder = file("$project.buildDir/outputs") - -def baseArtifactId = 'ceres' -def artifactGroupId = 'edu.wpi.first.thirdparty.frc2024.ceres' -def zipBaseName = '_GROUP_edu_wpi_first_thirdparty_frc2024_ceres_ID_ceres-cpp_CLS' - -def versionFile = file("$outputsFolder/version.txt") -def licenseFile = file("LICENSE.md") - -def outputClassifierStatic = project.ext.platformClassifier + 'static' -println triplet - -task copyAllOutputs(type: Copy) { - destinationDir = outputsFolder -} - -ext.addTaskToCopyAllOutputs = { task -> - copyAllOutputs.dependsOn task - copyAllOutputs.inputs.file task.archiveFile - copyAllOutputs.from task.archiveFile -} - -task buildVcpkg(type: Exec) { - def baseArgs = ['install', "--overlay-ports=$rootDir/overlayPorts"] - outputs.dir "vcpkg_installed/$triplet" - executable "$rootDir/vcpkg/vcpkg" - args baseArgs + "--triplet=$triplet" -} - -task outputVersions() { - description = 'Prints the versions of this to a file for use by the downstream packaging project' - group = 'Build' - outputs.files(versionFile) - - doFirst { - buildDir.mkdir() - outputsFolder.mkdir() - } - - doLast { - versionFile.write pubVersion - } -} - -task cppHeadersZip(type: Zip) { - dependsOn outputVersions - destinationDirectory = outputsFolder - archiveBaseName = zipBaseName - archiveClassifier = "headers" - - from(licenseFile) { - into '/' - } - def resolvedDir = Paths.get(projectDir.canonicalPath).resolve("vcpkg_installed").resolve(triplet).resolve("include") - from(resolvedDir.toFile()) { - into '/' - } - - includeEmptyDirs = false - dependsOn buildVcpkg -} - -task mergeStaticLibs(type: Exec) { - dependsOn(buildVcpkg) - def buildDirectory = Paths.get(projectDir.canonicalPath).resolve("vcpkg_installed").resolve(triplet) - - if (project.platformPath.startsWith('windows')) { - workingDir buildDirectory.resolve("lib").toString() - executable 'lib' - def inputFiles = ["ceres", "gflags_static", "GKlib", "glog", "lapack", "libamd", "libbtf", "libcamd", "libccolamd", "libcholmod", "libcolamd", "libcxsparse", "libklu", "libldl", "libspqr", "libumfpack", "metis", "openblas", "suitesparseconfig", "libf2c"] - def setArgs = ["/OUT:ceres${project.libVersion}.lib"] - inputFiles.each { - setArgs << it + ".lib" - } - args = setArgs - } else if (project.platformPath.startsWith('osx')) { - executable 'libtool' - workingDir buildDirectory.resolve("lib").toString() - - def outputLibName = "libceres${project.libVersion}.a" - - def inputFiles = ["libspqr", "libldl", "libceres", "libccolamd", "libklu", "libcxsparse", "libglog", "libsuitesparseconfig", "libbtf", "libmetis", "libumfpack", "libcholmod", "libcamd", "libgflags", "libamd", "libGKlib", "libcolamd"] - - args '-static', '-o', outputLibName - - inputFiles.each { - args "${buildDirectory.resolve("lib")}/$it" + ".a" - } - - inputs.files inputFiles.collect { buildDirectory.resolve("lib").resolve(it) } - outputs.file buildDirectory.resolve("lib/${outputLibName}") - } else { - workingDir buildDirectory.resolve("lib").toString() - executable 'ar' - args = ['-M'] - def inputFiles = ["libamd", "libbtf", "libcamd", "libccolamd", "libceres", "libcholmod", "libcolamd","libcxsparse", "libgflags", "libGKlib", "libglog", "libklu", "liblapack", "libldl", "libmetis", "libopenblas", "libspqr", "libsuitesparseconfig", "libumfpack"] - - def inputString = "create libceres${project.libVersion}.a\n" - inputFiles.each { - def inFile = 'addlib ' + it + ".a\n" - inputString += inFile - } - - inputString += "save\nend\n" - standardInput = new ByteArrayInputStream(inputString.getBytes()) - } -} - -task mergeDebugStaticLibs(type: Exec) { - dependsOn(buildVcpkg) - def buildDirectory = Paths.get(projectDir.canonicalPath).resolve("vcpkg_installed").resolve(triplet).resolve("debug") - - if (project.platformPath.startsWith('windows')) { - workingDir buildDirectory.resolve("lib").toString() - executable 'lib' - def inputFiles = ["ceres-debug", "gflags_static_debug", "GKlib", "glog", "lapack", "libamdd", "libbtfd", "libcamdd", "libccolamdd", "libcholmodd", "libcolamdd", "libcxsparsed", "libklud", "libldld", "libspqrd", "libumfpackd", "metis", "openblas", "suitesparseconfigd", "libf2c"] - def setArgs = ["/OUT:ceres-debug${project.libVersion}.lib"] - inputFiles.each { - setArgs << it + ".lib" - } - args = setArgs - } else if (project.platformPath.startsWith('osx')) { - executable 'libtool' - workingDir buildDirectory.resolve("lib").toString() - - def outputLibName = "libceres-debug${project.libVersion}.a" - - def inputFiles = ["libsuitesparseconfigd", "libspqrd", "libamdd", "libcxsparsed", "libldld", "libglog", "libgflags_debug", "libcolamdd", "libmetis", "libccolamdd", "libcamdd", "libumfpackd", "libklud", "libcholmodd", "libceres-debug", "libbtfd", "libGKlib"] - - args '-static', '-o', outputLibName - - inputFiles.each { - args "${buildDirectory.resolve("lib")}/$it" + ".a" - } - - inputs.files inputFiles.collect { buildDirectory.resolve("lib").resolve(it) } - outputs.file buildDirectory.resolve("lib/${outputLibName}") - } else { - workingDir buildDirectory.resolve("lib").toString() - executable 'ar' - args = ['-M'] - def inputFiles = ["libamdd", "libbtfd", "libcamdd", "libccolamdd", "libceres-debug", "libcholmodd", "libcolamdd", "libcxsparsed", "libgflags_debug", "libGKlib", "libglog", "libklud", "liblapack", "libldld", "libmetis", "libopenblas", "libspqrd", "libsuitesparseconfigd", "libumfpackd"] - - def inputString = "create libceres-debug${project.libVersion}.a\n" - inputFiles.each { - def inFile = 'addlib ' + it + ".a\n" - inputString += inFile - } - - inputString += "save\nend\n" - standardInput = new ByteArrayInputStream(inputString.getBytes()) - } -} - -task cppLibsZipStatic(type: Zip) { - dependsOn mergeStaticLibs - destinationDirectory = outputsFolder - archiveClassifier = outputClassifierStatic - archiveBaseName = zipBaseName - duplicatesStrategy = 'exclude' - - from(licenseFile) { - into '/' - } - def resolvedDir = Paths.get(projectDir.canonicalPath).resolve("vcpkg_installed").resolve(triplet).resolve("lib") - from(resolvedDir.toFile()) { - into project.platformPath + '/static' - exclude '**/pkgconfig' - include "**/libceres${project.libVersion}.a" - include "**/ceres${project.libVersion}.lib" - include '**/*.pdb' - } - dependsOn buildVcpkg -} - -task cppLibsZipStaticDebug(type: Zip) { - dependsOn mergeDebugStaticLibs - destinationDirectory = outputsFolder - archiveClassifier = outputClassifierStatic + 'debug' - archiveBaseName = zipBaseName - duplicatesStrategy = 'exclude' - - from(licenseFile) { - into '/' - } - def resolvedDir = Paths.get(projectDir.canonicalPath).resolve("vcpkg_installed").resolve(triplet).resolve("debug").resolve("lib") - from(resolvedDir.toFile()) { - into project.platformPath + '/static' - exclude '**/pkgconfig' - include "**/libceres-debug${project.libVersion}.a" - include "**/ceres-debug${project.libVersion}.lib" - include '**/*.pdb' - } - dependsOn buildVcpkg -} - -if (!project.hasProperty('skipRelease')) { - addTaskToCopyAllOutputs(cppLibsZipStatic) -} - -if (!project.hasProperty('skipDebug')) { - addTaskToCopyAllOutputs(cppLibsZipStaticDebug) -} - -model { - publishing { - publications { - cpp(MavenPublication) { - artifact cppHeadersZip - artifact cppLibsZipStatic - artifact cppLibsZipStaticDebug - - artifactId = "${baseArtifactId}-cpp" - groupId artifactGroupId - version pubVersion - } - } - repositories { - maven { - url "${System.getProperty('user.home')}/releases/maven/${project.repo}" - } - } - } -} diff --git a/vcpkg b/vcpkg deleted file mode 160000 index 29b2ea2..0000000 --- a/vcpkg +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 29b2ea2d4b6197e66ef346e62ccbba35b55b7de5 diff --git a/vcpkg.json b/vcpkg.json deleted file mode 100644 index 74f999b..0000000 --- a/vcpkg.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", - "dependencies": [ - { - - "name": "ceres", - "features": [ - "eigensparse", - "suitesparse" - ] - } - ], - "builtin-baseline": "29b2ea2d4b6197e66ef346e62ccbba35b55b7de5" - } \ No newline at end of file