Skip to content

Commit e3f9f1f

Browse files
Merge pull request #265 from espressif/ci/build_idf_examples_with_overriden_class_drivers
feat(ci): Build idf examples with overriden class driver components
2 parents 8543aac + a0b7f49 commit e3f9f1f

File tree

4 files changed

+113
-23
lines changed

4 files changed

+113
-23
lines changed

.github/ci/.idf-build-examples-rules.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ examples/peripherals/usb/device/tusb_ncm:
1515
- if: SOC_USB_OTG_SUPPORTED != 1 or SOC_WIFI_SUPPORTED != 1
1616

1717
examples/peripherals/usb/host:
18-
enable:
19-
- if: (IDF_VERSION >= "5.4.0")
20-
reason: Run USB Host examples with overridden (esp-usb) USB component only for service releases
2118
disable:
2219
- if: SOC_USB_OTG_SUPPORTED != 1
2320

.github/ci/.idf_build_examples_config.toml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,23 @@ paths = [
55
"examples/peripherals/usb/host", # USB Host examples
66
]
77

8+
# exclude cherryusb build
9+
exclude = [
10+
"examples/peripherals/usb/device/cherryusb_serial_device",
11+
"examples/peripherals/usb/host/cherryusb_host"
12+
]
13+
814
recursive = true
915
check_warnings = true
1016
target = "all"
1117

1218
# build related options
1319
build_dir = "build_@t_@w"
14-
work_dir = "@f_@t_@w"
20+
21+
# use ignore_build_warnings.txt from esp-idf
22+
ignore_warning_files = [
23+
'tools/ci/ignore_build_warnings.txt',
24+
]
1525

1626
# config rules
1727
config_rules = [

.github/ci/override_managed_component.py

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,50 +39,59 @@ def find_apps_with_manifest(apps):
3939
return apps_with_glob
4040

4141
def override_with_local_component(component, local_path, app):
42+
"""
43+
Override managed component in an example at local_path with a local component
44+
"""
4245
app_path = Path(app)
4346

4447
absolute_local_path = Path(local_path).absolute()
4548
if not absolute_local_path.exists():
46-
print('[Error] {} path does not exist'.format(local_path))
47-
raise Exception
49+
raise FileNotFoundError('[Error] {} path does not exist'.format(local_path))
4850
if not app_path.exists():
49-
print('[Error] {} path does not exist'.format(app_path))
50-
raise Exception
51+
raise FileNotFoundError('[Error] {} path does not exist'.format(app_path))
5152

5253
print('[Info] Processing app {}'.format(app))
5354
manager = ManifestManager(app_path / 'main', 'app')
54-
if '/' not in component:
55-
# Prepend with default namespace
56-
component_with_namespace = 'espressif/' + component
55+
# Add default namespace if missing
56+
component_with_namespace = component if "/" in component else f"espressif/{component}"
5757

5858
try:
59-
manifest_tree = yaml.safe_load(Path(manager.path).read_text())
59+
manifest_tree = yaml.safe_load(Path(manager.path).read_text(encoding='utf8'))
6060
manifest_tree['dependencies'][component_with_namespace] = {
6161
'version': '*',
6262
'override_path': str(absolute_local_path)
6363
}
64-
with open(manager.path, 'w') as f:
64+
with open(manager.path, 'w', encoding='utf8') as f:
6565
yaml.dump(manifest_tree, f, allow_unicode=True, Dumper=yaml.SafeDumper)
6666
except KeyError:
6767
print('[Error] {} app does not depend on {}'.format(app, component_with_namespace))
6868
raise KeyError
6969

7070
def override_with_local_component_all(component, local_path, apps):
71-
# Process wildcard, e.g. "app_prefix_*"
71+
"""
72+
Process all apps and apply the local component override.
73+
Returns 0 on success, non-zero on error.
74+
"""
7275
apps_with_glob = find_apps_with_manifest(apps)
76+
if not apps_with_glob:
77+
print("[Error] No apps found containing 'main/idf_component.yml'")
78+
return -1
7379

80+
print(f'[Info] Overriding {component} component with local path {local_path}')
7481
# Go through all collected apps
7582
for app in apps_with_glob:
7683
try:
7784
override_with_local_component(component, local_path, app)
78-
except:
79-
print("[Error] Could not process app {}".format(app))
85+
except Exception as exc:
86+
print("[Error] Could not process app {}: {}".format(app, exc))
8087
return -1
88+
print('[Info] All apps processed successfully')
8189
return 0
8290

8391

8492
if __name__ == '__main__':
85-
parser = argparse.ArgumentParser()
93+
parser = argparse.ArgumentParser(
94+
description="Override a managed component with a local one for multiple ESP-IDF apps.")
8695
parser.add_argument('component', help='Existing component that the app depends on')
8796
parser.add_argument('local_path', help='Path to component that will be used instead of the managed version')
8897
parser.add_argument('apps', nargs='*', help='List of apps to process')

.github/workflows/build_idf_examples.yml

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
# This workflow builds esp-idf examples:
22
#
33
# - usb device examples: with overridden esp_tinyusb from esp-usb/device/esp_tinyusb
4-
# - Only IDF Latest
4+
# - Override esp_tinyusb component only for IDF >= 6.0 temporarily
55
#
6-
# - usb host examples: with overridden usb component from esp-usb/host/usb
7-
# - Only service IDF releases
6+
# - usb host examples:
7+
# - Overridden usb component from esp-usb/host/usb and overridden class drivers from esp-usb/host/class
8+
# - Only service IDF releases
9+
# - Overridden class drivers from esp-usb/host/class
10+
# - All (service + maintenance IDF releases)
11+
#
12+
# - cherryusb examples are ignored
13+
# - usb_host_lib example -> manifest file must be created for IDF < 6.0 to override usb component
814

915
name: Build ESP-IDF USB examples
1016

@@ -32,6 +38,7 @@ jobs:
3238
env:
3339
CONFIG_PATH: ${{ github.workspace }}/.github/ci/.idf_build_examples_config.toml
3440
MANIFEST_PATH: ${{ github.workspace }}/.github/ci/.idf-build-examples-rules.yml
41+
EXAMPLES_PATH: ${{ github.workspace }} # Will be set-up in "Setup IDF Examples path" step
3542
steps:
3643
- uses: actions/checkout@v4
3744
with:
@@ -41,14 +48,81 @@ jobs:
4148
run: |
4249
. ${IDF_PATH}/export.sh
4350
pip install idf-component-manager>=2.1.2 idf-build-apps==2.12.2 pyyaml --upgrade
51+
- name: Setup IDF Examples path
52+
run: echo "EXAMPLES_PATH=${IDF_PATH}/examples/peripherals/usb" >> $GITHUB_ENV
53+
- name: Override device component
54+
# Override esp_tinyusb component only for IDF >= 6.0 temporarily
55+
if: contains('release-v6.0 latest', matrix.idf_ver)
56+
run: |
57+
. ${IDF_PATH}/export.sh
58+
python .github/ci/override_managed_component.py esp_tinyusb device/esp_tinyusb ${{ env.EXAMPLES_PATH }}/device/*
59+
- name: Override class components
60+
# Override all class drivers for all IDF releases
61+
run: |
62+
. ${IDF_PATH}/export.sh
63+
64+
# usb_host_cdc_acm component
65+
python .github/ci/override_managed_component.py usb_host_cdc_acm host/class/cdc/usb_host_cdc_acm ${{ env.EXAMPLES_PATH }}/host/cdc
66+
67+
# usb_host_ch34x_vcp component
68+
python .github/ci/override_managed_component.py usb_host_ch34x_vcp host/class/cdc/usb_host_ch34x_vcp ${{ env.EXAMPLES_PATH }}/host/cdc/cdc_acm_vcp
69+
70+
# usb_host_cp210x_vcp component
71+
python .github/ci/override_managed_component.py usb_host_cp210x_vcp host/class/cdc/usb_host_cp210x_vcp ${{ env.EXAMPLES_PATH }}/host/cdc/cdc_acm_vcp
72+
73+
# usb_host_ftdi_vcp component
74+
python .github/ci/override_managed_component.py usb_host_ftdi_vcp host/class/cdc/usb_host_ftdi_vcp ${{ env.EXAMPLES_PATH }}/host/cdc/cdc_acm_vcp
75+
76+
# usb_host_vcp component
77+
python .github/ci/override_managed_component.py usb_host_vcp host/class/cdc/usb_host_vcp ${{ env.EXAMPLES_PATH }}/host/cdc/cdc_acm_vcp
78+
79+
# usb_host_hid component
80+
python .github/ci/override_managed_component.py usb_host_hid host/class/hid/usb_host_hid ${{ env.EXAMPLES_PATH }}/host/hid
81+
82+
# usb_host_msc component
83+
python .github/ci/override_managed_component.py usb_host_msc host/class/msc/usb_host_msc ${{ env.EXAMPLES_PATH }}/host/msc
84+
85+
# usb_host_uvc component
86+
python .github/ci/override_managed_component.py usb_host_uvc host/class/uvc/usb_host_uvc ${{ env.EXAMPLES_PATH }}/host/uvc
87+
88+
- name: Create component manifest file for usb_host_lib
89+
# Create manifest file for usb_host_lib example, because the examples does not have it for IDF < 6.0
90+
# and we need to override the usb component
91+
if: contains('release-v5.4 release-v5.5', matrix.idf_ver)
92+
working-directory: ${{ env.EXAMPLES_PATH }}/host/usb_host_lib/main
93+
run: |
94+
python3 - << 'EOF'
95+
content = """## IDF Component Manager Manifest File
96+
dependencies:
97+
espressif/usb: "*"
98+
"""
99+
with open("idf_component.yml", "w") as f:
100+
f.write(content)
101+
EOF
102+
103+
if [ -f idf_component.yml ]; then
104+
echo "✅ File created successfully." && cat idf_component.yml
105+
else
106+
echo "❌ File was not created"
107+
exit 1
108+
fi
109+
- name: Override usb component
110+
# Override usb host component only for service releases
111+
if: contains('release-v5.4 release-v5.5 release-v6.0 latest', matrix.idf_ver)
112+
run: |
113+
. ${IDF_PATH}/export.sh
114+
python .github/ci/override_managed_component.py usb host/usb ${{ env.EXAMPLES_PATH }}/host/*
44115
- name: Build ESP-IDF ${{ matrix.idf_ver }} USB examples
116+
# Build esp-idf examples with overridden components
45117
shell: bash
46118
run: |
47119
. ${IDF_PATH}/export.sh
48-
49-
python .github/ci/override_managed_component.py esp_tinyusb device/esp_tinyusb ${IDF_PATH}/examples/peripherals/usb/device/*
50-
python .github/ci/override_managed_component.py usb host/usb ${IDF_PATH}/examples/peripherals/usb/host/*
51120
cd ${IDF_PATH}
52121
122+
# Export compiler flags
123+
export PEDANTIC_FLAGS="-DIDF_CI_BUILD -Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function"
124+
export EXTRA_CFLAGS="${PEDANTIC_FLAGS} -Wstrict-prototypes"
125+
export EXTRA_CXXFLAGS="${PEDANTIC_FLAGS}"
126+
53127
idf-build-apps find --config-file ${CONFIG_PATH} --manifest-file ${MANIFEST_PATH}
54128
idf-build-apps build --config-file ${CONFIG_PATH} --manifest-file ${MANIFEST_PATH}

0 commit comments

Comments
 (0)