I don't even know bro
I know you will murder me when you see this commit sometime in the future bodge, so sorry in advance :(main
parent
fc3799e9ac
commit
3aa51748bd
|
|
@ -107,71 +107,82 @@ fn run_compile_tasks(tasks []CompileTask, build_config config.BuildConfig) ![]st
|
|||
}
|
||||
|
||||
pub fn build(mut build_config config.BuildConfig) ! {
|
||||
// Run build flow and ensure that if any error occurs we print its message
|
||||
println('Building ${build_config.project_name}...')
|
||||
|
||||
// Create directories
|
||||
os.mkdir_all(build_config.build_dir) or { return error('Failed to create build directory') }
|
||||
os.mkdir_all(build_config.bin_dir) or { return error('Failed to create bin directory') }
|
||||
os.mkdir_all('${build_config.bin_dir}/lib') or { return error('Failed to create lib directory') }
|
||||
os.mkdir_all('${build_config.bin_dir}/tools') or { return error('Failed to create tools directory') }
|
||||
if build_config.shaders_dir != '' && build_config.shaders_dir != 'bin/shaders' {
|
||||
os.mkdir_all(build_config.shaders_dir) or { return error('Failed to create shaders directory') }
|
||||
}
|
||||
run_build := fn (mut build_config config.BuildConfig) ! {
|
||||
// Create directories
|
||||
os.mkdir_all(build_config.build_dir) or { return error('Failed to create build directory') }
|
||||
os.mkdir_all(build_config.bin_dir) or { return error('Failed to create bin directory') }
|
||||
os.mkdir_all('${build_config.bin_dir}/lib') or { return error('Failed to create lib directory') }
|
||||
os.mkdir_all('${build_config.bin_dir}/tools') or { return error('Failed to create tools directory') }
|
||||
if build_config.shaders_dir != '' && build_config.shaders_dir != 'bin/shaders' {
|
||||
os.mkdir_all(build_config.shaders_dir) or { return error('Failed to create shaders directory') }
|
||||
}
|
||||
|
||||
// Auto-discover sources if not specified
|
||||
auto_discover_sources(mut build_config)
|
||||
// Auto-discover sources if not specified
|
||||
auto_discover_sources(mut build_config)
|
||||
|
||||
// Build shared libraries first (from config)
|
||||
mut shared_libs_built := []string{}
|
||||
for mut lib_config in build_config.shared_libs {
|
||||
if lib_config.sources.len == 0 {
|
||||
// Build shared libraries first (from config)
|
||||
mut shared_libs_built := []string{}
|
||||
for mut lib_config in build_config.shared_libs {
|
||||
if lib_config.sources.len == 0 {
|
||||
if build_config.verbose {
|
||||
println('Skipping empty shared library: ${lib_config.name}')
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
println('Building shared library: ${lib_config.name}')
|
||||
build_shared_library(mut lib_config, build_config) or {
|
||||
return error('Failed to build shared library ${lib_config.name}: ${err}')
|
||||
}
|
||||
shared_libs_built << lib_config.name
|
||||
if build_config.verbose {
|
||||
println('Skipping empty shared library: ${lib_config.name}')
|
||||
println('Built shared library: ${lib_config.name}')
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
println('Building shared library: ${lib_config.name}')
|
||||
build_shared_library(mut lib_config, build_config) or {
|
||||
return error('Failed to build shared library ${lib_config.name}: ${err}')
|
||||
}
|
||||
shared_libs_built << lib_config.name
|
||||
if build_config.verbose {
|
||||
println('Built shared library: ${lib_config.name}')
|
||||
}
|
||||
}
|
||||
// Build targets from build directives
|
||||
build_from_directives(mut build_config, mut shared_libs_built)!
|
||||
|
||||
// Build targets from build directives
|
||||
build_from_directives(mut build_config, mut shared_libs_built)!
|
||||
// Build tools/executables from config
|
||||
for mut tool_config in build_config.tools {
|
||||
if tool_config.sources.len == 0 {
|
||||
if build_config.verbose {
|
||||
println('Skipping empty tool: ${tool_config.name}')
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Build tools/executables from config
|
||||
for mut tool_config in build_config.tools {
|
||||
if tool_config.sources.len == 0 {
|
||||
println('Building tool: ${tool_config.name}')
|
||||
build_tool(mut tool_config, build_config) or {
|
||||
return error('Failed to build tool ${tool_config.name}: ${err}')
|
||||
}
|
||||
if build_config.verbose {
|
||||
println('Skipping empty tool: ${tool_config.name}')
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
println('Building tool: ${tool_config.name}')
|
||||
build_tool(mut tool_config, build_config) or {
|
||||
return error('Failed to build tool ${tool_config.name}: ${err}')
|
||||
}
|
||||
if build_config.verbose {
|
||||
println('Built tool: ${tool_config.name}')
|
||||
}
|
||||
}
|
||||
|
||||
// Build shaders if configured and directory exists
|
||||
if build_config.shaders_dir != '' {
|
||||
compile_shaders(build_config) or {
|
||||
if !build_config.verbose {
|
||||
println('Warning: Failed to compile shaders: ${err}')
|
||||
println('Built tool: ${tool_config.name}')
|
||||
}
|
||||
}
|
||||
|
||||
// Build shaders if configured and directory exists
|
||||
if build_config.shaders_dir != '' {
|
||||
compile_shaders(build_config) or {
|
||||
if !build_config.verbose {
|
||||
println('Warning: Failed to compile shaders: ${err}')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println('Build completed successfully!')
|
||||
return
|
||||
}
|
||||
|
||||
println('Build completed successfully!')
|
||||
// Execute build and show full error output if something fails
|
||||
run_build(mut build_config) or {
|
||||
// Print error message to help debugging
|
||||
println('Build failed: ${err}')
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Build targets based on build directives from source files
|
||||
|
|
@ -202,25 +213,43 @@ fn build_from_directives(mut build_config config.BuildConfig, mut shared_libs_bu
|
|||
|
||||
// Find source file for this unit
|
||||
mut source_file := ''
|
||||
for src_path in directive.unit_name.split('/') {
|
||||
source_file = os.join_path(build_config.src_dir, src_path + '.cpp')
|
||||
if os.is_file(source_file) {
|
||||
break
|
||||
// First try the full unit path (e.g., src/lib/file.cpp)
|
||||
mut candidate := os.join_path(build_config.src_dir, directive.unit_name + '.cpp')
|
||||
if os.is_file(candidate) {
|
||||
source_file = candidate
|
||||
} else {
|
||||
candidate = os.join_path(build_config.src_dir, directive.unit_name + '.cc')
|
||||
if os.is_file(candidate) {
|
||||
source_file = candidate
|
||||
} else {
|
||||
candidate = os.join_path(build_config.src_dir, directive.unit_name + '.cxx')
|
||||
if os.is_file(candidate) {
|
||||
source_file = candidate
|
||||
}
|
||||
}
|
||||
source_file = os.join_path(build_config.src_dir, src_path + '.cc')
|
||||
if os.is_file(source_file) {
|
||||
break
|
||||
}
|
||||
source_file = os.join_path(build_config.src_dir, src_path + '.cxx')
|
||||
if os.is_file(source_file) {
|
||||
break
|
||||
}
|
||||
// if none matched, reset to empty for next iteration
|
||||
source_file = ''
|
||||
}
|
||||
|
||||
// Ensure the found source actually exists; avoid using last attempted extension if none matched
|
||||
if source_file == '' || !os.is_file(source_file) {
|
||||
// Fallback: try only the basename (e.g., src/file.cpp) for legacy layouts
|
||||
if source_file == '' {
|
||||
parts := directive.unit_name.split('/')
|
||||
base := if parts.len > 0 { parts[parts.len - 1] } else { directive.unit_name }
|
||||
candidate = os.join_path(build_config.src_dir, base + '.cpp')
|
||||
if os.is_file(candidate) {
|
||||
source_file = candidate
|
||||
} else {
|
||||
candidate = os.join_path(build_config.src_dir, base + '.cc')
|
||||
if os.is_file(candidate) {
|
||||
source_file = candidate
|
||||
} else {
|
||||
candidate = os.join_path(build_config.src_dir, base + '.cxx')
|
||||
if os.is_file(candidate) {
|
||||
source_file = candidate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if source_file == '' {
|
||||
if build_config.verbose {
|
||||
println('Warning: Source file not found for unit ${unit_name}')
|
||||
}
|
||||
|
|
@ -257,11 +286,17 @@ fn build_from_directives(mut build_config config.BuildConfig, mut shared_libs_bu
|
|||
// Link executable or shared library
|
||||
if directive.is_shared {
|
||||
// Link shared library
|
||||
lib_output := os.join_path(build_config.bin_dir, 'lib', directive.unit_name)
|
||||
// place shared libs directly under bin/lib (not nested by unit name)
|
||||
lib_output_dir := os.join_path(build_config.bin_dir, 'lib')
|
||||
// ensure output directory exists
|
||||
os.mkdir_all(lib_output) or { return error('Failed to create shared lib output directory: ${lib_output}') }
|
||||
println('Linking shared library: ${lib_output}')
|
||||
link_shared_library([obj_file], directive.unit_name, lib_output, build_config, config.SharedLibConfig{
|
||||
os.mkdir_all(lib_output_dir) or { return error('Failed to create shared lib output directory: ${lib_output_dir}') }
|
||||
println('Linking shared library: ${lib_output_dir}/${directive.unit_name.split('/').last()}.so')
|
||||
if build_config.verbose {
|
||||
// show contents of lib dir for debugging
|
||||
files := os.ls(lib_output_dir) or { []string{} }
|
||||
println('Contents of ${lib_output_dir}: ${files}')
|
||||
}
|
||||
link_shared_library([obj_file], directive.unit_name, lib_output_dir, build_config, config.SharedLibConfig{
|
||||
name: directive.unit_name
|
||||
libraries: directive.link_libs
|
||||
debug: build_config.debug
|
||||
|
|
@ -487,11 +522,12 @@ fn build_shared_library(mut lib_config config.SharedLibConfig, build_config conf
|
|||
}
|
||||
|
||||
// Link shared library
|
||||
lib_output := os.join_path(lib_config.output_dir, lib_config.name)
|
||||
// place shared libs directly under the configured output dir
|
||||
lib_output_dir := lib_config.output_dir
|
||||
// ensure output directory exists
|
||||
os.mkdir_all(lib_config.output_dir) or { return error('Failed to create shared lib output directory: ${lib_config.output_dir}') }
|
||||
println('Linking shared library: ${lib_output}')
|
||||
link_shared_library(object_files, lib_config.name, lib_output, build_config, lib_config) or {
|
||||
os.mkdir_all(lib_output_dir) or { return error('Failed to create shared lib output directory: ${lib_output_dir}') }
|
||||
println('Linking shared library: ${lib_output_dir}/${lib_config.name.split('/').last()}.so')
|
||||
link_shared_library(object_files, lib_config.name, lib_output_dir, build_config, lib_config) or {
|
||||
return error('Failed to link shared library ${lib_config.name}')
|
||||
}
|
||||
|
||||
|
|
@ -596,7 +632,10 @@ fn compile_file(source_file string, object_file string, build_config config.Buil
|
|||
// Execute compile
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code != 0 {
|
||||
return error('Compilation failed with exit code ${res.exit_code}:\n${res.output}')
|
||||
// Print compile command and raw output to aid debugging
|
||||
println('Compile command: ${cmd}')
|
||||
println('Compiler output:\n${res.output}')
|
||||
return error('Compilation failed with exit code ${res.exit_code}: ${res.output}')
|
||||
}
|
||||
|
||||
// Generate dependency file
|
||||
|
|
@ -615,7 +654,11 @@ fn link_shared_library(object_files []string, library_name string, output_path s
|
|||
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code != 0 {
|
||||
return error('Shared library linking failed with exit code ${res.exit_code}:\n${res.output}')
|
||||
// Always print the linker command and its raw output to aid debugging
|
||||
println('Linker command: ${cmd}')
|
||||
// print raw output (may contain stdout and stderr merged by os.execute)
|
||||
println('Linker output:\n${res.output}')
|
||||
return error('Shared library linking failed with exit code ${res.exit_code}: ${res.output}')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -628,7 +671,10 @@ fn link_tool(object_files []string, executable string, build_config config.Build
|
|||
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code != 0 {
|
||||
return error('Tool linking failed with exit code ${res.exit_code}:\n${res.output}')
|
||||
// Always print the linker command and its raw output to aid debugging
|
||||
println('Linker command: ${cmd}')
|
||||
println('Linker output:\n${res.output}')
|
||||
return error('Tool linking failed with exit code ${res.exit_code}: ${res.output}')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -752,9 +798,22 @@ fn find_glslc() !string {
|
|||
}
|
||||
|
||||
fn get_object_file(source_file string, object_dir string) string {
|
||||
// Replace src_dir with object_dir and change extension to .o
|
||||
mut obj_file := source_file.replace('src', object_dir)
|
||||
obj_file = obj_file.replace('.cpp', '.o').replace('.cc', '.o').replace('.cxx', '.o')
|
||||
// Compute object file path by preserving the path under src/ and placing it under object_dir
|
||||
// e.g., src/lib/file.cpp -> <object_dir>/lib/file.o
|
||||
// Detect the 'src' prefix and compute relative path
|
||||
rel := if source_file.starts_with('src/') {
|
||||
source_file[4..]
|
||||
} else if source_file.starts_with('./src/') {
|
||||
source_file[6..]
|
||||
} else {
|
||||
// fallback: use basename
|
||||
os.base(source_file)
|
||||
}
|
||||
|
||||
// strip extension and add .o using basename to avoid nested paths under object_dir
|
||||
rel_no_ext := rel.replace('.cpp', '').replace('.cc', '').replace('.cxx', '')
|
||||
base_name := os.base(rel_no_ext)
|
||||
obj_file := os.join_path(object_dir, base_name + '.o')
|
||||
return obj_file
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -575,12 +575,8 @@ pub fn parse_config_file(filename string) !BuildConfig {
|
|||
lib.ldflags << flag
|
||||
}
|
||||
}
|
||||
// merge project libraries
|
||||
for library in build_config.libraries {
|
||||
if library != '' && library !in lib.libraries {
|
||||
lib.libraries << library
|
||||
}
|
||||
}
|
||||
// Do NOT merge global libraries into shared lib 'libraries' here.
|
||||
// Global libraries should be linked globally during linker command assembly, not as per-target shared lib dependencies.
|
||||
}
|
||||
|
||||
for mut tool in build_config.tools {
|
||||
|
|
@ -602,12 +598,8 @@ pub fn parse_config_file(filename string) !BuildConfig {
|
|||
tool.ldflags << flag
|
||||
}
|
||||
}
|
||||
// merge project libraries
|
||||
for library in build_config.libraries {
|
||||
if library != '' && library !in tool.libraries {
|
||||
tool.libraries << library
|
||||
}
|
||||
}
|
||||
// Do NOT merge global libraries into tool 'libraries' here.
|
||||
// Keep per-tool libraries strictly those declared for the tool; global libraries will be added at link time.
|
||||
}
|
||||
|
||||
return build_config
|
||||
|
|
@ -731,10 +723,19 @@ pub fn build_shared_linker_command(object_files []string, library_name string, o
|
|||
}
|
||||
}
|
||||
|
||||
// Add this library's dependencies
|
||||
// Add this library's dependencies (hardcode to filename form: -l:<name>.so)
|
||||
for library in lib_config.libraries {
|
||||
if library != '' {
|
||||
cmd += ' -l:${library}.so'
|
||||
// strip any existing .so or lib/ prefix and ensure we request the explicit filename
|
||||
mut libfile := library
|
||||
if libfile.starts_with('lib/') {
|
||||
parts := libfile.split('/')
|
||||
libfile = parts[parts.len - 1]
|
||||
}
|
||||
if libfile.ends_with('.so') {
|
||||
libfile = libfile.replace('.so', '')
|
||||
}
|
||||
cmd += ' -l:${libfile}.so'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -788,10 +789,18 @@ pub fn build_tool_linker_command(object_files []string, executable string, build
|
|||
}
|
||||
}
|
||||
|
||||
// Add this tool's dependencies (shared libs)
|
||||
// Add this tool's dependencies (shared libs) — hardcode to explicit .so filenames
|
||||
for library in tool_config.libraries {
|
||||
if library != '' {
|
||||
cmd += ' -l:${library}.so'
|
||||
mut libfile := library
|
||||
if libfile.starts_with('lib/') {
|
||||
parts := libfile.split('/')
|
||||
libfile = parts[parts.len - 1]
|
||||
}
|
||||
if libfile.ends_with('.so') {
|
||||
libfile = libfile.replace('.so', '')
|
||||
}
|
||||
cmd += ' -l:${libfile}.so'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue