diff --git a/vlib/compiler/main.v b/vlib/compiler/main.v index 3c4be47b02..3ffc34aad8 100644 --- a/vlib/compiler/main.v +++ b/vlib/compiler/main.v @@ -77,6 +77,7 @@ pub mut: file_parser_idx map[string]int // map absolute file path to v.parsers index gen_parser_idx map[string]int cached_mods []string + module_lookup_paths []string } struct Preferences { @@ -641,23 +642,28 @@ pub fn (v &V) v_files_from_dir(dir string) []string { if file.ends_with('_c.v') && v.os == .js { continue } - res << '$dir${os.path_separator}$file' + res << filepath.join(dir,file) } return res } // Parses imports, adds necessary libs, and then user files pub fn (v mut V) add_v_files_to_compile() { + v.set_module_lookup_paths() mut builtin_files := v.get_builtin_files() if v.pref.is_bare { //builtin_files = [] } // Builtin cache exists? Use it. - builtin_vh := '${v.pref.vlib_path}${os.path_separator}builtin.vh' - if v.pref.is_cache && os.exists(builtin_vh) { - v.cached_mods << 'builtin' - builtin_files = [builtin_vh] + if v.pref.is_cache { + builtin_vh := filepath.join(v_modules_path,'vlib','builtin.vh') + if os.exists(builtin_vh) { + v.cached_mods << 'builtin' + builtin_files = [builtin_vh] + } } + if v.pref.is_verbose { v.log('v.add_v_files_to_compile > builtin_files: $builtin_files') } + // Parse builtin imports for file in builtin_files { // add builtins first @@ -768,11 +774,13 @@ pub fn (v &V) get_user_files() []string { } } if dir.ends_with('.v') || dir.ends_with('.vsh') { + single_v_file := dir // Just compile one file and get parent dir - user_files << dir - dir = dir.all_before(os.path_separator) + user_files << single_v_file + if v.pref.is_verbose { v.log('> just compile one file: "${single_v_file}"') } } else { + if v.pref.is_verbose { v.log('> add all .v files from directory "${dir}" ...') } // Add .v files from the directory being compiled files := v.v_files_from_dir(dir) for file in files { @@ -784,8 +792,7 @@ pub fn (v &V) get_user_files() []string { exit(1) } if v.pref.is_verbose { - v.log('user_files:') - println(user_files) + v.log('user_files: $user_files') } return user_files } diff --git a/vlib/compiler/modules.v b/vlib/compiler/modules.v index 2a3a0888eb..4d5d25336e 100644 --- a/vlib/compiler/modules.v +++ b/vlib/compiler/modules.v @@ -150,27 +150,45 @@ pub fn(graph &DepGraph) imports() []string { // 'strings' => 'VROOT/vlib/strings' // 'installed_mod' => '~/.vmodules/installed_mod' // 'local_mod' => '/path/to/current/dir/local_mod' -fn (v &V) find_module_path(mod string) ?string { + +fn (v mut V) set_module_lookup_paths(){ + mlookup_path := if v.pref.vpath.len>0{ v.pref.vpath }else{ v_modules_path } // Module search order: + // 0) V test files are very commonly located right inside the folder of the + // module, which they test. Adding the parent folder of the module folder + // with the _test.v files, *guarantees* that the tested module can be found + // without needing to set custom options/flags. + // 1) search in the *same* directory, as the compiled final v program source // (i.e. the . in `v .` or file.v in `v file.v`) // 2) search in the modules/ in the same directory. // 3) search in vlib/ // 4.1) search in -vpath (if given) // 4.2) search in ~/.vmodules/ (i.e. modules installed with vpm) (no -vpath) - modules_lookup_path := if v.pref.vpath.len > 0 { v.pref.vpath } else { v_modules_path } - mod_path := v.module_path(mod) - mut tried_paths := []string - tried_paths << filepath.join(v.compiled_dir, mod_path) - tried_paths << filepath.join(v.compiled_dir, 'modules', mod_path) - tried_paths << filepath.join(v.pref.vlib_path, mod_path) - tried_paths << filepath.join(modules_lookup_path, mod_path) - if v.pref.user_mod_path.len > 0 { - tried_paths << filepath.join(v.pref.user_mod_path, mod_path) + v.module_lookup_paths = [] + if v.pref.is_test { + v.module_lookup_paths << os.basedir(v.compiled_dir) // pdir of _test.v } - for try_path in tried_paths { + v.module_lookup_paths << v.compiled_dir + v.module_lookup_paths << filepath.join(v.compiled_dir, 'modules') + v.module_lookup_paths << v.pref.vlib_path + v.module_lookup_paths << mlookup_path + if v.pref.user_mod_path.len > 0 { + v.module_lookup_paths << v.pref.user_mod_path + } + + if v.pref.is_verbose { + v.log('v.module_lookup_paths: $v.module_lookup_paths') + } +} + +fn (v &V) find_module_path(mod string) ?string { + mod_path := v.module_path(mod) + for lookup_path in v.module_lookup_paths { + try_path := filepath.join(lookup_path, mod_path) if v.pref.is_verbose { println(' >> trying to find $mod in $try_path ...') } - if os.is_dir(try_path) { + if os.is_dir(try_path) { + if v.pref.is_verbose { println(' << found $try_path .') } return try_path } } diff --git a/vlib/compiler/tests/modules/simplemodule/importing_test.v b/vlib/compiler/tests/modules/simplemodule/importing_test.v new file mode 100644 index 0000000000..6cc3a00a2b --- /dev/null +++ b/vlib/compiler/tests/modules/simplemodule/importing_test.v @@ -0,0 +1,11 @@ +import simplemodule + +// this tests whether the tests can import the same module without any special +// custom paths setup on the CLI +fn test_iadd(){ + assert simplemodule.iadd(10, 20) == 30 +} + +fn test_imul(){ + assert simplemodule.imul(5,8) == 40 +} diff --git a/vlib/compiler/tests/modules/simplemodule/simplemodule.v b/vlib/compiler/tests/modules/simplemodule/simplemodule.v new file mode 100644 index 0000000000..fd3e125f5e --- /dev/null +++ b/vlib/compiler/tests/modules/simplemodule/simplemodule.v @@ -0,0 +1,9 @@ +module simplemodule + +pub fn iadd(x int, y int) int { + return x + y +} + +pub fn imul(x int, y int) int { + return x * y +}