mirror of
https://github.com/vlang/v.git
synced 2025-09-10 07:47:20 -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'
|
skip_files << 'examples/coroutines/simple_coroutines.v'
|
||||||
$if msvc {
|
$if msvc {
|
||||||
skip_files << 'vlib/v/tests/const_comptime_eval_before_vinit_test.v' // _constructor used
|
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 {
|
$if solaris {
|
||||||
skip_files << 'examples/gg/gg2.v'
|
skip_files << 'examples/gg/gg2.v'
|
||||||
|
@ -170,6 +170,7 @@ const (
|
|||||||
'vlib/orm/orm_insert_reserved_name_test.v',
|
'vlib/orm/orm_insert_reserved_name_test.v',
|
||||||
'vlib/v/tests/orm_sub_array_struct_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/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 = [
|
skip_with_werror = [
|
||||||
'do_not_remove',
|
'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_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/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/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 = [
|
skip_on_windows = [
|
||||||
'do_not_remove',
|
'do_not_remove',
|
||||||
@ -333,6 +335,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if github_job == 'windows-tcc' {
|
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
|
// TODO: fix these ASAP
|
||||||
tsession.skip_files << 'vlib/net/tcp_test.v'
|
tsession.skip_files << 'vlib/net/tcp_test.v'
|
||||||
tsession.skip_files << 'vlib/net/udp_test.v'
|
tsession.skip_files << 'vlib/net/udp_test.v'
|
||||||
|
@ -10,6 +10,13 @@ import v.util
|
|||||||
import v.vcache
|
import v.vcache
|
||||||
import term
|
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_verror_message_marker = 'VERROR_MESSAGE '
|
||||||
|
|
||||||
const c_error_info = '
|
const c_error_info = '
|
||||||
@ -131,13 +138,6 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
|
|||||||
// arguments for the C compiler
|
// arguments for the C compiler
|
||||||
ccoptions.args = [v.pref.cflags]
|
ccoptions.args = [v.pref.cflags]
|
||||||
ccoptions.ldflags = [v.pref.ldflags]
|
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 = [
|
ccoptions.wargs = [
|
||||||
'-Wall',
|
'-Wall',
|
||||||
'-Wextra',
|
'-Wextra',
|
||||||
@ -343,6 +343,14 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
|
|||||||
if v.pref.os == .macos {
|
if v.pref.os == .macos {
|
||||||
ccoptions.source_args << '-x none'
|
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?
|
// Min macos version is mandatory I think?
|
||||||
if v.pref.os == .macos {
|
if v.pref.os == .macos {
|
||||||
ccoptions.post_args << '-mmacosx-version-min=10.7'
|
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:
|
// 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, [
|
v.pref.cache_manager.set_temporary_options(v.thirdparty_object_args(v.ccoptions, [
|
||||||
ccoptions.guessed_compiler,
|
ccoptions.guessed_compiler,
|
||||||
]))
|
], false))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (v &Builder) all_args(ccoptions CcompilerOptions) []string {
|
fn (v &Builder) all_args(ccoptions CcompilerOptions) []string {
|
||||||
@ -437,8 +445,26 @@ fn (v &Builder) all_args(ccoptions CcompilerOptions) []string {
|
|||||||
return all
|
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{}
|
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.env_cflags
|
||||||
all << ccoptions.args
|
all << ccoptions.args
|
||||||
all << middle
|
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) {
|
fn (mut v Builder) build_thirdparty_obj_file(mod string, path string, moduleflags []cflag.CFlag) {
|
||||||
obj_path := os.real_path(path)
|
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)
|
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} ...'
|
mut rebuild_reason_message := '${obj_path} not found, building it in ${opath} ...'
|
||||||
if os.exists(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 << moduleflags.c_options_before_target()
|
||||||
all_options << '-o ${os.quoted_path(opath)}'
|
all_options << '-o ${os.quoted_path(opath)}'
|
||||||
all_options << '-c ${os.quoted_path(cfile)}'
|
all_options << '-c ${os.quoted_path(cfile)}'
|
||||||
cc_options := v.thirdparty_object_args(v.ccoptions, all_options).join(' ')
|
cc_options := v.thirdparty_object_args(v.ccoptions, all_options, cpp_file).join(' ')
|
||||||
cmd := '${v.quote_compiler_name(v.pref.ccompiler)} ${cc_options}'
|
|
||||||
|
// 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 ? {
|
$if trace_thirdparty_obj_files ? {
|
||||||
println('>>> build_thirdparty_obj_files cmd: ${cmd}')
|
println('>>> build_thirdparty_obj_files cmd: ${cmd}')
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,9 @@ pub fn (mut p Preferences) fill_with_defaults() {
|
|||||||
if p.ccompiler == '' {
|
if p.ccompiler == '' {
|
||||||
p.default_c_compiler()
|
p.default_c_compiler()
|
||||||
}
|
}
|
||||||
|
if p.cppcompiler == '' {
|
||||||
|
p.default_cpp_compiler()
|
||||||
|
}
|
||||||
p.find_cc_if_cross_compiling()
|
p.find_cc_if_cross_compiling()
|
||||||
p.ccompiler_type = cc_from_string(p.ccompiler)
|
p.ccompiler_type = cc_from_string(p.ccompiler)
|
||||||
p.is_test = p.path.ends_with('_test.v') || p.path.ends_with('_test.vv')
|
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
|
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 {
|
pub fn vexe_path() string {
|
||||||
vexe := os.getenv('VEXE')
|
vexe := os.getenv('VEXE')
|
||||||
if vexe != '' {
|
if vexe != '' {
|
||||||
|
@ -163,6 +163,7 @@ pub mut:
|
|||||||
m64 bool // true = generate 64-bit code, defaults to x64
|
m64 bool // true = generate 64-bit code, defaults to x64
|
||||||
ccompiler string // the name of the C compiler used
|
ccompiler string // the name of the C compiler used
|
||||||
ccompiler_type CompilerType // the type 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
|
third_party_option string
|
||||||
building_v bool
|
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]`
|
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}"'
|
res.build_options << '${arg} "${res.ccompiler}"'
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
'-c++' {
|
||||||
|
res.cppcompiler = cmdline.option(current_args, '-c++', 'c++')
|
||||||
|
i++
|
||||||
|
}
|
||||||
'-checker-match-exhaustive-cutoff-limit' {
|
'-checker-match-exhaustive-cutoff-limit' {
|
||||||
res.checker_match_exhaustive_cutoff_limit = cmdline.option(current_args,
|
res.checker_match_exhaustive_cutoff_limit = cmdline.option(current_args,
|
||||||
arg, '10').int()
|
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