v/vlib/v/builder/builder.v

236 lines
6.1 KiB
V
Raw Normal View History

module builder
import (
os
time
2020-02-03 07:31:54 +01:00
v.ast
v.table
v.pref
v.checker
v.parser
v.gen
v.gen.x64
)
pub struct Builder {
pub:
mod_file_cacher &ModFileCacher // used during lookup for v.mod to support @VROOT
pref &pref.Preferences
table &table.Table
checker checker.Checker
os pref.OS // the OS to build for
2020-03-20 16:41:18 +01:00
compiled_dir string // contains os.real_path() of the dir of the final file beeing compiled, or the dir itself when doing `v .`
module_path string
2020-02-03 07:31:54 +01:00
mut:
2020-03-01 21:56:07 +01:00
module_search_paths []string
parsed_files []ast.File
}
pub fn new_builder(pref &pref.Preferences) Builder {
table := table.new_table()
return Builder{
mod_file_cacher: new_mod_file_cacher()
pref: pref
table: table
checker: checker.new_checker(table)
}
}
pub fn (b mut Builder) gen_c(v_files []string) string {
t0 := time.ticks()
2020-03-27 14:44:30 +01:00
b.parsed_files = parser.parse_files(v_files, b.table, b.pref)
2020-02-03 07:31:54 +01:00
b.parse_imports()
t1 := time.ticks()
parse_time := t1 - t0
2020-03-31 19:58:44 +02:00
b.info('PARSE: ${parse_time}ms')
//
2020-02-03 07:31:54 +01:00
b.checker.check_files(b.parsed_files)
t2 := time.ticks()
check_time := t2 - t1
2020-03-31 19:58:44 +02:00
b.info('CHECK: ${check_time}ms')
if b.checker.nr_errors > 0 {
exit(1)
}
// println('starting cgen...')
2020-03-30 17:21:32 +02:00
res := gen.cgen(b.parsed_files, b.table, b.pref)
t3 := time.ticks()
gen_time := t3 - t2
2020-03-31 19:58:44 +02:00
b.info('C GEN: ${gen_time}ms')
// println('cgen done')
// println(res)
return res
}
pub fn (b mut Builder) build_c(v_files []string, out_file string) {
2020-03-31 19:58:44 +02:00
b.info('build_c($out_file)')
mut f := os.create(out_file) or {
panic(err)
}
f.writeln(b.gen_c(v_files))
f.close()
// os.write_file(out_file, b.gen_c(v_files))
}
pub fn (b mut Builder) build_x64(v_files []string, out_file string) {
t0 := time.ticks()
2020-03-27 14:44:30 +01:00
b.parsed_files = parser.parse_files(v_files, b.table, b.pref)
2020-02-03 07:31:54 +01:00
b.parse_imports()
t1 := time.ticks()
parse_time := t1 - t0
2020-03-31 19:58:44 +02:00
b.info('PARSE: ${parse_time}ms')
2020-02-03 07:31:54 +01:00
b.checker.check_files(b.parsed_files)
t2 := time.ticks()
check_time := t2 - t1
2020-03-31 19:58:44 +02:00
b.info('CHECK: ${check_time}ms')
2020-02-03 07:31:54 +01:00
x64.gen(b.parsed_files, out_file)
t3 := time.ticks()
gen_time := t3 - t2
2020-03-31 19:58:44 +02:00
b.info('x64 GEN: ${gen_time}ms')
}
2020-02-03 07:31:54 +01:00
// parse all deps from already parsed files
pub fn (b mut Builder) parse_imports() {
mut done_imports := []string
for i in 0 .. b.parsed_files.len {
ast_file := b.parsed_files[i]
for _, imp in ast_file.imports {
mod := imp.mod
if mod in done_imports {
continue
}
import_path := b.find_module_path(mod) or {
// v.parsers[i].error_with_token_index('cannot import module "$mod" (not found)', v.parsers[i].import_table.get_import_tok_idx(mod))
// break
2020-03-01 21:56:07 +01:00
// println('module_search_paths:')
// println(b.module_search_paths)
2020-02-03 07:31:54 +01:00
panic('cannot import module "$mod" (not found)')
}
v_files := b.v_files_from_dir(import_path)
if v_files.len == 0 {
// v.parsers[i].error_with_token_index('cannot import module "$mod" (no .v files in "$import_path")', v.parsers[i].import_table.get_import_tok_idx(mod))
2020-02-03 07:31:54 +01:00
panic('cannot import module "$mod" (no .v files in "$import_path")')
}
// Add all imports referenced by these libs
2020-03-27 14:44:30 +01:00
parsed_files := parser.parse_files(v_files, b.table, b.pref)
2020-02-03 07:31:54 +01:00
for file in parsed_files {
if file.mod.name != mod {
// v.parsers[pidx].error_with_token_index('bad module definition: ${v.parsers[pidx].file_path} imports module "$mod" but $file is defined as module `$p_mod`', 1
panic('bad module definition: ${ast_file.path} imports module "$mod" but $file.path is defined as module `$file.mod.name`')
2020-02-03 07:31:54 +01:00
}
}
b.parsed_files << parsed_files
done_imports << mod
}
}
}
pub fn (b &Builder) v_files_from_dir(dir string) []string {
mut res := []string
if !os.exists(dir) {
if dir == 'compiler' && os.is_dir('vlib') {
println('looks like you are trying to build V with an old command')
2020-02-09 10:08:04 +01:00
println('use `v -o v cmd/v` instead of `v -o v compiler`')
2020-02-03 07:31:54 +01:00
}
verror("$dir doesn't exist")
}
else if !os.is_dir(dir) {
2020-03-24 11:14:11 +01:00
verror("$dir isn't a directory!")
2020-02-03 07:31:54 +01:00
}
mut files := os.ls(dir) or {
2020-02-03 07:31:54 +01:00
panic(err)
}
2020-03-06 18:53:29 +01:00
if b.pref.verbosity.is_higher_or_equal(.level_one) {
2020-02-03 07:31:54 +01:00
println('v_files_from_dir ("$dir")')
}
files.sort()
for file in files {
if !file.ends_with('.v') && !file.ends_with('.vh') {
continue
}
if file.ends_with('_test.v') {
continue
}
if (file.ends_with('_win.v') || file.ends_with('_windows.v')) && b.os != .windows {
2020-02-03 07:31:54 +01:00
continue
}
if (file.ends_with('_lin.v') || file.ends_with('_linux.v')) && b.os != .linux {
2020-02-03 07:31:54 +01:00
continue
}
if (file.ends_with('_mac.v') || file.ends_with('_darwin.v')) && b.os != .mac {
2020-02-03 07:31:54 +01:00
continue
}
if file.ends_with('_nix.v') && b.os == .windows {
2020-02-03 07:31:54 +01:00
continue
}
if file.ends_with('_android.v') && b.pref.os != .android {
continue
}
if file.ends_with('_freebsd.v') && b.pref.os != .freebsd {
continue
}
if file.ends_with('_solaris.v') && b.pref.os != .solaris {
continue
}
if file.ends_with('_js.v') && b.os != .js {
2020-02-03 07:31:54 +01:00
continue
}
if file.ends_with('_c.v') && b.os == .js {
2020-02-03 07:31:54 +01:00
continue
}
if b.pref.compile_defines_all.len > 0 && file.contains('_d_') {
2020-02-03 07:31:54 +01:00
mut allowed := false
for cdefine in b.pref.compile_defines {
2020-02-03 07:31:54 +01:00
file_postfix := '_d_${cdefine}.v'
if file.ends_with(file_postfix) {
allowed = true
break
}
}
if !allowed {
continue
}
}
2020-03-09 02:23:34 +01:00
res << os.join_path(dir,file)
2020-02-03 07:31:54 +01:00
}
return res
}
fn verror(err string) {
panic('v error: $err')
}
pub fn (b &Builder) log(s string) {
2020-03-06 18:53:29 +01:00
if b.pref.verbosity.is_higher_or_equal(.level_two) {
2020-02-03 07:31:54 +01:00
println(s)
}
}
2020-03-01 21:56:07 +01:00
2020-03-31 19:58:44 +02:00
pub fn (b &Builder) info(s string) {
if b.pref.verbosity.is_higher_or_equal(.level_one) {
println(s)
}
}
2020-03-01 21:56:07 +01:00
[inline]
fn module_path(mod string) string {
// submodule support
2020-03-07 22:26:26 +01:00
return mod.replace('.', os.path_separator)
2020-03-01 21:56:07 +01:00
}
pub fn (b &Builder) find_module_path(mod string) ?string {
mod_path := module_path(mod)
for search_path in b.module_search_paths {
2020-03-24 11:14:11 +01:00
try_path := os.join_path(search_path,mod_path)
2020-03-06 18:53:29 +01:00
if b.pref.verbosity.is_higher_or_equal(.level_three) {
2020-03-01 21:56:07 +01:00
println(' >> trying to find $mod in $try_path ..')
}
if os.is_dir(try_path) {
2020-03-06 18:53:29 +01:00
if b.pref.verbosity.is_higher_or_equal(.level_three) {
2020-03-01 21:56:07 +01:00
println(' << found $try_path .')
}
return try_path
}
}
return error('module "$mod" not found')
}