Skip to content

Commit

Permalink
Initial pybind11 Controller Wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
krypton36 committed Jul 26, 2021
1 parent a85a567 commit 6d45518
Show file tree
Hide file tree
Showing 13 changed files with 615 additions and 17 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ jobs:

strategy:
matrix:
type: [gcc_debug, gcc_release, clang, mbedtls]
type: [gcc_debug, gcc_release, clang, mbedtls, python_lib]

env:
BUILD_TYPE: ${{ matrix.type }}

Expand Down Expand Up @@ -82,7 +83,9 @@ jobs:
"gcc_release") GN_ARGS='is_debug=false';;
"clang") GN_ARGS='is_clang=true';;
"mbedtls") GN_ARGS='chip_crypto="mbedtls"';;
"python_lib") GN_ARGS='enable_rtti=true enable_pylib=true';;
*) echo >&2 "Unrecognized build type: ${BUILD_TYPE}"; exit 1;;
esac
scripts/build/gn_gen.sh --args="$GN_ARGS"
Expand Down
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,7 @@
path = third_party/mbed-os-posix-socket/repo
url = https://github.com/ARMmbed/mbed-os-posix-socket.git
branch = main
[submodule "third_party/pybind11/repo"]
path = third_party/pybind11/repo
url = ../../pybind/pybind11
branch = stable
7 changes: 7 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {
chip_enable_python_modules =
(current_os == "mac" || current_os == "linux") &&
(host_cpu == "x64" || host_cpu == "arm64")
enable_pylib = false
}

# Python packages for supporting specific targets.
Expand Down Expand Up @@ -112,6 +113,9 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {
deps += [ "${chip_root}/src/tools/chip-cert" ]
}
if (chip_enable_python_modules) {
if (enable_pylib) {
deps += [ "${chip_root}/src/pybindings/pycontroller" ]
}
deps += [ "${chip_root}/src/controller/python" ]
}
}
Expand All @@ -129,6 +133,9 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {
data_deps = [ "${chip_root}/examples/chip-tool" ]

if (chip_enable_python_modules) {
if (enable_pylib) {
data_deps += [ "${chip_root}/src/pybindings/pycontroller" ]
}
data_deps += [ "${chip_root}/src/controller/python" ]
}

Expand Down
11 changes: 10 additions & 1 deletion build/config/compiler/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,11 @@ config("sanitize_default") {
config("fuzzing_default") {
}

declare_args() {
# Enable Runtime Type Information (RTTI)
enable_rtti = false
}

config("no_rtti") {
cflags_cc = [ "-fno-rtti" ]
}
Expand All @@ -365,7 +370,11 @@ config("rtti") {
}

config("rtti_default") {
configs = [ ":no_rtti" ]
if (enable_rtti) {
configs = [ ":rtti" ]
} else {
configs = [ ":no_rtti" ]
}
}

config("no_exceptions") {
Expand Down
19 changes: 10 additions & 9 deletions integrations/docker/images/chip-build/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,9 @@ RUN set -x \
ninja-build \
openjdk-8-jdk \
pkg-config \
python3 \
python3-dev \
python3-pip \
python3-venv \
python3.9 \
python3.9-dev \
python3.9-venv \
rsync \
shellcheck \
strace \
Expand All @@ -74,14 +73,16 @@ RUN set -x \
&& exec bash \
&& : # last line

# Python 2 and PIP
# Python 3.9 and PIP
RUN set -x \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y libgirepository1.0-dev \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y software-properties-common \
&& add-apt-repository universe \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y python python2 \
&& curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py \
&& python2 get-pip.py \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y python3.9 python3.9-venv python3.9-dev\
&& curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py \
&& python3.9 get-pip.py \
&& update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1 \
&& rm -rf /var/lib/apt/lists/ \
&& : # last line

Expand Down
2 changes: 1 addition & 1 deletion integrations/docker/images/chip-build/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.31
0.5.0
29 changes: 24 additions & 5 deletions scripts/build_python.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ OUTPUT_ROOT="$CHIP_ROOT/out/python_lib"
ENVIRONMENT_ROOT="$CHIP_ROOT/out/python_env"

declare chip_detail_logging=false
declare enable_pybindings=false
declare chip_mdns
declare clusters=true

help() {

echo "Usage: $file_name [ options ... ] [ -chip_detail_logging ChipDetailLoggingValue ] [ -chip_mdns ChipMDNSValue ]"
echo "Usage: $file_name [ options ... ] [ -chip_detail_logging ChipDetailLoggingValue ] [ -chip_mdns ChipMDNSValue ] [-enable_pybindings EnableValue]"

echo "General Options:
-h, --help Display this information.
Expand All @@ -55,6 +56,7 @@ Input Options:
By default it is minimal.
-c, --clusters_for_ip_commissioning true/false Specify whether to use clusters for IP commissioning.
By default it is true.
-p, --enable_pybindings EnableValue Specify whether to enable pybindings as python controller.
"
}

Expand All @@ -78,6 +80,10 @@ while (($#)); do
clusters=$2
shift
;;
--enable_pybindings | -p)
enable_pybindings=$2
shift
;;
-*)
help
echo "Unknown Option \"$1\""
Expand All @@ -88,25 +94,38 @@ while (($#)); do
done

# Print input values
echo "Input values: chip_detail_logging = $chip_detail_logging , chip_mdns = \"$chip_mdns\""
echo "Input values: chip_detail_logging = $chip_detail_logging , chip_mdns = \"$chip_mdns\", enable_pybindings = $enable_pybindings"

# Ensure we have a compilation environment
source "$CHIP_ROOT/scripts/activate.sh"

# Generates ninja files
[[ -n "$chip_mdns" ]] && chip_mdns_arg="chip_mdns=\"$chip_mdns\"" || chip_mdns_arg=""
gn --root="$CHIP_ROOT" gen "$OUTPUT_ROOT" --args="chip_detail_logging=$chip_detail_logging chip_use_clusters_for_ip_commissioning=$clusters $chip_mdns_arg"

gn --root="$CHIP_ROOT" gen "$OUTPUT_ROOT" --args="chip_detail_logging=$chip_detail_logging enable_pylib=$enable_pybindings enable_rtti=$enable_pybindings chip_use_clusters_for_ip_commissioning=$clusters $chip_mdns_arg"

# Compiles python files
ninja -C "$OUTPUT_ROOT" python
# Check pybindings was requested
if [ "$enable_pybindings" == true ]; then
ninja -v -C "$OUTPUT_ROOT" pycontroller
else
ninja -v -C "$OUTPUT_ROOT" python
fi

# Create a virtual environment that has access to the built python tools
virtualenv --clear "$ENVIRONMENT_ROOT"

# Activate the new enviroment to register the python WHL

if [ "$enable_pybindings" == true ]; then
WHEEL=$(ls "$OUTPUT_ROOT"/pybindings/pycontroller/pychip-*.whl | head -n 1)
else
WHEEL=$(ls "$OUTPUT_ROOT"/controller/python/chip-*.whl | head -n 1)
fi

source "$ENVIRONMENT_ROOT"/bin/activate
"$ENVIRONMENT_ROOT"/bin/python -m pip install --upgrade pip
"$ENVIRONMENT_ROOT"/bin/pip install --upgrade --force-reinstall --no-cache-dir "$OUTPUT_ROOT"/controller/python/chip-*.whl
"$ENVIRONMENT_ROOT"/bin/pip install --upgrade --force-reinstall --no-cache-dir "$WHEEL"

echo ""
echo_green "Compilation completed and WHL package installed in: "
Expand Down
1 change: 1 addition & 0 deletions scripts/tools/zap_regen_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def getSpecificTemplatesTargets():
targets.append(['src/controller/data_model/controller-clusters.zap', '-t', 'src/app/common/templates/templates.json'])
targets.append(['src/controller/data_model/controller-clusters.zap', '-t', 'examples/chip-tool/templates/templates.json'])
targets.append(['src/controller/data_model/controller-clusters.zap', '-t', 'src/controller/python/templates/templates.json'])
targets.append(['src/controller/data_model/controller-clusters.zap', '-t', 'src/pybindings/pycontroller/templates/templates.json'])
targets.append(['src/controller/data_model/controller-clusters.zap', '-t', 'src/darwin/Framework/CHIP/templates/templates.json'])
targets.append(['src/controller/data_model/controller-clusters.zap', '-t', 'src/controller/java/templates/templates.json'])
return targets
Expand Down
185 changes: 185 additions & 0 deletions src/pybindings/pycontroller/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# Copyright (c) 2021 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build_overrides/build.gni")
import("//build_overrides/chip.gni")
import("//build_overrides/pigweed.gni")

import("$dir_pw_build/python.gni")

import("${chip_root}/build/chip/tools.gni")
import("${chip_root}/src/platform/device.gni")
import("${dir_pw_unit_test}/test.gni")

if (current_os == "mac") {
import("${build_root}/config/mac/mac_sdk.gni")
}

config("controller_wno_deprecate") {
cflags = [
"-Wno-deprecated-declarations",
"-Wno-shadow",
"-Wno-unused-result",
"-Wsign-compare",
"-Wunreachable-code",
"-Wno-macro-redefined",
]
}

shared_library("CHIPController") {
configs -= [ "//build/config/compiler:exceptions_default" ]

output_name = "PyChip"
output_dir = "${target_out_dir}/pychip"
include_dirs = [ "${chip_root}/third_party/pybind11/repo/include" ]
if (current_os == "mac") {
include_dirs +=
[ "${chip_root}/.environment/cipd/python/include/python3.8" ]
} else if (current_os == "linux") {
include_dirs += [ "/usr/include/python3.9" ]
} else {
assert(false, "OS not supprted.")
}

sources = [
"${root_gen_dir}/include/pybindings/pycontroller/CHIPErrorToExceptionBindings.cpp",
"${root_gen_dir}/include/pybindings/pycontroller/CHIPErrorToExceptionBindings.h",
"ControllerBindings/PyChip_Main.cpp",
]

public_deps = [
":build_exceptions",
"${chip_root}/src/app",
"${chip_root}/src/controller/data_model",
"${chip_root}/src/lib",
"${chip_root}/src/lib/core",
"${chip_root}/src/lib/mdns",
"${chip_root}/src/lib/support",
"${chip_root}/src/platform",
"${chip_root}/src/setup_payload",
"${chip_root}/src/transport",
]
configs += [ ":controller_wno_deprecate" ]
ldflags = [ "-frtti" ]
if (current_os == "mac") {
ldflags += [
"-undefined",
"dynamic_lookup",
]
}
if (current_os == "linux") {
libs = [ "python3.9" ]
}
}
pw_python_action("build_exceptions") {
script = "create_error_wrapper.py"

header_file = "${root_gen_dir}/include/pybindings/pycontroller/CHIPErrorToExceptionBindings.h"
cpp_file = "${root_gen_dir}/include/pybindings/pycontroller/CHIPErrorToExceptionBindings.cpp"
outputs = [
header_file,
cpp_file,
]

args = [
"--output_cpp_file=" + rebase_path(cpp_file, root_build_dir),
"--output_header_file=" + rebase_path(header_file, root_build_dir),
"--error_header=" +
rebase_path("${chip_root}/src/lib/core/CHIPError.h", root_build_dir),
"--config_header=" +
rebase_path("${chip_root}/src/lib/core/CHIPConfig.h", root_build_dir),
]
}

pw_python_action("pycontroller") {
script = "build-chip-wheel.py"

_py_manifest_files = [
{
src_dir = "."
sources = []
},
{
src_dir = target_out_dir
sources = [ "${target_out_dir}/pychip/PyChip.so" ]
},
{
src_dir = "//"
sources = [ "//LICENSE" ]
},
]

_py_manifest_file = "${target_gen_dir}/${target_name}.py_manifest.json"

inputs = [
"${root_gen_dir}/include/pybindings/pycontroller/CHIPErrorToExceptionBindings.cpp",
"${root_gen_dir}/include/pybindings/pycontroller/CHIPErrorToExceptionBindings.h",
]
_py_manifest_files_rebased = []
foreach(_manifest_entry, _py_manifest_files) {
inputs += _manifest_entry.sources
_py_manifest_files_rebased += [
{
src_dir = rebase_path(_manifest_entry.src_dir,
get_path_info(_py_manifest_file, "dir"))
sources = rebase_path(_manifest_entry.sources, _manifest_entry.src_dir)
},
]
}

_py_manifest = {
files = _py_manifest_files_rebased
}

write_file(_py_manifest_file, _py_manifest, "json")

_dist_dir = "${root_out_dir}/pybindings/pycontroller"

if (current_cpu == "x64") {
cpu_tag = "x86_64"
} else if (current_cpu == "arm64") {
cpu_tag = "aarch64"
} else {
cpu_tag = current_cpu
}

if (current_os == "mac") {
platform_tag = "macosx_" + string_replace(mac_deployment_target, ".", "_")
} else {
platform_tag = current_os
}

platform_tag = platform_tag + "_" + cpu_tag

tags = "cp37-" + platform_tag

args = [
"--package_name",
"pychip",
"--build_number",
"0.0",
"--build_dir",
rebase_path("${target_gen_dir}/${target_name}.py_build", root_build_dir),
"--dist_dir",
rebase_path(_dist_dir, root_build_dir),
"--manifest",
rebase_path(_py_manifest_file, root_build_dir),
"--plat-name",
platform_tag,
]

public_deps = [ ":CHIPController" ]

output_name = "pychip-0.0.dist-info-0.0-${tags}.whl"
outputs = [ "${_dist_dir}/$output_name" ]
}
Loading

0 comments on commit 6d45518

Please sign in to comment.