Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v.pref: allow for -os wasm32_emscripten and later filtering _d_wasm32_emscripten.c.v and _notd_wasm32_emscripten.c.v files. #23797

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/2048/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
2048
main

index.js
index.wasm
13 changes: 4 additions & 9 deletions examples/2048/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -39,15 +40,9 @@ Compile & run the game with `./v run examples/2048`
```

3. Compile the game to WASM:

```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):

(the JS file contains a loader for the .wasm file, without the extension):
```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:
Expand Down
2 changes: 1 addition & 1 deletion vlib/os/os.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
4 changes: 3 additions & 1 deletion vlib/v/builder/cc.v
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ pub enum CC {
icc
msvc
clang
emcc
unknown
}

Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 6 additions & 2 deletions vlib/v/pref/default.v
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -189,13 +189,17 @@ 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.cflags.trim_space(),
p.third_party_option.trim_space(),
p.compile_defines_all.str(),
Expand Down
35 changes: 35 additions & 0 deletions vlib/v/pref/os.v
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
22 changes: 15 additions & 7 deletions vlib/v/pref/pref.v
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub enum CompilerType {
gcc
tinyc
clang
emcc
mingw
msvc
cplusplus
Expand Down Expand Up @@ -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' {
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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.')
Expand Down Expand Up @@ -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 }
Expand Down
45 changes: 24 additions & 21 deletions vlib/v/pref/should_compile.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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']
Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module main

fn abc() {
println('This is abc_d_wasm32_emscripten.c.v')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module main

fn abc() {
println('This is abc_notd_wasm32_emscripten.c.v')
}
Original file line number Diff line number Diff line change
@@ -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 changes: 6 additions & 0 deletions vlib/v/tests/project_compiling_to_wasm/main.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module main

fn main() {
abc()
println('hi from main.v')
}
Empty file.
Loading