checker,cgen: fix `-os cross` support for `$if !solaris { #include <sys/ptrace.h> }`

pull/10932/head
Delyan Angelov 2021-07-23 15:30:51 +03:00
parent c797e1460d
commit 6313ed6a79
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
8 changed files with 68 additions and 10 deletions

View File

@ -874,17 +874,19 @@ pub mut:
scope &Scope
}
// #include etc
// #include, #define etc
pub struct HashStmt {
pub:
mod string
pos token.Position
source_file string
pub mut:
val string // example: 'include <openssl/rand.h> # please install openssl // comment'
kind string // : 'include'
main string // : '<openssl/rand.h>'
msg string // : 'please install openssl'
val string // example: 'include <openssl/rand.h> # please install openssl // comment'
kind string // : 'include'
main string // : '<openssl/rand.h>'
msg string // : 'please install openssl'
ct_conds []Expr // *all* comptime conditions, that must be true, for the hash to be processed
// ct_conds is filled by the checker, based on the current nesting of `$if cond1 {}` blocks
}
/*

View File

@ -77,7 +77,8 @@ pub mut:
inside_fn_arg bool // `a`, `b` in `a.f(b)`
inside_ct_attr bool // true inside [if expr]
skip_flags bool // should `#flag` and `#include` be skipped
fn_level int // 0 for the top level, 1 for `fn abc() {}`, 2 for a nested fn, etc
fn_level int // 0 for the top level, 1 for `fn abc() {}`, 2 for a nested fn, etc
ct_cond_stack []ast.Expr
mut:
files []ast.File
expr_level int // to avoid infinite recursion segfaults due to compiler bugs
@ -4908,6 +4909,9 @@ fn (mut c Checker) hash_stmt(mut node ast.HashStmt) {
if c.skip_flags {
return
}
if c.ct_cond_stack.len > 0 {
node.ct_conds = c.ct_cond_stack.clone()
}
if c.pref.backend.is_js() {
if !c.file.path.ends_with('.js.v') {
c.error('hash statements are only allowed in backend specific files such "x.js.v"',
@ -6551,6 +6555,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
// statements, in `-os cross` mode
found_branch = false
c.skip_flags = false
c.ct_cond_stack << branch.cond
}
if !c.skip_flags {
c.stmts(branch.stmts)
@ -6573,6 +6578,9 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
c.comptime_fields_type.delete(comptime_field_name)
}
c.skip_flags = cur_skip_flags
if c.fn_level == 0 && c.pref.output_cross_c && c.ct_cond_stack.len > 0 {
c.ct_cond_stack.pop()
}
} else {
// smartcast sumtypes and interfaces when using `is`
c.smartcast_if_conds(branch.cond, mut branch.scope)

View File

@ -1358,6 +1358,19 @@ fn (mut g Gen) stmt(node ast.Stmt) {
g.writeln('goto $node.name;')
}
ast.HashStmt {
mut ct_condition := ''
if node.ct_conds.len > 0 {
ct_condition_start := g.out.len
for idx, ct_expr in node.ct_conds {
g.comp_if_cond(ct_expr, false)
if idx < node.ct_conds.len - 1 {
g.write(' && ')
}
}
ct_condition = g.out.cut_to(ct_condition_start).trim_space()
// dump(node)
// dump(ct_condition)
}
// #include etc
if node.kind == 'include' {
mut missing_message := 'Header file $node.main, needed for module `$node.mod` was not found.'
@ -1372,17 +1385,39 @@ fn (mut g Gen) stmt(node ast.Stmt) {
guarded_include = '#include $node.main'
}
if node.main.contains('.m') {
g.definitions.writeln('\n')
if ct_condition.len > 0 {
g.definitions.writeln('#if $ct_condition')
}
// Objective C code import, include it after V types, so that e.g. `string` is
// available there
g.definitions.writeln('// added by module `$node.mod`:')
g.definitions.writeln('// added by module `$node.mod`')
g.definitions.writeln(guarded_include)
if ct_condition.len > 0 {
g.definitions.writeln('#endif // \$if $ct_condition')
}
g.definitions.writeln('\n')
} else {
g.includes.writeln('// added by module `$node.mod`:')
g.includes.writeln('\n')
if ct_condition.len > 0 {
g.includes.writeln('#if $ct_condition')
}
g.includes.writeln('// added by module `$node.mod`')
g.includes.writeln(guarded_include)
if ct_condition.len > 0 {
g.includes.writeln('#endif // \$if $ct_condition')
}
g.includes.writeln('\n')
}
} else if node.kind == 'define' {
g.includes.writeln('// defined by module `$node.mod` in file `$node.source_file`:')
if ct_condition.len > 0 {
g.includes.writeln('#if $ct_condition')
}
g.includes.writeln('// defined by module `$node.mod`')
g.includes.writeln('#define $node.main')
if ct_condition.len > 0 {
g.includes.writeln('#endif // \$if $ct_condition')
}
}
}
ast.Import {}

View File

@ -154,7 +154,7 @@ pub mut:
custom_prelude string // Contents of custom V prelude that will be prepended before code in resulting .c files
lookup_path []string
bare_builtin_dir string // Path to implementation of malloc, memset, etc. Only used if is_bare is true
output_cross_c bool // true, when the user passed `-os cross`
output_cross_c bool // true, when the user passed `-os cross`
prealloc bool
vroot string
out_name_c string // full os.real_path to the generated .tmp.c file; set by builder.

View File

@ -0,0 +1 @@
char *version = "linux";

View File

@ -0,0 +1 @@
char *version = "non-linux";

View File

@ -0,0 +1,11 @@
$if linux {
#include "@VMODROOT/a_linux.h"
}
$if !linux {
#include "@VMODROOT/a_nonlinux.h"
}
fn main() {
C.printf(c'a: %s\n', C.version)
}