enable alpine/musl CI tests

pull/2916/head
Delyan Angelov 2019-11-28 10:46:52 +02:00 committed by Alexander Medvednikov
parent 3b7466a13d
commit 7545ea709a
13 changed files with 137 additions and 65 deletions

View File

@ -0,0 +1,15 @@
#!/bin/sh -l
set -e
pwd
uname -a
make
./v --version
du -s .
echo "DONE"

View File

@ -0,0 +1,15 @@
#!/bin/sh -l
set -e
pwd
uname -a
du -s .
ls -lat
./v test v
echo "DONE"

View File

@ -2,6 +2,24 @@ name: CI
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
build-alpine-docker-musl-gcc:
name: Alpine/musl
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Build V
uses: spytheman/docker_alpine_v@v5.0
with:
entrypoint: .github/workflows/alpine.build.sh
- name: Test V
uses: spytheman/docker_alpine_v@v5.0
with:
entrypoint: .github/workflows/alpine.test.sh
build-osx: build-osx:
runs-on: macOS-10.14 runs-on: macOS-10.14
steps: steps:
@ -123,3 +141,4 @@ jobs:
## v.js dosent work on windows ## v.js dosent work on windows
#.\v.exe -o hi.js examples/hello_v_js.v #.\v.exe -o hi.js examples/hello_v_js.v
#node hi.js #node hi.js

18
Dockerfile.alpine 100644
View File

@ -0,0 +1,18 @@
FROM alpine:3.10
LABEL maintainer="spytheman <spytheman@bulsynt.org>"
WORKDIR /opt/vlang
ENV VVV /opt/vlang
ENV PATH /opt/vlang:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RUN mkdir -p /opt/vlang && ln -s /opt/vlang/v /usr/bin/v
RUN apk --no-cache add \
git make upx gcc \
musl-dev \
openssl-dev sqlite-dev \
libx11-dev glfw-dev freetype-dev
RUN git clone https://github.com/vlang/v /opt/vlang && make && v --version

View File

@ -85,6 +85,15 @@ docker run --rm -it vlang:latest
v v
``` ```
### Docker with Alpine/musl:
```bash
git clone https://github.com/vlang/v
cd v
docker build -t vlang --file=Dockerfile.alpine .
docker run --rm -it vlang:latest
/usr/local/v/v
```
### Testing and running the examples ### Testing and running the examples
Make sure V can compile itself: Make sure V can compile itself:

View File

@ -89,22 +89,13 @@ pub fn eprintln(s string) {
if isnil(s.str) { if isnil(s.str) {
panic('eprintln(NIL)') panic('eprintln(NIL)')
} }
$if mac { $if !windows {
C.fflush(stdout)
C.fflush(stderr)
C.fprintf(stderr, '%.*s\n', s.len, s.str) C.fprintf(stderr, '%.*s\n', s.len, s.str)
C.fflush(stderr) C.fflush(stderr)
return return
} }
$if linux {
C.fprintf(stderr, '%.*s\n', s.len, s.str)
C.fflush(stderr)
return
}
$if freebsd {
C.fprintf(stderr, '%.*s\n', s.len, s.str)
C.fflush(stderr)
return
}
// TODO issues with stderr and cross compiling for Linux // TODO issues with stderr and cross compiling for Linux
println(s) println(s)
} }

View File

@ -124,6 +124,15 @@ pub fn (s string) cstr() byteptr {
return clone.str return clone.str
} }
*/ */
// cstring_to_vstring creates a copy of cstr and turns it into a v string
pub fn cstring_to_vstring(cstr byteptr) string {
slen := C.strlen(cstr)
mut s := byteptr( memdup(cstr, slen+1) )
s[slen] = `\0`
return tos(s, slen)
}
pub fn (s string) replace_once(rep, with string) string { pub fn (s string) replace_once(rep, with string) string {
index := s.index(rep) index := s.index(rep)
if index != -1 { if index != -1 {

View File

@ -541,7 +541,6 @@ pub fn final_target_out_name(out_name string) string {
pub fn (v V) run_compiled_executable_and_exit() { pub fn (v V) run_compiled_executable_and_exit() {
args := env_vflags_and_os_args() args := env_vflags_and_os_args()
if v.pref.is_verbose { if v.pref.is_verbose {
println('============ running $v.out_name ============') println('============ running $v.out_name ============')
} }

View File

@ -5,7 +5,8 @@ import log
import benchmark import benchmark
fn main(){ fn main(){
logger := &log.Log{log.DEBUG, 'terminal'} mut logger := log.Log{}
logger.set_level(log.DEBUG)
options := runner.new_options() options := runner.new_options()
mut bmark := benchmark.new_benchmark() mut bmark := benchmark.new_benchmark()

View File

@ -10,6 +10,10 @@ pub:
} }
pub fn full_path_to_v(dirs_in int) string { pub fn full_path_to_v(dirs_in int) string {
vexe_from_env := os.getenv('VEXE')
if vexe_from_env.len > 0 {
return vexe_from_env
}
vname := if os.user_os() == 'windows' { 'v.exe' } else { 'v' } vname := if os.user_os() == 'windows' { 'v.exe' } else { 'v' }
mut path := os.executable() mut path := os.executable()
for i := 0; i < dirs_in; i++ { for i := 0; i < dirs_in; i++ {

View File

@ -46,7 +46,12 @@ fn test_erf() {
fn test_gamma() { fn test_gamma() {
assert math.gamma(1) == 1 assert math.gamma(1) == 1
assert math.gamma(5) == 24 assert math.gamma(5) == 24
assert math.log_gamma(4.5) == math.log(math.gamma(4.5))
sval := '2.453737'
assert math.log_gamma(4.5).str() == sval
assert math.log(math.gamma(4.5)).str() == sval
assert math.abs( math.log_gamma(4.5) - math.log(math.gamma(4.5)) ) < 0.000001
// assert math.log_gamma(4.5) == math.log(math.gamma(4.5)) /* <-- fails on alpine/musl
} }
fn test_mod() { fn test_mod() {

View File

@ -64,7 +64,7 @@ mut:
fn C.getline(voidptr, voidptr, voidptr) int fn C.getline(voidptr, voidptr, voidptr) int
fn C.ftell(fp voidptr) int fn C.ftell(fp voidptr) int
fn C.getenv(byteptr) byteptr fn C.getenv(byteptr) &char
fn C.sigaction(int, voidptr, int) fn C.sigaction(int, voidptr, int)
@ -76,15 +76,11 @@ pub fn (f File) read_bytes(size int) []byte {
// read_bytes_at reads an amount of bytes at the given position in the file // read_bytes_at reads an amount of bytes at the given position in the file
pub fn (f File) read_bytes_at(size, pos int) []byte { pub fn (f File) read_bytes_at(size, pos int) []byte {
mut data := malloc(size)
mut arr := [`0`].repeat(size) mut arr := [`0`].repeat(size)
C.fseek(f.cfile, pos, C.SEEK_SET) C.fseek(f.cfile, pos, C.SEEK_SET)
C.fread(data, 1, size, f.cfile) nreadbytes := C.fread(arr.data, 1, size, f.cfile)
C.fseek(f.cfile, 0, C.SEEK_SET) C.fseek(f.cfile, 0, C.SEEK_SET)
for e := 0; e < size; e++ { return arr.slice(0, nreadbytes)
arr[e] = data[e]
}
return arr
} }
pub fn read_bytes(path string) ?[]byte { pub fn read_bytes(path string) ?[]byte {
@ -96,16 +92,10 @@ pub fn read_bytes(path string) ?[]byte {
fsize := C.ftell(fp) fsize := C.ftell(fp)
C.rewind(fp) C.rewind(fp)
println('fsize=$fsize') println('fsize=$fsize')
mut data := malloc(fsize)
C.fread(data, fsize, 1, fp)
mut res := [`0`].repeat(fsize) mut res := [`0`].repeat(fsize)
for i in 0..fsize { nreadbytes := C.fread(res.data, fsize, 1, fp)
res[i] = data[i]
}
C.fclose(fp) C.fclose(fp)
//res := []byte(data, 10) // TODO can't `return []byte(data)` return res.slice(0, nreadbytes )
//println('res0 = ' + res[0].str())
return res
} }
// read_file reads the file in `path` and returns the contents. // read_file reads the file in `path` and returns the contents.
@ -485,30 +475,28 @@ pub fn sigint_to_signal_name(si int) string {
pub fn getenv(key string) string { pub fn getenv(key string) string {
$if windows { $if windows {
s := C._wgetenv(key.to_wide()) s := C._wgetenv(key.to_wide())
if isnil(s) { if s == 0 {
return '' return ''
} }
return string_from_wide(s) return string_from_wide(s)
} $else { } $else {
s := *byte(C.getenv(key.str)) s := C.getenv(key.str)
if isnil(s) { if s == 0 {
return '' return ''
} }
return string(s) // NB: C.getenv *requires* that the result be copied.
return cstring_to_vstring( byteptr(s) )
} }
} }
pub fn setenv(name string, value string, overwrite bool) int { pub fn setenv(name string, value string, overwrite bool) int {
$if windows { $if windows {
format := '$name=$value' format := '$name=$value'
if overwrite { if overwrite {
return C._putenv(format.str) return C._putenv(format.str)
} }
return -1 return -1
} } $else {
$else {
return C.setenv(name.str, value.str, overwrite) return C.setenv(name.str, value.str, overwrite)
} }
} }
@ -516,10 +504,8 @@ pub fn setenv(name string, value string, overwrite bool) int {
pub fn unsetenv(name string) int { pub fn unsetenv(name string) int {
$if windows { $if windows {
format := '${name}=' format := '${name}='
return C._putenv(format.str) return C._putenv(format.str)
} } $else {
$else {
return C.unsetenv(name.str) return C.unsetenv(name.str)
} }
} }
@ -759,31 +745,32 @@ fn C.readlink() int
// process. // process.
pub fn executable() string { pub fn executable() string {
$if linux { $if linux {
mut result := malloc(MAX_PATH) mut result := calloc(MAX_PATH)
count := C.readlink('/proc/self/exe', result, MAX_PATH) count := C.readlink('/proc/self/exe', result, MAX_PATH)
if count < 0 { if count < 0 {
panic('error reading /proc/self/exe to get exe path') eprintln('os.executable() failed at reading /proc/self/exe to get exe path')
return os.args[0]
} }
return string(result, count) return string(result)
} }
$if windows { $if windows {
max := 512 max := 512
mut result := &u16(malloc(max*2)) // MAX_PATH * sizeof(wchar_t) mut result := &u16(calloc(max*2)) // MAX_PATH * sizeof(wchar_t)
len := int(C.GetModuleFileName( 0, result, max )) len := int(C.GetModuleFileName( 0, result, max ))
return string_from_wide2(result, len) return string_from_wide2(result, len)
} }
$if mac { $if mac {
mut result := malloc(MAX_PATH) mut result := calloc(MAX_PATH)
pid := C.getpid() pid := C.getpid()
ret := proc_pidpath (pid, result, MAX_PATH) ret := proc_pidpath (pid, result, MAX_PATH)
if ret <= 0 { if ret <= 0 {
println('os.executable() failed') eprintln('os.executable() failed at calling proc_pidpath with pid: $pid . proc_pidpath returned $ret ')
return '.' return os.args[0]
} }
return string(result) return string(result)
} }
$if freebsd { $if freebsd {
mut result := malloc(MAX_PATH) mut result := calloc(MAX_PATH)
mib := [1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1] mib := [1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1]
size := MAX_PATH size := MAX_PATH
C.sysctl(mib.data, 4, result, &size, 0, 0) C.sysctl(mib.data, 4, result, &size, 0, 0)
@ -797,18 +784,20 @@ pub fn executable() string {
$if solaris { $if solaris {
} }
$if netbsd { $if netbsd {
mut result := malloc(MAX_PATH) mut result := calloc(MAX_PATH)
count := int(C.readlink('/proc/curproc/exe', result, MAX_PATH )) count := int(C.readlink('/proc/curproc/exe', result, MAX_PATH ))
if count < 0 { if count < 0 {
panic('error reading /proc/curproc/exe to get exe path') eprintln('os.executable() failed at reading /proc/curproc/exe to get exe path')
return os.args[0]
} }
return string(result, count) return string(result, count)
} }
$if dragonfly { $if dragonfly {
mut result := malloc(MAX_PATH) mut result := calloc(MAX_PATH)
count := int(C.readlink('/proc/curproc/file', result, MAX_PATH )) count := int(C.readlink('/proc/curproc/file', result, MAX_PATH ))
if count < 0 { if count < 0 {
panic('error reading /proc/curproc/file to get exe path') eprintln('os.executable() failed at reading /proc/curproc/file to get exe path')
return os.args[0]
} }
return string(result, count) return string(result, count)
} }
@ -870,21 +859,19 @@ pub fn getwd() string {
// NB: this particular rabbit hole is *deep* ... // NB: this particular rabbit hole is *deep* ...
pub fn realpath(fpath string) string { pub fn realpath(fpath string) string {
mut fullpath := calloc(MAX_PATH) mut fullpath := calloc(MAX_PATH)
mut res := 0 mut ret := *char(0)
$if windows { $if windows {
ret := C._fullpath(fullpath, fpath.str, MAX_PATH) ret = C._fullpath(fullpath, fpath.str, MAX_PATH)
if ret == 0 { if ret == 0 {
return fpath return fpath
} }
return string(fullpath) } $else {
} ret = C.realpath(fpath.str, fullpath)
$else{
ret := C.realpath(fpath.str, fullpath)
if ret == 0 { if ret == 0 {
return fpath return fpath
} }
return string(fullpath)
} }
return string(fullpath)
} }
// walk_ext returns a recursive list of all file paths ending with `ext`. // walk_ext returns a recursive list of all file paths ending with `ext`.