mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
compiler: import modules relative to v.mod
This commit is contained in:
parent
615a4b3452
commit
1066ec5cd9
@ -1286,6 +1286,7 @@ Module {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
* Add these lines to the top of your module:
|
* Add these lines to the top of your module:
|
||||||
```v
|
```v
|
||||||
#flag -I @VROOT/c
|
#flag -I @VROOT/c
|
||||||
@ -1293,6 +1294,9 @@ Module {
|
|||||||
#include "header.h"
|
#include "header.h"
|
||||||
```
|
```
|
||||||
NB: @VROOT will be replaced by V with the *nearest parent folder, where there is a v.mod file*.
|
NB: @VROOT will be replaced by V with the *nearest parent folder, where there is a v.mod file*.
|
||||||
|
Any .v file beside or below the folder where the v.mod file is, can use #flag @VROOT/abc to refer to this folder.
|
||||||
|
The @VROOT folder is also *prepended* to the module lookup path, so you can *import* other
|
||||||
|
modules under your @VROOT, by just naming them.
|
||||||
|
|
||||||
The instructions above will make V look for an compiled .o file in your module folder/c/implementation.o .
|
The instructions above will make V look for an compiled .o file in your module folder/c/implementation.o .
|
||||||
If V finds it, the .o file will get linked to the main executable, that used the module.
|
If V finds it, the .o file will get linked to the main executable, that used the module.
|
||||||
|
@ -254,6 +254,11 @@ fn (p mut Parser) chash() {
|
|||||||
}
|
}
|
||||||
flag = flag.replace('@VROOT', vmod_file_location.vmod_folder )
|
flag = flag.replace('@VROOT', vmod_file_location.vmod_folder )
|
||||||
}
|
}
|
||||||
|
for deprecated in ['@VMOD', '@VMODULE', '@VPATH', '@VLIB_PATH'] {
|
||||||
|
if flag.contains(deprecated) {
|
||||||
|
p.error('${deprecated} had been deprecated, use @VROOT instead.')
|
||||||
|
}
|
||||||
|
}
|
||||||
// p.log('adding flag "$flag"')
|
// p.log('adding flag "$flag"')
|
||||||
_ = p.table.parse_cflag(flag, p.mod, p.v.pref.compile_defines_all ) or {
|
_ = p.table.parse_cflag(flag, p.mod, p.v.pref.compile_defines_all ) or {
|
||||||
p.error_with_token_index(err, p.cur_tok_index() - 1)
|
p.error_with_token_index(err, p.cur_tok_index() - 1)
|
||||||
|
@ -182,9 +182,18 @@ fn (v mut V) set_module_lookup_paths() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p &Parser) find_module_path(mod string) ?string {
|
fn (p mut Parser) find_module_path(mod string) ?string {
|
||||||
|
vmod_file_location := p.v.mod_file_cacher.get( p.file_path_dir )
|
||||||
|
mut module_lookup_paths := []string
|
||||||
|
if vmod_file_location.vmod_file.len != 0 {
|
||||||
|
if ! vmod_file_location.vmod_folder in p.v.module_lookup_paths {
|
||||||
|
module_lookup_paths << vmod_file_location.vmod_folder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module_lookup_paths << p.v.module_lookup_paths
|
||||||
|
|
||||||
mod_path := p.v.module_path(mod)
|
mod_path := p.v.module_path(mod)
|
||||||
for lookup_path in p.v.module_lookup_paths {
|
for lookup_path in module_lookup_paths {
|
||||||
try_path := filepath.join(lookup_path,mod_path)
|
try_path := filepath.join(lookup_path,mod_path)
|
||||||
if p.v.pref.is_verbose {
|
if p.v.pref.is_verbose {
|
||||||
println(' >> trying to find $mod in $try_path ...')
|
println(' >> trying to find $mod in $try_path ...')
|
||||||
@ -196,7 +205,7 @@ fn (p &Parser) find_module_path(mod string) ?string {
|
|||||||
return try_path
|
return try_path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return error('module "$mod" not found in ${p.v.module_lookup_paths}')
|
return error('module "$mod" not found in ${module_lookup_paths}')
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
2
vlib/compiler/tests/project_with_modules_having_submodules/.gitignore
vendored
Normal file
2
vlib/compiler/tests/project_with_modules_having_submodules/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/bin/main
|
||||||
|
/tests/submodule_test
|
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
This projects demonstrates how v.mod lookup can be used so that
|
||||||
|
a project/module can be as selfcontained as possible.
|
||||||
|
|
||||||
|
The programs under bin/ can find the modules mod1,
|
||||||
|
because the project has a 'v.mod' file, so v module lookup for
|
||||||
|
the programs under bin/ can still find the parent sibling folder
|
||||||
|
mod1/ through relation to the parent 'v.mod' file.
|
||||||
|
|
||||||
|
Note also that mod1/ also has its own 'v.mod' file.
|
||||||
|
This allows mod1 submodules to find and import themselves
|
||||||
|
in relation to it too.
|
||||||
|
|
||||||
|
Finally, there is a test/ folder, so you can put all your tests
|
||||||
|
in there, without cluttering your top level folder, or your module
|
||||||
|
folders if you so desire.
|
@ -0,0 +1,12 @@
|
|||||||
|
import mod1.submodule as m
|
||||||
|
|
||||||
|
fn test_mod1_can_still_be_found_through_parent_project_vmod(){
|
||||||
|
assert 1051 == m.f()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
NB: this main program is under bin/ , but it still
|
||||||
|
can find mod1, because the parent project has v.mod,
|
||||||
|
so v module lookup for this program will find mod1 through
|
||||||
|
relation to the parent v.mod file
|
||||||
|
*/
|
14
vlib/compiler/tests/project_with_modules_having_submodules/bin/main.vsh
Executable file
14
vlib/compiler/tests/project_with_modules_having_submodules/bin/main.vsh
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/local/bin/v run
|
||||||
|
import mod1.submodule as m
|
||||||
|
|
||||||
|
println('This script is located inside: ' + resource_abs_path(''))
|
||||||
|
|
||||||
|
println('The result of calling m.f is: ' + m.f().str() )
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
NB: this main program v script is under bin/ ,
|
||||||
|
but it *still* can find mod1, because the parent project has v.mod,
|
||||||
|
so v module lookup for this bin/main.vsh file will find mod1 through
|
||||||
|
relation to the parent ../v.mod file
|
||||||
|
*/
|
@ -0,0 +1,5 @@
|
|||||||
|
module mod1
|
||||||
|
|
||||||
|
pub fn f() int {
|
||||||
|
return 1
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
module mod11
|
||||||
|
|
||||||
|
pub fn f() int {
|
||||||
|
return 11
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
module mod12
|
||||||
|
|
||||||
|
pub fn f() int {
|
||||||
|
return 12
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
module mod13
|
||||||
|
|
||||||
|
pub fn f() int {
|
||||||
|
return 13
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
module mod14
|
||||||
|
|
||||||
|
import math
|
||||||
|
|
||||||
|
pub fn f() int {
|
||||||
|
return 14 + int(math.cos(0))
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
module submodule
|
||||||
|
|
||||||
|
/*
|
||||||
|
This submodule just imports its sibling submodules.
|
||||||
|
Note that they are NOT under 'submodule' itself,
|
||||||
|
but are in its parent mod1 , and mod1 has a 'v.mod' file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import mod11
|
||||||
|
import mod12
|
||||||
|
import mod13
|
||||||
|
import mod14
|
||||||
|
|
||||||
|
pub fn f() int {
|
||||||
|
return 1000 + mod11.f() + mod12.f() + mod13.f() + mod14.f()
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
#V Module#
|
||||||
|
|
||||||
|
Module {
|
||||||
|
name: 'mod1',
|
||||||
|
description: 'A module with several submodules.',
|
||||||
|
dependencies: []
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import mod1
|
||||||
|
|
||||||
|
import mod1.submodule
|
||||||
|
|
||||||
|
fn test_mod1(){
|
||||||
|
assert 1 == mod1.f()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mod1_submodule_can_find_and_use_all_its_sibling_submodules(){
|
||||||
|
assert 1051 == submodule.f()
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
#V Project#
|
||||||
|
|
||||||
|
Module {
|
||||||
|
name: 'project_with_modules_having_submodules',
|
||||||
|
description: 'This project was created with `v create` to prevent regressions with the way V module import lookup works.',
|
||||||
|
dependencies: []
|
||||||
|
}
|
@ -79,9 +79,6 @@ fn (mcache mut ModFileCacher) traverse(mfolder string) ([]string, ModFileAndFold
|
|||||||
mut folders_so_far := [cfolder]
|
mut folders_so_far := [cfolder]
|
||||||
mut levels := 0
|
mut levels := 0
|
||||||
for {
|
for {
|
||||||
$if debug {
|
|
||||||
eprintln('pdir2vmod mfolder: ${mfolder:-32s} | cfolder: ${cfolder:-20s} | levels: $levels')
|
|
||||||
}
|
|
||||||
if levels > 255 {
|
if levels > 255 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -102,10 +99,6 @@ fn (mcache mut ModFileCacher) traverse(mfolder string) ([]string, ModFileAndFold
|
|||||||
// TODO: actually read the v.mod file and parse its contents to see
|
// TODO: actually read the v.mod file and parse its contents to see
|
||||||
// if its source folder is different
|
// if its source folder is different
|
||||||
res := ModFileAndFolder{ vmod_file: filepath.join( cfolder, 'v.mod'), vmod_folder: cfolder }
|
res := ModFileAndFolder{ vmod_file: filepath.join( cfolder, 'v.mod'), vmod_folder: cfolder }
|
||||||
$if debug {
|
|
||||||
eprintln('FOUND v.mod:')
|
|
||||||
eprintln(' ModFileAndFolder{ vmod_file: $res.vmod_file , vmod_folder: $res.vmod_folder } ')
|
|
||||||
}
|
|
||||||
return folders_so_far, res
|
return folders_so_far, res
|
||||||
}
|
}
|
||||||
if mcache.check_for_stop( cfolder, files ) {
|
if mcache.check_for_stop( cfolder, files ) {
|
||||||
|
Loading…
Reference in New Issue
Block a user