mirror of
https://github.com/vlang/v.git
synced 2025-09-07 22:30:57 -04:00
builder,pref: allow thirdparty objects compilation with CPP compiler (#19124)
This commit is contained in:
parent
9543123dc5
commit
492e918fdb
@ -187,6 +187,7 @@ pub fn new_test_session(_vargs string, will_compile bool) TestSession {
|
||||
skip_files << 'examples/coroutines/simple_coroutines.v'
|
||||
$if msvc {
|
||||
skip_files << 'vlib/v/tests/const_comptime_eval_before_vinit_test.v' // _constructor used
|
||||
skip_files << 'vlib/v/tests/project_with_cpp_code/compiling_cpp_files_with_a_cplusplus_compiler_test.v'
|
||||
}
|
||||
$if solaris {
|
||||
skip_files << 'examples/gg/gg2.v'
|
||||
|
@ -170,6 +170,7 @@ const (
|
||||
'vlib/orm/orm_insert_reserved_name_test.v',
|
||||
'vlib/v/tests/orm_sub_array_struct_test.v',
|
||||
'vlib/v/tests/orm_handle_error_for_select_from_not_created_table_test.v',
|
||||
'vlib/v/tests/project_with_cpp_code/compiling_cpp_files_with_a_cplusplus_compiler_test.v', // fails compilation with: undefined reference to vtable for __cxxabiv1::__function_type_info'
|
||||
]
|
||||
skip_with_werror = [
|
||||
'do_not_remove',
|
||||
@ -243,6 +244,7 @@ const (
|
||||
'vlib/v/tests/const_fixed_array_containing_references_to_itself_test.v', // error C2099: initializer is not a constant
|
||||
'vlib/v/tests/const_and_global_with_same_name_test.v', // error C2099: initializer is not a constant
|
||||
'vlib/v/tests/sumtype_as_cast_test.v', // error: cannot support compound statement expression ({expr; expr; expr;})
|
||||
'vlib/v/tests/project_with_cpp_code/compiling_cpp_files_with_a_cplusplus_compiler_test.v', // TODO
|
||||
]
|
||||
skip_on_windows = [
|
||||
'do_not_remove',
|
||||
@ -333,6 +335,7 @@ fn main() {
|
||||
}
|
||||
|
||||
if github_job == 'windows-tcc' {
|
||||
tsession.skip_files << 'vlib/v/tests/project_with_cpp_code/compiling_cpp_files_with_a_cplusplus_compiler_test.v'
|
||||
// TODO: fix these ASAP
|
||||
tsession.skip_files << 'vlib/net/tcp_test.v'
|
||||
tsession.skip_files << 'vlib/net/udp_test.v'
|
||||
|
@ -10,6 +10,13 @@ import v.util
|
||||
import v.vcache
|
||||
import term
|
||||
|
||||
const (
|
||||
c_std = 'c99'
|
||||
c_std_gnu = 'gnu99'
|
||||
cpp_std = 'c++17'
|
||||
cpp_std_gnu = 'gnu++17'
|
||||
)
|
||||
|
||||
const c_verror_message_marker = 'VERROR_MESSAGE '
|
||||
|
||||
const c_error_info = '
|
||||
@ -131,13 +138,6 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
|
||||
// arguments for the C compiler
|
||||
ccoptions.args = [v.pref.cflags]
|
||||
ccoptions.ldflags = [v.pref.ldflags]
|
||||
if !v.pref.no_std {
|
||||
if v.pref.os == .linux {
|
||||
ccoptions.args << '-std=gnu99 -D_DEFAULT_SOURCE'
|
||||
} else {
|
||||
ccoptions.args << '-std=c99 -D_DEFAULT_SOURCE'
|
||||
}
|
||||
}
|
||||
ccoptions.wargs = [
|
||||
'-Wall',
|
||||
'-Wextra',
|
||||
@ -343,6 +343,14 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
|
||||
if v.pref.os == .macos {
|
||||
ccoptions.source_args << '-x none'
|
||||
}
|
||||
if !v.pref.no_std {
|
||||
if v.pref.os == .linux {
|
||||
ccoptions.source_args << '-std=${builder.c_std_gnu}'
|
||||
} else {
|
||||
ccoptions.source_args << '-std=${builder.c_std}'
|
||||
}
|
||||
ccoptions.source_args << '-D_DEFAULT_SOURCE'
|
||||
}
|
||||
// Min macos version is mandatory I think?
|
||||
if v.pref.os == .macos {
|
||||
ccoptions.post_args << '-mmacosx-version-min=10.7'
|
||||
@ -396,7 +404,7 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
|
||||
// setup the cache too, so that different compilers/options do not interfere:
|
||||
v.pref.cache_manager.set_temporary_options(v.thirdparty_object_args(v.ccoptions, [
|
||||
ccoptions.guessed_compiler,
|
||||
]))
|
||||
], false))
|
||||
}
|
||||
|
||||
fn (v &Builder) all_args(ccoptions CcompilerOptions) []string {
|
||||
@ -437,8 +445,26 @@ fn (v &Builder) all_args(ccoptions CcompilerOptions) []string {
|
||||
return all
|
||||
}
|
||||
|
||||
fn (v &Builder) thirdparty_object_args(ccoptions CcompilerOptions, middle []string) []string {
|
||||
fn (v &Builder) thirdparty_object_args(ccoptions CcompilerOptions, middle []string, cpp_file bool) []string {
|
||||
mut all := []string{}
|
||||
|
||||
if !v.pref.no_std {
|
||||
if v.pref.os == .linux {
|
||||
if cpp_file {
|
||||
all << '-std=${builder.cpp_std_gnu}'
|
||||
} else {
|
||||
all << '-std=${builder.c_std_gnu}'
|
||||
}
|
||||
} else {
|
||||
if cpp_file {
|
||||
all << '-std=${builder.cpp_std}'
|
||||
} else {
|
||||
all << '-std=${builder.c_std}'
|
||||
}
|
||||
}
|
||||
all << '-D_DEFAULT_SOURCE'
|
||||
}
|
||||
|
||||
all << ccoptions.env_cflags
|
||||
all << ccoptions.args
|
||||
all << middle
|
||||
@ -888,7 +914,13 @@ fn (mut b Builder) build_thirdparty_obj_files() {
|
||||
|
||||
fn (mut v Builder) build_thirdparty_obj_file(mod string, path string, moduleflags []cflag.CFlag) {
|
||||
obj_path := os.real_path(path)
|
||||
cfile := '${obj_path[..obj_path.len - 2]}.c'
|
||||
mut cfile := '${obj_path[..obj_path.len - 2]}.c'
|
||||
mut cpp_file := false
|
||||
if !os.exists(cfile) {
|
||||
// Guessed C file does not exist, so it may be a CPP file
|
||||
cfile += 'pp'
|
||||
cpp_file = true
|
||||
}
|
||||
opath := v.pref.cache_manager.mod_postfix_with_key2cpath(mod, '.o', obj_path)
|
||||
mut rebuild_reason_message := '${obj_path} not found, building it in ${opath} ...'
|
||||
if os.exists(opath) {
|
||||
@ -918,8 +950,17 @@ fn (mut v Builder) build_thirdparty_obj_file(mod string, path string, moduleflag
|
||||
all_options << moduleflags.c_options_before_target()
|
||||
all_options << '-o ${os.quoted_path(opath)}'
|
||||
all_options << '-c ${os.quoted_path(cfile)}'
|
||||
cc_options := v.thirdparty_object_args(v.ccoptions, all_options).join(' ')
|
||||
cmd := '${v.quote_compiler_name(v.pref.ccompiler)} ${cc_options}'
|
||||
cc_options := v.thirdparty_object_args(v.ccoptions, all_options, cpp_file).join(' ')
|
||||
|
||||
// If the third party object file requires a CPP file compilation, switch to a CPP compiler
|
||||
mut ccompiler := v.pref.ccompiler
|
||||
if cpp_file {
|
||||
$if trace_thirdparty_obj_files ? {
|
||||
println('>>> build_thirdparty_obj_files switched from compiler "${ccompiler}" to "${v.pref.cppcompiler}"')
|
||||
}
|
||||
ccompiler = v.pref.cppcompiler
|
||||
}
|
||||
cmd := '${v.quote_compiler_name(ccompiler)} ${cc_options}'
|
||||
$if trace_thirdparty_obj_files ? {
|
||||
println('>>> build_thirdparty_obj_files cmd: ${cmd}')
|
||||
}
|
||||
|
@ -119,6 +119,9 @@ pub fn (mut p Preferences) fill_with_defaults() {
|
||||
if p.ccompiler == '' {
|
||||
p.default_c_compiler()
|
||||
}
|
||||
if p.cppcompiler == '' {
|
||||
p.default_cpp_compiler()
|
||||
}
|
||||
p.find_cc_if_cross_compiling()
|
||||
p.ccompiler_type = cc_from_string(p.ccompiler)
|
||||
p.is_test = p.path.ends_with('_test.v') || p.path.ends_with('_test.vv')
|
||||
@ -244,6 +247,14 @@ pub fn (mut p Preferences) default_c_compiler() {
|
||||
return
|
||||
}
|
||||
|
||||
pub fn (mut p Preferences) default_cpp_compiler() {
|
||||
if p.ccompiler.contains('clang') {
|
||||
p.cppcompiler = 'clang++'
|
||||
return
|
||||
}
|
||||
p.cppcompiler = 'c++'
|
||||
}
|
||||
|
||||
pub fn vexe_path() string {
|
||||
vexe := os.getenv('VEXE')
|
||||
if vexe != '' {
|
||||
|
@ -163,6 +163,7 @@ pub mut:
|
||||
m64 bool // true = generate 64-bit code, defaults to x64
|
||||
ccompiler string // the name of the C compiler used
|
||||
ccompiler_type CompilerType // the type of the C compiler used
|
||||
cppcompiler string // the name of the CPP compiler used
|
||||
third_party_option string
|
||||
building_v bool
|
||||
no_bounds_checking bool // `-no-bounds-checking` turns off *all* bounds checks for all functions at runtime, as if they all had been tagged with `[direct_array_access]`
|
||||
@ -738,6 +739,10 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin
|
||||
res.build_options << '${arg} "${res.ccompiler}"'
|
||||
i++
|
||||
}
|
||||
'-c++' {
|
||||
res.cppcompiler = cmdline.option(current_args, '-c++', 'c++')
|
||||
i++
|
||||
}
|
||||
'-checker-match-exhaustive-cutoff-limit' {
|
||||
res.checker_match_exhaustive_cutoff_limit = cmdline.option(current_args,
|
||||
arg, '10').int()
|
||||
|
@ -0,0 +1,19 @@
|
||||
module main
|
||||
|
||||
#flag @VMODROOT/implementation.o
|
||||
#include "@VMODROOT/implementation.h"
|
||||
|
||||
fn C.sizeof_char() int
|
||||
|
||||
fn test_the_implementation_object_file_was_compiled_with_a_c_plus_plus_compiler() {
|
||||
res := C.sizeof_char()
|
||||
dump(res)
|
||||
if res == sizeof(int) {
|
||||
eprintln('implementation.o was compiled with a C compiler. Fail.')
|
||||
} else if res == sizeof(char) {
|
||||
println('implementation.o was compiled with a C++ compiler. Good.')
|
||||
} else {
|
||||
eprintln('¯\\_(ツ)_/¯ ... unknown C/C++ compiler')
|
||||
}
|
||||
assert res == sizeof(char)
|
||||
}
|
9
vlib/v/tests/project_with_cpp_code/implementation.cpp
Normal file
9
vlib/v/tests/project_with_cpp_code/implementation.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
// This file should be compiled with a C++ compiler:
|
||||
extern "C" {
|
||||
int sizeof_char(void);
|
||||
}
|
||||
|
||||
int sizeof_char(void) {
|
||||
// see https://stackoverflow.com/a/12887719/1023403
|
||||
return sizeof('a'); // 4 for C compilers, 1 for C++ compilers
|
||||
}
|
1
vlib/v/tests/project_with_cpp_code/implementation.h
Normal file
1
vlib/v/tests/project_with_cpp_code/implementation.h
Normal file
@ -0,0 +1 @@
|
||||
int sizeof_char(void);
|
5
vlib/v/tests/project_with_cpp_code/v.mod
Normal file
5
vlib/v/tests/project_with_cpp_code/v.mod
Normal file
@ -0,0 +1,5 @@
|
||||
Module {
|
||||
name: 'project_with_cpp_code',
|
||||
description: 'A simple project, containing a .cpp file with C++ code, that has to be compiled with a C++ compiler.',
|
||||
dependencies: []
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user