compiler: support storing temporary files under TMPDIR/v/

Fix for filepath.join not \0 terminating its result
pull/2791/head
Delyan Angelov 2019-11-17 05:45:20 +02:00 committed by Alexander Medvednikov
parent 200fcd41ce
commit be7cf3e812
6 changed files with 92 additions and 21 deletions

View File

@ -799,6 +799,7 @@ pub fn new_v(args[]string) &V {
vgen_buf.writeln('module vgen\nimport strings')
joined_args := args.join(' ')
target_os := get_arg(joined_args, 'os', '')
comptime_define := get_arg(joined_args, 'd', '')
//println('comptimedefine=$comptime_define')
@ -930,8 +931,8 @@ pub fn new_v(args[]string) &V {
println('Go to https://vlang.io to install V.')
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)
@ -978,7 +979,7 @@ pub fn new_v(args[]string) &V {
println('C compiler=$pref.ccompiler')
}
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 pref.is_bare && !out_name.ends_with('.c') {

View File

@ -28,6 +28,9 @@ pub const (
You can set it like this: `export VFLAGS="-cc clang -debug"` on *nix,
`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:
-h, help Display this information.
-o <file> Write output to <file>.

View 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) )
}

View File

@ -2,7 +2,6 @@ module filepath
import(
os
strings
)
// 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
// TODO use []string.join once ...string becomes "[]string"
pub fn join(base string, dirs ...string) string {
mut path := strings.new_builder(50)
path.write(base.trim_right('\\/'))
for d in dirs {
path.write(os.path_separator)
path.write(d)
}
return path.str()
mut result := []string
result << base.trim_right('\\/')
for d in dirs { result << d }
return result.join( os.path_separator )
}

View File

@ -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) {
return error('Source path doesn\'t exist')
}
//single file copy
if !os.is_dir(source_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 overwrite { os.rm(adjasted_path) }
else { return error('Destination file path already exist') }
if overwrite {
os.rm(adjasted_path)
}
else {
return error('Destination file path already exist')
}
}
os.cp(source_path, adjasted_path) or { return error(err) }
return true
@ -558,7 +567,7 @@ pub fn basedir(path string) string {
if pos == -1 {
return path
}
return path[..pos + 1]
return path[..pos ] // NB: *without* terminating /
}
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 )) )
}
$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)
if ret == 0 {
return fpath
@ -965,3 +970,31 @@ pub fn join(base string, dirs ...string) string {
println('use filepath.join')
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
}

View File

@ -152,6 +152,24 @@ fn test_cp_r() {
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() {
// pid := os.fork()
// if pid == 0 {
@ -179,7 +197,6 @@ fn test_zzz_cleanup(){
cleanup_leftovers() assert true
}
// this function is called by both test_aaa_setup & test_zzz_cleanup
// it ensures that os tests do not polute the filesystem with leftover
// files so that they can be run several times in a row.