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
Show file tree
Hide file tree
Changes from 18 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
Expand Up @@ -945,8 +945,6 @@ NitricOxideConcentrationMeasurement
NitrogenDioxideConcentrationMeasurement
nl
nltest
NLUnitTest
NLUnitTests
nmcli
nmtui
noc
Expand Down
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
Expand Up @@ -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
Expand All @@ -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"

Expand All @@ -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 = []

Expand All @@ -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}" ]
}
Expand All @@ -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" ]
}
Expand Down
18 changes: 13 additions & 5 deletions build/toolchain/flashable_executable.gni
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)) {
Expand All @@ -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" ]
}
Expand All @@ -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 {
Expand All @@ -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" ]
}
Expand Down
55 changes: 47 additions & 8 deletions scripts/build/builders/efr32.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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 += list(map(lambda x: os.path.basename(x), 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 map(lambda x: os.path.basename(x), 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):
Expand Down
Loading
Loading