compiler: support for custom flags

[if custom]fn..{} , #flag custom, $if custom {}
pull/3195/head^2
Delyan Angelov 2019-12-23 12:09:00 +02:00 committed by Alexander Medvednikov
parent 42b1660c7e
commit 6e130cd446
7 changed files with 107 additions and 21 deletions

View File

@ -486,24 +486,47 @@ fn find_c_compiler_default() string {
fn find_c_compiler_thirdparty_options() string { fn find_c_compiler_thirdparty_options() string {
fullargs := env_vflags_and_os_args() fullargs := env_vflags_and_os_args()
mut cflags := get_cmdline_cflags(fullargs) mut cflags := get_cmdline_multiple_values(fullargs,'-cflags')
$if !windows { $if !windows {
cflags += ' -fPIC' cflags << '-fPIC'
} }
if '-m32' in fullargs { if '-m32' in fullargs {
cflags += ' -m32' cflags << '-m32'
} }
return cflags return cflags.join(' ')
} }
fn get_cmdline_cflags(args []string) string { fn get_cmdline_multiple_values(args []string, optname string) []string {
mut cflags := '' mut flags := []string
for ci, cv in args { for ci, cv in args {
if cv == '-cflags' { if cv == optname {
cflags += args[ci + 1] + ' ' flags << args[ci + 1]
} }
} }
return cflags return flags
}
fn parse_defines(defines []string) ([]string,[]string) {
// '-d abc -d xyz=1 -d qwe=0' should produce:
// compile_defines: ['abc','xyz']
// compile_defines_all ['abc','xyz','qwe']
mut compile_defines := []string
mut compile_defines_all := []string
for dfn in defines {
dfn_parts := dfn.split('=')
if dfn_parts.len == 1 {
compile_defines << dfn
compile_defines_all << dfn
continue
}
if dfn_parts.len == 2 {
compile_defines_all << dfn_parts[0]
if dfn_parts[1] == '1' {
compile_defines << dfn_parts[0]
}
}
}
return compile_defines, compile_defines_all
} }
fn missing_compiler_info() string { fn missing_compiler_info() string {

View File

@ -19,10 +19,18 @@ pub fn (c &CFlag) str() string {
// get flags for current os // get flags for current os
fn (v &V) get_os_cflags() []CFlag { fn (v &V) get_os_cflags() []CFlag {
mut flags := []CFlag mut flags := []CFlag
mut ctimedefines := []string
if v.compile_defines.len > 0 {
ctimedefines << v.compile_defines
}
for flag in v.table.cflags { for flag in v.table.cflags {
if flag.os == '' || (flag.os == 'linux' && v.os == .linux) || (flag.os == 'darwin' && v.os == .mac) || (flag.os == 'freebsd' && v.os == .freebsd) || (flag.os == 'windows' && v.os == .windows) { if flag.os == '' || (flag.os == 'linux' && v.os == .linux) || (flag.os == 'darwin' && v.os == .mac) || (flag.os == 'freebsd' && v.os == .freebsd) || (flag.os == 'windows' && v.os == .windows) {
flags << flag flags << flag
} }
if flag.os in ctimedefines {
flags << flag
}
} }
return flags return flags
} }
@ -66,7 +74,7 @@ fn (table &Table) has_cflag(cflag CFlag) bool {
// parse the flags to (table.cflags) []CFlag // parse the flags to (table.cflags) []CFlag
// Note: clean up big time (joe-c) // Note: clean up big time (joe-c)
fn (table mut Table) parse_cflag(cflag string, mod string) ?bool { fn (table mut Table) parse_cflag(cflag string, mod string, ctimedefines []string) ?bool {
allowed_flags := ['framework', 'library', 'Wa', 'Wl', 'Wp', 'I', 'l', 'L', ] allowed_flags := ['framework', 'library', 'Wa', 'Wl', 'Wp', 'I', 'l', 'L', ]
flag_orig := cflag.trim_space() flag_orig := cflag.trim_space()
mut flag := flag_orig mut flag := flag_orig
@ -74,7 +82,10 @@ fn (table mut Table) parse_cflag(cflag string, mod string) ?bool {
return true return true
} }
mut fos := '' mut fos := ''
if flag.starts_with('linux') || flag.starts_with('darwin') || flag.starts_with('freebsd') || flag.starts_with('windows') { mut allowed_os_overrides := ['linux','darwin','freebsd','windows']
allowed_os_overrides << ctimedefines
for os_override in allowed_os_overrides {
if !flag.starts_with( os_override ) { continue }
pos := flag.index(' ') or { pos := flag.index(' ') or {
return none return none
} }

View File

@ -351,7 +351,11 @@ fn os_name_to_ifdef(name string) string {
return '' return ''
} }
fn platform_postfix_to_ifdefguard(name string) string { fn (v &V) platform_postfix_to_ifdefguard(name string) string {
if name.starts_with('custom '){
cdefine := name.replace('custom ','')
return '#ifdef CUSTOM_DEFINE_${cdefine}'
}
s := match name { s := match name {
'.v'{ '.v'{
'' ''

View File

@ -20,6 +20,7 @@ fn (p mut Parser) comp_time() {
} }
name := p.check_name() name := p.check_name()
p.fspace() p.fspace()
if name in supported_platforms { if name in supported_platforms {
ifdef_name := os_name_to_ifdef(name) ifdef_name := os_name_to_ifdef(name)
if name == 'mac' { if name == 'mac' {
@ -99,6 +100,9 @@ fn (p mut Parser) comp_time() {
else if name == 'clang' { else if name == 'clang' {
p.comptime_if_block('__clang__') p.comptime_if_block('__clang__')
} }
else if p.v.compile_defines_all.len > 0 && name in p.v.compile_defines_all {
p.comptime_if_block('CUSTOM_DEFINE_${name}')
}
else { else {
println('Supported platforms:') println('Supported platforms:')
println(supported_platforms) println(supported_platforms)
@ -209,7 +213,7 @@ fn (p mut Parser) chash() {
flag = flag.replace('@VLIB_PATH', p.pref.vlib_path) flag = flag.replace('@VLIB_PATH', p.pref.vlib_path)
flag = flag.replace('@VMOD', v_modules_path) flag = flag.replace('@VMOD', v_modules_path)
// p.log('adding flag "$flag"') // p.log('adding flag "$flag"')
_ = p.table.parse_cflag(flag, p.mod) or { _ = p.table.parse_cflag(flag, p.mod, p.v.compile_defines_all ) or {
p.error_with_token_index(err, p.cur_tok_index() - 1) p.error_with_token_index(err, p.cur_tok_index() - 1)
return return
} }

View File

@ -749,7 +749,7 @@ fn (p mut Parser) verify_fn_before_call(f &Fn) {
// p.tok == fn_name // p.tok == fn_name
fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type string) { fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type string) {
p.verify_fn_before_call(f) p.verify_fn_before_call(f)
is_comptime_define := f.comptime_define != '' && f.comptime_define != p.pref.comptime_define is_comptime_define := f.comptime_define != '' && !(f.comptime_define in p.v.compile_defines )
if is_comptime_define { if is_comptime_define {
p.cgen.nogen = true p.cgen.nogen = true
} }

View File

@ -76,6 +76,10 @@ pub mut:
gen_parser_idx map[string]int gen_parser_idx map[string]int
cached_mods []string cached_mods []string
module_lookup_paths []string module_lookup_paths []string
// -d vfmt and -d another=0 for `$if vfmt { will execute }` and `$if another { will NOT get here }`
compile_defines []string // just ['vfmt']
compile_defines_all []string // contains both: ['vfmt','another']
} }
struct Preferences { struct Preferences {
@ -117,7 +121,6 @@ pub mut:
// This is on by default, since a vast majority of users do not // This is on by default, since a vast majority of users do not
// work on the builtin module itself. // work on the builtin module itself.
// generating_vh bool // generating_vh bool
comptime_define string // -D vfmt for `if $vfmt {`
fast bool // use tcc/x64 codegen fast bool // use tcc/x64 codegen
enable_globals bool // allow __global for low level code enable_globals bool // allow __global for low level code
// is_fmt bool // is_fmt bool
@ -251,7 +254,20 @@ pub fn (v mut V) compile() {
else { else {
cgen.genln('#include <stdint.h>') cgen.genln('#include <stdint.h>')
} }
if v.compile_defines_all.len > 0 {
cgen.genln('')
cgen.genln('// All custom defines : ' + v.compile_defines_all.join(','))
cgen.genln('// Turned ON custom defines: ' + v.compile_defines.join(','))
for cdefine in v.compile_defines {
cgen.genln('#define CUSTOM_DEFINE_${cdefine}')
}
cgen.genln('//')
cgen.genln('')
}
cgen.genln(c_builtin_types) cgen.genln(c_builtin_types)
if !v.pref.is_bare { if !v.pref.is_bare {
cgen.genln(c_headers) cgen.genln(c_headers)
} }
@ -638,6 +654,19 @@ pub fn (v &V) v_files_from_dir(dir string) []string {
if file.ends_with('_c.v') && v.os == .js { if file.ends_with('_c.v') && v.os == .js {
continue continue
} }
if v.compile_defines_all.len > 0 && file.contains('_d_') {
mut allowed := false
for cdefine in v.compile_defines {
file_postfix := '_d_${cdefine}.v'
if file.ends_with(file_postfix) {
allowed = true
break
}
}
if !allowed {
continue
}
}
res << filepath.join(dir,file) res << filepath.join(dir,file)
} }
return res return res
@ -905,8 +934,6 @@ pub fn new_v(args []string) &V {
vgen_buf.writeln('module vgen\nimport strings') vgen_buf.writeln('module vgen\nimport strings')
joined_args := args.join(' ') joined_args := args.join(' ')
target_os := get_arg(joined_args, 'os', '') target_os := get_arg(joined_args, 'os', '')
comptime_define := get_arg(joined_args, 'd', '')
// println('comptimedefine=$comptime_define')
mut out_name := get_arg(joined_args, 'o', 'a.out') mut out_name := get_arg(joined_args, 'o', 'a.out')
mut dir := args.last() mut dir := args.last()
if 'run' in args { if 'run' in args {
@ -1031,7 +1058,11 @@ pub fn new_v(args []string) &V {
exit(1) exit(1)
} }
mut out_name_c := get_vtmp_filename(out_name, '.tmp.c') mut out_name_c := get_vtmp_filename(out_name, '.tmp.c')
cflags := get_cmdline_cflags(args) cflags := get_cmdline_multiple_values(args, '-cflags').join(' ')
defines := get_cmdline_multiple_values(args, '-d')
compile_defines, compile_defines_all := parse_defines( defines )
rdir := os.realpath(dir) rdir := os.realpath(dir)
rdir_name := os.filename(rdir) rdir_name := os.filename(rdir)
if '-bare' in args { if '-bare' in args {
@ -1073,7 +1104,6 @@ pub fn new_v(args []string) &V {
cflags: cflags cflags: cflags
ccompiler: find_c_compiler() ccompiler: find_c_compiler()
building_v: !is_repl && (rdir_name == 'compiler' || rdir_name == 'v.v' || dir.contains('vlib')) building_v: !is_repl && (rdir_name == 'compiler' || rdir_name == 'v.v' || dir.contains('vlib'))
comptime_define: comptime_define
// is_fmt: comptime_define == 'vfmt' // is_fmt: comptime_define == 'vfmt'
user_mod_path: user_mod_path user_mod_path: user_mod_path
@ -1104,7 +1134,9 @@ pub fn new_v(args []string) &V {
vroot: vroot vroot: vroot
pref: pref pref: pref
mod: mod mod: mod
vgen_buf: vgen_buf vgen_buf: vgen_buf
compile_defines: compile_defines
compile_defines_all: compile_defines_all
} }
} }

View File

@ -155,10 +155,22 @@ fn (v mut V) new_parser_from_file(path string) Parser {
println('warning: use "$p" file name instead of "$path"') println('warning: use "$p" file name instead of "$path"')
} }
path_platform = path_ending path_platform = path_ending
path_pcguard = platform_postfix_to_ifdefguard(path_ending) path_pcguard = v.platform_postfix_to_ifdefguard(path_ending)
break break
} }
} }
if v.compile_defines.len > 0 {
for cdefine in v.compile_defines {
custom_path_ending := '_d_${cdefine}.v'
if path.ends_with(custom_path_ending){
path_platform = custom_path_ending
path_pcguard = v.platform_postfix_to_ifdefguard('custom $cdefine')
break
}
}
}
mut p := v.new_parser(new_scanner_file(path)) mut p := v.new_parser(new_scanner_file(path))
p = { p = {
p | p |