Add static linking support and related configuration options
parent
f74b93ddf6
commit
1a233baed3
|
|
@ -592,6 +592,9 @@ fn build_directive_tool(directive config.BuildDirective, build_config config.Bui
|
||||||
println('Linking executable: ${executable}')
|
println('Linking executable: ${executable}')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Directive static(true/false) overrides global config, otherwise inherit global setting
|
||||||
|
use_static := directive.static_link or { build_config.static_link }
|
||||||
|
|
||||||
link_tool([ctx.object], executable, build_config, toolchain, config.ToolConfig{
|
link_tool([ctx.object], executable, build_config, toolchain, config.ToolConfig{
|
||||||
name: directive.unit_name
|
name: directive.unit_name
|
||||||
libraries: directive.link_libs
|
libraries: directive.link_libs
|
||||||
|
|
@ -599,6 +602,7 @@ fn build_directive_tool(directive config.BuildDirective, build_config config.Bui
|
||||||
optimize: build_config.optimize
|
optimize: build_config.optimize
|
||||||
verbose: build_config.verbose
|
verbose: build_config.verbose
|
||||||
ldflags: directive.ldflags
|
ldflags: directive.ldflags
|
||||||
|
static_link: use_static
|
||||||
}) or {
|
}) or {
|
||||||
return error('Failed to link executable ${directive.unit_name}')
|
return error('Failed to link executable ${directive.unit_name}')
|
||||||
}
|
}
|
||||||
|
|
@ -716,9 +720,25 @@ fn auto_discover_sources(mut build_config config.BuildConfig) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Also check if the main project exists as a build directive
|
||||||
|
if !main_tool_exists {
|
||||||
|
for directive in build_config.build_directives {
|
||||||
|
// Check if directive unit_name matches project_name or ends with project_name
|
||||||
|
if directive.unit_name == build_config.project_name {
|
||||||
|
main_tool_exists = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Also match "fossvg" to directive "fossvg" or "tools/fossvg"
|
||||||
|
parts := directive.unit_name.split('/')
|
||||||
|
if parts.len > 0 && parts[parts.len - 1] == build_config.project_name {
|
||||||
|
main_tool_exists = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !main_tool_exists {
|
if !main_tool_exists {
|
||||||
// Look for src/<project_name>.cpp
|
// 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')
|
main_src := os.join_path(build_config.src_dir, '${build_config.project_name}.cpp')
|
||||||
if os.is_file(main_src) {
|
if os.is_file(main_src) {
|
||||||
if build_config.verbose {
|
if build_config.verbose {
|
||||||
|
|
@ -978,6 +998,49 @@ fn link_shared_library(object_files []string, library_name string, output_path s
|
||||||
println(colorize('Linker output:\n${res.output}', ansi_red))
|
println(colorize('Linker output:\n${res.output}', ansi_red))
|
||||||
return error('Shared library linking failed with exit code ${res.exit_code}: ${res.output}')
|
return error('Shared library linking failed with exit code ${res.exit_code}: ${res.output}')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if static archive is needed: either global static_link or any tool has static_link
|
||||||
|
needs_static_archive := build_config.static_link || any_tool_needs_static_link(build_config)
|
||||||
|
if needs_static_archive {
|
||||||
|
create_static_archive(object_files, library_name, output_path, build_config, lib_config)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// any_tool_needs_static_link returns true if any tool in the config has static_link enabled
|
||||||
|
pub fn any_tool_needs_static_link(build_config config.BuildConfig) bool {
|
||||||
|
for tool in build_config.tools {
|
||||||
|
if tool.static_link {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_static_archive creates a static library (.a) from object files using ar
|
||||||
|
fn create_static_archive(object_files []string, library_name string, output_path string, build_config config.BuildConfig, lib_config config.SharedLibConfig) ! {
|
||||||
|
// Extract base name from library_name (e.g., "lib/cli" -> "cli")
|
||||||
|
parts := library_name.split('/')
|
||||||
|
base_name := if parts.len > 0 { parts[parts.len - 1] } else { library_name }
|
||||||
|
|
||||||
|
archive_path := os.join_path(output_path, '${base_name}.a')
|
||||||
|
|
||||||
|
// Build ar command: ar rcs <archive> <objects...>
|
||||||
|
mut cmd := 'ar rcs ${archive_path}'
|
||||||
|
for obj_file in object_files {
|
||||||
|
cmd += ' ${obj_file}'
|
||||||
|
}
|
||||||
|
|
||||||
|
if lib_config.verbose || build_config.verbose {
|
||||||
|
println('Creating static archive: ${archive_path}')
|
||||||
|
println('Archive command: ${cmd}')
|
||||||
|
}
|
||||||
|
|
||||||
|
ar_res := os.execute(cmd)
|
||||||
|
if ar_res.exit_code != 0 {
|
||||||
|
println(colorize('Archive command: ${cmd}', ansi_cyan))
|
||||||
|
println(colorize('Archive output:\n${ar_res.output}', ansi_red))
|
||||||
|
return error('Static archive creation failed with exit code ${ar_res.exit_code}: ${ar_res.output}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link_tool(object_files []string, executable string, build_config config.BuildConfig, toolchain config.Toolchain, tool_config config.ToolConfig) ! {
|
fn link_tool(object_files []string, executable string, build_config config.BuildConfig, toolchain config.Toolchain, tool_config config.ToolConfig) ! {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ pub mut:
|
||||||
cflags []string // file-specific CFLAGS
|
cflags []string // file-specific CFLAGS
|
||||||
ldflags []string // file-specific LDFLAGS
|
ldflags []string // file-specific LDFLAGS
|
||||||
is_shared bool // whether this is a shared library
|
is_shared bool // whether this is a shared library
|
||||||
|
static_link ?bool // override global static_link setting (none = use global)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TargetConfig is a sum type for build targets (shared lib or tool)
|
// TargetConfig is a sum type for build targets (shared lib or tool)
|
||||||
|
|
@ -46,6 +47,7 @@ pub mut:
|
||||||
debug bool
|
debug bool
|
||||||
optimize bool
|
optimize bool
|
||||||
verbose bool
|
verbose bool
|
||||||
|
static_link bool // link statically to produce self-contained binary
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dependency represents an external dependency to download/extract
|
// Dependency represents an external dependency to download/extract
|
||||||
|
|
@ -83,6 +85,7 @@ pub mut:
|
||||||
dependencies_dir string = 'dependencies' // external dependencies
|
dependencies_dir string = 'dependencies' // external dependencies
|
||||||
parallel_compilation bool = true // enable parallel builds
|
parallel_compilation bool = true // enable parallel builds
|
||||||
dependencies []Dependency
|
dependencies []Dependency
|
||||||
|
static_link bool // global static linking flag for tools
|
||||||
|
|
||||||
// Build directives from source files
|
// Build directives from source files
|
||||||
build_directives []BuildDirective
|
build_directives []BuildDirective
|
||||||
|
|
@ -100,6 +103,7 @@ mut:
|
||||||
optimize_str string
|
optimize_str string
|
||||||
verbose_str string
|
verbose_str string
|
||||||
parallel_str string
|
parallel_str string
|
||||||
|
static_link_str string
|
||||||
include_dirs []string
|
include_dirs []string
|
||||||
lib_search_paths []string
|
lib_search_paths []string
|
||||||
libraries []string
|
libraries []string
|
||||||
|
|
@ -134,6 +138,7 @@ mut:
|
||||||
debug_str string
|
debug_str string
|
||||||
optimize_str string
|
optimize_str string
|
||||||
verbose_str string
|
verbose_str string
|
||||||
|
static_link_str string
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RawDependencyConfig {
|
struct RawDependencyConfig {
|
||||||
|
|
@ -259,6 +264,7 @@ fn normalize_raw_config(raw RawBuildConfig, mut warnings []string) BuildConfig {
|
||||||
cfg.optimize = resolve_bool(cfg.optimize, raw.global.optimize_str, 'global', 'optimize', 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.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.parallel_compilation = resolve_bool(cfg.parallel_compilation, raw.global.parallel_str, 'global', 'parallel_compilation', mut warnings)
|
||||||
|
cfg.static_link = resolve_bool(cfg.static_link, raw.global.static_link_str, 'global', 'static_link', mut warnings)
|
||||||
|
|
||||||
cfg.include_dirs = inherit_list(raw.global.include_dirs, cfg.include_dirs)
|
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.lib_search_paths = inherit_list(raw.global.lib_search_paths, cfg.lib_search_paths)
|
||||||
|
|
@ -294,6 +300,7 @@ fn normalize_raw_config(raw RawBuildConfig, mut warnings []string) BuildConfig {
|
||||||
debug: resolve_bool(cfg.debug, raw_tool.debug_str, scope, 'debug', mut warnings)
|
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)
|
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)
|
verbose: resolve_bool(cfg.verbose, raw_tool.verbose_str, scope, 'verbose', mut warnings)
|
||||||
|
static_link: resolve_bool(cfg.static_link, raw_tool.static_link_str, scope, 'static_link', mut warnings)
|
||||||
}
|
}
|
||||||
tool.include_dirs = inherit_list(raw_tool.include_dirs, cfg.include_dirs)
|
tool.include_dirs = inherit_list(raw_tool.include_dirs, cfg.include_dirs)
|
||||||
tool.cflags = inherit_list(raw_tool.cflags, cfg.cflags)
|
tool.cflags = inherit_list(raw_tool.cflags, cfg.cflags)
|
||||||
|
|
@ -370,6 +377,8 @@ pub fn (mut build_config BuildConfig) parse_build_directives() ! {
|
||||||
mut file_cflags := []string{}
|
mut file_cflags := []string{}
|
||||||
mut file_ldflags := []string{}
|
mut file_ldflags := []string{}
|
||||||
mut is_shared := false
|
mut is_shared := false
|
||||||
|
mut static_override := false
|
||||||
|
mut has_static_override := false
|
||||||
|
|
||||||
for line1 in lines {
|
for line1 in lines {
|
||||||
line := line1.trim_space()
|
line := line1.trim_space()
|
||||||
|
|
@ -420,6 +429,10 @@ pub fn (mut build_config BuildConfig) parse_build_directives() ! {
|
||||||
'shared' {
|
'shared' {
|
||||||
is_shared = directive_value == 'true'
|
is_shared = directive_value == 'true'
|
||||||
}
|
}
|
||||||
|
'static' {
|
||||||
|
static_override = directive_value == 'true'
|
||||||
|
has_static_override = true
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if build_config.verbose {
|
if build_config.verbose {
|
||||||
println('Warning: Unknown build directive: ${directive_type} in ${src_file}')
|
println('Warning: Unknown build directive: ${directive_type} in ${src_file}')
|
||||||
|
|
@ -437,6 +450,7 @@ pub fn (mut build_config BuildConfig) parse_build_directives() ! {
|
||||||
cflags: file_cflags
|
cflags: file_cflags
|
||||||
ldflags: file_ldflags
|
ldflags: file_ldflags
|
||||||
is_shared: is_shared
|
is_shared: is_shared
|
||||||
|
static_link: if has_static_override { ?bool(static_override) } else { none }
|
||||||
}
|
}
|
||||||
|
|
||||||
if build_config.verbose {
|
if build_config.verbose {
|
||||||
|
|
@ -464,6 +478,7 @@ pub fn parse_args() !BuildConfig {
|
||||||
'-O', '--optimize' { build_config.optimize = true; build_config.debug = false }
|
'-O', '--optimize' { build_config.optimize = true; build_config.debug = false }
|
||||||
'-v', '--verbose' { build_config.verbose = true }
|
'-v', '--verbose' { build_config.verbose = true }
|
||||||
'-p', '--parallel' { build_config.parallel_compilation = true }
|
'-p', '--parallel' { build_config.parallel_compilation = true }
|
||||||
|
'-s', '--static' { build_config.static_link = true }
|
||||||
'-o', '--output' {
|
'-o', '--output' {
|
||||||
if i + 1 < os.args.len {
|
if i + 1 < os.args.len {
|
||||||
build_config.project_name = os.args[i + 1]
|
build_config.project_name = os.args[i + 1]
|
||||||
|
|
@ -533,6 +548,7 @@ pub fn parse_args() !BuildConfig {
|
||||||
debug: build_config.debug
|
debug: build_config.debug
|
||||||
optimize: build_config.optimize
|
optimize: build_config.optimize
|
||||||
verbose: build_config.verbose
|
verbose: build_config.verbose
|
||||||
|
static_link: build_config.static_link
|
||||||
}
|
}
|
||||||
build_config.tools << tool_config
|
build_config.tools << tool_config
|
||||||
i += 2
|
i += 2
|
||||||
|
|
@ -551,6 +567,7 @@ pub fn parse_args() !BuildConfig {
|
||||||
debug: build_config.debug
|
debug: build_config.debug
|
||||||
optimize: build_config.optimize
|
optimize: build_config.optimize
|
||||||
verbose: build_config.verbose
|
verbose: build_config.verbose
|
||||||
|
static_link: build_config.static_link
|
||||||
}
|
}
|
||||||
build_config.tools << default_tool
|
build_config.tools << default_tool
|
||||||
}
|
}
|
||||||
|
|
@ -571,6 +588,7 @@ pub fn parse_args() !BuildConfig {
|
||||||
debug: build_config.debug
|
debug: build_config.debug
|
||||||
optimize: build_config.optimize
|
optimize: build_config.optimize
|
||||||
verbose: build_config.verbose
|
verbose: build_config.verbose
|
||||||
|
static_link: build_config.static_link
|
||||||
}
|
}
|
||||||
build_config.tools << default_tool
|
build_config.tools << default_tool
|
||||||
}
|
}
|
||||||
|
|
@ -657,6 +675,7 @@ pub fn parse_config_file(filename string) !BuildConfig {
|
||||||
'cflags' { raw.global.cflags << parse_space_list(value) }
|
'cflags' { raw.global.cflags << parse_space_list(value) }
|
||||||
'ldflags' { raw.global.ldflags << parse_space_list(value) }
|
'ldflags' { raw.global.ldflags << parse_space_list(value) }
|
||||||
'dependencies_dir' { raw.global.dependencies_dir = value }
|
'dependencies_dir' { raw.global.dependencies_dir = value }
|
||||||
|
'static_link' { raw.global.static_link_str = value }
|
||||||
else { warnings << 'Unknown global config key: ${key}' }
|
else { warnings << 'Unknown global config key: ${key}' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -697,6 +716,7 @@ pub fn parse_config_file(filename string) !BuildConfig {
|
||||||
'optimize' { tool.optimize_str = value }
|
'optimize' { tool.optimize_str = value }
|
||||||
'verbose' { tool.verbose_str = value }
|
'verbose' { tool.verbose_str = value }
|
||||||
'output_dir' { tool.output_dir = value }
|
'output_dir' { tool.output_dir = value }
|
||||||
|
'static_link' { tool.static_link_str = value }
|
||||||
else { warnings << 'Unknown tools key: ${key}' }
|
else { warnings << 'Unknown tools key: ${key}' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -935,6 +955,11 @@ fn common_tool_link_command(compiler string, object_files []string, executable s
|
||||||
}
|
}
|
||||||
mut cmd := '${binary}'
|
mut cmd := '${binary}'
|
||||||
|
|
||||||
|
// Add static linking flags if enabled
|
||||||
|
if tool_config.static_link {
|
||||||
|
cmd += ' -static'
|
||||||
|
}
|
||||||
|
|
||||||
cmd += ' -L${build_config.bin_dir}/lib'
|
cmd += ' -L${build_config.bin_dir}/lib'
|
||||||
for lib_path in build_config.lib_search_paths {
|
for lib_path in build_config.lib_search_paths {
|
||||||
cmd += ' -L${lib_path}'
|
cmd += ' -L${lib_path}'
|
||||||
|
|
@ -954,7 +979,19 @@ fn common_tool_link_command(compiler string, object_files []string, executable s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for library in tool_config.libraries {
|
// For static linking, reverse library order so dependencies come after dependents
|
||||||
|
// (static linker resolves symbols left-to-right, so A depending on B needs: -lA -lB)
|
||||||
|
libs := if tool_config.static_link {
|
||||||
|
mut reversed := []string{}
|
||||||
|
for i := tool_config.libraries.len - 1; i >= 0; i-- {
|
||||||
|
reversed << tool_config.libraries[i]
|
||||||
|
}
|
||||||
|
reversed
|
||||||
|
} else {
|
||||||
|
tool_config.libraries
|
||||||
|
}
|
||||||
|
|
||||||
|
for library in libs {
|
||||||
if library != '' {
|
if library != '' {
|
||||||
mut libfile := library
|
mut libfile := library
|
||||||
if libfile.starts_with('lib/') {
|
if libfile.starts_with('lib/') {
|
||||||
|
|
@ -964,7 +1001,12 @@ fn common_tool_link_command(compiler string, object_files []string, executable s
|
||||||
if libfile.ends_with('.so') {
|
if libfile.ends_with('.so') {
|
||||||
libfile = libfile.replace('.so', '')
|
libfile = libfile.replace('.so', '')
|
||||||
}
|
}
|
||||||
cmd += ' -l:${libfile}.so'
|
// Use static library (.a) when static linking, otherwise shared (.so)
|
||||||
|
if tool_config.static_link {
|
||||||
|
cmd += ' -l:${libfile}.a'
|
||||||
|
} else {
|
||||||
|
cmd += ' -l:${libfile}.so'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -975,6 +1017,11 @@ fn common_tool_link_command(compiler string, object_files []string, executable s
|
||||||
cmd += ' ${flag}'
|
cmd += ' ${flag}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add static runtime flags for fully static binary
|
||||||
|
if tool_config.static_link {
|
||||||
|
cmd += ' -static-libgcc -static-libstdc++'
|
||||||
|
}
|
||||||
|
|
||||||
cmd += ' -o ${executable}'
|
cmd += ' -o ${executable}'
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ Global Options:
|
||||||
-O, --optimize Enable optimization (-O3, disables debug).
|
-O, --optimize Enable optimization (-O3, disables debug).
|
||||||
-v, --verbose Verbose logging (graph + compiler commands).
|
-v, --verbose Verbose logging (graph + compiler commands).
|
||||||
-p, --parallel Force parallel compilation worker pool.
|
-p, --parallel Force parallel compilation worker pool.
|
||||||
|
-s, --static Link tools statically (self-contained binaries).
|
||||||
-o, --output <name> Override project/output name.
|
-o, --output <name> Override project/output name.
|
||||||
-I <dir> Add include directory (repeatable).
|
-I <dir> Add include directory (repeatable).
|
||||||
-L <dir> Add library search path (repeatable).
|
-L <dir> Add library search path (repeatable).
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ debug = true
|
||||||
optimize = false
|
optimize = false
|
||||||
verbose = false
|
verbose = false
|
||||||
parallel_compilation = true
|
parallel_compilation = true
|
||||||
|
static_link = false
|
||||||
include_dirs = include
|
include_dirs = include
|
||||||
lib_search_paths =
|
lib_search_paths =
|
||||||
cflags = -Wall -Wextra
|
cflags = -Wall -Wextra
|
||||||
|
|
@ -22,3 +23,4 @@ dependencies_dir = dependencies
|
||||||
|
|
||||||
[tools]
|
[tools]
|
||||||
# legacy/manual entries go here when you don't want build directives
|
# legacy/manual entries go here when you don't want build directives
|
||||||
|
# Per-tool static_link can override global: static_link = true
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
module tests
|
||||||
|
|
||||||
|
import config
|
||||||
|
import builder
|
||||||
|
|
||||||
|
fn test_static_link_defaults_to_false() {
|
||||||
|
cfg := config.default_config
|
||||||
|
|
||||||
|
assert cfg.static_link == false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_tool_config_static_link_defaults_to_false() {
|
||||||
|
tool := config.ToolConfig{
|
||||||
|
name: 'test'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert tool.static_link == false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_static_link_command_includes_static_flag() {
|
||||||
|
cfg := config.BuildConfig{
|
||||||
|
compiler: 'g++'
|
||||||
|
toolchain: 'gcc'
|
||||||
|
bin_dir: 'bin'
|
||||||
|
}
|
||||||
|
tc := config.get_toolchain(cfg)
|
||||||
|
|
||||||
|
tool_cfg := config.ToolConfig{
|
||||||
|
name: 'mytool'
|
||||||
|
static_link: true
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := tc.tool_link_command(['main.o'], 'bin/tools/mytool', &cfg, tool_cfg)
|
||||||
|
|
||||||
|
assert cmd.contains('-static')
|
||||||
|
assert cmd.contains('-static-libgcc')
|
||||||
|
assert cmd.contains('-static-libstdc++')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_static_link_command_uses_static_libraries() {
|
||||||
|
cfg := config.BuildConfig{
|
||||||
|
compiler: 'g++'
|
||||||
|
toolchain: 'gcc'
|
||||||
|
bin_dir: 'bin'
|
||||||
|
}
|
||||||
|
tc := config.get_toolchain(cfg)
|
||||||
|
|
||||||
|
tool_cfg := config.ToolConfig{
|
||||||
|
name: 'mytool'
|
||||||
|
libraries: ['core']
|
||||||
|
static_link: true
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := tc.tool_link_command(['main.o'], 'bin/tools/mytool', &cfg, tool_cfg)
|
||||||
|
|
||||||
|
assert cmd.contains('-l:core.a')
|
||||||
|
assert !cmd.contains('-l:core.so')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_dynamic_link_command_uses_shared_libraries() {
|
||||||
|
cfg := config.BuildConfig{
|
||||||
|
compiler: 'g++'
|
||||||
|
toolchain: 'gcc'
|
||||||
|
bin_dir: 'bin'
|
||||||
|
}
|
||||||
|
tc := config.get_toolchain(cfg)
|
||||||
|
|
||||||
|
tool_cfg := config.ToolConfig{
|
||||||
|
name: 'mytool'
|
||||||
|
libraries: ['core']
|
||||||
|
static_link: false
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := tc.tool_link_command(['main.o'], 'bin/tools/mytool', &cfg, tool_cfg)
|
||||||
|
|
||||||
|
assert cmd.contains('-l:core.so')
|
||||||
|
assert !cmd.contains('-l:core.a')
|
||||||
|
assert !cmd.contains('-static')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_clang_static_link_command() {
|
||||||
|
cfg := config.BuildConfig{
|
||||||
|
compiler: 'clang++'
|
||||||
|
toolchain: 'clang'
|
||||||
|
bin_dir: 'bin'
|
||||||
|
}
|
||||||
|
tc := config.get_toolchain(cfg)
|
||||||
|
|
||||||
|
tool_cfg := config.ToolConfig{
|
||||||
|
name: 'mytool'
|
||||||
|
static_link: true
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := tc.tool_link_command(['main.o'], 'bin/tools/mytool', &cfg, tool_cfg)
|
||||||
|
|
||||||
|
assert cmd.starts_with('clang++')
|
||||||
|
assert cmd.contains('-static')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_any_tool_needs_static_link_returns_false_when_no_tools() {
|
||||||
|
cfg := config.BuildConfig{
|
||||||
|
tools: []
|
||||||
|
}
|
||||||
|
|
||||||
|
assert builder.any_tool_needs_static_link(cfg) == false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_any_tool_needs_static_link_returns_false_when_all_dynamic() {
|
||||||
|
cfg := config.BuildConfig{
|
||||||
|
tools: [
|
||||||
|
config.ToolConfig{ name: 'tool1', static_link: false },
|
||||||
|
config.ToolConfig{ name: 'tool2', static_link: false }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert builder.any_tool_needs_static_link(cfg) == false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_any_tool_needs_static_link_returns_true_when_one_static() {
|
||||||
|
cfg := config.BuildConfig{
|
||||||
|
tools: [
|
||||||
|
config.ToolConfig{ name: 'tool1', static_link: false },
|
||||||
|
config.ToolConfig{ name: 'tool2', static_link: true },
|
||||||
|
config.ToolConfig{ name: 'tool3', static_link: false }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert builder.any_tool_needs_static_link(cfg) == true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_any_tool_needs_static_link_returns_true_when_all_static() {
|
||||||
|
cfg := config.BuildConfig{
|
||||||
|
tools: [
|
||||||
|
config.ToolConfig{ name: 'tool1', static_link: true },
|
||||||
|
config.ToolConfig{ name: 'tool2', static_link: true }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert builder.any_tool_needs_static_link(cfg) == true
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue