Enhance build process: improve source file handling, ensure output directories exist, and merge global flags into shared libs and tools

main
Joca 2025-10-17 16:41:49 -03:00
parent 84f90e83c3
commit fc3799e9ac
Signed by: jocadbz
GPG Key ID: B1836DCE2F50BDF7
2 changed files with 95 additions and 13 deletions

View File

@ -215,9 +215,12 @@ fn build_from_directives(mut build_config config.BuildConfig, mut shared_libs_bu
if os.is_file(source_file) { if os.is_file(source_file) {
break break
} }
// if none matched, reset to empty for next iteration
source_file = ''
} }
if source_file == '' { // Ensure the found source actually exists; avoid using last attempted extension if none matched
if source_file == '' || !os.is_file(source_file) {
if build_config.verbose { if build_config.verbose {
println('Warning: Source file not found for unit ${unit_name}') println('Warning: Source file not found for unit ${unit_name}')
} }
@ -255,6 +258,8 @@ fn build_from_directives(mut build_config config.BuildConfig, mut shared_libs_bu
if directive.is_shared { if directive.is_shared {
// Link shared library // Link shared library
lib_output := os.join_path(build_config.bin_dir, 'lib', directive.unit_name) lib_output := os.join_path(build_config.bin_dir, 'lib', directive.unit_name)
// 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}') println('Linking shared library: ${lib_output}')
link_shared_library([obj_file], directive.unit_name, lib_output, build_config, config.SharedLibConfig{ link_shared_library([obj_file], directive.unit_name, lib_output, build_config, config.SharedLibConfig{
name: directive.unit_name name: directive.unit_name
@ -457,6 +462,11 @@ fn build_shared_library(mut lib_config config.SharedLibConfig, build_config conf
if needs_recompile(src_file, obj_file) { if needs_recompile(src_file, obj_file) {
println('Compiling ${lib_config.name}: ${src_file}...') println('Compiling ${lib_config.name}: ${src_file}...')
lib_target_config := config.TargetConfig(lib_config) lib_target_config := config.TargetConfig(lib_config)
// show compile command if verbose
if lib_config.verbose || build_config.verbose {
cmd_preview := config.build_shared_compiler_command(src_file, obj_file, build_config, lib_target_config)
println('Compile command (preview): ${cmd_preview}')
}
compile_tasks << CompileTask{source: src_file, obj: obj_file, target_config: lib_target_config} compile_tasks << CompileTask{source: src_file, obj: obj_file, target_config: lib_target_config}
} else { } else {
if lib_config.verbose { if lib_config.verbose {
@ -478,6 +488,8 @@ fn build_shared_library(mut lib_config config.SharedLibConfig, build_config conf
// Link shared library // Link shared library
lib_output := os.join_path(lib_config.output_dir, lib_config.name) lib_output := os.join_path(lib_config.output_dir, lib_config.name)
// 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}') println('Linking shared library: ${lib_output}')
link_shared_library(object_files, lib_config.name, lib_output, build_config, lib_config) or { link_shared_library(object_files, lib_config.name, lib_output, build_config, lib_config) or {
return error('Failed to link shared library ${lib_config.name}') return error('Failed to link shared library ${lib_config.name}')
@ -522,6 +534,11 @@ fn build_tool(mut tool_config config.ToolConfig, build_config config.BuildConfig
if needs_recompile(src_file, obj_file) { if needs_recompile(src_file, obj_file) {
println('Compiling ${tool_config.name}: ${src_file}...') println('Compiling ${tool_config.name}: ${src_file}...')
tool_target_config := config.TargetConfig(tool_config) tool_target_config := config.TargetConfig(tool_config)
// show compile command if verbose
if tool_config.verbose || build_config.verbose {
cmd_preview := config.build_shared_compiler_command(src_file, obj_file, build_config, tool_target_config)
println('Compile command (preview): ${cmd_preview}')
}
compile_tasks << CompileTask{source: src_file, obj: obj_file, target_config: tool_target_config} compile_tasks << CompileTask{source: src_file, obj: obj_file, target_config: tool_target_config}
} else { } else {
if tool_config.verbose { if tool_config.verbose {
@ -576,6 +593,7 @@ fn compile_file(source_file string, object_file string, build_config config.Buil
println('Compile command: ${cmd}') println('Compile command: ${cmd}')
} }
// Execute compile
res := os.execute(cmd) res := os.execute(cmd)
if res.exit_code != 0 { if res.exit_code != 0 {
return error('Compilation failed with exit code ${res.exit_code}:\n${res.output}') return error('Compilation failed with exit code ${res.exit_code}:\n${res.output}')
@ -766,6 +784,11 @@ fn find_source_files(dir string) ![]string {
} }
fn needs_recompile(source_file string, object_file string) bool { fn needs_recompile(source_file string, object_file string) bool {
if !os.is_file(source_file) {
// source missing, signal recompile to allow upstream code to handle error
return true
}
src_mtime := os.file_last_mod_unix(source_file) src_mtime := os.file_last_mod_unix(source_file)
obj_mtime := if os.is_file(object_file) { obj_mtime := if os.is_file(object_file) {
os.file_last_mod_unix(object_file) os.file_last_mod_unix(object_file)

View File

@ -89,7 +89,7 @@ __global:
// default config // default config
pub const default_config = BuildConfig{ pub const default_config = BuildConfig{
project_name: 'project' project_name: ''
src_dir: 'src' src_dir: 'src'
build_dir: 'build' build_dir: 'build'
bin_dir: 'bin' bin_dir: 'bin'
@ -135,7 +135,8 @@ pub fn (mut build_config BuildConfig) parse_build_directives() ! {
continue continue
} }
parts := line[17..].trim_space().split('(') // slice after the prefix '// build-directive:' (19 characters)
parts := line[19..].trim_space().split('(')
if parts.len != 2 { if parts.len != 2 {
continue continue
} }
@ -292,10 +293,10 @@ pub fn parse_args() !BuildConfig {
else { else {
if !arg.starts_with('-') { if !arg.starts_with('-') {
// Treat as project name or first source file // Treat as project name or first source file
if build_config.project_name == 'project' { if build_config.project_name == '' {
build_config.project_name = arg build_config.project_name = arg
} else { } else {
// Add as default tool // Add as default tool using the project name
mut default_tool := ToolConfig{ mut default_tool := ToolConfig{
name: build_config.project_name name: build_config.project_name
sources: [arg] sources: [arg]
@ -554,6 +555,61 @@ pub fn parse_config_file(filename string) !BuildConfig {
if !tool.verbose { tool.verbose = build_config.verbose } if !tool.verbose { tool.verbose = build_config.verbose }
} }
// Merge global flags and includes into individual shared libs and tools
for mut lib in build_config.shared_libs {
// merge include dirs
for inc in build_config.include_dirs {
if inc != '' && inc !in lib.include_dirs {
lib.include_dirs << inc
}
}
// merge cflags
for flag in build_config.cflags {
if flag != '' && flag !in lib.cflags {
lib.cflags << flag
}
}
// merge ldflags
for flag in build_config.ldflags {
if flag != '' && flag !in lib.ldflags {
lib.ldflags << flag
}
}
// merge project libraries
for library in build_config.libraries {
if library != '' && library !in lib.libraries {
lib.libraries << library
}
}
}
for mut tool in build_config.tools {
// merge include dirs
for inc in build_config.include_dirs {
if inc != '' && inc !in tool.include_dirs {
tool.include_dirs << inc
}
}
// merge cflags
for flag in build_config.cflags {
if flag != '' && flag !in tool.cflags {
tool.cflags << flag
}
}
// merge ldflags
for flag in build_config.ldflags {
if flag != '' && flag !in tool.ldflags {
tool.ldflags << flag
}
}
// merge project libraries
for library in build_config.libraries {
if library != '' && library !in tool.libraries {
tool.libraries << library
}
}
}
return build_config return build_config
} }
@ -630,7 +686,7 @@ pub fn build_shared_compiler_command(source_file string, object_file string, bui
} }
// Add standard flags // Add standard flags
cmd += ' -Wall -Wextra -std=c++17' cmd += ' -Wall -Wextra'
// Add global CFLAGS // Add global CFLAGS
for flag in build_config.cflags { for flag in build_config.cflags {
@ -691,7 +747,10 @@ pub fn build_shared_linker_command(object_files []string, library_name string, o
} }
// Set output name (with platform-specific extension) // Set output name (with platform-specific extension)
mut lib_name := library_name // Use only the basename of the library to avoid duplicating path segments
parts := library_name.split('/')
base_name := if parts.len > 0 { parts[parts.len - 1] } else { library_name }
mut lib_name := base_name
$if windows { $if windows {
lib_name += '.dll' lib_name += '.dll'
} $else { } $else {
@ -772,7 +831,7 @@ pub fn build_compiler_command(source_file string, object_file string, build_conf
} }
// Add standard flags // Add standard flags
cmd += ' -Wall -Wextra -std=c++17' cmd += ' -Wall -Wextra'
// Add custom CFLAGS // Add custom CFLAGS
for flag in build_config.cflags { for flag in build_config.cflags {