v/vlib/compiler/cflags.v

188 lines
4.4 KiB
V
Raw Normal View History

// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module compiler
import os
2019-09-06 14:43:03 +02:00
// parsed cflag
struct CFlag{
mod string // the module in which the flag was given
os string // eg. windows | darwin | linux
name string // eg. -I
2019-09-06 14:43:03 +02:00
value string // eg. /path/to/include
}
pub fn (c &CFlag) str() string {
return 'CFlag{ name: "$c.name" value: "$c.value" mod: "$c.mod" os: "$c.os" }'
}
// get flags for current os
fn (v &V) get_os_cflags() []CFlag {
mut flags := []CFlag
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
}
}
return flags
}
fn (v &V) get_rest_of_module_cflags(c &CFlag) []CFlag {
mut flags := []CFlag
cflags := v.get_os_cflags()
for flag in cflags {
if c.mod == flag.mod {
if c.name == flag.name && c.value == flag.value && c.os == flag.os { continue }
flags << flag
}
}
return flags
}
// format flag
fn (cf &CFlag) format() string {
mut value := cf.value
if cf.name in ['-l', '-Wa', '-Wl', '-Wp'] && value.len>0 {
return '${cf.name}${value}'.trim_space()
}
// convert to absolute path
if cf.name == '-I' || cf.name == '-L' || value.ends_with('.o') {
value = '"'+os.realpath(value)+'"'
}
return '$cf.name $value'.trim_space()
}
2019-09-06 14:43:03 +02:00
// check if cflag is in table
fn (table &Table) has_cflag(cflag CFlag) bool {
for cf in table.cflags {
if cf.os == cflag.os && cf.name == cflag.name && cf.value == cflag.value {
return true
}
}
return false
}
// 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 {
allowed_flags := [
'framework',
'library',
'Wa', 'Wl', 'Wp',
'I', 'l', 'L',
]
flag_orig := cflag.trim_space()
mut flag := flag_orig
if flag == '' {
return true
}
mut fos := ''
if flag.starts_with('linux') || flag.starts_with('darwin') || flag.starts_with('freebsd') || flag.starts_with('windows') {
pos := flag.index(' ') or { return none }
fos = flag[..pos].trim_space()
flag = flag[pos..].trim_space()
}
for {
2019-12-15 04:18:14 +01:00
mut name := ''
mut value := ''
if flag[0] == `-` {
for f in allowed_flags {
i := 1+f.len
if i <= flag.len && f == flag[1..i] {
name = flag[..i].trim_space()
flag = flag[i..].trim_space()
break
}
}
}
2019-12-15 04:18:14 +01:00
mut index := flag.index(' -') or { -1 }
for index > -1 {
mut has_next := false
for f in allowed_flags {
2019-12-15 04:18:14 +01:00
i := index+2+f.len
if i <= flag.len && f == flag[index+2..i] {
value = flag[..index+1].trim_space()
flag = flag[index+1..].trim_space()
has_next = true
break
}
}
2019-12-15 04:18:14 +01:00
if has_next { break }
index = flag.index_after(' -', index+1)
2019-09-07 18:19:17 +02:00
}
2019-12-15 04:18:14 +01:00
if index == -1 {
value = flag.trim_space()
}
if (name in ['-I', '-l', '-L']) && value == '' {
hint := if name == '-l' { 'library name' } else { 'path' }
return error('bad #flag `$flag_orig`: missing $hint after `$name`')
}
cf := CFlag{
mod: mod,
os: fos,
name: name,
value: value
}
if !table.has_cflag(cf) {
table.cflags << cf
}
if index == -1 {
break
}
}
return true
}
//TODO: implement msvc specific c_options_before_target and c_options_after_target ...
fn (cflags []CFlag) c_options_before_target_msvc() string { return '' }
fn (cflags []CFlag) c_options_after_target_msvc() string { return '' }
fn (cflags []CFlag) c_options_before_target() string {
// -I flags, optimization flags and so on
mut args:=[]string
for flag in cflags {
if flag.name != '-l' {
args << flag.format()
}
}
return args.join(' ')
}
fn (cflags []CFlag) c_options_after_target() string {
// -l flags (libs)
mut args:=[]string
for flag in cflags {
if flag.name == '-l' {
args << flag.format()
}
}
return args.join(' ')
}
fn (cflags []CFlag) c_options_without_object_files() string {
mut args:=[]string
for flag in cflags {
if flag.value.ends_with('.o') || flag.value.ends_with('.obj') {
continue
}
args << flag.format()
}
return args.join(' ')
}
fn (cflags []CFlag) c_options_only_object_files() string {
mut args:=[]string
for flag in cflags {
if flag.value.ends_with('.o') || flag.value.ends_with('.obj') {
args << flag.format()
}
}
return args.join(' ')
}