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

Generating separate binaries for each unit test for EFR32 #35028

Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
2 changes: 0 additions & 2 deletions .github/.wordlist.txt
Original file line number Diff line number Diff line change
@@ -945,8 +945,6 @@ NitricOxideConcentrationMeasurement
NitrogenDioxideConcentrationMeasurement
nl
nltest
NLUnitTest
NLUnitTests
nmcli
nmtui
noc
71 changes: 0 additions & 71 deletions build/chip/chip_test.gni

This file was deleted.

101 changes: 42 additions & 59 deletions build/chip/chip_test_suite.gni
Original file line number Diff line number Diff line change
@@ -14,13 +14,20 @@

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

import("${chip_root}/build/chip/chip_test.gni")
import("${chip_root}/build/chip/tests.gni")
import("${dir_pw_unit_test}/test.gni")

assert(chip_build_tests)

declare_args() {
# These may be overridden in args.gni to build platform-specific test binaries.
test_executable_output_name = ""
test_executable_output_name_suffix = ""
test_executable_ldflags = []
}

# Define CHIP unit tests
#
# Simple usage
@@ -41,50 +48,34 @@ assert(chip_build_tests)
# "${chip_root}/src/lib/foo", # add dependencies here
# ]
# }
#
#
# Deprecated usage (writing own driver files):
#
# chip_test_suite("tests") {
# output_name = "libFooTests"
#
# sources = [
# "TestDeclarations.h",
# "TestFoo.cpp",
# "TestBar.cpp",
# ]
#
# public_deps = [
# "${chip_root}/src/lib/foo", # add dependencies here
# ]
#
# tests = [
# "TestFoo", # Assumes TestFooDriver.cpp exists
# "TestBar", # Assumes TestBarDriver.cpp exists
# ]
# }

#
template("chip_test_suite") {
_suite_name = target_name

# Ensures that the common library has sources containing both common
# and individual unit tests.
if (!defined(invoker.sources)) {
invoker.sources = []
}

if (defined(invoker.test_sources)) {
invoker.sources += invoker.test_sources
exclude_variables = [ "tests" ]
if (chip_link_tests && chip_device_platform != "darwin") {
# Common library shouldn't have all the individual unit tests, only the common sources.
exclude_variables += [ "test_sources" ]
# NOTE: For `Build on Darwin (clang, python_lib, simulated)` the test_sources must be in common lib.
} else {
# Common library should have all the individual unit tests, in addition to the common sources.
if (!defined(invoker.sources)) {
invoker.sources = []
}
if (defined(invoker.test_sources)) {
invoker.sources += invoker.test_sources
}
}

# Target for the common library. Contains all the common sources, and sometimes all the individual test sources.
if (chip_build_test_static_libraries) {
_target_type = "static_library"
} else {
_target_type = "source_set"
}
target(_target_type, "${_suite_name}.lib") {
forward_variables_from(invoker, "*", [ "tests" ])
forward_variables_from(invoker, "*", exclude_variables)

output_dir = "${root_out_dir}/lib"

@@ -102,6 +93,8 @@ template("chip_test_suite") {
public_deps += [ "${chip_root}/src/platform/logging:default" ]
}
}

# Build a source_set or a flashable executable for each individual unit test source, which also includes the common files.
if (chip_link_tests) {
tests = []

@@ -115,50 +108,38 @@ template("chip_test_suite") {
}

pw_test(_test_name) {
# Forward certain variables from the invoker.
forward_variables_from(invoker,
[
"deps",
"public_deps",
"cflags",
"configs",
])

# Link to the common lib for this suite so we get its `sources`.
public_deps += [ ":${_suite_name}.lib" ]
sources = [ _test ]
output_dir = _test_output_dir
}
tests += [ _test_name ]
}
}

if (defined(invoker.tests)) {
foreach(_test, invoker.tests) {
_test_output_dir = "${root_out_dir}/tests"
if (defined(invoker.output_dir)) {
_test_output_dir = invoker.output_dir
}
# Set variables that the platform executable may need.
if (test_executable_output_name != "") {
output_name = test_executable_output_name + _test_name +
test_executable_output_name_suffix
}
ldflags = test_executable_ldflags

# Add the individual test source file (e.g. "TestSomething.cpp").
sources = [ _test ]

pw_test(_test) {
forward_variables_from(invoker,
[
"deps",
"public_deps",
"cflags",
"configs",
])
public_deps += [ ":${_suite_name}.lib" ]
test_main = ""
sources = [
"${_test}.cpp",
"${_test}Driver.cpp",
]
output_dir = _test_output_dir
}
tests += [ _test ]
tests += [ _test_name ]
}
}

group(_suite_name) {
deps = []

# Add each individual unit test.
foreach(_test, tests) {
deps += [ ":${_test}" ]
}
@@ -167,6 +148,8 @@ template("chip_test_suite") {
if (chip_pw_run_tests) {
group("${_suite_name}_run") {
deps = []

# Add the .run targets created by pw_test.
foreach(_test, tests) {
deps += [ ":${_test}.run" ]
}
18 changes: 13 additions & 5 deletions build/toolchain/flashable_executable.gni
Original file line number Diff line number Diff line change
@@ -86,6 +86,10 @@ template("gen_flashing_script") {
template("flashable_executable") {
executable_target = "$target_name.executable"

if (!defined(invoker.output_dir)) {
invoker.output_dir = root_out_dir
}

if (defined(invoker.flashing_script_name)) {
# Generating the flashing script is the final target.
final_target = "$target_name.flashing"
@@ -110,7 +114,10 @@ template("flashable_executable") {
data_deps += invoker.data_deps
}

write_runtime_deps = "${root_out_dir}/${flashbundle_name}"
# Invoker can stop this template from creating the flashbundle.txt by setting flashbundle_name to empty string.
if (flashbundle_name != "") {
write_runtime_deps = "${invoker.output_dir}/${flashbundle_name}"
}
}

if (defined(invoker.objcopy_image_name)) {
@@ -124,8 +131,8 @@ template("flashable_executable") {
objcopy = invoker.objcopy

objcopy_convert(image_target) {
conversion_input = "${root_out_dir}/${invoker.output_name}"
conversion_output = "${root_out_dir}/${image_name}"
conversion_input = "${invoker.output_dir}/${invoker.output_name}"
conversion_output = "${invoker.output_dir}/${image_name}"
conversion_target_format = image_format
deps = [ ":$executable_target" ]
}
@@ -141,7 +148,8 @@ template("flashable_executable") {
gen_flashing_script("$target_name.flashing") {
flashing_script_generator = invoker.flashing_script_generator
flashing_script_inputs = invoker.flashing_script_inputs
flashing_script_name = "$root_out_dir/${invoker.flashing_script_name}"
flashing_script_name =
"${invoker.output_dir}/${invoker.flashing_script_name}"
if (defined(invoker.flashing_options)) {
flashing_options = invoker.flashing_options
} else {
@@ -155,7 +163,7 @@ template("flashable_executable") {

flashing_options += [
"--application",
rebase_path(image_name, root_out_dir, root_out_dir),
rebase_path(image_name, invoker.output_dir, invoker.output_dir),
]
data_deps = [ ":$image_target" ]
}
55 changes: 47 additions & 8 deletions scripts/build/builders/efr32.py
Original file line number Diff line number Diff line change
@@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import glob
import logging
import os
import shlex
import subprocess
@@ -78,7 +80,7 @@ def FlashBundleName(self):
elif self == Efr32App.PUMP:
return 'pump_app.flashbundle.txt'
elif self == Efr32App.UNIT_TEST:
return 'efr32_device_tests.flashbundle.txt'
return os.path.join('tests', 'efr32_device_tests.flashbundle.txt')
else:
raise Exception('Unknown app type: %r' % self)

@@ -259,27 +261,64 @@ def __init__(self,
def GnBuildArgs(self):
return self.extra_gn_options

def _bundle(self):
# Only unit-test needs to generate the flashbundle here. All other examples will generate a flashbundle via the silabs_executable template.
if self.app == Efr32App.UNIT_TEST:
flash_bundle_path = os.path.join(self.output_dir, self.app.FlashBundleName())
logging.info(f'Generating flashbundle {flash_bundle_path}')

patterns = [
os.path.join(self.output_dir, "tests", "*.flash.py"),
os.path.join(self.output_dir, "tests", "*.s37"),
os.path.join(self.output_dir, "tests", "silabs_firmware_utils.py"),
os.path.join(self.output_dir, "tests", "firmware_utils.py"),
]

# Generate the list of files by globbing each pattern.
files = []
for pattern in patterns:
files.extend([os.path.basename(x) for x in glob.glob(pattern)])

# Create the bundle file.
with open(flash_bundle_path, 'w') as bundle_file:
bundle_file.write("\n".join(files))

def build_outputs(self):
extensions = ["out", "hex"]
if self.options.enable_link_map_file:
extensions.append("out.map")
for ext in extensions:
name = f"{self.app.AppNamePrefix()}.{ext}"
yield BuilderOutput(os.path.join(self.output_dir, name), name)

if self.app == Efr32App.UNIT_TEST:
# Efr32 unit-test generates the "tests" subdir with a set of files for each individual unit test source.
for ext in extensions:
pattern = os.path.join(self.output_dir, "tests", f"*.{ext}")
for name in [os.path.basename(x) for x in glob.glob(pattern)]:
yield BuilderOutput(os.path.join(self.output_dir, "tests", name), name)
else:
# All other examples have just one set of files.
for ext in extensions:
name = f"{self.app.AppNamePrefix()}.{ext}"
yield BuilderOutput(os.path.join(self.output_dir, name), name)

if self.app == Efr32App.UNIT_TEST:
# Include test runner python wheels
for root, dirs, files in os.walk(os.path.join(self.output_dir, 'chip_nl_test_runner_wheels')):
for root, dirs, files in os.walk(os.path.join(self.output_dir, 'chip_pw_test_runner_wheels')):
for file in files:
yield BuilderOutput(
os.path.join(root, file),
os.path.join("chip_nl_test_runner_wheels", file))
os.path.join("chip_pw_test_runner_wheels", file))

# Figure out flash bundle files and build accordingly
def bundle_outputs(self):
# If flashbundle creation is enabled, the outputs will include the s37 and flash.py files, plus the two firmware utils scripts that support flash.py.
# For the unit-test example, there will be a s37 and flash.py file for each unit test source.
with open(os.path.join(self.output_dir, self.app.FlashBundleName())) as f:
for name in filter(None, [x.strip() for x in f.readlines()]):
if self.app == Efr32App.UNIT_TEST:
sourcepath = os.path.join(self.output_dir, "tests", name) # Unit tests are in the "tests" subdir.
else:
sourcepath = os.path.join(self.output_dir, name)
yield BuilderOutput(
os.path.join(self.output_dir, name),
sourcepath,
os.path.join("flashbundle", name))

def generate(self):
Loading