87 lines
2.4 KiB
Odin
87 lines
2.4 KiB
Odin
package backend
|
|
|
|
import "../linker"
|
|
import "../target"
|
|
import "core:fmt"
|
|
import "core:mem"
|
|
import "core:os"
|
|
import "core:os/os2"
|
|
import "core:strings"
|
|
|
|
append_owned :: proc(command: ^[dynamic]string, value: string, allocator: mem.Allocator) {
|
|
append(command, strings.clone(value, allocator))
|
|
}
|
|
|
|
build_command :: proc(
|
|
llvm_path, output_path: string,
|
|
link_arguments: []linker.Argument,
|
|
selected := target.DEFAULT,
|
|
allocator := context.allocator,
|
|
) -> []string {
|
|
command: [dynamic]string
|
|
command.allocator = allocator
|
|
append_owned(&command, "/usr/bin/env", allocator)
|
|
append_owned(&command, "zig", allocator)
|
|
append_owned(&command, "cc", allocator)
|
|
append_owned(&command, "-target", allocator)
|
|
append_owned(&command, target.name(selected), allocator)
|
|
append_owned(&command, "-Wno-override-module", allocator)
|
|
append_owned(&command, llvm_path, allocator)
|
|
for argument in link_arguments {
|
|
switch argument.kind {
|
|
case .Input:
|
|
append_owned(&command, argument.value, allocator)
|
|
case .Library_Path:
|
|
append(&command, fmt.aprintf("-L%s", argument.value, allocator=allocator))
|
|
case .Library:
|
|
append(&command, fmt.aprintf("-l%s", argument.value, allocator=allocator))
|
|
}
|
|
}
|
|
append_owned(&command, "-o", allocator)
|
|
append_owned(&command, output_path, allocator)
|
|
return command[:]
|
|
}
|
|
|
|
destroy_command :: proc(command: []string, allocator := context.allocator) {
|
|
for argument in command {
|
|
delete(argument, allocator)
|
|
}
|
|
delete(command, allocator)
|
|
}
|
|
|
|
compile :: proc(
|
|
llvm_path, output_path: string,
|
|
link_arguments: []linker.Argument = nil,
|
|
selected := target.DEFAULT,
|
|
) -> bool {
|
|
pid := os2.get_pid()
|
|
temporary_output := fmt.tprintf("%s.brolang-tmp-%d", output_path, pid)
|
|
defer _ = os.remove(temporary_output)
|
|
|
|
command := build_command(llvm_path, temporary_output, link_arguments, selected)
|
|
defer destroy_command(command)
|
|
state, stdout, stderr, err := os2.process_exec(
|
|
os2.Process_Desc{command=command},
|
|
context.allocator,
|
|
)
|
|
defer delete(stdout)
|
|
defer delete(stderr)
|
|
if len(stdout) > 0 {
|
|
fmt.print(string(stdout))
|
|
}
|
|
if len(stderr) > 0 {
|
|
fmt.eprint(string(stderr))
|
|
}
|
|
if err != nil || state.exit_code != 0 {
|
|
if err != nil {
|
|
fmt.eprintln("failed to execute zig cc:", err)
|
|
}
|
|
return false
|
|
}
|
|
if rename_err := os2.rename(temporary_output, output_path); rename_err != nil {
|
|
fmt.eprintln("failed to atomically replace output:", rename_err)
|
|
return false
|
|
}
|
|
return true
|
|
}
|