Add build graph preview functionality and enhance configuration parsing
- Introduced GraphNodeSummary and GraphPlanSummary structures for build graph representation. - Implemented preview_build_graph function to generate a summary of the build graph. - Refactored configuration parsing to improve handling of boolean values and inheritance of lists. - Added unit tests for build graph preview and configuration parsing. I still don't know how to write tests.main
parent
d89a53de94
commit
4347a882a2
|
|
@ -59,6 +59,57 @@ struct BuildGraph {
|
|||
unresolved map[string][]string
|
||||
}
|
||||
|
||||
pub struct GraphNodeSummary {
|
||||
pub:
|
||||
id string
|
||||
name string
|
||||
target BuildTarget
|
||||
dependencies []string
|
||||
raw_dependencies []string
|
||||
is_directive bool
|
||||
output_path string
|
||||
}
|
||||
|
||||
pub struct GraphPlanSummary {
|
||||
pub:
|
||||
nodes []GraphNodeSummary
|
||||
order []string
|
||||
unresolved map[string][]string
|
||||
}
|
||||
|
||||
pub fn preview_build_graph(build_config &config.BuildConfig) !GraphPlanSummary {
|
||||
graph := plan_build_graph(build_config)!
|
||||
|
||||
mut nodes := []GraphNodeSummary{}
|
||||
for node in graph.nodes {
|
||||
nodes << GraphNodeSummary{
|
||||
id: node.id
|
||||
name: node.name
|
||||
target: node.target
|
||||
dependencies: node.dependencies.clone()
|
||||
raw_dependencies: node.raw_dependencies.clone()
|
||||
is_directive: node.is_directive
|
||||
output_path: node.output_path
|
||||
}
|
||||
}
|
||||
|
||||
mut order := []string{}
|
||||
for idx in graph.order {
|
||||
order << graph.nodes[idx].id
|
||||
}
|
||||
|
||||
mut unresolved := map[string][]string{}
|
||||
for id, deps in graph.unresolved {
|
||||
unresolved[id] = deps.clone()
|
||||
}
|
||||
|
||||
return GraphPlanSummary{
|
||||
nodes: nodes
|
||||
order: order
|
||||
unresolved: unresolved
|
||||
}
|
||||
}
|
||||
|
||||
struct DirectiveBuildContext {
|
||||
source string
|
||||
object string
|
||||
|
|
@ -653,6 +704,37 @@ fn auto_discover_sources(mut build_config config.BuildConfig) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the main project tool exists if it wasn't explicitly defined
|
||||
// This handles the case where config.ini defines other tools but not the main project tool
|
||||
mut main_tool_exists := false
|
||||
for tool in build_config.tools {
|
||||
if tool.name == build_config.project_name {
|
||||
main_tool_exists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !main_tool_exists {
|
||||
// Look for src/<project_name>.cpp
|
||||
// Really shit way to do it but meh, we'll figure this out soon enough.
|
||||
main_src := os.join_path(build_config.src_dir, '${build_config.project_name}.cpp')
|
||||
if os.is_file(main_src) {
|
||||
if build_config.verbose {
|
||||
println('Auto-discovered main project tool: ${build_config.project_name} from ${main_src}')
|
||||
}
|
||||
|
||||
new_tool := config.ToolConfig{
|
||||
name: build_config.project_name
|
||||
sources: [main_src]
|
||||
debug: build_config.debug
|
||||
optimize: build_config.optimize
|
||||
verbose: build_config.verbose
|
||||
libraries: [] // Will inherit global libs during link
|
||||
}
|
||||
build_config.tools << new_tool
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clean(build_config config.BuildConfig) {
|
||||
|
|
|
|||
134
config/config.v
134
config/config.v
|
|
@ -203,6 +203,30 @@ fn merge_unique(mut target []string, additions []string) {
|
|||
}
|
||||
}
|
||||
|
||||
fn resolve_bool(base bool, override_str string, scope string, field string, mut warnings []string) bool {
|
||||
if override_str.trim_space() == '' {
|
||||
return base
|
||||
}
|
||||
return parse_bool_str(override_str) or {
|
||||
warnings << 'Invalid boolean value for ${scope} ${field}: ${override_str}'
|
||||
base
|
||||
}
|
||||
}
|
||||
|
||||
fn inherit_list(primary []string, inherited []string) []string {
|
||||
mut merged := primary.clone()
|
||||
merge_unique(mut merged, inherited)
|
||||
return merged
|
||||
}
|
||||
|
||||
fn scope_label(name string, kind string) string {
|
||||
trimmed := name.trim_space()
|
||||
if trimmed != '' {
|
||||
return '${kind} ${trimmed}'
|
||||
}
|
||||
return kind
|
||||
}
|
||||
|
||||
fn normalize_raw_config(raw RawBuildConfig, mut warnings []string) BuildConfig {
|
||||
mut cfg := default_config
|
||||
default_shared := SharedLibConfig{}
|
||||
|
|
@ -230,113 +254,49 @@ fn normalize_raw_config(raw RawBuildConfig, mut warnings []string) BuildConfig {
|
|||
cfg.dependencies_dir = raw.global.dependencies_dir
|
||||
}
|
||||
|
||||
if raw.global.debug_str != '' {
|
||||
cfg.debug = parse_bool_str(raw.global.debug_str) or {
|
||||
warnings << 'Invalid boolean value for global.debug: ${raw.global.debug_str}'
|
||||
cfg.debug
|
||||
}
|
||||
}
|
||||
if raw.global.optimize_str != '' {
|
||||
cfg.optimize = parse_bool_str(raw.global.optimize_str) or {
|
||||
warnings << 'Invalid boolean value for global.optimize: ${raw.global.optimize_str}'
|
||||
cfg.optimize
|
||||
}
|
||||
}
|
||||
if raw.global.verbose_str != '' {
|
||||
cfg.verbose = parse_bool_str(raw.global.verbose_str) or {
|
||||
warnings << 'Invalid boolean value for global.verbose: ${raw.global.verbose_str}'
|
||||
cfg.verbose
|
||||
}
|
||||
}
|
||||
if raw.global.parallel_str != '' {
|
||||
cfg.parallel_compilation = parse_bool_str(raw.global.parallel_str) or {
|
||||
warnings << 'Invalid boolean value for global.parallel_compilation: ${raw.global.parallel_str}'
|
||||
cfg.parallel_compilation
|
||||
}
|
||||
}
|
||||
cfg.debug = resolve_bool(cfg.debug, raw.global.debug_str, 'global', 'debug', mut warnings)
|
||||
cfg.optimize = resolve_bool(cfg.optimize, raw.global.optimize_str, 'global', 'optimize', mut warnings)
|
||||
cfg.verbose = resolve_bool(cfg.verbose, raw.global.verbose_str, 'global', 'verbose', mut warnings)
|
||||
cfg.parallel_compilation = resolve_bool(cfg.parallel_compilation, raw.global.parallel_str, 'global', 'parallel_compilation', mut warnings)
|
||||
|
||||
cfg.include_dirs << raw.global.include_dirs
|
||||
cfg.lib_search_paths << raw.global.lib_search_paths
|
||||
cfg.libraries << raw.global.libraries
|
||||
cfg.cflags << raw.global.cflags
|
||||
cfg.ldflags << raw.global.ldflags
|
||||
cfg.include_dirs = inherit_list(raw.global.include_dirs, cfg.include_dirs)
|
||||
cfg.lib_search_paths = inherit_list(raw.global.lib_search_paths, cfg.lib_search_paths)
|
||||
cfg.libraries = inherit_list(raw.global.libraries, cfg.libraries)
|
||||
cfg.cflags = inherit_list(raw.global.cflags, cfg.cflags)
|
||||
cfg.ldflags = inherit_list(raw.global.ldflags, cfg.ldflags)
|
||||
|
||||
for raw_lib in raw.shared_libs {
|
||||
scope := scope_label(raw_lib.name, 'shared_lib')
|
||||
mut lib := SharedLibConfig{
|
||||
name: raw_lib.name
|
||||
output_dir: if raw_lib.output_dir != '' { raw_lib.output_dir } else { default_shared.output_dir }
|
||||
sources: raw_lib.sources.clone()
|
||||
libraries: raw_lib.libraries.clone()
|
||||
debug: cfg.debug
|
||||
optimize: cfg.optimize
|
||||
verbose: cfg.verbose
|
||||
debug: resolve_bool(cfg.debug, raw_lib.debug_str, scope, 'debug', mut warnings)
|
||||
optimize: resolve_bool(cfg.optimize, raw_lib.optimize_str, scope, 'optimize', mut warnings)
|
||||
verbose: resolve_bool(cfg.verbose, raw_lib.verbose_str, scope, 'verbose', mut warnings)
|
||||
}
|
||||
lib.include_dirs = raw_lib.include_dirs.clone()
|
||||
lib.cflags = raw_lib.cflags.clone()
|
||||
lib.ldflags = raw_lib.ldflags.clone()
|
||||
|
||||
if raw_lib.debug_str != '' {
|
||||
lib.debug = parse_bool_str(raw_lib.debug_str) or {
|
||||
warnings << 'Invalid boolean value for shared_lib ${raw_lib.name} debug: ${raw_lib.debug_str}'
|
||||
lib.debug
|
||||
}
|
||||
}
|
||||
if raw_lib.optimize_str != '' {
|
||||
lib.optimize = parse_bool_str(raw_lib.optimize_str) or {
|
||||
warnings << 'Invalid boolean value for shared_lib ${raw_lib.name} optimize: ${raw_lib.optimize_str}'
|
||||
lib.optimize
|
||||
}
|
||||
}
|
||||
if raw_lib.verbose_str != '' {
|
||||
lib.verbose = parse_bool_str(raw_lib.verbose_str) or {
|
||||
warnings << 'Invalid boolean value for shared_lib ${raw_lib.name} verbose: ${raw_lib.verbose_str}'
|
||||
lib.verbose
|
||||
}
|
||||
}
|
||||
|
||||
merge_unique(mut lib.include_dirs, cfg.include_dirs)
|
||||
merge_unique(mut lib.cflags, cfg.cflags)
|
||||
merge_unique(mut lib.ldflags, cfg.ldflags)
|
||||
lib.include_dirs = inherit_list(raw_lib.include_dirs, cfg.include_dirs)
|
||||
lib.cflags = inherit_list(raw_lib.cflags, cfg.cflags)
|
||||
lib.ldflags = inherit_list(raw_lib.ldflags, cfg.ldflags)
|
||||
|
||||
cfg.shared_libs << lib
|
||||
}
|
||||
|
||||
for raw_tool in raw.tools {
|
||||
scope := scope_label(raw_tool.name, 'tool')
|
||||
mut tool := ToolConfig{
|
||||
name: raw_tool.name
|
||||
output_dir: if raw_tool.output_dir != '' { raw_tool.output_dir } else { default_tool.output_dir }
|
||||
sources: raw_tool.sources.clone()
|
||||
libraries: raw_tool.libraries.clone()
|
||||
debug: cfg.debug
|
||||
optimize: cfg.optimize
|
||||
verbose: cfg.verbose
|
||||
debug: resolve_bool(cfg.debug, raw_tool.debug_str, scope, 'debug', mut warnings)
|
||||
optimize: resolve_bool(cfg.optimize, raw_tool.optimize_str, scope, 'optimize', mut warnings)
|
||||
verbose: resolve_bool(cfg.verbose, raw_tool.verbose_str, scope, 'verbose', mut warnings)
|
||||
}
|
||||
tool.include_dirs = raw_tool.include_dirs.clone()
|
||||
tool.cflags = raw_tool.cflags.clone()
|
||||
tool.ldflags = raw_tool.ldflags.clone()
|
||||
|
||||
if raw_tool.debug_str != '' {
|
||||
tool.debug = parse_bool_str(raw_tool.debug_str) or {
|
||||
warnings << 'Invalid boolean value for tool ${raw_tool.name} debug: ${raw_tool.debug_str}'
|
||||
tool.debug
|
||||
}
|
||||
}
|
||||
if raw_tool.optimize_str != '' {
|
||||
tool.optimize = parse_bool_str(raw_tool.optimize_str) or {
|
||||
warnings << 'Invalid boolean value for tool ${raw_tool.name} optimize: ${raw_tool.optimize_str}'
|
||||
tool.optimize
|
||||
}
|
||||
}
|
||||
if raw_tool.verbose_str != '' {
|
||||
tool.verbose = parse_bool_str(raw_tool.verbose_str) or {
|
||||
warnings << 'Invalid boolean value for tool ${raw_tool.name} verbose: ${raw_tool.verbose_str}'
|
||||
tool.verbose
|
||||
}
|
||||
}
|
||||
|
||||
merge_unique(mut tool.include_dirs, cfg.include_dirs)
|
||||
merge_unique(mut tool.cflags, cfg.cflags)
|
||||
merge_unique(mut tool.ldflags, cfg.ldflags)
|
||||
tool.include_dirs = inherit_list(raw_tool.include_dirs, cfg.include_dirs)
|
||||
tool.cflags = inherit_list(raw_tool.cflags, cfg.cflags)
|
||||
tool.ldflags = inherit_list(raw_tool.ldflags, cfg.ldflags)
|
||||
|
||||
cfg.tools << tool
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,31 +23,33 @@ pub fn extract_dependencies(source_file string) ![]string {
|
|||
in_string = false
|
||||
current_string_char = rune(0)
|
||||
} else if !in_string {
|
||||
if c == `#` && i + 1 < content.len && content[i + 1] == `i` {
|
||||
// Found #include
|
||||
i += 7 // skip "#include"
|
||||
if c == `#` && i + 8 <= content.len && content[i..].starts_with('#include') {
|
||||
i += '#include'.len
|
||||
for i < content.len && content[i].is_space() {
|
||||
i++
|
||||
}
|
||||
|
||||
if i < content.len && (content[i] == `"` || content[i] == `<`) {
|
||||
mut quote_char := content[i]
|
||||
|
||||
if i < content.len && (content[i] == `"` || content[i] == `<` || content[i] == `'`) {
|
||||
opening := content[i]
|
||||
closing := match opening {
|
||||
`"` { `"` }
|
||||
`'` { `'` }
|
||||
`<` { `>` }
|
||||
else { opening }
|
||||
}
|
||||
i++
|
||||
mut include_path := []u8{}
|
||||
|
||||
for i < content.len && content[i] != quote_char {
|
||||
|
||||
for i < content.len && content[i] != closing {
|
||||
include_path << content[i]
|
||||
i++
|
||||
}
|
||||
|
||||
|
||||
if include_path.len > 0 {
|
||||
include_name := include_path.bytestr()
|
||||
if include_name.contains('/') || include_name.contains('\\') {
|
||||
// Relative path
|
||||
dependencies << include_name
|
||||
} else {
|
||||
// System include - we could search standard paths
|
||||
// but for now just add the name
|
||||
dependencies << include_name
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
module tests
|
||||
|
||||
import os
|
||||
import builder
|
||||
import config
|
||||
|
||||
fn test_preview_build_graph_orders_dependencies() {
|
||||
tmp := new_temp_dir('lana_graph')
|
||||
defer {
|
||||
os.rmdir_all(tmp) or {}
|
||||
}
|
||||
|
||||
src_dir := os.join_path(tmp, 'src')
|
||||
lib_dir := os.join_path(src_dir, 'lib')
|
||||
tool_dir := os.join_path(src_dir, 'tools')
|
||||
os.mkdir_all(lib_dir) or { panic(err) }
|
||||
os.mkdir_all(tool_dir) or { panic(err) }
|
||||
|
||||
core_src := os.join_path(lib_dir, 'core.cpp')
|
||||
tool_src := os.join_path(tool_dir, 'demo.cpp')
|
||||
os.write_file(core_src, '// core stub\n') or { panic(err) }
|
||||
os.write_file(tool_src, '// tool stub\n') or { panic(err) }
|
||||
|
||||
mut cfg := config.BuildConfig{
|
||||
project_name: 'demo'
|
||||
src_dir: src_dir
|
||||
build_dir: os.join_path(tmp, 'build')
|
||||
bin_dir: os.join_path(tmp, 'bin')
|
||||
toolchain: 'gcc'
|
||||
compiler: 'g++'
|
||||
debug: true
|
||||
shared_libs: [
|
||||
config.SharedLibConfig{
|
||||
name: 'core'
|
||||
sources: [core_src]
|
||||
}
|
||||
]
|
||||
tools: [
|
||||
config.ToolConfig{
|
||||
name: 'demo'
|
||||
sources: [tool_src]
|
||||
libraries: ['core']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
summary := builder.preview_build_graph(&cfg) or { panic(err) }
|
||||
|
||||
assert summary.nodes.len == 2
|
||||
assert summary.unresolved.len == 0
|
||||
|
||||
mut shared_found := false
|
||||
mut tool_found := false
|
||||
for node in summary.nodes {
|
||||
if node.id == 'shared:core' {
|
||||
shared_found = true
|
||||
assert node.dependencies.len == 0
|
||||
}
|
||||
if node.id == 'tool:demo' {
|
||||
tool_found = true
|
||||
assert node.dependencies.contains('shared:core')
|
||||
}
|
||||
}
|
||||
|
||||
assert shared_found
|
||||
assert tool_found
|
||||
assert summary.order.len == 2
|
||||
assert summary.order[0] == 'shared:core'
|
||||
assert summary.order[1] == 'tool:demo'
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
module tests
|
||||
|
||||
import os
|
||||
import config
|
||||
|
||||
fn test_parse_config_file_reads_sections() {
|
||||
tmp := new_temp_dir('lana_config')
|
||||
defer {
|
||||
os.rmdir_all(tmp) or {}
|
||||
}
|
||||
|
||||
config_path := os.join_path(tmp, 'config.ini')
|
||||
config_content := '[global]\nproject_name = sample\nsrc_dir = src\ndebug = false\noptimize = true\nparallel_compilation = false\ninclude_dirs = include, external/include\nlibraries = cli\ncflags = -Wall -Wextra\n\n[shared_libs]\nname = core\nsources = src/lib/core.cpp\ninclude_dirs = include\ncflags = -fPIC\nlibraries = \n\n[tools]\nname = sample\nsources = src/main.cpp\nlibraries = core\n'
|
||||
os.write_file(config_path, config_content) or { panic(err) }
|
||||
|
||||
cfg := config.parse_config_file(config_path) or { panic(err) }
|
||||
|
||||
assert cfg.project_name == 'sample'
|
||||
assert cfg.src_dir == 'src'
|
||||
assert !cfg.debug
|
||||
assert cfg.optimize
|
||||
assert !cfg.parallel_compilation
|
||||
assert cfg.include_dirs.len == 2
|
||||
assert cfg.include_dirs.contains('include')
|
||||
assert cfg.include_dirs.contains('external/include')
|
||||
assert cfg.cflags.contains('-Wall')
|
||||
assert cfg.cflags.contains('-Wextra')
|
||||
assert cfg.libraries == ['cli']
|
||||
assert cfg.shared_libs.len == 1
|
||||
shared_cfg := cfg.shared_libs[0]
|
||||
assert shared_cfg.name == 'core'
|
||||
assert shared_cfg.include_dirs.contains('include')
|
||||
assert shared_cfg.cflags.contains('-fPIC')
|
||||
assert cfg.tools.len == 1
|
||||
tool := cfg.tools[0]
|
||||
assert tool.name == 'sample'
|
||||
assert tool.libraries == ['core']
|
||||
}
|
||||
|
||||
fn test_parse_build_directives_extracts_units() {
|
||||
tmp := new_temp_dir('lana_directives')
|
||||
defer {
|
||||
os.rmdir_all(tmp) or {}
|
||||
}
|
||||
|
||||
src_dir := os.join_path(tmp, 'src')
|
||||
tool_dir := os.join_path(src_dir, 'tools')
|
||||
lib_dir := os.join_path(src_dir, 'lib')
|
||||
os.mkdir_all(tool_dir) or { panic(err) }
|
||||
os.mkdir_all(lib_dir) or { panic(err) }
|
||||
|
||||
tool_source := '// build-directive: unit-name(tools/example)\n// build-directive: depends-units(lib/cli)\n// build-directive: link(cli.so)\n// build-directive: out(tools/example)\n// build-directive: cflags(-DTEST)\n// build-directive: ldflags(-pthread)\n// build-directive: shared(false)\n'
|
||||
os.write_file(os.join_path(tool_dir, 'example.cpp'), tool_source) or { panic(err) }
|
||||
|
||||
shared_source := '// build-directive: unit-name(lib/cli)\n// build-directive: depends-units()\n// build-directive: link()\n// build-directive: out(lib/cli)\n// build-directive: shared(true)\n'
|
||||
os.write_file(os.join_path(lib_dir, 'cli.cpp'), shared_source) or { panic(err) }
|
||||
|
||||
mut cfg := config.BuildConfig{
|
||||
project_name: 'sample'
|
||||
src_dir: src_dir
|
||||
build_dir: os.join_path(tmp, 'build')
|
||||
bin_dir: os.join_path(tmp, 'bin')
|
||||
}
|
||||
|
||||
cfg.parse_build_directives() or { panic(err) }
|
||||
|
||||
assert cfg.build_directives.len == 2
|
||||
|
||||
mut tool_found := false
|
||||
mut shared_found := false
|
||||
for directive in cfg.build_directives {
|
||||
if directive.unit_name == 'tools/example' {
|
||||
tool_found = true
|
||||
assert directive.depends_units == ['lib/cli']
|
||||
assert directive.link_libs == ['cli.so']
|
||||
assert directive.output_path == 'tools/example'
|
||||
assert directive.cflags.contains('-DTEST')
|
||||
assert directive.ldflags.contains('-pthread')
|
||||
assert !directive.is_shared
|
||||
}
|
||||
if directive.unit_name == 'lib/cli' {
|
||||
shared_found = true
|
||||
assert directive.is_shared
|
||||
}
|
||||
}
|
||||
|
||||
assert tool_found
|
||||
assert shared_found
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
module tests
|
||||
|
||||
import os
|
||||
import deps
|
||||
import config
|
||||
|
||||
fn test_extract_dependencies_finds_includes() {
|
||||
tmp := new_temp_dir('lana_deps')
|
||||
defer {
|
||||
os.rmdir_all(tmp) or {}
|
||||
}
|
||||
|
||||
source_path := os.join_path(tmp, 'sample.cpp')
|
||||
source_content := '#include "foo/bar.h"\n#include <vector>\nint main() { return 0; }\n'
|
||||
os.write_file(source_path, source_content) or { panic(err) }
|
||||
|
||||
parsed := deps.extract_dependencies(source_path) or { panic(err) }
|
||||
|
||||
assert parsed.any(it.contains('foo/bar.h'))
|
||||
assert parsed.any(it.contains('vector'))
|
||||
}
|
||||
|
||||
fn test_fetch_dependencies_runs_build_commands() {
|
||||
tmp := new_temp_dir('lana_fetch')
|
||||
defer {
|
||||
os.rmdir_all(tmp) or {}
|
||||
}
|
||||
|
||||
dep_root := os.join_path(tmp, 'deps')
|
||||
mut cfg := config.BuildConfig{
|
||||
dependencies_dir: dep_root
|
||||
dependencies: [
|
||||
config.Dependency{
|
||||
name: 'local'
|
||||
extract_to: 'localpkg'
|
||||
build_cmds: ['touch built.txt']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
deps.fetch_dependencies(cfg) or { panic(err) }
|
||||
|
||||
assert os.is_dir(os.join_path(dep_root, 'localpkg'))
|
||||
assert os.is_file(os.join_path(dep_root, 'localpkg', 'built.txt'))
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
module tests
|
||||
|
||||
import os
|
||||
import builder
|
||||
import config
|
||||
|
||||
fn test_auto_discover_main_tool_when_other_tools_exist() {
|
||||
tmp := new_temp_dir('lana_discovery')
|
||||
defer {
|
||||
os.rmdir_all(tmp) or {}
|
||||
}
|
||||
|
||||
src_dir := os.join_path(tmp, 'src')
|
||||
tools_dir := os.join_path(src_dir, 'tools')
|
||||
os.mkdir_all(tools_dir) or { panic(err) }
|
||||
|
||||
// Create a tool that IS in config
|
||||
os.write_file(os.join_path(tools_dir, 'existing.cpp'), 'int main(){}') or { panic(err) }
|
||||
|
||||
// Create a main source that SHOULD be discovered as the main tool
|
||||
os.write_file(os.join_path(src_dir, 'testproj.cpp'), 'int main(){}') or { panic(err) }
|
||||
|
||||
mut cfg := config.BuildConfig{
|
||||
project_name: 'testproj'
|
||||
src_dir: src_dir
|
||||
tools: [
|
||||
config.ToolConfig{
|
||||
name: 'existing'
|
||||
sources: [os.join_path(tools_dir, 'existing.cpp')]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// Run auto-discovery
|
||||
builder.auto_discover_sources(mut cfg)
|
||||
|
||||
// Check if testproj tool was added
|
||||
mut found := false
|
||||
for tool in cfg.tools {
|
||||
if tool.name == 'testproj' {
|
||||
found = true
|
||||
assert tool.sources.len == 1
|
||||
assert tool.sources[0].ends_with('testproj.cpp')
|
||||
}
|
||||
}
|
||||
assert found
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
module tests
|
||||
|
||||
import os
|
||||
import rand
|
||||
|
||||
fn new_temp_dir(prefix string) string {
|
||||
id := rand.uuid_v4()
|
||||
path := os.join_path(os.temp_dir(), '${prefix}_${id}')
|
||||
os.mkdir_all(path) or { panic(err) }
|
||||
return path
|
||||
}
|
||||
Loading…
Reference in New Issue