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:
|
||||
```v
|
||||
#flag -I @VROOT/c
|
||||
@ -1293,6 +1294,9 @@ Module {
|
||||
#include "header.h"
|
||||
```
|
||||
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 .
|
||||
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 )
|
||||
}
|
||||
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.table.parse_cflag(flag, p.mod, p.v.pref.compile_defines_all ) or {
|
||||
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)
|
||||
for lookup_path in p.v.module_lookup_paths {
|
||||
for lookup_path in module_lookup_paths {
|
||||
try_path := filepath.join(lookup_path,mod_path)
|
||||
if p.v.pref.is_verbose {
|
||||
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 error('module "$mod" not found in ${p.v.module_lookup_paths}')
|
||||
return error('module "$mod" not found in ${module_lookup_paths}')
|
||||
}
|
||||
|
||||
[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 levels := 0
|
||||
for {
|
||||
$if debug {
|
||||
eprintln('pdir2vmod mfolder: ${mfolder:-32s} | cfolder: ${cfolder:-20s} | levels: $levels')
|
||||
}
|
||||
if levels > 255 {
|
||||
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
|
||||
// if its source folder is different
|
||||
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
|
||||
}
|
||||
if mcache.check_for_stop( cfolder, files ) {
|
||||
|
Loading…
Reference in New Issue
Block a user