diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index 8974798342..f3a30045ce 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -15,9 +15,9 @@ on: - '*' jobs: - windows2022: - runs-on: windows-2022 - name: Windows 2022 + windows: + runs-on: windows-2025 + name: Windows outputs: version: ${{ steps.configure.outputs.version }} @@ -35,11 +35,11 @@ jobs: - name: Install Python packages uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Install numpy - #Need numpy to use SWIG numpy typemaps. - run: python3 -m pip install numpy==1.25 + # Need numpy to use SWIG numpy typemaps. + run: python3 -m pip install numpy==2.0 - name: Install SWIG run: | @@ -79,16 +79,15 @@ jobs: # TODO: Can remove /WX when we use that in CMakeLists.txt. # Set the CXXFLAGS environment variable to turn warnings into errors. # Skip timing test section included by default. - cmake -E env CXXFLAGS="/WX /MD -DSKIP_TIMING" cmake $env:GITHUB_WORKSPACE -LAH -G"Visual Studio 17 2022" -A x64 -DCMAKE_INSTALL_PREFIX=~/opensim-core-install -DOPENSIM_DEPENDENCIES_DIR=~/opensim_dependencies_install -DOPENSIM_C3D_PARSER=ezc3d -DOPENSIM_WITH_CASADI=on -DBUILD_PYTHON_WRAPPING=on -DBUILD_JAVA_WRAPPING=on -DPython3_ROOT_DIR=C:\hostedtoolcache\windows\Python\3.10.11\x64 + cmake -E env CXXFLAGS="/WX /MD -DSKIP_TIMING" cmake $env:GITHUB_WORKSPACE -LAH -G"Visual Studio 17 2022" -A x64 -DCMAKE_INSTALL_PREFIX=~/opensim-core-install -DOPENSIM_DEPENDENCIES_DIR=~/opensim_dependencies_install -DOPENSIM_C3D_PARSER=ezc3d -DOPENSIM_WITH_CASADI=on -DBUILD_PYTHON_WRAPPING=on -DBUILD_JAVA_WRAPPING=on -DPython3_ROOT_DIR=C:\hostedtoolcache\windows\Python\3.11.9\x64 $env:match = cmake -L . | Select-String -Pattern OPENSIM_QUALIFIED_VERSION $version = $env:match.split('=')[1] echo $version echo "VERSION=$version" >> $GITHUB_ENV echo "version=$version" >> $env:GITHUB_OUTPUT - - name: Build opensim-core - # Install now to avoid building bindings twice (TODO: issue when using Visual Studio 2019, is this an issue too in Visual Studio 2022?). + # Install now to avoid building bindings twice (TODO: still an issue with Visual Studio 2022). run: | chdir $env:GITHUB_WORKSPACE\\build cmake --build . --config Release --target doxygen -- /maxcpucount:4 @@ -100,7 +99,7 @@ jobs: ctest --parallel 4 --output-on-failure --build-config Release -E Java_* - name: Install opensim-core - # TODO: This is where we wish to do the installing, but it's done above for now. + # TODO: This is where we wish to do the installing, but it's done above for now. run: | chdir $env:GITHUB_WORKSPACE\\build chdir $env:GITHUB_WORKSPACE @@ -118,198 +117,9 @@ jobs: - name: Upload opensim-core uses: actions/upload-artifact@v4 with: - name: opensim-core-${{ steps.configure.outputs.version }}-win2022 + name: opensim-core-${{ steps.configure.outputs.version }}-win path: opensim-core-${{ steps.configure.outputs.version }}.zip - windows2022_perf: - runs-on: windows-2022 - name: Windows 2022 [main] - - if: ${{ contains(github.event.pull_request.title, '[perf-win]') || contains(github.event.pull_request.body, '[perf-win]') }} - - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.base.ref }} - - - name: Install Doxygen - # choco install doxygen.portable # <-- too unreliable. - run: | - (New-Object System.Net.WebClient).DownloadFile("https://github.com/doxygen/doxygen/releases/download/Release_1_12_0/doxygen-1.12.0.windows.x64.bin.zip", "doxygen.zip") - 7z x $env:GITHUB_WORKSPACE/doxygen.zip -odoxygen - echo "$env:GITHUB_WORKSPACE\\doxygen" >> $GITHUB_PATH - - - name: Install Python packages - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - - name: Install numpy - #Need numpy to use SWIG numpy typemaps. - run: python3 -m pip install numpy==1.25 - - - name: Install SWIG - run: | - choco install swig --version 4.1.1 --yes --limit-output --allow-downgrade - swig -swiglib - - - name: Cache dependencies - id: cache-dependencies - uses: actions/cache@v3 - with: - path: ~/opensim_dependencies_install - # Every time a cache is created, it's stored with this key. - # In subsequent runs, if the key matches the key of an existing cache, - # then the cache is used. We chose for this key to depend on the - # operating system and a hash of the hashes of all files in the - # dependencies directory (non-recursive). - # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/caching-dependencies-to-speed-up-workflows#matching-a-cache-key - key: ${{ runner.os }}-dependencies-${{ hashFiles('dependencies/*') }} - - - name: Build dependencies - if: steps.cache-dependencies.outputs.cache-hit != 'true' - run: | - echo $env:GITHUB_WORKSPACE\\build_deps - mkdir $env:GITHUB_WORKSPACE\\build_deps - chdir $env:GITHUB_WORKSPACE\\build_deps - # /W0 disables warnings. - # https://msdn.microsoft.com/en-us/library/19z1t1wy.aspx - # TODO: CMake provides /W3, which overrides our /W0 - cmake -E env CXXFLAGS="/W0" cmake $env:GITHUB_WORKSPACE/dependencies -LAH -G"Visual Studio 17 2022" -A x64 -DCMAKE_INSTALL_PREFIX=~/opensim_dependencies_install -DSUPERBUILD_ezc3d=ON -DOPENSIM_WITH_CASADI=ON - cmake --build . --config Release -- /maxcpucount:4 - - - name: Configure opensim-core - id: configure - run: | - mkdir $env:GITHUB_WORKSPACE\\build - chdir $env:GITHUB_WORKSPACE\\build - # TODO: Can remove /WX when we use that in CMakeLists.txt. - # Set the CXXFLAGS environment variable to turn warnings into errors. - # Skip timing test section included by default. - cmake -E env CXXFLAGS="/WX -DSKIP_TIMING" cmake $env:GITHUB_WORKSPACE -LAH -G"Visual Studio 17 2022" -A x64 -DCMAKE_INSTALL_PREFIX=~/opensim-core-install -DOPENSIM_DEPENDENCIES_DIR=~/opensim_dependencies_install -DOPENSIM_C3D_PARSER=ezc3d -DBUILD_PYTHON_WRAPPING=on -DBUILD_JAVA_WRAPPING=on -DPython3_ROOT_DIR=C:\hostedtoolcache\windows\Python\3.10.11\x64 - $env:match = cmake -L . | Select-String -Pattern OPENSIM_QUALIFIED_VERSION - $version = $env:match.split('=')[1] - echo $version - echo "VERSION=$version" >> $GITHUB_ENV - echo "version=$version" >> $env:GITHUB_OUTPUT - - - - name: Build opensim-core - # Install now to avoid building bindings twice (TODO: issue when using Visual Studio 2019, is this an issue too in Visual Studio 2022?). - run: | - chdir $env:GITHUB_WORKSPACE\\build - cmake --build . --config Release --target doxygen -- /maxcpucount:4 - cmake --build . --config Release --target install -- /maxcpucount:4 - - - name: Test opensim-core - run: | - chdir $env:GITHUB_WORKSPACE\\build - ctest --parallel 4 --output-on-failure --build-config Release -E Java_* - - - name: Install opensim-core - # TODO: This is where we wish to do the installing, but it's done above for now. - run: | - chdir $env:GITHUB_WORKSPACE\\build - chdir $env:GITHUB_WORKSPACE - Copy-Item -Path "~/opensim-core-install" -Destination "opensim-core-${{ github.event.pull_request.base.ref }}" -Recurse - 7z a "opensim-core-${{ github.event.pull_request.base.ref }}.zip" "opensim-core-${{ github.event.pull_request.base.ref }}" - - - name: Test Python bindings - run: | - echo "PYTHONPATH= $env:USERPROFILE/opensim-core-install/bin">> $GITHUB_ENV - # Move to the installed location of the python package. - cd ~/opensim-core-install/sdk/python - # Run python tests. - python -m unittest discover --start-directory opensim/tests --verbose - - - name: Upload opensim-core - uses: actions/upload-artifact@v4 - with: - name: opensim-core-${{ github.event.pull_request.base.ref }}-win2022 - path: opensim-core-${{ github.event.pull_request.base.ref }}.zip - - performance_analysis_win: - runs-on: ubuntu-latest - name: Performance Analysis [Windows 2022] - - env: - GH_TOKEN: ${{ github.token }} - - needs: - - windows2022 - - windows2022_perf - - if: ${{ contains(github.event.pull_request.title, '[perf-win]') || contains(github.event.pull_request.body, '[perf-win]') }} - - steps: - - name: Trigger opensim-perf workflow - uses: Codex-/return-dispatch@v1.12.0 - id: return_dispatch - with: - token: ${{ secrets.PERF_DISPATCH_PAT }} - repo: opensim-perf - owner: opensim-org - ref: main - workflow: performance_analysis_win.yml - workflow_inputs: '{"commit_sha": "${{ github.event.pull_request.head.sha }}", "target_artifact_name": "opensim-core-${{ github.event.pull_request.base.ref }}-win2022", "source_artifact_name": "opensim-core-${{ needs.windows2022.outputs.version }}-win2022", "target_artifact_zip": "opensim-core-${{ github.event.pull_request.base.ref }}.zip", "source_artifact_zip": "opensim-core-${{ needs.windows2022.outputs.version }}.zip"}' - - - name: Await opensim-perf workflow - uses: Codex-/await-remote-run@v1.11.0 - with: - token: ${{ secrets.PERF_DISPATCH_PAT }} - repo: opensim-perf - owner: opensim-org - run_id: ${{ steps.return_dispatch.outputs.run_id }} - run_timeout_seconds: 10000 - - - name: Download performance analysis results - id: download-artifact - uses: dawidd6/action-download-artifact@v6 - with: - github_token: ${{ secrets.PERF_DISPATCH_PAT }} - run_id: ${{ steps.return_dispatch.outputs.run_id }} - workflow: performance_analysis_win.yml - name: performance-results - path: results - repo: opensim-org/opensim-perf - - - name: Post results to pull request description - run: | - PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH") - EXISTING_COMMENT_CONTENT=$(gh api /repos/opensim-org/opensim-core/pulls/${PR_NUMBER} | jq -r '.body') - CUSTOM_HEADER="### Performance analysis" - - REVIEWABLE_TAG="" - REVIEWABLE_CONTENT="" - if [[ $EXISTING_COMMENT_CONTENT == *"$REVIEWABLE_TAG"* ]]; then - REVIEWABLE_CONTENT=$(echo "$EXISTING_COMMENT_CONTENT" | awk "/$REVIEWABLE_TAG/,0") - fi - - if [[ $EXISTING_COMMENT_CONTENT == *"$CUSTOM_HEADER"* ]]; then - CONTENT_TO_REPLACE=$(echo "$EXISTING_COMMENT_CONTENT" | awk "/$CUSTOM_HEADER/,0") - else - CONTENT_TO_REPLACE=${REVIEWABLE_CONTENT} - fi - - NEW_CONTENT="${CUSTOM_HEADER} - - Platform: Windows, self-hosted runner - - $(cat results/performance_results.md) - - ${REVIEWABLE_CONTENT} - " - NEW_COMMENT_BODY="${EXISTING_COMMENT_CONTENT/"${CONTENT_TO_REPLACE}"/${NEW_CONTENT}}" - - # Update the existing description - gh api \ - --method PATCH \ - -H "Content-Type: application/json" \ - -H "Accept: application/vnd.github.v3+json" \ - -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ - repos/opensim-org/opensim-core/pulls/${PR_NUMBER} \ - -f "body=${NEW_COMMENT_BODY}" - mac_x86_64: runs-on: macos-15-intel name: Mac x86_64 @@ -323,14 +133,14 @@ jobs: - name: Install Python packages uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Install Homebrew packages # Save the gfortran version to a file so we can use it in the cache key. run: | brew install pkgconfig autoconf libtool automake wget pcre doxygen llvm brew reinstall gcc - pip3 install numpy==1.25 + pip3 install numpy==2.0 gfortran -v mkdir gfortran_version gfortran -v &> gfortran_version/gfortran_version.txt @@ -362,7 +172,7 @@ jobs: key: ${{ runner.os }}-dependencies-${{ hashFiles('dependencies/*') }}-${{ hashFiles('gfortran_version/*') }} - name: Build dependencies - # if: steps.cache-dependencies.outputs.cache-hit != 'true' + if: steps.cache-dependencies.outputs.cache-hit != 'true' run: | mkdir $GITHUB_WORKSPACE/../build_deps cd $GITHUB_WORKSPACE/../build_deps @@ -449,14 +259,14 @@ jobs: - name: Install Python packages uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Install Homebrew packages # Save the gfortran version to a file so we can use it in the cache key. run: | brew install pkgconfig autoconf libtool automake wget pcre doxygen llvm brew reinstall gcc - pip3 install numpy==1.25 + pip3 install numpy==2.0 gfortran -v mkdir gfortran_version gfortran -v &> gfortran_version/gfortran_version.txt @@ -562,31 +372,25 @@ jobs: name: opensim-core-${{ steps.configure.outputs.version }}-mac-arm64 path: opensim-core-${{ steps.configure.outputs.version }}.zip - mac_arm64_perf: - runs-on: macos-15 - name: Mac Arm64 [main] - - if: ${{ contains(github.event.pull_request.title, '[perf-mac]') || contains(github.event.pull_request.body, '[perf-mac]') }} + ubuntu22: + name: Ubuntu 22.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.base.ref }} - name: Install Python packages uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - - name: Install Homebrew packages - # Save the gfortran version to a file so we can use it in the cache key. + - name: Install Numpy run: | - brew install pkgconfig autoconf libtool automake wget pcre doxygen llvm - brew reinstall gcc - pip3 install numpy==1.25 - gfortran -v - mkdir gfortran_version - gfortran -v &> gfortran_version/gfortran_version.txt + pip install pip --upgrade + pip install numpy==2.0 + + - name: Install packages + run: sudo apt-get update && sudo apt-get install --yes build-essential libtool autoconf pkg-config gfortran libopenblas-dev liblapack-dev freeglut3-dev libxi-dev libxmu-dev doxygen patchelf - name: Cache SWIG id: cache-swig @@ -609,10 +413,7 @@ jobs: uses: actions/cache@v3 with: path: ~/opensim_dependencies_install - # If Homebrew updates the gcc package, then our cache of IPOPT is invalid. - # Specifically, the pkgcfg_lib_IPOPT_gfortran CMake variable becomes - # undefined. - key: ${{ runner.os }}-dependencies-${{ hashFiles('dependencies/*') }}-${{ hashFiles('gfortran_version/*') }} + key: ${{ runner.os }}-dependencies-${{ hashFiles('dependencies/*') }} - name: Build dependencies if: steps.cache-dependencies.outputs.cache-hit != 'true' @@ -625,7 +426,6 @@ jobs: DEP_CMAKE_ARGS+=(-DSUPERBUILD_ezc3d=ON) DEP_CMAKE_ARGS+=(-DOPENSIM_WITH_CASADI=ON) DEP_CMAKE_ARGS+=(-DOPENSIM_DISABLE_LOG_FILE=ON) - DEP_CMAKE_ARGS+=(-DCMAKE_OSX_DEPLOYMENT_TARGET=11) printf '%s\n' "${DEP_CMAKE_ARGS[@]}" cmake "${DEP_CMAKE_ARGS[@]}" make --jobs 4 @@ -639,15 +439,15 @@ jobs: OSIM_CMAKE_ARGS+=(-DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/../opensim-core-install) OSIM_CMAKE_ARGS+=(-DCMAKE_BUILD_TYPE=Release) OSIM_CMAKE_ARGS+=(-DOPENSIM_DEPENDENCIES_DIR=~/opensim_dependencies_install) - OSIM_CMAKE_ARGS+=(-DCMAKE_OSX_DEPLOYMENT_TARGET=11) OSIM_CMAKE_ARGS+=(-DOPENSIM_C3D_PARSER=ezc3d) OSIM_CMAKE_ARGS+=(-DBUILD_PYTHON_WRAPPING=on -DBUILD_JAVA_WRAPPING=on) - OSIM_CMAKE_ARGS+=(-DSWIG_EXECUTABLE=$HOME/swig/bin/swig) + OSIM_CMAKE_ARGS+=(-DSWIG_DIR=~/swig/share/swig) + OSIM_CMAKE_ARGS+=(-DSWIG_EXECUTABLE=~/swig/bin/swig) OSIM_CMAKE_ARGS+=(-DOPENSIM_INSTALL_UNIX_FHS=OFF) OSIM_CMAKE_ARGS+=(-DOPENSIM_DOXYGEN_USE_MATHJAX=off) # TODO: Update to simbody.github.io/latest OSIM_CMAKE_ARGS+=(-DOPENSIM_SIMBODY_DOXYGEN_LOCATION="https://simbody.github.io/simtk.org/api_docs/simbody/latest/") - OSIM_CMAKE_ARGS+=(-DCMAKE_CXX_FLAGS="-Werror, -Wdeprecated-copy") + OSIM_CMAKE_ARGS+=(-DCMAKE_CXX_FLAGS="-Werror") printf '%s\n' "${OSIM_CMAKE_ARGS[@]}" cmake "${OSIM_CMAKE_ARGS[@]}" VERSION=`cmake -L . | grep OPENSIM_QUALIFIED_VERSION | cut -d "=" -f2` @@ -663,20 +463,23 @@ jobs: - name: Test opensim-core run: | cd $GITHUB_WORKSPACE/../build + # TODO: Temporary for python to find Simbody libraries. + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/opensim_dependencies_install/simbody/lib ctest --parallel 4 --output-on-failure - name: Install opensim-core run: | cd $GITHUB_WORKSPACE/../build make doxygen - make install + make --jobs 4 install cd $GITHUB_WORKSPACE - mv $GITHUB_WORKSPACE/../opensim-core-install opensim-core-${{ github.event.pull_request.base.ref }} - zip --symlinks --recurse-paths --quiet opensim-core-${{ github.event.pull_request.base.ref }}.zip opensim-core-${{ github.event.pull_request.base.ref }} - mv opensim-core-${{ github.event.pull_request.base.ref }} $GITHUB_WORKSPACE/../opensim-core-install + mv $GITHUB_WORKSPACE/../opensim-core-install opensim-core-${{ steps.configure.outputs.version }} + zip --symlinks --recurse-paths --quiet opensim-core-${{ steps.configure.outputs.version }}-ubuntu22.zip opensim-core-${{ steps.configure.outputs.version }} + mv opensim-core-${{ steps.configure.outputs.version }} $GITHUB_WORKSPACE/../opensim-core-install - name: Test Python bindings run: | + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/opensim_dependencies_install/simbody/lib cd $GITHUB_WORKSPACE/../opensim-core-install/sdk/Python # Run the python tests, verbosely. python3 -m unittest discover --start-directory opensim/tests --verbose @@ -686,94 +489,12 @@ jobs: with: # The upload-artifact zipping does not preserve symlinks or executable # bits. So we zip ourselves, even though this causes a double-zip. - name: opensim-core-${{ github.event.pull_request.base.ref }}-mac-arm64 - path: opensim-core-${{ github.event.pull_request.base.ref }}.zip - - performance_analysis_mac: - runs-on: ubuntu-latest - name: Performance Analysis [Mac Arm64] - - env: - GH_TOKEN: ${{ github.token }} - - if: ${{ contains(github.event.pull_request.title, '[perf-mac]') || contains(github.event.pull_request.body, '[perf-mac]') }} - - needs: - - mac_arm64 - - mac_arm64_perf - - steps: - - name: Trigger opensim-perf workflow - uses: Codex-/return-dispatch@v1.12.0 - id: return_dispatch - with: - token: ${{ secrets.PERF_DISPATCH_PAT }} - repo: opensim-perf - owner: opensim-org - ref: main - workflow: performance_analysis_mac.yml - workflow_inputs: '{"commit_sha": "${{ github.event.pull_request.head.sha }}", "target_artifact_name": "opensim-core-${{ github.event.pull_request.base.ref }}-mac-arm64", "source_artifact_name": "opensim-core-${{ needs.mac_arm64.outputs.version }}-mac-arm64", "target_artifact_zip": "opensim-core-${{ github.event.pull_request.base.ref }}.zip", "source_artifact_zip": "opensim-core-${{ needs.mac_arm64.outputs.version }}.zip"}' - - - name: Await opensim-perf workflow - uses: Codex-/await-remote-run@v1.11.0 - with: - token: ${{ secrets.PERF_DISPATCH_PAT }} - repo: opensim-perf - owner: opensim-org - run_id: ${{ steps.return_dispatch.outputs.run_id }} - run_timeout_seconds: 10000 - - - name: Download performance analysis results - id: download-artifact - uses: dawidd6/action-download-artifact@v6 - with: - github_token: ${{ secrets.PERF_DISPATCH_PAT }} - run_id: ${{ steps.return_dispatch.outputs.run_id }} - workflow: performance_analysis_mac.yml - name: performance-results - path: results - repo: opensim-org/opensim-perf - - - name: Post results to pull request description - run: | - PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH") - EXISTING_COMMENT_CONTENT=$(gh api /repos/opensim-org/opensim-core/pulls/${PR_NUMBER} | jq -r '.body') - CUSTOM_HEADER="### Performance analysis" - - REVIEWABLE_TAG="" - REVIEWABLE_CONTENT="" - if [[ $EXISTING_COMMENT_CONTENT == *"$REVIEWABLE_TAG"* ]]; then - REVIEWABLE_CONTENT=$(echo "$EXISTING_COMMENT_CONTENT" | awk "/$REVIEWABLE_TAG/,0") - fi - - if [[ $EXISTING_COMMENT_CONTENT == *"$CUSTOM_HEADER"* ]]; then - CONTENT_TO_REPLACE=$(echo "$EXISTING_COMMENT_CONTENT" | awk "/$CUSTOM_HEADER/,0") - else - CONTENT_TO_REPLACE=${REVIEWABLE_CONTENT} - fi - - NEW_CONTENT="${CUSTOM_HEADER} - - Platform: Mac, GitHub Actions runner - - $(cat results/performance_results.md) - - ${REVIEWABLE_CONTENT} - " - NEW_COMMENT_BODY="${EXISTING_COMMENT_CONTENT/"${CONTENT_TO_REPLACE}"/${NEW_CONTENT}}" + name: opensim-core-${{ steps.configure.outputs.version }}-ubuntu22-linux + path: opensim-core-${{ steps.configure.outputs.version }}-ubuntu22.zip - # Update the existing description - gh api \ - --method PATCH \ - -H "Content-Type: application/json" \ - -H "Accept: application/vnd.github.v3+json" \ - -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ - repos/opensim-org/opensim-core/pulls/${PR_NUMBER} \ - -f "body=${NEW_COMMENT_BODY}" - - ubuntu22: - name: Ubuntu 22.04 - runs-on: ubuntu-22.04 + ubuntu24: + name: Ubuntu 24.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -781,16 +502,23 @@ jobs: - name: Install Python packages uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Install Numpy run: | pip install pip --upgrade - pip install numpy==1.25 + pip install numpy==2.0 - name: Install packages run: sudo apt-get update && sudo apt-get install --yes build-essential libtool autoconf pkg-config gfortran libopenblas-dev liblapack-dev freeglut3-dev libxi-dev libxmu-dev doxygen patchelf + - name: Cache SWIG + id: cache-swig + uses: actions/cache@v3 + with: + path: ~/swig + key: ${{ runner.os }}-swig + - name: Install SWIG # if: steps.cache-swig.outputs.cache-hit != 'true' run: | @@ -808,7 +536,7 @@ jobs: key: ${{ runner.os }}-dependencies-${{ hashFiles('dependencies/*') }} - name: Build dependencies - # if: steps.cache-dependencies.outputs.cache-hit != 'true' + if: steps.cache-dependencies.outputs.cache-hit != 'true' run: | mkdir $GITHUB_WORKSPACE/../build_deps cd $GITHUB_WORKSPACE/../build_deps @@ -817,6 +545,7 @@ jobs: DEP_CMAKE_ARGS+=(-DCMAKE_BUILD_TYPE=Release) DEP_CMAKE_ARGS+=(-DSUPERBUILD_ezc3d=ON) DEP_CMAKE_ARGS+=(-DOPENSIM_WITH_CASADI=ON) + DEP_CMAKE_ARGS+=(-DOPENSIM_DISABLE_LOG_FILE=ON) printf '%s\n' "${DEP_CMAKE_ARGS[@]}" cmake "${DEP_CMAKE_ARGS[@]}" make --jobs 4 @@ -880,8 +609,8 @@ jobs: with: # The upload-artifact zipping does not preserve symlinks or executable # bits. So we zip ourselves, even though this causes a double-zip. - name: opensim-core-${{ steps.configure.outputs.version }}-ubuntu22-linux - path: opensim-core-${{ steps.configure.outputs.version }}-ubuntu22.zip + name: opensim-core-${{ steps.configure.outputs.version }}-ubuntu24-linux + path: opensim-core-${{ steps.configure.outputs.version }}-ubuntu24.zip build_gui: name: Build GUI diff --git a/Applications/CMC/test/testCMCGait10dof18musc.cpp b/Applications/CMC/test/testCMCGait10dof18musc.cpp index a7f4519f01..132f6cf5d0 100644 --- a/Applications/CMC/test/testCMCGait10dof18musc.cpp +++ b/Applications/CMC/test/testCMCGait10dof18musc.cpp @@ -29,31 +29,7 @@ using namespace OpenSim; -TEST_CASE("testGait10dof18musc (Windows)", "[win]") { - CMCTool cmc("gait10dof18musc_Setup_CMC.xml"); - cmc.run(); - - const TimeSeriesTable results( - "gait10dof18musc_ResultsCMC/walk_subject_states.sto"); - const TimeSeriesTable std( - "gait10dof18musc_std_walk_subject_states_win.sto"); - - // TODO: Replace with macro from OpenSim/Moco/Test/Testing.h - const auto& actual = results.getMatrix(); - const auto& expected = std.getMatrix(); - REQUIRE((actual.nrow() == expected.nrow())); - REQUIRE((actual.ncol() == expected.ncol())); - for (int ir = 0; ir < actual.nrow(); ++ir) { - for (int ic = 0; ic < actual.ncol(); ++ic) { - INFO("(" << ir << "," << ic << "): " << actual.getElt(ir, ic) << - " vs " << expected.getElt(ir, ic)); - REQUIRE((Catch::Approx(actual.getElt(ir, ic)).margin(1e-3) - == expected.getElt(ir, ic))); - } - } -} - -TEST_CASE("testGait10dof18musc (Mac/Linux)", "[unix]") { +TEST_CASE("testGait10dof18musc") { CMCTool cmc("gait10dof18musc_Setup_CMC.xml"); cmc.run(); @@ -62,12 +38,12 @@ TEST_CASE("testGait10dof18musc (Mac/Linux)", "[unix]") { const TimeSeriesTable std( "gait10dof18musc_std_walk_subject_states_unix.sto"); - // Unix systems produce inconsistent results compared to Windows. Somehow, - // CMC produces results with differing number of time points, so we need to - // interpolate the results to the same time points as the standard results. - // The shapes of the muscle activity curves also differ slightly, so we - // allow a larger margin of error for the muscle activity curves. Therefore, - // this is a weaker test compared to the Windows test. + // CMC produces results with differing number of time points on different + // systems, so we need to interpolate the results to the same time points as + // the standard results. The shapes of the muscle activity curves also + // differ slightly, so we allow a larger margin of error for the muscle + // activity curves. Therefore, this is a weaker test compared to other + // CMC tests. GCVSplineSet resultSplines(results); GCVSplineSet stdSplines(std); diff --git a/Bindings/SWIGSimTK/Mat.h b/Bindings/SWIGSimTK/Mat.h index a0b205e35d..63932317a8 100644 --- a/Bindings/SWIGSimTK/Mat.h +++ b/Bindings/SWIGSimTK/Mat.h @@ -30,6 +30,9 @@ #include "SimTKcommon/internal/common.h" +#include +#include + namespace SimTK { /** This class represents a small matrix whose size is known at compile time, @@ -336,71 +339,36 @@ template class Mat { explicit Mat(int i) { new (this) Mat(ELT(Precision(i))); } - // A bevy of constructors from individual exact-match elements IN ROW ORDER. - Mat(const ELT& e0,const ELT& e1) - {assert(M*N==2);d[rIx(0)]=e0;d[rIx(1)]=e1;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2) - {assert(M*N==3);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3) - {assert(M*N==4);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4) - {assert(M*N==5);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4, - const ELT& e5) - {assert(M*N==6);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4; - d[rIx(5)]=e5;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4, - const ELT& e5,const ELT& e6) - {assert(M*N==7);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4; - d[rIx(5)]=e5;d[rIx(6)]=e6;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4, - const ELT& e5,const ELT& e6,const ELT& e7) - {assert(M*N==8);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4; - d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4, - const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8) - {assert(M*N==9);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4; - d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4, - const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9) - {assert(M*N==10);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4; - d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4, - const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9, - const ELT& e10) - {assert(M*N==11);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4; - d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4, - const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9, - const ELT& e10, const ELT& e11) - {assert(M*N==12);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4; - d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10; - d[rIx(11)]=e11;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4, - const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9, - const ELT& e10, const ELT& e11, const ELT& e12) - {assert(M*N==13);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4; - d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10; - d[rIx(11)]=e11;d[rIx(12)]=e12;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4, - const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9, - const ELT& e10, const ELT& e11, const ELT& e12, const ELT& e13) - {assert(M*N==14);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4; - d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10; - d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4, - const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9, - const ELT& e10, const ELT& e11, const ELT& e12, const ELT& e13, const ELT& e14) - {assert(M*N==15);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4; - d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10; - d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;d[rIx(14)]=e14;} - Mat(const ELT& e0,const ELT& e1,const ELT& e2,const ELT& e3,const ELT& e4, - const ELT& e5,const ELT& e6,const ELT& e7,const ELT& e8,const ELT& e9, - const ELT& e10, const ELT& e11, const ELT& e12, const ELT& e13, const ELT& e14, - const ELT& e15) - {assert(M*N==16);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4; - d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10; - d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;d[rIx(14)]=e14;d[rIx(15)]=e15;} +#ifndef SWIG + // Constructs a `Mat` from individual exact-match elements IN ROW ORDER. + template< + typename... Elements, + typename = std::enable_if_t< + (M*N==sizeof...(Elements)) && + (std::is_convertible_v && ...) + > + > + Mat(Elements&&... elementsRowByRow) + { + assignDataRowByRow( + std::forward_as_tuple(elementsRowByRow...), + std::make_integer_sequence{} + ); + } +#else + template ::type = 0> + Mat(const E& e00, const E& e01, const E& e02, + const E& e10, const E& e11, const E& e12, + const E& e20, const E& e21, const E& e22) + { + const E elems[9] = {e00, e01, e02, + e10, e11, e12, + e20, e21, e22}; + for (int idx = 0; idx < 9; ++idx) + d[rIx(idx)] = elems[idx]; + } +#endif #ifndef SWIG // Construction from 1-6 *exact match* Rows @@ -1199,6 +1167,14 @@ template class Mat { const int col = k % N; // that's modulus, not cross product! return row*RS + col*CS; } + +#ifndef SWIG + template + void assignDataRowByRow(ElementsRowByRowTuple&& els, std::integer_sequence) + { + ((d[rIx(Idx)] = std::get(els)) , ...); + } +#endif }; ////////////////////////////////////////////// diff --git a/Bindings/SWIGSimTK/Vec.h b/Bindings/SWIGSimTK/Vec.h index a4722944b0..7a2fdbfca3 100644 --- a/Bindings/SWIGSimTK/Vec.h +++ b/Bindings/SWIGSimTK/Vec.h @@ -191,7 +191,7 @@ class Vec { NRows = M, NCols = 1, NPackedElements = M, - NActualElements = M * STRIDE, // includes trailing gap + NActualElements = (M-1)*STRIDE + 1, // no trailing gap NActualScalars = CNT::NActualScalars * NActualElements, RowSpacing = STRIDE, ColSpacing = NActualElements, diff --git a/CHANGELOG.md b/CHANGELOG.md index 95b3007a87..1533745333 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ performance and stability in wrapping solutions. - Added `Component::removeComponent` and `Component::extractComponent` methods, which enable removing subcomponents that were previously added via `Component::addComponent` or the `` XML element (#4174). - Updated required language level to C++20. (#3929) - Breaking: removed the `operator==` and `operator<` overloads in `ControlLinearNode` and replaced usages with the equivalent utility functions `isEqual()` and `isLessThan()`. (#4095) +- Made various changes to support builds on Ubuntu 24.04 with GCC 13. (#4186) v4.5.2 diff --git a/OpenSim/Analyses/Test/testOutputReporter.cpp b/OpenSim/Analyses/Test/testOutputReporter.cpp index c1451df6a4..35580e0b3f 100644 --- a/OpenSim/Analyses/Test/testOutputReporter.cpp +++ b/OpenSim/Analyses/Test/testOutputReporter.cpp @@ -213,9 +213,9 @@ void simulateMuscle( TimeSeriesTable_ tableSV("testOutputReporter_OutputsSpatialVec.sto"); double val_t0 = tableD.getIndependentColumn()[0]; - const SimTK::Real& val_ke0 = tableD.getRowAtIndex(0)[0]; - const Vec3& val_omega0 = tableV3.getRowAtIndex(0)[1]; - const SimTK::SpatialVec& val_jrf0 = tableSV.getRowAtIndex(0)[1]; + const SimTK::Real val_ke0 = tableD.getRowAtIndex(0)[0]; + const Vec3 val_omega0 = tableV3.getRowAtIndex(0)[1]; + const SimTK::SpatialVec val_jrf0 = tableSV.getRowAtIndex(0)[1]; CHECK_THAT(t0, Catch::Matchers::WithinAbs(val_t0, SimTK::Eps)); CHECK_THAT(ke0, Catch::Matchers::WithinAbs(val_ke0, SimTK::Eps)); @@ -229,9 +229,9 @@ void simulateMuscle( } double val_tf = tableD.getIndependentColumn()[tableD.getNumRows() - 1]; - const SimTK::Real& val_ke = tableD.getRowAtIndex(tableD.getNumRows() - 1)[0]; - const Vec3& val_omega = tableV3.getRowAtIndex(tableV3.getNumRows() - 1)[1]; - const SimTK::SpatialVec& val_jrf = + const SimTK::Real val_ke = tableD.getRowAtIndex(tableD.getNumRows() - 1)[0]; + const Vec3 val_omega = tableV3.getRowAtIndex(tableV3.getNumRows() - 1)[1]; + const SimTK::SpatialVec val_jrf = tableSV.getRowAtIndex(tableSV.getNumRows() - 1)[1]; model.realizeReport(state); diff --git a/OpenSim/Simulation/Wrap/PathWrapPoint.cpp b/OpenSim/Simulation/Wrap/PathWrapPoint.cpp index ad48f0897d..dfae17e4cc 100644 --- a/OpenSim/Simulation/Wrap/PathWrapPoint.cpp +++ b/OpenSim/Simulation/Wrap/PathWrapPoint.cpp @@ -27,9 +27,11 @@ void OpenSim::PathWrapPoint::extendAddToSystem(SimTK::MultibodySystem& system) c { Super::extendAddToSystem(system); - _wrapPath = addCacheVariable("wrap_path", Array{}, SimTK::Stage::Position); + _wrapPath = addCacheVariable("wrap_path", + Array(SimTK::Vec3(SimTK::NaN), 0, 1), + SimTK::Stage::Position); _wrapPathLength = addCacheVariable("wrap_path_length", 0.0, SimTK::Stage::Position); - _location = addCacheVariable("wrap_location", SimTK::Vec3{}, SimTK::Stage::Position); + _location = addCacheVariable("wrap_location", SimTK::Vec3(SimTK::NaN), SimTK::Stage::Position); } const OpenSim::WrapObject* OpenSim::PathWrapPoint::getWrapObject() const diff --git a/OpenSim/Simulation/Wrap/WrapResult.cpp b/OpenSim/Simulation/Wrap/WrapResult.cpp index 460d0c9094..8abcecfe4a 100644 --- a/OpenSim/Simulation/Wrap/WrapResult.cpp +++ b/OpenSim/Simulation/Wrap/WrapResult.cpp @@ -32,47 +32,40 @@ using namespace std; using namespace OpenSim; -WrapResult::WrapResult(const WrapResult& other) { - copyData(other); -} - -//_____________________________________________________________________________ -/** - * Copy data members from one WrapResult to another. - * - * @param aWrapResult WrapResult to be copied. - */ -void WrapResult::copyData(const WrapResult& aWrapResult) { - wrap_pts = aWrapResult.wrap_pts; - wrap_path_length = aWrapResult.wrap_path_length; - - startPoint = aWrapResult.startPoint; - endPoint = aWrapResult.endPoint; - - int i; - for (i = 0; i < 3; i++) { - r1[i] = aWrapResult.r1[i]; - r2[i] = aWrapResult.r2[i]; - c1[i] = aWrapResult.c1[i]; - sv[i] = aWrapResult.sv[i]; - } +WrapResult::WrapResult() + : startPoint{-1}, + endPoint{-1}, + wrap_pts{SimTK::Vec3(SimTK::NaN), 0, 1}, + wrap_path_length{SimTK::NaN}, + r1{SimTK::Vec3(SimTK::NaN)}, + r2{SimTK::Vec3(SimTK::NaN)}, + c1{SimTK::Vec3(SimTK::NaN)}, + sv{SimTK::Vec3(SimTK::NaN)} {} - singleWrap = aWrapResult.singleWrap; - // TODO: Should factor be omitted from the copy? -} +WrapResult::WrapResult(const WrapResult& other) + : startPoint{other.startPoint}, + endPoint{other.endPoint}, + wrap_pts{other.wrap_pts}, + wrap_path_length{other.wrap_path_length}, + r1{other.r1}, + r2{other.r2}, + c1{other.c1}, + sv{other.sv}, + factor{SimTK::NaN}, + singleWrap{other.singleWrap} {} -//============================================================================= -// OPERATORS -//============================================================================= -//_____________________________________________________________________________ -/** - * Assignment operator. - * - * @return Reference to this object. - */ -WrapResult& WrapResult::operator=(const WrapResult& aWrapResult) { - if (this != &aWrapResult) { - copyData(aWrapResult); +WrapResult& WrapResult::operator=(const WrapResult& other) { + if (this != &other) { + startPoint = other.startPoint; + endPoint = other.endPoint; + wrap_pts = other.wrap_pts; + wrap_path_length = other.wrap_path_length; + r1 = other.r1; + r2 = other.r2; + c1 = other.c1; + sv = other.sv; + factor = SimTK::NaN; + singleWrap = other.singleWrap; } return *this; diff --git a/OpenSim/Simulation/Wrap/WrapResult.h b/OpenSim/Simulation/Wrap/WrapResult.h index 5c469c49a4..6ca8f5fd63 100644 --- a/OpenSim/Simulation/Wrap/WrapResult.h +++ b/OpenSim/Simulation/Wrap/WrapResult.h @@ -69,14 +69,11 @@ class OSIMSIMULATION_API WrapResult // CONSTRUCTION //-------------------------------------------------------------------------- public: - WrapResult() = default; + WrapResult(); virtual ~WrapResult() = default; WrapResult(const WrapResult& other); WrapResult& operator=(const WrapResult& aWrapResult); -private: - void copyData(const WrapResult& aWrapResult); - //============================================================================= }; // END of class WrapResult //============================================================================= diff --git a/dependencies/CMakeLists.txt b/dependencies/CMakeLists.txt index b126aaa3ad..e7a55a425e 100644 --- a/dependencies/CMakeLists.txt +++ b/dependencies/CMakeLists.txt @@ -185,7 +185,7 @@ AddDependency(NAME ezc3d AddDependency(NAME simbody DEFAULT ON GIT_URL https://github.com/simbody/simbody.git - GIT_TAG 77bf63c030e4c30112952602abe120afedbdb1e6 + GIT_TAG f9ab12cbad9d0da106473259d34c50577f934f49 CMAKE_ARGS -DBUILD_EXAMPLES:BOOL=OFF -DBUILD_TESTING:BOOL=OFF ${SIMBODY_EXTRA_CMAKE_ARGS})