Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Tizen] Do not create flashbundle for non-TPK apps #20730

Merged
merged 2 commits into from
Jul 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/examples-tizen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,11 @@ jobs:
- name: Checkout submodules
run: scripts/checkout_submodules.py --shallow --platform tizen
- name: Build Tizen examples
run: scripts/run_in_build_env.sh "./scripts/build/build_examples.py --target-glob 'tizen-*' build"
run: |
./scripts/run_in_build_env.sh \
"./scripts/build/build_examples.py \
--enable-flashbundle \
--target-glob 'tizen-*' \
build \
--copy-artifacts-to out/artifacts \
"
5 changes: 4 additions & 1 deletion examples/all-clusters-app/tizen/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ executable("chip-all-clusters-app") {
}

tizen_sdk_package("chip-all-clusters-app:tpk") {
deps = [ ":chip-all-clusters-app" ]
deps = [
":chip-all-clusters-app",
"${chip_root}/examples/platform/tizen:author-certificate-CHIP",
]
manifest = "tizen-manifest.xml"
sign_security_profile = "CHIP"
}
Expand Down
5 changes: 4 additions & 1 deletion examples/all-clusters-minimal-app/tizen/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ executable("chip-all-clusters-minimal-app") {
}

tizen_sdk_package("chip-all-clusters-minimal-app:tpk") {
deps = [ ":chip-all-clusters-minimal-app" ]
deps = [
":chip-all-clusters-minimal-app",
"${chip_root}/examples/platform/tizen:author-certificate-CHIP",
]
manifest = "tizen-manifest.xml"
sign_security_profile = "CHIP"
}
Expand Down
5 changes: 4 additions & 1 deletion examples/lighting-app/tizen/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ executable("chip-lighting-app") {
}

tizen_sdk_package("chip-lighting-app:tpk") {
deps = [ ":chip-lighting-app" ]
deps = [
":chip-lighting-app",
"${chip_root}/examples/platform/tizen:author-certificate-CHIP",
]
manifest = "tizen-manifest.xml"
sign_security_profile = "CHIP"
}
Expand Down
11 changes: 11 additions & 0 deletions examples/platform/tizen/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@

import("//build_overrides/build.gni")
import("//build_overrides/chip.gni")
import("//build_overrides/tizen.gni")

import("${chip_root}/src/app/common_flags.gni")
import("${chip_root}/src/lib/core/core.gni")
import("${chip_root}/src/lib/lib.gni")

import("${build_root}/config/linux/pkg_config.gni")
import("${tizen_sdk_build_root}/tizen_sdk.gni")

config("config") {
include_dirs = [ "." ]
Expand All @@ -28,6 +31,14 @@ pkg_config("capi-appfw-service-application") {
packages = [ "capi-appfw-service-application" ]
}

tizen_sdk_certificate("author-certificate-CHIP") {
# Data for dummy author certificate.
author_certificate_name = "Matter Example"
author_certificate_email = "[email protected]"
author_certificate_password = "0123456789"
sign_security_profile = "CHIP"
}

source_set("app-main") {
sources = [
"OptionsProxy.cpp",
Expand Down
53 changes: 33 additions & 20 deletions scripts/build/builders/tizen.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from .gn import GnBuilder

App = namedtuple('App', ['name', 'source', 'outputs'])
Tool = namedtuple('Tool', ['name', 'source', 'outputs'])
Board = namedtuple('Board', ['target_cpu'])


Expand All @@ -36,21 +37,29 @@ class TizenApp(Enum):
'examples/all-clusters-minimal-app/tizen',
('chip-all-clusters-minimal-app',
'chip-all-clusters-minimal-app.map'))
CHIP_TOOL = App(
'chip-tool',
'examples/chip-tool',
('chip-tool',
'chip-tool.map'))
LIGHT = App(
'chip-lighting-app',
'examples/lighting-app/tizen',
('chip-lighting-app',
'chip-lighting-app.map'))

def PackageName(self):
CHIP_TOOL = Tool(
'chip-tool',
'examples/chip-tool',
('chip-tool',
'chip-tool.map'))

@property
def is_tpk(self):
"""If True, this app is a TPK."""
return isinstance(self.value, App)

@property
def package_name(self):
return self.manifest.get('package')

def PackageVersion(self):
@property
def package_version(self):
return self.manifest.get('version')

def parse_manifest(self, manifest: str):
Expand Down Expand Up @@ -82,15 +91,16 @@ def __init__(self,
self.board = board
self.extra_gn_options = []

try:
# Try to load Tizen application XML manifest. We have to use
# try/except here, because of TestBuilder test. This test runs
# in a fake build root /TEST/BUILD/ROOT which obviously does
# not have Tizen manifest file.
self.app.parse_manifest(
os.path.join(self.root, "tizen-manifest.xml"))
except FileNotFoundError:
pass
if self.app.is_tpk:
try:
# Try to load Tizen application XML manifest. We have to use
# try/except here, because of TestBuilder test. This test runs
# in a fake build root /TEST/BUILD/ROOT which obviously does
# not have Tizen manifest file.
self.app.parse_manifest(
os.path.join(self.root, "tizen-manifest.xml"))
except FileNotFoundError:
pass

if not enable_ble:
self.extra_gn_options.append('chip_config_network_layer_ble=false')
Expand All @@ -116,9 +126,10 @@ def GnBuildArgs(self):
]

def _generate_flashbundle(self):
logging.info('Packaging %s', self.output_dir)
cmd = ['ninja', '-C', self.output_dir, self.app.value.name + ':tpk']
self._Execute(cmd, title='Packaging ' + self.identifier)
if self.app.is_tpk:
logging.info('Packaging %s', self.output_dir)
cmd = ['ninja', '-C', self.output_dir, self.app.value.name + ':tpk']
self._Execute(cmd, title='Packaging ' + self.identifier)

def build_outputs(self):
return {
Expand All @@ -127,7 +138,9 @@ def build_outputs(self):
}

def flashbundle(self):
tpk = f'{self.app.PackageName()}-{self.app.PackageVersion()}.tpk'
if not self.app.is_tpk:
return {}
tpk = f'{self.app.package_name}-{self.app.package_version}.tpk'
return {
tpk: os.path.join(self.output_dir, 'package', 'out', tpk),
}
141 changes: 141 additions & 0 deletions third_party/tizen/tizen_dev_certificate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#!/usr/bin/env python

# Copyright (c) 2022 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 argparse
import logging
import os
import subprocess
import sys

# Absolute path to Tizen Studio CLI tool.
tizen_sdk_root = os.environ["TIZEN_SDK_ROOT"]
tizen_cli = os.path.join(tizen_sdk_root, "tools", "ide", "bin", "tizen")

# Setup basic logging capabilities.
logging.basicConfig(level=logging.DEBUG)


def create_author_certificate(alias: str, password: str,
name: str = "", email: str = ""):
cmd = [tizen_cli, "certificate", "--alias", alias, "--password", password]
if name:
cmd.extend(["--name", name])
if email:
cmd.extend(["--email", email])
logging.debug("Execute: %s", " ".join(cmd))
with subprocess.Popen(cmd, stdout=subprocess.PIPE) as proc:
for line in proc.stdout.readlines():
line = line.decode().rstrip()
if line.startswith("Working path:"):
wd = line[len("Working path:"):].strip()
print(line)
return os.path.join(wd, "author.p12")


def check_security_profile(profile):

# XXX: If Tizen Studio SDK data directory was removed but the config file
# was not, Tizen Studio CLI does not create profiles XML file. This
# is a workaround to create a dummy XML profiles file so later Tizen
# will regenerate it with the correct content.

tizen_sdk_data_dir = None
with open(os.environ["TIZEN_SDK_ROOT"] + "/sdk.info") as f:
for line in f.readlines():
if line.startswith("TIZEN_SDK_DATA_PATH"):
tizen_sdk_data_dir = line.split("=")[1].strip()
break
if not tizen_sdk_data_dir:
logging.error("Cannot find Tizen SDK data directory")
return False

profiles_xml = os.path.join(tizen_sdk_data_dir, "profile", "profiles.xml")
if not os.path.exists(profiles_xml):
os.makedirs(os.path.dirname(profiles_xml), exist_ok=True)
with open(profiles_xml, "w") as f:
f.write('<profiles/>')

cmd = [tizen_cli, "security-profiles", "list", "--name", profile]
logging.debug("Execute: %s", " ".join(cmd))
with subprocess.Popen(cmd, stdout=subprocess.PIPE) as proc:
for line in proc.stdout.readlines():
line = line.decode().rstrip()
print(line)
return proc.wait() == 0


def add_security_profile(profile: str, certificate: str, password: str):
cmd = [tizen_cli, "security-profiles", "add", "--active",
"--name", profile, "--author", certificate, "--password", password]
logging.debug("Execute: %s", " ".join(cmd))
with subprocess.Popen(cmd, stdout=subprocess.PIPE) as proc:
for line in proc.stdout.readlines():
line = line.decode().rstrip()
print(line)
return proc.wait() == 0


def update_stamp_file(path: str, message: str):
if path:
with open(path, "w") as f:
f.write(message + "\n")


parser = argparse.ArgumentParser(
description="Setup Tizen Studio development security profile.")
parser.add_argument(
'--author-certificate-name', metavar='NAME',
help="Set author certificate 'name' field.")
parser.add_argument(
'--author-certificate-email', metavar='EMAIL',
help="Set author certificate 'email' field.")
parser.add_argument(
'--author-certificate-password', metavar='PASSWORD', required=True,
help="Password for author certificate.")
parser.add_argument(
'--sign-security-profile', metavar='NAME', required=True,
help="Name of the security profile to add.")
parser.add_argument(
'--stamp-file', metavar='FILE',
help="Update the stamp file upon success.")

args = parser.parse_args()

rv = check_security_profile(args.sign_security_profile)
if rv:
update_stamp_file(args.stamp_file, "Using existing security profile.")
logging.info("Security profile already exists")
sys.exit()

# Create author certificate if it does not exist. If the certificate already
# exists, it will be used. However, if the password is different, it will not
# be possible to use the certificate when updating the security profile.
cert = create_author_certificate("CHIP",
args.author_certificate_password,
args.author_certificate_name,
args.author_certificate_email)
if not cert:
logging.error("Failed to create author certificate")
sys.exit(1)

rv = add_security_profile(args.sign_security_profile, cert,
args.author_certificate_password)
if not rv:
logging.error("Failed to add security profile")
sys.exit(1)

update_stamp_file(args.stamp_file, "New security profile created.")
sys.exit()
55 changes: 49 additions & 6 deletions third_party/tizen/tizen_sdk.gni
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,17 @@ import("//build_overrides/tizen.gni")

import("${build_root}/config/tizen/config.gni")

tizen_dev_certificate = get_path_info("tizen_dev_certificate.py", "abspath")
tizen_manifest_parser = get_path_info("tizen_manifest_parser.py", "abspath")

# Run Tizen Studio CLI as a project builder.
#
# Parameters:
# project_build_dir: Directory to build the project in.
# project_app_name: Name of the application within the project.
# args: List of arguments to pass to the CLI.
# outputs: List of created output files.
# deps: List of dependencies.
template("tizen_sdk") {
forward_variables_from(invoker,
[
Expand Down Expand Up @@ -59,20 +68,54 @@ template("tizen_sdk") {
}
}

# Generate author certificate and security profile.
#
# Parameters:
# author_certificate_name: Author certificate name field.
# author_certificate_email: Author certificate email field.
# author_certificate_password: Password for the author certificate.
# sign_security_profile: Name of the security profile to add.
template("tizen_sdk_certificate") {
assert(defined(invoker.author_certificate_password),
"It is required to specify `author_certificate_password`.")
assert(defined(invoker.sign_security_profile),
"It is required to specify a `sign_security_profile` which " +
"should be added to Tizen security profiles.")
stamp_file = "${root_build_dir}/.tizen_sdk_dev_certificate_stamp"
action(target_name) {
forward_variables_from(invoker, [ "deps" ])
script = tizen_dev_certificate
args = [
"--author-certificate-name=" + invoker.author_certificate_name,
"--author-certificate-email=" + invoker.author_certificate_email,
"--author-certificate-password=" + invoker.author_certificate_password,
"--sign-security-profile=" + invoker.sign_security_profile,
"--stamp-file=" + stamp_file,
]
outputs = [ stamp_file ]
}
}

# Package Tizen application as a TPK bundle.
#
# Parameters:
# manifest: The path to Tizen XML manifest file to use.
# sign_security_profile: Name of the security profile to use for signing.
# deps: List of dependencies.
template("tizen_sdk_package") {
assert(defined(invoker.manifest),
"It is required to specify Tizen `manifest` XML file.")
assert(defined(invoker.sign_security_profile),
"It is required to specify a `sign_security_profile` which " +
"should be used for signing TPK package.")

# Output directory where packaging will occur. We need a separate directory
# for this, because Tizen Studio CLI scans "res" (resources), "shared" and
# "lib" directories for items to pack. In our case it could include in the
# TPK package libraries available in ${root_out_dir}/lib directory.
tizen_package_dir = "${root_build_dir}/package"
tizen_package_out_dir = "${tizen_package_dir}/out"

assert(defined(invoker.manifest),
"It is required to specify Tizen `manifest` XML file.")
assert(defined(invoker.sign_security_profile),
"It is required to specify a `sign_security_profile` which " +
"should be used for signing TPK package.")

# Extract data from Tizen XML manifest.
manifest = exec_script(tizen_manifest_parser,
[ rebase_path(invoker.manifest, root_build_dir) ],
Expand Down