Skip to content

Commit e4d43e0

Browse files
committed
kbuild: Use tuxmake native fragment support with --kconfig-add
Switch to using TuxMake's native --kconfig-add parameter for applying configuration fragments instead of manually merging them. Use --kconfig-add for fragment support and add --output-dir to specify where tuxmake should place build artifacts. Build the dtbs target for architectures that support it. Call _fetch_firmware() for builds that need firmware. Raise an error on multiple defconfigs since tuxmake only supports one. Warn when kselftest is requested as it is not supported by tuxmake. Handle ChromeOS defconfig specially by pre-creating the .config file. Reviewed-by: Ben Copeland <ben.copeland@linaro.org Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
1 parent 0deb31b commit e4d43e0

File tree

1 file changed

+103
-16
lines changed

1 file changed

+103
-16
lines changed

kernelci/kbuild.py

Lines changed: 103 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -591,10 +591,21 @@ def _parse_fragments(self, firmware=False):
591591
# Use fragment configs passed from scheduler
592592
content = self.add_fragment(fragment)
593593

594+
if not content:
595+
print(f"[_parse_fragments] WARNING: Fragment {fragment} has no content")
596+
continue
597+
594598
fragfile = os.path.join(self._fragments_dir, f"{idx}.config")
595599
with open(fragfile, 'w') as f:
596600
f.write(content)
597601

602+
if not os.path.exists(fragfile):
603+
print(f"[_parse_fragments] ERROR: Failed to create fragment file: {fragfile}")
604+
continue
605+
606+
config_count = len([line for line in content.split('\n') if line.strip()])
607+
print(f"[_parse_fragments] Created {fragfile} ({config_count} configs)")
608+
598609
fragment_files.append(fragfile)
599610

600611
# add fragment to artifacts but relative to artifacts dir
@@ -608,12 +619,14 @@ def _parse_fragments(self, firmware=False):
608619
with open(fragfile, 'w') as f:
609620
f.write(content)
610621

611-
fragment_files.append(fragfile)
612-
613-
# add fragment to artifacts but relative to artifacts dir
614-
frag_rel = os.path.relpath(fragfile, self._af_dir)
615-
self._artifacts.append(frag_rel)
622+
if os.path.exists(fragfile):
623+
fragment_files.append(fragfile)
624+
frag_rel = os.path.relpath(fragfile, self._af_dir)
625+
self._artifacts.append(frag_rel)
626+
else:
627+
print("[_parse_fragments] ERROR: Failed to create firmware fragment")
616628

629+
print(f"[_parse_fragments] Created {len(fragment_files)} fragment files")
617630
return fragment_files
618631

619632
def _merge_frags(self, fragment_files):
@@ -725,19 +738,83 @@ def _build_with_make(self):
725738
self._build_dtbs_check()
726739

727740
def _build_with_tuxmake(self):
728-
""" Build kernel using tuxmake """
741+
""" Build kernel using tuxmake with native fragment support """
742+
print("[_build_with_tuxmake] Starting tuxmake build")
743+
744+
if not hasattr(self, '_fragment_files'):
745+
print("[_build_with_tuxmake] ERROR: No fragment files available")
746+
self._fragment_files = []
747+
748+
print(f"[_build_with_tuxmake] Using {len(self._fragment_files)} fragment files")
749+
750+
# Handle multiple defconfigs - tuxmake only supports one
751+
if isinstance(self._defconfig, list):
752+
if len(self._defconfig) > 1:
753+
raise ValueError(
754+
f"TuxMake backend does not support multiple defconfigs: "
755+
f"{self._defconfig}. Use backend=make or specify a single defconfig."
756+
)
757+
defconfig = self._defconfig[0]
758+
self._config_full = self._defconfig[0] + self._config_full
759+
elif isinstance(self._defconfig, str):
760+
defconfig = self._defconfig
761+
self._config_full = self._defconfig + self._config_full
762+
else:
763+
defconfig = 'defconfig'
764+
print("[_build_with_tuxmake] WARNING: No defconfig specified, using 'defconfig'")
765+
766+
# Check for unsupported kselftest
767+
if self._kfselftest:
768+
print("[_build_with_tuxmake] WARNING: kselftest is not supported with "
769+
"tuxmake backend, skipping. Use backend=make for kselftest builds.")
770+
771+
# Fetch firmware for builds that need it
772+
self._fetch_firmware()
773+
729774
self.startjob("build_tuxmake")
730775
self.addcmd("cd " + self._srcdir)
731776

732-
tuxmake_cmd = (
733-
f"tuxmake --runtime=null "
734-
f"--target-arch={self._arch} "
735-
f"--toolchain={self._compiler} "
736-
f"kernel modules"
737-
)
777+
use_kconfig_flag = True
738778

739-
print(f"Building with tuxmake: {tuxmake_cmd}")
779+
# Handle ChromeOS defconfig
780+
if defconfig.startswith('cros://'):
781+
print(f"[_build_with_tuxmake] Handling ChromeOS defconfig: {defconfig}")
782+
dotconfig = os.path.join(self._srcdir, ".config")
783+
content, defconfig_name = self._getcrosfragment(defconfig)
784+
with open(dotconfig, 'w') as f:
785+
f.write(content)
786+
self.addcmd("make olddefconfig")
787+
use_kconfig_flag = False
788+
789+
cmd_parts = [
790+
"tuxmake --runtime=null",
791+
f"--target-arch={self._arch}",
792+
f"--toolchain={self._compiler}",
793+
f"--output-dir={self._af_dir}",
794+
]
795+
796+
if use_kconfig_flag:
797+
cmd_parts.append(f"--kconfig={defconfig}")
798+
799+
for fragfile in self._fragment_files:
800+
if os.path.exists(fragfile):
801+
cmd_parts.append(f"--kconfig-add={fragfile}")
802+
print(f"[_build_with_tuxmake] Adding fragment: {os.path.basename(fragfile)}")
803+
else:
804+
print(f"[_build_with_tuxmake] WARNING: Fragment file not found: {fragfile}")
805+
806+
# Build targets: kernel modules, plus dtbs if arch supports it
807+
targets = ["kernel", "modules"]
808+
if self._arch not in DTBS_DISABLED:
809+
targets.append("dtbs")
810+
cmd_parts.append(" ".join(targets))
811+
print(f"[_build_with_tuxmake] Building targets: {' '.join(targets)}")
812+
813+
tuxmake_cmd = " ".join(cmd_parts)
814+
print(f"[_build_with_tuxmake] Command: {tuxmake_cmd}")
815+
print(f"[_build_with_tuxmake] Output directory: {self._af_dir}")
740816
self.addcmd(tuxmake_cmd)
817+
741818
self.addcmd("cd ..")
742819

743820
def _build_kernel(self):
@@ -987,9 +1064,19 @@ def upload_artifacts(self):
9871064

9881065
# Prepare all artifacts for upload
9891066
upload_tasks = []
990-
for artifact in self._artifacts:
991-
artifact_path = os.path.join(self._af_dir, artifact)
992-
upload_tasks.append((artifact, artifact_path))
1067+
if self._backend == 'tuxmake':
1068+
# For TuxMake, upload everything in artifacts directory
1069+
print("[_upload_artifacts] TuxMake backend: discovering files in artifacts dir")
1070+
for root, dirs, files in os.walk(self._af_dir):
1071+
for file in files:
1072+
file_rel = os.path.relpath(os.path.join(root, file), self._af_dir)
1073+
artifact_path = os.path.join(self._af_dir, file_rel)
1074+
upload_tasks.append((file_rel, artifact_path))
1075+
else:
1076+
# For make backend, upload only listed artifacts
1077+
for artifact in self._artifacts:
1078+
artifact_path = os.path.join(self._af_dir, artifact)
1079+
upload_tasks.append((artifact, artifact_path))
9931080

9941081
# Function to handle a single artifact upload
9951082
# args: (artifact, artifact_path)

0 commit comments

Comments
 (0)