Skip to content

Commit 0307faf

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. 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 935bc23 commit 0307faf

File tree

1 file changed

+100
-16
lines changed

1 file changed

+100
-16
lines changed

kernelci/kbuild.py

Lines changed: 100 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,80 @@ 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+
# Fetch firmware for builds that need it
767+
self._fetch_firmware()
768+
729769
self.startjob("build_tuxmake")
730770
self.addcmd("cd " + self._srcdir)
731771

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

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

743817
def _build_kernel(self):
@@ -987,9 +1061,19 @@ def upload_artifacts(self):
9871061

9881062
# Prepare all artifacts for upload
9891063
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))
1064+
if self._backend == 'tuxmake':
1065+
# For TuxMake, upload everything in artifacts directory
1066+
print("[_upload_artifacts] TuxMake backend: discovering files in artifacts dir")
1067+
for root, dirs, files in os.walk(self._af_dir):
1068+
for file in files:
1069+
file_rel = os.path.relpath(os.path.join(root, file), self._af_dir)
1070+
artifact_path = os.path.join(self._af_dir, file_rel)
1071+
upload_tasks.append((file_rel, artifact_path))
1072+
else:
1073+
# For make backend, upload only listed artifacts
1074+
for artifact in self._artifacts:
1075+
artifact_path = os.path.join(self._af_dir, artifact)
1076+
upload_tasks.append((artifact, artifact_path))
9931077

9941078
# Function to handle a single artifact upload
9951079
# args: (artifact, artifact_path)

0 commit comments

Comments
 (0)