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 {
fullargs := env_vflags_and_os_args()
mut cflags := get_cmdline_cflags(fullargs)
mut cflags := get_cmdline_multiple_values(fullargs,'-cflags')
$if !windows {
cflags += ' -fPIC'
cflags << '-fPIC'
}
if '-m32' in fullargs {
cflags += ' -m32'
cflags << '-m32'
}
return cflags
return cflags.join(' ')
}
fn get_cmdline_cflags(args []string) string {
mut cflags := ''
fn get_cmdline_multiple_values(args []string, optname string) []string {
mut flags := []string
for ci, cv in args {
if cv == '-cflags' {
cflags += args[ci + 1] + ' '
if cv == optname {
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 {

View File

@ -19,10 +19,18 @@ pub fn (c &CFlag) str() string {
// get flags for current os
fn (v &V) get_os_cflags() []CFlag {
mut flags := []CFlag
mut ctimedefines := []string
if v.compile_defines.len > 0 {
ctimedefines << v.compile_defines
}
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) {
flags << flag
}
if flag.os in ctimedefines {
flags << flag
}
}
return flags
}
@ -66,7 +74,7 @@ fn (table &Table) has_cflag(cflag CFlag) bool {
// parse the flags to (table.cflags) []CFlag
// 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', ]
flag_orig := cflag.trim_space()
mut flag := flag_orig
@ -74,7 +82,10 @@ fn (table mut Table) parse_cflag(cflag string, mod string) ?bool {
return true
}
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 {
return none
}

View File

@ -351,7 +351,11 @@ fn os_name_to_ifdef(name string) string {
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 {
'.v'{
''

View File

@ -20,6 +20,7 @@ fn (p mut Parser) comp_time() {
}
name := p.check_name()
p.fspace()
if name in supported_platforms {
ifdef_name := os_name_to_ifdef(name)
if name == 'mac' {
@ -99,6 +100,9 @@ fn (p mut Parser) comp_time() {
else if name == '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 {
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('@VMOD', v_modules_path)
// 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)
return
}

View File

@ -749,7 +749,7 @@ fn (p mut Parser) verify_fn_before_call(f &Fn) {
// p.tok == fn_name
fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type string) {
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 {
p.cgen.nogen = true
}

View File

@ -76,6 +76,10 @@ pub mut:
gen_parser_idx map[string]int
cached_mods []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 {
@ -117,7 +121,6 @@ pub mut:
// This is on by default, since a vast majority of users do not
// work on the builtin module itself.
// generating_vh bool
comptime_define string // -D vfmt for `if $vfmt {`
fast bool // use tcc/x64 codegen
enable_globals bool // allow __global for low level code
// is_fmt bool
@ -251,7 +254,20 @@ pub fn (v mut V) compile() {
else {
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)
if !v.pref.is_bare {
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 {
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)
}
return res
@ -905,8 +934,6 @@ pub fn new_v(args []string) &V {
vgen_buf.writeln('module vgen\nimport strings')
joined_args := args.join(' ')
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 dir := args.last()
if 'run' in args {
@ -1031,7 +1058,11 @@ pub fn new_v(args []string) &V {
exit(1)
}
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_name := os.filename(rdir)
if '-bare' in args {
@ -1073,7 +1104,6 @@ pub fn new_v(args []string) &V {
cflags: cflags
ccompiler: find_c_compiler()
building_v: !is_repl && (rdir_name == 'compiler' || rdir_name == 'v.v' || dir.contains('vlib'))
comptime_define: comptime_define
// is_fmt: comptime_define == 'vfmt'
user_mod_path: user_mod_path
@ -1104,7 +1134,9 @@ pub fn new_v(args []string) &V {
vroot: vroot
pref: pref
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"')
}
path_platform = path_ending
path_pcguard = platform_postfix_to_ifdefguard(path_ending)
path_pcguard = v.platform_postfix_to_ifdefguard(path_ending)
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))
p = {
p |