I’m trying to create a cross-platform way to build tree-sitter grammars for Emacs using Zig. I have a PowerShell Script written that downloads the right Zig version, then downloads a list of tree-sitter libraries. For each library it searches for all the .c files and dynamically links them. Unfortunately, I’ve discovered some repos use .cc files as well. So, I’ve added logic to compile the .cc files into .o files, but I’m running into this error when I try to compile everything.
Cloning into 'C:\Users\decre\AppData\Local\Temp\tree-sitter-yaml'...
remote: Enumerating objects: 324, done.
remote: Counting objects: 100% (83/83), done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 324 (delta 69), reused 62 (delta 62), pack-reused 241
Receiving objects: 100% (324/324), 1.22 MiB | 6.62 MiB/s, done.
Resolving deltas: 100% (157/157), done.
Compiling C++ files with the command: zig c++ -c -o libcpp.o C:\Users\decre\AppData\Local\Temp\tree-sitter-yaml\src\scanner.cc C:\Users\decre\AppData\Local\Temp\tree-sitter-yaml\src\schema.generated.cc -Isrc -Isrc/tree-sitter
error: coff does not support linking multiple objects into one
Compiling C files with the command: zig cc -c -o libc.o C:\Users\decre\AppData\Local\Temp\tree-sitter-yaml\src\parser.c -Isrc -Isrc/tree-sitter
Compiling final shared library with the command: zig cc -shared -o libtree-sitter-yaml.dll libcpp.o libc.o
LLD Link... lld-link: error: could not open 'libcpp.o': No such file or directory
Move-Item: C:\home\emacs.d\tree-sitter-install.ps1:172
For those who can’t read PowerShell, these are the commands that are being run
zig c++ -c -o libcpp.o C:\Users\decre\AppData\Local\Temp\tree-sitter-yaml\src\scanner.cc C:\Users\decre\AppData\Local\Temp\tree-sitter-yaml\src\schema.generated.cc -Isrc -Isrc/tree-sitter
zig cc -c -o libc.o C:\Users\decre\AppData\Local\Temp\tree-sitter-yaml\src\parser.c -Isrc -Isrc/tree-sitter
zig cc -shared -o libtree-sitter-yaml.dll libcpp.o libc.o
Here is the relevant part of the script
foreach ($url in $grammarUrls) {
$repoName = $url -split '/' | Select-Object -Last 1
# I.E tree-sitter-markdown to markdown
$languageName = $repoName -replace 'tree-sitter-', ''
$cloneDir = Join-Path $tempDir $repoName
# Check if grammar directory already exists and -ReinstallGrammar is not used
if ((Test-Path -Path $cloneDir) -and (-not $ReinstallGrammar)) {
Write-Host "$repoName already cloned. Pass -ReinstallGrammar to reclone."
continue
}
# If -ReinstallGrammar is used, clean up the current grammar directory
if ($ReinstallGrammar -And (Test-Path -Path $cloneDir)) {
Write-Host "Removing old version of $repoName"
Remove-Item -Path $cloneDir -Recurse -Force
}
Write-Host "Downloaded $url to $cloneDir"
# Clone the grammar repository
git clone $url $cloneDir
# Navigate to the cloned directory
Push-Location -Path $cloneDir
# Compile the grammar using zig cc
$libName = "libtree-sitter-$languageName$fileExt"
$cSrcFiles = (Get-ChildItem src/*.c -Recurse).FullName -join ' '
$cppSrcFiles = (Get-ChildItem src/*.cc -Recurse).FullName -join ' '
$includeDirs = @('-Isrc -Isrc/tree-sitter')
# Check if there are C++ source files
if ($cppSrcFiles -ne $null) {
# Compile C++ files using zig c++
$cppObj = "libcpp.o"
$cppCmd = "zig c++ -c -o $cppObj $cppSrcFiles $($includeDirs -join ' ')"
Write-Host "Compiling C++ files with the command: $cppCmd"
Invoke-Expression $cppCmd
$cObj = "libc.o"
$cCmd= "zig cc -c -o $cObj $cSrcFiles $($includeDirs -join ' ')"
Write-Host "Compiling C files with the command: $cCmd"
Invoke-Expression $cCmd
# Link the files together into a shared object file
$zigCmd = "zig dlltool -shared -o $libName $cppObj $cObj"
Write-Host "Compiling final shared library with the command: $zigCmd"
Invoke-Expression $zigCmd
}
else {
# Construct the zig cc command for compiling C files
$zigCmd = "zig cc -shared -o $libName $cSrcFiles $($includeDirs -join ' ')"
Write-Host "Compiling C files with the command: $zigCmd"
Invoke-Expression $zigCmd
}
I’m waay out of my element right now as a Zig/C/C++ noob. Can anyone point me in the right direction?
EDIT
I think I got it
if ($cppSrcFiles -ne $null) {
# Compile C++ files using zig c++
[System.Collections.ArrayList]$cppObjectFiles = @()
foreach ($fileName in $cppSrcFiles) {
$cppObject = $fileName + ".o"
$cppObjectFiles.Add($cppObject) | Out-Null
$cppCmd = "zig c++ -c -fPIC $fileName -o $cppObject $($includeDirs -join ' ' ) -lc"
Write-Host "Compiling C++ files with the command: $cppCmd`n"
Invoke-Expression $cppCmd
}
[System.Collections.ArrayList]$cObjectFiles = @()
foreach ($fileName in $cSrcFiles) {
$cObject = $fileName + ".o"
$cObjectFiles.Add($cObject) | Out-Null
$cCmd = "zig cc -c -fPIC $fileName -o $cObject $($includeDirs -join ' ')"
Write-Host "Compiling C files with the command: $cCmd`n"
Invoke-Expression $cCmd
}
$zigCmd = "zig c++ -shared -o $libName $($cppObjectFiles -join ' ') $($cOjbectFiles -join ' ')"
Write-Host "Compiling Shared files with the command: $zigCmd`n"
Invoke-Expression $zigCmd
}