compiler: support storing temporary files under TMPDIR/v/
Fix for filepath.join not \0 terminating its resultpull/2791/head
parent
200fcd41ce
commit
be7cf3e812
|
@ -799,6 +799,7 @@ pub fn new_v(args[]string) &V {
|
||||||
vgen_buf.writeln('module vgen\nimport strings')
|
vgen_buf.writeln('module vgen\nimport strings')
|
||||||
|
|
||||||
joined_args := args.join(' ')
|
joined_args := args.join(' ')
|
||||||
|
|
||||||
target_os := get_arg(joined_args, 'os', '')
|
target_os := get_arg(joined_args, 'os', '')
|
||||||
comptime_define := get_arg(joined_args, 'd', '')
|
comptime_define := get_arg(joined_args, 'd', '')
|
||||||
//println('comptimedefine=$comptime_define')
|
//println('comptimedefine=$comptime_define')
|
||||||
|
@ -930,8 +931,8 @@ pub fn new_v(args[]string) &V {
|
||||||
println('Go to https://vlang.io to install V.')
|
println('Go to https://vlang.io to install V.')
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
// println('out_name:$out_name')
|
|
||||||
mut out_name_c := os.realpath('${out_name}.tmp.c')
|
mut out_name_c := get_vtmp_filename( out_name, '.tmp.c')
|
||||||
|
|
||||||
cflags := get_cmdline_cflags(args)
|
cflags := get_cmdline_cflags(args)
|
||||||
|
|
||||||
|
@ -978,7 +979,7 @@ pub fn new_v(args[]string) &V {
|
||||||
println('C compiler=$pref.ccompiler')
|
println('C compiler=$pref.ccompiler')
|
||||||
}
|
}
|
||||||
if pref.is_so {
|
if pref.is_so {
|
||||||
out_name_c = out_name.all_after(os.path_separator) + '_shared_lib.c'
|
out_name_c = get_vtmp_filename( out_name, '.tmp.so.c')
|
||||||
}
|
}
|
||||||
$if !linux {
|
$if !linux {
|
||||||
if pref.is_bare && !out_name.ends_with('.c') {
|
if pref.is_bare && !out_name.ends_with('.c') {
|
||||||
|
|
|
@ -28,6 +28,9 @@ pub const (
|
||||||
You can set it like this: `export VFLAGS="-cc clang -debug"` on *nix,
|
You can set it like this: `export VFLAGS="-cc clang -debug"` on *nix,
|
||||||
`set VFLAGS=-cc msvc` on Windows.
|
`set VFLAGS=-cc msvc` on Windows.
|
||||||
|
|
||||||
|
V respects the TMPDIR environment variable, and will put .tmp.c files in TMPDIR/v/ .
|
||||||
|
If you have not set it, a suitable platform specific folder (like /tmp) will be used.
|
||||||
|
|
||||||
Options/commands:
|
Options/commands:
|
||||||
-h, help Display this information.
|
-h, help Display this information.
|
||||||
-o <file> Write output to <file>.
|
-o <file> Write output to <file>.
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
module compiler
|
||||||
|
|
||||||
|
import os
|
||||||
|
import filepath
|
||||||
|
|
||||||
|
pub fn get_vtmp_folder() string {
|
||||||
|
vtmp := filepath.join(os.tmpdir(),'v')
|
||||||
|
if !os.dir_exists( vtmp ) {
|
||||||
|
os.mkdir(vtmp)
|
||||||
|
}
|
||||||
|
return vtmp
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_vtmp_filename(base_file_name string, postfix string) string {
|
||||||
|
vtmp := get_vtmp_folder()
|
||||||
|
return os.realpath( filepath.join(vtmp, os.filename( base_file_name ) + postfix) )
|
||||||
|
}
|
|
@ -2,7 +2,6 @@ module filepath
|
||||||
|
|
||||||
import(
|
import(
|
||||||
os
|
os
|
||||||
strings
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// return the extension in the file `path`
|
// return the extension in the file `path`
|
||||||
|
@ -26,11 +25,8 @@ pub fn is_abs(path string) bool {
|
||||||
// pass directories as parameters, returns path as string
|
// pass directories as parameters, returns path as string
|
||||||
// TODO use []string.join once ...string becomes "[]string"
|
// TODO use []string.join once ...string becomes "[]string"
|
||||||
pub fn join(base string, dirs ...string) string {
|
pub fn join(base string, dirs ...string) string {
|
||||||
mut path := strings.new_builder(50)
|
mut result := []string
|
||||||
path.write(base.trim_right('\\/'))
|
result << base.trim_right('\\/')
|
||||||
for d in dirs {
|
for d in dirs { result << d }
|
||||||
path.write(os.path_separator)
|
return result.join( os.path_separator )
|
||||||
path.write(d)
|
|
||||||
}
|
|
||||||
return path.str()
|
|
||||||
}
|
}
|
||||||
|
|
51
vlib/os/os.v
51
vlib/os/os.v
|
@ -145,17 +145,26 @@ pub fn cp(old, new string) ?bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cp_r(source_path, dest_path string, overwrite bool) ?bool{
|
pub fn cp_r(osource_path, odest_path string, overwrite bool) ?bool{
|
||||||
|
source_path := os.realpath( osource_path )
|
||||||
|
dest_path := os.realpath( odest_path )
|
||||||
if !os.file_exists(source_path) {
|
if !os.file_exists(source_path) {
|
||||||
return error('Source path doesn\'t exist')
|
return error('Source path doesn\'t exist')
|
||||||
}
|
}
|
||||||
//single file copy
|
//single file copy
|
||||||
if !os.is_dir(source_path) {
|
if !os.is_dir(source_path) {
|
||||||
adjasted_path := if os.is_dir(dest_path) {
|
adjasted_path := if os.is_dir(dest_path) {
|
||||||
filepath.join(dest_path, os.basedir(source_path)) } else { dest_path }
|
filepath.join(dest_path, os.filename(source_path))
|
||||||
|
} else {
|
||||||
|
dest_path
|
||||||
|
}
|
||||||
if os.file_exists(adjasted_path) {
|
if os.file_exists(adjasted_path) {
|
||||||
if overwrite { os.rm(adjasted_path) }
|
if overwrite {
|
||||||
else { return error('Destination file path already exist') }
|
os.rm(adjasted_path)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return error('Destination file path already exist')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
os.cp(source_path, adjasted_path) or { return error(err) }
|
os.cp(source_path, adjasted_path) or { return error(err) }
|
||||||
return true
|
return true
|
||||||
|
@ -558,7 +567,7 @@ pub fn basedir(path string) string {
|
||||||
if pos == -1 {
|
if pos == -1 {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
return path[..pos + 1]
|
return path[..pos ] // NB: *without* terminating /
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filename(path string) string {
|
pub fn filename(path string) string {
|
||||||
|
@ -835,10 +844,6 @@ pub fn realpath(fpath string) string {
|
||||||
res = int( !isnil(C._fullpath( fullpath, fpath.str, MAX_PATH )) )
|
res = int( !isnil(C._fullpath( fullpath, fpath.str, MAX_PATH )) )
|
||||||
}
|
}
|
||||||
$else{
|
$else{
|
||||||
if fpath.len != strlen(fpath.str) {
|
|
||||||
l := strlen(fpath.str)
|
|
||||||
println('FIXME realpath diff len $fpath.len strlen=$l')
|
|
||||||
}
|
|
||||||
ret := C.realpath(fpath.str, fullpath)
|
ret := C.realpath(fpath.str, fullpath)
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
return fpath
|
return fpath
|
||||||
|
@ -965,3 +970,31 @@ pub fn join(base string, dirs ...string) string {
|
||||||
println('use filepath.join')
|
println('use filepath.join')
|
||||||
return filepath.join(base, dirs)
|
return filepath.join(base, dirs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tmpdir returns the path to a folder, that is suitable for storing temporary files
|
||||||
|
pub fn tmpdir() string {
|
||||||
|
mut path := os.getenv('TMPDIR')
|
||||||
|
$if linux {
|
||||||
|
if path == '' { path = '/tmp' }
|
||||||
|
}
|
||||||
|
$if mac {
|
||||||
|
/*
|
||||||
|
if path == '' {
|
||||||
|
// TODO untested
|
||||||
|
path = C.NSTemporaryDirectory()
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if path == '' { path = '/tmp' }
|
||||||
|
}
|
||||||
|
$if windows {
|
||||||
|
if path == '' {
|
||||||
|
// TODO see Qt's implementation?
|
||||||
|
// https://doc.qt.io/qt-5/qdir.html#tempPath
|
||||||
|
// https://github.com/qt/qtbase/blob/e164d61ca8263fc4b46fdd916e1ea77c7dd2b735/src/corelib/io/qfilesystemengine_win.cpp#L1275
|
||||||
|
path = os.getenv('TEMP')
|
||||||
|
if path == '' { path = os.getenv('TMP') }
|
||||||
|
if path == '' { path = 'C:/tmp' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
|
@ -152,6 +152,24 @@ fn test_cp_r() {
|
||||||
os.cp_r('ex', './', true) or { panic(err) }
|
os.cp_r('ex', './', true) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_tmpdir(){
|
||||||
|
t := os.tmpdir()
|
||||||
|
assert t.len > 0
|
||||||
|
assert os.is_dir(t)
|
||||||
|
|
||||||
|
tfile := t + os.path_separator + 'tmpfile.txt'
|
||||||
|
|
||||||
|
os.rm(tfile) // just in case
|
||||||
|
|
||||||
|
tfile_content := 'this is a temporary file'
|
||||||
|
os.write_file(tfile, tfile_content)
|
||||||
|
|
||||||
|
tfile_content_read := os.read_file(tfile) or { panic(err) }
|
||||||
|
assert tfile_content_read == tfile_content
|
||||||
|
|
||||||
|
os.rm(tfile)
|
||||||
|
}
|
||||||
|
|
||||||
//fn test_fork() {
|
//fn test_fork() {
|
||||||
// pid := os.fork()
|
// pid := os.fork()
|
||||||
// if pid == 0 {
|
// if pid == 0 {
|
||||||
|
@ -179,7 +197,6 @@ fn test_zzz_cleanup(){
|
||||||
cleanup_leftovers() assert true
|
cleanup_leftovers() assert true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// this function is called by both test_aaa_setup & test_zzz_cleanup
|
// this function is called by both test_aaa_setup & test_zzz_cleanup
|
||||||
// it ensures that os tests do not polute the filesystem with leftover
|
// it ensures that os tests do not polute the filesystem with leftover
|
||||||
// files so that they can be run several times in a row.
|
// files so that they can be run several times in a row.
|
||||||
|
|
Loading…
Reference in New Issue