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) {
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 {
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 {
// Link shared library
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}')
link_shared_library([obj_file], directive.unit_name, lib_output, build_config, config.SharedLibConfig{
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) {
println('Compiling ${lib_config.name}: ${src_file}...')
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}
} else {
if lib_config.verbose {
@ -478,6 +488,8 @@ 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)
// 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 {
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) {
println('Compiling ${tool_config.name}: ${src_file}...')
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}
} else {
if tool_config.verbose {
@ -569,13 +586,14 @@ fn get_target_verbose(target_config config.TargetConfig) bool {
fn compile_file(source_file string, object_file string, build_config config.BuildConfig, target_config config.TargetConfig) !string {
cmd := config.build_shared_compiler_command(source_file, object_file, build_config, target_config)
target_verbose := get_target_verbose(target_config)
if target_verbose {
println('Compile command: ${cmd}')
}
// Execute compile
res := os.execute(cmd)
if res.exit_code != 0 {
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 {
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)
obj_mtime := if os.is_file(object_file) {
os.file_last_mod_unix(object_file)

View File

@ -89,7 +89,7 @@ __global:
// default config
pub const default_config = BuildConfig{
project_name: 'project'
project_name: ''
src_dir: 'src'
build_dir: 'build'
bin_dir: 'bin'
@ -135,7 +135,8 @@ pub fn (mut build_config BuildConfig) parse_build_directives() ! {
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 {
continue
}
@ -292,10 +293,10 @@ pub fn parse_args() !BuildConfig {
else {
if !arg.starts_with('-') {
// Treat as project name or first source file
if build_config.project_name == 'project' {
if build_config.project_name == '' {
build_config.project_name = arg
} else {
// Add as default tool
// Add as default tool using the project name
mut default_tool := ToolConfig{
name: build_config.project_name
sources: [arg]
@ -553,6 +554,61 @@ pub fn parse_config_file(filename string) !BuildConfig {
if !tool.optimize { tool.optimize = build_config.optimize }
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
}
@ -630,7 +686,7 @@ pub fn build_shared_compiler_command(source_file string, object_file string, bui
}
// Add standard flags
cmd += ' -Wall -Wextra -std=c++17'
cmd += ' -Wall -Wextra'
// Add global CFLAGS
for flag in build_config.cflags {
@ -691,13 +747,16 @@ pub fn build_shared_linker_command(object_files []string, library_name string, o
}
// 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 {
lib_name += '.dll'
} $else {
lib_name += '.so'
}
cmd += ' -o ${output_path}/${lib_name}'
return cmd
}
@ -772,7 +831,7 @@ pub fn build_compiler_command(source_file string, object_file string, build_conf
}
// Add standard flags
cmd += ' -Wall -Wextra -std=c++17'
cmd += ' -Wall -Wextra'
// Add custom CFLAGS
for flag in build_config.cflags {