diff --git a/.docker/Dockerfile b/.docker/Dockerfile
index edc945b0e..9b07c8197 100644
--- a/.docker/Dockerfile
+++ b/.docker/Dockerfile
@@ -1,12 +1,10 @@
ARG from=diegoferigo/gym-ignition:pypi-master
FROM ${from}
-# Source /etc/bash.bashrc before each command
-SHELL ["/bin/bash", "-i", "-c"]
-
# Install the PyPI package in a virtualenv
ARG pip_options=""
RUN virtualenv -p $(which python3) ${VIRTUAL_ENV} &&\
+ python -m pip install --upgrade pip &&\
pip install ${pip_options} gym-ignition &&\
rm -r $HOME/.cache/pip
@@ -15,5 +13,7 @@ WORKDIR /github
ARG branch="master"
RUN git clone -b ${branch} https://github.com/robotology/gym-ignition /github
-CMD ["bash"]
+# Reset the entrypoint
ENTRYPOINT [""]
+
+CMD ["bash"]
diff --git a/.docker/base.Dockerfile b/.docker/base.Dockerfile
index 75fc24448..5fca6ba22 100644
--- a/.docker/base.Dockerfile
+++ b/.docker/base.Dockerfile
@@ -59,21 +59,4 @@ RUN add-apt-repository ppa:git-core/ppa &&\
ENV VIRTUAL_ENV=/venv
ENV PATH=$VIRTUAL_ENV/bin:$PATH
-# Install iDynTree
-RUN apt-get update &&\
- apt-get install -y --no-install-recommends \
- python3-numpy libxml2-dev coinor-libipopt-dev libeigen3-dev &&\
- rm -rf /var/lib/apt/lists/* &&\
- git clone --depth 1 -b devel https://github.com/robotology/idyntree /tmp/idyntree &&\
- mkdir -p /tmp/idyntree/build && cd /tmp/idyntree/build &&\
- cmake .. \
- -GNinja \
- -DCMAKE_BUILD_TYPE=Release \
- -DBUILD_SHARED_LIBS:BOOL=OFF \
- -DIDYNTREE_USES_PYTHON=True \
- -DIDYNTREE_USES_IPOPT:BOOL=ON \
- &&\
- cmake --build . --target install &&\
- rm -r /tmp/idyntree
-
CMD ["bash"]
diff --git a/.docker/cicd-devel.Dockerfile b/.docker/cicd-devel.Dockerfile
index 88a272300..eb32c7cfa 100644
--- a/.docker/cicd-devel.Dockerfile
+++ b/.docker/cicd-devel.Dockerfile
@@ -1,76 +1,24 @@
ARG from=diegoferigo/gym-ignition:base
FROM ${from}
-ARG IGNITION_DEFAULT_CHANNEL="stable"
-RUN echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-${IGNITION_DEFAULT_CHANNEL} `lsb_release -cs` main" > \
- /etc/apt/sources.list.d/gazebo-${IGNITION_DEFAULT_CHANNEL}.list &&\
- wget http://packages.osrfoundation.org/gazebo.key -O - | apt-key add - &&\
- apt-get update &&\
- apt-get install -y --no-install-recommends \
- cmake \
- freeglut3-dev \
- libavcodec-dev \
- libavdevice-dev \
- libavformat-dev \
- libavutil-dev \
- libbenchmark-dev \
- libcurl4-openssl-dev \
- libfreeimage-dev \
- libgflags-dev \
- libglew-dev \
- libgts-dev \
- libjsoncpp-dev \
- libogre-1.9-dev \
- libogre-2.1-dev \
- libprotobuf-dev \
- libprotoc-dev \
- libqt5core5a \
- libsqlite3-dev \
- libswscale-dev \
- libtinyxml-dev \
- libtinyxml2-dev \
- libwebsockets-dev \
- libyaml-dev \
- libzip-dev \
- libzmq3-dev \
- pkg-config \
- protobuf-compiler \
- python \
- qml-module-qt-labs-folderlistmodel \
- qml-module-qt-labs-settings \
- qml-module-qtqml-models2 \
- qml-module-qtquick-controls \
- qml-module-qtquick-controls2 \
- qml-module-qtquick-dialogs \
- qml-module-qtquick-layouts \
- qml-module-qtquick2 \
- qtbase5-dev \
- qtdeclarative5-dev \
- qtquickcontrols2-5-dev \
- ruby \
- ruby-dev \
- ruby-ronn \
- swig \
- uuid-dev \
- # Additional
- libdart-collision-ode-dev \
- libdart-dev \
- libdart-external-ikfast-dev \
- libdart-external-odelcpsolver-dev \
- libdart-utils-urdf-dev \
- &&\
- rm -rf /var/lib/apt/lists/*
-
RUN pip3 install vcstool colcon-common-extensions &&\
rm -r $HOME/.cache/pip
ARG CMAKE_BUILD_TYPE="Release"
-ARG ignition_codename="citadel"
+ARG ignition_codename="fortress"
+ARG IGNITION_DEFAULT_CHANNEL="stable"
-RUN mkdir -p /workspace/src &&\
+RUN echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-${IGNITION_DEFAULT_CHANNEL} `lsb_release -cs` main" > \
+ /etc/apt/sources.list.d/gazebo-${IGNITION_DEFAULT_CHANNEL}.list &&\
+ wget http://packages.osrfoundation.org/gazebo.key -O - | apt-key add - &&\
+ apt-get update &&\
+ mkdir -p /workspace/src &&\
cd /workspace/src &&\
wget https://raw.githubusercontent.com/ignition-tooling/gazebodistro/master/collection-${ignition_codename}.yaml &&\
vcs import < collection-${ignition_codename}.yaml &&\
+ apt -y install --no-install-recommends \
+ $(sort -u $(find . -iname 'packages-'$(lsb_release -cs)'.apt' -o -iname 'packages.apt') | grep -v -E "dart|^libignition|^libsdformat" | tr '\n' ' ') &&\
+ rm -rf /var/lib/apt/lists/* &&\
cd /workspace &&\
colcon graph &&\
colcon build \
@@ -80,8 +28,12 @@ RUN mkdir -p /workspace/src &&\
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \
--merge-install \
&&\
+ find build/ -type f -not -name 'CMakeCache.txt' -delete &&\
echo "source /workspace/install/setup.bash" >> /etc/bash.bashrc
+# Source /etc/bash.bashrc before each command
+SHELL ["/bin/bash", "-i", "-c"]
+
COPY entrypoint.sh /entrypoint.sh
COPY setup_virtualenv.sh /setup_virtualenv.sh
RUN chmod 755 /entrypoint.sh
diff --git a/.docker/cicd-master.Dockerfile b/.docker/cicd-master.Dockerfile
index f464f77b3..a7307c06d 100644
--- a/.docker/cicd-master.Dockerfile
+++ b/.docker/cicd-master.Dockerfile
@@ -2,7 +2,7 @@ ARG from=diegoferigo/gym-ignition:base
FROM ${from}
# Install ignition gazebo
-ARG ignition_codename="citadel"
+ARG ignition_codename="fortress"
RUN echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" \
> /etc/apt/sources.list.d/gazebo-stable.list &&\
wget http://packages.osrfoundation.org/gazebo.key -O - | apt-key add - &&\
diff --git a/.docker/docker-compose.yml b/.docker/docker-compose.yml
index 8cd493a50..a630f09d9 100644
--- a/.docker/docker-compose.yml
+++ b/.docker/docker-compose.yml
@@ -40,7 +40,7 @@ services:
build:
args:
from: diegoferigo/gym-ignition:base
- ignition_codename: dome
+ ignition_codename: fortress
CMAKE_BUILD_TYPE: Debug
context: .
dockerfile: cicd-devel.Dockerfile
@@ -50,7 +50,7 @@ services:
build:
args:
from: diegoferigo/gym-ignition:base
- ignition_codename: dome
+ ignition_codename: fortress
CMAKE_BUILD_TYPE: Release
context: .
dockerfile: cicd-devel.Dockerfile
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 000000000..6f458db64
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,2 @@
+# Default owners
+* @diegoferigo
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index ac1cdd1f5..36f273f8a 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -6,8 +6,9 @@ labels: issue::type::enhancement
-โ ๏ธ If you're not sure on the specifics of the feature or would like a broader discussion,
-please consider posting a proposal to [Discussions][Discussions] instead.
+โ ๏ธ If you're not sure on the specifics of the feature or would like a broader discussion, please consider posting a proposal to [Discussions][Discussions] instead.
+
+[Discussions]: https://github.com/robotology/gym-ignition/discussions
## Summary
@@ -15,8 +16,7 @@ Describe what this new feature is about and the context you would find it useful
## Implementation suggestion
-Provide a suggestion on how to implement this feature, which could help us
-to speed up the implementation.
+Provide a suggestion on how to implement this feature, which could help us to speed up the implementation.
## Additional context
diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml
index 38ead433a..68d3cd0dd 100644
--- a/.github/workflows/cicd.yml
+++ b/.github/workflows/cicd.yml
@@ -9,26 +9,26 @@ on:
jobs:
- build-and-test:
- name: Build and Test
+# =============
+ build-colcon:
+# =============
+ name: 'colcon@${{ matrix.ignition }}'
+ if: |
+ (github.event_name == 'push' && github.ref != 'refs/heads/master') ||
+ (github.event_name == 'pull_request' && github.event.pull_request.base.ref != 'master')
runs-on: ubuntu-latest
- container: 'ubuntu:focal'
strategy:
fail-fast: false
matrix:
- type:
- - User
- - Developer
ignition:
- - dome
- # - citadel
-
+ # - dome
+ # - edifice
+ - fortress
env:
CCACHE_DIR: ${{ github.workspace }}/.ccache
-
steps:
- - name: Inspect Environment
+ - name: '๐๏ธ Inspect Environment'
run: |
env | grep ^GITHUB
echo ""
@@ -36,80 +36,65 @@ jobs:
echo ""
env
- - name: Install dependencies
+ - name: 'โฌ๏ธ๏ธ Install dependencies'
run: |
- apt-get update
- apt-get install -y --no-install-recommends \
- wget \
+ sudo apt-get update
+ sudo apt-get install -y --no-install-recommends \
+ lz4 \
git \
+ wget \
gpg-agent \
ninja-build \
build-essential \
- software-properties-common \
- python3 \
- python3-pip \
- python3-wheel
- pip3 install pytest pytest-xvfb setuptools_scm
- env:
- DEBIAN_FRONTEND: noninteractive
+ software-properties-common
- - uses: actions/checkout@master
- - run: git fetch --prune --unshallow
+ - name: '๐ Initialize Python'
+ uses: actions/setup-python@v2
+ with:
+ python-version: 3.8
- - name: Compilation cache
+ - name: '๐ Compilation cache'
uses: actions/cache@v2
with:
path: ${{ env.CCACHE_DIR }}
# We include the commit sha in the cache key, as new cache entries are
# only created if there is no existing entry for the key yet.
- key: ${{ runner.os }}-ccache-${{ matrix.ignition }}-${{ matrix.type }}-${{ github.sha }}
+ key: ${{ runner.os }}-ccache-${{ matrix.ignition }}-${{ github.sha }}
# Restore any ccache cache entry, if none for the key above exists
- restore-keys: |
- ${{ runner.os }}-ccache-${{ matrix.ignition }}-${{ matrix.type }}
- ${{ runner.os }}-ccache-${{ matrix.ignition }}
- ${{ runner.os }}-ccache
+ restore-keys: ${{ runner.os }}-ccache-${{ matrix.ignition }}
- - name: Enable ccache
+ - name: '๐ Enable ccache'
run: |
- apt-get update
- apt-get install -y ccache
+ sudo apt-get update
+ sudo apt-get install -y ccache
echo "/usr/lib/ccache" >> $GITHUB_PATH
ccache --set-config=max_size=5.0G
ccache --set-config=sloppiness=file_macro,locale,time_macros
ccache -p
ccache -s
- # ================
- # Install Ignition
- # ================
-
- - name: '[Stable Channel] Install Ignition ${{ matrix.ignition }}'
- if: |
- github.event_name == 'release' ||
- github.ref == 'refs/heads/master' ||
- (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'master')
+ - name: 'โ๏ธ Add osrf ppa'
run: |
- sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" >\
+ sudo sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" >\
/etc/apt/sources.list.d/gazebo-stable.list'
- wget http://packages.osrfoundation.org/gazebo.key -O - | apt-key add -
- apt-get update
- apt-get install -y --no-install-recommends ignition-${{ matrix.ignition }}
+ wget http://packages.osrfoundation.org/gazebo.key -O - | sudo apt-key add -
+ sudo apt-get update
- - name: '[Nightly Channel] Install Ignition ${{ matrix.ignition }}'
- if: |
- (github.event_name == 'push' && github.ref != 'refs/heads/master') ||
- (github.event_name == 'pull_request' && github.event.pull_request.base.ref != 'master')
+ - name: 'โ๏ธ Prepare colcon workspace'
run: |
- sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" >\
- /etc/apt/sources.list.d/gazebo-stable.list'
- wget http://packages.osrfoundation.org/gazebo.key -O - | apt-key add -
- apt-get update
- pip3 install vcstool colcon-common-extensions
- mkdir -p /workspace/src
+ pip install vcstool colcon-common-extensions
+ sudo mkdir -p /workspace/src /workspace/install
+ sudo chmod -R a+rw /workspace
cd /workspace/src
wget -O - ${TAGS_YAML} | vcs import
- SYSTEM_VERSION=$(lsb_release -cs)
- apt-get -y install $(sort -u $(find . -iname 'packages-'$SYSTEM_VERSION'.apt' -o -iname 'packages.apt') | tr '\n' ' ')
+ echo $(sort -u $(find . -iname 'packages-'$(lsb_release -cs)'.apt' -o -iname 'packages.apt') | grep -v -E "^libignition|^libsdformat" | tr '\n' ' ') \
+ > /workspace/install/pkg.txt
+ xargs -a /workspace/install/pkg.txt sudo apt-get install -y --no-install-recommends
+ env:
+ TAGS_YAML: https://raw.githubusercontent.com/ignition-tooling/gazebodistro/master/collection-${{ matrix.ignition }}.yaml
+
+ - name: '๐๏ธ Build colcon workspace'
+ run: |
cd /workspace
colcon graph
colcon build \
@@ -118,144 +103,418 @@ jobs:
-DBUILD_TESTING:BOOL=OFF \
-DCMAKE_BUILD_TYPE=Debug \
--merge-install
- echo "source /workspace/install/setup.bash" >> /etc/bash.bashrc
- env:
- TAGS_YAML: https://raw.githubusercontent.com/ignition-tooling/gazebodistro/master/collection-${{ matrix.ignition }}.yaml
- # ==========================
- # Install other dependencies
- # ==========================
+ - name: '๐ Ccache stats'
+ run: ccache --show-stats
+
+ - name: '๐ฆ๏ธ Compress the workspace'
+ run: tar -I lz4 -cf /tmp/workspace_install.tar.lz4 /workspace/install
+ - name: 'โฌ๏ธ Upload the workspace'
+ uses: actions/upload-artifact@v2
+ with:
+ path: /tmp/workspace_install.tar.lz4
+ name: workspace-${{ matrix.ignition }}
+ retention-days: 1
+
+# ===============
+ build-and-test:
+# ===============
+ name: 'Build and Test [${{matrix.type}}|${{matrix.ignition}}|${{matrix.python}}]'
+ if: always()
+ needs: [ build-colcon ]
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os:
+ - ubuntu-latest
+ type:
+ - User
+ - Developer
+ ignition:
+ # - dome
+ # - edifice
+ - fortress
+ python:
+ - 3.8
+ - 3.9
+ steps:
+
+ - name: '๐ Inspect Environment'
+ run: |
+ env | grep ^GITHUB
+ echo ""
+ cat ${GITHUB_EVENT_PATH}
+ echo ""
+ env
- - name: Install iDynTree dependencies
+ - name: 'โฌ๏ธ Install build dependencies'
+ if: contains(matrix.os, 'ubuntu')
run: |
- apt-get update
- apt-get install -y --no-install-recommends \
- libxml2-dev coinor-libipopt-dev libeigen3-dev libassimp-dev swig
+ sudo apt-get update
+ sudo apt-get install -y --no-install-recommends \
+ lz4 \
+ git \
+ wget \
+ cmake \
+ gpg-agent \
+ ninja-build \
+ build-essential \
+ software-properties-common
+
+ - name: '๐ Initialize Python'
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python }}
+
+ - name: '๐ Clone repository'
+ uses: actions/checkout@master
+ - name: '๐ Download all refs'
+ run: git fetch --prune --unshallow
+
+ # ================
+ # Install Ignition
+ # ================
+
+ - name: 'โ๏ธ Add osrf ppa'
+ if: contains(matrix.os, 'ubuntu')
+ run: |
+ sudo sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" >\
+ /etc/apt/sources.list.d/gazebo-stable.list'
+ wget http://packages.osrfoundation.org/gazebo.key -O - | sudo apt-key add -
+ sudo apt-get update
+ - name: '[๐๏ธ|stable] Install Ignition from ppa'
+ if: |
+ contains(matrix.os, 'ubuntu') && (
+ github.event_name == 'release' ||
+ github.ref == 'refs/heads/master' ||
+ (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'master')
+ )
+ run: sudo apt-get install -y --no-install-recommends ignition-${{ matrix.ignition }}
+
+ - name: '[๐งช|nightly] Download pre-built colcon workspace'
+ uses: actions/download-artifact@v2
+ if: |
+ contains(matrix.os, 'ubuntu') && (
+ (github.event_name == 'push' && github.ref != 'refs/heads/master') ||
+ (github.event_name == 'pull_request' && github.event.pull_request.base.ref != 'master')
+ )
+ with:
+ path: /tmp
+ name: workspace-${{ matrix.ignition }}
+ - name: '[๐งช|nightly] Setup colcon workspace'
+ if: |
+ contains(matrix.os, 'ubuntu') && (
+ (github.event_name == 'push' && github.ref != 'refs/heads/master') ||
+ (github.event_name == 'pull_request' && github.event.pull_request.base.ref != 'master')
+ )
+ run: |
+ sudo tar -I lz4 -xf /tmp/workspace_install.tar.lz4 -C /
+ xargs -a /workspace/install/pkg.txt sudo apt-get install -y --no-install-recommends
+ echo "source /workspace/install/setup.bash" | sudo tee -a /etc/bash.bashrc
# =============
# Build project
# =============
- # Note: In order to execute the setup.sh script, the file /etc/bash.bashrc must be sourced.
- # To do that, we change the shell to a bash interactive session.
-
- # Developer installation
- - name: Install iDynTree
- if: matrix.type == 'Developer'
+ # This is required because ScenarIO needs to import the iDynTree targets
+ - name: 'โฌ๏ธ Install iDynTree dependencies'
+ if: contains(matrix.os, 'ubuntu')
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y --no-install-recommends \
+ libxml2-dev coinor-libipopt-dev libeigen3-dev libassimp-dev swig
+ - name: '๐ค Install iDynTree'
run: |
- pip3 install git+https://github.com/robotology/idyntree@devel
+ pip install idyntree
IDYNTREE_PYTHON_PKG=$(python3 -c 'import idyntree, pathlib; print(pathlib.Path(idyntree.__file__).parent)')
echo "CMAKE_PREFIX_PATH=$IDYNTREE_PYTHON_PKG" >> $GITHUB_ENV
- - name: '[Developer] Build and Install C++'
+
+ # Note: In order to execute the setup.sh script, the file /etc/bash.bashrc must be sourced.
+ # To do that, we change the shell to a bash interactive session with 'bash -i -e'.
+
+ # Developer installation
+ - name: '[๐ท|developer] Build and Install C++ ScenarIO'
if: matrix.type == 'Developer'
shell: bash -i -e {0}
run: |
env
- mkdir build && cd build
- cmake .. \
+ cmake -S . -B build/ \
-GNinja \
-DCMAKE_BUILD_TYPE=Debug \
-DIGNITION_DISTRIBUTION=$(python3 -c "print('${{ matrix.ignition }}'.capitalize())")
- cmake --build . --target install
- - name: '[Developer] Setup Python Package'
+ sudo cmake --build build/ --target install
+ - name: '[๐ท|developer] Install Python ScenarIO'
if: matrix.type == 'Developer'
- run: pip3 install -e .
+ run: pip install -e ./scenario
# User installation
- - name: '[User] Create wheel'
- if: matrix.type == 'User' && matrix.ignition == 'dome'
+ - name: '[๐ค|user] Create wheel (default ignition)'
+ if: matrix.type == 'User' && matrix.ignition == 'fortress'
shell: bash -i -e {0}
- run: pip3 wheel -v -w dist/ .
- # Note: calling "pip wheel" with "--global-option" forces dependencies to be build from their sdist.
- # Since it's very slow, we create the wheel from setup.py without isolation.
- - name: '[User] Create wheel'
- if: matrix.type == 'User' && matrix.ignition != 'dome'
+ run: pip wheel --use-feature=in-tree-build -v -w dist/ ./scenario
+ # Note: Calling "pip wheel" with "--global-option" forces all dependencies to be built from their sdist.
+ # Since it's very slow, we create the wheel from setup.py without isolation (requires system deps).
+ - name: '[๐ค|user] Create wheel (custom ignition)'
+ if: matrix.type == 'User' && matrix.ignition != 'fortress'
shell: bash -i -e {0}
run: |
- pip3 install \
- cmake_build_extension \
- git+https://github.com/robotology/idyntree@devel
- python3 setup.py bdist_wheel \
+ pip install wheel setuptools-scm cmake-build-extension
+ python3 ./scenario/setup.py bdist_wheel \
build_ext -DIGNITION_DISTRIBUTION=$(python3 -c "print('${{ matrix.ignition }}'.capitalize())")
- - name: '[User] Install local wheel'
+ - name: '[๐ค|user] Install local wheel'
if: matrix.type == 'User'
- run: |
- cd dist
- pip3 install -v *.whl
+ run: pip install -v dist/scenario-*.whl
- - name: Inspect installed ScenarIO package
+ - name: '๐๏ธ Inspect installed ScenarIO package'
+ if: matrix.type == 'User' && contains(matrix.os, 'ubuntu')
run: |
- apt-get install -y --no-install-recommends tree
+ sudo apt-get install -y --no-install-recommends tree
tree $(python3 -c "import scenario, pathlib; print(pathlib.Path(scenario.__file__).parent)")
- - name: Ccache stats
- run: ccache --show-stats
+ # ====================
+ # Install gym-ignition
+ # ====================
+
+ - name: '๐ Install gym-ignition'
+ run: pip install wheel && pip install .[all]
# ============
# Test project
# ============
- - name: '[ScenarI/O] Python Tests'
- run: |
- cd tests
- pytest -m "scenario"
+ - name: '[๐|scenario] Python Tests'
+ shell: bash -i -e {0}
+ run: pytest -m "scenario"
- - name: '[ScenarI/O] Python Tests with Valgrind'
+ - name: '[๐จ|scenario] Python Tests with Valgrind'
+ shell: bash -i -e {0}
if: failure()
run: |
- apt-get install -y --no-install-recommends valgrind
- pip3 install colour-valgrind
- cd tests
- valgrind --log-file=/tmp/valgrind.log pytest -s -m "scenario" || colour-valgrind -t /tmp/valgrind.log
+ sudo apt-get install -y --no-install-recommends valgrind
+ pip install colour-valgrind
+ valgrind --log-file=/tmp/valgrind.log pytest -m "scenario" || colour-valgrind -t /tmp/valgrind.log
- - name: '[gym_ignition] Python Tests'
- run: |
- cd tests
- pytest -m "gym_ignition"
+ - name: '[๐|gym-ignition] Python Tests'
+ shell: bash -i -e {0}
+ run: pytest -m "gym_ignition"
- - name: '[gym_ignition] Python Tests with Valgrind'
+ - name: '[๐จ|gym-ignition] Python Tests with Valgrind'
+ shell: bash -i -e {0}
if: failure()
run: |
- pip3 install colour-valgrind
- cd tests
- valgrind --log-file=/tmp/valgrind.log pytest -s -m "gym_ignition" || colour-valgrind -t /tmp/valgrind.log
+ sudo apt-get install -y --no-install-recommends valgrind
+ pip install colour-valgrind
+ valgrind --log-file=/tmp/valgrind.log pytest -m "gym_ignition" || colour-valgrind -t /tmp/valgrind.log
- # ======
- # Deploy
- # ======
+ # ============================
+ # Upload artifacts (only User)
+ # ============================
- - name: Remove other wheels
+ - name: '๐๏ธ Remove external wheels'
if: matrix.type == 'User'
- run: find dist/ -type f -not -name 'gym_ignition-*' -delete
+ run: find dist/ -type f -not -name 'scenario-*' -delete -print
- - name: Rename wheel
- if: matrix.type == 'User'
+ # We have to trick PyPI that our wheels are manylinux2014 even if they are not.
+ # Unfortunately we cannot create self-contained wheels (neither the PEP600 perennial)
+ # due to the Ignition architecture.
+ - name: '๐ Rename scenario wheel'
+ if: matrix.type == 'User' && contains(matrix.os, 'ubuntu')
run: |
ls dist/
- find dist/ -type f -name "*.whl" -exec rename.ul linux manylinux1 {} +
+ find dist/ -type f -name "*.whl" -exec rename.ul linux manylinux2014 {} +
ls dist/
- # When this workflow will test other OSs, the sdist has to be created and pushed only once
- - name: Create sdist
+ - name: '๐ Inspect dist folder'
if: matrix.type == 'User'
- # if: matrix.type == 'User' && startsWith(matrix.os, 'ubuntu')
+ run: ls -lah dist/
+
+ - name: 'โฌ๏ธ Upload artifacts'
+ uses: actions/upload-artifact@v2
+ if: matrix.type == 'User' && matrix.ignition == 'fortress'
+ with:
+ path: dist/*
+ name: dist
+
+ # =======
+ # Website
+ # =======
+
+ - name: 'โฌ๏ธ Install website dependencies'
run: |
- pip3 install cmake_build_extension setuptools_scm
- python3 setup.py sdist
+ sudo apt-get update
+ sudo apt-get install -y doxygen texlive-font-utils
- - uses: actions/upload-artifact@v2
- if: matrix.type == 'User'
+ - name: '๐ Inspect metadata'
+ run: sphinx-multiversion --dump-metadata docs/sphinx/ build/
+
+ # This is necessary because otherwise the check for uncommitted apidoc
+ # only detects additions, not removals.
+ - name: '๐๏ธ Remove apidoc folder'
+ run: rm -r docs/sphinx/apidoc
+
+ - name: '๐๏ธ Build sphinx website'
+ shell: bash -i -e {0}
+ run: |
+ [[ -d build ]] && sudo chown -R $(id -u):$(id -g) build/
+ cmake -S . -B build/ -DBUILD_DOCS:BOOL=ON
+ cmake --build build/ --target sphinx
+
+ - name: '๐ Check new uncommitted apidoc'
+ run: test $(git status --porcelain | wc -l) -eq 0
+
+ - name: '๐ git status'
+ if: ${{ failure() }}
+ run: |
+ git status
+ git diff
+
+ - name: 'โฌ๏ธ Upload website folder'
+ uses: actions/upload-artifact@v2
+ if: matrix.type == 'User' && matrix.ignition == 'fortress' && contains(matrix.os, 'ubuntu')
+ with:
+ path: build/html
+ name: website
+ retention-days: 1
+
+# ===================
+ website-deployment:
+# ===================
+ name: 'Website Deployment'
+ needs: [ build-and-test ]
+ runs-on: ubuntu-latest
+ steps:
+
+ - name: 'โฌ๏ธ Download website folder'
+ uses: actions/download-artifact@v2
+ with:
+ path: build/html
+ name: website
+
+ - name: '๐ Inspect html folder'
+ run: ls -lah build/html
+
+ - name: '๐ Deploy'
+ uses: JamesIves/github-pages-deploy-action@releases/v3
+ if: |
+ github.event_name == 'push' &&
+ github.repository == 'robotology/gym-ignition' &&
+ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/devel')
+ with:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ BRANCH: gh-pages
+ FOLDER: build/html
+ CLEAN: true
+ CLEAN_EXCLUDE: '[".gitignore", ".nojekyll"]'
+
+# =================
+ python-packaging:
+# =================
+ name: 'Python packaging'
+ needs: [ build-and-test ]
+ runs-on: ubuntu-latest
+ steps:
+
+ - name: '๐๏ธ Inspect Environment'
+ run: |
+ env | grep ^GITHUB
+ echo ""
+ cat ${GITHUB_EVENT_PATH}
+ echo ""
+ env
+
+ # Any Python3 version is ok in this job
+ - name: '๐ Initialize Python'
+ uses: actions/setup-python@v2
+ with:
+ python-version: 3.8
+
+ - name: '๐ Clone repository'
+ uses: actions/checkout@master
+ - name: '๐ Download all refs'
+ run: git fetch --prune --unshallow
+
+ # ===============
+ # Download wheels
+ # ===============
+
+ - name: 'โฌ๏ธ Download scenario wheels'
+ uses: actions/download-artifact@v2
+ with:
+ path: dist
+ name: dist
+
+ - name: '๐ Inspect dist folder'
+ run: ls -lah dist/
+
+ # ===============
+ # Create packages
+ # ===============
+
+ # We use build to create sdist. Also pipx would work.
+ # https://github.com/pypa/build
+ # Compared to calling setup.py, the advantage of these tools is that
+ # they automatically handle the build dependencies.
+ - name: '๐๏ธ๏ธ Install dependencies'
+ run: pip install build
+
+ - name: '[๐ฆ|scenario]๏ธ Create sdist'
+ run: python -m build --sdist scenario/ -o dist/
+
+ - name: '[๐ฆ|gym-ignition]๏ธ Create sdist'
+ run: python -m build --sdist .
+
+ - name: '[๐ฆ|gym-ignition]๏ธ Create wheel'
+ run: python -m build --wheel .
+
+ # ================
+ # Upload artifacts
+ # ================
+
+ - name: '๐๏ธ Remove external packages'
+ run: find dist/ -type f -not \( -name '*scenario-*' -o -name '*gym_ignition-*' \) -delete -print
+
+ - name: '๐ Check packages'
+ run: pipx run twine check dist/*
+
+ - name: '๐ Inspect dist folder'
+ run: ls -lah dist/
+
+ - name: 'โฌ๏ธ Upload artifacts'
+ uses: actions/upload-artifact@v2
with:
- name: packages
path: dist/*
+ name: dist
+
+# ============
+ upload_pypi:
+# ============
+ name: Publish to PyPI
+ needs:
+ - build-and-test
+ - python-packaging
+ runs-on: ubuntu-20.04
+ # Devel branch produces pre-releases.
+ # Tagged versions produce stable releases.
+
+ steps:
+
+ - name: 'โฌ๏ธ Download Python packages'
+ uses: actions/download-artifact@v2
+ with:
+ path: dist
+ name: dist
+
+ - name: '๐ Inspect dist folder'
+ run: ls -lah dist/
# Validate the last tag accordingly to PEP440
# From https://stackoverflow.com/a/37972030/12150968
- - name: Check PEP440 compliance
+ - name: '๐ Check PEP440 compliance'
if: github.event_name == 'release'
run: |
- apt-get update
- apt-get install -y source-highlight
+ sudo apt-get update
+ sudo apt-get install -y source-highlight
last_tag_with_v="$(git describe --abbrev=0 --tags)"
last_tag=${last_tag_with_v#v}
rel_regexp='^(\d+!)?(\d+)(\.\d+)+([\.\-\_])?((a(lpha)?|b(eta)?|c|r(c|ev)?|pre(view)?)\d*)?(\.?(post|dev)\d*)?$'
@@ -266,12 +525,11 @@ jobs:
match=$(check-regexp ${rel_regexp} ${last_tag} | grep matches | cut -d ' ' -f 5)
test $match -eq 1 && true
- # The package is deployed only if there's an upstream release / prerelease, or it is upstream's devel.
- - name: Publish package to PyPI
+ - name: 'โฌ๏ธ Publish packages to PyPI'
if: |
- github.repository == 'robotology/gym-ignition' && matrix.type == 'User' &&
- ((github.event_name == 'release' && github.event.action == 'published' && matrix.ignition == 'dome') ||
- (github.event_name == 'push' && matrix.ignition == 'dome' && github.ref == 'refs/heads/devel'))
+ github.repository == 'robotology/gym-ignition' &&
+ ((github.event_name == 'release' && github.event.action == 'published') ||
+ (github.event_name == 'push' && github.ref == 'refs/heads/devel'))
uses: pypa/gh-action-pypi-publish@master
with:
user: __token__
diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml
new file mode 100644
index 000000000..acdae9fe6
--- /dev/null
+++ b/.github/workflows/style.yml
@@ -0,0 +1,74 @@
+name: Code Style
+
+on:
+ push:
+ pull_request:
+ workflow_dispatch:
+
+jobs:
+
+ clang-format:
+
+ name: clang-format
+ runs-on: ubuntu-latest
+
+ steps:
+
+ - name: "๐ Checkout repository"
+ uses: actions/checkout@v2
+
+ - name: "โฌ๏ธ๏ธ Install dependencies"
+ run: sudo apt-get install -y --no-install-recommends colordiff
+
+ - name: "๐ Format C++"
+ uses: diegoferigo/gh-action-clang-format@main
+ id: format
+ with:
+ style: file
+ pattern: |
+ *.h
+ *.cpp
+
+ - name: "๐๏ธ Inspect style diff"
+ if: failure()
+ run: printf "${{ steps.format.outputs.diff }}" | colordiff
+
+ black:
+
+ name: black
+ runs-on: ubuntu-latest
+
+ steps:
+
+ - name: "๐ Checkout repository"
+ uses: actions/checkout@v2
+
+ - name: '๐ Initialize Python'
+ uses: actions/setup-python@v2
+ with:
+ python-version: "3.8"
+
+ - name: "๐ Black Code Formatter"
+ uses: psf/black@stable
+ with:
+ options: --check --diff --color
+
+ isort:
+
+ name: isort
+ runs-on: ubuntu-latest
+
+ steps:
+
+ - name: "๐ Checkout repository"
+ uses: actions/checkout@v2
+
+ - name: '๐ Initialize Python'
+ uses: actions/setup-python@v2
+ with:
+ python-version: "3.8"
+
+ - name: "๐ isort"
+ uses: isort/isort-action@master
+ with:
+ configuration: --check --diff --color
diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml
deleted file mode 100644
index 339c65bac..000000000
--- a/.github/workflows/website.yml
+++ /dev/null
@@ -1,109 +0,0 @@
-name: Website
-
-on:
- push:
- tags-ignore:
- - '**'
- pull_request:
- branches:
- - master
- - devel
-
-jobs:
- website:
- name: Build and Deploy
- runs-on: ubuntu-20.04
-
- steps:
-
- - uses: actions/checkout@master
- with:
- persist-credentials: false
-
- - run: git fetch --prune --unshallow
-
- - name: Setup Environment
- run: |
- echo "CC=gcc" >> $GITHUB_ENV
- echo "CXX=g++" >> $GITHUB_ENV
- echo "PYTHON_VERSION=3.8" >> $GITHUB_ENV
- env
-
- - name: Inspect Environment
- run: |
- env | grep ^GITHUB
- cat ${GITHUB_EVENT_PATH}
-
- - name: Setup docker image [master]
- if: |
- (github.event_name == 'push' && github.ref == 'refs/heads/master') ||
- (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'master')
- run: |
- docker run -d -i --name ci -v $(pwd):/github -w /github \
- -v /home/runner/work/_temp/:/home/runner/work/_temp/:rw \
- -e PYTHON_VERSION=$PYTHON_VERSION -e CC=$CC -e CXX=$CXX \
- diegoferigo/gym-ignition:ci-master bash
-
- - name: Setup docker image [devel]
- if: |
- (github.event_name == 'push' && github.ref != 'refs/heads/master') ||
- (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'devel')
- run: |
- docker run -d -i --name ci -v $(pwd):/github -w /github \
- -v /home/runner/work/_temp/:/home/runner/work/_temp/:rw \
- -e PYTHON_VERSION=$PYTHON_VERSION -e CC=$CC -e CXX=$CXX \
- diegoferigo/gym-ignition:ci-devel bash
-
- - name: Wait entrypoint
- run: |
- sleep 30
- docker logs ci
-
- - name: Install packages
- shell: docker exec -i ci bash -i -e {0}
- run: |
- apt-get update
- apt-get install -y doxygen texlive-font-utils
-
- - name: Install website dependecies
- shell: docker exec -i ci bash -i -e {0}
- run: pip3 install -e .[website]
-
- - name: Inspect metadata
- shell: docker exec -i ci bash -i -e {0}
- run: sphinx-multiversion --dump-metadata docs/sphinx/ build/
-
- # This is necessary because otherwise the check for uncommitted apidoc
- # only detects additions, not removals.
- - name: Remove apidoc folder
- shell: docker exec -i ci bash -i -e {0}
- run: rm -r docs/sphinx/apidoc
-
- - name: Build sphinx website
- shell: docker exec -i ci bash -i -e {0}
- run: |
- mkdir build && cd build
- cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DBUILD_DOCS:BOOL=ON
- cmake --build . --target sphinx
-
- - name: Check new uncommitted apidoc
- run: test $(git status --porcelain | wc -l) -eq 0
-
- - name: git status
- if: ${{ failure() }}
- run: |
- git status
- git diff
-
- - name: Deploy
- uses: JamesIves/github-pages-deploy-action@releases/v3
- if: |
- github.event_name == 'push' &&
- github.repository == 'robotology/gym-ignition' &&
- (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/devel')
- with:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- BRANCH: gh-pages
- FOLDER: build/html
- CLEAN: true
- CLEAN_EXCLUDE: '[".gitignore", ".nojekyll"]'
diff --git a/.gitignore b/.gitignore
index 1e3b0d6c0..803310da2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,5 +13,5 @@ __pycache__
*.egg-info
*.cache
.idea*
-dist/*
+**/dist/*
.egg*
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 24ff38ee5..e429cc1d4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,220 +2,20 @@
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.
+# This file is here only to allow build systems to find the
+# real CMake project that is stored in the scenario/ folder.
cmake_minimum_required(VERSION 3.16)
-project(Scenario VERSION 1.2.2)
+project(scenario)
+add_subdirectory(scenario)
-# Add custom functions / macros
-list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
+# The uninstall target resource must be included in the top-level CMakeLists
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/scenario/cmake)
+include(AddUninstallTarget)
+
+# =============
+# DOCUMENTATION
+# =============
if(BUILD_DOCS)
add_subdirectory(docs)
endif()
-
-# C++ standard
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_EXTENSIONS OFF)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
-# Include useful features
-include(GNUInstallDirs)
-
-# Build type
-if(NOT CMAKE_CONFIGURATION_TYPES)
- if(NOT CMAKE_BUILD_TYPE)
- set(CMAKE_BUILD_TYPE "Release" CACHE STRING
- "Choose the type of build, recommended options are: Debug or Release" FORCE)
- endif()
- set(SCENARIO_BUILD_TYPES "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
- set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${SCENARIO_BUILD_TYPES})
-endif()
-
-# This new build mode configures the CMake project to be compatible with the pipeline to
-# create the PyPI linux wheel
-include(AddNewBuildMode)
-add_new_build_mode(NAME "PyPI" TEMPLATE "Release")
-
-# Expose shared or static compilation
-set(SCENARIO_BUILD_SHARED_LIBRARY TRUE
- CACHE BOOL "Compile libraries as shared libraries")
-
-if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "PyPI")
- # Apply the user choice
- set(BUILD_SHARED_LIBS ${SCENARIO_BUILD_SHARED_LIBRARY})
-else()
- # Check that is Linux
- if(NOT (UNIX AND NOT APPLE))
- message(FATAL_ERROR "PyPI packages can be only created for Linux at the moment")
- endif()
-
- if(SCENARIO_BUILD_SHARED_LIBRARY)
- message(WARNING "Enabling static compilation, required by the PyPI build mode")
- endif()
-
- # Force static compilation
- set(BUILD_SHARED_LIBS FALSE)
-endif()
-
-# Use -fPIC even if statically compiled
-set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-
-# Tweak linker flags in Linux
-if(UNIX AND NOT APPLE)
- if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
- get_filename_component(LINKER_BIN ${CMAKE_LINKER} NAME)
- if("${LINKER_BIN}" STREQUAL "ld")
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--unresolved-symbols=report-all")
- endif()
- endif()
-endif()
-
-# Control where binaries and libraries are placed in the build folder.
-# This simplifies tests running in Windows.
-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}")
-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
-
-# Get include-what-you-use information when compiling
-option(SCENARIO_USE_IWYU "Get the output of include-what-you-use" OFF)
-mark_as_advanced(SCENARIO_USE_IWYU)
-if(SCENARIO_USE_IWYU)
- find_program(IWYU_PATH NAMES include-what-you-use iwyu)
- if(IWYU_PATH)
- set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${IWYU_PATH})
- endif()
-endif()
-
-# Settings for RPATH
-if(NOT MSVC)
- option(ENABLE_RPATH "Enable RPATH installation" TRUE)
- mark_as_advanced(ENABLE_RPATH)
-endif()
-
-# Dependencies
-add_subdirectory(deps)
-
-if(${CMAKE_VERSION} VERSION_GREATER 3.15)
- cmake_policy(SET CMP0094 NEW)
-endif()
-
-# Find virtualenv's before system's interpreters
-set(Python3_FIND_VIRTUALENV "FIRST" CACHE STRING
- "Configure the detection of virtual environments")
-set(Python3_FIND_VIRTUALENV_TYPES "FIRST" "ONLY" "STANDARD")
-mark_as_advanced(Python3_FIND_VIRTUALENV)
-set_property(CACHE Python3_FIND_VIRTUALENV PROPERTY STRINGS ${Python3_FIND_VIRTUALENV_TYPES})
-
-# Find Python3
-find_package(Python3 COMPONENTS Interpreter Development REQUIRED)
-message(STATUS "Using Python: ${Python3_EXECUTABLE}")
-
-# Select the appropriate install prefix used throughout the project.
-set(SCENARIO_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR})
-set(SCENARIO_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR})
-set(SCENARIO_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})
-
-if(NOT CMAKE_BUILD_TYPE STREQUAL "PyPI")
- # Add the libraries installed in the Python site-package folder
- set(EXTRA_RPATH_DIRS
- "${Python3_SITELIB}"
- "${Python3_SITELIB}/scenario/bindings")
-else()
- # Add the libraries installed in the Python site-package folder
- # (that in this case is CMAKE_INSTALL_PREFIX)
- set(EXTRA_RPATH_DIRS
- "${CMAKE_INSTALL_PREFIX}"
- "${CMAKE_INSTALL_PREFIX}/scenario/bindings")
-endif()
-
-# Configure RPATH
-include(AddInstallRPATHSupport)
-add_install_rpath_support(
- BIN_DIRS
- "${CMAKE_INSTALL_PREFIX}/${GYMPP_INSTALL_BINDIR}"
- "${CMAKE_INSTALL_PREFIX}/${SCENARIO_INSTALL_BINDIR}"
- LIB_DIRS
- "${CMAKE_INSTALL_PREFIX}/${SCENARIO_INSTALL_LIBDIR}"
- "${CMAKE_INSTALL_PREFIX}/${SCENARIO_INSTALL_LIBDIR}/scenario/plugins"
- "${EXTRA_RPATH_DIRS}"
- INSTALL_NAME_DIR
- "${CMAKE_INSTALL_PREFIX}/${SCENARIO_INSTALL_LIBDIR}"
- DEPENDS ENABLE_RPATH
- USE_LINK_PATH)
-
-# Find a supported Ignition distribution
-if(NOT IGNITION_DISTRIBUTION)
-
- include(FindIgnitionDistribution)
- set(SUPPORTED_IGNITION_DISTRIBUTIONS "Dome" "Citadel")
-
- foreach(distribution IN LISTS SUPPORTED_IGNITION_DISTRIBUTIONS)
-
- find_ignition_distribution(
- CODENAME ${distribution}
- PACKAGES
- ignition-gazebo
- REQUIRED FALSE)
-
- if(${${distribution}_FOUND})
- message(STATUS "Found Ignition ${distribution}")
-
- # Select Ignition distribution
- set(IGNITION_DISTRIBUTION "${distribution}" CACHE
- STRING "The Ignition distribution found in the system")
- set_property(CACHE IGNITION_DISTRIBUTION PROPERTY
- STRINGS ${SUPPORTED_IGNITION_DISTRIBUTIONS})
-
- break()
- endif()
-
- endforeach()
-
-endif()
-
-if(NOT IGNITION_DISTRIBUTION OR "${IGNITION_DISTRIBUTION}" STREQUAL "")
- set(USE_IGNITION FALSE)
-else()
- set(USE_IGNITION TRUE)
-endif()
-
-option(SCENARIO_USE_IGNITION
- "Build C++ code depending on Ignition"
- ${USE_IGNITION})
-
-# Fail if Ignition is enabled but no compatible distribution was found
-if(SCENARIO_USE_IGNITION AND "${IGNITION_DISTRIBUTION}" STREQUAL "")
- message(FATAL_ERROR "Failed to find a compatible Ignition Gazebo distribution")
-endif()
-
-# Alias the targets
-if(SCENARIO_USE_IGNITION)
- include(ImportTargets${IGNITION_DISTRIBUTION})
-endif()
-
-# Helper for exporting targets
-include(InstallBasicPackageFiles)
-
-# =========
-# SCENARI/O
-# =========
-
-add_subdirectory(cpp/scenario)
-
-# ========
-# BINDINGS
-# ========
-
-# Require to find Ignition libraries when packaging for PyPI
-if(CMAKE_BUILD_TYPE STREQUAL "PyPI" AND NOT USE_IGNITION)
- message(FATAL_ERROR "Found no Ignition distribution for PyPI package")
-endif()
-
-find_package(SWIG 4.0 QUIET)
-option(SCENARIO_ENABLE_BINDINGS "Enable SWIG bindings" ${SWIG_FOUND})
-
-if(SCENARIO_ENABLE_BINDINGS)
- add_subdirectory(bindings)
-endif()
-
-# Add unistall target
-include(AddUninstallTarget)
diff --git a/README.md b/README.md
index d45365f74..fa6d94cfc 100644
--- a/README.md
+++ b/README.md
@@ -2,36 +2,10 @@
gym-ignition
-
-Description
-โข
-Setup
-โข
-Citation
-โข
-Website
-
-
+||||
+|:---:|:---:|:---:|
+| ![][pendulum] | ![][panda] | ![][icub] |
+
+[icub]: https://user-images.githubusercontent.com/469199/99262746-9e021a80-281e-11eb-9df1-d70134b0801a.png
+[panda]: https://user-images.githubusercontent.com/469199/99263111-0cdf7380-281f-11eb-9cfe-338b2aae0503.png
+[pendulum]: https://user-images.githubusercontent.com/469199/99262383-321fb200-281e-11eb-89cc-cc31f590daa3.png
+
## Description
**gym-ignition** is a framework to create **reproducible robotics environments** for reinforcement learning research.
-The project consists of the following components:
+It is based on the [ScenarIO](scenario/) project which provides the low-level APIs to interface with the Ignition Gazebo simulator.
+By default, RL environments share a lot of boilerplate code, e.g. for initializing the simulator or structuring the classes
+to expose the `gym.Env` interface.
+Gym-ignition provides the [`Task`](python/gym_ignition/base/task.py) and [`Runtime`](python/gym_ignition/base/runtime.py)
+abstractions that help you focusing on the development of the decision-making logic rather than engineering.
+It includes [randomizers](python/gym_ignition/randomizers) to simplify the implementation of domain randomization
+of models, physics, and tasks.
+Gym-ignition also provides powerful dynamics algorithms compatible with both fixed-base and floating-based robots by
+exploiting [robotology/idyntree](https://github.com/robotology/idyntree/) and exposing
+[high-level functionalities](python/gym_ignition/rbd/idyntree).
-- [**`ScenarI/O`**](cpp/scenario/core):
- *Scene Interfaces for Robot Input / Output* is a C++ abstraction layer to interact with simulated and real robots.
-- [**`Gazebo ScenarI/O`**](cpp/scenario/gazebo):
- Implementation of the ScenarI/O interfaces to interact with the [Ignition Gazebo](https://ignitionrobotics.org) simulator.
- We provide Python bindings with functionalities comparable to popular alternatives like
- [pybullet](https://github.com/bulletphysics/bullet3) and [mujoco-py](https://github.com/openai/mujoco-py).
-- [**`gym_ignition`**](python/gym_ignition):
- A Python package with the tooling to create OpenAI Gym environments for robot learning.
- It provides abstractions like `Task` and `Runtime` to help developing environments that can be executed transparently
- on all the ScenarI/O implementations (different simulators, real robots, ...).
- The package also contains resources for inverse kinematics and multi-body dynamics supporting floating-based robots
- based on the [iDynTree](https://github.com/robotology/idyntree) library.
-- [**`gym_ignition_environments`**](python/gym_ignition_environments):
- Demo environments created with `gym_ignition` and [`gym-ignition-models`](https://github.com/dic-iit/gym-ignition-models)
- that show the recommended structure.
-
-This project provides the complete implementation of ScenarI/O for the Ignition Gazebo simulator.
-We expose all the physics engines supported by Ignition Gazebo.
-Currently, the default and only physics engine is [DART](https://github.com/dartsim/dart).
+Gym-ignition does not provide out-of-the-box environments ready to be used.
+Rather, its aim is simplifying and streamlining their development.
+Nonetheless, for illustrative purpose, it includes canonical examples in the
+[`gym_ignition_environments`](python/gym_ignition_environments) package.
-We are currently working on backends based on robotic middleware to transparently execute the environments developed
-with `gym_ignition` on real robots.
+Visit the [website][website] for more information about the project.
-If you're interested to know the reasons why we started developing gym-ignition and why we selected Ignition Gazebo for
-our simulations, visit the _Motivations_ section of the [website](https://robotology.github.io/gym-ignition).
+[website]: https://robotology.github.io/gym-ignition
-## Setup
+## Installation
-1. Install the latest Ignition suite following the [official instructions](https://ignitionrobotics.org/docs/dome).
-1. Execute `pip install gym-ignition`, preferably in a virtual environment.
+1. First, follow the installation instructions of [ScenarIO](scenario/).
+2. `pip install gym-ignition`, preferably in a [virtual environment](https://docs.python.org/3.8/tutorial/venv.html).
-**Note**: `gym-ignition` currently only supports the latest version of the ignition suite. For more information on supported versions please refer to the [Support Policy](https://robotology.github.io/gym-ignition/master/installation/support_policy.html).
+## Contributing
+You can visit our community forum hosted in [GitHub Discussions](https://github.com/robotology/gym-ignition/discussions).
+Even without coding skills, replying user's questions is a great way of contributing.
+If you use gym-ignition in your application and want to show it off, visit the
+[Show and tell](https://github.com/robotology/gym-ignition/discussions/categories/show-and-tell) section!
+You can advertise there your environments created with gym-ignition.
-Then, for some simple examples, visit the _Getting Started_ section of the [website](https://robotology.github.io/gym-ignition).
+Pull requests are welcome.
-You can decide to install only the C++ resources if you are not interested in using Python.
-We also offer a constantly updated pre-release channel with the last development updates.
-You can find all the details about the different types of installations we support in the [website](https://robotology.github.io/gym-ignition).
-
-||||
-|:---:|:---:|:---:|
-| ![](https://user-images.githubusercontent.com/469199/99262383-321fb200-281e-11eb-89cc-cc31f590daa3.png) | ![](https://user-images.githubusercontent.com/469199/99263111-0cdf7380-281f-11eb-9cfe-338b2aae0503.png) | ![](https://user-images.githubusercontent.com/469199/99262746-9e021a80-281e-11eb-9df1-d70134b0801a.png) |
+For major changes, please open a [discussion](https://github.com/robotology/gym-ignition/discussions)
+first to propose what you would like to change.
## Citation
-```
+```bibtex
@INPROCEEDINGS{ferigo2020gymignition,
title={Gym-Ignition: Reproducible Robotic Simulations for Reinforcement Learning},
author={D. {Ferigo} and S. {Traversaro} and G. {Metta} and D. {Pucci}},
@@ -132,6 +104,10 @@ You can find all the details about the different types of installations we suppo
}
```
+## License
+
+[LGPL v2.1](https://choosealicense.com/licenses/lgpl-2.1/) or any later version.
+
---
-**Disclaimer:** Gym-Ignition is an independent project and is not related by any means to OpenAI and Open Robotics.
+**Disclaimer:** Gym-ignition is an independent project and is not related by any means to OpenAI and Open Robotics.
diff --git a/cmake/FindPython/Support.cmake b/cmake/FindPython/Support.cmake
deleted file mode 100644
index a80640690..000000000
--- a/cmake/FindPython/Support.cmake
+++ /dev/null
@@ -1,2586 +0,0 @@
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
-
-# Taken from: https://github.com/Kitware/CMake/blob/v3.17.0/Modules/FindPython/Support.cmake
-
-#
-# This file is a "template" file used by various FindPython modules.
-#
-
-cmake_policy (GET CMP0094 _${_PYTHON_PREFIX}_LOOKUP_POLICY)
-
-cmake_policy (VERSION 3.7)
-
-if (_${_PYTHON_PREFIX}_LOOKUP_POLICY)
- cmake_policy (SET CMP0094 ${_${_PYTHON_PREFIX}_LOOKUP_POLICY})
-endif()
-
-#
-# Initial configuration
-#
-if (NOT DEFINED _PYTHON_PREFIX)
- message (FATAL_ERROR "FindPython: INTERNAL ERROR")
-endif()
-if (NOT DEFINED _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
- message (FATAL_ERROR "FindPython: INTERNAL ERROR")
-endif()
-if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL 3)
- set(_${_PYTHON_PREFIX}_VERSIONS 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
-elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL 2)
- set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
-else()
- message (FATAL_ERROR "FindPython: INTERNAL ERROR")
-endif()
-
-get_property(_${_PYTHON_PREFIX}_CMAKE_ROLE GLOBAL PROPERTY CMAKE_ROLE)
-
-
-#
-# helper commands
-#
-macro (_PYTHON_DISPLAY_FAILURE _PYTHON_MSG)
- if (${_PYTHON_PREFIX}_FIND_REQUIRED)
- message (FATAL_ERROR "${_PYTHON_MSG}")
- else()
- if (NOT ${_PYTHON_PREFIX}_FIND_QUIETLY)
- message(STATUS "${_PYTHON_MSG}")
- endif ()
- endif()
-
- set (${_PYTHON_PREFIX}_FOUND FALSE)
- string (TOUPPER "${_PYTHON_PREFIX}" _${_PYTHON_PREFIX}_UPPER_PREFIX)
- set (${_PYTHON_UPPER_PREFIX}_FOUND FALSE)
- return()
-endmacro()
-
-
-function (_PYTHON_MARK_AS_INTERNAL)
- foreach (var IN LISTS ARGV)
- if (DEFINED CACHE{${var}})
- set_property (CACHE ${var} PROPERTY TYPE INTERNAL)
- endif()
- endforeach()
-endfunction()
-
-
-macro (_PYTHON_SELECT_LIBRARY_CONFIGURATIONS _PYTHON_BASENAME)
- if(NOT DEFINED ${_PYTHON_BASENAME}_LIBRARY_RELEASE)
- set(${_PYTHON_BASENAME}_LIBRARY_RELEASE "${_PYTHON_BASENAME}_LIBRARY_RELEASE-NOTFOUND")
- endif()
- if(NOT DEFINED ${_PYTHON_BASENAME}_LIBRARY_DEBUG)
- set(${_PYTHON_BASENAME}_LIBRARY_DEBUG "${_PYTHON_BASENAME}_LIBRARY_DEBUG-NOTFOUND")
- endif()
-
- get_property(_PYTHON_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
- if (${_PYTHON_BASENAME}_LIBRARY_DEBUG AND ${_PYTHON_BASENAME}_LIBRARY_RELEASE AND
- NOT ${_PYTHON_BASENAME}_LIBRARY_DEBUG STREQUAL ${_PYTHON_BASENAME}_LIBRARY_RELEASE AND
- (_PYTHON_isMultiConfig OR CMAKE_BUILD_TYPE))
- # if the generator is multi-config or if CMAKE_BUILD_TYPE is set for
- # single-config generators, set optimized and debug libraries
- set (${_PYTHON_BASENAME}_LIBRARY "")
- foreach (_PYTHON_libname IN LISTS ${_PYTHON_BASENAME}_LIBRARY_RELEASE )
- list( APPEND ${_PYTHON_BASENAME}_LIBRARY optimized "${_PYTHON_libname}" )
- endforeach()
- foreach (_PYTHON_libname IN LISTS ${_PYTHON_BASENAME}_LIBRARY_DEBUG )
- list( APPEND ${_PYTHON_BASENAME}_LIBRARY debug "${_PYTHON_libname}" )
- endforeach()
- elseif (${_PYTHON_BASENAME}_LIBRARY_RELEASE)
- set (${_PYTHON_BASENAME}_LIBRARY "${${_PYTHON_BASENAME}_LIBRARY_RELEASE}")
- elseif (${_PYTHON_BASENAME}_LIBRARY_DEBUG)
- set (${_PYTHON_BASENAME}_LIBRARY "${${_PYTHON_BASENAME}_LIBRARY_DEBUG}")
- else()
- set (${_PYTHON_BASENAME}_LIBRARY "${_PYTHON_BASENAME}_LIBRARY-NOTFOUND")
- endif()
-
- set (${_PYTHON_BASENAME}_LIBRARIES "${${_PYTHON_BASENAME}_LIBRARY}")
-endmacro()
-
-
-macro (_PYTHON_FIND_FRAMEWORKS)
- set (${_PYTHON_PREFIX}_FRAMEWORKS)
- if (CMAKE_HOST_APPLE OR APPLE)
- file(TO_CMAKE_PATH "$ENV{CMAKE_FRAMEWORK_PATH}" _pff_CMAKE_FRAMEWORK_PATH)
- set (_pff_frameworks ${CMAKE_FRAMEWORK_PATH}
- ${_pff_CMAKE_FRAMEWORK_PATH}
- ~/Library/Frameworks
- /usr/local/Frameworks
- ${CMAKE_SYSTEM_FRAMEWORK_PATH})
- list (REMOVE_DUPLICATES _pff_frameworks)
- foreach (_pff_framework IN LISTS _pff_frameworks)
- if (EXISTS ${_pff_framework}/Python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}.framework)
- list (APPEND ${_PYTHON_PREFIX}_FRAMEWORKS ${_pff_framework}/Python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}.framework)
- endif()
- if (EXISTS ${_pff_framework}/Python.framework)
- list (APPEND ${_PYTHON_PREFIX}_FRAMEWORKS ${_pff_framework}/Python.framework)
- endif()
- endforeach()
- unset (_pff_frameworks)
- unset (_pff_framework)
- endif()
-endmacro()
-
-function (_PYTHON_GET_FRAMEWORKS _PYTHON_PGF_FRAMEWORK_PATHS _PYTHON_VERSION)
- set (_PYTHON_FRAMEWORK_PATHS)
- foreach (_PYTHON_FRAMEWORK IN LISTS ${_PYTHON_PREFIX}_FRAMEWORKS)
- list (APPEND _PYTHON_FRAMEWORK_PATHS
- "${_PYTHON_FRAMEWORK}/Versions/${_PYTHON_VERSION}")
- endforeach()
- set (${_PYTHON_PGF_FRAMEWORK_PATHS} ${_PYTHON_FRAMEWORK_PATHS} PARENT_SCOPE)
-endfunction()
-
-function (_PYTHON_GET_REGISTRIES _PYTHON_PGR_REGISTRY_PATHS _PYTHON_VERSION)
- string (REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${_PYTHON_VERSION})
- set (${_PYTHON_PGR_REGISTRY_PATHS}
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_PYTHON_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_PYTHON_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_PYTHON_VERSION}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_PYTHON_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_PYTHON_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_PYTHON_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_PYTHON_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_PYTHON_VERSION}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_PYTHON_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_PYTHON_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
- PARENT_SCOPE)
-endfunction()
-
-
-function (_PYTHON_GET_ABIFLAGS _PGABIFLAGS)
- set (abiflags)
- list (GET _${_PYTHON_PREFIX}_FIND_ABI 0 pydebug)
- list (GET _${_PYTHON_PREFIX}_FIND_ABI 1 pymalloc)
- list (GET _${_PYTHON_PREFIX}_FIND_ABI 2 unicode)
-
- if (pymalloc STREQUAL "ANY" AND unicode STREQUAL "ANY")
- set (abiflags "mu" "m" "u" "")
- elseif (pymalloc STREQUAL "ANY" AND unicode STREQUAL "ON")
- set (abiflags "mu" "u")
- elseif (pymalloc STREQUAL "ANY" AND unicode STREQUAL "OFF")
- set (abiflags "m" "")
- elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY")
- set (abiflags "mu" "m")
- elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ON")
- set (abiflags "mu")
- elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "OFF")
- set (abiflags "m")
- elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY")
- set (abiflags "u" "")
- elseif (pymalloc STREQUAL "OFF" AND unicode STREQUAL "ON")
- set (abiflags "u")
- endif()
-
- if (pydebug STREQUAL "ON")
- if (abiflags)
- list (TRANSFORM abiflags PREPEND "d")
- else()
- set (abiflags "d")
- endif()
- elseif (pydebug STREQUAL "ANY")
- if (abiflags)
- set (flags "${abiflags}")
- list (TRANSFORM flags PREPEND "d")
- list (APPEND abiflags "${flags}")
- else()
- set (abiflags "" "d")
- endif()
- endif()
-
- set (${_PGABIFLAGS} "${abiflags}" PARENT_SCOPE)
-endfunction()
-
-function (_PYTHON_GET_PATH_SUFFIXES _PYTHON_PGPS_PATH_SUFFIXES)
- cmake_parse_arguments (PARSE_ARGV 1 _PGPS "LIBRARY;INCLUDE" "VERSION" "")
-
- if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS)
- set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}")
- else()
- set (abi "mu" "m" "u" "")
- endif()
-
- set (path_suffixes)
- if (_PGPS_LIBRARY)
- if (CMAKE_LIBRARY_ARCHITECTURE)
- list (APPEND path_suffixes lib/${CMAKE_LIBRARY_ARCHITECTURE})
- endif()
- list (APPEND path_suffixes lib libs)
-
- if (CMAKE_LIBRARY_ARCHITECTURE)
- set (suffixes "${abi}")
- if (suffixes)
- list (TRANSFORM suffixes PREPEND "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}")
- list (TRANSFORM suffixes APPEND "-${CMAKE_LIBRARY_ARCHITECTURE}")
- else()
- set (suffixes "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}-${CMAKE_LIBRARY_ARCHITECTURE}")
- endif()
- list (APPEND path_suffixes ${suffixes})
- endif()
- set (suffixes "${abi}")
- if (suffixes)
- list (TRANSFORM suffixes PREPEND "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}")
- else()
- set (suffixes "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}")
- endif()
- list (APPEND path_suffixes ${suffixes})
- elseif (_PGPS_INCLUDE)
- set (suffixes "${abi}")
- if (suffixes)
- list (TRANSFORM suffixes PREPEND "include/python${_PGPS_VERSION}")
- else()
- set (suffixes "include/python${_PGPS_VERSION}")
- endif()
- list (APPEND path_suffixes ${suffixes} include)
- endif()
-
- set (${_PYTHON_PGPS_PATH_SUFFIXES} ${path_suffixes} PARENT_SCOPE)
-endfunction()
-
-function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES)
- cmake_parse_arguments (PARSE_ARGV 1 _PGN "POSIX;EXECUTABLE;CONFIG;LIBRARY;WIN32;DEBUG" "VERSION" "")
-
- set (names)
-
- if (_PGN_WIN32)
- string (REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${_PGN_VERSION})
-
- set (name python${_PYTHON_VERSION_NO_DOTS})
- if (_PGN_DEBUG)
- string (APPEND name "_d")
- endif()
-
- list (APPEND names "${name}")
- endif()
-
- if (_PGN_POSIX)
- if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS)
- set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}")
- else()
- if (_PGN_EXECUTABLE OR _PGN_CONFIG)
- set (abi "")
- else()
- set (abi "mu" "m" "u" "")
- endif()
- endif()
-
- if (abi)
- if (_PGN_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE)
- set (abinames "${abi}")
- list (TRANSFORM abinames PREPEND "${CMAKE_LIBRARY_ARCHITECTURE}-python${_PGN_VERSION}")
- list (TRANSFORM abinames APPEND "-config")
- list (APPEND names ${abinames})
- endif()
- set (abinames "${abi}")
- list (TRANSFORM abinames PREPEND "python${_PGN_VERSION}")
- if (_PGN_CONFIG)
- list (TRANSFORM abinames APPEND "-config")
- endif()
- list (APPEND names ${abinames})
- else()
- if (_PGN_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE)
- set (abinames "${CMAKE_LIBRARY_ARCHITECTURE}-python${_PGN_VERSION}")
- endif()
- list (APPEND abinames "python${_PGN_VERSION}")
- if (_PGN_CONFIG)
- list (TRANSFORM abinames APPEND "-config")
- endif()
- list (APPEND names ${abinames})
- endif()
- endif()
-
- set (${_PYTHON_PGN_NAMES} ${names} PARENT_SCOPE)
-endfunction()
-
-function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME)
- unset (${_PYTHON_PGCV_VALUE} PARENT_SCOPE)
-
- if (NOT NAME MATCHES "^(PREFIX|ABIFLAGS|CONFIGDIR|INCLUDES|LIBS|SOABI)$")
- return()
- endif()
-
- if (_${_PYTHON_PREFIX}_CONFIG)
- if (NAME STREQUAL "SOABI")
- set (config_flag "--extension-suffix")
- else()
- set (config_flag "--${NAME}")
- endif()
- string (TOLOWER "${config_flag}" config_flag)
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" ${config_flag}
- RESULT_VARIABLE _result
- OUTPUT_VARIABLE _values
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (_result)
- unset (_values)
- else()
- if (NAME STREQUAL "INCLUDES")
- # do some clean-up
- string (REGEX MATCHALL "(-I|-iwithsysroot)[ ]*[^ ]+" _values "${_values}")
- string (REGEX REPLACE "(-I|-iwithsysroot)[ ]*" "" _values "${_values}")
- list (REMOVE_DUPLICATES _values)
- elseif (NAME STREQUAL "SOABI")
- # clean-up: remove prefix character and suffix
- string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\1" _values "${_values}")
- endif()
- endif()
- endif()
-
- if (_${_PYTHON_PREFIX}_EXECUTABLE AND NOT CMAKE_CROSSCOMPILING)
- if (NAME STREQUAL "PREFIX")
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig; sys.stdout.write(';'.join([sysconfig.PREFIX,sysconfig.EXEC_PREFIX,sysconfig.BASE_EXEC_PREFIX]))"
- RESULT_VARIABLE _result
- OUTPUT_VARIABLE _values
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (_result)
- unset (_values)
- else()
- list (REMOVE_DUPLICATES _values)
- endif()
- elseif (NAME STREQUAL "INCLUDES")
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig; sys.stdout.write(';'.join([sysconfig.get_python_inc(plat_specific=True),sysconfig.get_python_inc(plat_specific=False)]))"
- RESULT_VARIABLE _result
- OUTPUT_VARIABLE _values
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (_result)
- unset (_values)
- endif()
- elseif (NAME STREQUAL "SOABI")
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig;sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('EXT_SUFFIX') or '']))"
- RESULT_VARIABLE _result
- OUTPUT_VARIABLE _soabi
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (_result)
- unset (_values)
- else()
- list (GET _soabi 0 _values)
- if (NOT _values)
- # try to compute SOABI from EXT_SUFFIX
- list (GET _soabi 1 _values)
- if (_values)
- # clean-up: remove prefix character and suffix
- string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\1" _values "${_values}")
- endif()
- endif()
- endif()
- else()
- set (config_flag "${NAME}")
- if (NAME STREQUAL "CONFIGDIR")
- set (config_flag "LIBPL")
- endif()
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.get_config_var('${config_flag}'))"
- RESULT_VARIABLE _result
- OUTPUT_VARIABLE _values
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (_result)
- unset (_values)
- endif()
- endif()
- endif()
-
- if (config_flag STREQUAL "ABIFLAGS")
- set (${_PYTHON_PGCV_VALUE} "${_values}" PARENT_SCOPE)
- return()
- endif()
-
- if (NOT _values OR _values STREQUAL "None")
- return()
- endif()
-
- if (NAME STREQUAL "LIBS")
- # do some clean-up
- string (REGEX MATCHALL "-(l|framework)[ ]*[^ ]+" _values "${_values}")
- # remove elements relative to python library itself
- list (FILTER _values EXCLUDE REGEX "-lpython")
- list (REMOVE_DUPLICATES _values)
- endif()
-
- set (${_PYTHON_PGCV_VALUE} "${_values}" PARENT_SCOPE)
-endfunction()
-
-function (_PYTHON_GET_VERSION)
- cmake_parse_arguments (PARSE_ARGV 0 _PGV "LIBRARY;INCLUDE" "PREFIX" "")
-
- unset (${_PGV_PREFIX}VERSION PARENT_SCOPE)
- unset (${_PGV_PREFIX}VERSION_MAJOR PARENT_SCOPE)
- unset (${_PGV_PREFIX}VERSION_MINOR PARENT_SCOPE)
- unset (${_PGV_PREFIX}VERSION_PATCH PARENT_SCOPE)
- unset (${_PGV_PREFIX}ABI PARENT_SCOPE)
-
- if (_PGV_LIBRARY)
- # retrieve version and abi from library name
- if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE)
- # extract version from library name
- if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "python([23])([0-9]+)")
- set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE)
- set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE)
- set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE)
- set (${_PGV_PREFIX}ABI "" PARENT_SCOPE)
- elseif (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "python([23])\\.([0-9]+)([dmu]*)")
- set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE)
- set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE)
- set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE)
- set (${_PGV_PREFIX}ABI "${CMAKE_MATCH_3}" PARENT_SCOPE)
- endif()
- endif()
- else()
- if (_${_PYTHON_PREFIX}_INCLUDE_DIR)
- # retrieve version from header file
- file (STRINGS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}/patchlevel.h" version
- REGEX "^#define[ \t]+PY_VERSION[ \t]+\"[^\"]+\"")
- string (REGEX REPLACE "^#define[ \t]+PY_VERSION[ \t]+\"([^\"]+)\".*" "\\1"
- version "${version}")
- string (REGEX MATCHALL "[0-9]+" versions "${version}")
- list (GET versions 0 version_major)
- list (GET versions 1 version_minor)
- list (GET versions 2 version_patch)
-
- set (${_PGV_PREFIX}VERSION "${version_major}.${version_minor}" PARENT_SCOPE)
- set (${_PGV_PREFIX}VERSION_MAJOR ${version_major} PARENT_SCOPE)
- set (${_PGV_PREFIX}VERSION_MINOR ${version_minor} PARENT_SCOPE)
- set (${_PGV_PREFIX}VERSION_PATCH ${version_patch} PARENT_SCOPE)
-
- # compute ABI flags
- if (version_major VERSION_GREATER 2)
- file (STRINGS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}/pyconfig.h" config REGEX "(Py_DEBUG|WITH_PYMALLOC|Py_UNICODE_SIZE|MS_WIN32)")
- set (abi)
- if (config MATCHES "#[ ]*define[ ]+MS_WIN32")
- # ABI not used on Windows
- set (abi "")
- else()
- if (config MATCHES "#[ ]*define[ ]+Py_DEBUG[ ]+1")
- string (APPEND abi "d")
- endif()
- if (config MATCHES "#[ ]*define[ ]+WITH_PYMALLOC[ ]+1")
- string (APPEND abi "m")
- endif()
- if (config MATCHES "#[ ]*define[ ]+Py_UNICODE_SIZE[ ]+4")
- string (APPEND abi "u")
- endif()
- set (${_PGV_PREFIX}ABI "${abi}" PARENT_SCOPE)
- endif()
- else()
- # ABI not supported
- set (${_PGV_PREFIX}ABI "" PARENT_SCOPE)
- endif()
- endif()
- endif()
-endfunction()
-
-
-function (_PYTHON_VALIDATE_INTERPRETER)
- if (NOT _${_PYTHON_PREFIX}_EXECUTABLE)
- return()
- endif()
-
- cmake_parse_arguments (PARSE_ARGV 0 _PVI "EXACT;CHECK_EXISTS" "" "")
- if (_PVI_UNPARSED_ARGUMENTS)
- set (expected_version ${_PVI_UNPARSED_ARGUMENTS})
- else()
- unset (expected_version)
- endif()
-
- if (_PVI_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_EXECUTABLE}")
- # interpreter does not exist anymore
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot find the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
- return()
- endif()
-
- # validate ABI compatibility
- if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI)
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
- "import sys; sys.stdout.write(sys.abiflags)"
- RESULT_VARIABLE result
- OUTPUT_VARIABLE abi
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (result)
- # assume ABI is not supported
- set (abi "")
- endif()
- if (NOT abi IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
- # incompatible ABI
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong ABI for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
- return()
- endif()
- endif()
-
- get_filename_component (python_name "${_${_PYTHON_PREFIX}_EXECUTABLE}" NAME)
-
- if (expected_version AND NOT python_name STREQUAL "pythonexpectedversion{abi}${CMAKE_EXECUTABLE_SUFFIX}")
- # executable found must have a specific version
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
- "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))"
- RESULT_VARIABLE result
- OUTPUT_VARIABLE version
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (result)
- # interpreter is not usable
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
- else()
- if (_PVI_EXACT AND NOT version VERSION_EQUAL expected_version)
- # interpreter has wrong version
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
- else()
- # check that version is OK
- string(REGEX REPLACE "^([0-9]+)\\..*$" "\\1" major_version "${version}")
- string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" expected_major_version "${expected_version}")
- if (NOT major_version VERSION_EQUAL expected_major_version
- OR NOT version VERSION_GREATER_EQUAL expected_version)
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
- endif()
- endif()
- endif()
- if (NOT _${_PYTHON_PREFIX}_EXECUTABLE)
- return()
- endif()
- else()
- if (NOT python_name STREQUAL "python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}${CMAKE_EXECUTABLE_SUFFIX}")
- # executable found do not have version in name
- # ensure major version is OK
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
- "import sys; sys.stdout.write(str(sys.version_info[0]))"
- RESULT_VARIABLE result
- OUTPUT_VARIABLE version
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
- # interpreter not usable or has wrong major version
- if (result)
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
- else()
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong major version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
- endif()
- set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
- return()
- endif()
- endif()
- endif()
-
- if (CMAKE_SIZEOF_VOID_P AND "Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
- AND NOT CMAKE_CROSSCOMPILING)
- # In this case, interpreter must have same architecture as environment
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
- "import sys, struct; sys.stdout.write(str(struct.calcsize(\"P\")))"
- RESULT_VARIABLE result
- OUTPUT_VARIABLE size
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (result OR NOT size EQUAL CMAKE_SIZEOF_VOID_P)
- # interpreter not usable or has wrong architecture
- if (result)
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
- else()
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
- endif()
- set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
- return()
- endif()
- endif()
-endfunction()
-
-
-function (_PYTHON_VALIDATE_COMPILER expected_version)
- if (NOT _${_PYTHON_PREFIX}_COMPILER)
- return()
- endif()
-
- cmake_parse_arguments (_PVC "EXACT;CHECK_EXISTS" "" "" ${ARGN})
- if (_PVC_UNPARSED_ARGUMENTS)
- set (major_version FALSE)
- set (expected_version ${_PVC_UNPARSED_ARGUMENTS})
- else()
- set (major_version TRUE)
- set (expected_version ${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR})
- set (_PVC_EXACT TRUE)
- endif()
-
- if (_PVC_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_COMPILER}")
- # Compiler does not exist anymore
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot find the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
- return()
- endif()
-
- # retrieve python environment version from compiler
- set (working_dir "CMAKECURRENTBINARYDIR{CMAKE_FILES_DIRECTORY}/PythonCompilerVersion.dir")
- if (major_version)
- # check only major version
- file (WRITE "${working_dir}/version.py" "import sys; sys.stdout.write(str(sys.version_info[0]))")
- else()
- file (WRITE "${working_dir}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))\n")
- endif()
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_COMPILER}" /target:exe /embed "${working_dir}/version.py"
- WORKING_DIRECTORY "${working_dir}"
- OUTPUT_QUIET
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- execute_process (COMMAND "${working_dir}/version"
- WORKING_DIRECTORY "${working_dir}"
- RESULT_VARIABLE result
- OUTPUT_VARIABLE version
- ERROR_QUIET)
- file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}")
-
- if (result OR (_PVC_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version))
- # Compiler not usable or has wrong version
- if (result)
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot use the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
- else()
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
- endif()
- set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
- endif()
-endfunction()
-
-
-function (_PYTHON_VALIDATE_LIBRARY)
- if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
- return()
- endif()
-
- cmake_parse_arguments (PARSE_ARGV 0 _PVL "EXACT;CHECK_EXISTS" "" "")
- if (_PVL_UNPARSED_ARGUMENTS)
- set (expected_version ${_PVL_UNPARSED_ARGUMENTS})
- else()
- unset (expected_version)
- endif()
-
- if (_PVL_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
- # library does not exist anymore
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
- if (WIN32)
- set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND")
- endif()
- set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
- return()
- endif()
-
- # retrieve version and abi from library name
- _python_get_version (LIBRARY PREFIX lib_)
-
- if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT lib_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
- # incompatible ABI
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
- else()
- if (expected_version)
- if ((_PVL_EXACT AND NOT lib_VERSION VERSION_EQUAL expected_version) OR (lib_VERSION VERSION_LESS expected_version))
- # library has wrong version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
- endif()
- else()
- if (NOT lib_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
- # library has wrong major version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
- endif()
- endif()
- endif()
-
- if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
- if (WIN32)
- set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND")
- endif()
- unset (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE CACHE)
- unset (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG CACHE)
- set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
- endif()
-endfunction()
-
-
-function (_PYTHON_VALIDATE_INCLUDE_DIR)
- if (NOT _${_PYTHON_PREFIX}_INCLUDE_DIR)
- return()
- endif()
-
- cmake_parse_arguments (PARSE_ARGV 0 _PVID "EXACT;CHECK_EXISTS" "" "")
- if (_PVID_UNPARSED_ARGUMENTS)
- set (expected_version ${_PVID_UNPARSED_ARGUMENTS})
- else()
- unset (expected_version)
- endif()
-
- if (_PVID_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}")
- # include file does not exist anymore
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
- return()
- endif()
-
- # retrieve version from header file
- _python_get_version (INCLUDE PREFIX inc_)
-
- if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT inc_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
- # incompatible ABI
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
- else()
- if (expected_version)
- if ((_PVID_EXACT AND NOT inc_VERSION VERSION_EQUAL expected_version) OR (inc_VERSION VERSION_LESS expected_version))
- # include dir has wrong version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
- endif()
- else()
- if (NOT inc_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
- # include dir has wrong major version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
- endif()
- endif()
- endif()
-endfunction()
-
-
-function (_PYTHON_FIND_RUNTIME_LIBRARY _PYTHON_LIB)
- string (REPLACE "_RUNTIME" "" _PYTHON_LIB "${_PYTHON_LIB}")
- # look at runtime part on systems supporting it
- if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR
- (CMAKE_SYSTEM_NAME MATCHES "MSYS|CYGWIN"
- AND ${_PYTHON_LIB} MATCHES "${CMAKE_IMPORT_LIBRARY_SUFFIX}$"))
- set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX})
- # MSYS has a special syntax for runtime libraries
- if (CMAKE_SYSTEM_NAME MATCHES "MSYS")
- list (APPEND CMAKE_FIND_LIBRARY_PREFIXES "msys-")
- endif()
- find_library (${ARGV})
- endif()
-endfunction()
-
-
-function (_PYTHON_SET_LIBRARY_DIRS _PYTHON_SLD_RESULT)
- unset (_PYTHON_DIRS)
- set (_PYTHON_LIBS ${ARGN})
- foreach (_PYTHON_LIB IN LISTS _PYTHON_LIBS)
- if (${_PYTHON_LIB})
- get_filename_component (_PYTHON_DIR "${${_PYTHON_LIB}}" DIRECTORY)
- list (APPEND _PYTHON_DIRS "${_PYTHON_DIR}")
- endif()
- endforeach()
- if (_PYTHON_DIRS)
- list (REMOVE_DUPLICATES _PYTHON_DIRS)
- endif()
- set (${_PYTHON_SLD_RESULT} ${_PYTHON_DIRS} PARENT_SCOPE)
-endfunction()
-
-
-# If major version is specified, it must be the same as internal major version
-if (DEFINED ${_PYTHON_PREFIX}_FIND_VERSION_MAJOR
- AND NOT ${_PYTHON_PREFIX}_FIND_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
- _python_display_failure ("Could NOT find ${_PYTHON_PREFIX}: Wrong major version specified is \"${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}\", but expected major version is \"${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}\"")
-endif()
-
-
-# handle components
-if (NOT ${_PYTHON_PREFIX}_FIND_COMPONENTS)
- set (${_PYTHON_PREFIX}_FIND_COMPONENTS Interpreter)
- set (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter TRUE)
-endif()
-if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
- list (APPEND ${_PYTHON_PREFIX}_FIND_COMPONENTS "Interpreter" "Development")
- list (REMOVE_DUPLICATES ${_PYTHON_PREFIX}_FIND_COMPONENTS)
-endif()
-foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Interpreter Compiler Development NumPy)
- set (${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_FOUND FALSE)
-endforeach()
-unset (_${_PYTHON_PREFIX}_FIND_VERSIONS)
-
-# Set versions to search
-## default: search any version
-set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${_${_PYTHON_PREFIX}_VERSIONS})
-
-if (${_PYTHON_PREFIX}_FIND_VERSION_COUNT GREATER 1)
- if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT)
- set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}.${${_PYTHON_PREFIX}_FIND_VERSION_MINOR})
- else()
- unset (_${_PYTHON_PREFIX}_FIND_VERSIONS)
- # add all compatible versions
- foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_VERSIONS)
- if (_${_PYTHON_PREFIX}_VERSION VERSION_GREATER_EQUAL ${_PYTHON_PREFIX}_FIND_VERSION)
- list (APPEND _${_PYTHON_PREFIX}_FIND_VERSIONS ${_${_PYTHON_PREFIX}_VERSION})
- endif()
- endforeach()
- endif()
-endif()
-
-# Set ABIs to search
-## default: search any ABI
-if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_LESS 3)
- # ABI not supported
- unset (_${_PYTHON_PREFIX}_FIND_ABI)
- set (_${_PYTHON_PREFIX}_ABIFLAGS "")
-else()
- unset (_${_PYTHON_PREFIX}_FIND_ABI)
- unset (_${_PYTHON_PREFIX}_ABIFLAGS)
- if (DEFINED ${_PYTHON_PREFIX}_FIND_ABI)
- # normalization
- string (TOUPPER "${${_PYTHON_PREFIX}_FIND_ABI}" _${_PYTHON_PREFIX}_FIND_ABI)
- list (TRANSFORM _${_PYTHON_PREFIX}_FIND_ABI REPLACE "^(TRUE|Y(ES)?|1)$" "ON")
- list (TRANSFORM _${_PYTHON_PREFIX}_FIND_ABI REPLACE "^(FALSE|N(O)?|0)$" "OFF")
- if (NOT _${_PYTHON_PREFIX}_FIND_ABI MATCHES "^(ON|OFF|ANY);(ON|OFF|ANY);(ON|OFF|ANY)$")
- message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_ABI}: invalid value for '${_PYTHON_PREFIX}_FIND_ABI'. Ignore it")
- unset (_${_PYTHON_PREFIX}_FIND_ABI)
- endif()
- _python_get_abiflags (_${_PYTHON_PREFIX}_ABIFLAGS)
- endif()
-endif()
-unset (${_PYTHON_PREFIX}_SOABI)
-
-# Define lookup strategy
-if (_${_PYTHON_PREFIX}_LOOKUP_POLICY STREQUAL "NEW")
- set (_${_PYTHON_PREFIX}_FIND_STRATEGY "LOCATION")
-else()
- set (_${_PYTHON_PREFIX}_FIND_STRATEGY "VERSION")
-endif()
-if (DEFINED ${_PYTHON_PREFIX}_FIND_STRATEGY)
- if (NOT ${_PYTHON_PREFIX}_FIND_STRATEGY MATCHES "^(VERSION|LOCATION)$")
- message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_STRATEGY}: invalid value for '${_PYTHON_PREFIX}_FIND_STRATEGY'. 'VERSION' or 'LOCATION' expected.")
- set (_${_PYTHON_PREFIX}_FIND_STRATEGY "VERSION")
- else()
- set (_${_PYTHON_PREFIX}_FIND_STRATEGY "${${_PYTHON_PREFIX}_FIND_STRATEGY}")
- endif()
-endif()
-
-# Python and Anaconda distributions: define which architectures can be used
-if (CMAKE_SIZEOF_VOID_P)
- # In this case, search only for 64bit or 32bit
- math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
- set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH})
-else()
- # architecture unknown, search for both 64bit and 32bit
- set (_${_PYTHON_PREFIX}_ARCH 64)
- set (_${_PYTHON_PREFIX}_ARCH2 32)
-endif()
-
-# IronPython support
-if (CMAKE_SIZEOF_VOID_P)
- # In this case, search only for 64bit or 32bit
- math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
- set (_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES ipy${_${_PYTHON_PREFIX}_ARCH} ipy)
-else()
- # architecture unknown, search for natural interpreter
- set (_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES ipy)
-endif()
-set (_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES net45 net40)
-
-# Apple frameworks handling
-_python_find_frameworks ()
-
-set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK "FIRST")
-
-if (DEFINED ${_PYTHON_PREFIX}_FIND_FRAMEWORK)
- if (NOT ${_PYTHON_PREFIX}_FIND_FRAMEWORK MATCHES "^(FIRST|LAST|NEVER)$")
- message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_FRAMEWORK}: invalid value for '${_PYTHON_PREFIX}_FIND_FRAMEWORK'. 'FIRST', 'LAST' or 'NEVER' expected. 'FIRST' will be used instead.")
- else()
- set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK ${${_PYTHON_PREFIX}_FIND_FRAMEWORK})
- endif()
-elseif (DEFINED CMAKE_FIND_FRAMEWORK)
- if (CMAKE_FIND_FRAMEWORK STREQUAL "ONLY")
- message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: CMAKE_FIND_FRAMEWORK: 'ONLY' value is not supported. 'FIRST' will be used instead.")
- elseif (NOT CMAKE_FIND_FRAMEWORK MATCHES "^(FIRST|LAST|NEVER)$")
- message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${CMAKE_FIND_FRAMEWORK}: invalid value for 'CMAKE_FIND_FRAMEWORK'. 'FIRST', 'LAST' or 'NEVER' expected. 'FIRST' will be used instead.")
- else()
- set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK})
- endif()
-endif()
-
-# Save CMAKE_FIND_APPBUNDLE
-if (DEFINED CMAKE_FIND_APPBUNDLE)
- set (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE ${CMAKE_FIND_APPBUNDLE})
-else()
- unset (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE)
-endif()
-# To avoid app bundle lookup
-set (CMAKE_FIND_APPBUNDLE "NEVER")
-
-# Save CMAKE_FIND_FRAMEWORK
-if (DEFINED CMAKE_FIND_FRAMEWORK)
- set (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK})
-else()
- unset (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK)
-endif()
-# To avoid framework lookup
-set (CMAKE_FIND_FRAMEWORK "NEVER")
-
-# Windows Registry handling
-if (DEFINED ${_PYTHON_PREFIX}_FIND_REGISTRY)
- if (NOT ${_PYTHON_PREFIX}_FIND_REGISTRY MATCHES "^(FIRST|LAST|NEVER)$")
- message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_REGISTRY}: invalid value for '${_PYTHON_PREFIX}_FIND_REGISTRY'. 'FIRST', 'LAST' or 'NEVER' expected. 'FIRST' will be used instead.")
- set (_${_PYTHON_PREFIX}_FIND_REGISTRY "FIRST")
- else()
- set (_${_PYTHON_PREFIX}_FIND_REGISTRY ${${_PYTHON_PREFIX}_FIND_REGISTRY})
- endif()
-else()
- set (_${_PYTHON_PREFIX}_FIND_REGISTRY "FIRST")
-endif()
-
-# virtual environments recognition
-if (DEFINED ENV{VIRTUAL_ENV} OR DEFINED ENV{CONDA_PREFIX})
- if (DEFINED ${_PYTHON_PREFIX}_FIND_VIRTUALENV)
- if (NOT ${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY|STANDARD)$")
- message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_VIRTUALENV}: invalid value for '${_PYTHON_PREFIX}_FIND_VIRTUALENV'. 'FIRST', 'ONLY' or 'STANDARD' expected. 'FIRST' will be used instead.")
- set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV "FIRST")
- else()
- set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV ${${_PYTHON_PREFIX}_FIND_VIRTUALENV})
- endif()
- else()
- set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV FIRST)
- endif()
-else()
- set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV STANDARD)
-endif()
-
-
-# Compute search signature
-# This signature will be used to check validity of cached variables on new search
-set (_${_PYTHON_PREFIX}_SIGNATURE "${${_PYTHON_PREFIX}_ROOT_DIR}:${${_PYTHON_PREFIX}_FIND_STRATEGY}:${${_PYTHON_PREFIX}_FIND_VIRTUALENV}")
-if (NOT WIN32)
- string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${${_PYTHON_PREFIX}_USE_STATIC_LIBS}:")
-endif()
-if (CMAKE_HOST_APPLE)
- string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${${_PYTHON_PREFIX}_FIND_FRAMEWORK}")
-endif()
-if (CMAKE_HOST_WIN32)
- string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${${_PYTHON_PREFIX}_FIND_REGISTRY}")
-endif()
-
-
-unset (_${_PYTHON_PREFIX}_REQUIRED_VARS)
-unset (_${_PYTHON_PREFIX}_CACHED_VARS)
-unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE)
-unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE)
-unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE)
-unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE)
-
-
-# first step, search for the interpreter
-if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
- list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_EXECUTABLE)
- if (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter)
- list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_EXECUTABLE)
- endif()
-
- if (DEFINED ${_PYTHON_PREFIX}_EXECUTABLE
- AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_EXECUTABLE}")
- if (NOT ${_PYTHON_PREFIX}_EXECUTABLE STREQUAL _${_PYTHON_PREFIX}_EXECUTABLE)
- # invalidate cache properties
- unset (_${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES CACHE)
- endif()
- set (_${_PYTHON_PREFIX}_EXECUTABLE "${${_PYTHON_PREFIX}_EXECUTABLE}" CACHE INTERNAL "")
- elseif (DEFINED _${_PYTHON_PREFIX}_EXECUTABLE)
- # compute interpreter signature and check validity of definition
- string (MD5 __${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_EXECUTABLE}")
- if (__${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE)
- # check version validity
- if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT CHECK_EXISTS)
- else()
- _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION} CHECK_EXISTS)
- endif()
- else()
- unset (_${_PYTHON_PREFIX}_EXECUTABLE CACHE)
- endif()
- if (NOT _${_PYTHON_PREFIX}_EXECUTABLE)
- unset (_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE CACHE)
- unset (_${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES CACHE)
- endif()
- endif()
-
- if (NOT _${_PYTHON_PREFIX}_EXECUTABLE)
- set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
-
- if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION")
- unset (_${_PYTHON_PREFIX}_NAMES)
- unset (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS)
- unset (_${_PYTHON_PREFIX}_REGISTRY_PATHS)
-
- foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
- # build all executable names
- _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX EXECUTABLE)
- list (APPEND _${_PYTHON_PREFIX}_NAMES ${_${_PYTHON_PREFIX}_VERSION_NAMES})
-
- # Framework Paths
- _python_get_frameworks (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_VERSION})
- list (APPEND _${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS})
-
- # Registry Paths
- _python_get_registries (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_VERSION})
- list (APPEND _${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS}
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath])
- endforeach()
- list (APPEND _${_PYTHON_PREFIX}_NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} python)
-
- while (TRUE)
- # Virtual environments handling
- if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX
- PATH_SUFFIXES bin Scripts
- NO_CMAKE_PATH
- NO_CMAKE_ENVIRONMENT_PATH
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
-
- _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION})
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- break()
- endif()
- if (NOT _${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY")
- break()
- endif()
- endif()
-
- # Apple frameworks handling
- if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- PATH_SUFFIXES bin
- NO_CMAKE_PATH
- NO_CMAKE_ENVIRONMENT_PATH
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION})
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- break()
- endif()
- endif()
- # Windows registry
- if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST")
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
- PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION})
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- break()
- endif()
- endif()
-
- # try using HINTS
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION})
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- break()
- endif()
- # try using standard paths
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
- NAMES_PER_DIR
- PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES})
- _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION})
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- break()
- endif()
-
- # Apple frameworks handling
- if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST")
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- NAMES_PER_DIR
- PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- PATH_SUFFIXES bin
- NO_DEFAULT_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION})
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- break()
- endif()
- endif()
- # Windows registry
- if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST")
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
- NAMES_PER_DIR
- PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
- PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION})
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- break()
- endif()
- endif()
-
- break()
- endwhile()
- else()
- # look-up for various versions and locations
- foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
- _python_get_names (_${_PYTHON_PREFIX}_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX EXECUTABLE)
- list (APPEND _${_PYTHON_PREFIX}_NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
- python)
-
- _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION})
- _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION})
-
- # Virtual environments handling
- if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX
- PATH_SUFFIXES bin Scripts
- NO_CMAKE_PATH
- NO_CMAKE_ENVIRONMENT_PATH
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT)
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- break()
- endif()
- if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY")
- continue()
- endif()
- endif()
-
- # Apple frameworks handling
- if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- PATH_SUFFIXES bin
- NO_CMAKE_PATH
- NO_CMAKE_ENVIRONMENT_PATH
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- # Windows registry
- if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST")
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT)
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- break()
- endif()
-
- # try using HINTS
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT)
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- break()
- endif()
- # try using standard paths.
- # NAMES_PER_DIR is not defined on purpose to have a chance to find
- # expected version.
- # For example, typical systems have 'python' for version 2.* and 'python3'
- # for version 3.*. So looking for names per dir will find, potentially,
- # systematically 'python' (i.e. version 2) even if version 3 is searched.
- if (CMAKE_HOST_WIN32)
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- python
- ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES})
- else()
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES})
- endif()
- _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT)
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- break()
- endif()
-
- # Apple frameworks handling
- if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST")
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- NAMES_PER_DIR
- PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- PATH_SUFFIXES bin
- NO_DEFAULT_PATH)
- endif()
-
- # Windows registry
- if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST")
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES}
- ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
- NAMES_PER_DIR
- PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- endif()
-
- _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT)
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- break()
- endif()
- endforeach()
-
- if (NOT _${_PYTHON_PREFIX}_EXECUTABLE AND
- NOT _${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY")
- # No specific version found. Retry with generic names and standard paths.
- # NAMES_PER_DIR is not defined on purpose to have a chance to find
- # expected version.
- # For example, typical systems have 'python' for version 2.* and 'python3'
- # for version 3.*. So looking for names per dir will find, potentially,
- # systematically 'python' (i.e. version 2) even if version 3 is searched.
- find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
- python
- ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES})
- _python_validate_interpreter ()
- endif()
- endif()
- endif()
-
- set (${_PYTHON_PREFIX}_EXECUTABLE "${_${_PYTHON_PREFIX}_EXECUTABLE}")
-
- # retrieve exact version of executable found
- if (_${_PYTHON_PREFIX}_EXECUTABLE)
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
- "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]]))"
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE ${_PYTHON_PREFIX}_VERSION
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (NOT _${_PYTHON_PREFIX}_RESULT)
- set (_${_PYTHON_PREFIX}_EXECUTABLE_USABLE TRUE)
- else()
- # Interpreter is not usable
- set (_${_PYTHON_PREFIX}_EXECUTABLE_USABLE FALSE)
- unset (${_PYTHON_PREFIX}_VERSION)
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot run the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
- endif()
- endif()
-
- if (_${_PYTHON_PREFIX}_EXECUTABLE AND _${_PYTHON_PREFIX}_EXECUTABLE_USABLE)
- if (_${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES)
- set (${_PYTHON_PREFIX}_Interpreter_FOUND TRUE)
-
- list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 0 ${_PYTHON_PREFIX}_INTERPRETER_ID)
-
- list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 1 ${_PYTHON_PREFIX}_VERSION_MAJOR)
- list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 2 ${_PYTHON_PREFIX}_VERSION_MINOR)
- list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 3 ${_PYTHON_PREFIX}_VERSION_PATH)
-
- list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 4 _${_PYTHON_PREFIX}_ARCH)
- set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH})
-
- list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 5 _${_PYTHON_PREFIX}_ABIFLAGS)
- list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 6 ${_PYTHON_PREFIX}_SOABI)
-
- list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 7 ${_PYTHON_PREFIX}_STDLIB)
- list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 8 ${_PYTHON_PREFIX}_STDARCH)
- list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 9 ${_PYTHON_PREFIX}_SITELIB)
- list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 10 ${_PYTHON_PREFIX}_SITEARCH)
- else()
- string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${${_PYTHON_PREFIX}_VERSION}")
- list (GET _${_PYTHON_PREFIX}_VERSIONS 0 ${_PYTHON_PREFIX}_VERSION_MAJOR)
- list (GET _${_PYTHON_PREFIX}_VERSIONS 1 ${_PYTHON_PREFIX}_VERSION_MINOR)
- list (GET _${_PYTHON_PREFIX}_VERSIONS 2 ${_PYTHON_PREFIX}_VERSION_PATCH)
-
- if (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
- set (${_PYTHON_PREFIX}_Interpreter_FOUND TRUE)
-
- # Use interpreter version and ABI for future searches to ensure consistency
- set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR})
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; sys.stdout.write(sys.abiflags)"
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE _${_PYTHON_PREFIX}_ABIFLAGS
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (_${_PYTHON_PREFIX}_RESULT)
- # assunme ABI is not supported
- set (_${_PYTHON_PREFIX}_ABIFLAGS "")
- endif()
- endif()
-
- if (${_PYTHON_PREFIX}_Interpreter_FOUND)
- # compute and save interpreter signature
- string (MD5 __${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_EXECUTABLE}")
- set (_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${__${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}" CACHE INTERNAL "")
-
- if (NOT CMAKE_SIZEOF_VOID_P)
- # determine interpreter architecture
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; print(sys.maxsize > 2**32)"
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE ${_PYTHON_PREFIX}_IS64BIT
- ERROR_VARIABLE ${_PYTHON_PREFIX}_IS64BIT)
- if (NOT _${_PYTHON_PREFIX}_RESULT)
- if (${_PYTHON_PREFIX}_IS64BIT)
- set (_${_PYTHON_PREFIX}_ARCH 64)
- set (_${_PYTHON_PREFIX}_ARCH2 64)
- else()
- set (_${_PYTHON_PREFIX}_ARCH 32)
- set (_${_PYTHON_PREFIX}_ARCH2 32)
- endif()
- endif()
- endif()
-
- # retrieve interpreter identity
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -V
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE ${_PYTHON_PREFIX}_INTERPRETER_ID
- ERROR_VARIABLE ${_PYTHON_PREFIX}_INTERPRETER_ID)
- if (NOT _${_PYTHON_PREFIX}_RESULT)
- if (${_PYTHON_PREFIX}_INTERPRETER_ID MATCHES "Anaconda")
- set (${_PYTHON_PREFIX}_INTERPRETER_ID "Anaconda")
- elseif (${_PYTHON_PREFIX}_INTERPRETER_ID MATCHES "Enthought")
- set (${_PYTHON_PREFIX}_INTERPRETER_ID "Canopy")
- else()
- string (REGEX REPLACE "^([^ ]+).*" "\\1" ${_PYTHON_PREFIX}_INTERPRETER_ID "${${_PYTHON_PREFIX}_INTERPRETER_ID}")
- if (${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "Python")
- # try to get a more precise ID
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; print(sys.copyright)"
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE ${_PYTHON_PREFIX}_COPYRIGHT
- ERROR_QUIET)
- if (${_PYTHON_PREFIX}_COPYRIGHT MATCHES "ActiveState")
- set (${_PYTHON_PREFIX}_INTERPRETER_ID "ActivePython")
- endif()
- endif()
- endif()
- else()
- set (${_PYTHON_PREFIX}_INTERPRETER_ID Python)
- endif()
-
- # retrieve various package installation directories
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig;sys.stdout.write(';'.join([sysconfig.get_python_lib(plat_specific=False,standard_lib=True),sysconfig.get_python_lib(plat_specific=True,standard_lib=True),sysconfig.get_python_lib(plat_specific=False,standard_lib=False),sysconfig.get_python_lib(plat_specific=True,standard_lib=False)]))"
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE _${_PYTHON_PREFIX}_LIBPATHS
- ERROR_QUIET)
- if (NOT _${_PYTHON_PREFIX}_RESULT)
- list (GET _${_PYTHON_PREFIX}_LIBPATHS 0 ${_PYTHON_PREFIX}_STDLIB)
- list (GET _${_PYTHON_PREFIX}_LIBPATHS 1 ${_PYTHON_PREFIX}_STDARCH)
- list (GET _${_PYTHON_PREFIX}_LIBPATHS 2 ${_PYTHON_PREFIX}_SITELIB)
- list (GET _${_PYTHON_PREFIX}_LIBPATHS 3 ${_PYTHON_PREFIX}_SITEARCH)
- else()
- unset (${_PYTHON_PREFIX}_STDLIB)
- unset (${_PYTHON_PREFIX}_STDARCH)
- unset (${_PYTHON_PREFIX}_SITELIB)
- unset (${_PYTHON_PREFIX}_SITEARCH)
- endif()
-
- if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_GREATER_EQUAL 3)
- _python_get_config_var (${_PYTHON_PREFIX}_SOABI SOABI)
- endif()
-
- # store properties in the cache to speed-up future searches
- set (_${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES
- "${${_PYTHON_PREFIX}_INTERPRETER_ID};${${_PYTHON_PREFIX}_VERSION_MAJOR};${${_PYTHON_PREFIX}_VERSION_MINOR};${${_PYTHON_PREFIX}_VERSION_PATCH};${_${_PYTHON_PREFIX}_ARCH};${_${_PYTHON_PREFIX}_ABIFLAGS};${${_PYTHON_PREFIX}_SOABI};${${_PYTHON_PREFIX}_STDLIB};${${_PYTHON_PREFIX}_STDARCH};${${_PYTHON_PREFIX}_SITELIB};${${_PYTHON_PREFIX}_SITEARCH}" CACHE INTERNAL "${_PYTHON_PREFIX} Properties")
- else()
- unset (_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE CACHE)
- unset (${_PYTHON_PREFIX}_INTERPRETER_ID)
- endif()
- endif()
- endif()
-
- _python_mark_as_internal (_${_PYTHON_PREFIX}_EXECUTABLE
- _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES
- _${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE)
-endif()
-
-
-# second step, search for compiler (IronPython)
-if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
- list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_COMPILER)
- if (${_PYTHON_PREFIX}_FIND_REQUIRED_Compiler)
- list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_COMPILER)
- endif()
-
- if (DEFINED ${_PYTHON_PREFIX}_COMPILER
- AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_COMPILER}")
- set (_${_PYTHON_PREFIX}_COMPILER "${${_PYTHON_PREFIX}_COMPILER}" CACHE INTERNAL "")
- elseif (DEFINED _${_PYTHON_PREFIX}_COMPILER)
- # compute compiler signature and check validity of definition
- string (MD5 __${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_COMPILER}")
- if (__${_PYTHON_PREFIX}_COMPILER_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_COMPILER_SIGNATURE)
- # check version validity
- if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT)
- _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT CHECK_EXISTS)
- else()
- _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION} CHECK_EXISTS)
- endif()
- else()
- unset (_${_PYTHON_PREFIX}_COMPILER CACHE)
- unset (_${_PYTHON_PREFIX}_COMPILER_SIGNATURE CACHE)
- endif()
- endif()
-
- if (NOT _${_PYTHON_PREFIX}_COMPILER)
- # IronPython specific artifacts
- # If IronPython interpreter is found, use its path
- unset (_${_PYTHON_PREFIX}_IRON_ROOT)
- if (${_PYTHON_PREFIX}_Interpreter_FOUND AND ${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "IronPython")
- get_filename_component (_${_PYTHON_PREFIX}_IRON_ROOT "${${_PYTHON_PREFIX}_EXECUTABLE}" DIRECTORY)
- endif()
-
- if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION")
- set (_${_PYTHON_PREFIX}_REGISTRY_PATHS)
-
- foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
- # Registry Paths
- list (APPEND _${_PYTHON_PREFIX}_REGISTRY_PATHS
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath])
- endforeach()
-
- while (TRUE)
- if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST")
- find_program (_${_PYTHON_PREFIX}_COMPILER
- NAMES ipyc
- HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION})
- if (_${_PYTHON_PREFIX}_COMPILER)
- break()
- endif()
- endif()
-
- find_program (_${_PYTHON_PREFIX}_COMPILER
- NAMES ipyc
- HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION})
- if (_${_PYTHON_PREFIX}_COMPILER)
- break()
- endif()
-
- if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST")
- find_program (_${_PYTHON_PREFIX}_COMPILER
- NAMES ipyc
- PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- endif()
-
- break()
- endwhile()
- else()
- # try using root dir and registry
- foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
- if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST")
- find_program (_${_PYTHON_PREFIX}_COMPILER
- NAMES ipyc
- HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
- PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VERSION} EXACT)
- if (_${_PYTHON_PREFIX}_COMPILER)
- break()
- endif()
- endif()
-
- find_program (_${_PYTHON_PREFIX}_COMPILER
- NAMES ipyc
- HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VERSION} EXACT)
- if (_${_PYTHON_PREFIX}_COMPILER)
- break()
- endif()
-
- if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST")
- find_program (_${_PYTHON_PREFIX}_COMPILER
- NAMES ipyc
- PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VERSION} EXACT)
- if (_${_PYTHON_PREFIX}_COMPILER)
- break()
- endif()
- endif()
- endforeach()
-
- # no specific version found, re-try in standard paths
- find_program (_${_PYTHON_PREFIX}_COMPILER
- NAMES ipyc
- HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES})
- endif()
- endif()
-
- set (${_PYTHON_PREFIX}_COMPILER "${_${_PYTHON_PREFIX}_COMPILER}")
-
- if (_${_PYTHON_PREFIX}_COMPILER)
- # retrieve python environment version from compiler
- set (_${_PYTHON_PREFIX}_VERSION_DIR "CMAKECURRENTBINARYDIR{CMAKE_FILES_DIRECTORY}/PythonCompilerVersion.dir")
- file (WRITE "${_${_PYTHON_PREFIX}_VERSION_DIR}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]]))\n")
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_COMPILER}" /target:exe /embed "${_${_PYTHON_PREFIX}_VERSION_DIR}/version.py"
- WORKING_DIRECTORY "${_${_PYTHON_PREFIX}_VERSION_DIR}"
- OUTPUT_QUIET
- ERROR_QUIET)
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_VERSION_DIR}/version"
- WORKING_DIRECTORY "${_${_PYTHON_PREFIX}_VERSION_DIR}"
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE _${_PYTHON_PREFIX}_VERSION
- ERROR_QUIET)
- if (NOT _${_PYTHON_PREFIX}_RESULT)
- set (_${_PYTHON_PREFIX}_COMPILER_USABLE TRUE)
- string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${_${_PYTHON_PREFIX}_VERSION}")
- list (GET _${_PYTHON_PREFIX}_VERSIONS 0 _${_PYTHON_PREFIX}_VERSION_MAJOR)
- list (GET _${_PYTHON_PREFIX}_VERSIONS 1 _${_PYTHON_PREFIX}_VERSION_MINOR)
- list (GET _${_PYTHON_PREFIX}_VERSIONS 2 _${_PYTHON_PREFIX}_VERSION_PATCH)
-
- if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND)
- # set public version information
- set (${_PYTHON_PREFIX}_VERSION ${_${_PYTHON_PREFIX}_VERSION})
- set (${_PYTHON_PREFIX}_VERSION_MAJOR ${_${_PYTHON_PREFIX}_VERSION_MAJOR})
- set (${_PYTHON_PREFIX}_VERSION_MINOR ${_${_PYTHON_PREFIX}_VERSION_MINOR})
- set (${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_VERSION_PATCH})
- endif()
- else()
- # compiler not usable
- set (_${_PYTHON_PREFIX}_COMPILER_USABLE FALSE)
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot run the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
- endif()
- file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}")
- endif()
-
- if (_${_PYTHON_PREFIX}_COMPILER AND _${_PYTHON_PREFIX}_COMPILER_USABLE)
- if (${_PYTHON_PREFIX}_Interpreter_FOUND)
- # Compiler must be compatible with interpreter
- if (${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR} VERSION_EQUAL ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR})
- set (${_PYTHON_PREFIX}_Compiler_FOUND TRUE)
- endif()
- elseif (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
- set (${_PYTHON_PREFIX}_Compiler_FOUND TRUE)
- # Use compiler version for future searches to ensure consistency
- set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR})
- endif()
- endif()
-
- if (${_PYTHON_PREFIX}_Compiler_FOUND)
- # compute and save compiler signature
- string (MD5 __${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_COMPILER}")
- set (_${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${__${_PYTHON_PREFIX}_COMPILER_SIGNATURE}" CACHE INTERNAL "")
-
- set (${_PYTHON_PREFIX}_COMPILER_ID IronPython)
- else()
- unset (_${_PYTHON_PREFIX}_COMPILER_SIGNATURE CACHE)
- unset (${_PYTHON_PREFIX}_COMPILER_ID)
- endif()
-
- _python_mark_as_internal (_${_PYTHON_PREFIX}_COMPILER
- _${_PYTHON_PREFIX}_COMPILER_SIGNATURE)
-endif()
-
-
-# third step, search for the development artifacts
-## Development environment is not compatible with IronPython interpreter
-if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
- AND NOT ${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "IronPython")
- list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_LIBRARY_RELEASE
- _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE
- _${_PYTHON_PREFIX}_LIBRARY_DEBUG
- _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG
- _${_PYTHON_PREFIX}_INCLUDE_DIR)
- if (${_PYTHON_PREFIX}_FIND_REQUIRED_Development)
- list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_LIBRARIES
- ${_PYTHON_PREFIX}_INCLUDE_DIRS)
- endif()
-
- if (DEFINED _${_PYTHON_PREFIX}_LIBRARY_RELEASE OR DEFINED _${_PYTHON_PREFIX}_INCLUDE_DIR)
- # compute development signature and check validity of definition
- string (MD5 __${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}:${_${_PYTHON_PREFIX}_INCLUDE_DIR}")
- if (WIN32 AND NOT DEFINED _${_PYTHON_PREFIX}_LIBRARY_DEBUG)
- set (_${_PYTHON_PREFIX}_LIBRARY_DEBUG "${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND" CACHE INTERNAL "")
- endif()
- if (NOT DEFINED _${_PYTHON_PREFIX}_INCLUDE_DIR)
- set (_${_PYTHON_PREFIX}_INCLUDE_DIR "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND" CACHE INTERNAL "")
- endif()
- if (__${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE)
- # check version validity
- if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT)
- _python_validate_library (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT CHECK_EXISTS)
- _python_validate_include_dir (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT CHECK_EXISTS)
- else()
- _python_validate_library (${${_PYTHON_PREFIX}_FIND_VERSION} CHECK_EXISTS)
- _python_validate_include_dir (${${_PYTHON_PREFIX}_FIND_VERSION} CHECK_EXISTS)
- endif()
- else()
- unset (_${_PYTHON_PREFIX}_LIBRARY_RELEASE CACHE)
- unset (_${_PYTHON_PREFIX}_LIBRARY_DEBUG CACHE)
- unset (_${_PYTHON_PREFIX}_INCLUDE_DIR CACHE)
- endif()
- endif()
- if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE OR NOT _${_PYTHON_PREFIX}_INCLUDE_DIR)
- unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
- unset (_${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE CACHE)
- endif()
-
- if (DEFINED ${_PYTHON_PREFIX}_LIBRARY
- AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_LIBRARY}")
- set (_${_PYTHON_PREFIX}_LIBRARY_RELEASE "${${_PYTHON_PREFIX}_LIBRARY}" CACHE INTERNAL "")
- unset (_${_PYTHON_PREFIX}_LIBRARY_DEBUG CACHE)
- unset (_${_PYTHON_PREFIX}_INCLUDE_DIR CACHE)
- endif()
- if (DEFINED ${_PYTHON_PREFIX}_INCLUDE_DIR
- AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_INCLUDE_DIR}")
- set (_${_PYTHON_PREFIX}_INCLUDE_DIR "${${_PYTHON_PREFIX}_INCLUDE_DIR}" CACHE INTERNAL "")
- endif()
-
- # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
- unset (_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES)
- if (DEFINED ${_PYTHON_PREFIX}_USE_STATIC_LIBS AND NOT WIN32)
- set(_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
- if(${_PYTHON_PREFIX}_USE_STATIC_LIBS)
- set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
- else()
- list (REMOVE_ITEM CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
- endif()
- endif()
-
- if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE OR NOT _${_PYTHON_PREFIX}_INCLUDE_DIR)
- # if python interpreter is found, use it to look-up for artifacts
- # to ensure consistency between interpreter and development environments.
- # If not, try to locate a compatible config tool
- if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND OR CMAKE_CROSSCOMPILING)
- set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
- unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS)
- if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
- set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX)
- endif()
- unset (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS)
-
- if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION")
- set (_${_PYTHON_PREFIX}_CONFIG_NAMES)
-
- foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
- _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX CONFIG)
- list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES ${_${_PYTHON_PREFIX}_VERSION_NAMES})
-
- # Framework Paths
- _python_get_frameworks (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_VERSION})
- list (APPEND _${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS})
- endforeach()
-
- # Apple frameworks handling
- if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
- find_program (_${_PYTHON_PREFIX}_CONFIG
- NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- PATH_SUFFIXES bin
- NO_CMAKE_PATH
- NO_CMAKE_ENVIRONMENT_PATH
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- find_program (_${_PYTHON_PREFIX}_CONFIG
- NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- PATH_SUFFIXES bin)
-
- # Apple frameworks handling
- if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST")
- find_program (_${_PYTHON_PREFIX}_CONFIG
- NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES}
- NAMES_PER_DIR
- PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- PATH_SUFFIXES bin
- NO_DEFAULT_PATH)
- endif()
-
- if (_${_PYTHON_PREFIX}_CONFIG)
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --help
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE __${_PYTHON_PREFIX}_HELP
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (_${_PYTHON_PREFIX}_RESULT)
- # assume config tool is not usable
- unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
- endif()
- endif()
-
- if (_${_PYTHON_PREFIX}_CONFIG)
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --abiflags
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE __${_PYTHON_PREFIX}_ABIFLAGS
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (_${_PYTHON_PREFIX}_RESULT)
- # assume ABI is not supported
- set (__${_PYTHON_PREFIX}_ABIFLAGS "")
- endif()
- if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT __${_PYTHON_PREFIX}_ABIFLAGS IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
- # Wrong ABI
- unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
- endif()
- endif()
-
- if (_${_PYTHON_PREFIX}_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE)
- # check that config tool match library architecture
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE _${_PYTHON_PREFIX}_CONFIGDIR
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (_${_PYTHON_PREFIX}_RESULT)
- unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
- else()
- string(FIND "${_${_PYTHON_PREFIX}_CONFIGDIR}" "${CMAKE_LIBRARY_ARCHITECTURE}" _${_PYTHON_PREFIX}_RESULT)
- if (_${_PYTHON_PREFIX}_RESULT EQUAL -1)
- unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
- endif()
- endif()
- endif()
- else()
- foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
- # try to use pythonX.Y-config tool
- _python_get_names (_${_PYTHON_PREFIX}_CONFIG_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX CONFIG)
-
- # Framework Paths
- _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION})
-
- # Apple frameworks handling
- if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
- find_program (_${_PYTHON_PREFIX}_CONFIG
- NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- PATH_SUFFIXES bin
- NO_CMAKE_PATH
- NO_CMAKE_ENVIRONMENT_PATH
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- find_program (_${_PYTHON_PREFIX}_CONFIG
- NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- PATH_SUFFIXES bin)
-
- # Apple frameworks handling
- if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST")
- find_program (_${_PYTHON_PREFIX}_CONFIG
- NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES}
- NAMES_PER_DIR
- PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- PATH_SUFFIXES bin
- NO_DEFAULT_PATH)
- endif()
-
- unset (_${_PYTHON_PREFIX}_CONFIG_NAMES)
-
- if (_${_PYTHON_PREFIX}_CONFIG)
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --help
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE __${_PYTHON_PREFIX}_HELP
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (_${_PYTHON_PREFIX}_RESULT)
- # assume config tool is not usable
- unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
- endif()
- endif()
-
- if (NOT _${_PYTHON_PREFIX}_CONFIG)
- continue()
- endif()
-
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --abiflags
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE __${_PYTHON_PREFIX}_ABIFLAGS
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (_${_PYTHON_PREFIX}_RESULT)
- # assume ABI is not supported
- set (__${_PYTHON_PREFIX}_ABIFLAGS "")
- endif()
- if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT __${_PYTHON_PREFIX}_ABIFLAGS IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
- # Wrong ABI
- unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
- continue()
- endif()
-
- if (_${_PYTHON_PREFIX}_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE)
- # check that config tool match library architecture
- execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE _${_PYTHON_PREFIX}_CONFIGDIR
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (_${_PYTHON_PREFIX}_RESULT)
- unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
- continue()
- endif()
- string (FIND "${_${_PYTHON_PREFIX}_CONFIGDIR}" "${CMAKE_LIBRARY_ARCHITECTURE}" _${_PYTHON_PREFIX}_RESULT)
- if (_${_PYTHON_PREFIX}_RESULT EQUAL -1)
- unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
- continue()
- endif()
- endif()
-
- if (_${_PYTHON_PREFIX}_CONFIG)
- break()
- endif()
- endforeach()
- endif()
- endif()
- endif()
-
- if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
- if ((${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT CMAKE_CROSSCOMPILING) OR _${_PYTHON_PREFIX}_CONFIG)
- # retrieve root install directory
- _python_get_config_var (_${_PYTHON_PREFIX}_PREFIX PREFIX)
-
- # enforce current ABI
- _python_get_config_var (_${_PYTHON_PREFIX}_ABIFLAGS ABIFLAGS)
-
- set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_PREFIX}")
-
- # retrieve library
- ## compute some paths and artifact names
- if (_${_PYTHON_PREFIX}_CONFIG)
- string (REGEX REPLACE "^.+python([0-9.]+)[a-z]*-config" "\\1" _${_PYTHON_PREFIX}_VERSION "${_${_PYTHON_PREFIX}_CONFIG}")
- else()
- set (_${_PYTHON_PREFIX}_VERSION "${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}")
- endif()
- _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_VERSION} LIBRARY)
- _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 POSIX LIBRARY)
-
- _python_get_config_var (_${_PYTHON_PREFIX}_CONFIGDIR CONFIGDIR)
- list (APPEND _${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_CONFIGDIR}")
-
- list (APPEND _${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
-
- find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE
- NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- # Rely on HINTS and standard paths if interpreter or config tool failed to locate artifacts
- if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
- set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
-
- unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS)
- if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
- set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX)
- endif()
-
- if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION")
- unset (_${_PYTHON_PREFIX}_LIB_NAMES)
- unset (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG)
- unset (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS)
- unset (_${_PYTHON_PREFIX}_REGISTRY_PATHS)
- unset (_${_PYTHON_PREFIX}_PATH_SUFFIXES)
-
- foreach (_${_PYTHON_PREFIX}_LIB_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
- # library names
- _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 POSIX LIBRARY)
- list (APPEND _${_PYTHON_PREFIX}_LIB_NAMES ${_${_PYTHON_PREFIX}_VERSION_NAMES})
- _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 DEBUG)
- list (APPEND _${_PYTHON_PREFIX}_LIB_NAMES_DEBUG ${_${_PYTHON_PREFIX}_VERSION_NAMES})
-
- # Framework Paths
- _python_get_frameworks (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION})
- list (APPEND _${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS})
-
- # Registry Paths
- _python_get_registries (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION})
- list (APPEND _${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS})
-
- # Paths suffixes
- _python_get_path_suffixes (_${_PYTHON_PREFIX}_VERSION_PATHS VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY)
- list (APPEND _${_PYTHON_PREFIX}_PATH_SUFFIXES ${_${_PYTHON_PREFIX}_VERSION_PATHS})
- endforeach()
-
- if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
- find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE
- NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_CMAKE_PATH
- NO_CMAKE_ENVIRONMENT_PATH
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST")
- find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE
- NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- # search in HINTS locations
- find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE
- NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
-
- if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST")
- set (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS})
- else()
- unset (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS)
- endif()
-
- if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST")
- set (__${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS})
- else()
- unset (__${_PYTHON_PREFIX}_REGISTRY_PATHS)
- endif()
-
- # search in all default paths
- find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE
- NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
- NAMES_PER_DIR
- PATHS ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- ${__${_PYTHON_PREFIX}_REGISTRY_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES})
- else()
- foreach (_${_PYTHON_PREFIX}_LIB_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
- _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 POSIX LIBRARY)
- _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 DEBUG)
-
- _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION})
- _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION})
-
- _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY)
-
- if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
- find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE
- NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_CMAKE_PATH
- NO_CMAKE_ENVIRONMENT_PATH
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST")
- find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE
- NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- # search in HINTS locations
- find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE
- NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
- NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
-
- if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST")
- set (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS})
- else()
- unset (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS)
- endif()
-
- if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST")
- set (__${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS})
- else()
- unset (__${_PYTHON_PREFIX}_REGISTRY_PATHS)
- endif()
-
- # search in all default paths
- find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE
- NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
- NAMES_PER_DIR
- PATHS ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- ${__${_PYTHON_PREFIX}_REGISTRY_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES})
-
- if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE)
- break()
- endif()
- endforeach()
- endif()
- endif()
- endif()
-
- # finalize library version information
- _python_get_version (LIBRARY PREFIX _${_PYTHON_PREFIX}_)
-
- set (${_PYTHON_PREFIX}_LIBRARY_RELEASE "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
-
- if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
- endif()
-
- set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
-
- if (WIN32 AND _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
- # search for debug library
- # use release library location as a hint
- _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 DEBUG)
- get_filename_component (_${_PYTHON_PREFIX}_PATH "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY)
- find_library (_${_PYTHON_PREFIX}_LIBRARY_DEBUG
- NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG}
- NAMES_PER_DIR
- HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS}
- NO_DEFAULT_PATH)
- endif()
-
- # retrieve runtime libraries
- if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE)
- _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 POSIX LIBRARY)
- get_filename_component (_${_PYTHON_PREFIX}_PATH "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY)
- get_filename_component (_${_PYTHON_PREFIX}_PATH2 "${_${_PYTHON_PREFIX}_PATH}" DIRECTORY)
- _python_find_runtime_library (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE
- NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
- NAMES_PER_DIR
- HINTS "${_${_PYTHON_PREFIX}_PATH}" "${_${_PYTHON_PREFIX}_PATH2}" ${_${_PYTHON_PREFIX}_HINTS}
- PATH_SUFFIXES bin)
- endif()
- if (_${_PYTHON_PREFIX}_LIBRARY_DEBUG)
- _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 DEBUG)
- get_filename_component (_${_PYTHON_PREFIX}_PATH "${_${_PYTHON_PREFIX}_LIBRARY_DEBUG}" DIRECTORY)
- get_filename_component (_${_PYTHON_PREFIX}_PATH2 "${_${_PYTHON_PREFIX}_PATH}" DIRECTORY)
- _python_find_runtime_library (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG
- NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG}
- NAMES_PER_DIR
- HINTS "${_${_PYTHON_PREFIX}_PATH}" "${_${_PYTHON_PREFIX}_PATH2}" ${_${_PYTHON_PREFIX}_HINTS}
- PATH_SUFFIXES bin)
- endif()
-
- # Don't search for include dir if no library was founded
- if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE AND NOT _${_PYTHON_PREFIX}_INCLUDE_DIR)
- if ((${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT CMAKE_CROSSCOMPILING) OR _${_PYTHON_PREFIX}_CONFIG)
- _python_get_config_var (_${_PYTHON_PREFIX}_INCLUDE_DIRS INCLUDES)
-
- find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR
- NAMES Python.h
- HINTS ${_${_PYTHON_PREFIX}_INCLUDE_DIRS}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- # Rely on HINTS and standard paths if interpreter or config tool failed to locate artifacts
- if (NOT _${_PYTHON_PREFIX}_INCLUDE_DIR)
- unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS)
- if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
- set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX)
- endif()
- unset (_${_PYTHON_PREFIX}_INCLUDE_HINTS)
-
- # Use the library's install prefix as a hint
- if (${_${_PYTHON_PREFIX}_LIBRARY_RELEASE} MATCHES "^(.+/Frameworks/Python.framework/Versions/[0-9.]+)")
- list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}")
- elseif (${_${_PYTHON_PREFIX}_LIBRARY_RELEASE} MATCHES "^(.+)/lib(64|32)?/python[0-9.]+/config")
- list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}")
- elseif (DEFINED CMAKE_LIBRARY_ARCHITECTURE AND ${_${_PYTHON_PREFIX}_LIBRARY_RELEASE} MATCHES "^(.+)/lib/${CMAKE_LIBRARY_ARCHITECTURE}")
- list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}")
- else()
- # assume library is in a directory under root
- get_filename_component (_${_PYTHON_PREFIX}_PREFIX "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY)
- get_filename_component (_${_PYTHON_PREFIX}_PREFIX "${_${_PYTHON_PREFIX}_PREFIX}" DIRECTORY)
- list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${_${_PYTHON_PREFIX}_PREFIX}")
- endif()
-
- _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION})
- _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION})
- _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_VERSION} INCLUDE)
-
- if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
- find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR
- NAMES Python.h
- HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_CMAKE_PATH
- NO_CMAKE_ENVIRONMENT_PATH
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST")
- find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR
- NAMES Python.h
- HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST")
- set (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS})
- else()
- unset (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS)
- endif()
-
- if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST")
- set (__${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS})
- else()
- unset (__${_PYTHON_PREFIX}_REGISTRY_PATHS)
- endif()
-
- find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR
- NAMES Python.h
- HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS}
- ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- ${__${_PYTHON_PREFIX}_REGISTRY_PATHS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- endif()
-
- # search header file in standard locations
- find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR
- NAMES Python.h)
- endif()
-
- set (${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}")
-
- if (_${_PYTHON_PREFIX}_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}")
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
- endif()
-
- if (_${_PYTHON_PREFIX}_INCLUDE_DIR)
- # retrieve version from header file
- _python_get_version (INCLUDE PREFIX _${_PYTHON_PREFIX}_INC_)
-
- # update versioning
- if (_${_PYTHON_PREFIX}_INC_VERSION VERSION_EQUAL ${_${_PYTHON_PREFIX}_VERSION})
- set (_${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_INC_VERSION_PATCH})
- endif()
- endif()
-
- if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT ${_PYTHON_PREFIX}_Compiler_FOUND)
- # set public version information
- set (${_PYTHON_PREFIX}_VERSION ${_${_PYTHON_PREFIX}_VERSION})
- set (${_PYTHON_PREFIX}_VERSION_MAJOR ${_${_PYTHON_PREFIX}_VERSION_MAJOR})
- set (${_PYTHON_PREFIX}_VERSION_MINOR ${_${_PYTHON_PREFIX}_VERSION_MINOR})
- set (${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_VERSION_PATCH})
- endif()
-
- # define public variables
- set (${_PYTHON_PREFIX}_LIBRARY_DEBUG "${_${_PYTHON_PREFIX}_LIBRARY_DEBUG}")
- _python_select_library_configurations (${_PYTHON_PREFIX})
-
- set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE "${_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}")
- set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG "${_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}")
-
- if (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE)
- set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "${_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}")
- elseif (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG)
- set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "${_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}")
- else()
- set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "${_PYTHON_PREFIX}_RUNTIME_LIBRARY-NOTFOUND")
- endif()
-
- _python_set_library_dirs (${_PYTHON_PREFIX}_LIBRARY_DIRS
- _${_PYTHON_PREFIX}_LIBRARY_RELEASE _${_PYTHON_PREFIX}_LIBRARY_DEBUG)
- if (UNIX)
- if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$")
- set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DIRS ${${_PYTHON_PREFIX}_LIBRARY_DIRS})
- endif()
- else()
- _python_set_library_dirs (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DIRS
- _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG)
- endif()
-
- if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE AND _${_PYTHON_PREFIX}_INCLUDE_DIR)
- if (${_PYTHON_PREFIX}_Interpreter_FOUND OR ${_PYTHON_PREFIX}_Compiler_FOUND)
- # development environment must be compatible with interpreter/compiler
- if (${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR} VERSION_EQUAL ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}
- AND ${_${_PYTHON_PREFIX}_INC_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_INC_VERSION_MINOR} VERSION_EQUAL ${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR})
- set (${_PYTHON_PREFIX}_Development_FOUND TRUE)
- endif()
- elseif (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR
- AND ${_${_PYTHON_PREFIX}_INC_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_INC_VERSION_MINOR} VERSION_EQUAL ${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR})
- set (${_PYTHON_PREFIX}_Development_FOUND TRUE)
- endif()
- if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND
- (NOT _${_PYTHON_PREFIX}_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS
- OR NOT _${_PYTHON_PREFIX}_INC_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS))
- set (${_PYTHON_PREFIX}_Development_FOUND FALSE)
- endif()
- endif()
-
- if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_GREATER_EQUAL 3
- AND NOT DEFINED ${_PYTHON_PREFIX}_SOABI)
- _python_get_config_var (${_PYTHON_PREFIX}_SOABI SOABI)
- endif()
-
- if (${_PYTHON_PREFIX}_Development_FOUND)
- # compute and save development signature
- string (MD5 __${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}:${_${_PYTHON_PREFIX}_INCLUDE_DIR}")
- set (_${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE "${__${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE}" CACHE INTERNAL "")
- else()
- unset (_${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE CACHE)
- endif()
-
- # Restore the original find library ordering
- if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES)
- set (CMAKE_FIND_LIBRARY_SUFFIXES ${_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES})
- endif()
-
- _python_mark_as_internal (_${_PYTHON_PREFIX}_LIBRARY_RELEASE
- _${_PYTHON_PREFIX}_LIBRARY_DEBUG
- _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE
- _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG
- _${_PYTHON_PREFIX}_INCLUDE_DIR
- _${_PYTHON_PREFIX}_CONFIG
- _${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE)
-endif()
-
-if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Interpreter_FOUND)
- list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR)
- if (${_PYTHON_PREFIX}_FIND_REQUIRED_NumPy)
- list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS)
- endif()
-
- if (DEFINED ${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR
- AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
- set (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}" CACHE INTERNAL "")
- elseif (DEFINED _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR)
- # compute numpy signature. Depends on interpreter and development signatures
- string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}:${_${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE}:${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
- if (NOT __${_PYTHON_PREFIX}_NUMPY_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_NUMPY_SIGNATURE
- OR NOT EXISTS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
- unset (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR CACHE)
- unset (_${_PYTHON_PREFIX}_NUMPY_SIGNATURE CACHE)
- endif()
- endif()
-
- if (NOT _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR)
- execute_process(
- COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
- "from __future__ import print_function\ntry: import numpy; print(numpy.get_include(), end='')\nexcept:pass\n"
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE _${_PYTHON_PREFIX}_NumPy_PATH
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
-
- if (NOT _${_PYTHON_PREFIX}_RESULT)
- find_path (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR
- NAMES "numpy/arrayobject.h" "numpy/numpyconfig.h"
- HINTS "${_${_PYTHON_PREFIX}_NumPy_PATH}"
- NO_DEFAULT_PATH)
- endif()
- endif()
-
- set (${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
-
- if(_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
- set (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}\"")
- set_property (CACHE _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR-NOTFOUND")
- endif()
-
- if (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR)
- execute_process (
- COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
- "from __future__ import print_function\ntry: import numpy; print(numpy.__version__, end='')\nexcept:pass\n"
- RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
- OUTPUT_VARIABLE _${_PYTHON_PREFIX}_NumPy_VERSION)
- if (NOT _${_PYTHON_PREFIX}_RESULT)
- set (${_PYTHON_PREFIX}_NumPy_VERSION "${_${_PYTHON_PREFIX}_NumPy_VERSION}")
- else()
- unset (${_PYTHON_PREFIX}_NumPy_VERSION)
- endif()
-
- # final step: set NumPy founded only if Development component is founded as well
- set(${_PYTHON_PREFIX}_NumPy_FOUND ${${_PYTHON_PREFIX}_Development_FOUND})
- else()
- set (${_PYTHON_PREFIX}_NumPy_FOUND FALSE)
- endif()
-
- if (${_PYTHON_PREFIX}_NumPy_FOUND)
- # compute and save numpy signature
- string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}:${_${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE}:${${_PYTHON_PREFIX}_NumPyINCLUDE_DIR}")
- set (_${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${__${_PYTHON_PREFIX}_NUMPY_SIGNATURE}" CACHE INTERNAL "")
- else()
- unset (_${_PYTHON_PREFIX}_NUMPY_SIGNATURE CACHE)
- endif()
-
- _python_mark_as_internal (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR
- _${_PYTHON_PREFIX}_NUMPY_SIGNATURE)
-endif()
-
-# final validation
-if (${_PYTHON_PREFIX}_VERSION_MAJOR AND
- NOT ${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
- _python_display_failure ("Could NOT find ${_PYTHON_PREFIX}: Found unsuitable major version \"${${_PYTHON_PREFIX}_VERSION_MAJOR}\", but required major version is exact version \"${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}\"")
-endif()
-
-unset (_${_PYTHON_PREFIX}_REASON_FAILURE)
-foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Interpreter Compiler Development NumPy)
- if (_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE)
- string (APPEND _${_PYTHON_PREFIX}_REASON_FAILURE "\n ${_${_PYTHON_PREFIX}_COMPONENT}: ${_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE}")
- endif()
-endforeach()
-
-include (FindPackageHandleStandardArgs)
-find_package_handle_standard_args (${_PYTHON_PREFIX}
- REQUIRED_VARS ${_${_PYTHON_PREFIX}_REQUIRED_VARS}
- VERSION_VAR ${_PYTHON_PREFIX}_VERSION
- HANDLE_COMPONENTS
- REASON_FAILURE_MESSAGE "${_${_PYTHON_PREFIX}_REASON_FAILURE}")
-
-# Create imported targets and helper functions
-if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT")
- if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
- AND ${_PYTHON_PREFIX}_Interpreter_FOUND
- AND NOT TARGET ${_PYTHON_PREFIX}::Interpreter)
- add_executable (${_PYTHON_PREFIX}::Interpreter IMPORTED)
- set_property (TARGET ${_PYTHON_PREFIX}::Interpreter
- PROPERTY IMPORTED_LOCATION "${${_PYTHON_PREFIX}_EXECUTABLE}")
- endif()
-
- if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
- AND ${_PYTHON_PREFIX}_Compiler_FOUND
- AND NOT TARGET ${_PYTHON_PREFIX}::Compiler)
- add_executable (${_PYTHON_PREFIX}::Compiler IMPORTED)
- set_property (TARGET ${_PYTHON_PREFIX}::Compiler
- PROPERTY IMPORTED_LOCATION "${${_PYTHON_PREFIX}_COMPILER}")
- endif()
-
- if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
- AND ${_PYTHON_PREFIX}_Development_FOUND)
-
- macro (__PYTHON_IMPORT_LIBRARY __name)
- if (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$"
- OR ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE)
- set (_${_PYTHON_PREFIX}_LIBRARY_TYPE SHARED)
- else()
- set (_${_PYTHON_PREFIX}_LIBRARY_TYPE STATIC)
- endif()
-
- if (NOT TARGET ${__name})
- add_library (${__name} ${_${_PYTHON_PREFIX}_LIBRARY_TYPE} IMPORTED)
- endif()
-
- set_property (TARGET ${__name}
- PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIRS}")
-
- if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE)
- # System manage shared libraries in two parts: import and runtime
- if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
- set_property (TARGET ${__name} PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG)
- set_target_properties (${__name}
- PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
- IMPORTED_IMPLIB_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}"
- IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}")
- set_target_properties (${__name}
- PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
- IMPORTED_IMPLIB_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}"
- IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}")
- else()
- set_target_properties (${__name}
- PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C"
- IMPORTED_IMPLIB "${${_PYTHON_PREFIX}_LIBRARY}"
- IMPORTED_LOCATION "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY}")
- endif()
- else()
- if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
- set_property (TARGET ${__name} PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG)
- set_target_properties (${__name}
- PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
- IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
- set_target_properties (${__name}
- PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
- IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}")
- else()
- set_target_properties (${__name}
- PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C"
- IMPORTED_LOCATION "${${_PYTHON_PREFIX}_LIBRARY}")
- endif()
- endif()
-
- if (_${_PYTHON_PREFIX}_LIBRARY_TYPE STREQUAL "STATIC")
- # extend link information with dependent libraries
- _python_get_config_var (_${_PYTHON_PREFIX}_LINK_LIBRARIES LIBS)
- if (_${_PYTHON_PREFIX}_LINK_LIBRARIES)
- set_property (TARGET ${__name}
- PROPERTY INTERFACE_LINK_LIBRARIES ${_${_PYTHON_PREFIX}_LINK_LIBRARIES})
- endif()
- endif()
- endmacro()
-
- __python_import_library (${_PYTHON_PREFIX}::Python)
-
- if (CMAKE_SYSTEM_NAME MATCHES "^(Windows.*|CYGWIN|MSYS)$")
- # On Windows/CYGWIN/MSYS, Python::Module is the same as Python::Python
- # but ALIAS cannot be used because the imported library is not GLOBAL.
- __python_import_library (${_PYTHON_PREFIX}::Module)
- else()
- if (NOT TARGET ${_PYTHON_PREFIX}::Module )
- add_library (${_PYTHON_PREFIX}::Module INTERFACE IMPORTED)
- endif()
- set_property (TARGET ${_PYTHON_PREFIX}::Module
- PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIRS}")
-
- # When available, enforce shared library generation with undefined symbols
- if (APPLE)
- set_property (TARGET ${_PYTHON_PREFIX}::Module
- PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-undefined,dynamic_lookup")
- endif()
- if (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
- set_property (TARGET ${_PYTHON_PREFIX}::Module
- PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-z,nodefs")
- endif()
- if (CMAKE_SYSTEM_NAME STREQUAL "AIX")
- set_property (TARGET ${_PYTHON_PREFIX}::Module
- PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-b,erok")
- endif()
- endif()
-
- #
- # PYTHON_ADD_LIBRARY ( [STATIC|SHARED|MODULE] src1 src2 ... srcN)
- # It is used to build modules for python.
- #
- function (__${_PYTHON_PREFIX}_ADD_LIBRARY prefix name)
- cmake_parse_arguments (PARSE_ARGV 2 PYTHON_ADD_LIBRARY
- "STATIC;SHARED;MODULE;WITH_SOABI" "" "")
-
- if (prefix STREQUAL "Python2" AND PYTHON_ADD_LIBRARY_WITH_SOABI)
- message (AUTHOR_WARNING "FindPython2: Option `WITH_SOABI` is not supported for Python2 and will be ignored.")
- unset (PYTHON_ADD_LIBRARY_WITH_SOABI)
- endif()
-
- if (PYTHON_ADD_LIBRARY_STATIC)
- set (type STATIC)
- elseif (PYTHON_ADD_LIBRARY_SHARED)
- set (type SHARED)
- else()
- set (type MODULE)
- endif()
- add_library (${name} ${type} ${PYTHON_ADD_LIBRARY_UNPARSED_ARGUMENTS})
-
- get_property (type TARGET ${name} PROPERTY TYPE)
-
- if (type STREQUAL "MODULE_LIBRARY")
- target_link_libraries (${name} PRIVATE ${prefix}::Module)
- # customize library name to follow module name rules
- set_property (TARGET ${name} PROPERTY PREFIX "")
- if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
- set_property (TARGET ${name} PROPERTY SUFFIX ".pyd")
- endif()
-
- if (PYTHON_ADD_LIBRARY_WITH_SOABI AND ${prefix}_SOABI)
- get_property (suffix TARGET ${name} PROPERTY SUFFIX)
- if (NOT suffix)
- set (suffix "${CMAKE_SHARED_MODULE_SUFFIX}")
- endif()
- set_property (TARGET ${name} PROPERTY SUFFIX ".${${prefix}_SOABI}${suffix}")
- endif()
- else()
- if (PYTHON_ADD_LIBRARY_WITH_SOABI)
- message (AUTHOR_WARNING "Find${prefix}: Option `WITH_SOABI` is only supported for `MODULE` library type.")
- endif()
- target_link_libraries (${name} PRIVATE ${prefix}::Python)
- endif()
- endfunction()
- endif()
-
- if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_NumPy_FOUND
- AND NOT TARGET ${_PYTHON_PREFIX}::NumPy AND TARGET ${_PYTHON_PREFIX}::Module)
- add_library (${_PYTHON_PREFIX}::NumPy INTERFACE IMPORTED)
- set_property (TARGET ${_PYTHON_PREFIX}::NumPy
- PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS}")
- target_link_libraries (${_PYTHON_PREFIX}::NumPy INTERFACE ${_PYTHON_PREFIX}::Module)
- endif()
-endif()
-
-# final clean-up
-
-# Restore CMAKE_FIND_APPBUNDLE
-if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE)
- set (CMAKE_FIND_APPBUNDLE ${_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE})
- unset (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE)
-else()
- unset (CMAKE_FIND_APPBUNDLE)
-endif()
-# Restore CMAKE_FIND_FRAMEWORK
-if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK)
- set (CMAKE_FIND_FRAMEWORK ${_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK})
- unset (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK)
-else()
- unset (CMAKE_FIND_FRAMEWORK)
-endif()
diff --git a/cmake/FindPython3.cmake b/cmake/FindPython3.cmake
deleted file mode 100644
index e88e58864..000000000
--- a/cmake/FindPython3.cmake
+++ /dev/null
@@ -1,15 +0,0 @@
-# Taken from: https://github.com/Kitware/CMake/blob/v3.17.0/Modules/FindPython3.cmake
-
-set (_PYTHON_PREFIX Python3)
-
-set (_Python3_REQUIRED_VERSION_MAJOR 3)
-
-include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake)
-
-if (COMMAND __Python3_add_library)
- macro (Python3_add_library)
- __Python3_add_library (Python3 ${ARGV})
- endmacro()
-endif()
-
-unset (_PYTHON_PREFIX)
diff --git a/cpp/scenario/gazebo/include/scenario/gazebo/components/WorldVelocityCmd.h b/cpp/scenario/gazebo/include/scenario/gazebo/components/WorldVelocityCmd.h
deleted file mode 100644
index 13a8d7490..000000000
--- a/cpp/scenario/gazebo/include/scenario/gazebo/components/WorldVelocityCmd.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)
- * All rights reserved.
- *
- * This project is dual licensed under LGPL v2.1+ or Apache License.
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * This software may be modified and distributed under the terms of the
- * GNU Lesser General Public License v2.1 or any later version.
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef IGNITION_GAZEBO_COMPONENTS_WORLDVELOCITYCMD_H
-#define IGNITION_GAZEBO_COMPONENTS_WORLDVELOCITYCMD_H
-
-#include
-
-#include
-#include
-
-#include "ignition/gazebo/components/Component.hh"
-#include
-
-namespace ignition::gazebo {
- // Inline bracket to help doxygen filtering.
- inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
- struct WorldVelocity
- {
- math::Vector3d linear;
- math::Vector3d angular;
-
- bool operator==(const WorldVelocity& other) const
- {
- return this->linear == other.linear
- && this->angular == other.angular;
- }
- };
-
- namespace components {
- /// \brief A component type that contains commanded velocity of
- /// an entity in the world frame represented by
- /// ignition::math::Vector3d.
- using WorldVelocityCmd =
- Component;
- IGN_GAZEBO_REGISTER_COMPONENT(
- "ign_gazebo_components.WorldVelocityCmdTag",
- WorldVelocityCmd)
- } // namespace components
- } // namespace IGNITION_GAZEBO_VERSION_NAMESPACE
-} // namespace ignition::gazebo
-#endif // IGNITION_GAZEBO_COMPONENTS_WORLDVELOCITYCMD_H
diff --git a/cpp/scenario/plugins/ECMProvider/CMakeLists.txt b/cpp/scenario/plugins/ECMProvider/CMakeLists.txt
deleted file mode 100644
index 0d1c811d6..000000000
--- a/cpp/scenario/plugins/ECMProvider/CMakeLists.txt
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)
-# All rights reserved.
-#
-# This project is dual licensed under LGPL v2.1+ or Apache License.
-#
-# - - - - - - - - - - - - - - - - - -
-#
-# This software may be modified and distributed under the terms of the
-# GNU Lesser General Public License v2.1 or any later version.
-#
-# - - - - - - - - - - - - - - - - - -
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# ===========
-# ECMProvider
-# ===========
-
-add_library(ECMProvider SHARED
- include/scenario/plugins/gazebo/ECMProvider.h
- ECMProvider.cpp)
-
-target_link_libraries(ECMProvider
- PUBLIC
- ${ignition-gazebo.core}
- PRIVATE
- ECMSingleton
- ScenarioGazebo::ScenarioGazebo
- ScenarioGazebo::ExtraComponents)
-
-target_include_directories(ECMProvider PRIVATE
- $)
-
-# ============
-# ECMSingleton
-# ============
-
-# Always compile the singletons as shared libraries even if
-# they are not plugins
-add_library(ECMSingleton SHARED
- include/scenario/plugins/gazebo/ECMSingleton.h
- ECMSingleton.cpp)
-add_library(ScenarioGazeboPlugins::ECMSingleton ALIAS ECMSingleton)
-
-target_include_directories(ECMSingleton PUBLIC
- $
- $)
-
-target_link_libraries(ECMSingleton
- PUBLIC
- ${ignition-gazebo.core}
- PRIVATE
- ScenarioGazebo::ScenarioGazebo)
-
-set_target_properties(ECMSingleton PROPERTIES
- PUBLIC_HEADER include/scenario/plugins/gazebo/ECMSingleton.h)
-
-# ===================
-# Install the targets
-# ===================
-
-install(
- TARGETS ECMProvider
- LIBRARY DESTINATION ${SCENARIO_INSTALL_LIBDIR}/scenario/plugins
- ARCHIVE DESTINATION ${SCENARIO_INSTALL_LIBDIR}/scenario/plugins
- RUNTIME DESTINATION ${SCENARIO_INSTALL_BINDIR})
-
-install(
- TARGETS ECMSingleton
- EXPORT ScenarioGazeboPluginsExport
- LIBRARY DESTINATION ${SCENARIO_INSTALL_LIBDIR}
- ARCHIVE DESTINATION ${SCENARIO_INSTALL_LIBDIR}
- RUNTIME DESTINATION ${SCENARIO_INSTALL_BINDIR}
- PUBLIC_HEADER DESTINATION
- ${SCENARIO_INSTALL_INCLUDEDIR}/scenario/plugins/gazebo)
diff --git a/cpp/scenario/plugins/ECMProvider/ECMProvider.cpp b/cpp/scenario/plugins/ECMProvider/ECMProvider.cpp
deleted file mode 100644
index 33693ed1d..000000000
--- a/cpp/scenario/plugins/ECMProvider/ECMProvider.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)
- * All rights reserved.
- *
- * This project is dual licensed under LGPL v2.1+ or Apache License.
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * This software may be modified and distributed under the terms of the
- * GNU Lesser General Public License v2.1 or any later version.
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "scenario/plugins/gazebo/ECMProvider.h"
-#include "scenario/gazebo/Log.h"
-#include "scenario/gazebo/helpers.h"
-#include "scenario/plugins/gazebo/ECMSingleton.h"
-
-#include
-#include
-#include
-#include
-
-using namespace scenario::gazebo;
-using namespace scenario::plugins::gazebo;
-
-class ECMProvider::Impl
-{
-public:
-};
-
-ECMProvider::ECMProvider()
- : System()
- , pImpl{std::make_unique()}
-{}
-
-ECMProvider::~ECMProvider()
-{
- ECMSingleton::Instance().clean();
- sDebug << "Destroying the ECMProvider" << std::endl;
-};
-
-void ECMProvider::Configure(const ignition::gazebo::Entity& entity,
- const std::shared_ptr& /*sdf*/,
- ignition::gazebo::EntityComponentManager& ecm,
- ignition::gazebo::EventManager& eventMgr)
-{
- if (!ecm.EntityHasComponentType(
- entity, ignition::gazebo::components::World::typeId)) {
- sError << "The ECMProvider plugin was not inserted "
- << "in a world element" << std::endl;
- return;
- }
-
- const auto& worldName = utils::getExistingComponentData< //
- ignition::gazebo::components::Name>(&ecm, entity);
-
- if (ECMSingleton::Instance().hasWorld(worldName)) {
- sWarning << "Resources of world " << worldName << " already inserted"
- << std::endl;
- return;
- }
-
- if (!ECMSingleton::Instance().storePtrs(&ecm, &eventMgr, worldName)) {
- sError << "Failed to store resources of world " << worldName << " ["
- << entity << "]" << std::endl;
- return;
- }
-
- sDebug << "World '" << worldName
- << "' successfully processed by ECMProvider" << std::endl;
-}
-
-IGNITION_ADD_PLUGIN(scenario::plugins::gazebo::ECMProvider,
- scenario::plugins::gazebo::ECMProvider::System,
- scenario::plugins::gazebo::ECMProvider::ISystemConfigure)
diff --git a/cpp/scenario/plugins/ECMProvider/ECMSingleton.cpp b/cpp/scenario/plugins/ECMProvider/ECMSingleton.cpp
deleted file mode 100644
index 1676223b5..000000000
--- a/cpp/scenario/plugins/ECMProvider/ECMSingleton.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)
- * All rights reserved.
- *
- * This project is dual licensed under LGPL v2.1+ or Apache License.
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * This software may be modified and distributed under the terms of the
- * GNU Lesser General Public License v2.1 or any later version.
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "scenario/plugins/gazebo/ECMSingleton.h"
-#include "scenario/gazebo/Log.h"
-
-#include
-#include
-#include
-#include
-#include
-
-using namespace scenario::plugins::gazebo;
-
-class ECMSingleton::Impl
-{
-public:
- struct ResourcePtrs
- {
- ResourcePtrs() = delete;
- ResourcePtrs(ignition::gazebo::EntityComponentManager* _ecm,
- ignition::gazebo::EventManager* _eventMgr)
- : ecm(_ecm)
- , eventMgr(_eventMgr)
- {}
-
- ignition::gazebo::EntityComponentManager* ecm = nullptr;
- ignition::gazebo::EventManager* eventMgr = nullptr;
- };
-
- mutable std::recursive_mutex mutex;
-
- using WorldName = std::string;
- std::unordered_map resources;
-};
-
-ECMSingleton::ECMSingleton()
- : pImpl{new Impl()}
-{}
-
-ECMSingleton::~ECMSingleton() = default;
-
-ECMSingleton& ECMSingleton::Instance()
-{
- static ECMSingleton instance;
- return instance;
-}
-
-void ECMSingleton::clean(const std::string& worldName)
-{
- std::unique_lock lock(pImpl->mutex);
-
- if (worldName.empty()) {
- pImpl->resources.clear();
- return;
- }
-
- if (!this->hasWorld(worldName)) {
- sError << "Resources of world " << worldName << " not found"
- << std::endl;
- return;
- }
-
- pImpl->resources.erase(worldName);
-}
-
-bool ECMSingleton::valid(const std::string& worldName) const
-{
- std::unique_lock lock(pImpl->mutex);
-
- if (!this->hasWorld(worldName)) {
- sDebug << "World" << worldName << " not found" << std::endl;
- return false;
- }
-
- if (!worldName.empty()) {
- const auto& ptrs = pImpl->resources.at(worldName);
- return ptrs.ecm && ptrs.eventMgr;
- }
- else {
- bool valid = true;
- for (const auto& [_, resources] : pImpl->resources) {
- valid = valid && resources.ecm && resources.eventMgr;
- }
-
- return valid;
- }
-}
-
-bool ECMSingleton::hasWorld(const std::string& worldName) const
-{
- std::unique_lock lock(pImpl->mutex);
-
- if (worldName.empty()) {
- return pImpl->resources.size() != 0;
- }
-
- return pImpl->resources.find(worldName) != pImpl->resources.end();
-}
-
-std::vector ECMSingleton::worldNames() const
-{
- std::unique_lock lock(pImpl->mutex);
- std::vector worldNames;
-
- for (const auto& [key, _] : pImpl->resources) {
- worldNames.emplace_back(key);
- }
-
- return worldNames;
-}
-
-ignition::gazebo::EventManager*
-ECMSingleton::getEventManager(const std::string& worldName) const
-{
- std::unique_lock lock(pImpl->mutex);
-
- if (!this->hasWorld(worldName)) {
- sError << "Resources of world " << worldName << " not found"
- << std::endl;
- return nullptr;
- }
-
- if (!this->valid(worldName)) {
- sError << "Resources of world " << worldName << " not valid"
- << std::endl;
- return nullptr;
- }
-
- return pImpl->resources.at(worldName).eventMgr;
-}
-
-ignition::gazebo::EntityComponentManager*
-ECMSingleton::getECM(const std::string& worldName) const
-{
- std::unique_lock lock(pImpl->mutex);
-
- if (!this->hasWorld(worldName)) {
- sError << "Resources of world " << worldName << " not found"
- << std::endl;
- return nullptr;
- }
-
- if (!this->valid(worldName)) {
- sError << "Resources of world " << worldName << " not valid"
- << std::endl;
- return nullptr;
- }
-
- return pImpl->resources.at(worldName).ecm;
-}
-
-bool ECMSingleton::storePtrs(ignition::gazebo::EntityComponentManager* ecm,
- ignition::gazebo::EventManager* eventMgr,
- const std::string& worldName)
-{
- if (!ecm || !eventMgr) {
- sError << "The pointer to the ECM or EventManager is not valid"
- << std::endl;
- return false;
- }
-
- if (worldName.empty()) {
- sError << "The world name is empty" << std::endl;
- return false;
- }
-
- std::unique_lock lock(pImpl->mutex);
-
- if (this->hasWorld(worldName)) {
- sError << "Resources of world " << worldName
- << " have been already stored" << std::endl;
- return false;
- }
-
- pImpl->resources.emplace(worldName, Impl::ResourcePtrs(ecm, eventMgr));
- return true;
-}
diff --git a/cpp/scenario/plugins/ECMProvider/include/scenario/plugins/gazebo/ECMProvider.h b/cpp/scenario/plugins/ECMProvider/include/scenario/plugins/gazebo/ECMProvider.h
deleted file mode 100644
index f99dafa2b..000000000
--- a/cpp/scenario/plugins/ECMProvider/include/scenario/plugins/gazebo/ECMProvider.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)
- * All rights reserved.
- *
- * This project is dual licensed under LGPL v2.1+ or Apache License.
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * This software may be modified and distributed under the terms of the
- * GNU Lesser General Public License v2.1 or any later version.
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SCENARIO_PLUGINS_GAZEBO_ECMPROVIDER
-#define SCENARIO_PLUGINS_GAZEBO_ECMPROVIDER
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-namespace scenario::plugins::gazebo {
- class ECMProvider;
-} // namespace scenario::plugins::gazebo
-
-class scenario::plugins::gazebo::ECMProvider final
- : public ignition::gazebo::System
- , public ignition::gazebo::ISystemConfigure
-{
-public:
- ECMProvider();
- ~ECMProvider() override;
-
- void Configure(const ignition::gazebo::Entity& entity,
- const std::shared_ptr& sdf,
- ignition::gazebo::EntityComponentManager& ecm,
- ignition::gazebo::EventManager& eventMgr) override;
-
-private:
- class Impl;
- std::unique_ptr pImpl = nullptr;
-};
-
-#endif // SCENARIO_PLUGINS_GAZEBO_ECMPROVIDER
diff --git a/cpp/scenario/plugins/ECMProvider/include/scenario/plugins/gazebo/ECMSingleton.h b/cpp/scenario/plugins/ECMProvider/include/scenario/plugins/gazebo/ECMSingleton.h
deleted file mode 100644
index f9400ccb5..000000000
--- a/cpp/scenario/plugins/ECMProvider/include/scenario/plugins/gazebo/ECMSingleton.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)
- * All rights reserved.
- *
- * This project is dual licensed under LGPL v2.1+ or Apache License.
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * This software may be modified and distributed under the terms of the
- * GNU Lesser General Public License v2.1 or any later version.
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SCENARIO_PLUGINS_GAZEBO_ECMSINGLETON_H
-#define SCENARIO_PLUGINS_GAZEBO_ECMSINGLETON_H
-
-#include "ignition/gazebo/EntityComponentManager.hh"
-#include "ignition/gazebo/EventManager.hh"
-
-#include
-
-namespace scenario::plugins::gazebo {
- class ECMSingleton;
-} // namespace scenario::plugins::gazebo
-
-class scenario::plugins::gazebo::ECMSingleton
-{
-public:
- ECMSingleton();
- ~ECMSingleton();
-
- ECMSingleton(ECMSingleton&) = delete;
- void operator=(const ECMSingleton&) = delete;
-
- static ECMSingleton& Instance();
-
- void clean(const std::string& worldName = {});
- bool valid(const std::string& worldName = {}) const;
- bool hasWorld(const std::string& worldName = {}) const;
-
- std::vector worldNames() const;
- ignition::gazebo::EventManager*
- getEventManager(const std::string& worldName) const;
- ignition::gazebo::EntityComponentManager*
- getECM(const std::string& worldName) const;
-
- bool storePtrs(ignition::gazebo::EntityComponentManager* ecm,
- ignition::gazebo::EventManager* eventMgr,
- const std::string& worldName);
-
-private:
- class Impl;
- std::unique_ptr pImpl;
-};
-
-#endif // SCENARIO_PLUGINS_GAZEBO_ECMSINGLETON_H
diff --git a/cpp/scenario/plugins/Physics/Physics.cpp b/cpp/scenario/plugins/Physics/Physics.cpp
deleted file mode 100644
index efdd5181f..000000000
--- a/cpp/scenario/plugins/Physics/Physics.cpp
+++ /dev/null
@@ -1,2556 +0,0 @@
-/*
- * Copyright (C) 2020 Open Source Robotics Foundation
- * All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Physics.h"
-#include "scenario/gazebo/components/ExternalWorldWrenchCmdWithDuration.h"
-#include "scenario/gazebo/components/HistoryOfAppliedJointForces.h"
-#include "scenario/gazebo/components/JointAcceleration.h"
-#include "scenario/gazebo/components/SimulatedTime.h"
-#include "scenario/gazebo/components/WorldVelocityCmd.h"
-#include "scenario/gazebo/helpers.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-using namespace ignition;
-using namespace scenario::plugins::gazebo;
-using namespace ignition::gazebo;
-using namespace ignition::gazebo::systems;
-using namespace ignition::gazebo::components;
-
-class Physics::Impl
-{
-public:
- /// \brief This is the minimum set of features that any physics engine must
- /// implement to be supported by this system.
- /// New features can't be added to this list in minor / patch releases, in
- /// order to maintain backwards compatibility with downstream physics
- /// plugins.
- struct MinimumFeatureList
- : ignition::physics::FeatureList< //
- ignition::physics::FindFreeGroupFeature,
- ignition::physics::SetFreeGroupWorldPose,
- ignition::physics::FreeGroupFrameSemantics,
- ignition::physics::LinkFrameSemantics,
- ignition::physics::SetFreeGroupWorldVelocity,
- ignition::physics::ForwardStep,
- ignition::physics::RemoveEntities,
- ignition::physics::sdf::ConstructSdfLink,
- ignition::physics::sdf::ConstructSdfModel,
- ignition::physics::sdf::ConstructSdfWorld>
- {};
-
- /// \brief Engine type with just the minimum features.
- using EnginePtrType = ignition::physics::EnginePtr< //
- ignition::physics::FeaturePolicy3d,
- MinimumFeatureList>;
-
- /// \brief World type with just the minimum features.
- using WorldPtrType = ignition::physics::WorldPtr< //
- ignition::physics::FeaturePolicy3d,
- MinimumFeatureList>;
-
- /// \brief Model type with just the minimum features.
- using ModelPtrType = ignition::physics::ModelPtr< //
- ignition::physics::FeaturePolicy3d,
- MinimumFeatureList>;
-
- /// \brief Link type with just the minimum features.
- using LinkPtrType = ignition::physics::LinkPtr< //
- ignition::physics::FeaturePolicy3d,
- MinimumFeatureList>;
-
- /// \brief Free group type with just the minimum features.
- using FreeGroupPtrType = ignition::physics::FreeGroupPtr< //
- ignition::physics::FeaturePolicy3d,
- MinimumFeatureList>;
-
- /// \brief Create physics entities
- /// \param[in] _ecm Constant reference to ECM.
- void CreatePhysicsEntities(const EntityComponentManager& _ecm);
-
- /// \brief Remove physics entities if they are removed from the ECM
- /// \param[in] _ecm Constant reference to ECM.
- void RemovePhysicsEntities(const EntityComponentManager& _ecm);
-
- /// \brief Update physics from components
- /// \param[in] _ecm Constant reference to ECM.
- void UpdatePhysics(const ignition::gazebo::UpdateInfo& _info,
- EntityComponentManager& _ecm);
-
- /// \brief Step the simulationrfor each world
- /// \param[in] _dt Duration
- void Step(const std::chrono::steady_clock::duration& _dt);
-
- /// \brief Update components from physics simulation
- /// \param[in] _ecm Mutable reference to ECM.
- void UpdateSim(const ignition::gazebo::UpdateInfo& _info,
- EntityComponentManager& _ecm);
-
- /// \brief Update collision components from physics simulation
- /// \param[in] _ecm Mutable reference to ECM.
- void UpdateCollisions(EntityComponentManager& _ecm);
-
- /// \brief FrameData relative to world at a given offset pose
- /// \param[in] _link ign-physics link
- /// \param[in] _pose Offset pose in which to compute the frame data
- /// \returns FrameData at the given offset pose
- ignition::physics::FrameData3d
- LinkFrameDataAtOffset(const LinkPtrType& _link,
- const math::Pose3d& _pose) const;
-
- /// \brief Get transform from one ancestor entity to a descendant entity
- /// that are in the same model.
- /// \param[in] _from An ancestor of the _to entity.
- /// \param[in] _to A descendant of the _from entity.
- /// \return Pose transform between the two entities
- ignition::math::Pose3d
- RelativePose(const Entity& _from,
- const Entity& _to,
- const EntityComponentManager& _ecm) const;
-
- /// \brief A map between world entity ids in the ECM to World Entities in
- /// ign-physics.
- std::unordered_map entityWorldMap;
-
- /// \brief A map between model entity ids in the ECM to Model Entities in
- /// ign-physics.
- std::unordered_map entityModelMap;
-
- /// \brief A map between link entity ids in the ECM to Link Entities in
- /// ign-physics.
- std::unordered_map entityLinkMap;
-
- /// \brief Reverse of entityLinkMap. This is used for finding the Entity
- /// associated with a physics Link
- std::unordered_map linkEntityMap;
-
- /// \brief A map between model entity ids in the ECM to whether its battery
- /// has drained.
- std::unordered_map entityOffMap;
-
- /// \brief used to store whether physics objects have been created.
- bool initialized = false;
-
- /// \brief Pointer to the underlying ign-physics Engine entity.
- EnginePtrType engine = nullptr;
-
- /// \brief Vector3d equality comparison function.
- std::function vec3Eql{
- [](const math::Vector3d& _a, const math::Vector3d& _b) {
- return _a.Equal(_b, 1e-6);
- }};
-
- /// \brief Pose3d equality comparison function.
- std::function pose3Eql{
- [](const math::Pose3d& _a, const math::Pose3d& _b) {
- return _a.Pos().Equal(_b.Pos(), 1e-6)
- && math::equal(_a.Rot().X(), _b.Rot().X(), 1e-6)
- && math::equal(_a.Rot().Y(), _b.Rot().Y(), 1e-6)
- && math::equal(_a.Rot().Z(), _b.Rot().Z(), 1e-6)
- && math::equal(_a.Rot().W(), _b.Rot().W(), 1e-6);
- }};
-
- /// \brief AxisAlignedBox equality comparison function.
- std::function
- axisAlignedBoxEql{
- [](const math::AxisAlignedBox& _a, const math::AxisAlignedBox& _b) {
- return _a == _b;
- }};
-
- /// \brief Environment variable which holds paths to look for engine plugins
- std::string pluginPathEnv = "IGN_GAZEBO_PHYSICS_ENGINE_PATH";
-
- //////////////////////////////////////////////////
- // Slip Compliance
-
- /// \brief Feature list to process `FrictionPyramidSlipCompliance`
- /// components.
- using FrictionPyramidSlipComplianceFeatureList = physics::FeatureList<
- MinimumFeatureList,
- ignition::physics::GetShapeFrictionPyramidSlipCompliance,
- ignition::physics::SetShapeFrictionPyramidSlipCompliance>;
-
- /// \brief Shape type with slip compliance features.
- using ShapeSlipParamPtrType =
- physics::ShapePtr;
-
- /// \brief A map between shape entity ids in the ECM to Shape Entities in
- /// ign-physics
- /// All shapes on this map are also in `entityCollisionMap`. The difference
- /// is that here they've been casted for
- /// `FrictionPyramidSlipComplianceFeatureList`.
- std::unordered_map entityShapeSlipParamMap;
-
- //////////////////////////////////////////////////
- // Joints
-
- /// \brief Feature list to handle joints.
- using JointFeatureList = ignition::physics::FeatureList<
- MinimumFeatureList,
- ignition::physics::GetBasicJointProperties,
- ignition::physics::GetBasicJointState,
- ignition::physics::SetBasicJointState,
- ignition::physics::sdf::ConstructSdfJoint>;
-
- /// \brief Joint type with joint features.
- using JointPtrType = ignition::physics::JointPtr< //
- ignition::physics::FeaturePolicy3d,
- JointFeatureList>;
-
- /// \brief Model type with joint features (models to attach to).
- using ModelJointPtrType = ignition::physics::ModelPtr< //
- ignition::physics::FeaturePolicy3d,
- JointFeatureList>;
-
- /// \brief A map between joint entity ids in the ECM to Joint Entities in
- /// ign-physics
- std::unordered_map entityJointMap;
-
- /// \brief A map between model entity ids in the ECM to Model Entities in
- /// ign-physics, with attach feature.
- /// All models on this map are also in `entityModelMap`. The difference is
- /// that here they've been casted for `JointFeatureList`.
- std::unordered_map entityModelJointMap;
-
- //////////////////////////////////////////////////
- // Detachable joints
-
- /// \brief Feature list to process `DetachableJoint` components.
- using DetachableJointFeatureList = ignition::physics::FeatureList< //
- JointFeatureList,
- ignition::physics::AttachFixedJointFeature,
- ignition::physics::DetachJointFeature,
- ignition::physics::SetJointTransformFromParentFeature>;
-
- /// \brief Joint type with detachable joint features.
- using JointDetachableJointPtrType = ignition::physics::JointPtr< //
- ignition::physics::FeaturePolicy3d,
- DetachableJointFeatureList>;
-
- /// \brief Link type with detachable joint features (links to attach to).
- using LinkDetachableJointPtrType = ignition::physics::LinkPtr< //
- ignition::physics::FeaturePolicy3d,
- DetachableJointFeatureList>;
-
- /// \brief A map between joint entity ids in the ECM to Joint Entities in
- /// ign-physics, with detach feature.
- /// All joints on this map are also in `entityJointMap`. The difference is
- /// that here they've been casted for `physics::DetachJointFeature`.
- std::unordered_map
- entityJointDetachableJointMap;
-
- /// \brief A map between link entity ids in the ECM to Link Entities in
- /// ign-physics, with attach feature.
- /// All links on this map are also in `entityLinkMap`. The difference is
- /// that here they've been casted for `DetachableJointFeatureList`.
- std::unordered_map
- entityLinkDetachableJointMap;
-
- //////////////////////////////////////////////////
- // Collisions
-
- /// \brief Feature list to handle collisions.
- using CollisionFeatureList = ignition::physics::FeatureList< //
- MinimumFeatureList,
- ignition::physics::GetContactsFromLastStepFeature,
- ignition::physics::sdf::ConstructSdfCollision>;
-
- /// \brief Collision type with collision features.
- using ShapePtrType = ignition::physics::ShapePtr< //
- ignition::physics::FeaturePolicy3d,
- CollisionFeatureList>;
-
- /// \brief Link type with collision features.
- using LinkShapePtrType = ignition::physics::LinkPtr< //
- ignition::physics::FeaturePolicy3d,
- CollisionFeatureList>;
-
- /// \brief World type with collision features.
- using WorldShapePtrType = ignition::physics::WorldPtr< //
- ignition::physics::FeaturePolicy3d,
- CollisionFeatureList>;
-
- /// \brief World type with just the minimum features. Non-pointer.
- using WorldShapeType = ignition::physics::World< //
- ignition::physics::FeaturePolicy3d,
- CollisionFeatureList>;
-
- /// \brief A map between collision entity ids in the ECM to Shape Entities
- /// in ign-physics.
- std::unordered_map entityCollisionMap;
-
- /// \brief A map between shape entities in ign-physics to collision entities
- /// in the ECM. This is the reverse map of entityCollisionMap.
- std::unordered_map collisionEntityMap;
-
- /// \brief A map between link entity ids in the ECM to Link Entities in
- /// ign-physics, with attach feature.
- /// All links on this map are also in `entityLinkMap`. The difference is
- /// that here they've been casted for `CollisionFeatureList`.
- std::unordered_map entityLinkCollisionMap;
-
- /// \brief A map between world entity ids in the ECM to World Entities in
- /// ign-physics, with attach feature.
- /// All worlds on this map are also in `entityWorldMap`. The difference is
- /// that here they've been casted for `CollisionFeatureList`.
- std::unordered_map entityWorldCollisionMap;
-
- //////////////////////////////////////////////////
- // Collision filtering with bitmasks
-
- /// \brief Feature list to filter collisions with bitmasks.
- using CollisionMaskFeatureList = ignition::physics::FeatureList<
- CollisionFeatureList,
- ignition::physics::CollisionFilterMaskFeature>;
-
- /// \brief Collision type with collision filtering features.
- using ShapeFilterMaskPtrType =
- ignition::physics::ShapePtr;
-
- /// \brief A map between collision entity ids in the ECM to Shape Entities
- /// in ign-physics, with collision filtering feature. All links on this map
- /// are also in `entityCollisionMap`. The difference is that here they've
- /// been casted for `CollisionMaskFeatureList`.
- std::unordered_map entityShapeMaskMap;
-
- //////////////////////////////////////////////////
- // Link force
-
- /// \brief Feature list for applying forces to links.
- using LinkForceFeatureList = ignition::physics::FeatureList< //
- ignition::physics::AddLinkExternalForceTorque>;
-
- /// \brief Link type with bounding box feature.
- using LinkForcePtrType = ignition::physics::LinkPtr< //
- ignition::physics::FeaturePolicy3d,
- LinkForceFeatureList>;
-
- /// \brief A map between link entity ids in the ECM to Link Entities in
- /// ign-physics, with force feature.
- /// All links on this map are also in `entityLinkMap`. The difference is
- /// that here they've been casted for `LinkForceFeatureList`.
- std::unordered_map entityLinkForceMap;
-
- //////////////////////////////////////////////////
- // Bounding box
-
- /// \brief Feature list for model bounding box.
- using BoundingBoxFeatureList = ignition::physics::FeatureList< //
- MinimumFeatureList,
- ignition::physics::GetModelBoundingBox>;
-
- /// \brief Model type with bounding box feature.
- using ModelBoundingBoxPtrType = ignition::physics::ModelPtr< //
- ignition::physics::FeaturePolicy3d,
- BoundingBoxFeatureList>;
-
- /// \brief A map between model entity ids in the ECM to Model Entities in
- /// ign-physics, with bounding box feature.
- /// All models on this map are also in `entityModelMap`. The difference is
- /// that here they've been casted for `BoundingBoxFeatureList`.
- std::unordered_map
- entityModelBoundingBoxMap;
-
- //////////////////////////////////////////////////
- // Joint velocity command
-
- /// \brief Feature list for set joint velocity command.
- using JointVelocityCommandFeatureList = ignition::physics::FeatureList< //
- physics::SetJointVelocityCommandFeature>;
-
- /// \brief Joint type with set joint velocity command.
- using JointVelocityCommandPtrType = ignition::physics::JointPtr< //
- ignition::physics::FeaturePolicy3d,
- JointVelocityCommandFeatureList>;
-
- /// \brief A map between joint entity ids in the ECM to Joint Entities in
- /// ign-physics, with velocity command feature.
- /// All joints on this map are also in `entityJointMap`. The difference is
- /// that here they've been casted for `JointVelocityCommandFeatureList`.
- std::unordered_map
- entityJointVelocityCommandMap;
-
- //////////////////////////////////////////////////
- // World velocity command
- using WorldVelocityCommandFeatureList = ignition::physics::FeatureList<
- ignition::physics::SetFreeGroupWorldVelocity>;
-
- /// \brief Free group type with world velocity command.
- using FreeGroupVelocityCmdPtrType =
- ignition::physics::FreeGroupPtr;
-
- /// \brief A map between free group entity ids in the ECM
- /// to FreeGroup Entities in ign-physics, with velocity command feature.
- /// All FreeGroup on this map are casted for
- /// `WorldVelocityCommandFeatureList`.
- std::unordered_map
- entityWorldVelocityCommandMap;
-
- //////////////////////////////////////////////////
- // Meshes
-
- /// \brief Feature list for meshes.
- /// Include MinimumFeatureList so created collision can be automatically
- /// up-cast.
- using MeshFeatureList = ignition::physics::FeatureList< //
- CollisionFeatureList,
- ignition::physics::mesh::AttachMeshShapeFeature>;
-
- /// \brief Link type with meshes.
- using LinkMeshPtrType = physics::LinkPtr< //
- ignition::physics::FeaturePolicy3d,
- MeshFeatureList>;
-
- /// \brief A map between link entity ids in the ECM to Link Entities in
- /// ign-physics, with mesh feature.
- /// All links on this map are also in `entityLinkMap`. The difference is
- /// that here they've been casted for `MeshFeatureList`.
- std::unordered_map entityLinkMeshMap;
-
- //////////////////////////////////////////////////
- // Nested Models
-
- /// \brief Feature list to construct nested models
- using NestedModelFeatureList = ignition::physics::FeatureList<
- MinimumFeatureList,
- ignition::physics::sdf::ConstructSdfNestedModel>;
-
- /// \brief Model type with nested model feature.
- using ModelNestedModelPtrType =
- physics::ModelPtr;
-
- /// \brief World type with nested model feature.
- using WorldNestedModelPtrType =
- physics::WorldPtr;
-
- /// \brief A map between model entity ids in the ECM to Model Entities in
- /// ign-physics, with Nested Model feature.
- /// All models on this map are also in `entityModelMap`. The difference is
- /// that here they've been casted for `ConstructedSdfNestedModel`.
- std::unordered_map
- entityModelNestedModelMap;
-
- /// \brief A map between model entity ids in the ECM to World Entities in
- /// ign-physics, with Nested Model feature.
- /// All models on this map are also in `entityWorldMap`. The difference is
- /// that here they've been casted for `ConstructedSdfNestedModel`.
- std::unordered_map
- entityWorldNestedModelMap;
-
- /// \brief Boolean value that is true only the first call of Configure and
- /// PreUpdate.
- bool firstRun = true;
-};
-
-Physics::Physics()
- : System()
- , pImpl(std::make_unique())
-{}
-
-void Physics::Configure(const Entity& _entity,
- const std::shared_ptr& _sdf,
- EntityComponentManager& _ecm,
- EventManager& /*_eventMgr*/)
-{
- std::string pluginLib;
-
- // 1. Engine from component (from command line / ServerConfig)
- auto engineComp =
- _ecm.Component(
- _entity);
- if (engineComp && !engineComp->Data().empty()) {
- pluginLib = engineComp->Data();
- }
- // 2. Engine from SDF
- else if (_sdf->HasElement("engine")) {
- auto sdfClone = _sdf->Clone();
- auto engineElem = sdfClone->GetElement("engine");
- pluginLib = engineElem->Get("filename", pluginLib).first;
- }
-
- // 3. Use DART by default
- if (pluginLib.empty()) {
- pluginLib = "ignition-physics-dartsim-plugin";
- }
-
- // Update component
- if (!engineComp) {
- _ecm.CreateComponent(_entity,
- components::PhysicsEnginePlugin(pluginLib));
- }
- else {
- engineComp->SetData(pluginLib,
- [](const std::string& _a, const std::string& _b) {
- return _a == _b;
- });
- }
-
- // Find engine shared library
- // Look in:
- // * Paths from environment variable
- // * Engines installed with ign-physics
- common::SystemPaths systemPaths;
- systemPaths.SetPluginPathEnv(pImpl->pluginPathEnv);
- systemPaths.AddPluginPaths({IGNITION_PHYSICS_ENGINE_INSTALL_DIR});
-
- auto pathToLib = systemPaths.FindSharedLibrary(pluginLib);
- if (pathToLib.empty()) {
- ignerr << "Failed to find plugin [" << pluginLib
- << "]. Have you checked the " << pImpl->pluginPathEnv
- << " environment variable?" << std::endl;
- return;
- }
-
- // Load engine plugin
- ignition::plugin::Loader pluginLoader;
- auto plugins = pluginLoader.LoadLib(pathToLib);
- if (plugins.empty()) {
- ignerr << "Unable to load the [" << pathToLib << "] library.\n";
- return;
- }
-
- auto classNames = pluginLoader.AllPlugins();
- if (classNames.empty()) {
- ignerr << "No plugins found in library [" << pathToLib << "]."
- << std::endl;
- return;
- }
-
- // Get the first plugin that works
- for (auto className : classNames) {
- auto plugin = pluginLoader.Instantiate(className);
-
- if (!plugin)
- continue;
-
- pImpl->engine = ignition::physics::RequestEngine<
- ignition::physics::FeaturePolicy3d,
- Impl::MinimumFeatureList>::From(plugin);
-
- if (nullptr != pImpl->engine) {
- igndbg << "Loaded [" << className << "] from library [" << pathToLib
- << "]" << std::endl;
- break;
- }
-
- auto missingFeatures = ignition::physics::RequestEngine<
- ignition::physics::FeaturePolicy3d,
- Impl::MinimumFeatureList>::MissingFeatureNames(plugin);
-
- std::stringstream msg;
- msg << "Plugin [" << className
- << "] misses required features:" << std::endl;
- for (auto feature : missingFeatures) {
- msg << "- " << feature << std::endl;
- }
- ignwarn << msg.str();
- }
-
- if (nullptr == pImpl->engine) {
- ignerr << "Failed to load a valid physics engine from [" << pathToLib
- << "]." << std::endl;
- }
-}
-
-Physics::~Physics() = default;
-
-void Physics::Update(const UpdateInfo& _info, EntityComponentManager& _ecm)
-{
- // \TODO(anyone) Support rewind
- if (_info.dt < std::chrono::steady_clock::duration::zero()) {
- ignwarn << "Detected jump back in time ["
- << std::chrono::duration_cast(_info.dt)
- .count()
- << "s]. System may not work properly." << std::endl;
- }
-
- // Update the component with the time in seconds that the simulation
- // will have after the step
- _ecm.Each(
- [&](const Entity& worldEntity,
- const components::World*,
- components::SimulatedTime*) {
- scenario::gazebo::utils::setExistingComponentData<
- ignition::gazebo::components::SimulatedTime>(
- &_ecm, worldEntity, _info.simTime);
- return true;
- });
-
- if (this->pImpl->engine) {
- this->pImpl->CreatePhysicsEntities(_ecm);
- this->pImpl->UpdatePhysics(_info, _ecm);
-
- // Only step if not paused.
- if (!_info.paused) {
- this->pImpl->Step(_info.dt);
- }
-
- this->pImpl->UpdateSim(_info, _ecm);
-
- // Entities scheduled to be removed should be removed from physics
- // after the simulation step. Otherwise, since the to-be-removed
- // entity still shows up in the ECM::Each the UpdatePhysics and
- // UpdateSim calls will have an error
- this->pImpl->RemovePhysicsEntities(_ecm);
- }
-}
-
-void Physics::Impl::CreatePhysicsEntities(const EntityComponentManager& _ecm)
-{
- auto processWorld = [&](const Entity& _entity,
- const components::World* /* _world */,
- const components::Name* _name,
- const components::Gravity* _gravity) -> bool {
- if (this->entityWorldMap.find(_entity) != this->entityWorldMap.end()) {
- ignwarn << "World entity [" << _entity
- << "] marked as new, but it's already on the map."
- << std::endl;
- return true;
- }
-
- sdf::World world;
- world.SetName(_name->Data());
- world.SetGravity(_gravity->Data());
- auto worldPtrPhys = this->engine->ConstructWorld(world);
- this->entityWorldMap.insert(std::make_pair(_entity, worldPtrPhys));
-
- return true;
- };
-
- auto processModel = [&](const Entity& _entity,
- const components::Model*,
- const components::Name* _name,
- const components::Pose* _pose,
- const components::ParentEntity* _parent) -> bool {
- // ignerr << "model " << _name->Data() << std::endl;
- // Check if model already exists
- if (this->entityModelMap.find(_entity) != this->entityModelMap.end()) {
- ignwarn << "Model entity [" << _entity
- << "] marked as new, but it's already on the map."
- << std::endl;
- return true;
- }
-
- // TODO(anyone) Don't load models unless they have collisions
-
- // Check if parent world / model exists
- sdf::Model model;
- model.SetName(_name->Data());
- model.SetRawPose(_pose->Data());
-
- auto staticComp = _ecm.Component(_entity);
- if (staticComp && staticComp->Data()) {
- model.SetStatic(staticComp->Data());
- }
-
- auto selfCollideComp = _ecm.Component(_entity);
- if (selfCollideComp && selfCollideComp->Data()) {
- model.SetSelfCollide(selfCollideComp->Data());
- }
-
- // check if parent is a world
- auto worldIt = this->entityWorldMap.find(_parent->Data());
- if (worldIt != this->entityWorldMap.end()) {
- auto worldPtrPhys = worldIt->second;
-
- // Use the ConstructNestedModel feature for nested models
- if (model.ModelCount() > 0) {
- auto nestedModelFeature =
- entityCast(_parent->Data(),
- worldPtrPhys,
- this->entityWorldNestedModelMap);
- if (!nestedModelFeature) {
- static bool informed{false};
- if (!informed) {
- igndbg
- << "Attempting to construct nested models, but the "
- << "phyiscs engine doesn't support feature "
- << "[ConstructSdfNestedModelFeature]. "
- << "Nested model will be ignored." << std::endl;
- informed = true;
- }
- return true;
- }
- auto modelPtrPhys =
- nestedModelFeature->ConstructNestedModel(model);
- this->entityModelMap.insert(
- std::make_pair(_entity, modelPtrPhys));
- }
- else {
- auto modelPtrPhys = worldPtrPhys->ConstructModel(model);
- this->entityModelMap.insert(
- std::make_pair(_entity, modelPtrPhys));
- }
- }
- // check if parent is a model (nested model)
- else {
- auto parentIt = this->entityModelMap.find(_parent->Data());
- if (parentIt != this->entityModelMap.end()) {
- auto parentPtrPhys = parentIt->second;
-
- auto nestedModelFeature =
- entityCast(_parent->Data(),
- parentPtrPhys,
- this->entityModelNestedModelMap);
- if (!nestedModelFeature) {
- static bool informed{false};
- if (!informed) {
- igndbg
- << "Attempting to construct nested models, but the "
- << "physics engine doesn't support feature "
- << "[ConstructSdfNestedModelFeature]. "
- << "Nested model will be ignored." << std::endl;
- informed = true;
- }
- return true;
- }
-
- // override static property only if parent is static.
- auto parentStaticComp =
- _ecm.Component(_parent->Data());
- if (parentStaticComp && parentStaticComp->Data())
- model.SetStatic(true);
-
- auto modelPtrPhys =
- nestedModelFeature->ConstructNestedModel(model);
- if (modelPtrPhys) {
- this->entityModelMap.insert(
- std::make_pair(_entity, modelPtrPhys));
- }
- else {
- ignerr << "Model: '" << _name->Data() << "' not loaded. "
- << "Failed to create nested model." << std::endl;
- }
- }
- else {
- ignwarn << "Model's parent entity [" << _parent->Data()
- << "] not found on world / model map." << std::endl;
- return true;
- }
- }
-
- return true;
- };
-
- auto processLink = [&](const Entity& _entity,
- const components::Link* /* _link */,
- const components::Name* _name,
- const components::Pose* _pose,
- const components::ParentEntity* _parent) -> bool {
- // Check if link already exists
- if (this->entityLinkMap.find(_entity) != this->entityLinkMap.end()) {
- ignwarn << "Link entity [" << _entity
- << "] marked as new, but it's already on the map."
- << std::endl;
- return true;
- }
-
- // TODO(anyone) Don't load links unless they have collisions
-
- // Check if parent model exists
- if (this->entityModelMap.find(_parent->Data())
- == this->entityModelMap.end()) {
- ignwarn << "Link's parent entity [" << _parent->Data()
- << "] not found on model map." << std::endl;
- return true;
- }
- auto modelPtrPhys = this->entityModelMap.at(_parent->Data());
-
- sdf::Link link;
- link.SetName(_name->Data());
- link.SetRawPose(_pose->Data());
-
- // get link inertial
- auto inertial = _ecm.Component(_entity);
- if (inertial) {
- link.SetInertial(inertial->Data());
- }
-
- auto linkPtrPhys = modelPtrPhys->ConstructLink(link);
- this->entityLinkMap.insert(std::make_pair(_entity, linkPtrPhys));
- this->linkEntityMap.insert(std::make_pair(linkPtrPhys, _entity));
-
- return true;
- };
-
- auto processCollision =
- [&](const Entity& _entity,
- const components::Collision*,
- const components::Name* _name,
- const components::Pose* _pose,
- const components::Geometry* _geom,
- const components::CollisionElement* _collElement,
- const components::ParentEntity* _parent) -> bool {
- if (this->entityCollisionMap.find(_entity)
- != this->entityCollisionMap.end()) {
- ignwarn << "Collision entity [" << _entity
- << "] marked as new, but it's already on the map."
- << std::endl;
- return true;
- }
-
- // Check if parent link exists
- if (this->entityLinkMap.find(_parent->Data())
- == this->entityLinkMap.end()) {
- ignwarn << "Collision's parent entity [" << _parent->Data()
- << "] not found on link map." << std::endl;
- return true;
- }
- auto linkPtrPhys = this->entityLinkMap.at(_parent->Data());
-
- // Make a copy of the collision DOM so we can set its pose which has
- // been resolved and is now expressed w.r.t the parent link of the
- // collision.
- sdf::Collision collision = _collElement->Data();
- collision.SetRawPose(_pose->Data());
- collision.SetPoseRelativeTo("");
- auto collideBitmask = collision.Surface()->Contact()->CollideBitmask();
-
- ShapePtrType collisionPtrPhys;
- if (_geom->Data().Type() == sdf::GeometryType::MESH) {
- const sdf::Mesh* meshSdf = _geom->Data().MeshShape();
- if (nullptr == meshSdf) {
- ignwarn << "Mesh geometry for collision [" << _name->Data()
- << "] missing mesh shape." << std::endl;
- return true;
- }
-
- auto& meshManager = *ignition::common::MeshManager::Instance();
- auto fullPath = asFullPath(meshSdf->Uri(), meshSdf->FilePath());
- auto* mesh = meshManager.Load(fullPath);
- if (nullptr == mesh) {
- ignwarn << "Failed to load mesh from [" << fullPath << "]."
- << std::endl;
- return true;
- }
-
- auto linkMeshFeature = entityCast(
- _parent->Data(), linkPtrPhys, this->entityLinkMeshMap);
- if (!linkMeshFeature) {
- static bool informed{false};
- if (!informed) {
- igndbg
- << "Attempting to process mesh geometries, but the "
- << "physics engine doesn't support feature "
- << "[AttachMeshShapeFeature]. Meshes will be ignored."
- << std::endl;
- informed = true;
- }
- return true;
- }
-
- collisionPtrPhys = linkMeshFeature->AttachMeshShape(
- _name->Data(),
- *mesh,
- math::eigen3::convert(_pose->Data()),
- math::eigen3::convert(meshSdf->Scale()));
- }
- else {
- auto linkCollisionFeature = entityCast(
- _parent->Data(), linkPtrPhys, this->entityLinkCollisionMap);
- if (!linkCollisionFeature) {
- static bool informed{false};
- if (!informed) {
- igndbg
- << "Attempting to process collisions, but the physics "
- << "engine doesn't support feature "
- << "[ConstructSdfCollision]. Collisions will be "
- << "ignored." << std::endl;
- informed = true;
- }
- return true;
- }
-
- collisionPtrPhys =
- linkCollisionFeature->ConstructCollision(collision);
- }
- // Check that the physics engine has a filter mask feature
- // Set the collide_bitmask if it does
- auto filterMaskFeature =
- entityCast(_parent->Data(), collisionPtrPhys, entityShapeMaskMap);
- if (filterMaskFeature) {
- filterMaskFeature->SetCollisionFilterMask(collideBitmask);
- }
- else {
- static bool informed{false};
- if (!informed) {
- igndbg
- << "Attempting to set collision bitmasks, but the physics "
- << "engine doesn't support feature [CollisionFilterMask]. "
- << "Collision bitmasks will be ignored." << std::endl;
- informed = true;
- }
- }
-
- this->entityCollisionMap.insert(
- std::make_pair(_entity, collisionPtrPhys));
- this->collisionEntityMap.insert(
- std::make_pair(collisionPtrPhys, _entity));
- return true;
- };
-
- auto processJoint =
- [&](const Entity& _entity,
- const components::Joint* /* _joint */,
- const components::Name* _name,
- const components::JointType* _jointType,
- const components::Pose* _pose,
- const components::ThreadPitch* _threadPitch,
- const components::ParentEntity* _parentModel,
- const components::ParentLinkName* _parentLinkName,
- const components::ChildLinkName* _childLinkName) -> bool {
- // Check if joint already exists
- if (this->entityJointMap.find(_entity) != this->entityJointMap.end()) {
- ignwarn << "Joint entity [" << _entity
- << "] marked as new, but it's already on the map."
- << std::endl;
- return true;
- }
-
- // Check if parent model exists
- if (this->entityModelMap.find(_parentModel->Data())
- == this->entityModelMap.end()) {
- ignwarn << "Joint's parent entity [" << _parentModel->Data()
- << "] not found on model map." << std::endl;
- return true;
- }
- auto modelPtrPhys = this->entityModelMap.at(_parentModel->Data());
-
- auto modelJointFeature = entityCast(
- _parentModel->Data(), modelPtrPhys, this->entityModelJointMap);
- if (!modelJointFeature) {
- static bool informed{false};
- if (!informed) {
- igndbg << "Attempting to process joints, but the physics "
- << "engine doesn't support joint features. "
- << "Joints will be ignored." << std::endl;
- informed = true;
- }
-
- // Break Each call since no joints can be processed
- return false;
- }
-
- sdf::Joint joint;
- joint.SetName(_name->Data());
- joint.SetType(_jointType->Data());
- joint.SetRawPose(_pose->Data());
- joint.SetThreadPitch(_threadPitch->Data());
-
- joint.SetParentLinkName(_parentLinkName->Data());
- joint.SetChildLinkName(_childLinkName->Data());
-
- auto jointAxis = _ecm.Component(_entity);
- auto jointAxis2 = _ecm.Component(_entity);
-
- // Since we're making copies of the joint axes that were created
- // using `Model::Load`, frame semantics should work for resolving
- // their xyz axis
- if (jointAxis)
- joint.SetAxis(0, jointAxis->Data());
- if (jointAxis2)
- joint.SetAxis(1, jointAxis2->Data());
-
- // Use the parent link's parent model as the model of this joint
- auto jointPtrPhys = modelJointFeature->ConstructJoint(joint);
-
- if (jointPtrPhys.Valid()) {
- // Some joints may not be supported, so only add them to the map
- // if the physics entity is valid
- this->entityJointMap.insert(std::make_pair(_entity, jointPtrPhys));
- }
- return true;
- };
-
- auto processDetachableJoint =
- [&](const Entity& _entity,
- const components::DetachableJoint* _jointInfo) -> bool {
- if (_jointInfo->Data().jointType != "fixed") {
- ignerr << "Detachable joint type [" << _jointInfo->Data().jointType
- << "] is currently not supported" << std::endl;
- return true;
- }
- // Check if joint already exists
- if (this->entityJointMap.find(_entity) != this->entityJointMap.end()) {
- ignwarn << "Joint entity [" << _entity
- << "] marked as new, but it's already on the map."
- << std::endl;
- return true;
- }
-
- // Check if the link entities exist in the physics engine
- auto parentLinkPhysIt =
- this->entityLinkMap.find(_jointInfo->Data().parentLink);
- if (parentLinkPhysIt == this->entityLinkMap.end()) {
- ignwarn << "DetachableJoint's parent link entity ["
- << _jointInfo->Data().parentLink
- << "] not found in link map." << std::endl;
- return true;
- }
-
- auto childLinkEntity = _jointInfo->Data().childLink;
-
- // Get child link
- auto childLinkIt = this->entityLinkMap.find(childLinkEntity);
- if (childLinkIt == this->entityLinkMap.end()) {
- ignwarn << "Failed to find joint's child link [" << childLinkEntity
- << "]." << std::endl;
- return true;
- }
-
- auto childLinkDetachableJointFeature =
- entityCast(childLinkEntity,
- childLinkIt->second,
- this->entityLinkDetachableJointMap);
- if (!childLinkDetachableJointFeature) {
- static bool informed{false};
- if (!informed) {
- igndbg
- << "Attempting to create a detachable joint, but the "
- "physics"
- << " engine doesn't support feature "
- << "[AttachFixedJointFeature]. Detachable joints will be "
- << "ignored." << std::endl;
- informed = true;
- }
-
- // Break Each call since no DetachableJoints can be processed
- return false;
- }
-
- const auto poseParent =
- parentLinkPhysIt->second->FrameDataRelativeToWorld().pose;
- const auto poseChild =
- childLinkDetachableJointFeature->FrameDataRelativeToWorld().pose;
-
- // Pose of child relative to parent
- auto poseParentChild = poseParent.inverse() * poseChild;
- auto jointPtrPhys = childLinkDetachableJointFeature->AttachFixedJoint(
- parentLinkPhysIt->second);
- if (jointPtrPhys.Valid()) {
- // We let the joint be at the origin of the child link.
- jointPtrPhys->SetTransformFromParent(poseParentChild);
-
- igndbg << "Creating detachable joint [" << _entity << "]"
- << std::endl;
- this->entityJointMap.insert(std::make_pair(_entity, jointPtrPhys));
- }
- else {
- ignwarn << "DetachableJoint could not be created." << std::endl;
- }
- return true;
- };
-
- if (this->firstRun) {
- this->firstRun = false;
-
- _ecm.Each(
- processWorld);
-
- _ecm.Each(processModel);
-
- _ecm.Each(processLink);
-
- // We don't need to add visuals to the physics engine.
-
- _ecm.Each(processCollision);
-
- _ecm.Each(processJoint);
-
- _ecm.Each(
- [&](const Entity& _entity, const components::BatterySoC*) -> bool {
- // Parent entity of battery is model entity
- this->entityOffMap.insert(
- std::make_pair(_ecm.ParentEntity(_entity), false));
- return true;
- });
-
- _ecm.Each(processDetachableJoint);
- }
- else {
- _ecm.EachNew(
- processWorld);
-
- _ecm.EachNew(processModel);
-
- _ecm.EachNew(processLink);
-
- // We don't need to add visuals to the physics engine.
-
- _ecm.EachNew(processCollision);
-
- _ecm.EachNew(processJoint);
-
- _ecm.EachNew(
- [&](const Entity& _entity, const components::BatterySoC*) -> bool {
- // Parent entity of battery is model entity
- this->entityOffMap.insert(
- std::make_pair(_ecm.ParentEntity(_entity), false));
- return true;
- });
-
- _ecm.EachNew(processDetachableJoint);
- }
-}
-
-void Physics::Impl::RemovePhysicsEntities(const EntityComponentManager& _ecm)
-{
- // Assume the world will not be erased
- // Only removing models is supported by ign-physics right now so we only
- // remove links, joints and collisions if they are children of the
- // removed model. We assume the links, joints and collisions will be
- // removed from the physics engine when the containing model gets
- // removed so, here, we only remove the entities from the gazebo
- // entity->physics entity map.
- _ecm.EachRemoved([&](const Entity& _entity,
- const components::Model*
- /* _model */) -> bool {
- // Remove model if found
- auto modelIt = this->entityModelMap.find(_entity);
- if (modelIt != this->entityModelMap.end()) {
- // Remove child links, collisions and joints first
- for (const auto& childLink :
- _ecm.ChildrenByComponents(_entity, components::Link())) {
- for (const auto& childCollision : _ecm.ChildrenByComponents(
- childLink, components::Collision())) {
- auto collIt = this->entityCollisionMap.find(childCollision);
- if (collIt != this->entityCollisionMap.end()) {
- this->collisionEntityMap.erase(collIt->second);
- this->entityCollisionMap.erase(collIt);
- }
- }
- // First erase the entry associated with this link from the
- // linkEntityMap which is the reverse of entityLinkMap
- auto linkPhysIt = this->entityLinkMap.find(childLink);
- if (linkPhysIt != this->entityLinkMap.end()) {
- this->linkEntityMap.erase(linkPhysIt->second);
- }
- this->entityLinkMap.erase(childLink);
- }
-
- for (const auto& childJoint :
- _ecm.ChildrenByComponents(_entity, components::Joint())) {
- this->entityJointMap.erase(childJoint);
- }
-
- // Remove the model from the physics engine
- modelIt->second->Remove();
- this->entityModelMap.erase(_entity);
- }
- return true;
- });
-
- _ecm.EachRemoved(
- [&](const Entity& _entity, const components::DetachableJoint*) -> bool {
- auto jointIt = this->entityJointMap.find(_entity);
- if (jointIt == this->entityJointMap.end()) {
- ignwarn << "Failed to find joint [" << _entity << "]."
- << std::endl;
- return true;
- }
-
- auto castEntity = entityCast(
- _entity, jointIt->second, this->entityJointDetachableJointMap);
- if (!castEntity) {
- static bool informed{false};
- if (!informed) {
- igndbg << "Attempting to detach a joint, but the physics "
- << "engine doesn't support feature "
- << "[DetachJointFeature]. Joint won't be detached."
- << std::endl;
- informed = true;
- }
-
- // Break Each call since no DetachableJoints can be processed
- return false;
- }
-
- igndbg << "Detaching joint [" << _entity << "]" << std::endl;
- castEntity->Detach();
- return true;
- });
-}
-
-void Physics::Impl::UpdatePhysics(const ignition::gazebo::UpdateInfo& _info,
- EntityComponentManager& _ecm)
-{
- // Battery state
- _ecm.Each(
- [&](const Entity& _entity, const components::BatterySoC* _bat) {
- if (_bat->Data() <= 0)
- entityOffMap[_ecm.ParentEntity(_entity)] = true;
- else
- entityOffMap[_ecm.ParentEntity(_entity)] = false;
- return true;
- });
-
- // Handle joint state
- _ecm.Each([&](const Entity& _entity,
- const components::Joint*,
- const components::Name*
- _name) {
- auto jointIt = this->entityJointMap.find(_entity);
- if (jointIt == this->entityJointMap.end())
- return true;
-
- // Model is out of battery
- if (this->entityOffMap[_ecm.ParentEntity(_entity)]) {
- std::size_t nDofs = jointIt->second->GetDegreesOfFreedom();
- for (std::size_t i = 0; i < nDofs; ++i) {
- jointIt->second->SetForce(i, 0);
- }
- return true;
- }
-
- auto posReset = _ecm.Component(_entity);
- auto velReset = _ecm.Component(_entity);
-
- // Reset the velocity
- if (velReset) {
- auto& jointVelocity = velReset->Data();
-
- if (jointVelocity.size()
- != jointIt->second->GetDegreesOfFreedom()) {
- ignwarn
- << "There is a mismatch in the degrees of freedom "
- "between "
- << "Joint [" << _name->Data() << "(Entity=" << _entity
- << ")] and its JointVelocityReset component. The joint has "
- << jointIt->second->GetDegreesOfFreedom() << " while the "
- << " component has " << jointVelocity.size() << ".\n";
- }
-
- std::size_t nDofs = std::min(
- jointVelocity.size(), jointIt->second->GetDegreesOfFreedom());
-
- for (std::size_t i = 0; i < nDofs; ++i) {
- jointIt->second->SetVelocity(i, jointVelocity[i]);
- }
- }
-
- // Reset the position
- if (posReset) {
- auto& jointPosition = posReset->Data();
-
- if (jointPosition.size()
- != jointIt->second->GetDegreesOfFreedom()) {
- ignwarn
- << "There is a mismatch in the degrees of freedom "
- "between "
- << "Joint [" << _name->Data() << "(Entity=" << _entity
- << ")] and its JointPositionReset component. The joint has "
- << jointIt->second->GetDegreesOfFreedom() << " while the "
- << " component has " << jointPosition.size() << ".\n";
- }
- std::size_t nDofs = std::min(
- jointPosition.size(), jointIt->second->GetDegreesOfFreedom());
- for (std::size_t i = 0; i < nDofs; ++i) {
- jointIt->second->SetPosition(i, jointPosition[i]);
- }
- }
-
- auto force = _ecm.Component(_entity);
- auto velCmd = _ecm.Component(_entity);
-
- if (force) {
- if (force->Data().size()
- != jointIt->second->GetDegreesOfFreedom()) {
- ignwarn << "There is a mismatch in the degrees of freedom "
- "between "
- << "Joint [" << _name->Data() << "(Entity=" << _entity
- << ")] and its JointForceCmd component. The joint has "
- << jointIt->second->GetDegreesOfFreedom()
- << " while the "
- << " component has " << force->Data().size() << ".\n";
- }
- std::size_t nDofs = std::min(
- force->Data().size(), jointIt->second->GetDegreesOfFreedom());
- for (std::size_t i = 0; i < nDofs; ++i) {
- jointIt->second->SetForce(i, force->Data()[i]);
- }
- }
- else {
- // Only set joint velocity if joint force is not set.
- // If both the cmd and reset components are found, cmd is
- // ignored.
- if (velCmd) {
- auto velocityCmd = velCmd->Data();
-
- if (velReset) {
- ignwarn << "Found both JointVelocityReset and "
- << "JointVelocityCmd components "
- << "for Joint [" << _name->Data()
- << "(Entity=" << _entity
- << "]). Ignoring JointVelocityReset component."
- << std::endl;
- return true;
- }
-
- if (velocityCmd.size()
- != jointIt->second->GetDegreesOfFreedom()) {
- ignwarn << "There is a mismatch in the degrees of freedom "
- << "between Joint [" << _name->Data()
- << "(Entity=" << _entity
- << ")] and its JointVelocityCmd component. The "
- << "joint has "
- << jointIt->second->GetDegreesOfFreedom()
- << " while the component has " << velocityCmd.size()
- << ".\n";
- }
-
- auto jointVelFeature =
- entityCast(_entity,
- jointIt->second,
- this->entityJointVelocityCommandMap);
- if (!jointVelFeature) {
- return true;
- }
-
- std::size_t nDofs = std::min(
- velocityCmd.size(), jointIt->second->GetDegreesOfFreedom());
-
- for (std::size_t i = 0; i < nDofs; ++i) {
- jointVelFeature->SetVelocityCommand(i, velocityCmd[i]);
- }
- }
- }
- return true;
- });
-
- // Link wrenches
- _ecm.Each(
- [&](const Entity& _entity,
- const components::ExternalWorldWrenchCmd* _wrenchComp) {
- auto linkIt = this->entityLinkMap.find(_entity);
- if (linkIt == this->entityLinkMap.end()) {
- ignwarn << "Failed to find link [" << _entity << "]."
- << std::endl;
- return true;
- }
-
- auto linkForceFeature =
- entityCast(_entity, linkIt->second, this->entityLinkForceMap);
- if (!linkForceFeature) {
- static bool informed{false};
- if (!informed) {
- igndbg << "Attempting to apply a wrench, but the physics "
- << "engine doesn't support feature "
- << "[AddLinkExternalForceTorque]. Wrench will be "
- "ignored."
- << std::endl;
- informed = true;
- }
-
- // Break Each call since no ExternalWorldWrenchCmd's can be
- // processed
- return false;
- }
-
- math::Vector3 force = msgs::Convert(_wrenchComp->Data().force());
- math::Vector3 torque = msgs::Convert(_wrenchComp->Data().torque());
- linkForceFeature->AddExternalForce(math::eigen3::convert(force));
- linkForceFeature->AddExternalTorque(math::eigen3::convert(torque));
-
- return true;
- });
-
- // Link wrenches with duration
- if (!_info.paused) {
- _ecm.Each(
- [&](const Entity& _entity,
- components::ExternalWorldWrenchCmdWithDuration*
- _wrenchWithDurComp) {
- auto linkIt = this->entityLinkMap.find(_entity);
- if (linkIt == this->entityLinkMap.end()) {
- ignwarn << "Failed to find link [" << _entity << "]."
- << std::endl;
- return true;
- }
-
- auto linkForceFeature = entityCast(
- _entity, linkIt->second, this->entityLinkForceMap);
- if (!linkForceFeature) {
- static bool informed{false};
- if (!informed) {
- igndbg
- << "Attempting to apply a wrench, but the physics "
- << "engine doesn't support feature "
- << "[AddLinkExternalForceTorque]. Wrench will be "
- "ignored."
- << std::endl;
- informed = true;
- }
-
- // Break Each call since no ExternalWorldWrenchCmd's can be
- // processed
- return false;
- }
-
- const auto& totalWrench =
- _wrenchWithDurComp->Data().totalWrench();
- const math::Vector3 force = msgs::Convert(totalWrench.force());
- const math::Vector3 torque =
- msgs::Convert(totalWrench.torque());
-
- linkForceFeature->AddExternalForce(
- math::eigen3::convert(force));
- linkForceFeature->AddExternalTorque(
- math::eigen3::convert(torque));
-
- // NOTE: Cleaning could be moved to UpdateSim, but let's
- // keep things all together for now
- auto simTimeAfterStep = _info.simTime;
- _wrenchWithDurComp->Data().cleanExpired(simTimeAfterStep);
-
- return true;
- });
- }
-
- // Update model pose
- _ecm.Each(
- [&](const Entity& _entity,
- const components::Model*,
- const components::WorldPoseCmd* _poseCmd) {
- auto modelIt = this->entityModelMap.find(_entity);
- if (modelIt == this->entityModelMap.end())
- return true;
-
- // world pose cmd currently not supported for nested models
- if (_entity != topLevelModel(_entity, _ecm)) {
- ignerr << "Unable to set world pose for nested models."
- << std::endl;
- return true;
- }
-
- // The canonical link as specified by sdformat is different from
- // the canonical link of the FreeGroup object
-
- // TODO(addisu) Store the free group instead of searching for it
- // at every iteration
- auto freeGroup = modelIt->second->FindFreeGroup();
- if (!freeGroup)
- return true;
-
- // Get canonical link offset
- auto linkEntityIt =
- this->linkEntityMap.find(freeGroup->CanonicalLink());
- if (linkEntityIt == this->linkEntityMap.end())
- return true;
-
- // set world pose of canonical link in freegroup
- // canonical link might be in a nested model so use RelativePose to
- // get its pose relative to this model
- math::Pose3d linkPose =
- this->RelativePose(_entity, linkEntityIt->second, _ecm);
-
- freeGroup->SetWorldPose(
- math::eigen3::convert(_poseCmd->Data() * linkPose));
-
- // Process pose commands for static models here, as one-time
- // changes
- const components::Static* staticComp =
- _ecm.Component(_entity);
- if (staticComp && staticComp->Data()) {
- auto worldPoseComp = _ecm.Component(_entity);
- if (worldPoseComp) {
- auto state =
- worldPoseComp->SetData(_poseCmd->Data(), this->pose3Eql)
- ? ComponentState::OneTimeChange
- : ComponentState::NoChange;
- _ecm.SetChanged(_entity, components::Pose::typeId, state);
- }
- }
-
- return true;
- });
-
- // Slip compliance on Collisions
- _ecm.Each(
- [&](const Entity& _entity,
- const components::SlipComplianceCmd* _slipCmdComp) {
- auto shapeIt = this->entityCollisionMap.find(_entity);
- if (shapeIt == this->entityCollisionMap.end()) {
- ignwarn << "Failed to find shape [" << _entity << "]."
- << std::endl;
- return true;
- }
-
- auto slipComplianceShape = entityCast(
- _entity, shapeIt->second, this->entityShapeSlipParamMap);
-
- if (!slipComplianceShape) {
- ignwarn << "Can't process Wheel Slip component, physics engine "
- << "missing SetShapeFrictionPyramidSlipCompliance"
- << std::endl;
-
- // Break Each call since no SlipCompliances can be processed
- return false;
- }
-
- if (_slipCmdComp->Data().size() == 2) {
- slipComplianceShape->SetPrimarySlipCompliance(
- _slipCmdComp->Data()[0]);
- slipComplianceShape->SetSecondarySlipCompliance(
- _slipCmdComp->Data()[1]);
- }
-
- return true;
- });
-
- // Update model angular velocity
- _ecm.Each(
- [&](const Entity& _entity,
- const components::Model*,
- const components::AngularVelocityCmd* _angularVelocityCmd) {
- auto modelIt = this->entityModelMap.find(_entity);
- if (modelIt == this->entityModelMap.end())
- return true;
-
- // angular vel cmd currently not supported for nested models
- if (_entity != topLevelModel(_entity, _ecm)) {
- ignerr << "Unable to set angular velocity for nested models."
- << std::endl;
- return true;
- }
-
- auto freeGroup = modelIt->second->FindFreeGroup();
- if (!freeGroup)
- return true;
-
- const components::Pose* poseComp =
- _ecm.Component(_entity);
- math::Vector3d worldAngularVel =
- poseComp->Data().Rot() * _angularVelocityCmd->Data();
-
- auto worldAngularVelFeature = entityCast(
- _entity, freeGroup, this->entityWorldVelocityCommandMap);
- if (!worldAngularVelFeature) {
- static bool informed{false};
- if (!informed) {
- igndbg
- << "Attempting to set model angular velocity, but the "
- << "physics engine doesn't support velocity commands. "
- << "Velocity won't be set." << std::endl;
- informed = true;
- }
- return true;
- }
-
- worldAngularVelFeature->SetWorldAngularVelocity(
- math::eigen3::convert(worldAngularVel));
-
- return true;
- });
-
- // Update model linear velocity
- _ecm.Each(
- [&](const Entity& _entity,
- const components::Model*,
- const components::LinearVelocityCmd* _linearVelocityCmd) {
- auto modelIt = this->entityModelMap.find(_entity);
- if (modelIt == this->entityModelMap.end())
- return true;
-
- // linear vel cmd currently not supported for nested models
- if (_entity != topLevelModel(_entity, _ecm)) {
- ignerr << "Unable to set linear velocity for nested models."
- << std::endl;
- return true;
- }
-
- auto freeGroup = modelIt->second->FindFreeGroup();
- if (!freeGroup)
- return true;
-
- const components::Pose* poseComp =
- _ecm.Component(_entity);
- math::Vector3d worldLinearVel =
- poseComp->Data().Rot() * _linearVelocityCmd->Data();
-
- auto worldLinearVelFeature = entityCast(
- _entity, freeGroup, this->entityWorldVelocityCommandMap);
- if (!worldLinearVelFeature) {
- static bool informed{false};
- if (!informed) {
- igndbg
- << "Attempting to set model linear velocity, but the "
- << "physics engine doesn't support velocity commands. "
- << "Velocity won't be set." << std::endl;
- informed = true;
- }
- return true;
- }
-
- worldLinearVelFeature->SetWorldLinearVelocity(
- math::eigen3::convert(worldLinearVel));
-
- return true;
- });
-
- // Process WorldVelocityCmd
- _ecm.Each(
- [&](const Entity& _entity,
- const components::Model*,
- components::WorldVelocityCmd* _modelWorldVelocityCmd) {
- auto modelIt = this->entityModelMap.find(_entity);
- if (modelIt == this->entityModelMap.end())
- return true;
-
- // The canonical link as specified by sdformat is different from
- // the canonical link of the FreeGroup object
-
- // TODO(addisu) Store the free group instead of searching for it
- // at every iteration
-
- // The FreeGroup is created only for floating-base object that
- // do not have any defined joint between the world and their
- // base
- auto freeGroup = modelIt->second->FindFreeGroup();
- if (!freeGroup) {
- ignwarn << "Failed to find FreeGroup. Linear and angular "
- "velocities commands ignored."
- << std::endl;
- return true;
- }
-
- ignition::math::Vector3d& modelWorldLinearVelocity =
- _modelWorldVelocityCmd->Data().linear;
- ignition::math::Vector3d& modelWorldAngularVelocity =
- _modelWorldVelocityCmd->Data().angular;
-
- freeGroup->SetWorldLinearVelocity(
- math::eigen3::convert(modelWorldLinearVelocity));
- freeGroup->SetWorldAngularVelocity(
- math::eigen3::convert(modelWorldAngularVelocity));
-
- // TODO(diego): static models from above
- return true;
- });
-
- // Clear pending commands
- // Note: Removing components from inside an Each call can be dangerous.
- // Instead, we collect all the entities that have the desired components
- // and remove the component from them afterward.
- std::vector entitiesWorldCmd;
- _ecm.Each(
- [&](const Entity& _entity, components::WorldPoseCmd*) -> bool {
- entitiesWorldCmd.push_back(_entity);
- return true;
- });
-
- for (const Entity& entity : entitiesWorldCmd) {
- _ecm.RemoveComponent(entity);
- }
-
- // Populate bounding box info
- // Only compute bounding box if component exists to avoid unnecessary
- // computations
- _ecm.Each([&](const Entity& _entity,
- const components::Model*,
- components::AxisAlignedBox*
- _bbox) {
- auto modelIt = this->entityModelMap.find(_entity);
- if (modelIt == this->entityModelMap.end()) {
- ignwarn << "Failed to find model [" << _entity << "]." << std::endl;
- return true;
- }
-
- auto bbModel = entityCast(
- _entity, modelIt->second, this->entityModelBoundingBoxMap);
- if (!bbModel) {
- static bool informed{false};
- if (!informed) {
- igndbg
- << "Attempting to get a bounding box, but the physics "
- << "engine doesn't support feature "
- << "[GetModelBoundingBox]. Bounding box won't be populated."
- << std::endl;
- informed = true;
- }
-
- // Break Each call since no AxisAlignedBox'es can be processed
- return false;
- }
-
- math::AxisAlignedBox bbox =
- math::eigen3::convert(bbModel->GetAxisAlignedBoundingBox());
- auto state = _bbox->SetData(bbox, this->axisAlignedBoxEql)
- ? ComponentState::OneTimeChange
- : ComponentState::NoChange;
- _ecm.SetChanged(_entity, components::AxisAlignedBox::typeId, state);
-
- return true;
- });
-
- // Clear WorldVelocityCmd
- entitiesWorldCmd.clear();
- _ecm.Each(
- [&](const Entity& _entity, components::WorldVelocityCmd*) -> bool {
- entitiesWorldCmd.push_back(_entity);
- return true;
- });
-
- for (const Entity& entity : entitiesWorldCmd) {
- _ecm.RemoveComponent(entity);
- }
-}
-
-void Physics::Impl::Step(const std::chrono::steady_clock::duration& _dt)
-{
- ignition::physics::ForwardStep::Input input;
- ignition::physics::ForwardStep::State state;
- ignition::physics::ForwardStep::Output output;
-
- input.Get() = _dt;
-
- for (auto& world : this->entityWorldMap) {
- world.second->Step(output, state, input);
- }
-}
-
-ignition::math::Pose3d
-Physics::Impl::RelativePose(const Entity& _from,
- const Entity& _to,
- const EntityComponentManager& _ecm) const
-{
- math::Pose3d transform;
-
- if (_from == _to)
- return transform;
-
- auto currentEntity = _to;
- auto parentComp = _ecm.Component(_to);
- while (parentComp) {
- auto parentEntity = parentComp->Data();
-
- // get the entity pose
- auto entityPoseComp = _ecm.Component(currentEntity);
-
- // update transform
- transform = entityPoseComp->Data() * transform;
-
- if (parentEntity == _from)
- break;
-
- // set current entity to parent
- currentEntity = parentEntity;
-
- // get entity's parent
- parentComp = _ecm.Component(parentEntity);
- }
-
- return transform;
-}
-
-void Physics::Impl::UpdateSim(const ignition::gazebo::UpdateInfo& _info,
- EntityComponentManager& _ecm)
-{
- // local pose
- _ecm.Each([&](const Entity& _entity,
- components::Link* /*_link*/,
- components::Pose* _pose,
- const components::ParentEntity*
- _parent) -> bool {
- // If parent is static, don't process pose changes as periodic
- const auto* staticComp =
- _ecm.Component(_parent->Data());
-
- if (staticComp && staticComp->Data())
- return true;
-
- auto linkIt = this->entityLinkMap.find(_entity);
- if (linkIt != this->entityLinkMap.end()) {
- // get top level model of this link
- auto topLevelModelEnt = topLevelModel(_parent->Data(), _ecm);
-
- auto canonicalLink =
- _ecm.Component(_entity);
-
- auto frameData = linkIt->second->FrameDataRelativeToWorld();
- const auto& worldPose = frameData.pose;
-
- if (canonicalLink) {
- // This is the canonical link, update the top level model.
- // The pose of this link w.r.t its top level model never
- // changes because it's "fixed" to the model. Instead, we
- // change the top level model's pose here. The physics
- // engine gives us the pose of this link relative to world
- // so to set the top level model's pose, we have to
- // post-multiply it by the inverse of the transform of the
- // link w.r.t to its top level model.
- math::Pose3d linkPoseFromTopLevelModel;
- linkPoseFromTopLevelModel =
- this->RelativePose(topLevelModelEnt, _entity, _ecm);
-
- // update top level model's pose
- auto mutableModelPose =
- _ecm.Component(topLevelModelEnt);
- *(mutableModelPose) =
- components::Pose(math::eigen3::convert(worldPose)
- * linkPoseFromTopLevelModel.Inverse());
-
- _ecm.SetChanged(topLevelModelEnt,
- components::Pose::typeId,
- ComponentState::PeriodicChange);
- }
- else {
- // Compute the relative pose of this link from the top level
- // model first get the world pose of the top level model
- auto worldComp =
- _ecm.Component(topLevelModelEnt);
- // if the worldComp is a nullptr, something is wrong with ECS
- if (!worldComp) {
- ignerr
- << "The parent component of " << topLevelModelEnt
- << " could not be found. This should never happen!\n";
- return true;
- }
- math::Pose3d parentWorldPose = this->RelativePose(
- worldComp->Data(), _parent->Data(), _ecm);
-
- // Unlike canonical links, pose of regular links can move
- // relative. to the parent. Same for links inside nested models.
- *_pose = components::Pose(math::eigen3::convert(worldPose)
- + parentWorldPose.Inverse());
- _ecm.SetChanged(_entity,
- components::Pose::typeId,
- ComponentState::PeriodicChange);
- }
-
- // Populate world poses, velocities and accelerations of the
- // link. For now these components are updated only if another
- // system has created the corresponding component on the entity.
- auto worldPoseComp = _ecm.Component(_entity);
- if (worldPoseComp) {
- auto state =
- worldPoseComp->SetData(
- math::eigen3::convert(frameData.pose), this->pose3Eql)
- ? ComponentState::PeriodicChange
- : ComponentState::NoChange;
- _ecm.SetChanged(_entity, components::WorldPose::typeId, state);
- }
-
- // Velocity in world coordinates
- auto worldLinVelComp =
- _ecm.Component(_entity);
- if (worldLinVelComp) {
- auto state =
- worldLinVelComp->SetData(
- math::eigen3::convert(frameData.linearVelocity),
- this->vec3Eql)
- ? ComponentState::PeriodicChange
- : ComponentState::NoChange;
- _ecm.SetChanged(
- _entity, components::WorldLinearVelocity::typeId, state);
- }
-
- // Angular velocity in world frame coordinates
- auto worldAngVelComp =
- _ecm.Component(_entity);
- if (worldAngVelComp) {
- auto state =
- worldAngVelComp->SetData(
- math::eigen3::convert(frameData.angularVelocity),
- this->vec3Eql)
- ? ComponentState::PeriodicChange
- : ComponentState::NoChange;
- _ecm.SetChanged(
- _entity, components::WorldAngularVelocity::typeId, state);
- }
-
- // Acceleration in world frame coordinates
- auto worldLinAccelComp =
- _ecm.Component(_entity);
- if (worldLinAccelComp) {
- auto state =
- worldLinAccelComp->SetData(
- math::eigen3::convert(frameData.linearAcceleration),
- this->vec3Eql)
- ? ComponentState::PeriodicChange
- : ComponentState::NoChange;
- _ecm.SetChanged(_entity,
- components::WorldLinearAcceleration::typeId,
- state);
- }
-
- // Angular acceleration in world frame coordinates
- auto worldAngAccelComp =
- _ecm.Component(_entity);
-
- if (worldAngAccelComp) {
- auto state =
- worldAngAccelComp->SetData(
- math::eigen3::convert(frameData.angularAcceleration),
- this->vec3Eql)
- ? ComponentState::PeriodicChange
- : ComponentState::NoChange;
- _ecm.SetChanged(_entity,
- components::WorldAngularAcceleration::typeId,
- state);
- }
-
- const Eigen::Matrix3d R_bs =
- worldPose.linear().transpose(); // NOLINT
-
- // Velocity in body-fixed frame coordinates
- auto bodyLinVelComp =
- _ecm.Component(_entity);
- if (bodyLinVelComp) {
- Eigen::Vector3d bodyLinVel = R_bs * frameData.linearVelocity;
- auto state =
- bodyLinVelComp->SetData(math::eigen3::convert(bodyLinVel),
- this->vec3Eql)
- ? ComponentState::PeriodicChange
- : ComponentState::NoChange;
- _ecm.SetChanged(
- _entity, components::LinearVelocity::typeId, state);
- }
-
- // Angular velocity in body-fixed frame coordinates
- auto bodyAngVelComp =
- _ecm.Component(_entity);
- if (bodyAngVelComp) {
- Eigen::Vector3d bodyAngVel = R_bs * frameData.angularVelocity;
- auto state =
- bodyAngVelComp->SetData(math::eigen3::convert(bodyAngVel),
- this->vec3Eql)
- ? ComponentState::PeriodicChange
- : ComponentState::NoChange;
- _ecm.SetChanged(
- _entity, components::AngularVelocity::typeId, state);
- }
-
- // Acceleration in body-fixed frame coordinates
- auto bodyLinAccelComp =
- _ecm.Component(_entity);
- if (bodyLinAccelComp) {
- Eigen::Vector3d bodyLinAccel =
- R_bs * frameData.linearAcceleration;
- auto state =
- bodyLinAccelComp->SetData(
- math::eigen3::convert(bodyLinAccel), this->vec3Eql)
- ? ComponentState::PeriodicChange
- : ComponentState::NoChange;
- _ecm.SetChanged(
- _entity, components::LinearAcceleration::typeId, state);
- }
-
- // Angular acceleration in world frame coordinates
- auto bodyAngAccelComp =
- _ecm.Component(_entity);
- if (bodyAngAccelComp) {
- Eigen::Vector3d bodyAngAccel =
- R_bs * frameData.angularAcceleration;
- auto state =
- bodyAngAccelComp->SetData(
- math::eigen3::convert(bodyAngAccel), this->vec3Eql)
- ? ComponentState::PeriodicChange
- : ComponentState::NoChange;
- _ecm.SetChanged(
- _entity, components::AngularAcceleration::typeId, state);
- }
- }
- return true;
- });
-
- // history of applied joint forces (commands)
- _ecm.Each([&](const Entity& _entity,
- components::Joint* /*_joint*/,
- components::Name* /*_name*/,
- components::JointForceCmd*
- _forceCmd) -> bool {
- // Get the data from the components
- auto jointForceCmdData = _forceCmd->Data();
-
- // If the history is enabled, append the force command also there
- auto historyComponent = _ecm.Component<
- ignition::gazebo::components::HistoryOfAppliedJointForces>(_entity);
-
- // Since the operation is an append, we have to perform it only when
- // the physics step is actually performed
- if (!_info.paused && historyComponent) {
- auto& history = scenario::gazebo::utils::getExistingComponentData<
- ignition::gazebo::components::HistoryOfAppliedJointForces>(
- &_ecm, _entity);
-
- for (const auto& jointForceCmd : jointForceCmdData) {
- history.push(jointForceCmd);
- }
- }
-
- return true;
- });
-
- // pose/velocity/acceleration of non-link entities such as sensors /
- // collisions. These get updated only if another system has created a
- // components::WorldPose component for the entity.
- // Populated components:
- // * WorldPose
- // * WorldLinearVelocity
- // * AngularVelocity
- // * LinearAcceleration
-
- // world pose
- _ecm.Each(
- [&](const Entity&,
- const components::Pose* _pose,
- components::WorldPose* _worldPose,
- const components::ParentEntity* _parent) -> bool {
- // check if parent entity is a link, e.g. entity is sensor /
- // collision
- auto linkIt = this->entityLinkMap.find(_parent->Data());
- if (linkIt != this->entityLinkMap.end()) {
- const auto entityFrameData =
- this->LinkFrameDataAtOffset(linkIt->second, _pose->Data());
-
- *_worldPose = components::WorldPose(
- math::eigen3::convert(entityFrameData.pose));
- }
-
- return true;
- });
-
- // world linear velocity
- _ecm.Each(
- [&](const Entity&,
- const components::Pose* _pose,
- components::WorldLinearVelocity* _worldLinearVel,
- const components::ParentEntity* _parent) -> bool {
- // check if parent entity is a link, e.g. entity is sensor /
- // collision
- auto linkIt = this->entityLinkMap.find(_parent->Data());
- if (linkIt != this->entityLinkMap.end()) {
- const auto entityFrameData =
- this->LinkFrameDataAtOffset(linkIt->second, _pose->Data());
-
- // set entity world linear velocity
- *_worldLinearVel = components::WorldLinearVelocity(
- math::eigen3::convert(entityFrameData.linearVelocity));
- }
-
- return true;
- });
-
- // body angular velocity
- _ecm.Each(
- [&](const Entity&,
- const components::Pose* _pose,
- components::AngularVelocity* _angularVel,
- const components::ParentEntity* _parent) -> bool {
- // check if parent entity is a link, e.g. entity is sensor /
- // collision
- auto linkIt = this->entityLinkMap.find(_parent->Data());
- if (linkIt != this->entityLinkMap.end()) {
- const auto entityFrameData =
- this->LinkFrameDataAtOffset(linkIt->second, _pose->Data());
-
- auto entityWorldPose =
- math::eigen3::convert(entityFrameData.pose);
- ignition::math::Vector3d entityWorldAngularVel =
- math::eigen3::convert(entityFrameData.angularVelocity);
-
- auto entityBodyAngularVel =
- entityWorldPose.Rot().RotateVectorReverse(
- entityWorldAngularVel);
- *_angularVel =
- components::AngularVelocity(entityBodyAngularVel);
- }
-
- return true;
- });
-
- // body linear acceleration
- _ecm.Each(
- [&](const Entity&,
- const components::Pose* _pose,
- components::LinearAcceleration* _linearAcc,
- const components::ParentEntity* _parent) -> bool {
- auto linkIt = this->entityLinkMap.find(_parent->Data());
- if (linkIt != this->entityLinkMap.end()) {
- const auto entityFrameData =
- this->LinkFrameDataAtOffset(linkIt->second, _pose->Data());
-
- auto entityWorldPose =
- math::eigen3::convert(entityFrameData.pose);
- ignition::math::Vector3d entityWorldLinearAcc =
- math::eigen3::convert(entityFrameData.linearAcceleration);
-
- auto entityBodyLinearAcc =
- entityWorldPose.Rot().RotateVectorReverse(
- entityWorldLinearAcc);
- *_linearAcc =
- components::LinearAcceleration(entityBodyLinearAcc);
- }
-
- return true;
- });
-
- // Clear reset components
- std::vector entitiesPositionReset;
- _ecm.Each(
- [&](const Entity& _entity, components::JointPositionReset*) -> bool {
- entitiesPositionReset.push_back(_entity);
- return true;
- });
-
- for (const auto entity : entitiesPositionReset) {
- _ecm.RemoveComponent(entity);
- }
-
- std::vector entitiesVelocityReset;
- _ecm.Each(
- [&](const Entity& _entity, components::JointVelocityReset*) -> bool {
- entitiesVelocityReset.push_back(_entity);
- return true;
- });
-
- for (const auto entity : entitiesVelocityReset) {
- _ecm.RemoveComponent(entity);
- }
-
- // Clear pending commands
- _ecm.Each(
- [&](const Entity&, components::JointForceCmd* _force) -> bool {
- std::fill(_force->Data().begin(), _force->Data().end(), 0.0);
- return true;
- });
-
- _ecm.Each(
- [&](const Entity&,
- components::ExternalWorldWrenchCmd* _wrench) -> bool {
- _wrench->Data().Clear();
- return true;
- });
-
- _ecm.Each(
- [&](const Entity&, components::JointVelocityCmd* _vel) -> bool {
- std::fill(_vel->Data().begin(), _vel->Data().end(), 0.0);
- return true;
- });
-
- _ecm.Each(
- [&](const Entity&, components::SlipComplianceCmd* _slip) -> bool {
- std::fill(_slip->Data().begin(), _slip->Data().end(), 0.0);
- return true;
- });
-
- // Update joint positions
- _ecm.Each(
- [&](const Entity& _entity,
- components::Joint*,
- components::JointPosition* _jointPos) -> bool {
- auto jointIt = this->entityJointMap.find(_entity);
- if (jointIt != this->entityJointMap.end()) {
- _jointPos->Data().resize(
- jointIt->second->GetDegreesOfFreedom());
- for (std::size_t i = 0;
- i < jointIt->second->GetDegreesOfFreedom();
- ++i) {
- _jointPos->Data()[i] = jointIt->second->GetPosition(i);
- }
- }
- return true;
- });
-
- // Update joint Velocities
- _ecm.Each(
- [&](const Entity& _entity,
- components::Joint*,
- components::JointVelocity* _jointVel) -> bool {
- auto jointIt = this->entityJointMap.find(_entity);
- if (jointIt != this->entityJointMap.end()) {
- _jointVel->Data().resize(
- jointIt->second->GetDegreesOfFreedom());
- for (std::size_t i = 0;
- i < jointIt->second->GetDegreesOfFreedom();
- ++i) {
- _jointVel->Data()[i] = jointIt->second->GetVelocity(i);
- }
- }
- return true;
- });
-
- // Update joint acceleration
- _ecm.Each(
- [&](const Entity& _entity,
- components::Joint*,
- components::JointAcceleration* _jointAcc) -> bool {
- auto jointIt = this->entityJointMap.find(_entity);
- if (jointIt != this->entityJointMap.end()) {
- _jointAcc->Data().resize(
- jointIt->second->GetDegreesOfFreedom());
- for (std::size_t i = 0;
- i < jointIt->second->GetDegreesOfFreedom();
- ++i) {
- _jointAcc->Data()[i] = jointIt->second->GetAcceleration(i);
- }
- }
- return true;
- });
-
- // Update joint forces
- _ecm.Each(
- [&](const Entity& _entity,
- components::Joint*,
- components::JointForce* _jointForce) -> bool {
- auto jointIt = this->entityJointMap.find(_entity);
- if (jointIt != this->entityJointMap.end()) {
- _jointForce->Data().resize(
- jointIt->second->GetDegreesOfFreedom());
- for (std::size_t i = 0;
- i < jointIt->second->GetDegreesOfFreedom();
- ++i) {
- _jointForce->Data()[i] = jointIt->second->GetForce(i);
- }
- }
- return true;
- });
-
- // TODO(louise) Skip this if there are no collision features
- this->UpdateCollisions(_ecm);
-}
-
-void Physics::Impl::UpdateCollisions(EntityComponentManager& _ecm)
-{
- // Quit early if the ContactData component hasn't been created. This
- // means there are no systems that need contact information
- if (!_ecm.HasComponentType(components::ContactSensorData::typeId))
- return;
-
- // TODO(addisu) If systems are assumed to only have one world, we should
- // capture the world Entity in a Configure call
- Entity worldEntity = _ecm.EntityByComponents(components::World());
-
- if (worldEntity == kNullEntity) {
- ignerr << "Missing world entity.\n";
- return;
- }
-
- auto worldIt = this->entityWorldMap.find(worldEntity);
- if (worldIt == this->entityWorldMap.end()) {
- ignwarn << "Failed to find world [" << worldEntity << "]." << std::endl;
- return;
- }
-
- auto worldCollisionFeature =
- entityCast(worldEntity, worldIt->second, this->entityWorldCollisionMap);
- if (!worldCollisionFeature) {
- static bool informed{false};
- if (!informed) {
- igndbg << "Attempting process contacts, but the physics "
- << "engine doesn't support collision features. "
- << "Contacts won't be computed." << std::endl;
- informed = true;
- }
- return;
- }
-
- // Struct containing pointer of contact data
- struct AllContactData
- {
- const WorldShapeType::ContactPoint* point;
- const WorldShapeType::ExtraContactData* extra;
- };
-
- // Each contact object we get from ign-physics contains the EntityPtrs
- // of the two colliding entities and other data about the contact such
- // as the position. This map groups contacts so that it is easy to query
- // all the contacts of one entity.
- using EntityContactMap =
- std::unordered_map>;
-
- // This data structure is essentially a mapping between a pair of
- // entities and a list of pointers to their contact object. We use a map
- // inside a map to create msgs::Contact objects conveniently later on.
- std::unordered_map entityContactMap;
-
- // Note that we are temporarily storing pointers to elements in this
- // ("allContacts") container. Thus, we must make sure it doesn't get
- // destroyed until the end of this function.
- auto allContacts = worldCollisionFeature->GetContactsFromLastStep();
- for (const auto& contactComposite : allContacts) {
- // Get the RequireData
- const auto& contact =
- contactComposite.Get();
- auto coll1It = this->collisionEntityMap.find(contact.collision1);
- auto coll2It = this->collisionEntityMap.find(contact.collision2);
-
- // Check the ExpectData
- const auto* extraContactData =
- contactComposite.Query();
-
- if ((coll1It != this->collisionEntityMap.end())
- && (coll2It != this->collisionEntityMap.end())) {
-
- AllContactData allContactData;
- allContactData.point = &contact;
-
- if (extraContactData) {
- allContactData.extra = extraContactData;
- }
-
- // Note that the ExtraContactData is valid only when the first
- // collision is the first body. Quantities like the force and
- // the normal must be flipped in the second case.
- entityContactMap[coll1It->second][coll2It->second].push_back(
- allContactData);
- entityContactMap[coll2It->second][coll1It->second].push_back(
- allContactData);
- }
- }
-
- // Go through each collision entity that has a ContactData component and
- // set the component value to the list of contacts that correspond to
- // the collision entity
- _ecm.Each(
- [&](const Entity& _collEntity1,
- components::Collision*,
- components::ContactSensorData* _contacts) -> bool {
- if (entityContactMap.find(_collEntity1) == entityContactMap.end()) {
- // Clear the last contact data
- *_contacts = components::ContactSensorData();
- return true;
- }
-
- const auto& contactMap = entityContactMap[_collEntity1];
-
- msgs::Contacts contactsComp;
-
- for (const auto& [collEntity2, contactData] : contactMap) {
-
- msgs::Contact* contactMsg = contactsComp.add_contact();
- contactMsg->mutable_collision1()->set_id(_collEntity1);
- contactMsg->mutable_collision2()->set_id(collEntity2);
-
- for (const auto& contact : contactData) {
- auto* position = contactMsg->add_position();
- position->set_x(contact.point->point.x());
- position->set_y(contact.point->point.y());
- position->set_z(contact.point->point.z());
-
- if (contact.extra) {
- // Add the penetration depth
- contactMsg->add_depth(contact.extra->depth);
-
- // Get the name of the collisions
- auto collisionName1 =
- _ecm.Component(_collEntity1)
- ->Data();
- auto collisionName2 =
- _ecm.Component(collEntity2)
- ->Data();
-
- // Add the wrench (only the force component)
- auto* wrench = contactMsg->add_wrench();
- wrench->set_body_1_name(collisionName1);
- wrench->set_body_2_name(collisionName2);
- auto* wrench1 = wrench->mutable_body_1_wrench();
- auto* wrench2 = wrench->mutable_body_2_wrench();
-
- auto* force1 = wrench1->mutable_force();
- auto* force2 = wrench2->mutable_force();
- auto* torque1 = wrench1->mutable_torque();
- auto* torque2 = wrench2->mutable_torque();
-
- // The same ContactPoint and ExtraContactData are
- // used for the contact between collision1 and
- // collision2. In those structures there is some
- // data, like the force and normal, that cannot
- // commute.
- if (_collEntity1
- == this->collisionEntityMap.at(
- contact.point->collision1)) {
- assert(collEntity2
- == this->collisionEntityMap.at(
- contact.point->collision2));
- // Use the data as it is
- *force1 = msgs::Convert(
- math::eigen3::convert(contact.extra->force));
- *force2 = msgs::Convert(
- -math::eigen3::convert(contact.extra->force));
- // Add the wrench normal
- auto* normal = contactMsg->add_normal();
- normal->set_x(contact.extra->normal.x());
- normal->set_y(contact.extra->normal.y());
- normal->set_z(contact.extra->normal.z());
- }
- else {
- assert(collEntity2
- == this->collisionEntityMap.at(
- contact.point->collision1));
- // Flip the force
- *force1 = msgs::Convert(
- -math::eigen3::convert(contact.extra->force));
- *force2 = msgs::Convert(
- math::eigen3::convert(contact.extra->force));
- // Flip the normal
- auto* normal = contactMsg->add_normal();
- normal->set_x(-contact.extra->normal.x());
- normal->set_y(-contact.extra->normal.y());
- normal->set_z(-contact.extra->normal.z());
- }
-
- *torque1 = msgs::Convert(math::Vector3d::Zero);
- *torque2 = msgs::Convert(math::Vector3d::Zero);
- }
- }
- }
- *_contacts = components::ContactSensorData(contactsComp);
-
- return true;
- });
-}
-
-physics::FrameData3d
-Physics::Impl::LinkFrameDataAtOffset(const LinkPtrType& _link,
- const math::Pose3d& _pose) const
-{
- physics::FrameData3d parent;
- parent.pose = math::eigen3::convert(_pose);
- physics::RelativeFrameData3d relFrameData(_link->GetFrameID(), parent);
- return this->engine->Resolve(relFrameData, physics::FrameID::World());
-}
-
-IGNITION_ADD_PLUGIN(Physics,
- ignition::gazebo::System,
- Physics::ISystemConfigure,
- Physics::ISystemUpdate)
-IGNITION_ADD_PLUGIN_ALIAS(Physics, "ignition::gazebo::systems::Physics")
diff --git a/cpp/scenario/plugins/Physics/Physics.h b/cpp/scenario/plugins/Physics/Physics.h
deleted file mode 100644
index 39d8612aa..000000000
--- a/cpp/scenario/plugins/Physics/Physics.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2020 Open Source Robotics Foundation
- * All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SCENARIO_PLUGINS_GAZEBO_PHYSICS
-#define SCENARIO_PLUGINS_GAZEBO_PHYSICS
-
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-// Features need to be defined ahead of entityCast
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include