1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

remove duplication by using a new Preferences struct

This commit is contained in:
Archan Patkar
2019-07-01 01:33:17 +05:30
committed by Alexander Medvednikov
parent 42a622c10f
commit 74d234f8cd
4 changed files with 163 additions and 160 deletions

View File

@@ -58,32 +58,38 @@ enum Pass {
main
}
*/
struct Preferences {
mut:
build_mode BuildMode
nofmt bool // disable vfmt
is_test bool // `v test string_test.v`
is_script bool // single file mode (`v program.v`), `fn main(){}` can be skipped
is_live bool // for hot code reloading
is_so bool
is_prof bool // benchmark every function
translated bool // `v translate doom.v` are we running V code translated from C? allow globals, ++ expressions, etc
is_prod bool // use "-O2"
is_verbose bool // print extra information with `v.log()`
obfuscate bool // `v -obf program.v`, renames functions to "f_XXX"
is_play bool // playground mode
is_repl bool
is_run bool
show_c_cmd bool // `v -show_c_cmd` prints the C command to build program.v.c
sanitize bool // use Clang's new "-fsanitize" option
}
struct V {
mut:
build_mode BuildMode
os Os // the OS to build for
nofmt bool // disable vfmt
out_name_c string // name of the temporary C file
files []string // all V files that need to be parsed and compiled
dir string // directory (or file) being compiled (TODO rename to path?)
table *Table // table with types, vars, functions etc
cgen *CGen // C code generator
is_test bool // `v test string_test.v`
is_script bool // single file mode (`v program.v`), `fn main(){}` can be skipped
is_so bool
is_live bool // for hot code reloading
is_prof bool // benchmark every function
translated bool // `v translate doom.v` are we running V code translated from C? allow globals, ++ expressions, etc
obfuscate bool // `v -obf program.v`, renames functions to "f_XXX"
lang_dir string // path to V repo
is_verbose bool // print extra information with `v.log()`
is_run bool // `v run program.v`
is_play bool // playground mode
show_c_cmd bool // `v -show_c_cmd` prints the C command to build program.v.c
sanitize bool // use Clang's new "-fsanitize" option
pref *Preferences // all the prefrences and settings extracted to a struct for reusability
lang_dir string // "~/code/v"
out_name string // "program.exe"
is_prod bool // use "-O2"
is_repl bool
vroot string
}
@@ -137,7 +143,7 @@ fn main() {
}
// Construct the V object from command line arguments
mut c := new_v(args)
if c.is_verbose {
if c.pref.is_verbose {
println(args)
}
// Generate the docs and exit
@@ -153,7 +159,7 @@ fn (c mut V) compile() {
cgen.genln('// Generated by V')
// Add user files to compile
c.add_user_v_files()
if c.is_verbose {
if c.pref.is_verbose {
println('all .v files:')
println(c.files)
}
@@ -164,7 +170,7 @@ fn (c mut V) compile() {
}
// Main pass
cgen.run = RUN_MAIN
if c.is_play {
if c.pref.is_play {
cgen.genln('#define VPLAY (1) ')
}
cgen.genln('
@@ -238,23 +244,23 @@ void reload_so();
void init_consts();')
imports_json := c.table.imports.contains('json')
// TODO remove global UI hack
if c.os == MAC && ((c.build_mode == EMBED_VLIB && c.table.imports.contains('ui')) ||
(c.build_mode == BUILD && c.dir.contains('/ui'))) {
if c.os == MAC && ((c.pref.build_mode == EMBED_VLIB && c.table.imports.contains('ui')) ||
(c.pref.build_mode == BUILD && c.dir.contains('/ui'))) {
cgen.genln('id defaultFont = 0; // main.v')
}
// TODO remove ugly .c include once V has its own json parser
// Embed cjson either in embedvlib or in json.o
if imports_json && c.build_mode == EMBED_VLIB ||
(c.build_mode == BUILD && c.out_name.contains('json.o')) {
if imports_json && c.pref.build_mode == EMBED_VLIB ||
(c.pref.build_mode == BUILD && c.out_name.contains('json.o')) {
cgen.genln('#include "cJSON.c" ')
}
// We need the cjson header for all the json decoding user will do in default mode
if c.build_mode == DEFAULT_MODE {
if c.pref.build_mode == DEFAULT_MODE {
if imports_json {
cgen.genln('#include "cJSON.h"')
}
}
if c.build_mode == EMBED_VLIB || c.build_mode == DEFAULT_MODE {
if c.pref.build_mode == EMBED_VLIB || c.pref.build_mode == DEFAULT_MODE {
// If we declare these for all modes, then when running `v a.v` we'll get
// `/usr/bin/ld: multiple definition of 'total_m'`
// TODO
@@ -277,7 +283,7 @@ void init_consts();')
p.parse()
// p.g.gen_x64()
// Format all files (don't format automatically generated vlib headers)
if !c.nofmt && !file.contains('/vlib/') {
if !c.pref.nofmt && !file.contains('/vlib/') {
// new vfmt is not ready yet
}
}
@@ -292,14 +298,14 @@ void init_consts();')
d.writeln(cgen.fns.join_lines())
d.writeln(cgen.consts.join_lines())
d.writeln(cgen.thread_args.join_lines())
if c.is_prof {
if c.pref.is_prof {
d.writeln('; // Prof counters:')
d.writeln(c.prof_counters())
}
dd := d.str()
cgen.lines.set(defs_pos, dd)// TODO `def.str()` doesn't compile
// if c.build_mode in [.default, .embed_vlib] {
if c.build_mode == DEFAULT_MODE || c.build_mode == EMBED_VLIB {
if c.pref.build_mode == DEFAULT_MODE || c.pref.build_mode == EMBED_VLIB {
// vlib can't have `init_consts()`
cgen.genln('void init_consts() { g_str_buf=malloc(1000); ${cgen.consts_init.join_lines()} }')
// _STR function can't be defined in vlib
@@ -339,10 +345,10 @@ string _STR_TMP(const char *fmt, ...) {
}
// Make sure the main function exists
// Obviously we don't need it in libraries
if c.build_mode != BUILD {
if !c.table.main_exists() && !c.is_test {
if c.pref.build_mode != BUILD {
if !c.table.main_exists() && !c.pref.is_test {
// It can be skipped in single file programs
if c.is_script {
if c.pref.is_script {
//println('Generating main()...')
cgen.genln('int main() { $cgen.fn_main; return 0; }')
}
@@ -351,7 +357,7 @@ string _STR_TMP(const char *fmt, ...) {
}
}
// Generate `main` which calls every single test function
else if c.is_test {
else if c.pref.is_test {
cgen.genln('int main() { init_consts();')
for v in c.table.fns {
if v.name.starts_with('test_') {
@@ -361,7 +367,7 @@ string _STR_TMP(const char *fmt, ...) {
cgen.genln('return g_test_ok == 0; }')
}
}
if c.is_live {
if c.pref.is_live {
cgen.genln(' int load_so(byteptr path) {
printf("load_so %s\\n", path); dlclose(live_lib); live_lib = dlopen(path, RTLD_LAZY);
if (!live_lib) {puts("open failed"); exit(1); return 0;}
@@ -372,13 +378,13 @@ string _STR_TMP(const char *fmt, ...) {
cgen.genln('return 1; }')
}
cgen.save()
if c.is_verbose {
if c.pref.is_verbose {
c.log('flags=')
println(c.table.flags)
}
c.cc()
if c.is_test || c.is_run {
if true || c.is_verbose {
if c.pref.is_test || c.pref.is_run {
if true || c.pref.is_verbose {
println('============ running $c.out_name ============')
}
mut cmd := if c.out_name.starts_with('/') {
@@ -405,32 +411,31 @@ string _STR_TMP(const char *fmt, ...) {
}
fn (c mut V) cc() {
ticks := time.ticks()
linux_host := os.user_os() == 'linux'
c.log('cc() isprod=$c.is_prod outname=$c.out_name')
c.log('cc() isprod=$c.pref.is_prod outname=$c.out_name')
mut a := ['-w']// arguments for the C compiler
flags := c.table.flags.join(' ')
/*
mut shared := ''
if c.is_so {
if c.pref.is_so {
a << '-shared'// -Wl,-z,defs'
c.out_name = c.out_name + '.so'
}
*/
if c.is_prod {
if c.pref.is_prod {
a << '-O2'
}
else {
a << '-g'
}
mut libs := ''// builtin.o os.o http.o etc
if c.build_mode == BUILD {
if c.pref.build_mode == BUILD {
a << '-c'
}
else if c.build_mode == EMBED_VLIB {
else if c.pref.build_mode == EMBED_VLIB {
//
}
else if c.build_mode == DEFAULT_MODE {
else if c.pref.build_mode == DEFAULT_MODE {
libs = '$TmpPath/vlib/builtin.o'
if !os.file_exists(libs) {
println('`builtin.o` not found')
@@ -453,7 +458,7 @@ mut args := ''
}
}
*/
if c.sanitize {
if c.pref.sanitize {
a << '-fsanitize=leak'
}
// Cross compiling linux
@@ -485,11 +490,11 @@ mut args := ''
a << '-x objective-c'
}
// Without these libs compilation will fail on Linux
if c.os == LINUX && c.build_mode != BUILD {
if c.os == LINUX && c.pref.build_mode != BUILD {
a << '-lm -ldl -lpthread'
}
// Find clang executable
fast_clang := 'ff'///usr/local/Cellar/llvm/8.0.0/bin/clang'
fast_clang := '/usr/local/Cellar/llvm/8.0.0/bin/clang'
args := a.join(' ')
mut cmd := if os.file_exists(fast_clang) {
'$fast_clang $args'
@@ -501,7 +506,7 @@ mut args := ''
cmd = 'gcc $args'
}
// Print the C command
if c.show_c_cmd || c.is_verbose {
if c.pref.show_c_cmd || c.pref.is_verbose {
println('\n==========\n$cmd\n=========\n')
}
// Run
@@ -512,7 +517,7 @@ mut args := ''
panic('clang error')
}
// Link it if we are cross compiling and need an executable
if c.os == LINUX && !linux_host && c.build_mode != BUILD {
if c.os == LINUX && !linux_host && c.pref.build_mode != BUILD {
c.out_name = c.out_name.replace('.o', '')
obj_file := c.out_name + '.o'
println('linux obj_file=$obj_file out_name=$c.out_name')
@@ -531,10 +536,6 @@ mut args := ''
}
println('linux cross compilation done. resulting binary: "$c.out_name"')
}
if c.show_c_cmd {
diff := time.ticks() - ticks
println('cc() took $diff ms ')
}
//os.rm('$TmpPath/$c.out_name_c')
}
@@ -546,7 +547,7 @@ fn (c &V) v_files_from_dir(dir string) []string {
panic('$dir isn\'t a directory')
}
mut files := os.ls(dir)
if c.is_verbose {
if c.pref.is_verbose {
println('v_files_from_dir ("$dir")')
}
// println(files.len)
@@ -617,7 +618,7 @@ fn (c mut V) add_user_v_files() {
println('No input .v files')
exit(1)
}
if c.is_verbose {
if c.pref.is_verbose {
c.log('user_files:')
println(user_files)
}
@@ -627,7 +628,7 @@ fn (c mut V) add_user_v_files() {
p.parse()
}
// Parse lib imports
if c.build_mode == DEFAULT_MODE {
if c.pref.build_mode == DEFAULT_MODE {
for i := 0; i < c.table.imports.len; i++ {
pkg := c.table.imports[i]
vfiles := c.v_files_from_dir('$TmpPath/vlib/$pkg')
@@ -652,7 +653,7 @@ fn (c mut V) add_user_v_files() {
}
}
}
if c.is_verbose {
if c.pref.is_verbose {
c.log('imports:')
println(c.table.imports)
}
@@ -662,7 +663,7 @@ fn (c mut V) add_user_v_files() {
// If we are in default mode, we don't parse vlib .v files, but header .vh files in
// TmpPath/vlib
// These were generated by vfmt
if c.build_mode == DEFAULT_MODE || c.build_mode == BUILD {
if c.pref.build_mode == DEFAULT_MODE || c.pref.build_mode == BUILD {
module_path = '$TmpPath/vlib/$pkg'
}
vfiles := c.v_files_from_dir(module_path)
@@ -695,13 +696,13 @@ fn get_arg(joined_args, arg, def string) string {
}
fn (c &V) log(s string) {
if !c.is_verbose {
if !c.pref.is_verbose {
return
}
println(s)
}
fn new_v(args []string) *V {
fn new_v(args[]string) *V {
mut dir := args.last()
if args.contains('run') {
dir = args[2]
@@ -823,7 +824,25 @@ fn new_v(args []string) *V {
files << f
}
}
obfuscate := args.contains('-obf')
obfuscate := args.contains('-obf')
pref := &Preferences {
is_test: is_test
is_script: is_script
is_so: args.contains('-shared')
is_play: args.contains('play')
is_prod: args.contains('-prod')
is_verbose: args.contains('-verbose')
obfuscate: obfuscate
is_prof: args.contains('-prof')
is_live: args.contains('-live')
sanitize: args.contains('-sanitize')
nofmt: args.contains('-nofmt')
show_c_cmd: args.contains('-show_c_cmd')
translated: args.contains('translated')
is_run: args.contains('run')
is_repl: args.contains('-repl')
build_mode: build_mode
}
return &V {
os: _os
out_name: out_name
@@ -833,24 +852,9 @@ fn new_v(args []string) *V {
table: new_table(obfuscate)
out_name: out_name
out_name_c: out_name_c
is_test: is_test
is_script: is_script
is_so: args.contains('-shared')
is_play: args.contains('play')
is_prod: args.contains('-prod')
is_verbose: args.contains('-verbose')
obfuscate: args.contains('-obf')
is_prof: args.contains('-prof')
is_live: args.contains('-live')
sanitize: args.contains('-sanitize')
nofmt: args.contains('-nofmt')
show_c_cmd: args.contains('-show_c_cmd')
translated: args.contains('translated')
cgen: new_cgen(out_name_c)
build_mode: build_mode
is_run: args.contains('run')
is_repl: args.contains('-repl')
vroot: lang_dir
pref: pref
}
}