mirror of
https://github.com/vlang/v.git
synced 2025-08-04 02:07:28 -04:00
v.pref: allow for -os wasm32_emscripten
and filtering _d_wasm32_emscripten.c.v
and _notd_wasm32_emscripten.c.v
files. (#23797)
This commit is contained in:
parent
252df04ceb
commit
f83c8bf478
2
examples/2048/.gitignore
vendored
2
examples/2048/.gitignore
vendored
@ -2,3 +2,5 @@
|
||||
2048
|
||||
main
|
||||
|
||||
index.js
|
||||
index.wasm
|
||||
|
@ -28,7 +28,8 @@ Compile & run the game with `./v run examples/2048`
|
||||
|
||||
## Compiling to WASM
|
||||
|
||||
1. Install Emscripten from https://emscripten.org/docs/getting_started/downloads.html
|
||||
1. Install Emscripten from:
|
||||
https://emscripten.org/docs/getting_started/downloads.html
|
||||
|
||||
2. Make sure that the environment in your shell is setup correctly,
|
||||
i.e. that `emcc --version` works.
|
||||
@ -39,15 +40,9 @@ Compile & run the game with `./v run examples/2048`
|
||||
```
|
||||
|
||||
3. Compile the game to WASM:
|
||||
|
||||
(the JS file contains a loader for the .wasm file, without the extension):
|
||||
```sh
|
||||
v -skip-unused -prod -os wasm32_emscripten examples/2048/`
|
||||
```
|
||||
|
||||
4. Copy the 2048 file to `index.js` (can be done once; this step will be removed soon):
|
||||
|
||||
```sh
|
||||
cp examples/2048/2048 examples/2048/index.js
|
||||
v -prod -os wasm32_emscripten -o examples/2048/index.js examples/2048/
|
||||
```
|
||||
|
||||
5. Run/test the game:
|
||||
|
@ -608,7 +608,7 @@ pub fn find_abs_path_of_executable(exe_name string) !string {
|
||||
$if trace_find_abs_path_of_executable ? {
|
||||
dump(found_abs_path)
|
||||
}
|
||||
if exists(found_abs_path) && is_executable(found_abs_path) {
|
||||
if is_file(found_abs_path) && is_executable(found_abs_path) {
|
||||
res = found_abs_path
|
||||
break
|
||||
}
|
||||
|
@ -108,6 +108,7 @@ pub enum CC {
|
||||
icc
|
||||
msvc
|
||||
clang
|
||||
emcc
|
||||
unknown
|
||||
}
|
||||
|
||||
@ -210,6 +211,7 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
|
||||
cc_file_name.contains('clang') || ccoptions.guessed_compiler == 'clang' { .clang }
|
||||
cc_file_name.contains('msvc') || ccoptions.guessed_compiler == 'msvc' { .msvc }
|
||||
cc_file_name.contains('icc') || ccoptions.guessed_compiler == 'icc' { .icc }
|
||||
cc_file_name.contains('emcc') || ccoptions.guessed_compiler == 'emcc' { .emcc }
|
||||
else { .unknown }
|
||||
// vfmt on
|
||||
}
|
||||
@ -652,7 +654,7 @@ pub fn (mut v Builder) cc() {
|
||||
// whether to just create a .c or .js file and exit, for example: `v -o v.c cmd.v`
|
||||
ends_with_c := v.pref.out_name.ends_with('.c')
|
||||
ends_with_js := v.pref.out_name.ends_with('.js')
|
||||
if ends_with_c || ends_with_js {
|
||||
if ends_with_c || (ends_with_js && v.pref.os != .wasm32_emscripten) {
|
||||
v.pref.skip_running = true
|
||||
msg_mv := 'os.mv_by_cp ${os.quoted_path(v.out_name_c)} => ${os.quoted_path(v.pref.out_name)}'
|
||||
util.timing_start(msg_mv)
|
||||
|
@ -61,7 +61,7 @@ fn (mut p Preferences) setup_os_and_arch_when_not_explicitly_set() {
|
||||
host_os := if p.backend == .wasm { OS.wasi } else { get_host_os() }
|
||||
if p.os == ._auto {
|
||||
p.os = host_os
|
||||
p.build_options << '-os ${host_os}'
|
||||
p.build_options << '-os ${host_os.lower()}'
|
||||
}
|
||||
|
||||
if !p.output_cross_c {
|
||||
@ -83,6 +83,19 @@ fn (mut p Preferences) setup_os_and_arch_when_not_explicitly_set() {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut p Preferences) defines_map_unique_keys() string {
|
||||
mut defines_map := map[string]bool{}
|
||||
for d in p.compile_defines {
|
||||
defines_map[d] = true
|
||||
}
|
||||
for d in p.compile_defines_all {
|
||||
defines_map[d] = true
|
||||
}
|
||||
keys := defines_map.keys()
|
||||
skeys := keys.sorted()
|
||||
return skeys.join(',')
|
||||
}
|
||||
|
||||
pub fn (mut p Preferences) fill_with_defaults() {
|
||||
p.setup_os_and_arch_when_not_explicitly_set()
|
||||
p.expand_lookup_paths()
|
||||
@ -189,17 +202,20 @@ pub fn (mut p Preferences) fill_with_defaults() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final_os := p.os.lower()
|
||||
p.parse_define(final_os)
|
||||
|
||||
// Prepare the cache manager. All options that can affect the generated cached .c files
|
||||
// should go into res.cache_manager.vopts, which is used as a salt for the cache hash.
|
||||
vhash := @VHASH
|
||||
p.cache_manager = vcache.new_cache_manager([
|
||||
vhash,
|
||||
// ensure that different v versions use separate build artefacts
|
||||
'${p.backend} | ${p.os} | ${p.ccompiler} | ${p.is_prod} | ${p.sanitize}',
|
||||
'${p.backend} | ${final_os} | ${p.ccompiler} | ${p.is_prod} | ${p.sanitize}',
|
||||
p.defines_map_unique_keys(),
|
||||
p.cflags.trim_space(),
|
||||
p.third_party_option.trim_space(),
|
||||
p.compile_defines_all.str(),
|
||||
p.compile_defines.str(),
|
||||
p.lookup_path.str(),
|
||||
])
|
||||
// eprintln('prefs.cache_manager: $p')
|
||||
|
@ -131,6 +131,41 @@ pub fn os_from_string(os_str string) !OS {
|
||||
}
|
||||
}
|
||||
|
||||
// lower returns the name that could be used with `-os osname`, for each OS enum value
|
||||
// NOTE: it is important to not change the names here, they should match 1:1, since they
|
||||
// are used as part of the cache keys, when -usecache is passed.
|
||||
pub fn (o OS) lower() string {
|
||||
return match o {
|
||||
._auto { '' }
|
||||
.linux { 'linux' }
|
||||
.windows { 'windows' }
|
||||
.macos { 'macos' }
|
||||
.ios { 'ios' }
|
||||
.freebsd { 'freebsd' }
|
||||
.openbsd { 'openbsd' }
|
||||
.netbsd { 'netbsd' }
|
||||
.dragonfly { 'dragonfly' }
|
||||
.js_node { 'js' }
|
||||
.js_freestanding { 'js_freestanding' }
|
||||
.js_browser { 'js_browser' }
|
||||
.solaris { 'solaris' }
|
||||
.serenity { 'serenity' }
|
||||
.qnx { 'qnx' }
|
||||
.plan9 { 'plan9' }
|
||||
.vinix { 'vinix' }
|
||||
.android { 'android' }
|
||||
.termux { 'termux' }
|
||||
.haiku { 'haiku' }
|
||||
.raw { 'raw' }
|
||||
.wasm32 { 'wasm32' }
|
||||
.wasm32_wasi { 'wasm32_wasi' }
|
||||
.wasm32_emscripten { 'wasm32_emscripten' }
|
||||
.browser { 'browser' }
|
||||
.wasi { 'wasi' }
|
||||
.all { 'all' }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (o OS) str() string {
|
||||
// TODO: check more thoroughly, why this method needs to exist at all,
|
||||
// and why should it override the default autogenerated .str() method,
|
||||
|
@ -76,6 +76,7 @@ pub enum CompilerType {
|
||||
gcc
|
||||
tinyc
|
||||
clang
|
||||
emcc
|
||||
mingw
|
||||
msvc
|
||||
cplusplus
|
||||
@ -830,7 +831,7 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin
|
||||
res.build_options << '${arg}'
|
||||
}
|
||||
'-os' {
|
||||
target_os := cmdline.option(args[i..], '-os', '')
|
||||
target_os := cmdline.option(args[i..], '-os', '').to_lower_ascii()
|
||||
i++
|
||||
target_os_kind := os_from_string(target_os) or {
|
||||
if target_os == 'cross' {
|
||||
@ -895,12 +896,6 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin
|
||||
}
|
||||
'-o', '-output' {
|
||||
res.out_name = cmdline.option(args[i..], arg, '')
|
||||
if res.out_name.ends_with('.js') {
|
||||
res.backend = .js_node
|
||||
res.output_cross_c = true
|
||||
} else if res.out_name.ends_with('.o') {
|
||||
res.is_o = true
|
||||
}
|
||||
if !os.is_abs_path(res.out_name) {
|
||||
res.out_name = os.join_path(os.getwd(), res.out_name)
|
||||
}
|
||||
@ -1053,6 +1048,18 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin
|
||||
res.is_run = true
|
||||
}
|
||||
res.show_asserts = res.show_asserts || res.is_stats || os.getenv('VTEST_SHOW_ASSERTS') != ''
|
||||
|
||||
if res.os != .wasm32_emscripten {
|
||||
if res.out_name.ends_with('.js') {
|
||||
res.backend = .js_node
|
||||
res.output_cross_c = true
|
||||
}
|
||||
}
|
||||
|
||||
if res.out_name.ends_with('.o') {
|
||||
res.is_o = true
|
||||
}
|
||||
|
||||
if command == 'run' && res.is_prod && os.is_atty(1) > 0 {
|
||||
eprintln_cond(show_output && !res.is_quiet, "Note: building an optimized binary takes much longer. It shouldn't be used with `v run`.")
|
||||
eprintln_cond(show_output && !res.is_quiet, 'Use `v run` without optimization, or build an optimized binary with -prod first, then run it separately.')
|
||||
@ -1226,6 +1233,7 @@ pub fn cc_from_string(s string) CompilerType {
|
||||
cc.contains('tcc') || cc.contains('tinyc') { .tinyc }
|
||||
cc.contains('gcc') { .gcc }
|
||||
cc.contains('clang') { .clang }
|
||||
cc.contains('emcc') { .emcc }
|
||||
cc.contains('msvc') { .msvc }
|
||||
cc.contains('mingw') { .mingw }
|
||||
cc.contains('++') { .cplusplus }
|
||||
|
@ -15,28 +15,9 @@ pub fn (prefs &Preferences) should_compile_filtered_files(dir string, files_ []s
|
||||
|| file.all_before_last('.v').all_before_last('.').ends_with('_test') {
|
||||
continue
|
||||
}
|
||||
if prefs.backend in [.c, .interpret] && !prefs.should_compile_c(file) {
|
||||
continue
|
||||
}
|
||||
if prefs.backend.is_js() && !prefs.should_compile_js(file) {
|
||||
continue
|
||||
}
|
||||
if prefs.backend == .native && !prefs.should_compile_native(file) {
|
||||
continue
|
||||
}
|
||||
if !prefs.backend.is_js() && !prefs.should_compile_asm(file) {
|
||||
continue
|
||||
}
|
||||
if file.starts_with('.#') {
|
||||
continue
|
||||
}
|
||||
if !prefs.prealloc && !prefs.output_cross_c && file.ends_with('prealloc.c.v') {
|
||||
continue
|
||||
}
|
||||
if prefs.nofloat && file.ends_with('float.c.v') {
|
||||
continue
|
||||
}
|
||||
mut is_d_notd_file := false
|
||||
if file.contains('_d_') {
|
||||
is_d_notd_file = true
|
||||
if prefs.compile_defines_all.len == 0 {
|
||||
continue
|
||||
}
|
||||
@ -58,6 +39,7 @@ pub fn (prefs &Preferences) should_compile_filtered_files(dir string, files_ []s
|
||||
}
|
||||
}
|
||||
if file.contains('_notd_') {
|
||||
is_d_notd_file = true
|
||||
mut allowed := true
|
||||
for cdefine in prefs.compile_defines {
|
||||
file_postfixes := ['_notd_${cdefine}.v', '_notd_${cdefine}.c.v']
|
||||
@ -75,6 +57,27 @@ pub fn (prefs &Preferences) should_compile_filtered_files(dir string, files_ []s
|
||||
continue
|
||||
}
|
||||
}
|
||||
if prefs.backend in [.c, .interpret] && !is_d_notd_file && !prefs.should_compile_c(file) {
|
||||
continue
|
||||
}
|
||||
if prefs.backend.is_js() && !prefs.should_compile_js(file) {
|
||||
continue
|
||||
}
|
||||
if prefs.backend == .native && !prefs.should_compile_native(file) {
|
||||
continue
|
||||
}
|
||||
if !prefs.backend.is_js() && !prefs.should_compile_asm(file) {
|
||||
continue
|
||||
}
|
||||
if file.starts_with('.#') {
|
||||
continue
|
||||
}
|
||||
if !prefs.prealloc && !prefs.output_cross_c && file.ends_with('prealloc.c.v') {
|
||||
continue
|
||||
}
|
||||
if prefs.nofloat && file.ends_with('float.c.v') {
|
||||
continue
|
||||
}
|
||||
if prefs.exclude.len > 0 {
|
||||
full_file_path := os.join_path(dir, file)
|
||||
for epattern in prefs.exclude {
|
||||
|
@ -0,0 +1,5 @@
|
||||
module main
|
||||
|
||||
fn abc() {
|
||||
println('This is abc_d_wasm32_emscripten.c.v')
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
module main
|
||||
|
||||
fn abc() {
|
||||
println('This is abc_notd_wasm32_emscripten.c.v')
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
import os
|
||||
|
||||
const vexe = os.quoted_path(@VEXE)
|
||||
const project_folder = os.dir(@FILE)
|
||||
const output_path = os.join_path(os.vtmp_dir(), 'check_wasm_works')
|
||||
|
||||
fn testsuite_begin() {
|
||||
os.mkdir_all(output_path) or {}
|
||||
os.chdir(output_path)!
|
||||
dump(os.getwd())
|
||||
}
|
||||
|
||||
fn testsuite_end() {
|
||||
os.system('ls -la .')
|
||||
os.chdir(os.home_dir()) or {}
|
||||
os.rmdir_all(output_path) or {}
|
||||
}
|
||||
|
||||
fn test_normal() {
|
||||
if os.user_os() == 'windows' {
|
||||
return
|
||||
}
|
||||
defer { println('done ${@FN}') }
|
||||
dump(vexe)
|
||||
res := os.system('${os.quoted_path(vexe)} -o normal.exe ${os.quoted_path(project_folder)}')
|
||||
assert res == 0
|
||||
dump(res)
|
||||
assert os.exists('normal.exe')
|
||||
content := os.read_file('normal.exe')!
|
||||
assert content.contains('This is abc_notd_wasm32_emscripten.c.v')
|
||||
}
|
||||
|
||||
fn test_emcc() {
|
||||
if os.user_os() == 'windows' {
|
||||
return
|
||||
}
|
||||
defer { println('done ${@FN}') }
|
||||
emcc := os.find_abs_path_of_executable('emcc') or {
|
||||
println('skipping ${@FN} since `emcc` is not found')
|
||||
return
|
||||
}
|
||||
dump(emcc)
|
||||
res := os.system('${os.quoted_path(vexe)} -os wasm32_emscripten -o wasm_check.html ${os.quoted_path(project_folder)}')
|
||||
assert res == 0
|
||||
dump(res)
|
||||
assert os.exists('wasm_check.html')
|
||||
assert os.exists('wasm_check.js')
|
||||
assert os.exists('wasm_check.wasm')
|
||||
content := os.read_file('wasm_check.wasm')!
|
||||
assert content.contains('This is abc_d_wasm32_emscripten.c.v')
|
||||
}
|
6
vlib/v/tests/project_compiling_to_wasm/main.v
Normal file
6
vlib/v/tests/project_compiling_to_wasm/main.v
Normal file
@ -0,0 +1,6 @@
|
||||
module main
|
||||
|
||||
fn main() {
|
||||
abc()
|
||||
println('hi from main.v')
|
||||
}
|
0
vlib/v/tests/project_compiling_to_wasm/v.mod
Normal file
0
vlib/v/tests/project_compiling_to_wasm/v.mod
Normal file
Loading…
x
Reference in New Issue
Block a user